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