Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente |
issue48:tuto-python [2011/05/29 20:12] – [CODE PAGE 10 (haut)] fredphil91 | issue48:tuto-python [2011/06/16 08:37] (Version actuelle) – auntiee |
---|
Last month, in part 21, you were told to save what you have as "PlaylistMaker.glade", but, in the code, it was referred to as: "playlistmaker.glade". I’m sure you noticed that one has capitals and the other does not. The code will run only if you use both the call and file name with, or both without, the capitals.** | Last month, in part 21, you were told to save what you have as "PlaylistMaker.glade", but, in the code, it was referred to as: "playlistmaker.glade". I’m sure you noticed that one has capitals and the other does not. The code will run only if you use both the call and file name with, or both without, the capitals.** |
| |
//Je propose de ne pas mettre ce paragraphe en VF : nous n'avions pas d'erreur de nom de fichier dans la VF !// | //Je propose de ne pas mettre ce paragraphe en VF : nous n'avions pas d'erreur de nom de fichier dans la VF !// On le supprime de notre version carrément, alors ? |
| |
**To start off on the right foot, you need to have the playlistmaker.glade and playlistmaker.py from last month. If you don't, jump over to the last issue and get the goodies. Before we get to the code, let's take a look at what a playlist file is. There are multiple versions of play lists, and they all have different extensions. The one we will be creating will be a *.m3u type playlist. In its simplest form, it's just a text file that starts with “#EXTM3U”, and then has an entry for each song file you want to play - including the full path. There's also an extension that can be added before each entry that includes the length of the song, the album name the song comes from, the track number, and the song name. We'll bypass the extension for now and just concentrate on the basic version. | **To start off on the right foot, you need to have the playlistmaker.glade and playlistmaker.py from last month. If you don't, jump over to the last issue and get the goodies. Before we get to the code, let's take a look at what a playlist file is. There are multiple versions of play lists, and they all have different extensions. The one we will be creating will be a *.m3u type playlist. In its simplest form, it's just a text file that starts with “#EXTM3U”, and then has an entry for each song file you want to play - including the full path. There's also an extension that can be added before each entry that includes the length of the song, the album name the song comes from, the track number, and the song name. We'll bypass the extension for now and just concentrate on the basic version. |
Adult Contemporary/Chris Rea/Collection/11 - Looking For The Summer.mp3** | Adult Contemporary/Chris Rea/Collection/11 - Looking For The Summer.mp3** |
| |
Pour commencer du bon pied, vous avez besoin d'avoir les fichiers playlistmaker.glade et playlistmaker.py du mois dernier. Si ce n'est pas le cas, sautez sur le numéro précédent pour les récupérer. Avant de passer au code, nous allons jeter un oeil à ce qu'est un fichier de liste de lecture. Il y a plusieurs versions des listes de lecture, qui ont toutes des extensions différentes. Le fichier que nous allons créer sera de type *.m3u. Dans sa forme la plus simple, c'est juste un fichier texte qui commence par « #EXTM3U " et qui contient une entrée pour chaque fichier audio que vous voulez écouter - avec le chemin d'accès complet. Il y a aussi une extension qui peut être ajoutée avant chaque entrée contenant la longueur de la chanson, le nom de l'album d'où vient la chanson, le numéro de piste et le nom du morceau. Nous allons ignorer l'extension pour l'instant et se concentrer uniquement sur la version de base. | Pour bien commencer, vous devez avoir les fichiers playlistmaker.glade et playlistmaker.py du mois dernier. Si ce n'est pas le cas, sautez sur le numéro précédent pour les récupérer. Avant de passer au code, nous allons jeter un œil à ce qu'est un fichier de liste de lecture. Il y a plusieurs versions des listes de lecture, qui ont toutes des extensions différentes. Le fichier que nous allons créer sera de type *.m3u. Dans sa forme la plus simple, c'est juste un fichier texte qui commence par « #EXTM3U " et qui contient une entrée pour chaque fichier audio que vous voulez écouter - avec le chemin d'accès complet. Il y a aussi une extension qui peut être ajoutée avant chaque entrée contenant la longueur de la chanson, le nom de l'album d'où vient la chanson, le numéro de piste et le nom du morceau. Nous allons ignorer l'extension pour l'instant et se concentrer uniquement sur la version de base. |
| |
Voici un exemple d'un fichier de liste de lecture M3U. | Voici un exemple d'un fichier de liste de lecture M3U. |
Maintenant, nous devons créer une routine de gestion d'événement pour chacun des événements que nous avons mis en place. Notez que on_FenetrePrincipale_destroy et on_boBtnQuitter_clicked sont déjà faits pour nous, il n'en reste donc que dix autres à écrire (voir en haut à droite). Écrivons juste des ébauches pour l'instant. | Maintenant, nous devons créer une routine de gestion d'événement pour chacun des événements que nous avons mis en place. Notez que on_FenetrePrincipale_destroy et on_boBtnQuitter_clicked sont déjà faits pour nous, il n'en reste donc que dix autres à écrire (voir en haut à droite). Écrivons juste des ébauches pour l'instant. |
| |
Nous modifierons ces ébauches de routines dans quelques minutes. Pour l'instant, cela devrait nous permettre de démarrer l'application, et nous pourrons tester les choses au fur et à mesure que nous avançons. Nous devons quand même ajouter une ligne supplémentaire à la routine <nowiki>__init__</nowiki> avant que nous puissions démarrer l'application. Après la ligne self.wTree, ajouter : | Nous modifierons ces ébauches de routines dans quelques minutes. Pour l'instant, cela devrait nous permettre de démarrer l'application ; nous pourrons tester les choses au fur et à mesure que nous avançons. Nous devons quand même ajouter une ligne supplémentaire à la routine <nowiki>__init__</nowiki> avant de pouvoir démarrer l'application. Après la ligne self.wTree, ajouter : |
| |
self.DicoEvenements() | self.DicoEvenements() |
gtk.MessageDialog(parent,flags,MessageType,Buttons,message)** | gtk.MessageDialog(parent,flags,MessageType,Buttons,message)** |
| |
Maintenant, vous pouvez exécuter l'application, voir la fenêtre, puis cliquez sur le bouton Quitter de la barre pour quitter l'application correctement. Enregistrez le code sous le nom "CreateurListeDeLecture-1a.py" et essayez-le. Souvenez-vous qu'il faut l'enregistrer dans le même dossier que le fichier glade nous avons créé la dernière fois, ou bien copier le fichier glade dans le dossier dans lequel vous avez enregistré ce code. | Maintenant, vous pouvez exécuter l'application, voir la fenêtre, puis cliquer sur le bouton Quitter de la barre d'outils pour quitter l'application correctement. Enregistrez le code sous le nom « CreateurListeDeLecture-1a.py » et essayez-le. Souvenez-vous qu'il faut l'enregistrer dans le même dossier que le fichier glade nous avons créé la dernière fois ou bien copier le fichier glade dans le dossier dans lequel vous avez enregistré ce code. |
| |
Nous avons également besoin de définir quelques variables pour une utilisation future. Ajoutez ceci après l'appel à DicoEvenements() dans la fonction <nowiki>__init__</nowiki>. | Nous avons également besoin de définir quelques variables pour une utilisation future. Ajoutez ceci après l'appel à DicoEvenements() dans la fonction <nowiki>__init__</nowiki>. |
self.NombreDeLignes = 0 | self.NombreDeLignes = 0 |
| |
Maintenant, nous allons créer une fonction qui nous permet d'afficher une boîte de dialogue à chaque fois que nous avons besoin de donner des informations à nos utilisateurs. Il existe un ensemble de routines toutes faites que nous allons utiliser, mais nous allons faire une routine à nous pour nous faciliter les choses. C'est la routine gtk.MessageDialog, et la syntaxe est la suivante... | Maintenant, nous allons créer une fonction qui nous permet d'afficher une boîte de dialogue à chaque fois que nous avons besoin de donner des informations au utilisateur. Il existe un ensemble de routines toutes faites que nous allons utiliser, mais nous allons faire une routine à nous pour nous faciliter les choses. C'est la routine gtk.MessageDialog et la syntaxe est la suivante : |
| |
gtk.MessageDialog (parent, drapeaux, MessageType, boutons, message) | gtk.MessageDialog (parent, drapeaux, MessageType, boutons, message) |
GTK_BUTTONS_OK_CANCEL - OK and Cancel Buttons** | GTK_BUTTONS_OK_CANCEL - OK and Cancel Buttons** |
| |
Une discussion est nécessaire avant d'aller trop loin. Le type de message peut être une des suivants... | Une discussion est nécessaire avant d'aller trop loin. Le type de message peut être l'un des suivants : |
| |
GTK_MESSAGE_INFO - message d'information | GTK_MESSAGE_INFO - message d'information |
GTK_MESSAGE_ERROR - message d'erreur fatale | GTK_MESSAGE_ERROR - message d'erreur fatale |
| |
Et les types de boutons sont... | Et les types de boutons sont : |
| |
GTK_BUTTONS_NONE - aucun bouton | GTK_BUTTONS_NONE - aucun bouton |
However, if you want to display a message box to the user more than once or twice, that's a LOT of typing. The general rule of thumb is that if you write a series of lines-of-code more than once or twice, it's usually better to create a function and then call that. Think of it this way: If we want to display a message dialog to the user, say ten times in your application, that's 10 X 3 (or 30) lines of code. By making a function to do this for us (using the example I just presented), we would have 10 + 3 (or 13) lines of code to write. The more we call a dialog, the less code we actually have to type, and the more readable our code is. Our function (top right) will allow us to call any of the four message dialog types with just one routine using different parameters.** | However, if you want to display a message box to the user more than once or twice, that's a LOT of typing. The general rule of thumb is that if you write a series of lines-of-code more than once or twice, it's usually better to create a function and then call that. Think of it this way: If we want to display a message dialog to the user, say ten times in your application, that's 10 X 3 (or 30) lines of code. By making a function to do this for us (using the example I just presented), we would have 10 + 3 (or 13) lines of code to write. The more we call a dialog, the less code we actually have to type, and the more readable our code is. Our function (top right) will allow us to call any of the four message dialog types with just one routine using different parameters.** |
| |
Normalement, vous devez utiliser le code suivant, ou du code similaire, pour créer la boîte de dialogue, de l'afficher, attendre une réponse, puis le détruire. | Normalement, vous utiliseriez le code suivant, ou du code similaire, pour créer la boîte de dialogue, l'afficher, attendre une réponse, puis le détruire. |
| |
dlg = gtk.MessageDialog (None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Ceci est un message de test ...") | dlg = gtk.MessageDialog (None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Ceci est un message de test ...") |
dlg.destroy () | dlg.destroy () |
| |
Toutefois, si vous voulez afficher une boîte de message à l'utilisateur plus d'une ou deux fois, c'est beaucoup de dactylographie. La règle générale est que si vous écrivez une série de lignes de code plus d'une ou deux fois, il est généralement préférable de créer une fonction puis de l'appeler. Pensez-y de cette manière : si nous voulons afficher un message de dialogue à l'utilisateur par exemple dix fois dans votre application, cela représente 10 x 3 (soit 30) lignes de code. En faisant une fonction pour faire cela pour nous (en utilisant l'exemple que je viens de présenter), nous aurions 10 + 3 (soit 13) lignes de code à écrire. Plus nous appelons une boîte de dialogue, moins cela fait de code à taper, et plus lisible est notre code. Notre fonction (en haut à droite) nous permettra d'appeler l'un des quatre types de message de dialogue avec juste une routine en utilisant différents paramètres. | Toutefois, si vous voulez afficher une boîte de message à l'utilisateur plus d'une ou deux fois, c'est beaucoup de dactylographie. La règle générale est que si vous écrivez une série de lignes de code plus d'une ou deux fois, il est généralement préférable de créer une fonction puis de l'appeler. Pensez-y de cette manière : si nous voulons afficher un message de dialogue pour l'utilisateur, disons dix fois dans l'application, cela représente 10 x 3 (soit 30) lignes de code. En faisant une fonction pour faire cela pour nous (en utilisant l'exemple que je viens de présenter), nous aurions 10 + 3 (soit 13) lignes de code à écrire. Plus nous appelons une boîte de dialogue, moins cela fait de code à taper, et plus lisible est notre code. Notre fonction (en haut à droite) nous permettra d'appeler l'un des quatre types de message de dialogue avec une seule routine en utilisant différents paramètres. |
| |
**This is a very simple function that we would then call like this... | **This is a very simple function that we would then call like this... |
print "NO was clicked"** | print "NO was clicked"** |
| |
C'est une fonction très simple que nous pourrons ensuite appeler de cette façon... | C'est une fonction très simple que nous pourrons ensuite appeler comme suit : |
| |
self.MessageBox("info", "Le bouton QUITTER a été cliqué") | self.MessageBox("info", "Le bouton QUITTER a été cliqué") |
| |
Notez que si nous choisissons d'utiliser le type de dialogue MESSAGE_QUESTION, il y a deux réponses possibles qui seront retournées par la fenêtre de dialogue - un « oui » ou un « non ». Quelle que soit le bouton cliqué par l'utilisateur, nous allons recevoir les informations de retour dans notre code. Pour utiliser la boîte de dialogue de question, l'appel ressemblera à ça ... | Notez que si nous choisissons d'utiliser le type de dialogue MESSAGE_QUESTION, il y a deux réponses possibles qui seront retournées par la fenêtre de dialogue - un « oui » ou un « non ». Quel que soit le bouton cliqué par l'utilisateur, nous allons recevoir les informations de retour dans notre code. Pour utiliser la boîte de dialogue de question, l'appel ressemblera à ceci : |
| |
reponse = self.MessageBox(« question », « Êtes-vous sûr de vouloir faire cela maintenant ? ") | reponse = self.MessageBox(« question », « Êtes-vous sûr de vouloir faire cela maintenant ? ») |
| |
if reponse == gtk.RESPONSE_YES: | if reponse == gtk.RESPONSE_YES: |
| |
print "Clic sur oui" | print "clic sur oui" |
| |
elif reponse == gtk.RESPONSE_NO: | elif reponse == gtk.RESPONSE_NO: |
Next, let's set up the function that displays the “about” dialog when we click the About toolbar button. Again, there is a built-in routine to do this provided by the GTK library. Put this after the MessageBox function. Here's the code, below right.** | Next, let's set up the function that displays the “about” dialog when we click the About toolbar button. Again, there is a built-in routine to do this provided by the GTK library. Put this after the MessageBox function. Here's the code, below right.** |
| |
| Vous voyez comment vous pouvez vérifier la valeur du bouton cliqué. Alors maintenant, remplacez l'appel à « pass » dans chacune de nos routines de gestion d'événement par ce que vous voyez ci-dessous à droite. |
| |
| Nous n'allons pas le garder comme ça, mais cela vous donne une indication visuelle que les boutons fonctionnent comme nous le voulons. Enregistrez maintenant le code sous « CréateurListeDeLecture-1b.py » et testez votre programme. Maintenant nous allons créer une fonction pour définir nos références de widgets. Cette routine va être appelée une seule fois, mais elle rendra notre code beaucoup plus maniable et lisible. En fait, nous voulons créer des variables locales qui font référence à des widgets dans la fenêtre glade - afin que nous puissions faire des appels à eux chaque fois que (et si jamais) nous en avons besoin. Mettez cette fonction (en haut à droite) en dessous de la fonction DicoEvenements. |
| |
| Remarquez qu'il y a une chose qui n'est pas référencée dans notre routine. Il s'agit du widget treeview. Nous allons créer cette référence lorsque nous créerons l'arborescence elle-même. Notez également la dernière ligne de notre routine. Pour utiliser la barre d'état, il faut s'y référer par son id de contexte. Nous allons utiliser cela plus loin. |
| |
| Ensuite, nous allons mettre en place la fonction qui affiche le dialogue « à propos » quand on clique sur le bouton À propos de la barre d'outils. Encore une fois, ceci est une routine intégrée fournie par la bibliothèque GTK. Placez ceci après la fonction MessageBox. Voici le code, en bas à droite. |
| |
**Save your code and then give it a try. You should see a pop-up box, centered in our application, that displays everything we have set. There are more attributes that you can set for the about box (which can be found at http://www.pygtk.org/docs/pygtk/class-gtkaboutdialog.html), but these are what I would consider a minimum set. | **Save your code and then give it a try. You should see a pop-up box, centered in our application, that displays everything we have set. There are more attributes that you can set for the about box (which can be found at http://www.pygtk.org/docs/pygtk/class-gtkaboutdialog.html), but these are what I would consider a minimum set. |
Before we go on, we need to discuss exactly what will happen from here. The general idea is that the user will click on the "Add" toolbar button, we'll pop up a file dialog box to allow them to add files to the playlist, and then display the file information into our treeview widget. From there, they can add more files, delete single file entries, delete all file entries, move a file entry up, down, or to the top or down to the bottom of the treeview. Eventually, they'll set the path that the file will be saved to, provide a filename with a "m3u" extension, and click the save file button. While this seems simple enough, there's a lot that happens behind the scenes. The magic all happens in the treeview widget, so let's discuss that. This will get pretty deep, so you might want to read carefully, since an understanding of this will keep you from making mistakes later on.** | Before we go on, we need to discuss exactly what will happen from here. The general idea is that the user will click on the "Add" toolbar button, we'll pop up a file dialog box to allow them to add files to the playlist, and then display the file information into our treeview widget. From there, they can add more files, delete single file entries, delete all file entries, move a file entry up, down, or to the top or down to the bottom of the treeview. Eventually, they'll set the path that the file will be saved to, provide a filename with a "m3u" extension, and click the save file button. While this seems simple enough, there's a lot that happens behind the scenes. The magic all happens in the treeview widget, so let's discuss that. This will get pretty deep, so you might want to read carefully, since an understanding of this will keep you from making mistakes later on.** |
| |
| Sauvegardez votre code, puis faites un essai. Vous devriez voir une fenêtre pop-up, centrée dans notre application, qui affiche ce que nous avons prévu. Il y a plusieurs attributs que vous pouvez définir pour la boîte à propos (qui peuvent être trouvés sur http://www.pygtk.org/docs/pygtk/class-gtkaboutdialog.html), mais ceux-ci sont ceux que je considère être un ensemble minimal. |
| |
| Avant de poursuivre, nous devons discuter de ce qui se produira à partir d'ici. L'idée générale est que l'utilisateur clique sur le bouton « Ajouter » de la barre d'outils, nous afficherons alors une boîte de dialogue de fichier pour lui permettre d'ajouter des fichiers à la liste de lecture, puis nous afficherons les informations du fichier dans notre widget treeview. De là, il peut ajouter d'autres fichiers, supprimer un fichier unique, supprimer tous les fichiers, déplacer un fichier vers le haut ou le bas, ou bien tout en haut ou tout en bas de l'arborescence. Enfin, il va définir le chemin où le fichier sera enregistré, fournir un nom de fichier avec une extension « m3u », puis cliquer sur le bouton Sauvegarder. Bien que cela semble assez simple, il se passe beaucoup de choses en coulisses. La magie se produit dans le widget treeview, nous allons donc en discuter. Cela ira assez loin, alors lisez attentivement, car il faut le comprendre pour éviter de commettre des erreurs plus tard. |
| |
**A treeview can be something as simple as a columnar list of data like a spreadsheet or database representation, or it could be more complex like a file-folder listing with parents and children, where the folder would be the parent and the files in that folder would be the children, or something even more complex. For this project, we'll use the first example, a columnar list. In the list, there will be three columns. One is for the name of the music file, one is for the extension of the file (mp3, ogg, wav, etc) and the final column is for the path. Combining this into a string (path, filename, extension) gives us the entry into the playlist we will be writing. You could, of course, add more columns as you wish, but for now, we'll deal with just three. | **A treeview can be something as simple as a columnar list of data like a spreadsheet or database representation, or it could be more complex like a file-folder listing with parents and children, where the folder would be the parent and the files in that folder would be the children, or something even more complex. For this project, we'll use the first example, a columnar list. In the list, there will be three columns. One is for the name of the music file, one is for the extension of the file (mp3, ogg, wav, etc) and the final column is for the path. Combining this into a string (path, filename, extension) gives us the entry into the playlist we will be writing. You could, of course, add more columns as you wish, but for now, we'll deal with just three. |
• Fill in the data.** | • Fill in the data.** |
| |
| Une arborescence peut être quelque chose d'aussi simple qu'une liste à colonnes de données, comme dans une feuille de calcul ou une base de données, ou bien elle peut être plus complexe, comme une liste de fichiers/dossiers avec des parents et enfants, où le dossier serait le parent et les fichiers de ce dossier seraient les enfants, ou quelque chose d'encore plus complexe. Pour ce projet, nous allons utiliser le premier exemple, une liste à colonnes. Dans la liste, il y aura trois colonnes. Une pour le nom du fichier de musique, une pour l'extension du fichier (mp3, ogg, wav, etc.) et la dernière colonne pour le chemin d'accès. En combinant tout ça dans une chaîne (chemin d'accès, nom de fichier, extension) on obtient l'entrée que nous allons écrire dans la liste de lecture. Vous pourriez bien sûr ajouter d'autres colonnes si vous le souhaitez, mais pour l'instant nous allons nous contenter de trois. |
| |
| Une arborescence est simplement un conteneur visuel de stockage qui détient et affiche un modèle. Le modèle est le véritable « dispositif » qui contient et manipule nos données. Il existe deux modèles prédéfinis qui sont utilisés avec un treeview, mais vous pouvez certainement créer le vôtre. Cela étant dit, pour 98 % de votre travail, l'un des deux modèles prédéfinis fera ce dont vous avez besoin. Les deux types sont GTKListStore et GTKTreeStore. Comme leur nom l'indique, le modèle ListStore est habituellement utilisé pour les listes, le TreeStore est utilisé pour les arbres. Pour notre application, nous allons utiliser un GTKListStore. |
| Les étapes de base sont les suivantes : |
| |
| • Créer une référence au widget TreeView. |
| • Ajouter les colonnes. |
| • Définir le type de moteur de rendu à utiliser. |
| • Créer le ListStore. |
| • Définir l'attribut de modèle dans l'arborescence de notre modèle. |
| • Remplir les données. |
| |
**The third step is to set up the type of renderer the column will use to display the data. This is simply a routine that is used to draw the data into the tree model. There are many different cell renderers that come with GTK, but most of the ones that you would normally use include GtkCellRenderText and GtkCellRendererToggle. | **The third step is to set up the type of renderer the column will use to display the data. This is simply a routine that is used to draw the data into the tree model. There are many different cell renderers that come with GTK, but most of the ones that you would normally use include GtkCellRenderText and GtkCellRendererToggle. |
Next we call a routine (next page, top right), which we'll create in just a moment, for each column we want. Then we define our GTKListStore with three text fields, and finally set the model attribute of our TreeView widget to our GTKListStore. Let's create the AddPlaylistColumn function next. Put it after the SetupTreeview function.** | Next we call a routine (next page, top right), which we'll create in just a moment, for each column we want. Then we define our GTKListStore with three text fields, and finally set the model attribute of our TreeView widget to our GTKListStore. Let's create the AddPlaylistColumn function next. Put it after the SetupTreeview function.** |
| |
| La troisième étape consiste à mettre en place le type de moteur de rendu que la colonne utilisera pour afficher les données. C'est tout simplement une routine qui est utilisée pour tracer les données dans le modèle de l'arbre. GTK fournit de nombreux moteurs de rendu de cellules différents, mais normalement vous utiliserez le plus souvent GtkCellRenderText et GtkCellRendererToggle. |
| |
| Nous allons donc créer une fonction (ci-dessus) qui met en place notre widget TreeView. Nous allons l'appeler SetupTreeview. Nous allons d'abord définir quelques variables pour nos colonnes, définir la variable de référence du TreeView proprement dit, ajouter les colonnes, mettre en place le ListStore, et définir le modèle. Voici le code pour la fonction. Placez-le après la fonction ReferencesWidget. |
| |
| Les variables cNomFic, cTypeFic et cCheminFic définissent les numéros de colonne. Les variables sNomFic, sTypeFic et sCheminFic contiennent les noms de colonnes de notre vue. La septième ligne définit la variable de référence du widget treeview tel qu'il figure dans notre fichier glade. |
| |
| Ensuite nous appelons une routine (page suivante, en haut à droite), que nous allons créer dans un instant, pour chaque colonne que nous voulons. Puis, nous définissons notre GTKListStore avec trois champs de texte et, enfin, nous utilisons ce GTKListStore comme attribut de modèle de notre widget TreeView. Nous allons ensuite créer la fonction AjouterColonne. Placez-la après la fonction SetupTreeview. |
| |
**Each column is created with this function. We pass in the title of the column (what's displayed on the top line of each column) and a columnID. In this case, the variables we set up earlier (sFName and cFname) will be passed here. We then create a column in our TreeView widget giving the title, what kind of cell renderer it will be using, and, finally, the id of the column. We then set the column to be resizable, set the sort id, and finally append the column into the TreeView. | **Each column is created with this function. We pass in the title of the column (what's displayed on the top line of each column) and a columnID. In this case, the variables we set up earlier (sFName and cFname) will be passed here. We then create a column in our TreeView widget giving the title, what kind of cell renderer it will be using, and, finally, the id of the column. We then set the column to be resizable, set the sort id, and finally append the column into the TreeView. |
Save and run your program, and you will see that we now have three columns with headers in our TreeView widget.** | Save and run your program, and you will see that we now have three columns with headers in our TreeView widget.** |
| |
| Chaque colonne est créée avec cette fonction. Nous lui passons le titre de la colonne (ce qui est affiché sur la première ligne de chaque colonne) et un idColonne. Dans ce cas, nous utilisons les variables que nous avons créées plus tôt (sNomFic et cNomFic). Nous créons ensuite une colonne dans notre widget TreeView donnant le titre, le type de rendu de cellule et enfin l'id de la colonne. Nous indiquons ensuite que la colonne est redimensionnable, nous définissons l'id de tri et ajoutons enfin la colonne dans le TreeView. |
| |
| Ajoutez ces deux fonctions à votre code. J'ai choisi de les mettre tout de suite après la fonction ReferencesWidget, mais vous pouvez les mettre n'importe où dans la classe CreateurListeDeLecture. Ajoutez la ligne suivante après l'appel à ReferencesWidget() dans la fonction <nowiki>__init__</nowiki> pour appeler la fonction. |
| |
| self.SetupTreeview () |
| |
| Enregistrez et exécutez votre programme et vous verrez que nous avons maintenant trois colonnes avec en-têtes dans notre widget TreeView. |
| |
**There are so many things left to do. We have to have a way to get the music filenames from the user and put them into the TreeView as rows of data. We have to create our Delete, ClearAll, movement functions, save routine, and file path routines, plus a few "pretty" things that will make our application look more professional. Let's start with the Add routine. After all, that's the first button on our toolbar. | **There are so many things left to do. We have to have a way to get the music filenames from the user and put them into the TreeView as rows of data. We have to create our Delete, ClearAll, movement functions, save routine, and file path routines, plus a few "pretty" things that will make our application look more professional. Let's start with the Add routine. After all, that's the first button on our toolbar. |
def ShowDialog(self,which,CurrentPath):** | def ShowDialog(self,which,CurrentPath):** |
| |
| Il reste tellement de choses à faire. Nous devons avoir un moyen d'obtenir les noms de fichiers de musique de l'utilisateur et un moyen de les mettre dans le TreeView sous forme de lignes de données. Nous devons créer nos fonctions Supprimer, Effacer tout, les fonctions de déplacement, la routine de sauvegarde et les routines de chemins de fichiers, plus quelques « jolies » choses qui donneront à notre application un aspect plus professionnel. Commençons par la routine Ajouter. Après tout, c'est le premier bouton sur notre barre d'outils. |
| Lorsque l'utilisateur clique sur le bouton Ajouter, nous voulons faire apparaître une fenêtre de dialogue « standard » d'ouverture de fichier, qui permet des sélections multiples. Une fois que l'utilisateur a fait son choix, nous voulons ensuite prendre ces données et les ajouter dans l'arborescence, comme je l'ai indiqué ci-dessus. Ainsi, la première chose logique à faire est de travailler sur la boîte de dialogue Fichier. Encore une fois, GTK nous fournit un moyen d'appeler une boîte de dialogue « standard » de fichiers. Nous pourrions coder ça en dur simplement avec des lignes de code dans le gestionnaire d'événements on_boBtnAjouter_clicked, mais nous allons faire une classe distincte pour le gérer. Tant que nous y sommes, nous pouvons faire en sorte que cette classe gère non seulement un dialogue Ouvrir un fichier, mais aussi un dialogue Sélectionner un dossier. Comme auparavant avec la fonction MessageBox, vous pouvez l'extraire dans un fichier qui contient toutes sortes de routines réutilisables pour un usage ultérieur. |
| |
| Nous allons commencer par définir une nouvelle classe appelée DialogueFichier qui a une seule fonction appelée AfficheDialogue. Cette fonction prendra deux paramètres, l'un appelé « type » (un '0' ou un '1'), qui précise si nous créons un dialogue d'ouverture de fichier ou de sélection de dossier, et l'autre, qui est le chemin à utiliser pour la vue par défaut de la boîte de dialogue appelée CheminCourant. Créez cette classe juste avant notre code principal à la fin du fichier source. |
| |
| class DialogueFichier: |
| |
| def AfficheDialogue(self,type,CheminCourant): |
| |
**The first part of our code should be an IF statement | **The first part of our code should be an IF statement |
As you can see, the title is "Select files to add...", the parent is set to None. We are requesting a File Open type dialog (action), and we want a Cancel and an Open button, both using "stock" type icons. We are also setting the return codes of gtk.RESPONSE_CANCEL and gtk.RESPONSE_OK for when the user makes their selections. The call for our Folder Chooser under the Else clause is similar.** | As you can see, the title is "Select files to add...", the parent is set to None. We are requesting a File Open type dialog (action), and we want a Cancel and an Open button, both using "stock" type icons. We are also setting the return codes of gtk.RESPONSE_CANCEL and gtk.RESPONSE_OK for when the user makes their selections. The call for our Folder Chooser under the Else clause is similar.** |
| |
| La première partie de notre code doit être une instruction IF |
| |
| if type == 0: # choix de fichier |
| ... |
| else: # choix de dossier |
| ... |
| |
| Avant d'aller plus loin, nous allons voir la façon dont la boîte de dialogue de fichier/dossier est effectivement appelée et utilisée. La syntaxe de la boîte de dialogue se présente comme suit : |
| |
| gtk.FileChooserDialog(titre,parent,action,boutons,backend) |
| |
| et retourne un objet fenêtre de dialogue. Notre première ligne (dans le cas où type vaut 0) sera la ligne ci-dessous. |
| |
| Comme vous pouvez le voir, le titre est « Choisir les fichiers a ajouter... », le parent est défini sur none (aucun). Nous demandons une fenêtre de type ouverture de fichier (action) et nous voulons des boutons Annuler et Ouvrir, les deux utilisant des icônes de type « stock ». Nous réglons également les codes de retour de gtk.RESPONSE_CANCEL et gtk.RESPONSE_OK lorsque l'utilisateur fait ses choix. L'appel au sélecteur de dossier dans la clause else est similaire. |
| |
**Basically, the only thing that changed between the two definitions are the title (shown above right) and the action type. So our code for the class should now be the code shown middle right. | **Basically, the only thing that changed between the two definitions are the title (shown above right) and the action type. So our code for the class should now be the code shown middle right. |
These set the default response to be the OK button, and then to turn on the multiple select feature so the user can select (you guessed it) multiple files to add. If we didn't set this, the dialog would only allow one file to be selected at a time, since set_select_multiple is set to False by default. Our next lines are setting the current path, and then displaying the dialog itself. Before we type in the code, let me explain why we want to deal with the current path. Every time you pop up a file dialog box, and you DON'T set a path, the default is to the folder where our application resides. So, let's say that the music files that the user would be looking for are in /media/music_files/, and are then broken down by genre, and further by artist, and further by album. Let's further assume that the user has installed our application in /home/user2/playlistmaker. Each time we pop up the dialog, the starting folder would be /home/user2/playlistmaker. Quickly, the user would become frustrated by this, wanting the last folder he was in to be the starting folder next time. Make sense? OK. So, bottom right are our next lines of code.** | These set the default response to be the OK button, and then to turn on the multiple select feature so the user can select (you guessed it) multiple files to add. If we didn't set this, the dialog would only allow one file to be selected at a time, since set_select_multiple is set to False by default. Our next lines are setting the current path, and then displaying the dialog itself. Before we type in the code, let me explain why we want to deal with the current path. Every time you pop up a file dialog box, and you DON'T set a path, the default is to the folder where our application resides. So, let's say that the music files that the user would be looking for are in /media/music_files/, and are then broken down by genre, and further by artist, and further by album. Let's further assume that the user has installed our application in /home/user2/playlistmaker. Each time we pop up the dialog, the starting folder would be /home/user2/playlistmaker. Quickly, the user would become frustrated by this, wanting the last folder he was in to be the starting folder next time. Make sense? OK. So, bottom right are our next lines of code.** |
| |
| Fondamentalement, les seules choses qui ont changé entre les deux définitions sont le titre (ci-dessus à droite) et le type d'action. Donc le code de la classe devrait maintenant être le code affiché au milieu à droite. |
| |
| Nous définissons la réponse par défaut à la touche OK, puis activons la fonctionnalité de sélection multiple pour que l'utilisateur puisse sélectionner (vous l'aurez deviné) plusieurs fichiers à ajouter. Si nous n'avions pas indiqué cela, la boîte de dialogue permettrait seulement de sélectionner un fichier à la fois, car set_select_multiple est réglé sur faux par défaut. Nos lignes suivantes règlent le chemin actuel, puis affichent la boîte de dialogue elle-même. Avant de taper le code, je vais vous expliquer pourquoi nous devons nous occuper du chemin courant. À chaque fois que vous faites apparaître une boîte de dialogue de fichier et que vous ne définissez pas un chemin, la valeur par défaut est le dossier où réside notre application. Ainsi, si les fichiers de musique que l'utilisateur utilise sont dans /media/musique/ ils sont ensuite triés par genre puis par artiste, et puis après par album. Supposons également que l'utilisateur a installé notre application dans /home/user2/createurListeDeLecture. Chaque fois que nous faisons apparaître le dialogue, le dossier de départ serait /home/user2/createurListeDeLecture. Rapidement, l'utilisateur devrait se sentir frustré par cela, préférant retrouver le dernier dossier dans lequel il était lorsqu'il démarre la prochaine fois. Vous comprenez ? Bien. Voici donc en bas à droite les lignes de code suivantes. |
| |
**Here we check the responses sent back. If the user clicked the 'Open' button which sends back a gtk.RESPONSE_OK, we get the name or names of the files the user selected, set the current path to the folder we are in, destroy the dialog, and then return the data back to the calling routine. If, on the other hand, the user clicked on the 'Cancel' button, we simply destroy the dialog. I put the print statement in there just to show you that the button press worked. You can leave it or take it out. Notice that when we return from the Open button part of the routine, we are returning two sets of values. 'fileselection' is a list of the files selected by the user, as well as the CurrentPath. | **Here we check the responses sent back. If the user clicked the 'Open' button which sends back a gtk.RESPONSE_OK, we get the name or names of the files the user selected, set the current path to the folder we are in, destroy the dialog, and then return the data back to the calling routine. If, on the other hand, the user clicked on the 'Cancel' button, we simply destroy the dialog. I put the print statement in there just to show you that the button press worked. You can leave it or take it out. Notice that when we return from the Open button part of the routine, we are returning two sets of values. 'fileselection' is a list of the files selected by the user, as well as the CurrentPath. |
print "Current path is %s" % self.CurrentPath** | print "Current path is %s" % self.CurrentPath** |
| |
| Ici, nous vérifions les réponses renvoyées. Si l'utilisateur a cliqué sur le bouton « Ouvrir » qui renvoie gtk.RESPONSE_OK, nous obtenons le nom ou les noms des fichiers que l'utilisateur a sélectionné, on définit le chemin d'accès courant vers le dossier où nous sommes, on détruit la boîte de dialogue, puis on renvoie les données à la routine appelante. Si, en revanche, l'utilisateur a cliqué sur le bouton « Annuler », il suffit de détruire la boîte de dialogue. Je mets l'instruction print là juste pour vous montrer que l'appui sur le bouton a fonctionné. Vous pouvez la laisser ou la retirer. Notez que lorsque nous sortons de la partie concernant le bouton Ouvrir dans cette routine, nous renvoyons deux ensembles de valeurs : selectionFichiers qui est une liste des fichiers sélectionnés par l'utilisateur, ainsi que le CheminCourant. |
| |
| Afin que la routine fasse quelque chose, ajoutez la ligne suivante dans la routine on_boBtnAjouter_clicked : |
| |
| fd = DialogueFichier () |
| |
| fichiersChoisis,self.CheminCourant = fd.AfficheDialogue(0,self.CheminCourant) |
| |
| Ici on récupère les deux valeurs de retour qui sont renvoyées depuis le return. Pour le moment, ajoutez le code ci-dessous pour voir à quoi les informations retournées ressemblent : |
| |
| for f in fichiersChoisis: |
| |
| print "Choix utilisateur : %s" % f |
| |
| print "Chemin courant : %s" % self.CheminCourant |
| |
**When you run the program, click on the 'Add' button. You'll see the file dialog. Now move to somewhere where you have some files and select them. You can hold down the [ctrl] key and click on multiple files to select them individually, or the [shift] key to select multiple contiguous files. Click on the 'Open' button, and look at the response in your terminal window. Please note that if you click on the 'Cancel' button right now, you'll get an error message. That's because the above code assumes that there are no files selected. Don't worry about that right now - we'll handle that in a little bit. I just wanted to let you see what comes back if the 'Open' button is pressed. One thing we should do is add a filter to our file-open dialog. Since we expect the user to normally select music files, we should (1) give the option to display only music files, and (2) give the option to show all files just-in-case. We do this by using the filefilter attributes of the dialog. Here's the code for that which should go in the which == 0 section right after the dialog set line. | **When you run the program, click on the 'Add' button. You'll see the file dialog. Now move to somewhere where you have some files and select them. You can hold down the [ctrl] key and click on multiple files to select them individually, or the [shift] key to select multiple contiguous files. Click on the 'Open' button, and look at the response in your terminal window. Please note that if you click on the 'Cancel' button right now, you'll get an error message. That's because the above code assumes that there are no files selected. Don't worry about that right now - we'll handle that in a little bit. I just wanted to let you see what comes back if the 'Open' button is pressed. One thing we should do is add a filter to our file-open dialog. Since we expect the user to normally select music files, we should (1) give the option to display only music files, and (2) give the option to show all files just-in-case. We do this by using the filefilter attributes of the dialog. Here's the code for that which should go in the which == 0 section right after the dialog set line. |
dialog.add_filter(filter)** | dialog.add_filter(filter)** |
| |
| Lorsque vous exécutez le programme, cliquez sur le bouton « Ajouter ». Vous verrez la boîte de dialogue de fichier. Allez maintenant à un endroit où vous avez des fichiers et sélectionnez-les. Vous pouvez appuyer sur la touche [Ctrl] et cliquer sur plusieurs fichiers pour les sélectionner individuellement, ou sur la touche [Maj] pour sélectionner plusieurs fichiers contigus. Cliquez sur le bouton « Ouvrir », et examinez la réponse dans un terminal. Remarquez que si vous cliquez sur le bouton « Annuler » à ce moment, vous obtiendrez un message d'erreur. C'est parce que le code ci-dessus suppose qu'il n'y a pas de fichiers sélectionnés. Ne vous inquiétez pas pour l'instant, nous allons régler cela sous peu. Je voulais simplement vous permettre de voir ce qui revient si l'on appuie sur le bouton « Ouvrir ». Une chose que nous devrions faire est d'ajouter un filtre à notre fenêtre d'ouverture de fichier. Puisque nous attendons que l'utilisateur sélectionne normalement des fichiers de musique, nous devrions : 1) donner la possibilité d'afficher des fichiers de musique uniquement et, 2) donner la possibilité d'afficher tous les fichiers au cas où. Nous faisons cela en utilisant les attributs FileFilter de la boîte de dialogue. Voici le code pour cela, qu'il faut placer dans la partie « type == 0 » juste après la ligne créant le dialogue. |
| |
| filtre = gtk.FileFilter() |
| filtre.set_name("Fichiers musicaux") |
| filtre.add_pattern("*.mp3") |
| filtre.add_pattern("*.ogg") |
| filtre.add_pattern("*.wav") |
| dialogue.add_filter(filtre) |
| filtre = gtk.FileFilter() |
| filtre.set_name("Tous les fichiers") |
| filtre.add_pattern("*") |
| dialogue.add_filter(filtre) |
| |
**We are setting up two "groups", one for music files (filter.set_name("Music Files")), and the other for all files. We use a pattern to define the types of files we want. I have defined three patterns, but you can add or delete any that you wish. I put the music filter first, since that's what we will assume the user is going to be mainly concerned with. So the steps are... | **We are setting up two "groups", one for music files (filter.set_name("Music Files")), and the other for all files. We use a pattern to define the types of files we want. I have defined three patterns, but you can add or delete any that you wish. I put the music filter first, since that's what we will assume the user is going to be mainly concerned with. So the steps are... |
so our routine now looks like the code shown on the next page.** | so our routine now looks like the code shown on the next page.** |
| |
| Nous mettons en place deux « groupes », l'un pour les fichiers de musique (filtre.set_name("Fichiers musicaux")), et l'autre pour tous les fichiers. Nous utilisons un motif pour définir les types de fichiers que nous voulons. J'ai défini trois motifs, mais vous pouvez ajouter ou supprimer tous ceux que vous souhaitez. Je mets le filtre pour la musique en premier, puisque c'est ce qui intéresse principalement l'utilisateur. Ainsi, les étapes sont : |
| |
| • Définir une variable de filtre. |
| • Régler le nom. |
| • Ajouter un motif. |
| • Ajouter le filtre à la boîte de dialogue. |
| |
| Vous pouvez avoir autant ou aussi peu de filtres que vous le souhaitez. Notez également qu'une fois que vous avez ajouté le filtre à la boîte de dialogue, vous pouvez réutiliser la variable de filtre. |
| |
| Retournez dans la routine on_boBtnAjouter_clicked, commentez les dernières lignes que nous avons ajoutées et remplacez-les par cette seule ligne. |
| |
| self.AjouterFichiers(fichiersChoisis) |
| |
| Ainsi notre routine ressemble maintenant au code affiché sur la page suivante. |
| |
**So, when we get the response back from file dialog, we will send the list containing the selected files to this routine. Once here, we set up a counter variable (how many files we are adding), then parse the list. Remember that each entry contains the fully qualified filename with path and extension. We'll want to split the filename into path, filename, and extension. First we get the very last 'period' from the filename and assume that is the beginning of the extension and assign its position in the string to extStart. Next we find the very last '/' in the filename to determine the beginning of the filename. Then we break up the string into extension, filename and file path. We then stuff these values into a list named 'data' and append this into our playlist ListStore. We increment the counter since we have done all the work. Finally we increment the variable RowCount which holds the total number of rows in our ListStore, and then we print a message to the status bar. | **So, when we get the response back from file dialog, we will send the list containing the selected files to this routine. Once here, we set up a counter variable (how many files we are adding), then parse the list. Remember that each entry contains the fully qualified filename with path and extension. We'll want to split the filename into path, filename, and extension. First we get the very last 'period' from the filename and assume that is the beginning of the extension and assign its position in the string to extStart. Next we find the very last '/' in the filename to determine the beginning of the filename. Then we break up the string into extension, filename and file path. We then stuff these values into a list named 'data' and append this into our playlist ListStore. We increment the counter since we have done all the work. Finally we increment the variable RowCount which holds the total number of rows in our ListStore, and then we print a message to the status bar. |
Next time, we'll finalize our application, filling in the missing routines, etc.** | Next time, we'll finalize our application, filling in the missing routines, etc.** |
| |
| Ainsi, lorsque nous aurons la réponse au retour de la fenêtre de sélection de fichiers, nous enverrons la liste contenant les fichiers sélectionnés à cette routine. Une fois ici, nous créons une variable de compteur (le nombre de fichiers que nous ajoutons), puis analysons la liste. Rappelez-vous que chaque entrée contient le nom de fichier complet avec le chemin et l'extension. Nous allons devoir fractionner le nom du fichier en chemin, nom de fichier et extension. Nous récupérons d'abord le tout dernier « . » dans le nom de fichier et supposons que c'est le début de l'extension, et nous affectons sa position dans la chaîne à debutExt. Nous trouvons ensuite le tout dernier « / » dans le nom du fichier pour déterminer le début du nom de fichier. Puis, nous découpons la chaîne en extension, nom de fichier et chemin du fichier. Nous plaçons ensuite ces valeurs dans une liste nommée « data » et ajoutons ceci dans listeLecture. Nous incrémentons le compteur puisque nous avons fait tout le travail. Enfin on incrémente la variable NombreDeLignes qui contient le nombre total de lignes dans listeLecture et nous affichons un message dans la barre d'état. |
| |
| Maintenant vous pouvez lancer l'application et voir les données dans l'arborescence. |
| |
| Comme toujours, le code complet peut être trouvé à http://pastebin.com/wTCcGDSW. |
| |
| La prochaine fois, nous allons finaliser notre application, en remplissant les routines manquantes, etc. |
| |
====== CODE PAGE 7 ====== | ====== CODE PAGE 7 ====== |
| |
def ReferencesWidgets(self): | def ReferencesWidgets(self): |
self.txtFilename = self.wTree.get_widget("txtNomFicher") | self.txtNomFicher = self.wTree.get_widget("txtNomFicher") |
self.txtPath = self.wTree.get_widget("txtChemin") | self.txtChemin = self.wTree.get_widget("txtChemin") |
self.boBtnAjouter = self.wTree.get_widget("boBtnAjouter") | self.boBtnAjouter = self.wTree.get_widget("boBtnAjouter") |
self.boBtnSupprimer = self.wTree.get_widget("boBtnSupprimer") | self.boBtnSupprimer = self.wTree.get_widget("boBtnSupprimer") |
apropos.destroy() | apropos.destroy() |
| |
Maintenant, commentez (ou retirez simplement) l'appel à MessageBox dans la routine on_boBtnAPropos_clicked, et remplacez-le par un appel à la fonction AfficherAPropos. Cela devrait ressembler à cela. | Maintenant, commentez (ou retirez simplement) l'appel à MessageBox dans la routine on_boBtnAPropos_clicked, et remplacez-le par un appel à la fonction AfficherAPropos. Cela devrait ressembler à : |
| |
def on_boBtnAPropos_clicked(self,widget): | def on_boBtnAPropos_clicked(self,widget): |
self.AjouterColonne(self.sTypeFic,self.cTypeFic) | self.AjouterColonne(self.sTypeFic,self.cTypeFic) |
self.AjouterColonne(self.sCheminFic,self.cCheminFic) | self.AjouterColonne(self.sCheminFic,self.cCheminFic) |
self.playList = gtk.ListStore(str,str,str) | self.listeLecture = gtk.ListStore(str,str,str) |
self.treeview.set_model(self.playList) | self.treeview.set_model(self.listeLecture) |
self.treeview.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) | self.treeview.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) |
| |
====== CODE PAGE 13 (milieu) ====== | ====== CODE PAGE 13 (milieu) ====== |
| |
class FileDialog: | class DialogueFichier: |
def ShowDialog(self,which,CheminCourant): | def AfficheDialogue(self,type,CheminCourant): |
if which == 0: # choix de fichiers | if type == 0: # choix de fichiers |
#gtk.FileChooserDialog(titre,parent,action,boutons,backend) | #gtk.FileChooserDialog(titre,parent,action,boutons,backend) |
dialog = gtk.FileChooserDialog("Choisir les fichiers a ajouter...",None, | dialog = gtk.FileChooserDialog("Choisir les fichiers a ajouter...",None, |
| |
| |
Les deux lignes suivantes seront (en dehors de l'instruction if/else)... | Les deux lignes suivantes seront (en dehors de l'instruction if/else) : |
| |
dialog.set_default_response(gtk.RESPONSE_OK) | dialog.set_default_response(gtk.RESPONSE_OK) |
| |
if reponse == gtk.RESPONSE_OK: | if reponse == gtk.RESPONSE_OK: |
fileselection = dialog.get_filenames() | selectionFichiers = dialog.get_filenames() |
CheminCourant = dialog.get_current_folder() | CheminCourant = dialog.get_current_folder() |
dialog.destroy() | dialog.destroy() |
return (fileselection,CheminCourant) | return (selectionFichiers,CheminCourant) |
elif reponse == gtk.RESPONSE_CANCEL: | elif reponse == gtk.RESPONSE_CANCEL: |
print 'Annulation, aucun fichier choisi' | print 'Annulation, aucun fichier choisi' |
| |
def on_boBtnAjouter_clicked(self,widget): | def on_boBtnAjouter_clicked(self,widget): |
fd = FileDialog() | fd = DialogueFichier() |
fichiersChoisis,self.CheminCourant = fd.ShowDialog(0,self.CheminCourant) | fichiersChoisis,self.CheminCourant = fd.AfficheDialogue(0,self.CheminCourant) |
self.AjouterFichiers(fichiersChoisis) | self.AjouterFichiers(fichiersChoisis) |
| |
cheminFic = f[:debutnomFic] | cheminFic = f[:debutnomFic] |
data = [nomFic,extension,cheminFic] | data = [nomFic,extension,cheminFic] |
self.playList.append(data) | self.listeLecture.append(data) |
compteur += 1 | compteur += 1 |
self.NombreDeLignes += compteur | self.NombreDeLignes += compteur |
self.sbar.push(self.context_id,"%s fichiers ajoutes sur un total de %d" % (compteur,self.NombreDeLignes)) | self.sbar.push(self.context_id,"%s fichiers ajoutes sur un total de %d" % (compteur,self.NombreDeLignes)) |
| |