# -*- coding: iso-8859-1 -*-############################################### Nom : Stats WhatPulse ## Auteur : Xn/Syntax <xn.exelsior@gmail.com ## Date : 28/11/2007 Fichier : main.py ################################################ Import des différents modules spécials GTKimport pygtkimport gtkimport gobject# urllib qui est le plus simple pour récuperer# la source d'une page webimport urllib# On load le module minidom pour parse le xmlfrom xml.dom import minidom# K Alors c'est parti, voici la premiere class# Elle est là pour recuperer toutes les infos relatives a l'UserID# passé en parametre de la fonction main.class Whatpulse: def main ( self, userID ): # On creer une variable et on lui assigne l'objet urllib self.myPage = urllib.urlopen("http://whatpulse.org/api/user.php?UserID=" + userID) # Maintenant on recupere le code XML a parser self.myXML = self.myPage.read() # Si la page que l'on a ressemble a Unknow/No UserID given # On renvoie des erreurs if (self.myXML == "Unknow UserID given!"): return 2 elif (self.myXML == "No UserID given!"): return 3 # Sinon, rouler jeunesse, on parse le xml # grâce a la méthode parseString(<string>) de minidom else: self.xml2 = minidom.parseString(self.myXML) # On recupere le root de l'arbre xml self.UserStats = self.xml2.firstChild # Maintenant on a une fonction pour récuperer chaque élement de notre arbre xml # et on return la valeur récupérée def GetGeneratedDate ( self ): GeneratedStats = self.UserStats.childNodes[1] return GeneratedStats.firstChild.data def GetUserID ( self ): UserID = self.UserStats.childNodes[3] return UserID.firstChild.data def GetAccount ( self ): Account = self.UserStats.childNodes[5] return Account.firstChild.data def GetCountry ( self ): Country = self.UserStats.childNodes[7] return Country.firstChild.data def GetJoined ( self ): DateJoined = self.UserStats.childNodes[9] return DateJoined.firstChild.data def GetHomePage ( self ): Homepage = self.UserStats.childNodes[11] try: return Homepage.firstChild.data except: return "None" def GetLastPulse ( self ): LastPulse = self.UserStats.childNodes[13] return LastPulse.firstChild.data def GetPulses ( self ): NPulses = self.UserStats.childNodes[15] return NPulses.firstChild.data def GetTotalKeys ( self ): KeysTotal = self.UserStats.childNodes[17] return KeysTotal.firstChild.data def GetTotalClick ( self ): ClicksTotal = self.UserStats.childNodes[19] return ClicksTotal.firstChild.data def GetMiles ( self ): Miles = self.UserStats.childNodes[21] return Miles.firstChild.data def AvgKeyPulse ( self ): AvgKey = self.UserStats.childNodes[23] return AvgKey.firstChild.data def AvgClicksPulse ( self ): AvgClick = self.UserStats.childNodes[25] return AvgClick.firstChild.data def AvgKPS ( self ): AvgKPS = self.UserStats.childNodes[27] return AvgKPS.firstChild.data def AvgCPS ( self ): AvgCPS = self.UserStats.childNodes[29] return AvgCPS.firstChild.data def GetRank ( self ): Rank = self.UserStats.childNodes[31] return Rank.firstChild.data def CheckTeam ( self ): TeamID = self.UserStats.childNodes[33] try: isTeamID = TeamID.firstChild.data return 1 except: return 0 def GetTeamID ( self ): if (self.CheckTeam()): TeamID = self.UserStats.childNodes[33] return TeamID.firstChild.data def GetTeamName ( self ): if (self.CheckTeam()): TeamName = self.UserStats.childNodes[35] return TeamName.firstChild.data def GetTeamMem ( self ): if (self.CheckTeam()): TeamMem = self.UserStats.childNodes[37] return TeamMem.firstChild.data def GetTeamKeys ( self ): if (self.CheckTeam()): TeamKeys = self.UserStats.childNodes[39] return TeamKeys.firstChild.data def GetTeamClicks ( self ): if (self.CheckTeam()): TeamClicks = self.UserStats.childNodes[41] return TeamClicks.firstChild.data def GetTeamMiles ( self ): if (self.CheckTeam()): TeamMiles = self.UserStats.childNodes[43] return TeamMiles.firstChild.data def GetTeamDescription ( self ): if (self.CheckTeam()): Teamdesc = self.UserStats.childNodes[45] try: return Teamdesc.firstChild.data except: return "None" def GetTeamDateFormed ( self ): if (self.CheckTeam()): Teamdate = self.UserStats.childNodes[47] try: return Teamdate.firstChild.data except: return "None" def GetTeamRank ( self ): if (self.CheckTeam()): TeamRank = self.UserStats.childNodes[49] try: return TeamRank.firstChild.data except: return "None" def GetRankInTeam ( self ): if (self.CheckTeam()): RankIn = self.UserStats.childNodes[51] try: return RankIn.firstChild.data except: return "None"# Maintenant qu'on a une class qui nous envoies toutes ces infos# on va creer l'interface histoire de faire un truc un peu plus# joli. class WPInterface: # __init__ est le contructeur de la class, ce sont les actions # qui sont exécutées dés la création de la class. def __init__(self): # k là on entre dans le gros du boulot, on creer d'abord la window self.MyGUI = gtk.Window(gtk.WINDOW_TOPLEVEL) # Ensuite on lui met un titre self.MyGUI.set_title('- WhatPulse Stats - Xn') # On met des bordures "invisibles" de 10pixels self.MyGUI.set_border_width(10) # On enleve le resizable pour cette fenêtre self.MyGUI.set_resizable(False) # On regle la taille du GUI, pas trop grand ni trop petit self.MyGUI.set_size_request(400,305) # Maintenant on va y ajouter un bouton, même deux ^^ self.MyButton = gtk.Button('Refresh') self.MyButton2 = gtk.Button('Test') # Un Label :P self.MyLabel = gtk.Label('User ID :') # là on ajoute un containeur, car le composant GtkWindow (notre fenêtre principale) # ne peut contenir qu'un seul composant "fille", c'est pourquoi on doit "packé" nos # controles pour pouvoir tout faire rentrer. self.Container = gtk.Fixed() # Et hop, on ajoute notre conteneur a notre fenetre mère self.MyGUI.add(self.Container) # On creer une zone de texte, là ou on va entrer l'userID du compte # à inspecter self.MyEntry = gtk.Entry() # On met un texte par défault (Mon UserID, flemme de le retaper a chaque fois) self.MyEntry.set_text('195719') # Comme tout a l'heure on regle la taille, mais cette fois ci du controle toujours avec # la méthode set_size_request(largeur,hauteur) self.MyEntry.set_size_request(50,20) # La on ajoute une scrollbar pour notre ListView, sinon il n'y en a pas, # cette "dite" scrollbar va en fait contenir notre listview et scrollé au besoin self.MyScrollbar = gtk.ScrolledWindow() # Ici on regle les propriétés de défilement, Automatique, Jamais pour ici. self.MyScrollbar.set_policy(gtk.POLICY_NEVER,gtk.POLICY_AUTOMATIC) # La aussi, gros boulot, on creer notre ListView, qui ici s'instance avec gtk.TreeView() # on lui applique ensuite un modele, gtk.ListStore, qui indique quelle données vont aller dans # quelle colonne de notre listview, ici deux colonnes de type String (chaines de caracteres) self.MyTreeStore = gtk.TreeView() self.MyModel= gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_STRING ) # Il ne faut pas oublier d'appliquer le modele a notre listview self.MyTreeStore.set_model(self.MyModel) # On regle la taille et la bordure comme nous l'avons fait avant. self.MyTreeStore.set_size_request(375,245) self.MyTreeStore.set_border_width(10) # Autre partie, toujours de la listview, on va regle les styles des cellules # pour le texte qui y rentrera. On fait ca avec la méthode CellRendererText() self.MyRenderer1 = gtk.CellRendererText() # On set quelques propriétés, ici la largeur de cette colonne, la police en gras, # et le fond de la cellule. self.MyRenderer1.set_property('width',190) self.MyRenderer1.set_property('font','bold') self.MyRenderer1.set_property('background','#d2eef8') # On en creer une deuxieme, ewi on a deux colonnes =l, on regle juste la largeur # cette fois ci. self.MyRenderer2 = gtk.CellRendererText() self.MyRenderer2.set_property('width',150) # Et maintenant on creer et ajoute les colonnes a notre listview. # --> L'argument text=0 ou text=1 nous servira plus tard pour l'ajout des données. self.MyColumn1 = gtk.TreeViewColumn('Info',self.MyRenderer1,text=0) self.MyColumn2 = gtk.TreeViewColumn('Data',self.MyRenderer2,text=1) self.MyTreeStore.append_column(self.MyColumn1) self.MyTreeStore.append_column(self.MyColumn2) # Ici petit exemple d'ajout pour illustrer les arguments text=0 et text=1, # - Lorsque l'on ajoute des données, nous devons faire un tableau, et passer # ce tableau a la méthode append() du modele de notre listview. # - En clair, le text=0 signifie que dans le tableau que vous avez passer en argument # vous utiliserez la premiere donnée insérée dans le tableau. text=1 représente la deuxieme donnée # et ainsi de suite # ---- Exemple : self.model.append(['Ma premiere donnée : text=0','Ma deuxieme donnée : text=1']) self.MyModel.append() # Events des différentes composants, on affecte une action aux signaux que l'on veut. Ici lorsque # on clique le bouton "MyButton", la fonction WPRefreshClicked s'execute. self.MyGUI.connect('destroy',self.WPDestroy) self.MyButton.connect('clicked',self.WPRefreshClicked) # On place les controles sur le conteneur. # ---- Syntax : Conteneur.put(ControleAPlacer,x,y) self.MyScrollbar.add(self.MyTreeStore) self.Container.put(self.MyButton,110,1) self.Container.put(self.MyLabel,1,6) self.Container.put(self.MyEntry,55,3) self.Container.put(self.MyScrollbar,1,35) # Je met le focus sur l'edit a l'ouverture, et je "show", c'est a dire # que j'affiche tout notre fenêtre a l'écran. self.MyEntry.grab_focus() self.MyGUI.show_all() def WPMain(self): # Procédure obligatoire, c'est ce qui lance notre petit programme ^^ gtk.main() def WPDestroy(self,data=None): # Procédure obligatoire également, cela permet de finaliser la fermeture # de notre interface. gtk.main_quit() # Cette fonction est une fonction classique. Elle ajoute les données à la listview def WPRefreshClicked(self,widget): # On récupère le texte de l'edit que l'on a mis. Cela doit contenir l'userID a vérifier. self.MyReq = self.MyEntry.get_text() # On vérifie si la variable est nulle if (self.MyReq <> ""): # On clear notre listview pour ajouter soit les données, soit les messages d'erreur. self.MyModel.clear() # On creer notre class qui nous permet de récuperer nos infos. self.MyStats = Whatpulse() # On lance la fonction main, avec comme parametre notre "userID" MyRes = self.MyStats.main(self.MyReq) # Notre fonction main nous renvoie SOIT une valeur d'erreur (2 ou 3) soit les données # a ajouter sur notre listview if (MyRes == 2): self.MyModel.append(['Error','Unknow User ID']) elif (MyRes == 3): self.MyModel.append(['Error','Bad User ID']) else: # On Ajoute nos données comme tout a l'heure, en utilisant les fonctions de la classe # WhatPulse. self.MyModel.append(['Derniere Generation',self.MyStats.GetGeneratedDate()]) self.MyModel.append(['User ID',self.MyStats.GetUserID()]) self.MyModel.append(['Account Name',self.MyStats.GetAccount()]) self.MyModel.append(['Country',self.MyStats.GetCountry()]) self.MyModel.append(['Joined',self.MyStats.GetJoined()]) self.MyModel.append(['HomePage',self.MyStats.GetHomePage()]) self.MyModel.append(['Last Pulse',self.MyStats.GetLastPulse()]) self.MyModel.append(['Pulses',self.MyStats.GetPulses()]) self.MyModel.append(['Total Keys',self.MyStats.GetTotalKeys()]) self.MyModel.append(['Total Clicks',self.MyStats.GetTotalClick()]) self.MyModel.append(['Miles',self.MyStats.GetMiles()]) self.MyModel.append(['Average Key Per Pulse',self.MyStats.AvgKeyPulse()]) self.MyModel.append(['Average Click Per Pulse',self.MyStats.AvgClicksPulse()]) self.MyModel.append(['Average Keys Per Second',self.MyStats.AvgKPS()]) self.MyModel.append(['Average Clicks Per Second',self.MyStats.AvgCPS()]) self.MyModel.append(['Rank',self.MyStats.GetRank()]) # Petite condition qui vérifie si le joueur a une équipe ou non, si il en # a pas, on va rien ajouter de relatif a son équipe. if (self.MyStats.CheckTeam()): self.MyModel.append(['Team ID',self.MyStats.GetTeamID()]) self.MyModel.append(['Team Name',self.MyStats.GetTeamName()]) self.MyModel.append(['Team Members',self.MyStats.GetTeamMem()]) self.MyModel.append(['Team Keys',self.MyStats.GetTeamKeys()]) self.MyModel.append(['Team Clicks',self.MyStats.GetTeamClicks()]) self.MyModel.append(['Team Miles',self.MyStats.GetTeamMiles()]) self.MyModel.append(['Team Description',self.MyStats.GetTeamDescription()]) self.MyModel.append(['Team formed on',self.MyStats.GetTeamDateFormed()]) self.MyModel.append(['Team rank',self.MyStats.GetTeamRank()]) self.MyModel.append(['Rank in team',self.MyStats.GetRankInTeam()]) self.MyAdjus = gtk.Adjustment() self.MyAdjus.upper = self.MyScrollbar.get_vadjustment().upper * 15 self.MyAdjus.value = self.MyAdjus.upper self.MyScrollbar.set_vadjustment(self.MyAdjus) print self.MyScrollbar.get_vadjustment().value# On lance gentillement le programme en creant un objet WPInterface()# Puis on execute la méthode WPMain() de l'objet qui affiche notre joli GUI# à l'écran. if (__name__=="__main__"): MyWP = WPInterface() MyWP.WPMain()##################################################################### Résumé : ## - On a une class WhatPulse qui récupere les infos ## - Une autre class WPInterface() qui creer le GUI et l'affiche ## à l'écran. ## Notions vues : ## - Utilisation de PyGTK et GTK pour creer des Interfaces ## - Utilisation des objets pour une meilleure compréhension ## et exécution. ## - Utilisation du module minidom pour parser du xml a partir ## d'une chaine de caractere. #####################################################################