ScolaSync 1.0
chooseInSticks.py
Aller à la documentation de ce fichier.
00001 # -*- coding: utf-8 -*-    
00002 # $Id: chooseInSticks.py 47 2011-06-13 10:20:14Z georgesk $     
00003 
00004 licenceEn="""
00005     file chooseInSticks.py
00006     this file is part of the project scolasync
00007     
00008     Copyright (C) 2010 Georges Khaznadar <georgesk@ofset.org>
00009 
00010     This program is free software: you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation, either version3 of the License, or
00013     (at your option) any later version.
00014 
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU General Public License for more details.
00019 
00020     You should have received a copy of the GNU General Public License
00021     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00022 """
00023 
00024 from PyQt4.QtCore import *
00025 from PyQt4.QtGui import *
00026 import os.path
00027 
00028 import Ui_chooseInSticks
00029 
00030 ##
00031 # 
00032 #     Un dialogue pour choisir un ensemble de fichiers à copier depuis une clé USB.
00033 #     
00034 class chooseDialog(QDialog):
00035     ##
00036     # 
00037     #         Le constructeur
00038     #         @param parent un mainWindow, qui est censé contenir des données
00039     #         telles que parent.workdir, ...
00040     #         @param title1 le titre du dialogue
00041     #         @param title2 le titre pour la série de fichiers/modèles
00042     #         @param ok le texte du bouton OK
00043     #         
00044     def __init__(self,parent = None, title1="", title2="", ok="OK"):
00045         QDialog.__init__(self,parent)
00046         self.mainWindow=parent
00047         self._ui=Ui_chooseInSticks.Ui_Dialog()
00048         self._ui.setupUi(self)
00049         ## mise en place des titres personnalisés
00050         self.setWindowTitle(title1)
00051         self._ui.groupBox.setTitle(title2)
00052         ## mise en place du bouton personnalisé
00053         okButton=self._ui.buttonBox.button(QDialogButtonBox.Ok)
00054         self._ui.buttonBox.removeButton(okButton)
00055         self._ui.buttonBox.addButton(QPushButton(ok),
00056                                      QDialogButtonBox.AcceptRole)
00057         ## création de la structure de liste pour les fichiers
00058         self._fileListModel=QStandardItemModel()
00059         self._fileListProxyModel = QSortFilterProxyModel()
00060         self._fileListProxyModel.setSourceModel(self._fileListModel)
00061         self._ui.listView.setModel(self._fileListProxyModel)
00062         self._fileListProxyModel.setDynamicSortFilter(True)
00063         ## création de la structure de liste pour les noms de baladeurs
00064         self._storListModel=QStandardItemModel()
00065         self._storListProxyModel = QSortFilterProxyModel()
00066         self._storListProxyModel.setSourceModel(self._storListModel)
00067         self._ui.listChoixCle.setModel(self._storListProxyModel)
00068         self._storListProxyModel.setDynamicSortFilter(True)
00069         ## peuplement de la zone des noms de baladeurs
00070         self.ownedUsbDictionary={}
00071         self.listStorages()
00072         ##
00073         self._ui.minusButton.setEnabled(False)
00074         self._ui.travailEdit.setText(self.mainWindow.workdir)
00075         QObject.connect(self._ui.plusButton, SIGNAL("clicked()"), self.plus)
00076         QObject.connect(self._ui.chooseButton, SIGNAL("clicked()"), self.choose)
00077         QObject.connect(self._ui.chooseButton_dir, SIGNAL("clicked()"), self.choose_dir)
00078         QObject.connect(self._ui.minusButton, SIGNAL("clicked()"), self.minus)
00079         QObject.connect(self._ui.listView, SIGNAL("clicked(QModelIndex)"), self.activate)
00080         QObject.connect(self._ui.travailEdit, SIGNAL("editingFinished()"), self.changeWd)
00081 
00082 
00083     ##
00084     # 
00085     #         Met en place la liste des noms de baladeurs connectés en tenant compte
00086     #         du nom de répertoire de travail et d'un baladeur éventuellement
00087     #         sélectionné dans la fenêtre principale
00088     #         
00089     def listStorages(self):
00090         sel=self.mainWindow.ui.tableView.selectedIndexes()
00091         for d in qApp.diskData:
00092             o=d.ownerByDb()
00093             mountPath=d.ensureMounted()
00094             item=QStandardItem(o)
00095             # on cherche à voir si la clé est déjà sélectionnée
00096             for modelIndex in sel:
00097                 if o == u"%s" %modelIndex.data(Qt.DisplayRole).toString():
00098                     break
00099             self._storListModel.appendRow(item)
00100             self.ownedUsbDictionary[o]=mountPath
00101         self._storListProxyModel.sort(0)
00102         self.checkWorkDirs()
00103 
00104     ##
00105     # 
00106     #         met à jour la possibilité de sélectionner les baladeurs dans la liste
00107     #         selon qu'ils ont ou pas un répertoire de travail, puis sélectionne
00108     #         si possible un baladeur, si aucun ne l'était avant.
00109     #         
00110     def checkWorkDirs(self):
00111         firstSelectable=None
00112         okSelected=None
00113         # on récupère la sélection courante à travers le proxy
00114         selection=self._ui.listChoixCle.selectionModel().selection()
00115         selection = self._storListProxyModel.mapSelectionToSource(selection)
00116         selectedRows=map(lambda x: x.row(), self._ui.listChoixCle.selectedIndexes())
00117         itemList=self._storListModel.findItems ("*",Qt.MatchWildcard)
00118         itemList.sort(key=lambda i: i.data(Qt.DisplayRole).toString())
00119         # parcours des items de la liste par ordre alphabétique
00120         # pour élire celui qui sera sélectionné initialement
00121         for item in itemList:
00122             index=self._storListModel.indexFromItem(item)
00123             o=u"%s" %item.data(Qt.DisplayRole).toString()
00124             testDir=os.path.join(self.ownedUsbDictionary[o],self.mainWindow.workdir)
00125             if os.path.isdir(testDir):
00126                 # si l'item concerne un disque qui contient le répertoire de
00127                 # travail, on le rend sélectionnable
00128                 item.setSelectable(True)
00129                 item.setEnabled(True)
00130                 # et si c'est le tout premier, on s'en souvient.
00131                 if firstSelectable == None:
00132                     firstSelectable=index
00133                 # on vérifie s'il était déjà dans la sélection
00134                 if index.row() in selectedRows:
00135                     okSelected=index
00136             else:
00137                 item.setSelectable(False)
00138                 item.setEnabled(False)
00139         if okSelected == None and firstSelectable != None:
00140             selection=QItemSelection(firstSelectable,firstSelectable)
00141             selection=self._storListProxyModel.mapSelectionFromSource(selection)
00142             self._ui.listChoixCle.selectionModel().select(selection, QItemSelectionModel.Select);
00143 
00144     ##
00145     # 
00146     #         @return le répertoire à partir duquel on peut commencer à faire
00147     #         un choix de fichier ou de sous-répertoire. Il dépend du baladeur
00148     #         sélectionné s'il y en a un et du nom du répertoire de travail.
00149     #         Si on n'arrive pas à déterminer ce répertoire, renvoie None
00150     #         
00151     def baseDir(self):
00152         mp=self.selectedDiskMountPoint()
00153         if mp:
00154             return os.path.join(mp,self.mainWindow.workdir)
00155         else:
00156             return None
00157 
00158     ##
00159     # 
00160     #         @return le point de montage du support sélectionné s'il y en a un
00161     #         
00162     def selectedDiskMountPoint(self):
00163         o=self.selectedDiskOwner()
00164         if o==None:
00165             return None
00166         else:
00167             return self.ownedUsbDictionary[o]
00168 
00169     ##
00170     # 
00171     #         @return le nom du propriétaire du disque sélectionné s'il y en a un,
00172     #         sinon None.
00173     #         
00174     def selectedDiskOwner(self):
00175         selection=self._ui.listChoixCle.selectionModel().selection()
00176         if len(selection)==0:
00177             return None
00178         selection = self._storListProxyModel.mapSelectionToSource(selection)
00179         return u"%s" %selection.indexes()[0].data(Qt.DisplayRole).toString()
00180                 
00181     ##
00182     # 
00183     #         changement du répertoire de travail
00184     #         
00185     def changeWd(self):
00186         newDir=u"%s" %self._ui.travailEdit.text().toUtf8()
00187         self.mainWindow.changeWd(newDir)
00188         self.checkWorkDirs()
00189 
00190     ##
00191     # 
00192     #         Facilite le choix de motifs de fichiers en recherchant dans
00193     #         les clés USB, modifie l'éditeur de ligne de texte et place le
00194     #         fichier choisi dans la liste
00195     #         @param kind type d'élément à choisir : "file" pour un fichier,
00196     #         "dir" pour un répertoire
00197     #         
00198     def choose(self, kind="file"):
00199         if kind == "file":
00200             func=QFileDialog.getOpenFileNames
00201             msg=QApplication.translate("Dialog",
00202                                        "Choissez un fichier (ou plus)",
00203                                        encoding=QApplication.UnicodeUTF8)
00204         else:
00205             func=QFileDialog.getExistingDirectory
00206             msg=QApplication.translate("Dialog",
00207                                        "Choissez un répertoire",
00208                                        encoding=QApplication.UnicodeUTF8)
00209         cd=self.baseDir()
00210         if cd!=None:
00211             f = func (None, msg, cd)
00212             if f and len(f)>0:
00213                 if type(f)==type(QStringList()):
00214                     theList=f
00215                 else:
00216                     theList=[f]
00217                 for f in theList:
00218                     path=f.remove(self.selectedDiskMountPoint()+"/")
00219                     self._ui.lineEdit.setText(path)
00220                     self.plus()
00221         else:
00222             titre=QApplication.translate("Dialog",
00223                                          "Aucune clé modèle sélectionnée",
00224                                          encoding=QApplication.UnicodeUTF8)
00225             msg=QApplication.translate("Dialog",
00226                                        "Veuillez choisir une clé modèle<br>parmi les clés connectées en cliquant<br>sur une ligne du tableau, pour<br>bénéficier de l'aide au choix de fichiers.<br><br>Cette clé doit contenir au moins<br>un répertoire « {workdir} ».".format(workdir=self.mainWindow.workdir),
00227                                        encoding=QApplication.UnicodeUTF8)
00228             msgBox=QMessageBox.warning(None, titre, msg)
00229         
00230     ##
00231     # 
00232     #         Facilite le choix de motifs de répertoires en recherchant dans
00233     #         les clés USB, modifie l'éditeur de ligne de texte et place le
00234     #         répertoire choisi dans la liste
00235     #         
00236     def choose_dir(self):
00237         self.choose(kind="dir")
00238         
00239     ##
00240     # 
00241     #         Fonction de rappel quand un item de la liste est activé
00242     #         @param item désignation de l'item activé
00243     #         
00244     def activate(self, item):
00245         self._ui.minusButton.setEnabled(True)
00246         
00247     ##
00248     # 
00249     #         Permet de choisir et d'ajouter un nouveau fichier ou répertoire à
00250     #         supprimer
00251     #         
00252     def plus(self):
00253         text=self._ui.lineEdit.text()
00254         if len(text)>0 :
00255             self.append(text)
00256         
00257     ##
00258     # 
00259     #         Permet de retirer de la liste des fichiers à supprimer ceux qu'on
00260     #         a sélectionnés
00261     #         
00262     def minus(self):
00263         sel=self._ui.listView.selectedIndexes()
00264         sel1=map(self._fileListProxyModel.mapToSource,sel)
00265         rows=map(lambda x: x.row(), sel1)
00266         rows.sort("descending")
00267         for r in rows:
00268             self._fileListModel.removeRow(r)
00269         sel=self._ui.listView.selectedIndexes()
00270         if len(sel)==0:
00271             self._ui.minusButton.setEnabled(False)
00272         
00273     ##
00274     # 
00275     #         Ajoute un chemin avec ou sans jokers à la liste des chemins à supprimer
00276     #         @param path le chemin
00277     #         
00278     def append(self, path):
00279         f=self._fileListModel.findItems(path)
00280         if len(f)==0:
00281             item=QStandardItem(path)
00282             self._fileListModel.appendRow(item)
00283             self._fileListProxyModel.sort(0)
00284         else:
00285             print path, "est déjà sélectionné"
00286 
00287     ##
00288     # 
00289     #         renvoie la liste des chemins sélectionnés; dans le cas de chemins
00290     #         sans jokers (caractères * ou ?), les chemins sont protégés par des
00291     #         guillemets, afin qu'ils soient adaptés à un shell POSIX.
00292     #         @return une liste de chemins, sous forme de QStrings
00293     #         
00294     def pathList(self):
00295         itemList=self._fileListModel.findItems("*",Qt.MatchWildcard)
00296         result=map(lambda x: x.text(), itemList)
00297         otherText=self._ui.lineEdit.text()
00298         if len(otherText) > 0 and otherText not in result :
00299             result.append(otherText)
00300         return result
00301 
00302         
00303         
00304 
 Tout Classes Espaces de nommage Fichiers Fonctions Variables