ScolaSync  4.0
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
chooseInSticks.py
Aller à la documentation de ce fichier.
1 # -*- coding: utf-8 -*-
2 # $Id: chooseInSticks.py 47 2011-06-13 10:20:14Z georgesk $
3 
4 licenceEn="""
5  file chooseInSticks.py
6  this file is part of the project scolasync
7 
8  Copyright (C) 2010 Georges Khaznadar <georgesk@ofset.org>
9 
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version3 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program. If not, see <http://www.gnu.org/licenses/>.
22 """
23 
24 python3safe=True
25 
26 from PyQt4.QtCore import *
27 from PyQt4.QtGui import *
28 import os.path
29 
30 import Ui_chooseInSticks
31 
32 ##
33 #
34 # Un dialogue pour choisir un ensemble de fichiers à copier depuis une clé USB.
35 #
37  ##
38  #
39  # Le constructeur
40  # @param parent un mainWindow, qui est censé contenir des données
41  # telles que parent.workdir, ...
42  # @param title1 le titre du dialogue
43  # @param title2 le titre pour la série de fichiers/modèles
44  # @param okPrompt le texte du bouton OK
45  #
46  def __init__(self,parent = None, title1="", title2="", okPrompt="OK"):
47  QDialog.__init__(self,parent)
48  self.mainWindow=parent
49  self._ui=Ui_chooseInSticks.Ui_Dialog()
50  self._ui.setupUi(self)
51  ## mise en place des titres personnalisés
52  self.setWindowTitle(title1)
53  self._ui.groupBox.setTitle(title2)
54  ## mise en place du bouton personnalisé
55  okButton=self._ui.buttonBox.button(QDialogButtonBox.Ok)
56  self._ui.buttonBox.removeButton(okButton)
57  self.okButton=QPushButton(okPrompt)
58  self._ui.buttonBox.addButton(self.okButton,
59  QDialogButtonBox.AcceptRole)
60  ## création de la structure de liste pour les fichiers
61  self._fileListModel=QStandardItemModel()
62  self._fileListProxyModel = QSortFilterProxyModel()
63  self._fileListProxyModel.setSourceModel(self._fileListModel)
64  self._ui.listView.setModel(self._fileListProxyModel)
65  self._fileListProxyModel.setDynamicSortFilter(True)
66  ## création de la structure de liste pour les noms de baladeurs
67  self._storListModel=QStandardItemModel()
68  self._storListProxyModel = QSortFilterProxyModel()
69  self._storListProxyModel.setSourceModel(self._storListModel)
70  self._ui.listChoixCle.setModel(self._storListProxyModel)
71  self._storListProxyModel.setDynamicSortFilter(True)
72  ## peuplement de la zone des noms de baladeurs
74  self.listStorages()
75  ##
76  self._ui.minusButton.setEnabled(False)
77  self._ui.travailEdit.setText(self.mainWindow.workdir)
78  QObject.connect(self._ui.plusButton, SIGNAL("clicked()"), self.plus)
79  QObject.connect(self._ui.chooseButton, SIGNAL("clicked()"), self.choose)
80  QObject.connect(self._ui.chooseButton_dir, SIGNAL("clicked()"), self.choose_dir)
81  QObject.connect(self.okButton, SIGNAL("clicked()"), self.checkValues)
82  QObject.connect(self._ui.minusButton, SIGNAL("clicked()"), self.minus)
83  QObject.connect(self._ui.listView, SIGNAL("clicked(QModelIndex)"), self.activate)
84  QObject.connect(self._ui.travailEdit, SIGNAL("editingFinished()"), self.changeWd)
85  self.ok=False
86 
87  ##
88  #
89  # fonction de rappel liée au bouton de validation, vérifie s'il y a bien
90  # au moins un fichier ou un répertoire sélectionné
91  #
92  def checkValues(self):
93  self.ok=self._ui.listView.model().rowCount()>0
94 
95  ##
96  #
97  # Met en place la liste des noms de baladeurs connectés en tenant compte
98  # du nom de répertoire de travail et d'un baladeur éventuellement
99  # sélectionné dans la fenêtre principale
100  #
101  def listStorages(self):
102  sel=self.mainWindow.ui.tableView.selectedIndexes()
103  for d in qApp.diskData:
104  o=d.ownerByDb()
105  mountPath=d.ensureMounted()
106  item=QStandardItem(o)
107  # on cherche à voir si la clé est déjà sélectionnée
108  for modelIndex in sel:
109  if o == "%s" %modelIndex.data(Qt.DisplayRole).toString():
110  break
111  self._storListModel.appendRow(item)
112  self.ownedUsbDictionary[o]=mountPath
113  self._storListProxyModel.sort(0)
114  self.checkWorkDirs()
115 
116  ##
117  #
118  # met à jour la possibilité de sélectionner les baladeurs dans la liste
119  # selon qu'ils ont ou pas un répertoire de travail, puis sélectionne
120  # si possible un baladeur, si aucun ne l'était avant.
121  #
122  def checkWorkDirs(self):
123  firstSelectable=None
124  okSelected=None
125  # on récupère la sélection courante à travers le proxy
126  selection=self._ui.listChoixCle.selectionModel().selection()
127  selection = self._storListProxyModel.mapSelectionToSource(selection)
128  selectedRows=map(lambda x: x.row(), self._ui.listChoixCle.selectedIndexes())
129  itemList=self._storListModel.findItems ("*",Qt.MatchWildcard)
130  itemList.sort(key=lambda i: i.data(Qt.DisplayRole).toString())
131  # parcours des items de la liste par ordre alphabétique
132  # pour élire celui qui sera sélectionné initialement
133  for item in itemList:
134  index=self._storListModel.indexFromItem(item)
135  o="%s" %item.data(Qt.DisplayRole).toString()
136  testDir=os.path.join(self.ownedUsbDictionary[o],self.mainWindow.workdir)
137  if os.path.isdir(testDir):
138  # si l'item concerne un disque qui contient le répertoire de
139  # travail, on le rend sélectionnable
140  item.setSelectable(True)
141  item.setEnabled(True)
142  # et si c'est le tout premier, on s'en souvient.
143  if firstSelectable == None:
144  firstSelectable=index
145  # on vérifie s'il était déjà dans la sélection
146  if index.row() in selectedRows:
147  okSelected=index
148  else:
149  item.setSelectable(False)
150  item.setEnabled(False)
151  if okSelected == None and firstSelectable != None:
152  selection=QItemSelection(firstSelectable,firstSelectable)
153  selection=self._storListProxyModel.mapSelectionFromSource(selection)
154  self._ui.listChoixCle.selectionModel().select(selection, QItemSelectionModel.Select);
155 
156  ##
157  #
158  # @return le répertoire à partir duquel on peut commencer à faire
159  # un choix de fichier ou de sous-répertoire. Il dépend du baladeur
160  # sélectionné s'il y en a un et du nom du répertoire de travail.
161  # Si on n'arrive pas à déterminer ce répertoire, renvoie None
162  #
163  def baseDir(self):
164  mp=self.selectedDiskMountPoint()
165  if mp:
166  return os.path.join(mp,self.mainWindow.workdir)
167  else:
168  return None
169 
170  ##
171  #
172  # @return le point de montage du support sélectionné s'il y en a un
173  #
175  o=self.selectedDiskOwner()
176  if o==None:
177  return None
178  else:
179  return self.ownedUsbDictionary[o]
180 
181  ##
182  #
183  # @return le nom du propriétaire du disque sélectionné s'il y en a un,
184  # sinon None.
185  #
186  def selectedDiskOwner(self):
187  selection=self._ui.listChoixCle.selectionModel().selection()
188  if len(selection)==0:
189  return None
190  selection = self._storListProxyModel.mapSelectionToSource(selection)
191  return "%s" %selection.indexes()[0].data(Qt.DisplayRole).toString()
192 
193  ##
194  #
195  # changement du répertoire de travail
196  #
197  def changeWd(self):
198  newDir=self._ui.travailEdit.text()
199  self.mainWindow.changeWd(newDir)
200  self.checkWorkDirs()
201 
202  ##
203  #
204  # Facilite le choix de motifs de fichiers en recherchant dans
205  # les clés USB, modifie l'éditeur de ligne de texte et place le
206  # fichier choisi dans la liste
207  # @param kind type d'élément à choisir : "file" pour un fichier,
208  # "dir" pour un répertoire
209  #
210  def choose(self, kind="file"):
211  if kind == "file":
212  func=QFileDialog.getOpenFileNames
213  msg=QApplication.translate("Dialog",
214  "Choissez un fichier (ou plus)",
215  encoding=QApplication.UnicodeUTF8)
216  else:
217  func=QFileDialog.getExistingDirectory
218  msg=QApplication.translate("Dialog",
219  "Choissez un répertoire",
220  encoding=QApplication.UnicodeUTF8)
221  cd=self.baseDir()
222  if cd!=None:
223  f = func (None, msg, cd)
224  if f and len(f)>0:
225  if isinstance(f, str):
226  theList=[f]
227  else:
228  theList=f
229  for f in theList:
230  path=f.replace(self.selectedDiskMountPoint()+"/", "")
231  self._ui.lineEdit.setText(path)
232  self.plus()
233  else:
234  titre=QApplication.translate("Dialog",
235  "Aucune clé modèle sélectionnée",
236  encoding=QApplication.UnicodeUTF8)
237  msg=QApplication.translate("Dialog",
238  "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),
239  encoding=QApplication.UnicodeUTF8)
240  msgBox=QMessageBox.warning(None, titre, msg)
241 
242  ##
243  #
244  # Facilite le choix de motifs de répertoires en recherchant dans
245  # les clés USB, modifie l'éditeur de ligne de texte et place le
246  # répertoire choisi dans la liste
247  #
248  def choose_dir(self):
249  self.choose(kind="dir")
250 
251  ##
252  #
253  # Fonction de rappel quand un item de la liste est activé
254  # @param item désignation de l'item activé
255  #
256  def activate(self, item):
257  self._ui.minusButton.setEnabled(True)
258 
259  ##
260  #
261  # Permet de choisir et d'ajouter un nouveau fichier ou répertoire à
262  # supprimer
263  #
264  def plus(self):
265  text=self._ui.lineEdit.text()
266  if len(text)>0 :
267  self.append(text)
268 
269  ##
270  #
271  # Permet de retirer de la liste des fichiers à supprimer ceux qu'on
272  # a sélectionnés
273  #
274  def minus(self):
275  sel=self._ui.listView.selectedIndexes()
276  sel1=map(self._fileListProxyModel.mapToSource,sel)
277  rows=map(lambda x: x.row(), sel1)
278  rows.sort("descending")
279  for r in rows:
280  self._fileListModel.removeRow(r)
281  sel=self._ui.listView.selectedIndexes()
282  if len(sel)==0:
283  self._ui.minusButton.setEnabled(False)
284 
285  ##
286  #
287  # Ajoute un chemin avec ou sans jokers à la liste des chemins à supprimer
288  # @param path le chemin
289  #
290  def append(self, path):
291  f=self._fileListModel.findItems(path)
292  if len(f)==0:
293  item=QStandardItem(path)
294  self._fileListModel.appendRow(item)
295  self._fileListProxyModel.sort(0)
296  else:
297  print ("%s est déjà sélectionné" %path)
298 
299  ##
300  #
301  # renvoie la liste des chemins sélectionnés; dans le cas de chemins
302  # sans jokers (caractères * ou ?), les chemins sont protégés par des
303  # guillemets, afin qu'ils soient adaptés à un shell POSIX.
304  # @return une liste de chemins, sous forme de QStrings
305  #
306  def pathList(self):
307  itemList=self._fileListModel.findItems("*",Qt.MatchWildcard)
308  result=[x.text() for x in itemList]
309  otherText=self._ui.lineEdit.text()
310  if len(otherText) > 0 and otherText not in result :
311  result.append(otherText)
312  return result
313 
314 
315 
def checkWorkDirs
met à jour la possibilité de sélectionner les baladeurs dans la liste selon qu'ils ont ou pas un répe...
def plus
Permet de choisir et d'ajouter un nouveau fichier ou répertoire à supprimer.
def append
Ajoute un chemin avec ou sans jokers à la liste des chemins à supprimer.
_fileListModel
création de la structure de liste pour les fichiers
ownedUsbDictionary
peuplement de la zone des noms de baladeurs
def checkValues
fonction de rappel liée au bouton de validation, vérifie s'il y a bien au moins un fichier ou un répe...
def choose
Facilite le choix de motifs de fichiers en recherchant dans les clés USB, modifie l'éditeur de ligne ...
def __init__
Le constructeur.
def pathList
renvoie la liste des chemins sélectionnés; dans le cas de chemins sans jokers (caractères * ou ...
def choose_dir
Facilite le choix de motifs de répertoires en recherchant dans les clés USB, modifie l'éditeur de lig...
def activate
Fonction de rappel quand un item de la liste est activé
_storListModel
création de la structure de liste pour les noms de baladeurs
def changeWd
changement du répertoire de travail
def listStorages
Met en place la liste des noms de baladeurs connectés en tenant compte du nom de répertoire de travai...
def minus
Permet de retirer de la liste des fichiers à supprimer ceux qu'on a sélectionnés. ...
okButton
mise en place des titres personnalisés
Un dialogue pour choisir un ensemble de fichiers à copier depuis une clé USB.