MultiProject/MultiProject.py

branch
Py2 comp.
changeset 3484
645c12de6b0c
parent 3178
f25fc1364c88
parent 3345
071afe8be2a1
child 3541
5c35f4f0ecf1
equal deleted inserted replaced
3456:96232974dcdb 3484:645c12de6b0c
9 9
10 from __future__ import unicode_literals 10 from __future__ import unicode_literals
11 11
12 import os 12 import os
13 13
14 from PyQt4.QtCore import pyqtSignal, Qt, QFileInfo, QFile, QIODevice, QObject 14 from PyQt4.QtCore import pyqtSignal, pyqtSlot, Qt, QFileInfo, QFile, \
15 QIODevice, QObject
15 from PyQt4.QtGui import QMenu, QApplication, QDialog, QCursor, QToolBar 16 from PyQt4.QtGui import QMenu, QApplication, QDialog, QCursor, QToolBar
16 17
17 from Globals import recentNameMultiProject 18 from Globals import recentNameMultiProject
18 19
19 from E5Gui.E5Action import E5Action, createActionGroup 20 from E5Gui.E5Action import E5Action, createActionGroup
89 self.description = "" # description of the multi project 90 self.description = "" # description of the multi project
90 self.name = "" 91 self.name = ""
91 self.opened = False 92 self.opened = False
92 self.projects = [] # list of project info; each info entry is 93 self.projects = [] # list of project info; each info entry is
93 # a dictionary 94 # a dictionary
94 # 'name' : Name of the project 95 # 'name' : name of the project
95 # 'file' : project filename 96 # 'file' : project file name
96 # 'master' : flag indicating the master 97 # 'master' : flag indicating the master
97 # project 98 # project
98 # 'description' : description of the project 99 # 'description' : description of the project
100 # 'category' : name of the group
101 self.categories = []
99 102
100 def __loadRecent(self): 103 def __loadRecent(self):
101 """ 104 """
102 Private method to load the recently opened multi project filenames. 105 Private method to load the recently opened multi project filenames.
103 """ 106 """
187 190
188 if removelist: 191 if removelist:
189 for project in removelist: 192 for project in removelist:
190 self.projects.remove(project) 193 self.projects.remove(project)
191 self.setDirty(True) 194 self.setDirty(True)
195
196 def __extractCategories(self):
197 """
198 Private slot to extract the categories used in the project definitions.
199 """
200 for project in self.projects:
201 if project['category'] and \
202 project['category'] not in self.categories:
203 self.categories.append(project['category'])
204
205 def getCategories(self):
206 """
207 Public method to get the list of defined categories.
208
209 @return list of categories (list of string)
210 """
211 return [c for c in self.categories if c]
192 212
193 def __readMultiProject(self, fn): 213 def __readMultiProject(self, fn):
194 """ 214 """
195 Private method to read in a multi project (.e4m) file. 215 Private method to read in a multi project (.e4m) file.
196 216
207 return False 227 return False
208 else: 228 else:
209 QApplication.restoreOverrideCursor() 229 QApplication.restoreOverrideCursor()
210 E5MessageBox.critical( 230 E5MessageBox.critical(
211 self.ui, 231 self.ui,
212 self.trUtf8("Read multiproject file"), 232 self.tr("Read multiproject file"),
213 self.trUtf8( 233 self.tr(
214 "<p>The multiproject file <b>{0}</b> could not be" 234 "<p>The multiproject file <b>{0}</b> could not be"
215 " read.</p>").format(fn)) 235 " read.</p>").format(fn))
216 return False 236 return False
217 237
218 self.pfile = os.path.abspath(fn) 238 self.pfile = os.path.abspath(fn)
219 self.ppath = os.path.abspath(os.path.dirname(fn)) 239 self.ppath = os.path.abspath(os.path.dirname(fn))
240
241 self.__extractCategories()
220 242
221 # insert filename into list of recently opened multi projects 243 # insert filename into list of recently opened multi projects
222 self.__syncRecent() 244 self.__syncRecent()
223 245
224 self.name = os.path.splitext(os.path.basename(fn))[0] 246 self.name = os.path.splitext(os.path.basename(fn))[0]
250 .writeXML() 272 .writeXML()
251 res = True 273 res = True
252 else: 274 else:
253 E5MessageBox.critical( 275 E5MessageBox.critical(
254 self.ui, 276 self.ui,
255 self.trUtf8("Save multiproject file"), 277 self.tr("Save multiproject file"),
256 self.trUtf8( 278 self.tr(
257 "<p>The multiproject file <b>{0}</b> could not be " 279 "<p>The multiproject file <b>{0}</b> could not be "
258 "written.</p>").format(fn)) 280 "written.</p>").format(fn))
259 res = False 281 res = False
260 282
261 if res: 283 if res:
267 # insert filename into list of recently opened projects 289 # insert filename into list of recently opened projects
268 self.__syncRecent() 290 self.__syncRecent()
269 291
270 return res 292 return res
271 293
294 @pyqtSlot()
272 def addProject(self, startdir=None): 295 def addProject(self, startdir=None):
273 """ 296 """
274 Public slot used to add files to the project. 297 Public slot used to add files to the project.
275 298
276 @param startdir start directory for the selection dialog (string) 299 @param startdir start directory for the selection dialog (string)
278 from .AddProjectDialog import AddProjectDialog 301 from .AddProjectDialog import AddProjectDialog
279 if not startdir: 302 if not startdir:
280 startdir = self.ppath 303 startdir = self.ppath
281 if not startdir: 304 if not startdir:
282 startdir = Preferences.getMultiProject("Workspace") 305 startdir = Preferences.getMultiProject("Workspace")
283 dlg = AddProjectDialog(self.ui, startdir=startdir) 306 dlg = AddProjectDialog(self.ui, startdir=startdir,
307 categories=self.categories)
284 if dlg.exec_() == QDialog.Accepted: 308 if dlg.exec_() == QDialog.Accepted:
285 name, filename, isMaster, description = dlg.getData() 309 name, filename, isMaster, description, category = dlg.getData()
286 310
287 # step 1: check, if project was already added 311 # step 1: check, if project was already added
288 for project in self.projects: 312 for project in self.projects:
289 if project['file'] == filename: 313 if project['file'] == filename:
290 return 314 return
302 project = { 326 project = {
303 'name': name, 327 'name': name,
304 'file': filename, 328 'file': filename,
305 'master': isMaster, 329 'master': isMaster,
306 'description': description, 330 'description': description,
331 'category': category,
307 } 332 }
308 self.projects.append(project) 333 self.projects.append(project)
334 if category not in self.categories:
335 self.categories.append(category)
309 self.projectAdded.emit(project) 336 self.projectAdded.emit(project)
310 self.setDirty(True) 337 self.setDirty(True)
311 338
312 def changeProjectProperties(self, pro): 339 def changeProjectProperties(self, pro):
313 """ 340 """
326 break 353 break
327 354
328 # step 2: change the entry 355 # step 2: change the entry
329 for project in self.projects: 356 for project in self.projects:
330 if project['file'] == pro['file']: 357 if project['file'] == pro['file']:
331 # project filename is not changeable via interface 358 # project file name is not changeable via interface
332 project['name'] = pro['name'] 359 project['name'] = pro['name']
333 project['master'] = pro['master'] 360 project['master'] = pro['master']
334 project['description'] = pro['description'] 361 project['description'] = pro['description']
362 project['category'] = pro['category']
363 if project['category'] not in self.categories:
364 self.categories.append(project['category'])
335 self.projectDataChanged.emit(project) 365 self.projectDataChanged.emit(project)
336 self.setDirty(True) 366 self.setDirty(True)
337 367
338 def getProjects(self): 368 def getProjects(self):
339 """ 369 """
402 if dlg.exec_() == QDialog.Accepted: 432 if dlg.exec_() == QDialog.Accepted:
403 dlg.storeData() 433 dlg.storeData()
404 self.setDirty(True) 434 self.setDirty(True)
405 self.multiProjectPropertiesChanged.emit() 435 self.multiProjectPropertiesChanged.emit()
406 436
437 @pyqtSlot()
438 @pyqtSlot(str)
407 def openMultiProject(self, fn=None, openMaster=True): 439 def openMultiProject(self, fn=None, openMaster=True):
408 """ 440 """
409 Public slot to open a multi project. 441 Public slot to open a multi project.
410 442
411 @param fn optional filename of the multi project file to be 443 @param fn optional filename of the multi project file to be
417 return 449 return
418 450
419 if fn is None: 451 if fn is None:
420 fn = E5FileDialog.getOpenFileName( 452 fn = E5FileDialog.getOpenFileName(
421 self.parent(), 453 self.parent(),
422 self.trUtf8("Open multiproject"), 454 self.tr("Open multiproject"),
423 Preferences.getMultiProject("Workspace") or 455 Preferences.getMultiProject("Workspace") or
424 Utilities.getHomeDir(), 456 Utilities.getHomeDir(),
425 self.trUtf8("Multiproject Files (*.e4m)")) 457 self.tr("Multiproject Files (*.e5m *.e4m)"))
426 458
427 if fn == "": 459 if fn == "":
428 fn = None 460 fn = None
429 461
430 QApplication.processEvents() 462 QApplication.processEvents()
457 489
458 @return flag indicating success (boolean) 490 @return flag indicating success (boolean)
459 """ 491 """
460 if self.isDirty(): 492 if self.isDirty():
461 if len(self.pfile) > 0: 493 if len(self.pfile) > 0:
494 if self.pfile.endswith(".e4m"):
495 self.pfile = self.pfile.replace(".e4m", ".e5m")
496 self.__syncRecent()
462 ok = self.__writeMultiProject() 497 ok = self.__writeMultiProject()
463 else: 498 else:
464 ok = self.saveMultiProjectAs() 499 ok = self.saveMultiProjectAs()
465 else: 500 else:
466 ok = True 501 ok = True
470 """ 505 """
471 Public slot to save the current multi project to a different file. 506 Public slot to save the current multi project to a different file.
472 507
473 @return flag indicating success (boolean) 508 @return flag indicating success (boolean)
474 """ 509 """
475 defaultFilter = self.trUtf8("Multiproject Files (*.e4m)") 510 defaultFilter = self.tr("Multiproject Files (*.e5m)")
476 if self.ppath: 511 if self.ppath:
477 defaultPath = self.ppath 512 defaultPath = self.ppath
478 else: 513 else:
479 defaultPath = Preferences.getMultiProject("Workspace") or \ 514 defaultPath = Preferences.getMultiProject("Workspace") or \
480 Utilities.getHomeDir() 515 Utilities.getHomeDir()
481 fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( 516 fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
482 self.parent(), 517 self.parent(),
483 self.trUtf8("Save multiproject as"), 518 self.tr("Save multiproject as"),
484 defaultPath, 519 defaultPath,
485 self.trUtf8("Multiproject Files (*.e4m)"), 520 self.tr("Multiproject Files (*.e5m)"),
486 defaultFilter, 521 defaultFilter,
487 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) 522 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
488 523
489 if fn: 524 if fn:
490 ext = QFileInfo(fn).suffix() 525 ext = QFileInfo(fn).suffix()
493 if ex: 528 if ex:
494 fn += ex 529 fn += ex
495 if QFileInfo(fn).exists(): 530 if QFileInfo(fn).exists():
496 res = E5MessageBox.yesNo( 531 res = E5MessageBox.yesNo(
497 self.parent(), 532 self.parent(),
498 self.trUtf8("Save File"), 533 self.tr("Save File"),
499 self.trUtf8("<p>The file <b>{0}</b> already exists." 534 self.tr("<p>The file <b>{0}</b> already exists."
500 " Overwrite it?</p>").format(fn), 535 " Overwrite it?</p>").format(fn),
501 icon=E5MessageBox.Warning) 536 icon=E5MessageBox.Warning)
502 if not res: 537 if not res:
503 return False 538 return False
504 539
505 self.name = QFileInfo(fn).baseName() 540 self.name = QFileInfo(fn).baseName()
518 @return flag indicating whether this operation was successful (boolean) 553 @return flag indicating whether this operation was successful (boolean)
519 """ 554 """
520 if self.isDirty(): 555 if self.isDirty():
521 res = E5MessageBox.okToClearData( 556 res = E5MessageBox.okToClearData(
522 self.parent(), 557 self.parent(),
523 self.trUtf8("Close Multiproject"), 558 self.tr("Close Multiproject"),
524 self.trUtf8("The current multiproject has unsaved changes."), 559 self.tr("The current multiproject has unsaved changes."),
525 self.saveMultiProject) 560 self.saveMultiProject)
526 if res: 561 if res:
527 self.setDirty(False) 562 self.setDirty(False)
528 return res 563 return res
529 564
571 self.actions = [] 606 self.actions = []
572 607
573 self.actGrp1 = createActionGroup(self) 608 self.actGrp1 = createActionGroup(self)
574 609
575 act = E5Action( 610 act = E5Action(
576 self.trUtf8('New multiproject'), 611 self.tr('New multiproject'),
577 UI.PixmapCache.getIcon("multiProjectNew.png"), 612 UI.PixmapCache.getIcon("multiProjectNew.png"),
578 self.trUtf8('&New...'), 0, 0, 613 self.tr('&New...'), 0, 0,
579 self.actGrp1, 'multi_project_new') 614 self.actGrp1, 'multi_project_new')
580 act.setStatusTip(self.trUtf8('Generate a new multiproject')) 615 act.setStatusTip(self.tr('Generate a new multiproject'))
581 act.setWhatsThis(self.trUtf8( 616 act.setWhatsThis(self.tr(
582 """<b>New...</b>""" 617 """<b>New...</b>"""
583 """<p>This opens a dialog for entering the info for a""" 618 """<p>This opens a dialog for entering the info for a"""
584 """ new multiproject.</p>""" 619 """ new multiproject.</p>"""
585 )) 620 ))
586 act.triggered[()].connect(self.__newMultiProject) 621 act.triggered.connect(self.__newMultiProject)
587 self.actions.append(act) 622 self.actions.append(act)
588 623
589 act = E5Action( 624 act = E5Action(
590 self.trUtf8('Open multiproject'), 625 self.tr('Open multiproject'),
591 UI.PixmapCache.getIcon("multiProjectOpen.png"), 626 UI.PixmapCache.getIcon("multiProjectOpen.png"),
592 self.trUtf8('&Open...'), 0, 0, 627 self.tr('&Open...'), 0, 0,
593 self.actGrp1, 'multi_project_open') 628 self.actGrp1, 'multi_project_open')
594 act.setStatusTip(self.trUtf8('Open an existing multiproject')) 629 act.setStatusTip(self.tr('Open an existing multiproject'))
595 act.setWhatsThis(self.trUtf8( 630 act.setWhatsThis(self.tr(
596 """<b>Open...</b>""" 631 """<b>Open...</b>"""
597 """<p>This opens an existing multiproject.</p>""" 632 """<p>This opens an existing multiproject.</p>"""
598 )) 633 ))
599 act.triggered[()].connect(self.openMultiProject) 634 act.triggered.connect(self.openMultiProject)
600 self.actions.append(act) 635 self.actions.append(act)
601 636
602 self.closeAct = E5Action( 637 self.closeAct = E5Action(
603 self.trUtf8('Close multiproject'), 638 self.tr('Close multiproject'),
604 UI.PixmapCache.getIcon("multiProjectClose.png"), 639 UI.PixmapCache.getIcon("multiProjectClose.png"),
605 self.trUtf8('&Close'), 0, 0, self, 'multi_project_close') 640 self.tr('&Close'), 0, 0, self, 'multi_project_close')
606 self.closeAct.setStatusTip(self.trUtf8( 641 self.closeAct.setStatusTip(self.tr(
607 'Close the current multiproject')) 642 'Close the current multiproject'))
608 self.closeAct.setWhatsThis(self.trUtf8( 643 self.closeAct.setWhatsThis(self.tr(
609 """<b>Close</b>""" 644 """<b>Close</b>"""
610 """<p>This closes the current multiproject.</p>""" 645 """<p>This closes the current multiproject.</p>"""
611 )) 646 ))
612 self.closeAct.triggered[()].connect(self.closeMultiProject) 647 self.closeAct.triggered.connect(self.closeMultiProject)
613 self.actions.append(self.closeAct) 648 self.actions.append(self.closeAct)
614 649
615 self.saveAct = E5Action( 650 self.saveAct = E5Action(
616 self.trUtf8('Save multiproject'), 651 self.tr('Save multiproject'),
617 UI.PixmapCache.getIcon("multiProjectSave.png"), 652 UI.PixmapCache.getIcon("multiProjectSave.png"),
618 self.trUtf8('&Save'), 0, 0, self, 'multi_project_save') 653 self.tr('&Save'), 0, 0, self, 'multi_project_save')
619 self.saveAct.setStatusTip(self.trUtf8('Save the current multiproject')) 654 self.saveAct.setStatusTip(self.tr('Save the current multiproject'))
620 self.saveAct.setWhatsThis(self.trUtf8( 655 self.saveAct.setWhatsThis(self.tr(
621 """<b>Save</b>""" 656 """<b>Save</b>"""
622 """<p>This saves the current multiproject.</p>""" 657 """<p>This saves the current multiproject.</p>"""
623 )) 658 ))
624 self.saveAct.triggered[()].connect(self.saveMultiProject) 659 self.saveAct.triggered.connect(self.saveMultiProject)
625 self.actions.append(self.saveAct) 660 self.actions.append(self.saveAct)
626 661
627 self.saveasAct = E5Action( 662 self.saveasAct = E5Action(
628 self.trUtf8('Save multiproject as'), 663 self.tr('Save multiproject as'),
629 UI.PixmapCache.getIcon("multiProjectSaveAs.png"), 664 UI.PixmapCache.getIcon("multiProjectSaveAs.png"),
630 self.trUtf8('Save &as...'), 0, 0, self, 665 self.tr('Save &as...'), 0, 0, self,
631 'multi_project_save_as') 666 'multi_project_save_as')
632 self.saveasAct.setStatusTip(self.trUtf8( 667 self.saveasAct.setStatusTip(self.tr(
633 'Save the current multiproject to a new file')) 668 'Save the current multiproject to a new file'))
634 self.saveasAct.setWhatsThis(self.trUtf8( 669 self.saveasAct.setWhatsThis(self.tr(
635 """<b>Save as</b>""" 670 """<b>Save as</b>"""
636 """<p>This saves the current multiproject to a new file.</p>""" 671 """<p>This saves the current multiproject to a new file.</p>"""
637 )) 672 ))
638 self.saveasAct.triggered[()].connect(self.saveMultiProjectAs) 673 self.saveasAct.triggered.connect(self.saveMultiProjectAs)
639 self.actions.append(self.saveasAct) 674 self.actions.append(self.saveasAct)
640 675
641 self.addProjectAct = E5Action( 676 self.addProjectAct = E5Action(
642 self.trUtf8('Add project to multiproject'), 677 self.tr('Add project to multiproject'),
643 UI.PixmapCache.getIcon("fileProject.png"), 678 UI.PixmapCache.getIcon("fileProject.png"),
644 self.trUtf8('Add &project...'), 0, 0, 679 self.tr('Add &project...'), 0, 0,
645 self, 'multi_project_add_project') 680 self, 'multi_project_add_project')
646 self.addProjectAct.setStatusTip(self.trUtf8( 681 self.addProjectAct.setStatusTip(self.tr(
647 'Add a project to the current multiproject')) 682 'Add a project to the current multiproject'))
648 self.addProjectAct.setWhatsThis(self.trUtf8( 683 self.addProjectAct.setWhatsThis(self.tr(
649 """<b>Add project...</b>""" 684 """<b>Add project...</b>"""
650 """<p>This opens a dialog for adding a project""" 685 """<p>This opens a dialog for adding a project"""
651 """ to the current multiproject.</p>""" 686 """ to the current multiproject.</p>"""
652 )) 687 ))
653 self.addProjectAct.triggered[()].connect(self.addProject) 688 self.addProjectAct.triggered.connect(self.addProject)
654 self.actions.append(self.addProjectAct) 689 self.actions.append(self.addProjectAct)
655 690
656 self.propsAct = E5Action( 691 self.propsAct = E5Action(
657 self.trUtf8('Multiproject properties'), 692 self.tr('Multiproject properties'),
658 UI.PixmapCache.getIcon("multiProjectProps.png"), 693 UI.PixmapCache.getIcon("multiProjectProps.png"),
659 self.trUtf8('&Properties...'), 0, 0, self, 694 self.tr('&Properties...'), 0, 0, self,
660 'multi_project_properties') 695 'multi_project_properties')
661 self.propsAct.setStatusTip(self.trUtf8( 696 self.propsAct.setStatusTip(self.tr(
662 'Show the multiproject properties')) 697 'Show the multiproject properties'))
663 self.propsAct.setWhatsThis(self.trUtf8( 698 self.propsAct.setWhatsThis(self.tr(
664 """<b>Properties...</b>""" 699 """<b>Properties...</b>"""
665 """<p>This shows a dialog to edit the multiproject""" 700 """<p>This shows a dialog to edit the multiproject"""
666 """ properties.</p>""" 701 """ properties.</p>"""
667 )) 702 ))
668 self.propsAct.triggered[()].connect(self.__showProperties) 703 self.propsAct.triggered.connect(self.__showProperties)
669 self.actions.append(self.propsAct) 704 self.actions.append(self.propsAct)
670 705
671 self.closeAct.setEnabled(False) 706 self.closeAct.setEnabled(False)
672 self.saveAct.setEnabled(False) 707 self.saveAct.setEnabled(False)
673 self.saveasAct.setEnabled(False) 708 self.saveasAct.setEnabled(False)
678 """ 713 """
679 Public slot to initialize the multi project menu. 714 Public slot to initialize the multi project menu.
680 715
681 @return the menu generated (QMenu) 716 @return the menu generated (QMenu)
682 """ 717 """
683 menu = QMenu(self.trUtf8('&Multiproject'), self.parent()) 718 menu = QMenu(self.tr('&Multiproject'), self.parent())
684 self.recentMenu = QMenu(self.trUtf8('Open &Recent Multiprojects'), 719 self.recentMenu = QMenu(self.tr('Open &Recent Multiprojects'),
685 menu) 720 menu)
686 721
687 self.__menus = { 722 self.__menus = {
688 "Main": menu, 723 "Main": menu,
689 "Recent": self.recentMenu, 724 "Recent": self.recentMenu,
717 752
718 @param toolbarManager reference to a toolbar manager object 753 @param toolbarManager reference to a toolbar manager object
719 (E5ToolBarManager) 754 (E5ToolBarManager)
720 @return the toolbar generated (QToolBar) 755 @return the toolbar generated (QToolBar)
721 """ 756 """
722 tb = QToolBar(self.trUtf8("Multiproject"), self.ui) 757 tb = QToolBar(self.tr("Multiproject"), self.ui)
723 tb.setIconSize(UI.Config.ToolBarIconSize) 758 tb.setIconSize(UI.Config.ToolBarIconSize)
724 tb.setObjectName("MultiProjectToolbar") 759 tb.setObjectName("MultiProjectToolbar")
725 tb.setToolTip(self.trUtf8('Multiproject')) 760 tb.setToolTip(self.tr('Multiproject'))
726 761
727 tb.addActions(self.actGrp1.actions()) 762 tb.addActions(self.actGrp1.actions())
728 tb.addAction(self.closeAct) 763 tb.addAction(self.closeAct)
729 tb.addSeparator() 764 tb.addSeparator()
730 tb.addAction(self.saveAct) 765 tb.addAction(self.saveAct)
779 act.setData(rp) 814 act.setData(rp)
780 act.setEnabled(QFileInfo(rp).exists()) 815 act.setEnabled(QFileInfo(rp).exists())
781 idx += 1 816 idx += 1
782 817
783 self.recentMenu.addSeparator() 818 self.recentMenu.addSeparator()
784 self.recentMenu.addAction(self.trUtf8('&Clear'), self.__clearRecent) 819 self.recentMenu.addAction(self.tr('&Clear'), self.__clearRecent)
785 820
786 def __openRecent(self, act): 821 def __openRecent(self, act):
787 """ 822 """
788 Private method to open a multi project from the list of rencently 823 Private method to open a multi project from the list of rencently
789 opened multi projects. 824 opened multi projects.

eric ide

mercurial