Beispiel #1
0
class FileWidget(QWidget, Ui_Form):
    """The table that stored workbook data,
    including IO functions.
    """

    load_id = pyqtSignal(int)

    def __init__(self, parent):
        super(FileWidget, self).__init__(parent)
        self.setupUi(self)
        """UI part
        
        + ID
        + Date
        + Description
        + Author
        + Previous
        + Branch
        """
        self.CommitTable.setColumnWidth(0, 70)
        self.CommitTable.setColumnWidth(1, 70)
        self.CommitTable.setColumnWidth(2, 130)
        self.CommitTable.setColumnWidth(3, 70)
        self.CommitTable.setColumnWidth(4, 70)
        self.CommitTable.setColumnWidth(5, 70)
        """The main window functions.
        
        + Get current point data.
        + Get current link data.
        """
        self.pointDataFunc = parent.Entities_Point.data
        self.linkDataFunc = parent.Entities_Link.data
        self.storageDataFunc = lambda: tuple(
            (parent.mechanism_storage.item(row).text(),
             parent.mechanism_storage.item(row).expr)
            for row in range(parent.mechanism_storage.count()))
        """Functions to get and set data.
        
        + Call it to get main window be shown as saved.
        + Add empty link with color.
        + Main window will load the entered expression.
        + Reset the main window.
        + Call to load storages.
        + Call after loaded paths.
        """
        self.isSavedFunc = parent.workbookSaved
        self.linkGroupFunc = parent.emptyLinkGroup
        self.parseFunc = parent.parseExpression
        self.clearFunc = parent.clear
        self.loadStorageFunc = parent.loadStorage
        """Mentioned in 'core.widgets.custom',
        because DimensionalSynthesis created after FileWidget.
        
        self.CollectDataFunc #Call to get collections data.
        self.TriangleDataFunc #Call to get triangle data.
        self.InputsDataFunc #Call to get inputs variables data.
        self.AlgorithmDataFunc #Call to get algorithm data.
        self.pathDataFunc #Call to get path data.
        self.loadCollectFunc #Call to load collections data.
        self.loadTriangleFunc #Call to load triangle data.
        self.loadInputsFunc #Call to load inputs variables data.
        self.loadAlgorithmFunc #Call after loaded algorithm results.
        self.loadPathFunc #Call after loaded paths.
        """
        #Close database when destroyed.
        self.destroyed.connect(self.colseDatabase)
        #Undo Stack
        self.CommandStack = parent.CommandStack
        #Reset
        self.reset()

    def reset(self):
        """Clear all the things that dependent on database."""
        #peewee Quary(CommitModel) type
        self.history_commit = None
        self.Script = ""
        self.fileName = QFileInfo("Untitled")
        self.lastTime = datetime.datetime.now()
        self.changed = False
        self.Stack = 0
        self.CommandStack.clear()
        for row in range(self.CommitTable.rowCount()):
            self.CommitTable.removeRow(0)
        self.BranchList.clear()
        self.AuthorList.clear()
        self.FileAuthor.clear()
        self.FileDescription.clear()
        self.branch_current.clear()
        self.commit_search_text.clear()
        self.commit_current_id.setValue(0)

    def connectDatabase(self, fileName: str):
        """Connect database."""
        self.colseDatabase()
        db.init(fileName)
        db.connect()
        db.create_tables([CommitModel, UserModel, BranchModel], safe=True)

    @pyqtSlot()
    def colseDatabase(self):
        if not db.deferred:
            db.close()

    def save(self, fileName: str, isBranch=False):
        """Save database.
        
        + Append to new branch function.
        """
        author_name = self.FileAuthor.text()
        if not author_name:
            author_name = self.FileAuthor.placeholderText()
        branch_name = '' if isBranch else self.branch_current.text()
        commit_text = self.FileDescription.text()
        while not author_name:
            author_name, ok = QInputDialog.getText(
                self, "Author", "Please enter author's name:",
                QLineEdit.Normal, "Anonymous")
            if not ok:
                return
        while not branch_name.isidentifier():
            branch_name, ok = QInputDialog.getText(
                self, "Branch", "Please enter a branch name:",
                QLineEdit.Normal, "master")
            if not ok:
                return
        while not commit_text:
            commit_text, ok = QInputDialog.getText(self, "Commit",
                                                   "Please add a comment:",
                                                   QLineEdit.Normal,
                                                   "Update mechanism.")
            if not ok:
                return
        if ((fileName != self.fileName.absoluteFilePath())
                and os.path.isfile(fileName)):
            os.remove(fileName)
            print("The original file has been overwritten.")
        self.connectDatabase(fileName)
        isError = False
        with db.atomic():
            if author_name in (user.name for user in UserModel.select()):
                author_model = (UserModel.select().where(
                    UserModel.name == author_name).get())
            else:
                author_model = UserModel(name=author_name)
            if branch_name in (branch.name for branch in BranchModel.select()):
                branch_model = (BranchModel.select().where(
                    BranchModel.name == branch_name).get())
            else:
                branch_model = BranchModel(name=branch_name)
            pointData = self.pointDataFunc()
            linkcolor = {
                vlink.name: vlink.colorSTR
                for vlink in self.linkDataFunc()
            }
            args = {
                'author':
                author_model,
                'description':
                commit_text,
                'mechanism':
                compress("M[{}]".format(", ".join(vpoint.expr
                                                  for vpoint in pointData))),
                'linkcolor':
                compress(linkcolor),
                'storage':
                compress(self.storageDataFunc()),
                'pathdata':
                compress(self.pathDataFunc()),
                'collectiondata':
                compress(self.CollectDataFunc()),
                'triangledata':
                compress(self.TriangleDataFunc()),
                'inputsdata':
                compress(self.InputsDataFunc()),
                'algorithmdata':
                compress(self.AlgorithmDataFunc()),
                'branch':
                branch_model
            }
            try:
                args['previous'] = (CommitModel.select().where(
                    CommitModel.id == self.commit_current_id.value()).get())
            except CommitModel.DoesNotExist:
                args['previous'] = None
            new_commit = CommitModel(**args)
            try:
                author_model.save()
                branch_model.save()
                new_commit.save()
            except Exception as e:
                print(str(e))
                db.rollback()
                isError = True
            else:
                self.history_commit = (CommitModel.select().order_by(
                    CommitModel.id))
        if isError:
            os.remove(fileName)
            print("The file was removed.")
            return
        self.read(fileName)
        print("Saving \"{}\" successful.".format(fileName))
        size = QFileInfo(fileName).size()
        print(
            "Size: {}".format("{} MB".format(round(size / 1024 /
                                                   1024, 2)) if size / 1024 //
                              1024 else "{} KB".format(round(size / 1024, 2))))

    def read(self, fileName: str):
        """Load database commit."""
        self.connectDatabase(fileName)
        history_commit = CommitModel.select().order_by(CommitModel.id)
        commit_count = len(history_commit)
        if not commit_count:
            QMessageBox.warning(self, "Warning",
                                "This file is a non-committed database.")
            return
        self.clearFunc()
        self.reset()
        self.history_commit = history_commit
        for commit in self.history_commit:
            self.addCommit(commit)
        print("{} commit(s) was find in database.".format(commit_count))
        self.loadCommit(self.history_commit.order_by(-CommitModel.id).get())
        self.fileName = QFileInfo(fileName)
        self.isSavedFunc()

    def importMechanism(self, fileName: str):
        """Pick and import the latest mechanism from a branch."""
        self.connectDatabase(fileName)
        commit_all = CommitModel.select().join(BranchModel)
        branch_all = BranchModel.select().order_by(BranchModel.name)
        if self.history_commit != None:
            self.connectDatabase(self.fileName.absoluteFilePath())
        else:
            self.colseDatabase()
        branch_name, ok = QInputDialog.getItem(
            self, "Branch", "Select the latest commit in the branch to load.",
            [branch.name for branch in branch_all], 0, False)
        if not ok:
            return
        try:
            commit = (commit_all.where(
                BranchModel.name == branch_name).order_by(
                    CommitModel.date).get())
        except CommitModel.DoesNotExist:
            QMessageBox.warning(self, "Warning",
                                "This file is a non-committed database.")
        else:
            self.importCommit(commit)

    def addCommit(self, commit: CommitModel):
        """Add commit data to all widgets.
        
        + Commit ID
        + Date
        + Description
        + Author
        + Previous commit
        + Branch
        + Add to table widget.
        """
        row = self.CommitTable.rowCount()
        self.CommitTable.insertRow(row)

        self.commit_current_id.setValue(commit.id)
        button = LoadCommitButton(commit.id, self)
        button.loaded.connect(self.loadCommitID)
        self.load_id.connect(button.isLoaded)
        self.CommitTable.setCellWidget(row, 0, button)

        date = ("{t.year:02d}-{t.month:02d}-{t.day:02d} " +
                "{t.hour:02d}:{t.minute:02d}:{t.second:02d}").format(
                    t=commit.date)

        self.CommitTable.setItem(row, 2, QTableWidgetItem(commit.description))

        author_name = commit.author.name
        all_authors = [
            self.AuthorList.item(row).text()
            for row in range(self.AuthorList.count())
        ]
        if author_name not in all_authors:
            self.AuthorList.addItem(author_name)

        if commit.previous:
            previous_id = "#{}".format(commit.previous.id)
        else:
            previous_id = "None"

        branch_name = commit.branch.name
        all_branchs = [
            self.BranchList.item(row).text()
            for row in range(self.BranchList.count())
        ]
        if branch_name not in all_branchs:
            self.BranchList.addItem(branch_name)
        self.branch_current.setText(branch_name)

        for i, text in enumerate(
            [date, commit.description, author_name, previous_id, branch_name]):
            item = QTableWidgetItem(text)
            item.setToolTip(text)
            self.CommitTable.setItem(row, i + 1, item)

    def loadCommitID(self, id: int):
        """Check the id is correct."""
        try:
            commit = self.history_commit.where(CommitModel.id == id).get()
        except CommitModel.DoesNotExist:
            QMessageBox.warning(self, "Warning", "Commit ID is not exist.")
        except AttributeError:
            QMessageBox.warning(self, "Warning", "Nothing submitted.")
        else:
            self.loadCommit(commit)

    def loadCommit(self, commit: CommitModel):
        """Load the commit pointer."""
        if not self.checkSaved():
            return
        #Reset the main window status.
        self.clearFunc()
        #Load the commit to widgets.
        print("Loading commit #{}.".format(commit.id))
        self.load_id.emit(commit.id)
        self.commit_current_id.setValue(commit.id)
        self.branch_current.setText(commit.branch.name)
        #Load the expression.
        self.linkGroupFunc(decompress(commit.linkcolor))
        self.parseFunc(decompress(commit.mechanism))
        #Load the storages.
        self.loadStorageFunc(decompress(commit.storage))
        #Load pathdata.
        self.loadPathFunc(decompress(commit.pathdata))
        #Load collectiondata.
        self.loadCollectFunc(decompress(commit.collectiondata))
        #Load triangledata.
        self.loadTriangleFunc(decompress(commit.triangledata))
        #Load inputsdata.
        self.loadInputsFunc(decompress(commit.inputsdata))
        #Load algorithmdata.
        self.loadAlgorithmFunc(decompress(commit.algorithmdata))
        #Workbook loaded.
        self.isSavedFunc()
        print("The specified phase has been loaded.")

    def importCommit(self, commit: CommitModel):
        """Just load the expression. (No clear step!)"""
        self.parseFunc(decompress(commit.mechanism))
        print("The specified phase has been merged.")

    @pyqtSlot()
    def on_commit_stash_clicked(self):
        """Reload the least commit ID."""
        self.loadCommitID(self.commit_current_id.value())

    def loadExample(self, isImport=False) -> bool:
        """Load example to new workbook."""
        if not self.checkSaved():
            return False
        #load example by expression.
        example_name, ok = QInputDialog.getItem(
            self, "Examples", "Select a example to load:",
            sorted(k for k in example_list), 0, False)
        if not ok:
            return False
        if not isImport:
            self.reset()
            self.clearFunc()
        self.parseFunc(example_list[example_name])
        self.fileName = QFileInfo(example_name)
        self.isSavedFunc()
        print("Example \"{}\" has been loaded.".format(example_name))
        return True

    def checkSaved(self) -> bool:
        """Check and warn if user is not saved yet."""
        if not self.changed:
            return True
        reply = QMessageBox.question(
            self, "Message",
            "Are you sure to load?\nAny changes won't be saved.",
            (QMessageBox.Ok | QMessageBox.Cancel), QMessageBox.Ok)
        return reply == QMessageBox.Ok

    @pyqtSlot(str)
    def on_commit_search_text_textEdited(self, text: str):
        """Commit filter (by description and another)."""
        if not text:
            for row in range(self.CommitTable.rowCount()):
                self.CommitTable.setRowHidden(row, False)
            return
        for row in range(self.CommitTable.rowCount()):
            self.CommitTable.setRowHidden(
                row, not ((text in self.CommitTable.item(row, 2).text()) or
                          (text in self.CommitTable.item(row, 3).text())))

    @pyqtSlot(str)
    def on_AuthorList_currentTextChanged(self, text: str):
        """Change default author's name when select another author."""
        self.FileAuthor.setPlaceholderText(text)

    @pyqtSlot()
    def on_branch_checkout_clicked(self):
        """Switch to the last commit of branch."""
        if not self.BranchList.currentRow() > -1:
            return
        branch_name = self.BranchList.currentItem().text()
        if branch_name != self.branch_current.text():
            leastCommit = (self.history_commit.join(BranchModel).where(
                BranchModel.name == branch_name).order_by(
                    -CommitModel.date).get())
            self.loadCommit(leastCommit)

    @pyqtSlot()
    def on_branch_delete_clicked(self):
        """Delete all commits in the branch."""
        if not self.BranchList.currentRow() > -1:
            return
        branch_name = self.BranchList.currentItem().text()
        if branch_name != self.branch_current.text():
            fileName = self.fileName.absoluteFilePath()
            #Connect on database to remove all the commit in this branch.
            with db.atomic():
                branch_quary = (BranchModel.select().where(
                    BranchModel.name == branch_name))
                (CommitModel.delete().where(
                    CommitModel.branch.in_(branch_quary)).execute())
                (BranchModel.delete().where(
                    BranchModel.name == branch_name).execute())
            db.close()
            print("Branch {} was deleted.".format(branch_name))
            #Reload database.
            self.read(fileName)
        else:
            QMessageBox.warning(self, "Warning",
                                "Cannot delete current branch.")
Beispiel #2
0
class DatabaseWidget(QWidget, Ui_Form):
    """The table that stored workbook data and changes."""

    load_id = pyqtSignal(int)

    def __init__(self, parent: 'mw.MainWindow'):
        super(DatabaseWidget, self).__init__(parent)
        self.setupUi(self)

        # ID
        self.CommitTable.setColumnWidth(0, 70)
        # Date
        self.CommitTable.setColumnWidth(1, 70)
        # Description
        self.CommitTable.setColumnWidth(2, 130)
        # Author
        self.CommitTable.setColumnWidth(3, 70)
        # Previous
        self.CommitTable.setColumnWidth(4, 70)
        # Branch
        self.CommitTable.setColumnWidth(5, 70)

        # Check file changed function.
        self.__check_file_changed = parent.checkFileChanged
        # Check workbook saved function.
        self.__workbook_saved = parent.workbookSaved

        # Call to get point expressions.
        self.__point_expr_func = parent.EntitiesPoint.expression
        # Call to get link data.
        self.__link_expr_func = parent.EntitiesLink.colors
        # Call to get storage data.
        self.__storage_data_func = parent.getStorage
        # Call to get collections data.
        self.__collect_data_func = parent.CollectionTabPage.collect_data
        # Call to get triangle data.
        self.__triangle_data_func = parent.CollectionTabPage.triangle_data
        # Call to get inputs variables data.
        self.__inputs_data_func = parent.InputsWidget.inputPairs
        # Call to get algorithm data.
        self.__algorithm_data_func = parent.DimensionalSynthesis.mechanism_data
        # Call to get path data.
        self.__path_data_func = parent.InputsWidget.pathData

        # Add empty links function.
        self.__add_links_func = parent.addEmptyLinks
        # Parse function.
        self.__parse_func = parent.parseExpression

        # Call to load inputs variables data.
        self.__load_inputs_func = parent.InputsWidget.addInputsVariables
        # Add storage function.
        self.__add_storage_func = parent.addMultipleStorage
        # Call to load paths.
        self.__load_path_func = parent.InputsWidget.loadPaths
        # Call to load collections data.
        self.__load_collect_func = parent.CollectionTabPage.StructureWidget.addCollections
        # Call to load triangle data.
        self.__load_triangle_func = parent.CollectionTabPage.TriangularIterationWidget.addCollections
        # Call to load algorithm results.
        self.__load_algorithm_func = parent.DimensionalSynthesis.loadResults

        # Clear function for main window.
        self.__clear_func = parent.clear

        # Close database when destroyed.
        self.destroyed.connect(self.__close_database)
        # Undo Stack
        self.__command_clear = parent.CommandStack.clear

        # Reset
        self.history_commit = None
        self.file_name = QFileInfo("Untitled")
        self.last_time = datetime.datetime.now()
        self.changed = False
        self.Stack = 0
        self.reset()

    def reset(self):
        """Clear all the things that dependent on database."""
        self.history_commit: Optional[CommitModel] = None
        self.file_name = QFileInfo("Untitled")
        self.last_time = datetime.datetime.now()
        self.changed = False
        self.Stack = 0
        self.__command_clear()
        for row in range(self.CommitTable.rowCount()):
            self.CommitTable.removeRow(0)
        self.BranchList.clear()
        self.AuthorList.clear()
        self.FileAuthor.clear()
        self.FileDescription.clear()
        self.branch_current.clear()
        self.commit_search_text.clear()
        self.commit_current_id.setValue(0)
        self.__close_database()

    def setFileName(self, file_name: str):
        """Set file name."""
        self.file_name = QFileInfo(file_name)

    def __connect_database(self, file_name: str):
        """Connect database."""
        self.__close_database()
        _db.init(file_name)
        _db.connect()
        _db.create_tables([CommitModel, UserModel, BranchModel], safe=True)

    @pyqtSlot()
    def __close_database(self):
        if not _db.deferred:
            _db.close()

    def save(self, file_name: str, is_branch: bool = False):
        """Save database, append commit to new branch function."""
        author_name = self.FileAuthor.text(
        ) or self.FileAuthor.placeholderText()
        branch_name = '' if is_branch else self.branch_current.text()
        commit_text = self.FileDescription.text()
        while not author_name:
            author_name, ok = QInputDialog.getText(
                self, "Author", "Please enter author's name:",
                QLineEdit.Normal, "Anonymous")
            if not ok:
                return
        while not branch_name.isidentifier():
            branch_name, ok = QInputDialog.getText(
                self, "Branch", "Please enter a branch name:",
                QLineEdit.Normal, "master")
            if not ok:
                return
        while not commit_text:
            commit_text, ok = QInputDialog.getText(self, "Commit",
                                                   "Please add a comment:",
                                                   QLineEdit.Normal,
                                                   "Update mechanism.")
            if not ok:
                return
        if (file_name !=
                self.file_name.absoluteFilePath()) and isfile(file_name):
            os_remove(file_name)
            print("The original file has been overwritten.")
        self.__connect_database(file_name)
        is_error = False
        with _db.atomic():
            if author_name in (user.name for user in UserModel.select()):
                author_model = (UserModel.select().where(
                    UserModel.name == author_name).get())
            else:
                author_model = UserModel(name=author_name)
            if branch_name in (branch.name for branch in BranchModel.select()):
                branch_model = (BranchModel.select().where(
                    BranchModel.name == branch_name).get())
            else:
                branch_model = BranchModel(name=branch_name)
            args = {
                'author':
                author_model,
                'description':
                commit_text,
                'mechanism':
                _compress(self.__point_expr_func()),
                'linkcolor':
                _compress(self.__link_expr_func()),
                'storage':
                _compress(list(self.__storage_data_func())),
                'pathdata':
                _compress(self.__path_data_func()),
                'collectiondata':
                _compress(self.__collect_data_func()),
                'triangledata':
                _compress(self.__triangle_data_func()),
                'inputsdata':
                _compress(
                    tuple((b, d) for b, d, a in self.__inputs_data_func())),
                'algorithmdata':
                _compress(self.__algorithm_data_func()),
                'branch':
                branch_model,
            }
            try:
                args['previous'] = (CommitModel.select().where(
                    CommitModel.id == self.commit_current_id.value()).get())
            except CommitModel.DoesNotExist:
                args['previous'] = None
            new_commit = CommitModel(**args)
            try:
                author_model.save()
                branch_model.save()
                new_commit.save()
            except Exception as e:
                print(str(e))
                _db.rollback()
                is_error = True
            else:
                self.history_commit = CommitModel.select().order_by(
                    CommitModel.id)
        if is_error:
            os_remove(file_name)
            print("The file was removed.")
            return
        self.read(file_name)
        print(f"Saving \"{file_name}\" successful.")
        size = QFileInfo(file_name).size()
        print("Size: " + (f"{size / 1024 / 1024:.02f} MB" if size / 1024 //
                          1024 else f"{size / 1024:.02f} KB"))

    def read(self, file_name: str):
        """Load database commit."""
        self.__connect_database(file_name)
        history_commit = CommitModel.select().order_by(CommitModel.id)
        commit_count = len(history_commit)
        if not commit_count:
            QMessageBox.warning(self, "Warning",
                                "This file is a non-committed database.")
            return
        self.__clear_func()
        self.reset()
        self.history_commit = history_commit
        for commit in self.history_commit:
            self.__add_commit(commit)
        print(f"{commit_count} commit(s) was find in database.")
        self.__load_commit(self.history_commit.order_by(-CommitModel.id).get())
        self.file_name = QFileInfo(file_name)
        self.__workbook_saved()

    def importMechanism(self, file_name: str):
        """Pick and import the latest mechanism from a branch."""
        self.__connect_database(file_name)
        commit_all = CommitModel.select().join(BranchModel)
        branch_all = BranchModel.select().order_by(BranchModel.name)
        if self.history_commit:
            self.__connect_database(self.file_name.absoluteFilePath())
        else:
            self.__close_database()
        branch_name, ok = QInputDialog.getItem(
            self, "Branch", "Select the latest commit in the branch to load.",
            [branch.name for branch in branch_all], 0, False)
        if not ok:
            return
        try:
            commit = (commit_all.where(
                BranchModel.name == branch_name).order_by(
                    CommitModel.date).get())
        except CommitModel.DoesNotExist:
            QMessageBox.warning(self, "Warning",
                                "This file is a non-committed database.")
        else:
            self.__import_commit(commit)

    def __add_commit(self, commit: CommitModel):
        """Add commit data to all widgets.

        + Commit ID
        + Date
        + Description
        + Author
        + Previous commit
        + Branch
        + Add to table widget.
        """
        row = self.CommitTable.rowCount()
        self.CommitTable.insertRow(row)

        self.commit_current_id.setValue(commit.id)
        button = LoadCommitButton(commit.id, self)
        button.loaded.connect(self.__load_commit_id)
        self.load_id.connect(button.set_loaded)
        self.CommitTable.setCellWidget(row, 0, button)

        self.CommitTable.setItem(row, 2, QTableWidgetItem(commit.description))

        author_name = commit.author.name
        for row in range(self.AuthorList.count()):
            if author_name == self.AuthorList.item(row).text():
                break
        else:
            self.AuthorList.addItem(author_name)

        branch_name = commit.branch.name
        for row in range(self.BranchList.count()):
            if branch_name == self.BranchList.item(row).text():
                break
        else:
            self.BranchList.addItem(branch_name)
        self.branch_current.setText(branch_name)
        t = commit.date
        for i, text in enumerate(
            (f"{t.year:02d}-{t.month:02d}-{t.day:02d} "
             f"{t.hour:02d}:{t.minute:02d}:{t.second:02d}", commit.description,
             author_name,
             f"#{commit.previous.id}" if commit.previous else "None",
             branch_name)):
            item = QTableWidgetItem(text)
            item.setToolTip(text)
            self.CommitTable.setItem(row, i + 1, item)

    def __load_commit_id(self, id_int: int):
        """Check the id_int is correct."""
        try:
            commit = self.history_commit.where(CommitModel.id == id_int).get()
        except CommitModel.DoesNotExist:
            QMessageBox.warning(self, "Warning", "Commit ID is not exist.")
        except AttributeError:
            QMessageBox.warning(self, "Warning", "Nothing submitted.")
        else:
            self.__load_commit(commit)

    def __load_commit(self, commit: CommitModel):
        """Load the commit pointer."""
        if self.__check_file_changed():
            return
        # Reset the main window status.
        self.__clear_func()
        # Load the commit to widgets.
        print(f"Loading commit # {commit.id}.")
        self.load_id.emit(commit.id)
        self.commit_current_id.setValue(commit.id)
        self.branch_current.setText(commit.branch.name)
        # Load the expression.
        self.__add_links_func(_decompress(commit.linkcolor))
        self.__parse_func(_decompress(commit.mechanism))
        # Load inputs data.
        input_data: Sequence[Tuple[int, int]] = _decompress(commit.inputsdata)
        self.__load_inputs_func(input_data)
        # Load the storage.
        storage_data: List[Tuple[str, str]] = _decompress(commit.storage)
        self.__add_storage_func(storage_data)
        # Load path data.
        path_data: Dict[str,
                        Sequence[Tuple[float,
                                       float]]] = _decompress(commit.pathdata)
        self.__load_path_func(path_data)
        # Load collection data.
        collection_data: List[Tuple[Tuple[int, int],
                                    ...]] = _decompress(commit.collectiondata)
        self.__load_collect_func(collection_data)
        # Load triangle data.
        triangle_data: Dict[str, Dict[str,
                                      Any]] = _decompress(commit.triangledata)
        self.__load_triangle_func(triangle_data)
        # Load algorithm data.
        algorithm_data: List[Dict[str,
                                  Any]] = _decompress(commit.algorithmdata)
        self.__load_algorithm_func(algorithm_data)

        # Workbook loaded.
        self.__workbook_saved()
        print("The specified phase has been loaded.")

        # Show overview dialog.
        dlg = OverviewDialog(self,
                             f"{commit.branch.name} - commit # {commit.id}",
                             storage_data, input_data, path_data,
                             collection_data, triangle_data, algorithm_data)
        dlg.show()
        dlg.exec_()

    def __import_commit(self, commit: CommitModel):
        """Just load the expression. (No clear step!)"""
        self.__parse_func(_decompress(commit.mechanism))
        print("The specified phase has been merged.")

    @pyqtSlot(name='on_commit_stash_clicked')
    def stash(self):
        """Reload the least commit ID."""
        self.__load_commit_id(self.commit_current_id.value())

    def loadExample(self, is_import: bool = False) -> bool:
        """Load example to new workbook."""
        if self.__check_file_changed():
            return False
        # load example by expression.
        example_name, ok = QInputDialog.getItem(self, "Examples",
                                                "Select an example to load:",
                                                sorted(example_list), 0, False)
        if not ok:
            return False
        expr, inputs = example_list[example_name]
        if not is_import:
            self.reset()
            self.__clear_func()
        self.__parse_func(expr)
        if not is_import:
            # Import without input data.
            self.__load_inputs_func(inputs)
        self.file_name = QFileInfo(example_name)
        self.__workbook_saved()
        print(f"Example \"{example_name}\" has been loaded.")
        return True

    @pyqtSlot(str, name='on_commit_search_text_textEdited')
    def __set_search_text(self, text: str):
        """Commit filter (by description and another)."""
        if not text:
            for row in range(self.CommitTable.rowCount()):
                self.CommitTable.setRowHidden(row, False)
            return
        for row in range(self.CommitTable.rowCount()):
            self.CommitTable.setRowHidden(
                row, not ((text in self.CommitTable.item(row, 2).text()) or
                          (text in self.CommitTable.item(row, 3).text())))

    @pyqtSlot(str, name='on_AuthorList_currentTextChanged')
    def __set_author(self, text: str):
        """Change default author's name when select another author."""
        self.FileAuthor.setPlaceholderText(text)

    @pyqtSlot(name='on_branch_checkout_clicked')
    def __checkout_branch(self):
        """Switch to the last commit of branch."""
        if not self.BranchList.currentRow() > -1:
            return
        branch_name = self.BranchList.currentItem().text()
        if branch_name == self.branch_current.text():
            return
        least_commit = (self.history_commit.join(BranchModel).where(
            BranchModel.name == branch_name).order_by(-CommitModel.date).get())
        self.__load_commit(least_commit)

    @pyqtSlot(name='on_branch_delete_clicked')
    def __delete_branch(self):
        """Delete all commits in the branch."""
        if not self.BranchList.currentRow() > -1:
            return
        branch_name = self.BranchList.currentItem().text()
        if branch_name == self.branch_current.text():
            QMessageBox.warning(self, "Warning",
                                "Cannot delete current branch.")
            return
        file_name = self.file_name.absoluteFilePath()
        # Connect on database to remove all the commit in this branch.
        with _db.atomic():
            CommitModel.delete().where(
                CommitModel.branch.in_(BranchModel.select().where(
                    BranchModel.name == branch_name))).execute()
            BranchModel.delete().where(
                BranchModel.name == branch_name).execute()
        _db.close()
        print(f"Branch {branch_name} was deleted.")
        # Reload database.
        self.read(file_name)