issue49:tutopython
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
issue49:tutopython [2011/06/20 21:36] – [CODE PAGE 10 milieu bas] fredphil91 | issue49:tutopython [2011/07/06 12:19] (Version actuelle) – peji | ||
---|---|---|---|
Ligne 3: | Ligne 3: | ||
First, using the MainWindow, go to the General tab, and scroll down until you find Icon. Using the browse tool, find your icon and select that. Now the text box should contain “logo.png”. Next, in the hierarchy box, select treeview1, go to the signal tab, and, under GtkTreeView | cursor-changed, | First, using the MainWindow, go to the General tab, and scroll down until you find Icon. Using the browse tool, find your icon and select that. Now the text box should contain “logo.png”. Next, in the hierarchy box, select treeview1, go to the signal tab, and, under GtkTreeView | cursor-changed, | ||
- | Cette fois-ci, nous allons terminer notre programme de création de liste de lecture. La dernière fois, nous avions bien avancé, mais nous n' | + | Cette fois-ci, nous allons terminer notre programme de création de liste de lecture. La dernière fois, nous avions bien avancé, mais nous n' |
- | Tout d' | + | Tout d' |
**Now it's time to complete our project. We'll start from where we left off using last month' | **Now it's time to complete our project. We'll start from where we left off using last month' | ||
Ligne 13: | Ligne 13: | ||
You might imagine, this simply looks at the value of each key that is pressed when the user is in the txtFilename text box, and compares it to the value 65293, which is the code that is assigned to the return key (enter key). If it matches, then it calls the SavePlaylist function. The user doesn' | You might imagine, this simply looks at the value of each key that is pressed when the user is in the txtFilename text box, and compares it to the value 65293, which is the code that is assigned to the return key (enter key). If it matches, then it calls the SavePlaylist function. The user doesn' | ||
- | Maintenant il est temps de continuer | + | Maintenant il est temps de terminer |
- | La première chose que je veux faire est de modifier le code de la classe DialogueFichier. Si vous vous souvenez de la dernière fois, si l' | + | La première chose que je veux faire est modifier le code de la classe DialogueFichier. Si vous vous souvenez de la dernière fois, si l' |
- | Comme vous l' | + | Comme vous pouvez le supposer, cela regarde simplement la valeur de chaque touche enfoncée lorsque l' |
**Now on to new code. Let's deal with the toolbar button ClearAll. When the user clicks this button, we want the treeview and the ListStore to be cleared. This is a simple one-liner that we can put into the on_tbtnClearAll_clicked routine. | **Now on to new code. Let's deal with the toolbar button ClearAll. When the user clicks this button, we want the treeview and the ListStore to be cleared. This is a simple one-liner that we can put into the on_tbtnClearAll_clicked routine. | ||
Ligne 29: | Ligne 29: | ||
First we have to discuss how we get a selection from the treeview widget and the ListStore. This is complicated, | First we have to discuss how we get a selection from the treeview widget and the ListStore. This is complicated, | ||
- | Maintenant passons au code. Occupons-nous du bouton Effacer de la barre d' | + | Maintenant passons au code. Occupons-nous du bouton Effacer de la barre d' |
def on_boBtnEffacer_clicked(self, | def on_boBtnEffacer_clicked(self, | ||
Ligne 44: | Ligne 44: | ||
The first line creates the TreeSelection object. We use that to get the rows selected (which is only one because we didn't set the model to support multiple selections), | The first line creates the TreeSelection object. We use that to get the rows selected (which is only one because we didn't set the model to support multiple selections), | ||
- | Je sais que vous pensez « mais bon sang, qu' | + | Je sais que vous pensez |
- | Regardez la boucle for. On utilise un itérateur pour parcourir la liste ListeFichiers. Dans ce cas, l' | + | Regardez la boucle for. On utilise un itérateur pour parcourir la liste ListeFichiers. Dans ce cas, l' |
- | La première ligne crée l' | + | La première ligne crée l' |
**Now, before we get to the move functions, let's deal with the save-file-path function. We'll use our FileDialog class as before. We'll do all the code (bottom right)for this in the on_btnGetFolder_clicked routine. | **Now, before we get to the move functions, let's deal with the save-file-path function. We'll use our FileDialog class as before. We'll do all the code (bottom right)for this in the on_btnGetFolder_clicked routine. | ||
Ligne 66: | Ligne 66: | ||
We can now start work on the move functions. Let's start with the Move To Top routine. Like we did when we wrote the delete function, we get the selection and then the selected row. Next we have to step through the rows to get two variables. We will call them path1 and path2. Path2, in this case will be set to 0, which is the “target” row. Path1 is the row the user has selected. We finally use the model.move_before() method to move the selected row up to row 0, effectively pushing everything down. We'll put the code (below right) directly in the on_tbtnMoveToTop_clicked routine.** | We can now start work on the move functions. Let's start with the Move To Top routine. Like we did when we wrote the delete function, we get the selection and then the selected row. Next we have to step through the rows to get two variables. We will call them path1 and path2. Path2, in this case will be set to 0, which is the “target” row. Path1 is the row the user has selected. We finally use the model.move_before() method to move the selected row up to row 0, effectively pushing everything down. We'll put the code (below right) directly in the on_tbtnMoveToTop_clicked routine.** | ||
- | Maintenant que l'on a un chemin (cf) et un nom de fichier (nf), on peut ouvrir le fichier, imprimer notre en-tête M3U et parcourir la liste de lecture. Le chemin est stocké (si vous vous souvenez) dans la colonne 2, le nom du fichier dans la colonne 0, et l' | + | Maintenant que l'on a un chemin (cf) et un nom de fichier (nf), on peut ouvrir le fichier, imprimer notre en-tête M3U et parcourir la liste de lecture. Le chemin est stocké (si vous vous souvenez) dans la colonne 2, le nom du fichier dans la colonne 0 et l' |
- | On peut maintenant commencer à travailler sur les fonctions de déplacement. Commençons par la routine Haut. Comme nous l' | + | On peut maintenant commencer à travailler sur les fonctions de déplacement. Commençons par la routine Haut. Comme nous l' |
**For the MoveToBottom function, we will use almost exactly the same code as the MoveToTop routine, but, in place of the model.move_before() method, we will use the model.move_after() method, and, instead of setting path2 to 0, we set it to self.RowCount-1. Now you understand why we have a RowCount variable. Remember the counts are zero based, so we have to use RowCount-1 (above right). | **For the MoveToBottom function, we will use almost exactly the same code as the MoveToTop routine, but, in place of the model.move_before() method, we will use the model.move_after() method, and, instead of setting path2 to 0, we set it to self.RowCount-1. Now you understand why we have a RowCount variable. Remember the counts are zero based, so we have to use RowCount-1 (above right). | ||
Ligne 74: | Ligne 74: | ||
Now let's take a look at what it will take to do the MoveUp routine. Once again, it is fairly similar to the last two functions we created. This time, we get path1 which is the selected row and then assign that row number–1 to path2. Then IF path2 (the target row) is greater than or equal to 0, we use the model.swap() method (second down, right).** | Now let's take a look at what it will take to do the MoveUp routine. Once again, it is fairly similar to the last two functions we created. This time, we get path1 which is the selected row and then assign that row number–1 to path2. Then IF path2 (the target row) is greater than or equal to 0, we use the model.swap() method (second down, right).** | ||
- | Pour la fonction Bas, nous utiliserons presque le même code que pour la routine Haut, mais au lieu d' | + | Pour la fonction Bas, nous utiliserons presque le même code que pour la routine Haut, mais au lieu d' |
Maintenant regardons ce que donne la fonction Monter. À nouveau, elle est très ressemblante aux deux fonctions que nous venons de créer. Cette fois-ci, on a chemin1 qui contient la ligne sélectionnée, | Maintenant regardons ce que donne la fonction Monter. À nouveau, elle est très ressemblante aux deux fonctions que nous venons de créer. Cette fois-ci, on a chemin1 qui contient la ligne sélectionnée, | ||
Ligne 88: | Ligne 88: | ||
C'est la même chose pour la fonction Descendre. Cette fois-ci, on vérifie que chemin2 est plus PETIT ou égal à self.NombreDeLignes-1 (troisième en bas à droite). | C'est la même chose pour la fonction Descendre. Cette fois-ci, on vérifie que chemin2 est plus PETIT ou égal à self.NombreDeLignes-1 (troisième en bas à droite). | ||
- | Maintenant, modifions quelques fonctionnalités de notre liste de lecture. Dans l' | + | Maintenant, modifions quelques fonctionnalités de notre liste de lecture. Dans l' |
- | Cependant, je vous ai indiqué qu'il y avait aussi un format étendu. Dans le format étendu, il y a une ligne supplémentaire que l'on peut ajouter au fichier avant chaque chanson, contenant des informations supplémentaires sur la chanson. Le format de cette ligne est le suivant... | + | Cependant, je vous ai indiqué qu'il y avait aussi un format étendu. Dans le format étendu, il y a une ligne supplémentaire que l'on peut ajouter au fichier avant chaque chanson, contenant des informations supplémentaires sur la chanson. Le format de cette ligne est le suivant |
- | # | + | # |
**You might have wondered why we included the mutagen library from the beginning since we never used it. Well, we will now. To refresh your memory, the mutagen library is for accessing ID3 tag information from inside of MP3 files. To get the full discussion about this, please refer to issue 35 of Full Circle which has my part 9 of this series. We'll create a function to deal with the reading of the MP3 file and return the Artist name, the Song Title, and the length of the song in seconds, which are the three things we need for the extended information line. Put the function after the ShowAbout function within the PlaylistCreator class (next page, top right). | **You might have wondered why we included the mutagen library from the beginning since we never used it. Well, we will now. To refresh your memory, the mutagen library is for accessing ID3 tag information from inside of MP3 files. To get the full discussion about this, please refer to issue 35 of Full Circle which has my part 9 of this series. We'll create a function to deal with the reading of the MP3 file and return the Artist name, the Song Title, and the length of the song in seconds, which are the three things we need for the extended information line. Put the function after the ShowAbout function within the PlaylistCreator class (next page, top right). | ||
Ligne 98: | Ligne 98: | ||
Again, to refresh your memory, I'll walk through the code. First we clear the three return variables so that if anything happens they are blank upon return. We then pass in the filename of the MP3 file we are going to look at. Next we pull the keys into (yes, you guessed it) an iterator, and walk through that iterator looking for two specific tags. They are ' | Again, to refresh your memory, I'll walk through the code. First we clear the three return variables so that if anything happens they are blank upon return. We then pass in the filename of the MP3 file we are going to look at. Next we pull the keys into (yes, you guessed it) an iterator, and walk through that iterator looking for two specific tags. They are ' | ||
- | Vous vous demandez | + | Vous vous demandiez |
- | À nouveau, pour vous rafraîchir la mémoire, je vais parcourir le code. Tout d' | + | À nouveau, pour vous rafraîchir la mémoire, je vais parcourir le code. Tout d' |
**Now, we will want to modify the SavePlaylist function to support the extended information line. While we are there, let's check to see if the filename exists, and, if so, flag the user and exit the routine. Also, to make things a bit easier for the user, since we don't support any other filetype, let's automatically append the extension ' | **Now, we will want to modify the SavePlaylist function to support the extended information line. While we are there, let's check to see if the filename exists, and, if so, flag the user and exit the routine. Also, to make things a bit easier for the user, since we don't support any other filetype, let's automatically append the extension ' | ||
Ligne 110: | Ligne 110: | ||
| | ||
- | On va maintenant modifier la fonction SauvegarderListe pour qu' | + | On va maintenant modifier la fonction SauvegarderListe pour qu' |
Tout comme pour la fonction AjouterFichiers, | Tout comme pour la fonction AjouterFichiers, | ||
Ligne 116: | Ligne 116: | ||
if os.path.exists(cf + "/" | if os.path.exists(cf + "/" | ||
- | | + | |
**Next, we want to wrap the rest of the function with an IF|ELSE clause (top right) so if the file already exists, we simply fall out of the routine. We use os.path.exists(filename) to do this check. | **Next, we want to wrap the rest of the function with an IF|ELSE clause (top right) so if the file already exists, we simply fall out of the routine. We use os.path.exists(filename) to do this check. | ||
Ligne 124: | Ligne 124: | ||
Line 2 opens the file we are going to write. Line 3 puts the M3U header in. Line 4 sets up for a walk through the playList ListStore. Line 5 creates the filename from the three columns of the ListStore. Line 6 calls GetMP3Info and stores the return values into variables. Line 7 then checks to see if we have values in all three variables. If so, we write the extended information line in line 8, otherwise we don't try. Line 9 writes the filename line as before. Line 10 closes the file gracefully, and line 11 pops up the message box letting the user know the process is all done.** | Line 2 opens the file we are going to write. Line 3 puts the M3U header in. Line 4 sets up for a walk through the playList ListStore. Line 5 creates the filename from the three columns of the ListStore. Line 6 calls GetMP3Info and stores the return values into variables. Line 7 then checks to see if we have values in all three variables. If so, we write the extended information line in line 8, otherwise we don't try. Line 9 writes the filename line as before. Line 10 closes the file gracefully, and line 11 pops up the message box letting the user know the process is all done.** | ||
- | Ensuite on veut entourer le reste de la fonction dans une clause IF|ELSE (en haut à droite) pour que si le fichier existe déjà on puisse simplement sortir de la routine. On utilise os.path.exists(nom du fichier) pour cette vérification. | + | Ensuite on veut entourer le reste de la fonction dans une clause IF|ELSE (en haut à droite) pour que, si le fichier existe déjà, on puisse simplement sortir de la routine. On utilise os.path.exists(nom du fichier) pour cette vérification. |
Le reste du code sert principalement à sauvegarder comme précédemment, | Le reste du code sert principalement à sauvegarder comme précédemment, | ||
- | La ligne 2 ouvre le fichier dans lequel nous allons écrire. La ligne 3 y place l' | + | La ligne 2 ouvre le fichier dans lequel nous allons écrire. La ligne 3 y place l' |
**Go ahead and save your code and give it a test drive. | **Go ahead and save your code and give it a test drive. | ||
Ligne 137: | Ligne 137: | ||
self.SetupToolTops()** | self.SetupToolTops()** | ||
+ | |||
Allez, sauvegardez votre code et essayez-le. | Allez, sauvegardez votre code et essayez-le. | ||
- | À ce point, la seule chose qu'on pourrait encore ajouter serait des bulles d'aide lorsque l' | + | À ce stade, la seule chose qu'on pourrait encore ajouter serait des bulles d'aide lorsque l' |
- | Nous utilisons le widget references que nous avons réglé plus haut, puis on règle le texte pour la bulle d'aide avec (vous l' | + | Nous utilisons le widget references que nous avons réglé plus haut, puis on règle le texte pour la bulle d'aide avec (vous l' |
- | self.SetupToolTops() | + | self.SetupBullesAide() |
**Last, but certainly not least, we want to put our logo into our About box. Just like everything else there, there' | **Last, but certainly not least, we want to put our logo into our About box. Just like everything else there, there' | ||
Ligne 156: | Ligne 157: | ||
Until next time, enjoy your new found skills.** | Until next time, enjoy your new found skills.** | ||
- | Pour finir, mais est-ce vraiment la fin, on veut placer notre logo dans la boite APropos. Comme tout le reste ici, il y a un attribut pour faire cela. Ajoutez la ligne suivante à la routine APropos. | + | Enfin et surtout (!), on veut placer notre logo dans la boîte |
- | about.set_logo(gtk.gdk.pixbuf_new_from_file(" | + | apropos.set_logo(gtk.gdk.pixbuf_new_from_file(" |
- | Et voila. Vous avez maintenant une application complète | + | Et voilà. Vous avez maintenant une application complète, fonctionnelle et jolie, qui fait un travail merveilleux de création de liste de lecture pour vos fichiers de musique. |
- | Le code complet, incluant le fichier glade que nous avons créé le mois dernier, est disponible ici : http:// | + | Le code complet, incluant le fichier glade que nous avons créé le mois dernier, est disponible ici : http:// |
Profitez des nouveaux talents que vous vous êtes découverts, | Profitez des nouveaux talents que vous vous êtes découverts, | ||
Ligne 226: | Ligne 227: | ||
nf = self.txtNomFichier.get_text() # recuperer le nom du fichier dans le champ de texte | nf = self.txtNomFichier.get_text() # recuperer le nom du fichier dans le champ de texte | ||
- | Maintenant on vérifie les valeurs... | + | Maintenant on vérifie les valeurs |
if cf == "": | if cf == "": | ||
Ligne 270: | Ligne 271: | ||
(modele, | (modele, | ||
for chemin1 in lignes: | for chemin1 in lignes: | ||
- | chemin2 = self.NombreLignes-1 | + | chemin2 = self.NombreDeLignes-1 |
iter1=modele.get_iter(chemin1) | iter1=modele.get_iter(chemin1) | ||
iter2 = modele.get_iter(chemin2) | iter2 = modele.get_iter(chemin2) | ||
Ligne 307: | Ligne 308: | ||
====== CODE PAGE 11 haut ====== | ====== CODE PAGE 11 haut ====== | ||
- | def GetMP3Info(self,filename): | + | |
- | | + | |
- | | + | |
- | | + | |
- | audio = MP3(filename) | + | audio = MP3(nomFichier) |
- | | + | |
- | for key in keys: | + | for cle in cles: |
try: | try: | ||
- | if key == " | + | if cle == " |
- | | + | |
except: | except: | ||
- | | + | |
try: | try: | ||
- | if key == " | + | if cle == " |
- | | + | |
except: | except: | ||
- | | + | |
- | | + | |
- | return (artist,title,songlength) | + | return (artiste,titre,longueurChanson) |
====== CODE PAGE 11 bas ====== | ====== CODE PAGE 11 bas ====== | ||
Ligne 331: | Ligne 332: | ||
import os.path | import os.path | ||
- | Then, go ahead and comment out your existing SavePlaylist function and we'll replace it. | + | Ensuite continuez et commentez la fonction SauveListeLecture actuelle et nous allons la remplacer. |
def SavePlaylist(self): | def SavePlaylist(self): | ||
Ligne 342: | Ligne 343: | ||
else: # Otherwise | else: # Otherwise | ||
- | Up to this point, the routine | + | Jusqu' |
- | + | ||
- | extStart = fn.rfind(" | + | |
- | if extStart == -1: | + | |
- | fn += ' | + | |
- | self.txtFilename.set_text(fn) #replace the filename in the text box | + | |
+ | debutExt = nf.rfind(" | ||
+ | if debutExt == -1: | ||
+ | nf += ' | ||
+ | self.txtNomFichier.set_text(nf) # remplace le nom de fichier dans le champ de texte | ||
====== CODE PAGE 12 haut ====== | ====== CODE PAGE 12 haut ====== | ||
- | else: | + | |
- | plfile | + | |
- | plfile.writelines('# | + | fic.writelines('# |
- | | + | for ligne in self.listeLecture: |
- | | + | nomFic |
- | | + | artiste,titre,longueurChanson |
- | if songlength | + | |
- | plfile.writelines("# | + | fic.writelines("# |
- | | + | fic.writelines(" |
- | plfile.close | + | fic.close |
- | | + | self.MessageBox(" |
====== CODE PAGE 12 bas ====== | ====== CODE PAGE 12 bas ====== | ||
- | def SetupToolTips(self): | + | |
- | self.tbtnAdd.set_tooltip_text(" | + | self.boBtnAjouter.set_tooltip_text(" |
- | self.tbtnAbout.set_tooltip_text(" | + | self.boBtnAPropos.set_tooltip_text(" |
- | self.tbtnDelete.set_tooltip_text(" | + | self.boBtnSupprimer.set_tooltip_text(" |
- | self.tbtnClearAll.set_tooltip_text(" | + | self.boBtnEffacer.set_tooltip_text(" |
- | self.tbtnQuit.set_tooltip_text(" | + | self.boBtnQuitter.set_tooltip_text(" |
- | self.tbtnMoveToTop.set_tooltip_text(" | + | self.boBtnHaut.set_tooltip_text(" |
- | self.tbtnMoveUp.set_tooltip_text(" | + | self.boBtnMonter.set_tooltip_text(" |
- | self.tbtnMoveDown.set_tooltip_text(" | + | self.boBtnDescendre.set_tooltip_text(" |
- | self.tbtnMoveToBottom.set_tooltip_text(" | + | self.boBtnBas.set_tooltip_text(" |
- | self.btnGetFolder.set_tooltip_text(" | + | self.btnNomRepertoire.set_tooltip_text(" |
- | self.btnSavePlaylist.set_tooltip_text(" | + | self.btnSauvegarderListe.set_tooltip_text(" |
- | self.txtFilename.set_tooltip_text(" | + | self.txtNomFichier.set_tooltip_text(" |
issue49/tutopython.1308598562.txt.gz · Dernière modification : 2011/06/20 21:36 de fredphil91