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