src/eric7/EricWidgets/EricModelToolBar.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9473
3f23dbf37dbe
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
13 13
14 14
15 class EricModelToolBar(QToolBar): 15 class EricModelToolBar(QToolBar):
16 """ 16 """
17 Class implementing a tool bar populated from a QAbstractItemModel. 17 Class implementing a tool bar populated from a QAbstractItemModel.
18 18
19 @signal activated(QModelIndex) emitted when an action has been triggered 19 @signal activated(QModelIndex) emitted when an action has been triggered
20 """ 20 """
21
21 activated = pyqtSignal(QModelIndex) 22 activated = pyqtSignal(QModelIndex)
22 23
23 def __init__(self, title=None, parent=None): 24 def __init__(self, title=None, parent=None):
24 """ 25 """
25 Constructor 26 Constructor
26 27
27 @param title title for the tool bar (string) 28 @param title title for the tool bar (string)
28 @param parent reference to the parent widget (QWidget) 29 @param parent reference to the parent widget (QWidget)
29 """ 30 """
30 if title is not None: 31 if title is not None:
31 super().__init__(title, parent) 32 super().__init__(title, parent)
32 else: 33 else:
33 super().__init__(parent) 34 super().__init__(parent)
34 35
35 self.__model = None 36 self.__model = None
36 37
37 self.__root = QModelIndex() 38 self.__root = QModelIndex()
38 self.__dragStartPosition = QPoint() 39 self.__dragStartPosition = QPoint()
39 40
40 if self.isVisible(): 41 if self.isVisible():
41 self._build() 42 self._build()
42 43
43 self.setAcceptDrops(True) 44 self.setAcceptDrops(True)
44 45
45 self._mouseButton = Qt.MouseButton.NoButton 46 self._mouseButton = Qt.MouseButton.NoButton
46 self._keyboardModifiers = Qt.KeyboardModifier.NoModifier 47 self._keyboardModifiers = Qt.KeyboardModifier.NoModifier
47 self.__dropRow = -1 48 self.__dropRow = -1
48 self.__dropIndex = None 49 self.__dropIndex = None
49 50
50 def setModel(self, model): 51 def setModel(self, model):
51 """ 52 """
52 Public method to set the model for the tool bar. 53 Public method to set the model for the tool bar.
53 54
54 @param model reference to the model (QAbstractItemModel) 55 @param model reference to the model (QAbstractItemModel)
55 """ 56 """
56 if self.__model is not None: 57 if self.__model is not None:
57 self.__model.modelReset.disconnect(self._build) 58 self.__model.modelReset.disconnect(self._build)
58 self.__model.rowsInserted[QModelIndex, int, int].disconnect( 59 self.__model.rowsInserted[QModelIndex, int, int].disconnect(self._build)
59 self._build) 60 self.__model.rowsRemoved[QModelIndex, int, int].disconnect(self._build)
60 self.__model.rowsRemoved[QModelIndex, int, int].disconnect( 61 self.__model.dataChanged.disconnect(self._build)
61 self._build) 62
62 self.__model.dataChanged.disconnect(
63 self._build)
64
65 self.__model = model 63 self.__model = model
66 64
67 if self.__model is not None: 65 if self.__model is not None:
68 self.__model.modelReset.connect(self._build) 66 self.__model.modelReset.connect(self._build)
69 self.__model.rowsInserted[QModelIndex, int, int].connect( 67 self.__model.rowsInserted[QModelIndex, int, int].connect(self._build)
70 self._build) 68 self.__model.rowsRemoved[QModelIndex, int, int].connect(self._build)
71 self.__model.rowsRemoved[QModelIndex, int, int].connect( 69 self.__model.dataChanged.connect(self._build)
72 self._build) 70
73 self.__model.dataChanged.connect(
74 self._build)
75
76 def model(self): 71 def model(self):
77 """ 72 """
78 Public method to get a reference to the model. 73 Public method to get a reference to the model.
79 74
80 @return reference to the model (QAbstractItemModel) 75 @return reference to the model (QAbstractItemModel)
81 """ 76 """
82 return self.__model 77 return self.__model
83 78
84 def setRootIndex(self, idx): 79 def setRootIndex(self, idx):
85 """ 80 """
86 Public method to set the root index. 81 Public method to set the root index.
87 82
88 @param idx index to be set as the root index (QModelIndex) 83 @param idx index to be set as the root index (QModelIndex)
89 """ 84 """
90 self.__root = idx 85 self.__root = idx
91 86
92 def rootIndex(self): 87 def rootIndex(self):
93 """ 88 """
94 Public method to get the root index. 89 Public method to get the root index.
95 90
96 @return root index (QModelIndex) 91 @return root index (QModelIndex)
97 """ 92 """
98 return self.__root 93 return self.__root
99 94
100 def _build(self): 95 def _build(self):
101 """ 96 """
102 Protected slot to build the tool bar. 97 Protected slot to build the tool bar.
103 """ 98 """
104 if self.__model is None: 99 if self.__model is None:
105 return 100 return
106 101
107 self.clear() 102 self.clear()
108 103
109 for i in range(self.__model.rowCount(self.__root)): 104 for i in range(self.__model.rowCount(self.__root)):
110 idx = self.__model.index(i, 0, self.__root) 105 idx = self.__model.index(i, 0, self.__root)
111 106
112 title = idx.data(Qt.ItemDataRole.DisplayRole) 107 title = idx.data(Qt.ItemDataRole.DisplayRole)
113 icon = idx.data(Qt.ItemDataRole.DecorationRole) 108 icon = idx.data(Qt.ItemDataRole.DecorationRole)
114 if icon == NotImplemented or icon is None: 109 if icon == NotImplemented or icon is None:
115 icon = QIcon() 110 icon = QIcon()
116 folder = self.__model.hasChildren(idx) 111 folder = self.__model.hasChildren(idx)
117 112
118 act = self.addAction(icon, title) 113 act = self.addAction(icon, title)
119 act.setData(idx) 114 act.setData(idx)
120 115
121 button = self.widgetForAction(act) 116 button = self.widgetForAction(act)
122 button.installEventFilter(self) 117 button.installEventFilter(self)
123 118
124 if folder: 119 if folder:
125 menu = self._createMenu() 120 menu = self._createMenu()
126 menu.setModel(self.__model) 121 menu.setModel(self.__model)
127 menu.setRootIndex(idx) 122 menu.setRootIndex(idx)
128 button.setMenu(menu) 123 button.setMenu(menu)
129 button.setPopupMode( 124 button.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
130 QToolButton.ToolButtonPopupMode.InstantPopup) 125 button.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
131 button.setToolButtonStyle( 126
132 Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
133
134 def index(self, action): 127 def index(self, action):
135 """ 128 """
136 Public method to get the index of an action. 129 Public method to get the index of an action.
137 130
138 @param action reference to the action to get the index for (QAction) 131 @param action reference to the action to get the index for (QAction)
139 @return index of the action (QModelIndex) 132 @return index of the action (QModelIndex)
140 """ 133 """
141 if action is None: 134 if action is None:
142 return QModelIndex() 135 return QModelIndex()
143 136
144 idx = action.data() 137 idx = action.data()
145 if idx is None: 138 if idx is None:
146 return QModelIndex() 139 return QModelIndex()
147 140
148 if not isinstance(idx, QModelIndex): 141 if not isinstance(idx, QModelIndex):
149 return QModelIndex() 142 return QModelIndex()
150 143
151 return idx 144 return idx
152 145
153 def _createMenu(self): 146 def _createMenu(self):
154 """ 147 """
155 Protected method to create the menu for a tool bar action. 148 Protected method to create the menu for a tool bar action.
156 149
157 @return menu for a tool bar action (EricModelMenu) 150 @return menu for a tool bar action (EricModelMenu)
158 """ 151 """
159 from .EricModelMenu import EricModelMenu 152 from .EricModelMenu import EricModelMenu
153
160 return EricModelMenu(self) 154 return EricModelMenu(self)
161 155
162 def eventFilter(self, obj, evt): 156 def eventFilter(self, obj, evt):
163 """ 157 """
164 Public method to handle event for other objects. 158 Public method to handle event for other objects.
165 159
166 @param obj reference to the object (QObject) 160 @param obj reference to the object (QObject)
167 @param evt reference to the event (QEvent) 161 @param evt reference to the event (QEvent)
168 @return flag indicating that the event should be filtered out (boolean) 162 @return flag indicating that the event should be filtered out (boolean)
169 """ 163 """
170 if evt.type() == QEvent.Type.MouseButtonRelease: 164 if evt.type() == QEvent.Type.MouseButtonRelease:
173 act = obj.defaultAction() 167 act = obj.defaultAction()
174 idx = self.index(act) 168 idx = self.index(act)
175 if idx.isValid(): 169 if idx.isValid():
176 self.activated[QModelIndex].emit(idx) 170 self.activated[QModelIndex].emit(idx)
177 elif ( 171 elif (
178 evt.type() == QEvent.Type.MouseButtonPress and 172 evt.type() == QEvent.Type.MouseButtonPress
179 evt.buttons() & Qt.MouseButton.LeftButton 173 and evt.buttons() & Qt.MouseButton.LeftButton
180 ): 174 ):
181 self.__dragStartPosition = self.mapFromGlobal( 175 self.__dragStartPosition = self.mapFromGlobal(
182 evt.globalPosition().toPoint()) 176 evt.globalPosition().toPoint()
183 177 )
178
184 return False 179 return False
185 180
186 def dragEnterEvent(self, evt): 181 def dragEnterEvent(self, evt):
187 """ 182 """
188 Protected method to handle drag enter events. 183 Protected method to handle drag enter events.
189 184
190 @param evt reference to the event (QDragEnterEvent) 185 @param evt reference to the event (QDragEnterEvent)
191 """ 186 """
192 if self.__model is not None: 187 if self.__model is not None:
193 mimeTypes = self.__model.mimeTypes() 188 mimeTypes = self.__model.mimeTypes()
194 for mimeType in mimeTypes: 189 for mimeType in mimeTypes:
195 if evt.mimeData().hasFormat(mimeType): 190 if evt.mimeData().hasFormat(mimeType):
196 evt.acceptProposedAction() 191 evt.acceptProposedAction()
197 192
198 super().dragEnterEvent(evt) 193 super().dragEnterEvent(evt)
199 194
200 def dropEvent(self, evt): 195 def dropEvent(self, evt):
201 """ 196 """
202 Protected method to handle drop events. 197 Protected method to handle drop events.
203 198
204 @param evt reference to the event (QDropEvent) 199 @param evt reference to the event (QDropEvent)
205 @exception RuntimeError raised to indicate an invalid model index 200 @exception RuntimeError raised to indicate an invalid model index
206 """ 201 """
207 if self.__model is not None: 202 if self.__model is not None:
208 act = self.actionAt(evt.position().toPoint()) 203 act = self.actionAt(evt.position().toPoint())
215 raise RuntimeError("invalid index") 210 raise RuntimeError("invalid index")
216 row = idx.row() 211 row = idx.row()
217 if self.__model.hasChildren(idx): 212 if self.__model.hasChildren(idx):
218 parentIndex = idx 213 parentIndex = idx
219 row = self.__model.rowCount(idx) 214 row = self.__model.rowCount(idx)
220 215
221 self.__dropRow = row 216 self.__dropRow = row
222 self.__dropIndex = parentIndex 217 self.__dropIndex = parentIndex
223 evt.acceptProposedAction() 218 evt.acceptProposedAction()
224 self.__model.dropMimeData(evt.mimeData(), evt.dropAction(), 219 self.__model.dropMimeData(
225 row, 0, parentIndex) 220 evt.mimeData(), evt.dropAction(), row, 0, parentIndex
226 221 )
222
227 super().dropEvent(evt) 223 super().dropEvent(evt)
228 224
229 def mouseMoveEvent(self, evt): 225 def mouseMoveEvent(self, evt):
230 """ 226 """
231 Protected method to handle mouse move events. 227 Protected method to handle mouse move events.
232 228
233 @param evt reference to the event (QMouseEvent) 229 @param evt reference to the event (QMouseEvent)
234 @exception RuntimeError raised to indicate an invalid model index 230 @exception RuntimeError raised to indicate an invalid model index
235 """ 231 """
236 if self.__model is None: 232 if self.__model is None:
237 super().mouseMoveEvent(evt) 233 super().mouseMoveEvent(evt)
238 return 234 return
239 235
240 if not (evt.buttons() & Qt.MouseButton.LeftButton): 236 if not (evt.buttons() & Qt.MouseButton.LeftButton):
241 super().mouseMoveEvent(evt) 237 super().mouseMoveEvent(evt)
242 return 238 return
243 239
244 manhattanLength = (evt.position().toPoint() - 240 manhattanLength = (
245 self.__dragStartPosition).manhattanLength() 241 evt.position().toPoint() - self.__dragStartPosition
242 ).manhattanLength()
246 if manhattanLength <= QApplication.startDragDistance(): 243 if manhattanLength <= QApplication.startDragDistance():
247 super().mouseMoveEvent(evt) 244 super().mouseMoveEvent(evt)
248 return 245 return
249 246
250 act = self.actionAt(self.__dragStartPosition) 247 act = self.actionAt(self.__dragStartPosition)
251 if act is None: 248 if act is None:
252 super().mouseMoveEvent(evt) 249 super().mouseMoveEvent(evt)
253 return 250 return
254 251
255 idx = self.index(act) 252 idx = self.index(act)
256 if not idx.isValid(): 253 if not idx.isValid():
257 raise RuntimeError("invalid index") 254 raise RuntimeError("invalid index")
258 255
259 drag = QDrag(self) 256 drag = QDrag(self)
260 drag.setMimeData(self.__model.mimeData([idx])) 257 drag.setMimeData(self.__model.mimeData([idx]))
261 actionRect = self.actionGeometry(act) 258 actionRect = self.actionGeometry(act)
262 drag.setPixmap(self.grab(actionRect)) 259 drag.setPixmap(self.grab(actionRect))
263 260
264 if drag.exec() == Qt.DropAction.MoveAction: 261 if drag.exec() == Qt.DropAction.MoveAction:
265 row = idx.row() 262 row = idx.row()
266 if self.__dropIndex == idx.parent() and self.__dropRow <= row: 263 if self.__dropIndex == idx.parent() and self.__dropRow <= row:
267 row += 1 264 row += 1
268 self.__model.removeRow(row, self.__root) 265 self.__model.removeRow(row, self.__root)
269 266
270 def hideEvent(self, evt): 267 def hideEvent(self, evt):
271 """ 268 """
272 Protected method to handle hide events. 269 Protected method to handle hide events.
273 270
274 @param evt reference to the hide event (QHideEvent) 271 @param evt reference to the hide event (QHideEvent)
275 """ 272 """
276 self.clear() 273 self.clear()
277 super().hideEvent(evt) 274 super().hideEvent(evt)
278 275
279 def showEvent(self, evt): 276 def showEvent(self, evt):
280 """ 277 """
281 Protected method to handle show events. 278 Protected method to handle show events.
282 279
283 @param evt reference to the hide event (QHideEvent) 280 @param evt reference to the hide event (QHideEvent)
284 """ 281 """
285 if len(self.actions()) == 0: 282 if len(self.actions()) == 0:
286 self._build() 283 self._build()
287 super().showEvent(evt) 284 super().showEvent(evt)
288 285
289 def resetFlags(self): 286 def resetFlags(self):
290 """ 287 """
291 Public method to reset the saved internal state. 288 Public method to reset the saved internal state.
292 """ 289 """
293 self._mouseButton = Qt.MouseButton.NoButton 290 self._mouseButton = Qt.MouseButton.NoButton

eric ide

mercurial