eric6/Project/ProjectOthersBrowser.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2002 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a class used to display the parts of the project, that
8 don't fit the other categories.
9 """
10
11 from __future__ import unicode_literals
12
13 from PyQt5.QtCore import QModelIndex, pyqtSignal, QUrl
14 from PyQt5.QtGui import QDesktopServices
15 from PyQt5.QtWidgets import QDialog, QMenu
16
17 from E5Gui import E5MessageBox
18
19 from .ProjectBrowserModel import ProjectBrowserFileItem, \
20 ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem, \
21 ProjectBrowserOthersType
22 from .ProjectBaseBrowser import ProjectBaseBrowser
23
24 import Utilities.MimeTypes
25 import Preferences
26
27
28 class ProjectOthersBrowser(ProjectBaseBrowser):
29 """
30 A class used to display the parts of the project, that don't fit the
31 other categories.
32
33 @signal showMenu(str, QMenu) emitted when a menu is about to be shown.
34 The name of the menu and a reference to the menu are given.
35 """
36 showMenu = pyqtSignal(str, QMenu)
37
38 def __init__(self, project, parent=None):
39 """
40 Constructor
41
42 @param project reference to the project object
43 @param parent parent widget of this browser (QWidget)
44 """
45 ProjectBaseBrowser.__init__(self, project, ProjectBrowserOthersType,
46 parent)
47
48 self.selectedItemsFilter = [ProjectBrowserFileItem,
49 ProjectBrowserDirectoryItem]
50 self.specialMenuEntries = [1]
51
52 self.setWindowTitle(self.tr('Others'))
53
54 self.setWhatsThis(self.tr(
55 """<b>Project Others Browser</b>"""
56 """<p>This allows to easily see all other files and directories"""
57 """ contained in the current project. Several actions can be"""
58 """ executed via the context menu. The entry which is registered"""
59 """ in the project is shown in a different colour.</p>"""
60 ))
61
62 project.prepareRepopulateItem.connect(self._prepareRepopulateItem)
63 project.completeRepopulateItem.connect(self._completeRepopulateItem)
64
65 def _createPopupMenus(self):
66 """
67 Protected overloaded method to generate the popup menu.
68 """
69 ProjectBaseBrowser._createPopupMenus(self)
70
71 self.menu.addAction(
72 self.tr('Open in Hex Editor'), self._openHexEditor)
73 self.editPixmapAct = self.menu.addAction(
74 self.tr('Open in Icon Editor'), self._editPixmap)
75 self.menu.addSeparator()
76 self.mimeTypeAct = self.menu.addAction(
77 self.tr('Show Mime-Type'), self.__showMimeType)
78 self.menu.addSeparator()
79 self.renameFileAct = self.menu.addAction(
80 self.tr('Rename file'), self._renameFile)
81 self.menuActions.append(self.renameFileAct)
82 act = self.menu.addAction(
83 self.tr('Remove from project'), self.__removeItem)
84 self.menuActions.append(act)
85 act = self.menu.addAction(self.tr('Delete'), self.__deleteItem)
86 self.menuActions.append(act)
87 self.menu.addSeparator()
88 self.menu.addAction(
89 self.tr('Add files...'), self.project.addOthersFiles)
90 self.menu.addAction(
91 self.tr('Add directory...'), self.project.addOthersDir)
92 self.menu.addSeparator()
93 self.menu.addAction(self.tr('Refresh'), self.__refreshItem)
94 self.menu.addSeparator()
95 self.menu.addAction(
96 self.tr('Copy Path to Clipboard'), self._copyToClipboard)
97 self.menu.addSeparator()
98 self.menu.addAction(
99 self.tr('Expand all directories'), self._expandAllDirs)
100 self.menu.addAction(
101 self.tr('Collapse all directories'), self._collapseAllDirs)
102 self.menu.addSeparator()
103 self.menu.addAction(self.tr('Configure...'), self._configure)
104
105 self.backMenu = QMenu(self)
106 self.backMenu.addAction(
107 self.tr('Add files...'), self.project.addOthersFiles)
108 self.backMenu.addAction(
109 self.tr('Add directory...'), self.project.addOthersDir)
110 self.backMenu.addSeparator()
111 self.backMenu.addAction(
112 self.tr('Expand all directories'), self._expandAllDirs)
113 self.backMenu.addAction(
114 self.tr('Collapse all directories'), self._collapseAllDirs)
115 self.backMenu.addSeparator()
116 self.backMenu.addAction(self.tr('Configure...'), self._configure)
117 self.backMenu.setEnabled(False)
118
119 self.multiMenu.addSeparator()
120 act = self.multiMenu.addAction(
121 self.tr('Remove from project'), self.__removeItem)
122 self.multiMenuActions.append(act)
123 act = self.multiMenu.addAction(
124 self.tr('Delete'), self.__deleteItem)
125 self.multiMenuActions.append(act)
126 self.multiMenu.addSeparator()
127 self.multiMenu.addAction(
128 self.tr('Expand all directories'), self._expandAllDirs)
129 self.multiMenu.addAction(
130 self.tr('Collapse all directories'), self._collapseAllDirs)
131 self.multiMenu.addSeparator()
132 self.multiMenu.addAction(self.tr('Configure...'), self._configure)
133
134 self.menu.aboutToShow.connect(self.__showContextMenu)
135 self.multiMenu.aboutToShow.connect(self.__showContextMenuMulti)
136 self.backMenu.aboutToShow.connect(self.__showContextMenuBack)
137 self.mainMenu = self.menu
138
139 def _contextMenuRequested(self, coord):
140 """
141 Protected slot to show the context menu.
142
143 @param coord the position of the mouse pointer (QPoint)
144 """
145 if not self.project.isOpen():
146 return
147
148 try:
149 cnt = self.getSelectedItemsCount()
150 if cnt <= 1:
151 index = self.indexAt(coord)
152 if index.isValid():
153 self._selectSingleItem(index)
154 cnt = self.getSelectedItemsCount()
155
156 if cnt > 1:
157 self.multiMenu.popup(self.mapToGlobal(coord))
158 else:
159 index = self.indexAt(coord)
160 if cnt == 1 and index.isValid():
161 itm = self.model().item(index)
162 if isinstance(itm, ProjectBrowserFileItem):
163 self.editPixmapAct.setVisible(itm.isPixmapFile())
164 self.mimeTypeAct.setVisible(True)
165 self.menu.popup(self.mapToGlobal(coord))
166 elif isinstance(itm, ProjectBrowserDirectoryItem):
167 self.editPixmapAct.setVisible(False)
168 self.mimeTypeAct.setVisible(False)
169 self.menu.popup(self.mapToGlobal(coord))
170 else:
171 self.backMenu.popup(self.mapToGlobal(coord))
172 else:
173 self.backMenu.popup(self.mapToGlobal(coord))
174 except Exception:
175 pass
176
177 def __showContextMenu(self):
178 """
179 Private slot called by the menu aboutToShow signal.
180 """
181 self._showContextMenu(self.menu)
182
183 self.showMenu.emit("Main", self.menu)
184
185 def __showContextMenuMulti(self):
186 """
187 Private slot called by the multiMenu aboutToShow signal.
188 """
189 ProjectBaseBrowser._showContextMenuMulti(self, self.multiMenu)
190
191 self.showMenu.emit("MainMulti", self.multiMenu)
192
193 def __showContextMenuBack(self):
194 """
195 Private slot called by the backMenu aboutToShow signal.
196 """
197 ProjectBaseBrowser._showContextMenuBack(self, self.backMenu)
198
199 self.showMenu.emit("MainBack", self.backMenu)
200
201 def _showContextMenu(self, menu):
202 """
203 Protected slot called before the context menu is shown.
204
205 It enables/disables the VCS menu entries depending on the overall
206 VCS status and the file status.
207
208 @param menu Reference to the popup menu (QPopupMenu)
209 """
210 if self.project.vcs is None:
211 for act in self.menuActions:
212 act.setEnabled(True)
213 itm = self.model().item(self.currentIndex())
214 if isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \
215 isinstance(itm, ProjectBrowserDirectoryItem):
216 self.renameFileAct.setEnabled(False)
217 else:
218 self.vcsHelper.showContextMenu(menu, self.menuActions)
219
220 def _editPixmap(self):
221 """
222 Protected slot to handle the open in icon editor popup menu entry.
223 """
224 itmList = self.getSelectedItems()
225
226 for itm in itmList:
227 if isinstance(itm, ProjectBrowserFileItem):
228 if itm.isPixmapFile():
229 self.pixmapEditFile.emit(itm.fileName())
230
231 def _openHexEditor(self):
232 """
233 Protected slot to handle the open in hex editor popup menu entry.
234 """
235 itmList = self.getSelectedItems()
236
237 for itm in itmList:
238 if isinstance(itm, ProjectBrowserFileItem):
239 self.binaryFile.emit(itm.fileName())
240
241 def _openItem(self):
242 """
243 Protected slot to handle the open popup menu entry.
244 """
245 itmList = self.getSelectedItems()
246
247 for itm in itmList:
248 if isinstance(itm, ProjectBrowserFileItem):
249 if itm.isPixmapFile():
250 self.pixmapFile.emit(itm.fileName())
251 elif itm.isSvgFile():
252 self.svgFile.emit(itm.fileName())
253 else:
254 if Utilities.MimeTypes.isTextFile(itm.fileName()):
255 self.sourceFile.emit(itm.fileName())
256 else:
257 QDesktopServices.openUrl(QUrl(itm.fileName()))
258
259 def __showMimeType(self):
260 """
261 Private slot to show the mime type of the selected entry.
262 """
263 itmList = self.getSelectedItems()
264 if itmList:
265 mimetype = Utilities.MimeTypes.mimeType(itmList[0].fileName())
266 if mimetype is None:
267 E5MessageBox.warning(
268 self,
269 self.tr("Show Mime-Type"),
270 self.tr("""The mime type of the file could not be"""
271 """ determined."""))
272 elif mimetype.split("/")[0] == "text":
273 E5MessageBox.information(
274 self,
275 self.tr("Show Mime-Type"),
276 self.tr("""The file has the mime type <b>{0}</b>.""")
277 .format(mimetype))
278 else:
279 textMimeTypesList = Preferences.getUI("TextMimeTypes")
280 if mimetype in textMimeTypesList:
281 E5MessageBox.information(
282 self,
283 self.tr("Show Mime-Type"),
284 self.tr("""The file has the mime type <b>{0}</b>.""")
285 .format(mimetype))
286 else:
287 ok = E5MessageBox.yesNo(
288 self,
289 self.tr("Show Mime-Type"),
290 self.tr("""The file has the mime type <b>{0}</b>."""
291 """<br/> Shall it be added to the list of"""
292 """ text mime types?""").format(mimetype))
293 if ok:
294 textMimeTypesList.append(mimetype)
295 Preferences.setUI("TextMimeTypes", textMimeTypesList)
296
297 def __removeItem(self):
298 """
299 Private slot to remove the selected entry from the OTHERS project
300 data area.
301 """
302 itmList = self.getSelectedItems()
303
304 for itm in itmList[:]:
305 if isinstance(itm, ProjectBrowserFileItem):
306 fn = itm.fileName()
307 self.closeSourceWindow.emit(fn)
308 self.project.removeFile(fn)
309 else:
310 dn = itm.dirName()
311 self.project.removeDirectory(dn)
312
313 def __deleteItem(self):
314 """
315 Private method to delete the selected entry from the OTHERS project
316 data area.
317 """
318 itmList = self.getSelectedItems()
319
320 items = []
321 names = []
322 fullNames = []
323 dirItems = []
324 dirNames = []
325 dirFullNames = []
326 for itm in itmList:
327 if isinstance(itm, ProjectBrowserFileItem):
328 fn2 = itm.fileName()
329 fn = self.project.getRelativePath(fn2)
330 items.append(itm)
331 fullNames.append(fn2)
332 names.append(fn)
333 else:
334 dn2 = itm.dirName()
335 dn = self.project.getRelativePath(dn2)
336 dirItems.append(itm)
337 dirFullNames.append(dn2)
338 dirNames.append(dn)
339 items.extend(dirItems)
340 fullNames.extend(dirFullNames)
341 names.extend(dirNames)
342 del itmList
343 del dirFullNames
344 del dirNames
345
346 from UI.DeleteFilesConfirmationDialog import \
347 DeleteFilesConfirmationDialog
348 dlg = DeleteFilesConfirmationDialog(
349 self.parent(),
350 self.tr("Delete files/directories"),
351 self.tr(
352 "Do you really want to delete these entries from the"
353 " project?"),
354 names)
355
356 if dlg.exec_() == QDialog.Accepted:
357 for itm, fn2, fn in zip(items[:], fullNames, names):
358 if isinstance(itm, ProjectBrowserFileItem):
359 self.closeSourceWindow.emit(fn2)
360 self.project.deleteFile(fn)
361 elif isinstance(itm, ProjectBrowserDirectoryItem):
362 self.project.deleteDirectory(fn2)
363
364 def __refreshItem(self):
365 """
366 Private slot to refresh (repopulate) an item.
367 """
368 itm = self.model().item(self.currentIndex())
369 if isinstance(itm, ProjectBrowserFileItem):
370 name = itm.fileName()
371 self.project.repopulateItem(name)
372 elif isinstance(itm, ProjectBrowserDirectoryItem):
373 name = itm.dirName()
374 self._model.directoryChanged(name)
375 else:
376 name = ''
377
378 self._resizeColumns(QModelIndex())

eric ide

mercurial