Outils pour utilisateurs

Outils du site


issue49:tutopython

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
issue49:tutopython [2011/06/20 21:35] fredphil91issue49: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, add a handler for on_treeview1_cursor_changed. Remember, as I told you last month, to click off that to make the change stick. Finally, again in the hierarchy box, select txtFilename, and go to the signal tab. Scroll down until you find 'GtkWidget', and scroll down further until you get to 'key-press-event'. Add a handler for 'on_txtFilename_key_press_event'. Save your glade project and close glade.** 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, add a handler for on_treeview1_cursor_changed. Remember, as I told you last month, to click off that to make the change stick. Finally, again in the hierarchy box, select txtFilename, and go to the signal tab. Scroll down until you find 'GtkWidget', and scroll down further until you get to 'key-press-event'. Add a handler for 'on_txtFilename_key_press_event'. Save your glade project and close glade.**
  
-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'avons pas terminé certaines parties. Nous ne pouvons pas encore sauvegarder la liste de lecture, les fonctions de déplacement ne sont pas implémentées, nous ne pouvons pas choisir le chemin vers lequel on veut sauvegarder, etc. Cependant, il faut commencer par certaines choses avant de commencer à coder. Tout d'abord, nous devons trouver une image pour le logo de notre application dans la boite « À propos »et lorsque l'application est minimisée. Vous pouvez chercher une icône qui vous plaît dans le répertoire /usr/share/icons, ou aller sur le web en chercher uneou encore en créer une vous-mêmes. Quel que soit le choix, placez cette image dans le répertoire contenant le code source et le fichier glade du mois dernier. Nommez-la logo.png. Ensuite, nous devons ouvrir le fichier glade du mois dernier et faire quelques changements.+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'avons pas terminé certaines parties. Nous ne pouvons pas encore sauvegarder la liste de lecture, les fonctions de déplacement ne sont pas implémentées, nous ne pouvons pas choisir le chemin vers lequel on veut sauvegarder, etc. Cependant, nous devons faire certaines choses avant de commencer à coder. Tout d'abord, nous devons trouver une image pour le logo de notre application dans la boîte « À propos » et lorsque l'application est minimisée. Vous pouvez chercher une icône qui vous plaît dans le répertoire /usr/share/icons, ou aller sur le web en chercher une ou encore en créer une vous-même. Quel que soit le choix, placez cette image dans le répertoire contenant le code source et le fichier glade du mois dernier. Nommez-la logo.png. Ensuite, nous devons ouvrir le fichier glade du mois dernier et faire quelques changements.
  
-Tout d'abord, avec la FenetrePrincipale, allez dans l'onglet Général et descendez jusqu'à trouver Icône. En utilisant l'outil de parcours de fichiers, trouvez votre icône et sélectionnez-la. Maintenant le champ de texte devrait contenir "logo.png". Puis, dans la boite de hiérarchie, choisissez treeview1, allez dans l'onglet Signaux et ajoutez un gestionnaire pour on_treeview1_cursor_changed dans la partie GtkTreeView | cursor-changed. Souvenez-vous que nous avons vu le mois dernier que vous devez cliquer à côté pour conserver vos changements. Enfin, toujours dans la boite hiérarchie, choisissez txtNomFichier et allez dans l'onglet Signaux. Descendez jusqu'à trouver GtkWidget et descendez encore jusqu'à key-press-event. Ajoutez un gestionnaire d'événement pour on_txtNomFichier_key_press_event. Sauvegardez votre projet glade et fermez glade.+Tout d'abord, avec la FenetrePrincipale, allez dans l'onglet Général et descendez jusqu'à trouver Icône. En utilisant l'outil de parcours de fichiers, trouvez votre icône et sélectionnez-la. Maintenant le champ de texte devrait contenir "logo.png". Puis, dans la boîte de hiérarchie, choisissez treeview1, allez dans l'onglet Signaux et ajoutez un gestionnaire pour on_treeview1_cursor_changed dans la partie GtkTreeView | cursor-changed. Souvenez-vous que nous avons vu le mois dernier que vous devez cliquer à côté pour conserver vos modifications. Enfin, toujours dans la boîte hiérarchie, choisissez txtNomFichier et allez dans l'onglet Signaux. Descendez jusqu'à trouver GtkWidget et descendez encore jusqu'à key-press-event. Ajoutez un gestionnaire d'événement pour on_txtNomFichier_key_press_event. Sauvegardez votre projet glade et fermez glade.
  
 **Now it's time to complete our project. We'll start from where we left off using last month's code. **Now it's time to complete our project. We'll start from where we left off using last month's code.
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't have to even click the button.** 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't have to even click the button.**
  
-Maintenant il est temps de continuer notre projet. Nous commencerons à coder là où nous en étions resté le mois dernier.+Maintenant il est temps de terminer notre projet. Nous commencerons à coder là où nous en étions resté le mois dernier.
  
-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'utilisateur cliquait le bouton Annuler, il se produisait une erreur. Nous allons commencer par corriger ça. À la fin de la routine, vous avez le code ci-dessus.+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'utilisateur cliquait le bouton Annuler, il se produisait une erreur. Nous allons commencer par corriger ça. À la fin de la routine, vous avez le code ci-dessus.
  
-Comme vous l'imaginez, cela regarde simplement la valeur de chaque touche enfoncée lorsque l'utilisateur se trouve dans le champ de texte txtNomFichieret la compare à la valeur 65293, qui est le code attribué à la touche Entrée. Si cela  correspond, alors il appelle la fonction SauvegarderListe. L'utilisateur n'a même pas besoin de cliquer sur le bouton.+Comme vous pouvez le supposer, cela regarde simplement la valeur de chaque touche enfoncée lorsque l'utilisateur se trouve dans le champ de texte txtNomFichier et la compare à la valeur 65293, qui est le code attribué à la touche Entrée. Si cela correspond, alors il appelle la fonction SauvegarderListe. L'utilisateur n'a même pas besoin de cliquer sur le bouton.
  
 **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, so go slowly. In order to get data back from the ListStore, we first have to get a gtk.TreeSelection which is a helper object that manages the selection within a treeview. Then we use that helper object to retrieve the model type, and an iterator that contains the selected rows.** First we have to discuss how we get a selection from the treeview widget and the ListStore. This is complicated, so go slowly. In order to get data back from the ListStore, we first have to get a gtk.TreeSelection which is a helper object that manages the selection within a treeview. Then we use that helper object to retrieve the model type, and an iterator that contains the selected rows.**
  
-Maintenant passons au code. Occupons-nous du bouton Effacer de la barre d'outils. Lorsque l'utilisateur clique sur ce bouton, on veut effacer la vue en arbre et ListStore. Cela se fait en une ligne, que l'on peut placer dans la routine on_boBtnEffacer_clicked.+Maintenant passons au code. Occupons-nous du bouton Effacer de la barre d'outils. Lorsque l'utilisateur clique sur ce bouton, on veut effacer la liste arborescente et ListStore. Cela se fait en une ligne, que l'on peut placer dans la routine on_boBtnEffacer_clicked.
  
 def on_boBtnEffacer_clicked(self,widget): def on_boBtnEffacer_clicked(self,widget):
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), fill that into a list called iters, and then walk it removing (like the .clear method). We also decrement the variable RowCount, and then display the number of files in the status bar.** 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), fill that into a list called iters, and then walk it removing (like the .clear method). We also decrement the variable RowCount, and then display the number of files in the status bar.**
  
-Je sais que vous pensez « mais bon sang, qu'est-ce qu'un itérateur ? ». Eh bien vous en avez déjà utilisé sans même le savoir. Regardez le code suivant (ci-dessus à droite) provenant de la fonction AjouterFichiers du mois dernier.+Je sais que vous pensez « Mais bon sang, qu'est-ce qu'un itérateur ? ». Eh bienvous en avez déjà utilisé sans même le savoir. Regardez le code suivant (ci-dessus à droite) provenant de la fonction AjouterFichiers du mois dernier.
  
-Regardez la boucle for. On utilise un itérateur pour parcourir la liste ListeFichiers. Dans ce cas, l'itérateur passe tout simplement d'une entrée de la liste à la suivante, renvoyant chaque élément séparément. Nous allons donc créer un itérateur, le remplir avec les lignes de la vue arborescente sélectionnées et utiliser cela comme une liste. Donc voici le code (au milieu à droite) pour on_boBtnSupprimer.+Regardez la boucle for. On utilise un itérateur pour parcourir la liste ListeFichiers. Dans ce cas, l'itérateur passe tout simplement d'une entrée de la liste à la suivante, renvoyant chaque élément séparément. Nous allons créer un itérateur, le remplir avec les lignes de la vue arborescente sélectionnées et l'utiliser comme une liste. Voici donc le code (au milieu à droite) pour on_boBtnSupprimer.
  
-La première ligne crée l'objet TreeSelection. On l'utilise pour récupérer les lignes sélectionnées (il n'y en a qu'une car notre modèle n'est pas réglé pour offrir la sélection multiple), remplir une liste nommée iter, et la parcourir en enlevant chaque élément (comme la méthode .clear). On décrément également la variable NombreDeLignes, puis on affiche le nombre de fichiers dans la barre d'état.+La première ligne crée l'objet TreeSelection. On l'utilise pour récupérer les lignes sélectionnées (il n'y en a qu'une car notre modèle n'est pas réglé pour offrir la sélection multiple), remplir une liste nommée iter avec, et la parcourir en enlevant chaque élément (comme la méthode .clear). On décrémente également la variable NombreDeLignes, puis on affiche le nombre de fichiers dans la barre d'état.
  
 **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 0et l'extension dans la colonne 1. On crée simplement (à droite) une chaîne puis on l'écrit dans le fichier et enfin on ferme le fichier.+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'extension dans la colonne 1. On crée simplement (à droite) une chaînepuis on l'écrit dans le fichier et enfin on ferme le fichier.
  
-On peut maintenant commencer à travailler sur les fonctions de déplacement. Commençons par la routine Haut. Comme nous l'avons fait en écrivant la fonction Supprimer, on récupère la sélection puis les lignes sélectionnées. Ensuite on doit parcourir les lignes pour récupérer 2 variables. Nous les appellerons chemin1 et chemin2. chemin2 sera réglé à 0 dans ce cas, car cc'est la ligne de « destination ». chemin1 est la ligne que l'utilisateur a sélectionnée. On utilise enfin la méthode modele.move_before() pour déplacer la ligne sélectionnée sur la ligne 0, en poussant d'office tout vers le bas. Nous placerons le code (ci-dessous à droite) directement dans la routine on_boBtnHaut_clicked.+On peut maintenant commencer à travailler sur les fonctions de déplacement. Commençons par la routine Haut. Comme nous l'avons fait en écrivant la fonction Supprimer, on récupère la sélection puis la ligne sélectionnée. Ensuite on doit parcourir les lignes pour récupérer 2 variables. Nous les appellerons chemin1 et chemin2. chemin2 sera réglé à 0 dans ce cas, car c'est la ligne de « destination ». chemin1 est la ligne que l'utilisateur a sélectionnée. On utilise enfin la méthode modele.move_before() pour déplacer la ligne sélectionnée sur la ligne 0, en poussant d'office tout vers le bas. Nous placerons le code (ci-dessous à droite) directement dans la routine on_boBtnHaut_clicked.
  
 **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'utiliser la méthode modele.moveBefore(), nous utiliserons la méthode modele.moveAfter()et au lieu de régller chemin2 à 0 on le réglera à self.NombreDeLignes-1. Maintenant vous comprenez à quoi sert la variable NombreDeLignes. Souvenez-vous que les lignes sont numérotées à partir de 0, donc il faut utiliser NombreDeLignes-1 (ci-dessus à droite).+Pour la fonction Bas, nous utiliserons presque le même code que pour la routine Haut, mais au lieu d'utiliser la méthode modele.moveBefore(), nous utiliserons la méthode modele.moveAfter() etau lieu de régler chemin2 à 0on le réglera à self.NombreDeLignes-1. Maintenant vous comprenez à quoi sert la variable NombreDeLignes. Souvenez-vous que les lignes sont numérotées à partir de 0, donc il faut utiliser NombreDeLignes-1 (ci-dessus à droite).
  
 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, et on règle chemin2 à NumeroLigne-1. Ensuite, SI chemin2 (la ligne de destination) est supérieur ou égal à 0, on utilise la méthode modele.swap() (deuxième en bas à droite). 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, et on règle chemin2 à NumeroLigne-1. Ensuite, SI chemin2 (la ligne de destination) est supérieur ou égal à 0, on utilise la méthode modele.swap() (deuxième en bas à droite).
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'article du mois dernier, je vous ai montré le format basique d'une liste de lecture (en bas).+Maintenant, modifions quelques fonctionnalités de notre liste de lecture. Dans l'article du mois dernier, je vous ai montré le format de base d'une liste de lecture (en bas).
  
-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 :
  
-#EXTINF:[longueur de la chanson en secondes],[Nom de l'artiste] – [Titre de la chanson]**+#EXTINF:[longueur de la chanson en secondes],[Nom de l'artiste] – [Titre de la chanson]
  
 **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 'TPE1' which is the artist name, and 'TIT2' which is the song title. Now, if the key doesn't exist, we would get an error, so we wrap each get call with a 'try|except' statement. We then pull the song length from the audio.info.length attribute, and return the whole shebang.** 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 'TPE1' which is the artist name, and 'TIT2' which is the song title. Now, if the key doesn't exist, we would get an error, so we wrap each get call with a 'try|except' statement. We then pull the song length from the audio.info.length attribute, and return the whole shebang.**
  
-Vous vous demandez peut-être pourquoi on a inclus la bibliothèque mutagen depuis le début alors qu'on ne l'a jamais utilisée. Eh bien nous allons l'utiliser maintenant. Pour vous rafraîchir la mémoire, la bibliothèque mutagen permet d'avoir accès les informations des balises ID3 des fichiers MP3. Pour lire la discussion complète là-dessus, reportez-vous au numéro 35 de Full Circle qui contient la partie 9 de cette série. Nous créerons une fonction pour gérer la lecture d'un fichier MP3 et renvoyer le nom de l'artiste, le titre de la chanson et sa longueur en secondes, qui sont les trois informations dont nous avons besoin pour la ligne des informations étendues. Placez cette fonction après la fonction APropos dans la classe CreateurListeDeLecture (page suivante, en haut à droite).+Vous vous demandiez peut-être pourquoi on a inclus la bibliothèque mutagen depuis le début alors qu'on ne l'a jamais utilisée. Eh biennous allons l'utiliser maintenant. Pour vous rafraîchir la mémoire, la bibliothèque mutagen permet d'avoir accès aux informations des balises ID3 des fichiers MP3. Pour lire la discussion complète là-dessus, reportez-vous au numéro 35 du Full Circle qui contient la partie 9 de cette série. Nous créerons une fonction pour gérer la lecture d'un fichier MP3 et renvoyer le nom de l'artiste, le titre de la chanson et sa longueur en secondes, qui sont les trois informations dont nous avons besoin pour la ligne des informations étendues. Placez cette fonction après la fonction APropos dans la classe CreateurListeDeLecture (page suivante, en haut à droite).
  
-À nouveau, pour vous rafraîchir la mémoire, je vais parcourir le code. Tout d'abord nous effaçons les trois variables de retour pour qu'elles soient renvoyées vides si quelque chose se passe de travers. Ensuite on passe le nom du fichier MP3 que nous allons examiner. Ensuite on place les clés dans (vous avez deviné) un itérateur et on parcourt cet itérateur en cherchant les deux balises spécifiques. Ce sont TPE1 pour le nom de l'artiste et TIT2 pour le titre de la chanson. Si jamais la clé n'existe pas, on obtiendra une erreur, donc on entoure chaque appel avec une instruction try|except. Ensuite on va chercher la longueur de la chanson dans l'attribut audio.song.info.length  et on retourne tout ça.+À nouveau, pour vous rafraîchir la mémoire, je vais parcourir le code. Tout d'abord nous effaçons les trois variables de retour pour qu'elles soient renvoyées vides si quelque chose se passe de travers. Ensuite on passe le nom du fichier MP3 que nous allons examiner. Puis on place les clés dans (vous l'avez deviné) un itérateur et on parcourt cet itérateur en cherchant les deux balises spécifiques. Ce sont TPE1 pour le nom de l'artiste et TIT2 pour le titre de la chanson. Si jamais la clé n'existe pas, on obtiendra une erreur, donc on entoure chaque appel avec une instruction try|except. Ensuite on va chercher la longueur de la chanson dans l'attribut audio.info.length et on retourne tout ça.
  
 **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 '.m3u' to the path and filename if it doesn't exist. First add an import line at the top of the code importing os.path between the sys import and the mutagen import (bottom right). **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 '.m3u' to the path and filename if it doesn't exist. First add an import line at the top of the code importing os.path between the sys import and the mutagen import (bottom right).
Ligne 110: Ligne 110:
    self.MessageBox("error","The file already exists. Please select another.")**    self.MessageBox("error","The file already exists. Please select another.")**
  
-On va maintenant modifier la fonction SauvegarderListe pour qu'elle supporte la ligne d'informations étendues. Tant que nous y sommes, vérifions si le nom de fichier existe et si c'est le cas prévenons l'utilisateur et sortons de la routine. Aussi, pour rendre les choses un peu plus faciles pour l'utilisateuret puisqu'on ne supporte aucun autre type de fichier, ajoutons automatiquement l'extension .m3u au chemin et au nom de fichier si elle n'y est pas déjà. Commençons par ajouter une ligne « import os.path » au début du code entre les import de sys et de mutagen. (en bas à droite).+On va maintenant modifier la fonction SauvegarderListe pour qu'elle supporte la ligne d'informations étendues. Tant que nous y sommes, vérifions si le nom de fichier existe etsi c'est le casprévenons l'utilisateur et sortons de la routine. Aussi, pour rendre les choses un peu plus faciles pour l'utilisateur etpuisqu'on ne supporte aucun autre type de fichier, ajoutons automatiquement l'extension .m3u au chemin et au nom de fichier si elle n'y est pas déjà. Commençons par ajouter une ligne « import os.path » au début du code entre les import de sys et de mutagen. (en bas à droite).
  
 Tout comme pour la fonction AjouterFichiers, nous utiliserons la méthode rfind pour trouver la position du dernier point (« . ») dans le nom du fichier nf. S'il n'y en a pas, la valeur renvoyée sera -1. Donc nous vérifions si la valeur retournée est -1 et si c'est le cas on ajoute l'extension et on replace le nom du fichier dans le champ de texte pour être sympa. Tout comme pour la fonction AjouterFichiers, nous utiliserons la méthode rfind pour trouver la position du dernier point (« . ») dans le nom du fichier nf. S'il n'y en a pas, la valeur renvoyée sera -1. Donc nous vérifions si la valeur retournée est -1 et si c'est le cas on ajoute l'extension et on replace le nom du fichier dans le champ de texte pour être sympa.
Ligne 116: Ligne 116:
 if os.path.exists(cf + "/" + nf): if os.path.exists(cf + "/" + nf):
  
-   self.MessageBox("erreur","Le fichier existe déjà. Choisissez un autre nom.")+   self.MessageBox("erreur","Le fichier existe deja. Choisissez un autre nom.")
  
 **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 quesi 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, mais regardons-le quand même. Le reste du code sert principalement à sauvegarder comme précédemment, mais regardons-le quand même.
  
-La ligne 2 ouvre le fichier dans lequel nous allons écrire. La ligne 3 y place l'en-tête M3U. La ligne 4 règle un parcours à travers la liste de lecture ListStore. La ligne 5 crée le nom du fichier à partir des trois colonnes de ListStore. La ligne 6 appelle GetMP3Info et stocke les valeurs renvoyées dans des variables. La ligne 7 vérifie ensuite si nous avons des valeurs dans toutes ces variables. Si c'est le cas, on écrit la ligne d'informations étendues à la ligne 8, sinon on n'essaie pas. La ligne 9 écrit la ligne du nom du fichier comme précédemment. La ligne 10 ferme le fichier gentiment, et la ligne 11 affiche un message à l'utilisateur indiquant que tout est terminé.+La ligne 2 ouvre le fichier dans lequel nous allons écrire. La ligne 3 y place l'en-tête M3U. La ligne 4 règle un parcours à travers la liste de lecture ListStore. La ligne 5 crée le nom du fichier à partir des trois colonnes de ListStore. La ligne 6 appelle RecupererInfoMP3 et stocke les valeurs renvoyées dans des variables. La ligne 7 vérifie ensuite si nous avons des valeurs dans toutes ces variables. Si c'est le cas, on écrit la ligne d'informations étendues à la ligne 8, sinon on n'essaie pas. La ligne 9 écrit la ligne du nom du fichier comme précédemment. La ligne 10 ferme gentiment le fichier et la ligne 11 affiche un message à l'utilisateur indiquant que tout est terminé.
  
 **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'utilisateur survole nos contrôles avec sa souris. Cela ajoute cet air professionnel (ci--dessous). Créons maintenant une fonction pour faire cela.+À ce stade, la seule chose qu'on pourrait encore ajouter serait des bulles d'aide lorsque l'utilisateur survole nos contrôles avec sa souris. Cela ajoute cet air professionnel (ci-dessous). Créons maintenant une fonction pour faire cela.
  
-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'aurez deviné) l'attribut set_tooltip_text. Ensuiteon doit ajouter l'appel à la routine. Retournez dans la routine <nowiki>__init__</nowiki> après la ligne self.ReferencesWidgets, ajoutez :+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'aurez deviné) l'attribut set_tooltip_text. Ensuite on doit ajouter l'appel à la routine. Retournez dans la routine <nowiki>__init__</nowiki>après la ligne self.ReferencesWidgets, ajoutez :
  
-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's an attribute for that. Add the following line to the ShowAbout routine. **Last, but certainly not least, we want to put our logo into our About box. Just like everything else there, there's an attribute for that. Add the following line to the ShowAbout routine.
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 APropos. Comme tout le reste ici, il y a un attribut pour faire cela. Ajoutez la ligne suivante à la routine APropos :
  
-about.set_logo(gtk.gdk.pixbuf_new_from_file("logo.png"))+apropos.set_logo(gtk.gdk.pixbuf_new_from_file("logo.png"))
  
-Et voila. Vous avez maintenant une application complète et fonctionnelle et jolie, qui fait un travail merveilleux de création de liste de lecture pour vos fichiers de musique.+Et voilà. Vous avez maintenant une application complètefonctionnelle 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://pastebin.com/+Le code complet, incluant le fichier glade que nous avons créé le mois dernier, est disponible ici : http://pastebin.com/ZfZ69zVJ
  
 Profitez des nouveaux talents que vous vous êtes découverts, jusqu'à la prochaine fois. Profitez des nouveaux talents que vous vous êtes découverts, jusqu'à la prochaine fois.
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 == "":                     # SI le chemin est vide         if cf == "":                     # SI le chemin est vide
Ligne 270: Ligne 271:
         (modele,lignes) = sel.get_selected_rows()         (modele,lignes) = sel.get_selected_rows()
         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 293: Ligne 294:
             chemin2 = (chemin1[0]+1,)             chemin2 = (chemin1[0]+1,)
         iter1=modele.get_iter(chemin1)         iter1=modele.get_iter(chemin1)
-        if chemin2[0] <= self.NombreLignes-1:+        if chemin2[0] <= self.NombreDeLignes-1:
             iter2 = modele.get_iter(chemin2)             iter2 = modele.get_iter(chemin2)
             modele.swap(iter1,iter2)             modele.swap(iter1,iter2)
Ligne 307: Ligne 308:
 ====== CODE PAGE 11 haut ====== ====== CODE PAGE 11 haut ======
  
-def GetMP3Info(self,filename): +  def RecupererInfoMP3(self,nomFichier): 
-        artist = '' +        artiste = '' 
-        title = '' +        titre = '' 
-        songlength = 0 +        longueurChanson = 0 
-        audio = MP3(filename+        audio = MP3(nomFichier
-        keys = audio.keys() +        cles = audio.keys() 
-        for key in keys:+        for cle in cles:
             try:             try:
-                if key == "TPE1":         # Artist +                if cle == "TPE1":         # Artiste 
-                    artist = audio.get(key)+                    artiste = audio.get(cle)
             except:             except:
-                artist = ''+                artiste = ''
             try:             try:
-                if key == "TIT2":         # Song Title +                if cle == "TIT2":         # Titre de la chanson 
-                    title = audio.get(key)+                    titre = audio.get(cle)
             except:             except:
-                title = '' +                titre = '' 
-            songlength = audio.info.length    # Audio Length +            longueurChanson = audio.info.length    # longueur de la chanson 
-        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 is the same. Here's where the changes start. +Jusqu'ici la routine est la mêmeVoici où les changements commencent.
- +
-            extStart = fn.rfind(".") # Find the extension start position +
-            if extStart == -1: +
-                fn += '.m3u' #append the extension if there isn't one. +
-                self.txtFilename.set_text(fn) #replace the filename in the text box+
  
 +        debutExt = nf.rfind(".") # cherche le debut de l'extension
 +        if debutExt == -1:
 +            nf += '.m3u' # ajouter une extension s'il n'y en a pas
 +            self.txtNomFichier.set_text(nf) # remplace le nom de fichier dans le champ de texte
 ====== CODE PAGE 12 haut ====== ====== CODE PAGE 12 haut ======
  
-else: +  else: 
-       plfile = open(fp + "/"fn,"w"Open the file +            fic = open(cf + "/"nf,"w"ouvre le fichier 
-       plfile.writelines('#EXTM3U\n'   #Print the M3U header +            fic.writelines('#EXTM3U\n'   # affiche l'en-tete M3U 
-       for row in self.playList+            for ligne in self.listeLecture
-          fname = "%s/%s.%s" % (row[2],row[0],row[1]) +               nomFic = "%s/%s.%s" % (ligne[2],ligne[0],ligne[1]) 
-          artist,title,songlength = self.GetMP3Info(fname+               artiste,titre,longueurChanson = self.RecupererInfoMP3(nomFic
-          if songlength > 0 and (artist != '' and title != ''): +               if longueurChanson > 0 and (artiste != '' and titre != ''): 
-             plfile.writelines("#EXTINF:%d,%s - %s\n" % (songlength,artist,title)) +                  fic.writelines("#EXTINF:%d,%s - %s\n" % (longueurChanson,artiste,titre)) 
-          plfile.writelines("%s\n"fname+               fic.writelines("%s\n"nomFic
-       plfile.close Finally Close the file +            fic.close referme le fichier 
-       self.MessageBox("info","Playlist file saved!")+            self.MessageBox("info","Liste de lecture sauvegardee !")
  
 ====== CODE PAGE 12 bas ====== ====== CODE PAGE 12 bas ======
  
-def SetupToolTips(self): +  def SetupBullesAide(self): 
-        self.tbtnAdd.set_tooltip_text("Add file or files to the playlist.") +        self.boBtnAjouter.set_tooltip_text("Ajoute un ou des fichier(s) la liste de lecture.") 
-        self.tbtnAbout.set_tooltip_text("Display the About Information.") +        self.boBtnAPropos.set_tooltip_text("Affiche les informations sur le programme.") 
-        self.tbtnDelete.set_tooltip_text("Delete selected entry from the list.") +        self.boBtnSupprimer.set_tooltip_text("Supprime l'entree selectionnee de la liste.") 
-        self.tbtnClearAll.set_tooltip_text("Remove all entries from the list.") +        self.boBtnEffacer.set_tooltip_text("Supprime toutes les entrees de la liste.") 
-        self.tbtnQuit.set_tooltip_text("Quit this program.") +        self.boBtnQuitter.set_tooltip_text("Quitte le programme.") 
-        self.tbtnMoveToTop.set_tooltip_text("Move the selected entry to the top of the list.") +        self.boBtnHaut.set_tooltip_text("Deplace l'entree selectionne tout en haut de la liste.") 
-        self.tbtnMoveUp.set_tooltip_text("Move the selected entry up in the list.") +        self.boBtnMonter.set_tooltip_text("Remonte l'entree selectionnee dans la liste.") 
-        self.tbtnMoveDown.set_tooltip_text("Move the selected entry down in the list.") +        self.boBtnDescendre.set_tooltip_text("Descend l'entree selectionne dans la liste.") 
-        self.tbtnMoveToBottom.set_tooltip_text("Move the selected entry to the bottom of the list.") +        self.boBtnBas.set_tooltip_text("Deplace l'entree selectionnee tout en bas de la liste.") 
-        self.btnGetFolder.set_tooltip_text("Select the folder that the playlist will be saved to.") +        self.btnNomRepertoire.set_tooltip_text("Choisis le repertoire de sauvegarde de la liste.") 
-        self.btnSavePlaylist.set_tooltip_text("Save the playlist.") +        self.btnSauvegarderListe.set_tooltip_text("Sauvegarde la liste.") 
-        self.txtFilename.set_tooltip_text("Enter the filename to be saved here The extension '.m3u' will be added for you if you don't include it.")+        self.txtNomFichier.set_tooltip_text("Entrez ici le nom du fichier a sauvegarderL'extension .m3u sera ajoutee pour vous si vous l'oubliez.")
  
  
issue49/tutopython.1308598522.txt.gz · Dernière modification : 2011/06/20 21:35 de fredphil91