16 ) |
16 ) |
17 from PyQt6.QtWidgets import QMenu, QApplication, QDialog, QToolBar |
17 from PyQt6.QtWidgets import QMenu, QApplication, QDialog, QToolBar |
18 |
18 |
19 from Globals import recentNameMultiProject |
19 from Globals import recentNameMultiProject |
20 |
20 |
21 from E5Gui.E5Action import E5Action, createActionGroup |
21 from E5Gui.EricAction import EricAction, createActionGroup |
22 from E5Gui import E5FileDialog, E5MessageBox, E5PathPickerDialog |
22 from E5Gui import EricFileDialog, EricMessageBox, EricPathPickerDialog |
23 from E5Gui.E5PathPickerDialog import E5PathPickerModes |
23 from E5Gui.EricPathPickerDialog import EricPathPickerModes |
24 from E5Gui.E5OverrideCursor import E5OverrideCursor |
24 from E5Gui.EricOverrideCursor import EricOverrideCursor |
25 |
25 |
26 import UI.PixmapCache |
26 import UI.PixmapCache |
27 |
27 |
28 import Preferences |
28 import Preferences |
29 import Utilities |
29 import Utilities |
227 @param fn filename of the multi project file to be read (string) |
227 @param fn filename of the multi project file to be read (string) |
228 @return flag indicating success |
228 @return flag indicating success |
229 """ |
229 """ |
230 if os.path.splitext(fn)[1] == ".emj": |
230 if os.path.splitext(fn)[1] == ".emj": |
231 # new JSON based format |
231 # new JSON based format |
232 with E5OverrideCursor(): |
232 with EricOverrideCursor(): |
233 res = self.__multiProjectFile.readFile(fn) |
233 res = self.__multiProjectFile.readFile(fn) |
234 else: |
234 else: |
235 # old XML based format |
235 # old XML based format |
236 f = QFile(fn) |
236 f = QFile(fn) |
237 if f.open(QIODevice.OpenModeFlag.ReadOnly): |
237 if f.open(QIODevice.OpenModeFlag.ReadOnly): |
238 with E5OverrideCursor(): |
238 with EricOverrideCursor(): |
239 from EricXML.MultiProjectReader import MultiProjectReader |
239 from EricXML.MultiProjectReader import MultiProjectReader |
240 reader = MultiProjectReader(f, self) |
240 reader = MultiProjectReader(f, self) |
241 reader.readXML() |
241 reader.readXML() |
242 f.close() |
242 f.close() |
243 res = not reader.hasError() |
243 res = not reader.hasError() |
244 else: |
244 else: |
245 E5MessageBox.critical( |
245 EricMessageBox.critical( |
246 self.ui, |
246 self.ui, |
247 self.tr("Read Multi Project File"), |
247 self.tr("Read Multi Project File"), |
248 self.tr( |
248 self.tr( |
249 "<p>The multi project file <b>{0}</b> could not be" |
249 "<p>The multi project file <b>{0}</b> could not be" |
250 " read.</p>").format(fn)) |
250 " read.</p>").format(fn)) |
363 startdir = self.ppath |
363 startdir = self.ppath |
364 if not startdir: |
364 if not startdir: |
365 startdir = Preferences.getMultiProject("Workspace") |
365 startdir = Preferences.getMultiProject("Workspace") |
366 srcProject = self.__projects[uid] |
366 srcProject = self.__projects[uid] |
367 srcProjectDirectory = os.path.dirname(srcProject["file"]) |
367 srcProjectDirectory = os.path.dirname(srcProject["file"]) |
368 dstProjectDirectory, ok = E5PathPickerDialog.getPath( |
368 dstProjectDirectory, ok = EricPathPickerDialog.getPath( |
369 self.parent(), |
369 self.parent(), |
370 self.tr("Copy Project"), |
370 self.tr("Copy Project"), |
371 self.tr("Enter directory for the new project (must not exist" |
371 self.tr("Enter directory for the new project (must not exist" |
372 " already):"), |
372 " already):"), |
373 mode=E5PathPickerModes.DIRECTORY_MODE, |
373 mode=EricPathPickerModes.DIRECTORY_MODE, |
374 path=srcProjectDirectory, |
374 path=srcProjectDirectory, |
375 defaultDirectory=startdir, |
375 defaultDirectory=startdir, |
376 ) |
376 ) |
377 if ( |
377 if ( |
378 ok and |
378 ok and |
380 not os.path.exists(dstProjectDirectory) |
380 not os.path.exists(dstProjectDirectory) |
381 ): |
381 ): |
382 try: |
382 try: |
383 shutil.copytree(srcProjectDirectory, dstProjectDirectory) |
383 shutil.copytree(srcProjectDirectory, dstProjectDirectory) |
384 except shutil.Error: |
384 except shutil.Error: |
385 E5MessageBox.critical( |
385 EricMessageBox.critical( |
386 self.parent(), |
386 self.parent(), |
387 self.tr("Copy Project"), |
387 self.tr("Copy Project"), |
388 self.tr("<p>The source project <b>{0}</b> could not" |
388 self.tr("<p>The source project <b>{0}</b> could not" |
389 " be copied to its destination <b>{1}</b>." |
389 " be copied to its destination <b>{1}</b>." |
390 "</p>").format(srcProjectDirectory, |
390 "</p>").format(srcProjectDirectory, |
534 """ |
534 """ |
535 if not self.checkDirty(): |
535 if not self.checkDirty(): |
536 return |
536 return |
537 |
537 |
538 if fn is None: |
538 if fn is None: |
539 fn = E5FileDialog.getOpenFileName( |
539 fn = EricFileDialog.getOpenFileName( |
540 self.parent(), |
540 self.parent(), |
541 self.tr("Open Multi Project"), |
541 self.tr("Open Multi Project"), |
542 Preferences.getMultiProject("Workspace") or |
542 Preferences.getMultiProject("Workspace") or |
543 Utilities.getHomeDir(), |
543 Utilities.getHomeDir(), |
544 self.tr("Multi Project Files (*.emj);;" |
544 self.tr("Multi Project Files (*.emj);;" |
599 self.ppath |
599 self.ppath |
600 if self.ppath else |
600 if self.ppath else |
601 (Preferences.getMultiProject("Workspace") or |
601 (Preferences.getMultiProject("Workspace") or |
602 Utilities.getHomeDir()) |
602 Utilities.getHomeDir()) |
603 ) |
603 ) |
604 fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( |
604 fn, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( |
605 self.parent(), |
605 self.parent(), |
606 self.tr("Save Multiproject"), |
606 self.tr("Save Multiproject"), |
607 defaultPath, |
607 defaultPath, |
608 self.tr("Multi Project Files (*.emj)"), |
608 self.tr("Multi Project Files (*.emj)"), |
609 defaultFilter, |
609 defaultFilter, |
610 E5FileDialog.DontConfirmOverwrite) |
610 EricFileDialog.DontConfirmOverwrite) |
611 |
611 |
612 if fn: |
612 if fn: |
613 ext = QFileInfo(fn).suffix() |
613 ext = QFileInfo(fn).suffix() |
614 if not ext: |
614 if not ext: |
615 ex = selectedFilter.split("(*")[1].split(")")[0] |
615 ex = selectedFilter.split("(*")[1].split(")")[0] |
616 if ex: |
616 if ex: |
617 fn += ex |
617 fn += ex |
618 if QFileInfo(fn).exists(): |
618 if QFileInfo(fn).exists(): |
619 res = E5MessageBox.yesNo( |
619 res = EricMessageBox.yesNo( |
620 self.parent(), |
620 self.parent(), |
621 self.tr("Save File"), |
621 self.tr("Save File"), |
622 self.tr("<p>The file <b>{0}</b> already exists." |
622 self.tr("<p>The file <b>{0}</b> already exists." |
623 " Overwrite it?</p>").format(fn), |
623 " Overwrite it?</p>").format(fn), |
624 icon=E5MessageBox.Warning) |
624 icon=EricMessageBox.Warning) |
625 if not res: |
625 if not res: |
626 return False |
626 return False |
627 |
627 |
628 self.name = QFileInfo(fn).baseName() |
628 self.name = QFileInfo(fn).baseName() |
629 self.__writeMultiProject(fn) |
629 self.__writeMultiProject(fn) |
639 Public method to check the dirty status and open a message window. |
639 Public method to check the dirty status and open a message window. |
640 |
640 |
641 @return flag indicating whether this operation was successful (boolean) |
641 @return flag indicating whether this operation was successful (boolean) |
642 """ |
642 """ |
643 if self.isDirty(): |
643 if self.isDirty(): |
644 res = E5MessageBox.okToClearData( |
644 res = EricMessageBox.okToClearData( |
645 self.parent(), |
645 self.parent(), |
646 self.tr("Close Multiproject"), |
646 self.tr("Close Multiproject"), |
647 self.tr("The current multiproject has unsaved changes."), |
647 self.tr("The current multiproject has unsaved changes."), |
648 self.saveMultiProject) |
648 self.saveMultiProject) |
649 if res: |
649 if res: |
693 """ |
693 """ |
694 self.actions = [] |
694 self.actions = [] |
695 |
695 |
696 self.actGrp1 = createActionGroup(self) |
696 self.actGrp1 = createActionGroup(self) |
697 |
697 |
698 act = E5Action( |
698 act = EricAction( |
699 self.tr('New multiproject'), |
699 self.tr('New multiproject'), |
700 UI.PixmapCache.getIcon("multiProjectNew"), |
700 UI.PixmapCache.getIcon("multiProjectNew"), |
701 self.tr('&New...'), 0, 0, |
701 self.tr('&New...'), 0, 0, |
702 self.actGrp1, 'multi_project_new') |
702 self.actGrp1, 'multi_project_new') |
703 act.setStatusTip(self.tr('Generate a new multiproject')) |
703 act.setStatusTip(self.tr('Generate a new multiproject')) |
707 """ new multiproject.</p>""" |
707 """ new multiproject.</p>""" |
708 )) |
708 )) |
709 act.triggered.connect(self.__newMultiProject) |
709 act.triggered.connect(self.__newMultiProject) |
710 self.actions.append(act) |
710 self.actions.append(act) |
711 |
711 |
712 act = E5Action( |
712 act = EricAction( |
713 self.tr('Open multiproject'), |
713 self.tr('Open multiproject'), |
714 UI.PixmapCache.getIcon("multiProjectOpen"), |
714 UI.PixmapCache.getIcon("multiProjectOpen"), |
715 self.tr('&Open...'), 0, 0, |
715 self.tr('&Open...'), 0, 0, |
716 self.actGrp1, 'multi_project_open') |
716 self.actGrp1, 'multi_project_open') |
717 act.setStatusTip(self.tr('Open an existing multiproject')) |
717 act.setStatusTip(self.tr('Open an existing multiproject')) |
720 """<p>This opens an existing multiproject.</p>""" |
720 """<p>This opens an existing multiproject.</p>""" |
721 )) |
721 )) |
722 act.triggered.connect(self.openMultiProject) |
722 act.triggered.connect(self.openMultiProject) |
723 self.actions.append(act) |
723 self.actions.append(act) |
724 |
724 |
725 self.closeAct = E5Action( |
725 self.closeAct = EricAction( |
726 self.tr('Close multiproject'), |
726 self.tr('Close multiproject'), |
727 UI.PixmapCache.getIcon("multiProjectClose"), |
727 UI.PixmapCache.getIcon("multiProjectClose"), |
728 self.tr('&Close'), 0, 0, self, 'multi_project_close') |
728 self.tr('&Close'), 0, 0, self, 'multi_project_close') |
729 self.closeAct.setStatusTip(self.tr( |
729 self.closeAct.setStatusTip(self.tr( |
730 'Close the current multiproject')) |
730 'Close the current multiproject')) |
733 """<p>This closes the current multiproject.</p>""" |
733 """<p>This closes the current multiproject.</p>""" |
734 )) |
734 )) |
735 self.closeAct.triggered.connect(self.closeMultiProject) |
735 self.closeAct.triggered.connect(self.closeMultiProject) |
736 self.actions.append(self.closeAct) |
736 self.actions.append(self.closeAct) |
737 |
737 |
738 self.saveAct = E5Action( |
738 self.saveAct = EricAction( |
739 self.tr('Save multiproject'), |
739 self.tr('Save multiproject'), |
740 UI.PixmapCache.getIcon("multiProjectSave"), |
740 UI.PixmapCache.getIcon("multiProjectSave"), |
741 self.tr('&Save'), 0, 0, self, 'multi_project_save') |
741 self.tr('&Save'), 0, 0, self, 'multi_project_save') |
742 self.saveAct.setStatusTip(self.tr('Save the current multiproject')) |
742 self.saveAct.setStatusTip(self.tr('Save the current multiproject')) |
743 self.saveAct.setWhatsThis(self.tr( |
743 self.saveAct.setWhatsThis(self.tr( |
745 """<p>This saves the current multiproject.</p>""" |
745 """<p>This saves the current multiproject.</p>""" |
746 )) |
746 )) |
747 self.saveAct.triggered.connect(self.saveMultiProject) |
747 self.saveAct.triggered.connect(self.saveMultiProject) |
748 self.actions.append(self.saveAct) |
748 self.actions.append(self.saveAct) |
749 |
749 |
750 self.saveasAct = E5Action( |
750 self.saveasAct = EricAction( |
751 self.tr('Save multiproject as'), |
751 self.tr('Save multiproject as'), |
752 UI.PixmapCache.getIcon("multiProjectSaveAs"), |
752 UI.PixmapCache.getIcon("multiProjectSaveAs"), |
753 self.tr('Save &as...'), 0, 0, self, |
753 self.tr('Save &as...'), 0, 0, self, |
754 'multi_project_save_as') |
754 'multi_project_save_as') |
755 self.saveasAct.setStatusTip(self.tr( |
755 self.saveasAct.setStatusTip(self.tr( |
759 """<p>This saves the current multiproject to a new file.</p>""" |
759 """<p>This saves the current multiproject to a new file.</p>""" |
760 )) |
760 )) |
761 self.saveasAct.triggered.connect(self.saveMultiProjectAs) |
761 self.saveasAct.triggered.connect(self.saveMultiProjectAs) |
762 self.actions.append(self.saveasAct) |
762 self.actions.append(self.saveasAct) |
763 |
763 |
764 self.addProjectAct = E5Action( |
764 self.addProjectAct = EricAction( |
765 self.tr('Add project to multiproject'), |
765 self.tr('Add project to multiproject'), |
766 UI.PixmapCache.getIcon("fileProject"), |
766 UI.PixmapCache.getIcon("fileProject"), |
767 self.tr('Add &project...'), 0, 0, |
767 self.tr('Add &project...'), 0, 0, |
768 self, 'multi_project_add_project') |
768 self, 'multi_project_add_project') |
769 self.addProjectAct.setStatusTip(self.tr( |
769 self.addProjectAct.setStatusTip(self.tr( |
774 """ to the current multiproject.</p>""" |
774 """ to the current multiproject.</p>""" |
775 )) |
775 )) |
776 self.addProjectAct.triggered.connect(self.addNewProject) |
776 self.addProjectAct.triggered.connect(self.addNewProject) |
777 self.actions.append(self.addProjectAct) |
777 self.actions.append(self.addProjectAct) |
778 |
778 |
779 self.propsAct = E5Action( |
779 self.propsAct = EricAction( |
780 self.tr('Multiproject properties'), |
780 self.tr('Multiproject properties'), |
781 UI.PixmapCache.getIcon("multiProjectProps"), |
781 UI.PixmapCache.getIcon("multiProjectProps"), |
782 self.tr('&Properties...'), 0, 0, self, |
782 self.tr('&Properties...'), 0, 0, self, |
783 'multi_project_properties') |
783 'multi_project_properties') |
784 self.propsAct.setStatusTip(self.tr( |
784 self.propsAct.setStatusTip(self.tr( |
837 def initToolbar(self, toolbarManager): |
837 def initToolbar(self, toolbarManager): |
838 """ |
838 """ |
839 Public slot to initialize the multi project toolbar. |
839 Public slot to initialize the multi project toolbar. |
840 |
840 |
841 @param toolbarManager reference to a toolbar manager object |
841 @param toolbarManager reference to a toolbar manager object |
842 (E5ToolBarManager) |
842 (EricToolBarManager) |
843 @return the toolbar generated (QToolBar) |
843 @return the toolbar generated (QToolBar) |
844 """ |
844 """ |
845 tb = QToolBar(self.tr("Multiproject"), self.ui) |
845 tb = QToolBar(self.tr("Multiproject"), self.ui) |
846 tb.setIconSize(UI.Config.ToolBarIconSize) |
846 tb.setIconSize(UI.Config.ToolBarIconSize) |
847 tb.setObjectName("MultiProjectToolbar") |
847 tb.setObjectName("MultiProjectToolbar") |
921 |
921 |
922 def getActions(self): |
922 def getActions(self): |
923 """ |
923 """ |
924 Public method to get a list of all actions. |
924 Public method to get a list of all actions. |
925 |
925 |
926 @return list of all actions (list of E5Action) |
926 @return list of all actions (list of EricAction) |
927 """ |
927 """ |
928 return self.actions[:] |
928 return self.actions[:] |
929 |
929 |
930 def addE5Actions(self, actions): |
930 def addEricActions(self, actions): |
931 """ |
931 """ |
932 Public method to add actions to the list of actions. |
932 Public method to add actions to the list of actions. |
933 |
933 |
934 @param actions list of actions (list of E5Action) |
934 @param actions list of actions (list of EricAction) |
935 """ |
935 """ |
936 self.actions.extend(actions) |
936 self.actions.extend(actions) |
937 |
937 |
938 def removeE5Actions(self, actions): |
938 def removeEricActions(self, actions): |
939 """ |
939 """ |
940 Public method to remove actions from the list of actions. |
940 Public method to remove actions from the list of actions. |
941 |
941 |
942 @param actions list of actions (list of E5Action) |
942 @param actions list of actions (list of EricAction) |
943 """ |
943 """ |
944 for act in actions: |
944 for act in actions: |
945 with contextlib.suppress(ValueError): |
945 with contextlib.suppress(ValueError): |
946 self.actions.remove(act) |
946 self.actions.remove(act) |
947 |
947 |