eric6/E5Gui/E5ToolBarDialog.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) 2008 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a toolbar configuration dialog.
8 """
9
10 from __future__ import unicode_literals
11
12 from PyQt5.QtCore import pyqtSlot, Qt
13 from PyQt5.QtGui import QColor
14 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QTreeWidgetItem, \
15 QInputDialog, QLineEdit, QListWidgetItem, QAbstractButton
16
17 from E5Gui import E5MessageBox
18
19 from .Ui_E5ToolBarDialog import Ui_E5ToolBarDialog
20
21 import UI.PixmapCache
22
23
24 class E5ToolBarItem(object):
25 """
26 Class storing data belonging to a toolbar entry of the toolbar dialog.
27 """
28 def __init__(self, toolBarId, actionIDs, default):
29 """
30 Constructor
31
32 @param toolBarId id of the toolbar object (integer)
33 @param actionIDs list of action IDs belonging to the toolbar
34 (list of integer)
35 @param default flag indicating a default toolbar (boolean)
36 """
37 self.toolBarId = toolBarId
38 self.actionIDs = actionIDs[:]
39 self.isDefault = default
40 self.title = ""
41 self.isChanged = False
42
43
44 class E5ToolBarDialog(QDialog, Ui_E5ToolBarDialog):
45 """
46 Class implementing a toolbar configuration dialog.
47 """
48 ActionIdRole = Qt.UserRole
49 WidgetActionRole = Qt.UserRole + 1
50
51 def __init__(self, toolBarManager, parent=None):
52 """
53 Constructor
54
55 @param toolBarManager reference to a toolbar manager object
56 (E5ToolBarManager)
57 @param parent reference to the parent widget (QWidget)
58 """
59 super(E5ToolBarDialog, self).__init__(parent)
60 self.setupUi(self)
61
62 self.__manager = toolBarManager
63 self.__toolbarItems = {}
64 # maps toolbar item IDs to toolbar items
65 self.__currentToolBarItem = None
66 self.__removedToolBarIDs = []
67 # remember custom toolbars to be deleted
68
69 self.__widgetActionToToolBarItemID = {}
70 # maps widget action IDs to toolbar item IDs
71 self.__toolBarItemToWidgetActionID = {}
72 # maps toolbar item IDs to widget action IDs
73
74 self.upButton.setIcon(UI.PixmapCache.getIcon("1uparrow.png"))
75 self.downButton.setIcon(UI.PixmapCache.getIcon("1downarrow.png"))
76 self.leftButton.setIcon(UI.PixmapCache.getIcon("1leftarrow.png"))
77 self.rightButton.setIcon(UI.PixmapCache.getIcon("1rightarrow.png"))
78
79 self.__restoreDefaultsButton = \
80 self.buttonBox.button(QDialogButtonBox.RestoreDefaults)
81 self.__resetButton = self.buttonBox.button(QDialogButtonBox.Reset)
82
83 self.actionsTree.header().hide()
84 self.__separatorText = self.tr("--Separator--")
85 itm = QTreeWidgetItem(self.actionsTree, [self.__separatorText])
86 self.actionsTree.setCurrentItem(itm)
87
88 for category in sorted(self.__manager.categories()):
89 categoryItem = QTreeWidgetItem(self.actionsTree, [category])
90 for action in self.__manager.categoryActions(category):
91 item = QTreeWidgetItem(categoryItem)
92 item.setText(0, action.text())
93 item.setIcon(0, action.icon())
94 item.setTextAlignment(0, Qt.AlignLeft | Qt.AlignVCenter)
95 item.setData(0, E5ToolBarDialog.ActionIdRole, int(id(action)))
96 item.setData(0, E5ToolBarDialog.WidgetActionRole, False)
97 if self.__manager.isWidgetAction(action):
98 item.setData(0, E5ToolBarDialog.WidgetActionRole, True)
99 item.setData(0, Qt.TextColorRole, QColor(Qt.blue))
100 self.__widgetActionToToolBarItemID[id(action)] = None
101 categoryItem.setExpanded(True)
102
103 for tbID, actions in list(self.__manager.toolBarsActions().items()):
104 tb = self.__manager.toolBarById(tbID)
105 default = self.__manager.isDefaultToolBar(tb)
106 tbItem = E5ToolBarItem(tbID, [], default)
107 self.__toolbarItems[id(tbItem)] = tbItem
108 self.__toolBarItemToWidgetActionID[id(tbItem)] = []
109 actionIDs = []
110 for action in actions:
111 if action is None:
112 actionIDs.append(None)
113 else:
114 aID = id(action)
115 actionIDs.append(aID)
116 if aID in self.__widgetActionToToolBarItemID:
117 self.__widgetActionToToolBarItemID[aID] = id(tbItem)
118 self.__toolBarItemToWidgetActionID[id(tbItem)]\
119 .append(aID)
120 tbItem.actionIDs = actionIDs
121 self.toolbarComboBox.addItem(tb.windowTitle(), int(id(tbItem)))
122 if default:
123 self.toolbarComboBox.setItemData(
124 self.toolbarComboBox.count() - 1,
125 QColor(Qt.darkGreen), Qt.ForegroundRole)
126 self.toolbarComboBox.model().sort(0)
127
128 self.toolbarComboBox.currentIndexChanged[int].connect(
129 self.__toolbarComboBox_currentIndexChanged)
130 self.toolbarComboBox.setCurrentIndex(0)
131
132 @pyqtSlot()
133 def on_newButton_clicked(self):
134 """
135 Private slot to create a new toolbar.
136 """
137 name, ok = QInputDialog.getText(
138 self,
139 self.tr("New Toolbar"),
140 self.tr("Toolbar Name:"),
141 QLineEdit.Normal)
142 if ok and name:
143 if self.toolbarComboBox.findText(name) != -1:
144 # toolbar with this name already exists
145 E5MessageBox.critical(
146 self,
147 self.tr("New Toolbar"),
148 self.tr(
149 """A toolbar with the name <b>{0}</b> already"""
150 """ exists.""")
151 .format(name))
152 return
153
154 tbItem = E5ToolBarItem(None, [], False)
155 tbItem.title = name
156 tbItem.isChanged = True
157 self.__toolbarItems[id(tbItem)] = tbItem
158 self.__toolBarItemToWidgetActionID[id(tbItem)] = []
159 self.toolbarComboBox.addItem(name, int(id(tbItem)))
160 self.toolbarComboBox.model().sort(0)
161 self.toolbarComboBox.setCurrentIndex(
162 self.toolbarComboBox.findText(name))
163
164 @pyqtSlot()
165 def on_removeButton_clicked(self):
166 """
167 Private slot to remove a custom toolbar.
168 """
169 name = self.toolbarComboBox.currentText()
170 res = E5MessageBox.yesNo(
171 self,
172 self.tr("Remove Toolbar"),
173 self.tr(
174 """Should the toolbar <b>{0}</b> really be removed?""")
175 .format(name))
176 if res:
177 index = self.toolbarComboBox.currentIndex()
178 tbItemID = self.toolbarComboBox.itemData(index)
179 tbItem = self.__toolbarItems[tbItemID]
180 if tbItem.toolBarId is not None and \
181 tbItem.toolBarId not in self.__removedToolBarIDs:
182 self.__removedToolBarIDs.append(tbItem.toolBarId)
183 del self.__toolbarItems[tbItemID]
184 for widgetActionID in self.__toolBarItemToWidgetActionID[tbItemID]:
185 self.__widgetActionToToolBarItemID[widgetActionID] = None
186 del self.__toolBarItemToWidgetActionID[tbItemID]
187 self.toolbarComboBox.removeItem(index)
188
189 @pyqtSlot()
190 def on_renameButton_clicked(self):
191 """
192 Private slot to rename a custom toolbar.
193 """
194 oldName = self.toolbarComboBox.currentText()
195 newName, ok = QInputDialog.getText(
196 self,
197 self.tr("Rename Toolbar"),
198 self.tr("New Toolbar Name:"),
199 QLineEdit.Normal,
200 oldName)
201 if ok and newName:
202 if oldName == newName:
203 return
204 if self.toolbarComboBox.findText(newName) != -1:
205 # toolbar with this name already exists
206 E5MessageBox.critical(
207 self,
208 self.tr("Rename Toolbar"),
209 self.tr(
210 """A toolbar with the name <b>{0}</b> already"""
211 """ exists.""")
212 .format(newName))
213 return
214 index = self.toolbarComboBox.currentIndex()
215 self.toolbarComboBox.setItemText(index, newName)
216 tbItem = \
217 self.__toolbarItems[self.toolbarComboBox.itemData(index)]
218 tbItem.title = newName
219 tbItem.isChanged = True
220
221 def __setupButtons(self):
222 """
223 Private slot to set the buttons state.
224 """
225 index = self.toolbarComboBox.currentIndex()
226 if index > -1:
227 itemID = self.toolbarComboBox.itemData(index)
228 self.__currentToolBarItem = self.__toolbarItems[itemID]
229 self.renameButton.setEnabled(
230 not self.__currentToolBarItem.isDefault)
231 self.removeButton.setEnabled(
232 not self.__currentToolBarItem.isDefault)
233 self.__restoreDefaultsButton.setEnabled(
234 self.__currentToolBarItem.isDefault)
235 self.__resetButton.setEnabled(
236 self.__currentToolBarItem.toolBarId is not None)
237
238 row = self.toolbarActionsList.currentRow()
239 self.upButton.setEnabled(row > 0)
240 self.downButton.setEnabled(row < self.toolbarActionsList.count() - 1)
241 self.leftButton.setEnabled(self.toolbarActionsList.count() > 0)
242 rightEnable = self.actionsTree.currentItem().parent() is not None or \
243 self.actionsTree.currentItem().text(0) == self.__separatorText
244 self.rightButton.setEnabled(rightEnable)
245
246 @pyqtSlot(int)
247 def __toolbarComboBox_currentIndexChanged(self, index):
248 """
249 Private slot called upon a selection of the current toolbar.
250
251 @param index index of the new current toolbar (integer)
252 """
253 itemID = self.toolbarComboBox.itemData(index)
254 self.__currentToolBarItem = self.__toolbarItems[itemID]
255 self.toolbarActionsList.clear()
256 for actionID in self.__currentToolBarItem.actionIDs:
257 item = QListWidgetItem(self.toolbarActionsList)
258 if actionID is None:
259 item.setText(self.__separatorText)
260 else:
261 action = self.__manager.actionById(actionID)
262 item.setText(action.text())
263 item.setIcon(action.icon())
264 item.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter)
265 item.setData(E5ToolBarDialog.ActionIdRole, int(id(action)))
266 item.setData(E5ToolBarDialog.WidgetActionRole, False)
267 if self.__manager.isWidgetAction(action):
268 item.setData(E5ToolBarDialog.WidgetActionRole, True)
269 item.setData(Qt.TextColorRole, QColor(Qt.blue))
270 self.toolbarActionsList.setCurrentRow(0)
271
272 self.__setupButtons()
273
274 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
275 def on_actionsTree_currentItemChanged(self, current, previous):
276 """
277 Private slot called, when the currently selected action changes.
278
279 @param current reference to the current item (QTreeWidgetItem)
280 @param previous reference to the previous current item
281 (QTreeWidgetItem)
282 """
283 self.__setupButtons()
284
285 @pyqtSlot(QListWidgetItem, QListWidgetItem)
286 def on_toolbarActionsList_currentItemChanged(self, current, previous):
287 """
288 Private slot to handle a change of the current item.
289
290 @param current reference to the current item (QListWidgetItem)
291 @param previous reference to the previous current item
292 (QListWidgetItem)
293 """
294 self.__setupButtons()
295
296 @pyqtSlot()
297 def on_upButton_clicked(self):
298 """
299 Private slot used to move an action up in the list.
300 """
301 row = self.toolbarActionsList.currentRow()
302 if row == 0:
303 # we're already at the top
304 return
305
306 actionID = self.__currentToolBarItem.actionIDs.pop(row)
307 self.__currentToolBarItem.actionIDs.insert(row - 1, actionID)
308 self.__currentToolBarItem.isChanged = True
309 itm = self.toolbarActionsList.takeItem(row)
310 self.toolbarActionsList.insertItem(row - 1, itm)
311 self.toolbarActionsList.setCurrentItem(itm)
312 self.__setupButtons()
313
314 @pyqtSlot()
315 def on_downButton_clicked(self):
316 """
317 Private slot used to move an action down in the list.
318 """
319 row = self.toolbarActionsList.currentRow()
320 if row == self.toolbarActionsList.count() - 1:
321 # we're already at the end
322 return
323
324 actionID = self.__currentToolBarItem.actionIDs.pop(row)
325 self.__currentToolBarItem.actionIDs.insert(row + 1, actionID)
326 self.__currentToolBarItem.isChanged = True
327 itm = self.toolbarActionsList.takeItem(row)
328 self.toolbarActionsList.insertItem(row + 1, itm)
329 self.toolbarActionsList.setCurrentItem(itm)
330 self.__setupButtons()
331
332 @pyqtSlot()
333 def on_leftButton_clicked(self):
334 """
335 Private slot to delete an action from the list.
336 """
337 row = self.toolbarActionsList.currentRow()
338 actionID = self.__currentToolBarItem.actionIDs.pop(row)
339 self.__currentToolBarItem.isChanged = True
340 if actionID in self.__widgetActionToToolBarItemID:
341 self.__widgetActionToToolBarItemID[actionID] = None
342 self.__toolBarItemToWidgetActionID[id(self.__currentToolBarItem)]\
343 .remove(actionID)
344 itm = self.toolbarActionsList.takeItem(row)
345 del itm
346 self.toolbarActionsList.setCurrentRow(row)
347 self.__setupButtons()
348
349 @pyqtSlot()
350 def on_rightButton_clicked(self):
351 """
352 Private slot to add an action to the list.
353 """
354 row = self.toolbarActionsList.currentRow() + 1
355
356 item = QListWidgetItem()
357 if self.actionsTree.currentItem().text(0) == self.__separatorText:
358 item.setText(self.__separatorText)
359 actionID = None
360 else:
361 actionID = self.actionsTree.currentItem()\
362 .data(0, E5ToolBarDialog.ActionIdRole)
363 action = self.__manager.actionById(actionID)
364 item.setText(action.text())
365 item.setIcon(action.icon())
366 item.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter)
367 item.setData(E5ToolBarDialog.ActionIdRole, int(id(action)))
368 item.setData(E5ToolBarDialog.WidgetActionRole, False)
369 if self.__manager.isWidgetAction(action):
370 item.setData(E5ToolBarDialog.WidgetActionRole, True)
371 item.setData(Qt.TextColorRole, QColor(Qt.blue))
372 oldTbItemID = self.__widgetActionToToolBarItemID[actionID]
373 if oldTbItemID is not None:
374 self.__toolbarItems[oldTbItemID].actionIDs.remove(actionID)
375 self.__toolbarItems[oldTbItemID].isChanged = True
376 self.__toolBarItemToWidgetActionID[oldTbItemID]\
377 .remove(actionID)
378 self.__widgetActionToToolBarItemID[actionID] = \
379 id(self.__currentToolBarItem)
380 self.__toolBarItemToWidgetActionID[
381 id(self.__currentToolBarItem)].append(actionID)
382 self.toolbarActionsList.insertItem(row, item)
383 self.__currentToolBarItem.actionIDs.insert(row, actionID)
384 self.__currentToolBarItem.isChanged = True
385 self.toolbarActionsList.setCurrentRow(row)
386 self.__setupButtons()
387
388 @pyqtSlot(QAbstractButton)
389 def on_buttonBox_clicked(self, button):
390 """
391 Private slot called, when a button of the button box was clicked.
392
393 @param button reference to the button clicked (QAbstractButton)
394 """
395 if button == self.buttonBox.button(QDialogButtonBox.Cancel):
396 self.reject()
397 elif button == self.buttonBox.button(QDialogButtonBox.Apply):
398 self.__saveToolBars()
399 self.__setupButtons()
400 elif button == self.buttonBox.button(QDialogButtonBox.Ok):
401 self.__saveToolBars()
402 self.accept()
403 elif button == self.buttonBox.button(QDialogButtonBox.Reset):
404 self.__resetCurrentToolbar()
405 self.__setupButtons()
406 elif button == self.buttonBox.button(QDialogButtonBox.RestoreDefaults):
407 self.__restoreCurrentToolbarToDefault()
408 self.__setupButtons()
409
410 def __saveToolBars(self):
411 """
412 Private method to save the configured toolbars.
413
414 @exception RuntimeError raised to indicate an invalid action
415 """
416 # step 1: remove toolbars marked for deletion
417 for tbID in self.__removedToolBarIDs:
418 tb = self.__manager.toolBarById(tbID)
419 self.__manager.deleteToolBar(tb)
420 self.__removedToolBarIDs = []
421
422 # step 2: save configured toolbars
423 for tbItem in list(self.__toolbarItems.values()):
424 if not tbItem.isChanged:
425 continue
426
427 if tbItem.toolBarId is None:
428 # new custom toolbar
429 tb = self.__manager.createToolBar(tbItem.title)
430 tbItem.toolBarId = id(tb)
431 else:
432 tb = self.__manager.toolBarById(tbItem.toolBarId)
433 if not tbItem.isDefault and tbItem.title:
434 self.__manager.renameToolBar(tb, tbItem.title)
435
436 actions = []
437 for actionID in tbItem.actionIDs:
438 if actionID is None:
439 actions.append(None)
440 else:
441 action = self.__manager.actionById(actionID)
442 if action is None:
443 raise RuntimeError(
444 "No such action, id: 0x{0:x}".format(actionID))
445 actions.append(action)
446 self.__manager.setToolBar(tb, actions)
447 tbItem.isChanged = False
448
449 def __restoreCurrentToolbar(self, actions):
450 """
451 Private methdo to restore the current toolbar to the given list of
452 actions.
453
454 @param actions list of actions to set for the current toolbar
455 (list of QAction)
456 """
457 tbItemID = id(self.__currentToolBarItem)
458 for widgetActionID in self.__toolBarItemToWidgetActionID[tbItemID]:
459 self.__widgetActionToToolBarItemID[widgetActionID] = None
460 self.__toolBarItemToWidgetActionID[tbItemID] = []
461 self.__currentToolBarItem.actionIDs = []
462
463 for action in actions:
464 if action is None:
465 self.__currentToolBarItem.actionIDs.append(None)
466 else:
467 actionID = id(action)
468 self.__currentToolBarItem.actionIDs.append(actionID)
469 if actionID in self.__widgetActionToToolBarItemID:
470 oldTbItemID = self.__widgetActionToToolBarItemID[actionID]
471 if oldTbItemID is not None:
472 self.__toolbarItems[oldTbItemID].actionIDs.remove(
473 actionID)
474 self.__toolbarItems[oldTbItemID].isChanged = True
475 self.__toolBarItemToWidgetActionID[oldTbItemID].remove(
476 actionID)
477 self.__widgetActionToToolBarItemID[actionID] = tbItemID
478 self.__toolBarItemToWidgetActionID[tbItemID].append(
479 actionID)
480 self.__toolbarComboBox_currentIndexChanged(
481 self.toolbarComboBox.currentIndex())
482
483 def __resetCurrentToolbar(self):
484 """
485 Private method to revert all changes made to the current toolbar.
486 """
487 tbID = self.__currentToolBarItem.toolBarId
488 actions = self.__manager.toolBarActions(tbID)
489 self.__restoreCurrentToolbar(actions)
490 self.__currentToolBarItem.isChanged = False
491
492 def __restoreCurrentToolbarToDefault(self):
493 """
494 Private method to set the current toolbar to its default configuration.
495 """
496 if not self.__currentToolBarItem.isDefault:
497 return
498
499 tbID = self.__currentToolBarItem.toolBarId
500 actions = self.__manager.defaultToolBarActions(tbID)
501 self.__restoreCurrentToolbar(actions)
502 self.__currentToolBarItem.isChanged = True

eric ide

mercurial