14 from PyQt6.QtWidgets import QDialog, QMenu, QTreeWidget, QTreeWidgetItem |
14 from PyQt6.QtWidgets import QDialog, QMenu, QTreeWidget, QTreeWidgetItem |
15 |
15 |
16 from eric7.EricGui import EricPixmapCache |
16 from eric7.EricGui import EricPixmapCache |
17 from eric7.EricWidgets import EricMessageBox |
17 from eric7.EricWidgets import EricMessageBox |
18 from eric7.EricWidgets.EricApplication import ericApp |
18 from eric7.EricWidgets.EricApplication import ericApp |
|
19 |
|
20 from .MultiProjectProjectMeta import MultiProjectProjectMeta |
19 |
21 |
20 |
22 |
21 class MultiProjectBrowser(QTreeWidget): |
23 class MultiProjectBrowser(QTreeWidget): |
22 """ |
24 """ |
23 Class implementing the multi project browser. |
25 Class implementing the multi project browser. |
98 |
100 |
99 def __projectAdded(self, project): |
101 def __projectAdded(self, project): |
100 """ |
102 """ |
101 Private slot to handle the addition of a project to the multi project. |
103 Private slot to handle the addition of a project to the multi project. |
102 |
104 |
103 @param project reference to the project data dictionary |
105 @param project reference to the project metadata |
|
106 @type MultiProjectProjectMeta |
104 """ |
107 """ |
105 self.__addProject(project) |
108 self.__addProject(project) |
106 self.sortItems(0, Qt.SortOrder.AscendingOrder) |
109 self.sortItems(0, Qt.SortOrder.AscendingOrder) |
107 |
110 |
108 def __projectRemoved(self, project): |
111 def __projectRemoved(self, project): |
109 """ |
112 """ |
110 Private slot to handle the removal of a project from the multi project. |
113 Private slot to handle the removal of a project from the multi project. |
111 |
114 |
112 @param project reference to the project data dictionary |
115 @param project reference to the project metadata |
|
116 @type MultiProjectProjectMeta |
113 """ |
117 """ |
114 itm = self.__findProjectItem(project) |
118 itm = self.__findProjectItem(project) |
115 if itm: |
119 if itm: |
116 parent = itm.parent() |
120 parent = itm.parent() |
117 parent.removeChild(itm) |
121 parent.removeChild(itm) |
123 |
127 |
124 def __projectDataChanged(self, project): |
128 def __projectDataChanged(self, project): |
125 """ |
129 """ |
126 Private slot to handle the change of a project of the multi project. |
130 Private slot to handle the change of a project of the multi project. |
127 |
131 |
128 @param project reference to the project data dictionary |
132 @param project reference to the project metadata |
129 """ |
133 """ |
130 itm = self.__findProjectItem(project) |
134 itm = self.__findProjectItem(project) |
131 if itm: |
135 if itm: |
132 parent = itm.parent() |
136 parent = itm.parent() |
133 if parent.text(0) != project["category"]: |
137 if parent.text(0) != project.category: |
134 self.__projectRemoved(project) |
138 self.__projectRemoved(project) |
135 self.__addProject(project) |
139 self.__addProject(project) |
136 else: |
140 else: |
137 self.__setItemData(itm, project) |
141 self.__setItemData(itm, project) |
138 |
142 |
171 |
172 |
172 def __contextMenuRequested(self, coord): |
173 def __contextMenuRequested(self, coord): |
173 """ |
174 """ |
174 Private slot to show the context menu. |
175 Private slot to show the context menu. |
175 |
176 |
176 @param coord the position of the mouse pointer (QPoint) |
177 @param coord the position of the mouse pointer |
|
178 @type QPoint |
177 """ |
179 """ |
178 itm = self.itemAt(coord) |
180 itm = self.itemAt(coord) |
179 if itm is None or itm.parent() is None: |
181 if itm is None or itm.parent() is None: |
|
182 self.__clearRemovedBackAct.setEnabled( |
|
183 self.multiProject.hasRemovedProjects() |
|
184 ) |
180 self.__backMenu.popup(self.mapToGlobal(coord)) |
185 self.__backMenu.popup(self.mapToGlobal(coord)) |
181 else: |
186 else: |
|
187 self.__clearRemovedAct.setEnabled( |
|
188 self.multiProject.hasRemovedProjects() |
|
189 ) |
182 self.__menu.popup(self.mapToGlobal(coord)) |
190 self.__menu.popup(self.mapToGlobal(coord)) |
183 |
191 |
184 def __openItem(self, itm=None): |
192 def __openItem(self, itm=None): |
185 """ |
193 """ |
186 Private slot to open a project. |
194 Private slot to open a project. |
187 |
195 |
188 @param itm reference to the project item to be opened (QTreeWidgetItem) |
196 @param itm reference to the project item to be opened |
|
197 @type QTreeWidgetItem |
189 """ |
198 """ |
190 if itm is None: |
199 if itm is None: |
191 itm = self.currentItem() |
200 itm = self.currentItem() |
192 if itm is None or itm.parent() is None: |
201 if itm is None or itm.parent() is None: |
193 return |
202 return |
205 |
214 |
206 def __findCategoryItem(self, category): |
215 def __findCategoryItem(self, category): |
207 """ |
216 """ |
208 Private method to find the item for a category. |
217 Private method to find the item for a category. |
209 |
218 |
210 @param category category to search for (string) |
219 @param category category to search for |
|
220 @type str |
211 @return reference to the category item or None, if there is |
221 @return reference to the category item or None, if there is |
212 no such item (QTreeWidgetItem or None) |
222 no such item |
|
223 @rtype QTreeWidgetItem or None |
213 """ |
224 """ |
214 if category == "": |
225 if category == "": |
215 category = self.tr("Not categorized") |
226 category = self.tr("Not categorized") |
216 for index in range(self.topLevelItemCount()): |
227 for index in range(self.topLevelItemCount()): |
217 itm = self.topLevelItem(index) |
228 itm = self.topLevelItem(index) |
222 |
233 |
223 def __addProject(self, project): |
234 def __addProject(self, project): |
224 """ |
235 """ |
225 Private method to add a project to the list. |
236 Private method to add a project to the list. |
226 |
237 |
227 @param project reference to the project data dictionary |
238 @param project reference to the project metadata |
228 """ |
239 @type MultiProjectProjectMeta |
229 parent = self.__findCategoryItem(project["category"]) |
240 """ |
|
241 parent = self.__findCategoryItem(project.category) |
230 if parent is None: |
242 if parent is None: |
231 if project["category"]: |
243 if project.category: |
232 parent = QTreeWidgetItem(self, [project["category"]]) |
244 parent = QTreeWidgetItem(self, [project.category]) |
233 else: |
245 else: |
234 parent = QTreeWidgetItem(self, [self.tr("Not categorized")]) |
246 parent = QTreeWidgetItem(self, [self.tr("Not categorized")]) |
235 parent.setExpanded(True) |
247 parent.setExpanded(True) |
236 itm = QTreeWidgetItem(parent) |
248 itm = QTreeWidgetItem(parent) |
237 self.__setItemData(itm, project) |
249 self.__setItemData(itm, project) |
238 |
250 |
239 def __setItemData(self, itm, project): |
251 def __setItemData(self, itm, project): |
240 """ |
252 """ |
241 Private method to set the data of a project item. |
253 Private method to set the data of a project item. |
242 |
254 |
243 @param itm reference to the item to be set (QTreeWidgetItem) |
255 @param itm reference to the item to be set |
244 @param project reference to the project data dictionary |
256 @type QTreeWidgetItem |
245 """ |
257 @param project reference to the project metadata |
246 itm.setText(0, project["name"]) |
258 @type MultiProjectProjectMeta |
247 if project["master"]: |
259 """ |
|
260 itm.setText(0, project.name) |
|
261 if project.master: |
248 itm.setIcon(0, EricPixmapCache.getIcon("mainProject")) |
262 itm.setIcon(0, EricPixmapCache.getIcon("mainProject")) |
249 else: |
263 else: |
250 itm.setIcon(0, EricPixmapCache.getIcon("empty")) |
264 itm.setIcon(0, EricPixmapCache.getIcon("empty")) |
251 itm.setToolTip(0, project["file"]) |
265 itm.setToolTip(0, project.file) |
252 itm.setData(0, MultiProjectBrowser.ProjectFileNameRole, project["file"]) |
266 itm.setData(0, MultiProjectBrowser.ProjectFileNameRole, project.file) |
253 itm.setData(0, MultiProjectBrowser.ProjectUidRole, project["uid"]) |
267 itm.setData(0, MultiProjectBrowser.ProjectUidRole, project.uid) |
|
268 |
|
269 if project.removed: |
|
270 itm.setText(0, self.tr("{0} (removed)").format(itm.text(0))) |
|
271 font = itm.font(0) |
|
272 font.setItalic(True) |
|
273 itm.setFont(0, font) |
254 |
274 |
255 def __findProjectItem(self, project): |
275 def __findProjectItem(self, project): |
256 """ |
276 """ |
257 Private method to search a specific project item. |
277 Private method to search a specific project item. |
258 |
278 |
259 @param project reference to the project data dictionary |
279 @param project reference to the project metadata |
260 @return reference to the item (QTreeWidgetItem) or None |
280 @type MultiProjectProjectMeta |
261 """ |
281 @return reference to the item or None |
262 if project["uid"]: |
282 @rtype QTreeWidgetItem |
263 compareData = project["uid"] |
283 """ |
|
284 if project.uid: |
|
285 compareData = project.uid |
264 compareRole = MultiProjectBrowser.ProjectUidRole |
286 compareRole = MultiProjectBrowser.ProjectUidRole |
265 else: |
287 else: |
266 compareData = project["file"] |
288 compareData = project.file |
267 compareRole = MultiProjectBrowser.ProjectFileNameRole |
289 compareRole = MultiProjectBrowser.ProjectFileNameRole |
268 |
290 |
269 for topIndex in range(self.topLevelItemCount()): |
291 for topIndex in range(self.topLevelItemCount()): |
270 topItm = self.topLevelItem(topIndex) |
292 topItm = self.topLevelItem(topIndex) |
271 for childIndex in range(topItm.childCount()): |
293 for childIndex in range(topItm.childCount()): |
362 if itm is not None and itm.parent() is not None: |
384 if itm is not None and itm.parent() is not None: |
363 uid = itm.data(0, MultiProjectBrowser.ProjectUidRole) |
385 uid = itm.data(0, MultiProjectBrowser.ProjectUidRole) |
364 if uid: |
386 if uid: |
365 project = self.multiProject.getProject(uid) |
387 project = self.multiProject.getProject(uid) |
366 if project is not None: |
388 if project is not None: |
|
389 # TODO: change the dialog |
367 dlg = AddProjectDialog( |
390 dlg = AddProjectDialog( |
368 self, |
391 self, |
369 project=project, |
392 project=project, |
370 categories=self.multiProject.getCategories(), |
393 categories=self.multiProject.getCategories(), |
371 ) |
394 ) |
372 if dlg.exec() == QDialog.DialogCode.Accepted: |
395 if dlg.exec() == QDialog.DialogCode.Accepted: |
373 ( |
396 # TODO: move the metadata creation to the dialog |
374 name, |
397 project = dlg.getProjectMetadata() |
375 filename, |
|
376 isMain, |
|
377 description, |
|
378 category, |
|
379 uid, |
|
380 ) = dlg.getData() |
|
381 project = { |
|
382 "name": name, |
|
383 "file": filename, |
|
384 "master": isMain, |
|
385 "description": description, |
|
386 "category": category, |
|
387 "uid": uid, |
|
388 } |
|
389 self.multiProject.changeProjectProperties(project) |
398 self.multiProject.changeProjectProperties(project) |
390 |
399 |
391 def __addNewProject(self): |
400 def __addNewProject(self): |
392 """ |
401 """ |
393 Private method to add a new project entry. |
402 Private method to add a new project entry. |
427 self.__menu.addAction(self.tr("Properties"), self.__showProjectProperties) |
436 self.__menu.addAction(self.tr("Properties"), self.__showProjectProperties) |
428 self.__menu.addSeparator() |
437 self.__menu.addSeparator() |
429 self.__menu.addAction(self.tr("Add Project..."), self.__addNewProject) |
438 self.__menu.addAction(self.tr("Add Project..."), self.__addNewProject) |
430 self.__menu.addAction(self.tr("Copy Project..."), self.__copyProject) |
439 self.__menu.addAction(self.tr("Copy Project..."), self.__copyProject) |
431 self.__menu.addSeparator() |
440 self.__menu.addSeparator() |
|
441 self.__clearRemovedAct = self.__menu.addAction( |
|
442 self.tr("Clear Out"), self.multiProject.clearRemovedProjects |
|
443 ) |
|
444 self.__menu.addSeparator() |
432 self.__menu.addAction(self.tr("Configure..."), self.__configure) |
445 self.__menu.addAction(self.tr("Configure..."), self.__configure) |
433 |
446 |
434 self.__backMenu = QMenu(self) |
447 self.__backMenu = QMenu(self) |
435 self.__backMenu.addAction(self.tr("Add Project..."), self.__addNewProject) |
448 self.__backMenu.addAction(self.tr("Add Project..."), self.__addNewProject) |
436 self.__backMenu.addSeparator() |
449 self.__backMenu.addSeparator() |
|
450 self.__clearRemovedBackAct = self.__backMenu.addAction( |
|
451 self.tr("Clear Out"), self.multiProject.clearRemovedProjects |
|
452 ) |
|
453 self.__backMenu.addSeparator() |
437 self.__backMenu.addAction(self.tr("Configure..."), self.__configure) |
454 self.__backMenu.addAction(self.tr("Configure..."), self.__configure) |
438 |
455 |
439 def __configure(self): |
456 def __configure(self): |
440 """ |
457 """ |
441 Private method to open the configuration dialog. |
458 Private method to open the configuration dialog. |