コード例 #1
0
ファイル: run.py プロジェクト: archtool/archtool
    def open(self, triggered=False, url=None, new=False):
        """ Actually open a specific database.
            Called after the user has selected a database.
        """
        if not new and url.startswith(SQLITE_URL_PREFIX):
            # Check if the file already exists.
            fname = url.split(SQLITE_URL_PREFIX)[-1]
            if not os.path.exists(fname):
                QtGui.QMessageBox.critical(self, 'File does not exist',
                                           'The file %s does not appear to exist anymore' % fname)
                return
        if self.centralwidget:
            self.centralwidget.close()

        model.open(url, create=True)
        self.session = model.SessionFactory()
        Controller.setSession(self.session)

        # Check the version, if it exists
        versions = self.session.query(model.DbaseVersion).all()
        if len(versions) > 0:
            if versions[0].Version < model.VERSION:
                # Try to convert the model.
                dbname = url.split('/')[-1]
                q = QtGui.QMessageBox.question(self, 'Old database model %s' % dbname,
                                               'This database uses an old version of the database. ' + \
                                               'Conversion is necessary  in order to continue. ' + \
                                               'Database URL is: %s' % maskPasswords(url),
                                               buttons=QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel,
                                               defaultButton=QtGui.QMessageBox.Ok)
                self.session = None
                if q != QtGui.QMessageBox.Ok:
                    self.centralwidget.clean()
                    return
                # User wants to convert the model.
                updateDatabase(model.the_engine, url)
                self.open(url=url)
                return

        Styles.load(self.session)
        self.centralwidget = ArchitectureView(self)
        self.setCentralWidget(self.centralwidget)
        self.centralwidget.open(self.session)

        self.setWindowTitle("Architecture Tool: %s" % url.split('/')[-1])
        config.addRecentFile(url)
        self.current_url = url

        # Update the recent file menu
        self.setRecentFileMenu()
コード例 #2
0
ファイル: run.py プロジェクト: archtool/archtool
class ArchitectureTool(MainWindowForm[1]):
    def __init__(self):
        # Setup UI first.
        QtGui.QMainWindow.__init__(self, None)

        self.current_url = None
        self.centralwidget = None

        self.setStyleSheet('font: %spt "%s";' % (config.getConfig('font_size'),
                                                 config.getConfig('font_name')))
        # self.setStyleSheet('font: 12 "MS Shell Dlg 2";')
        # self.setStyleSheet('font: 12pt "MS Shell Dlg 2";')
        self.ui = MainWindowForm[0]()
        self.ui.setupUi(self)

        for action, func in [(self.ui.actionNew, self.onNew),
                             (self.ui.actionOpen, self.onOpen),
                             (self.ui.actionArchitecture, self.onArchitectureView),
                             (self.ui.actionPlanning, self.onPlanningView),
                             (self.ui.actionExport_as_CSV, self.exportCsv),
                             (self.ui.actionNew_from_CSV, self.newFromCsv),
                             (self.ui.actionWork_Items, self.onWorkItemView),
                             (self.ui.actionRequirements_Document, self.onRequirementsDocument),
                             (self.ui.actionOpen_Database, self.onOpenDatabase),
                             (self.ui.actionProgress_Report, self.onProgressReport)
                            ]:
            action.triggered.connect(func)

        # Add the recent files to the menu
        self.setRecentFileMenu()

        # Open the most recent file
        recent = config.getRecentFiles()
        if len(recent) > 0:
            self.open(url=recent[0])

        # Monkey-patch the menu to show its tooltips. I don't believe QT developers are so arrogant
        # they purposely disable tooltips in menu's!
        def handleMenuHovered(action):
            QtGui.QToolTip.showText(
                QtGui.QCursor.pos(), action.toolTip(),
                self.ui.menuRecent_Files, self.ui.menuRecent_Files.actionGeometry(action))

        self.ui.menuRecent_Files.hovered.connect(handleMenuHovered)


    def setRecentFileMenu(self):
        self.ui.menuRecent_Files.clear()
        # Add the recent files to the menu
        recent = config.getRecentFiles()
        for f in recent:
            a = QtGui.QAction(os.path.basename(f), self)
            a.triggered.connect(partial(self.open, url=f))
            # Mask any passwords
            f_nopasswd = maskPasswords(f)
            a.setToolTip(f_nopasswd)
            self.ui.menuRecent_Files.addAction(a)


    def onNew(self, fname=None):
        if not fname:
            fname = str(QtGui.QFileDialog.getSaveFileName(self, "Open an architecture model",
                                                          '.', "*.db"))
        if fname == '':
            return

        if self.centralwidget:
            self.centralwidget.clean()
        self.open(url=SQLITE_URL_PREFIX + fname, new=True)
        # Write the version number to the database
        self.session.add(model.DbaseVersion())
        self.session.commit()

    def newFromCsv(self):
        """ Create a new database from a CSV file exported earlier.
        """
        diag = CsvImportEditor(self)
        result = diag.exec_()
        if result != QtGui.QDialog.Accepted:
            return

        if self.centralwidget:
            self.centralwidget.close()

        url = diag.burp()
        csvname = diag.csv_file
        if not (csvname and url):
            return

        model.createDatabase(url)
        # Import and create the database
        data = loadCsv(csvname)
        importData(data, url)
        # Open the database
        self.open(url=url)

    def onOpenDatabase(self):
        """ Open a remote database instead of a local file.
        """
        url = QtGui.QInputDialog.getText(self, 'Open a database', 'Url:')
        if not url[1]:
            return

        url = str(url[0])
        self.open(url=url)

    def onOpen(self):
        """ Open an existing database.
        No check for outstanding changes necessary: all changes are
        stored immediatly.
        """
        fname = str(QtGui.QFileDialog.getOpenFileName(self, "Open an architecture model",
                                                      '.', "*.db"))
        if fname == '':
            return

        self.open(url=SQLITE_URL_PREFIX + fname)


    @reportError('Could not open the database.\n\nSee output for more details')
    def open(self, triggered=False, url=None, new=False):
        """ Actually open a specific database.
            Called after the user has selected a database.
        """
        if not new and url.startswith(SQLITE_URL_PREFIX):
            # Check if the file already exists.
            fname = url.split(SQLITE_URL_PREFIX)[-1]
            if not os.path.exists(fname):
                QtGui.QMessageBox.critical(self, 'File does not exist',
                                           'The file %s does not appear to exist anymore' % fname)
                return
        if self.centralwidget:
            self.centralwidget.close()

        model.open(url, create=True)
        self.session = model.SessionFactory()
        Controller.setSession(self.session)

        # Check the version, if it exists
        versions = self.session.query(model.DbaseVersion).all()
        if len(versions) > 0:
            if versions[0].Version < model.VERSION:
                # Try to convert the model.
                dbname = url.split('/')[-1]
                q = QtGui.QMessageBox.question(self, 'Old database model %s' % dbname,
                                               'This database uses an old version of the database. ' + \
                                               'Conversion is necessary  in order to continue. ' + \
                                               'Database URL is: %s' % maskPasswords(url),
                                               buttons=QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel,
                                               defaultButton=QtGui.QMessageBox.Ok)
                self.session = None
                if q != QtGui.QMessageBox.Ok:
                    self.centralwidget.clean()
                    return
                # User wants to convert the model.
                updateDatabase(model.the_engine, url)
                self.open(url=url)
                return

        Styles.load(self.session)
        self.centralwidget = ArchitectureView(self)
        self.setCentralWidget(self.centralwidget)
        self.centralwidget.open(self.session)

        self.setWindowTitle("Architecture Tool: %s" % url.split('/')[-1])
        config.addRecentFile(url)
        self.current_url = url

        # Update the recent file menu
        self.setRecentFileMenu()

    def onArchitectureView(self, triggered=False, cls=ArchitectureView):
        """ Open the Architecture View in the central window.

            The function is also used to open other views...
        """
        if not isinstance(self.centralwidget, cls):
            self.centralwidget.clean()
            self.centralwidget.close()

            self.centralwidget = cls(self)
            self.setCentralWidget(self.centralwidget)
            self.centralwidget.open(self.session)

    def onPlanningView(self):
        """ Open the Planning View in the central window.
        """
        # Use the onArchitectureView to open the PlanningView widget
        self.onArchitectureView(cls=PlanningView)

    def onWorkItemView(self):
      """ Open the Work Item view in the central window.
      """
      self.onArchitectureView(cls=WorkitemView)

    def exportCsv(self):
        """ Export the current model as a CSV file.
        """
        # Check a database is opened.
        if model.the_engine is None:
            return
        name = self.current_url.split('/')[-1].split('.')[0]
        # First ask the user for the file to save to.
        fname = str(QtGui.QFileDialog.getSaveFileName(self, 'export as CSV', '%s.csv' % name, '*.csv'))
        if fname == '':
            return
        # Then export the database
        export(fname, model.the_engine)


    def getProject(self):
        # Find the possible top requirements for the document, and let the user choose one.
        projects = self.session.query(model.Project).all()
        tops = [p.Name for p in projects]
        name, ok =  QtGui.QInputDialog.getItem(self, "Document Generation",
                                                  "Select the project to generate the document for:",
                                                  tops, editable=False)
        name = str(name)
        if ok and name:
            return projects[tops.index(name)]

    def onRequirementsDocument(self):
        """ Called when the user wants to generate a requirements document.
            Requirements documents are generated from one top element, and include
            all its child elements.
        """
        project = self.getProject()
        if not project:
            return
        # Find the requirements linked to this project
        requirements = [it for it in project.AItems if it.ItemType == 'requirement']
        if not requirements:
            msg = "There are no requirements associated with project %s"%project.Name
            QtGui.QMessageBox.critical(self, 'No requirements', msg)
            return

        exportRequirementsDocument(self.session, requirements)

    def onProgressReport(self):
        """ Called when the user wants to generate a progress report.
        """
        project = self.getProject()
        if not project:
            return

        createProgressReport(self.session, project)



    def customEvent(self, ev):
        """ Custom event handler.
            Custom events are expected to follow the command pattern.
        """
        try:
            ev.execute(self)
        except:
            logging.exception('Exception while handling custom event.')