25 |
25 |
26 import UI.PixmapCache |
26 import UI.PixmapCache |
27 |
27 |
28 import Preferences |
28 import Preferences |
29 import Utilities |
29 import Utilities |
|
30 |
30 |
31 |
31 class MultiProject(QObject): |
32 class MultiProject(QObject): |
32 """ |
33 """ |
33 Class implementing the project management functionality. |
34 Class implementing the project management functionality. |
34 |
35 |
35 @signal dirty(bool) emitted when the dirty state changes |
36 @signal dirty(bool) emitted when the dirty state changes |
36 @signal newMultiProject() emitted after a new multi project was generated |
37 @signal newMultiProject() emitted after a new multi project was generated |
37 @signal multiProjectOpened() emitted after a multi project file was read |
38 @signal multiProjectOpened() emitted after a multi project file was read |
38 @signal multiProjectClosed() emitted after a multi project was closed |
39 @signal multiProjectClosed() emitted after a multi project was closed |
39 @signal multiProjectPropertiesChanged() emitted after the multi project |
40 @signal multiProjectPropertiesChanged() emitted after the multi project |
40 properties were changed |
41 properties were changed |
41 @signal showMenu(string, QMenu) emitted when a menu is about to be shown. |
42 @signal showMenu(string, QMenu) emitted when a menu is about to be shown. |
42 The name of the menu and a reference to the menu are given. |
43 The name of the menu and a reference to the menu are given. |
43 @signal projectDataChanged(project data dict) emitted after a project entry |
44 @signal projectDataChanged(project data dict) emitted after a project entry |
44 has been changed |
45 has been changed |
45 @signal projectAdded(project data dict) emitted after a project entry |
46 @signal projectAdded(project data dict) emitted after a project entry |
46 has been added |
47 has been added |
57 projectDataChanged = pyqtSignal(dict) |
58 projectDataChanged = pyqtSignal(dict) |
58 projectAdded = pyqtSignal(dict) |
59 projectAdded = pyqtSignal(dict) |
59 projectRemoved = pyqtSignal(dict) |
60 projectRemoved = pyqtSignal(dict) |
60 projectOpened = pyqtSignal(str) |
61 projectOpened = pyqtSignal(str) |
61 |
62 |
62 def __init__(self, project, parent = None, filename = None): |
63 def __init__(self, project, parent=None, filename=None): |
63 """ |
64 """ |
64 Constructor |
65 Constructor |
65 |
66 |
66 @param project reference to the project object (Project.Project) |
67 @param project reference to the project object (Project.Project) |
67 @param parent parent widget (usually the ui object) (QWidget) |
68 @param parent parent widget (usually the ui object) (QWidget) |
171 """ |
172 """ |
172 return self.pfile |
173 return self.pfile |
173 |
174 |
174 def __checkFilesExist(self): |
175 def __checkFilesExist(self): |
175 """ |
176 """ |
176 Private method to check, if the files in a list exist. |
177 Private method to check, if the files in a list exist. |
177 |
178 |
178 The project files are checked for existance in the |
179 The project files are checked for existance in the |
179 filesystem. Non existant projects are removed from the list and the |
180 filesystem. Non existant projects are removed from the list and the |
180 dirty state of the multi project is changed accordingly. |
181 dirty state of the multi project is changed accordingly. |
181 """ |
182 """ |
222 # check, if the files of the multi project still exist |
223 # check, if the files of the multi project still exist |
223 self.__checkFilesExist() |
224 self.__checkFilesExist() |
224 |
225 |
225 return True |
226 return True |
226 |
227 |
227 def __writeMultiProject(self, fn = None): |
228 def __writeMultiProject(self, fn=None): |
228 """ |
229 """ |
229 Private method to save the multi project infos to a multi project file. |
230 Private method to save the multi project infos to a multi project file. |
230 |
231 |
231 @param fn optional filename of the multi project file to be written. |
232 @param fn optional filename of the multi project file to be written. |
232 If fn is None, the filename stored in the multi project object |
233 If fn is None, the filename stored in the multi project object |
259 # insert filename into list of recently opened projects |
260 # insert filename into list of recently opened projects |
260 self.__syncRecent() |
261 self.__syncRecent() |
261 |
262 |
262 return res |
263 return res |
263 |
264 |
264 def addProject(self, startdir = None): |
265 def addProject(self, startdir=None): |
265 """ |
266 """ |
266 Public slot used to add files to the project. |
267 Public slot used to add files to the project. |
267 |
268 |
268 @param startdir start directory for the selection dialog (string) |
269 @param startdir start directory for the selection dialog (string) |
269 """ |
270 """ |
270 if startdir is None: |
271 if startdir is None: |
271 startdir = self.ppath |
272 startdir = self.ppath |
272 dlg = AddProjectDialog(self.ui, startdir = startdir) |
273 dlg = AddProjectDialog(self.ui, startdir=startdir) |
273 if dlg.exec_() == QDialog.Accepted: |
274 if dlg.exec_() == QDialog.Accepted: |
274 name, filename, isMaster, description = dlg.getData() |
275 name, filename, isMaster, description = dlg.getData() |
275 |
276 |
276 # step 1: check, if project was already added |
277 # step 1: check, if project was already added |
277 for project in self.projects: |
278 for project in self.projects: |
388 if dlg.exec_() == QDialog.Accepted: |
389 if dlg.exec_() == QDialog.Accepted: |
389 dlg.storeData() |
390 dlg.storeData() |
390 self.setDirty(True) |
391 self.setDirty(True) |
391 self.multiProjectPropertiesChanged.emit() |
392 self.multiProjectPropertiesChanged.emit() |
392 |
393 |
393 def openMultiProject(self, fn = None, openMaster = True): |
394 def openMultiProject(self, fn=None, openMaster=True): |
394 """ |
395 """ |
395 Public slot to open a multi project. |
396 Public slot to open a multi project. |
396 |
397 |
397 @param fn optional filename of the multi project file to be read (string) |
398 @param fn optional filename of the multi project file to be read (string) |
398 @param openMaster flag indicating, that the master project |
399 @param openMaster flag indicating, that the master project |
399 should be opened depending on the configuration (boolean) |
400 should be opened depending on the configuration (boolean) |
400 """ |
401 """ |
401 if not self.checkDirty(): |
402 if not self.checkDirty(): |
402 return |
403 return |
403 |
404 |
473 if QFileInfo(fn).exists(): |
474 if QFileInfo(fn).exists(): |
474 res = E5MessageBox.yesNo(self.parent(), |
475 res = E5MessageBox.yesNo(self.parent(), |
475 self.trUtf8("Save File"), |
476 self.trUtf8("Save File"), |
476 self.trUtf8("<p>The file <b>{0}</b> already exists." |
477 self.trUtf8("<p>The file <b>{0}</b> already exists." |
477 " Overwrite it?</p>").format(fileName), |
478 " Overwrite it?</p>").format(fileName), |
478 icon = E5MessageBox.Warning) |
479 icon=E5MessageBox.Warning) |
479 if not res: |
480 if not res: |
480 return False |
481 return False |
481 |
482 |
482 self.name = QFileInfo(fn).baseName() |
483 self.name = QFileInfo(fn).baseName() |
483 self.__writeMultiProject(fn) |
484 self.__writeMultiProject(fn) |
493 Public method to check the dirty status and open a message window. |
494 Public method to check the dirty status and open a message window. |
494 |
495 |
495 @return flag indicating whether this operation was successful (boolean) |
496 @return flag indicating whether this operation was successful (boolean) |
496 """ |
497 """ |
497 if self.isDirty(): |
498 if self.isDirty(): |
498 res = E5MessageBox.okToClearData(self.parent(), |
499 res = E5MessageBox.okToClearData(self.parent(), |
499 self.trUtf8("Close Multiproject"), |
500 self.trUtf8("Close Multiproject"), |
500 self.trUtf8("The current multiproject has unsaved changes."), |
501 self.trUtf8("The current multiproject has unsaved changes."), |
501 self.saveMultiProject) |
502 self.saveMultiProject) |
502 if res: |
503 if res: |
503 self.setDirty(False) |
504 self.setDirty(False) |
549 self.actGrp1 = createActionGroup(self) |
550 self.actGrp1 = createActionGroup(self) |
550 |
551 |
551 act = E5Action(self.trUtf8('New multiproject'), |
552 act = E5Action(self.trUtf8('New multiproject'), |
552 UI.PixmapCache.getIcon("multiProjectNew.png"), |
553 UI.PixmapCache.getIcon("multiProjectNew.png"), |
553 self.trUtf8('&New...'), 0, 0, |
554 self.trUtf8('&New...'), 0, 0, |
554 self.actGrp1,'multi_project_new') |
555 self.actGrp1, 'multi_project_new') |
555 act.setStatusTip(self.trUtf8('Generate a new multiproject')) |
556 act.setStatusTip(self.trUtf8('Generate a new multiproject')) |
556 act.setWhatsThis(self.trUtf8( |
557 act.setWhatsThis(self.trUtf8( |
557 """<b>New...</b>""" |
558 """<b>New...</b>""" |
558 """<p>This opens a dialog for entering the info for a""" |
559 """<p>This opens a dialog for entering the info for a""" |
559 """ new multiproject.</p>""" |
560 """ new multiproject.</p>""" |
562 self.actions.append(act) |
563 self.actions.append(act) |
563 |
564 |
564 act = E5Action(self.trUtf8('Open multiproject'), |
565 act = E5Action(self.trUtf8('Open multiproject'), |
565 UI.PixmapCache.getIcon("multiProjectOpen.png"), |
566 UI.PixmapCache.getIcon("multiProjectOpen.png"), |
566 self.trUtf8('&Open...'), 0, 0, |
567 self.trUtf8('&Open...'), 0, 0, |
567 self.actGrp1,'multi_project_open') |
568 self.actGrp1, 'multi_project_open') |
568 act.setStatusTip(self.trUtf8('Open an existing multiproject')) |
569 act.setStatusTip(self.trUtf8('Open an existing multiproject')) |
569 act.setWhatsThis(self.trUtf8( |
570 act.setWhatsThis(self.trUtf8( |
570 """<b>Open...</b>""" |
571 """<b>Open...</b>""" |
571 """<p>This opens an existing multiproject.</p>""" |
572 """<p>This opens an existing multiproject.</p>""" |
572 )) |
573 )) |
608 self.actions.append(self.saveasAct) |
609 self.actions.append(self.saveasAct) |
609 |
610 |
610 self.addProjectAct = E5Action(self.trUtf8('Add project to multiproject'), |
611 self.addProjectAct = E5Action(self.trUtf8('Add project to multiproject'), |
611 UI.PixmapCache.getIcon("fileProject.png"), |
612 UI.PixmapCache.getIcon("fileProject.png"), |
612 self.trUtf8('Add &project...'), 0, 0, |
613 self.trUtf8('Add &project...'), 0, 0, |
613 self,'multi_project_add_project') |
614 self, 'multi_project_add_project') |
614 self.addProjectAct.setStatusTip(self.trUtf8( |
615 self.addProjectAct.setStatusTip(self.trUtf8( |
615 'Add a project to the current multiproject')) |
616 'Add a project to the current multiproject')) |
616 self.addProjectAct.setWhatsThis(self.trUtf8( |
617 self.addProjectAct.setWhatsThis(self.trUtf8( |
617 """<b>Add project...</b>""" |
618 """<b>Add project...</b>""" |
618 """<p>This opens a dialog for adding a project""" |
619 """<p>This opens a dialog for adding a project""" |
646 """ |
647 """ |
647 menu = QMenu(self.trUtf8('&Multiproject'), self.parent()) |
648 menu = QMenu(self.trUtf8('&Multiproject'), self.parent()) |
648 self.recentMenu = QMenu(self.trUtf8('Open &Recent Multiprojects'), menu) |
649 self.recentMenu = QMenu(self.trUtf8('Open &Recent Multiprojects'), menu) |
649 |
650 |
650 self.__menus = { |
651 self.__menus = { |
651 "Main" : menu, |
652 "Main": menu, |
652 "Recent" : self.recentMenu, |
653 "Recent": self.recentMenu, |
653 } |
654 } |
654 |
655 |
655 # connect the aboutToShow signals |
656 # connect the aboutToShow signals |
656 self.recentMenu.aboutToShow.connect(self.__showContextMenuRecent) |
657 self.recentMenu.aboutToShow.connect(self.__showContextMenuRecent) |
657 self.recentMenu.triggered.connect(self.__openRecent) |
658 self.recentMenu.triggered.connect(self.__openRecent) |
733 if idx < 10: |
734 if idx < 10: |
734 formatStr = '&{0:d}. {1}' |
735 formatStr = '&{0:d}. {1}' |
735 else: |
736 else: |
736 formatStr = '{0:d}. {1}' |
737 formatStr = '{0:d}. {1}' |
737 act = self.recentMenu.addAction( |
738 act = self.recentMenu.addAction( |
738 formatStr.format(idx, |
739 formatStr.format(idx, |
739 Utilities.compactPath(rp, self.ui.maxMenuFilePathLen))) |
740 Utilities.compactPath(rp, self.ui.maxMenuFilePathLen))) |
740 act.setData(rp) |
741 act.setData(rp) |
741 act.setEnabled(QFileInfo(rp).exists()) |
742 act.setEnabled(QFileInfo(rp).exists()) |
742 idx += 1 |
743 idx += 1 |
743 |
744 |
744 self.recentMenu.addSeparator() |
745 self.recentMenu.addSeparator() |
745 self.recentMenu.addAction(self.trUtf8('&Clear'), self.__clearRecent) |
746 self.recentMenu.addAction(self.trUtf8('&Clear'), self.__clearRecent) |
746 |
747 |
747 def __openRecent(self, act): |
748 def __openRecent(self, act): |
748 """ |
749 """ |
749 Private method to open a multi project from the list of rencently |
750 Private method to open a multi project from the list of rencently |
750 opened multi projects. |
751 opened multi projects. |
751 |
752 |
752 @param act reference to the action that triggered (QAction) |
753 @param act reference to the action that triggered (QAction) |
753 """ |
754 """ |
754 file = act.data() |
755 file = act.data() |
808 @param filename filename of the project file (string) |
809 @param filename filename of the project file (string) |
809 """ |
810 """ |
810 self.projectObject.openProject(filename) |
811 self.projectObject.openProject(filename) |
811 self.projectOpened.emit(filename) |
812 self.projectOpened.emit(filename) |
812 |
813 |
813 def __openMasterProject(self, reopen = True): |
814 def __openMasterProject(self, reopen=True): |
814 """ |
815 """ |
815 Public slot to open the master project. |
816 Public slot to open the master project. |
816 |
817 |
817 @param reopen flag indicating, that the master project should be |
818 @param reopen flag indicating, that the master project should be |
818 reopened, if it has been opened already (boolean) |
819 reopened, if it has been opened already (boolean) |