Example #1
0
 def cherry_pick(self):
     self.cpdw = CherryPickDialogWrapper(self.ui.repositoryTableWidget.item(self.ui.repositoryTableWidget.currentRow(), 1).text(), self)
     self.cpdw.exec_()
Example #2
0
class MainWindowWrapper(QMainWindow):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        # Repository list
        self.ui.listWidget.setMouseTracking(True)
        self.ui.listWidget.itemSelectionChanged.connect(self.view_repository)
        self.list_all_repositories()
        #Repository Table
        self.ui.repositoryTableWidget.setSelectionMode(QAbstractItemView.SingleSelection)
        self.ui.repositoryTableWidget.verticalHeader().setVisible(False)
        self.ui.repositoryTableWidget.itemSelectionChanged.connect(self.check_table_line)
        #Files List
        self.ui.files_listWidget.itemSelectionChanged.connect(self.view_file_changes)
        self.ui.Unstaged_listwidget.itemSelectionChanged.connect(self.view_current_unstaged_file_changes)
        self.ui.Staged_listWidget.itemSelectionChanged.connect(self.view_current_staged_file_changes)
        #Un/staged_listWidget
        self.ui.Staged_listWidget.setSelectionMode(QAbstractItemView.MultiSelection)
        self.ui.Unstaged_listwidget.setSelectionMode(QAbstractItemView.MultiSelection)
        # Menu/toolbar
        QObject.connect(self.ui.actionAdd_existing_repository, SIGNAL('triggered()'), self.browse)
        QObject.connect(self.ui.actionAdd_existing_repository_2, SIGNAL('triggered()'), self.browse)
        QObject.connect(self.ui.actionSettings, SIGNAL('triggered()'), self.settings_dialog)
        QObject.connect(self.ui.actionExit, SIGNAL('triggered()'), qApp.exit)
        QObject.connect(self.ui.actionDelete_repository, SIGNAL('triggered()'), self.delete_listWidgetitem)
        QObject.connect(self.ui.actionClone_repository_3, SIGNAL('triggered()'), self.clone_respoitory)
        QObject.connect(self.ui.actionClone_repository_2, SIGNAL('triggered()'), self.clone_respoitory)
        QObject.connect(self.ui.actionClone_repository, SIGNAL('triggered()'), self.clone_respoitory)
        QObject.connect(self.ui.actionPull, SIGNAL('triggered()'), self.pull)
        QObject.connect(self.ui.actionPush, SIGNAL('triggered()'), self.push)
        QObject.connect(self.ui.actionChange_branch, SIGNAL('triggered()'), self.change_branch_dialog)
        QObject.connect(self.ui.actionDelete_branch, SIGNAL('triggered()'), self.delete_branch_dialog)
        QObject.connect(self.ui.actionCreate_branch, SIGNAL('triggered()'), self.create_branch)
        QObject.connect(self.ui.actionAbout_Gitraffe, SIGNAL('triggered()'), self.about_dialog)
        QObject.connect(self.ui.actionRefresh, SIGNAL('triggered()'), self.view_repository)
        QObject.connect(self.ui.actionStashes, SIGNAL('triggered()'), self.stashes)
        # Buttons
        QObject.connect(self.ui.pullButton, SIGNAL('clicked()'), self.pull)
        QObject.connect(self.ui.pullButton_2, SIGNAL('clicked()'), self.pull)
        QObject.connect(self.ui.pushButton, SIGNAL('clicked()'), self.push)
        QObject.connect(self.ui.pushButton_2, SIGNAL('clicked()'), self.push)
        QObject.connect(self.ui.stageButton_2, SIGNAL('clicked()'), self.stage_files)
        QObject.connect(self.ui.unstageButton_2, SIGNAL('clicked()'), self.unstage_files)
        QObject.connect(self.ui.discardButton_2, SIGNAL('clicked()'), self.discard_files)
        QObject.connect(self.ui.commitButton_2, SIGNAL('clicked()'), self.commit_files)
        QObject.connect(self.ui.stashButton_2, SIGNAL('clicked()'), self.stash)
        # Widgets
        self.ui.repositoryTableWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.repositoryTableWidget.customContextMenuRequested.connect(self.cherry_pick_menu)
        header = self.ui.repositoryTableWidget.horizontalHeader()
        for i in range(1, 5):
            header.setResizeMode(i, QHeaderView.Stretch)

    def list_all_repositories(self):
        repositories = db_adapter.get_repositories()
        for repository in repositories:
            self.add_to_list(repository.name, repository.path)

    def browse(self):
        directory = QFileDialog.getExistingDirectory(self, QDir.homePath(), QDir.homePath())
        if directory!="":
            if check_repository(directory):
                if not db_adapter.exists_repository(directory):
                    name = QInputDialog().getText(self, 'Name', 'Put your repository name:', text=basename(directory))
                    if name[1]:
                        self.add_to_database(name[0], directory)
                        self.add_to_list(name[0], directory)
                else:
                    QMessageBox.critical(self, "Error", "This repository is already added", QMessageBox.Ok)
            else: QMessageBox.critical(self, "Error", "That directory is not a git repository", QMessageBox.Ok)

    def add_to_database(self, name, directory):
        db_adapter.add_repository(name, directory)

    def add_to_list(self, name, directory):
        repo = QListWidgetItem(QIcon(dirname(main_window.__file__)+'/icons/Git-Icon-Black.png'), name, self.ui.listWidget)
        repo.setStatusTip(directory)
        repo.setData(Qt.UserRole, directory)
        repo.setFlags(repo.flags() | Qt.ItemIsEditable)

    def delete_listWidgetitem(self):
        if self.ui.listWidget.count()!=0:
            name = self.ui.listWidget.item(self.ui.listWidget.currentRow()).text()
            respond = QMessageBox.question(self, "Delete",
                                           "Are you sure, that you want delete " + name,
                                           QMessageBox.Ok, QMessageBox.Cancel)
            if respond==QMessageBox.Ok:
                db_adapter.delete_repository(self.ui.listWidget.currentItem().data(Qt.UserRole))
                self.ui.repositoryTableWidget.setRowCount(0)
                self.ui.listWidget.takeItem(self.ui.listWidget.currentRow())

    def graph(self):
        graph = get_graph()
        commits = get_commits()
        self.ui.repositoryTableWidget.setRowCount(len(commits)+1)
        item = DefinedGraphWidget('current.png')
        self.ui.repositoryTableWidget.setCellWidget(0, 0, item)
        self.ui.repositoryTableWidget.setItem(0, 2, QTableWidgetItem('Current local changes'))
        max_size = 30
        if len(commits) > 0:
            item = FirstGraphWidget(graph[0])
            self.ui.repositoryTableWidget.setCellWidget(1, 0, item)
            for i in range(len(commits[0])):
                item = QTableWidgetItem(commits[0][i])
                self.ui.repositoryTableWidget.setItem(1, i+1, item)
            for i in range(1, len(graph)-1):
                item = GraphWidget(graph[i], None, graph[i-1])
                self.ui.repositoryTableWidget.setCellWidget(i+1, 0, item)
                if item.size > max_size:
                    max_size = item.size
                for j in range(len(commits[i])):
                    item = QTableWidgetItem(commits[i][j])
                    self.ui.repositoryTableWidget.setItem(i+1, j+1, item)
            item = LastGraphWidget(graph[-1])
            self.ui.repositoryTableWidget.setCellWidget(len(graph), 0, item)
            for i in range(len(commits[-1])):
                item = QTableWidgetItem(commits[-1][i])
                self.ui.repositoryTableWidget.setItem(len(graph), i+1, item)
        self.ui.repositoryTableWidget.horizontalHeader().resizeSection(0, max_size)

    def refresh_graph(self):
        self.ui.repositoryTableWidget.clearContents()
        self.graph()

    def view_repository(self):
        item = self.ui.listWidget.currentItem()
        if item != None:
            path = item.data(Qt.UserRole)
            open_repository(path)
            self.graph()
            if self.ui.repositoryTableWidget.currentRow() == 0:
                self.view_current_changes()
            self.ui.repositoryTableWidget.selectRow(0)

    def clone_respoitory(self):
        cwd = CloneWindowWrapper(self)
        cwd.exec_()

    def check_table_line(self):
        if self.ui.repositoryTableWidget.currentRow() == 0:
            self.view_current_changes()
        else:
            self.view_files()

    def view_current_changes(self):
        self.ui.bottomwidgets.setCurrentIndex(1)
        self.ui.Unstaged_listwidget.clear()
        self.ui.Staged_listWidget.clear()
        for un_file in get_unstaged_files():
            if len(un_file)!=0:
                QListWidgetItem(' '.join(un_file), self.ui.Unstaged_listwidget)
        for s_file in get_staged_files():
            if len(s_file)!=0:
                QListWidgetItem(' '.join(s_file), self.ui.Staged_listWidget)

    def view_files(self):
        self.ui.bottomwidgets.setCurrentIndex(0)
        self.ui.files_listWidget.clear() #makes view_file_changes
        commit = self.ui.repositoryTableWidget.item(self.ui.repositoryTableWidget.currentRow(), 1)
        if commit != None:
            files = get_files(commit.text())
            try:
                for flag, com_file in files:
                    QListWidgetItem(flag + " " + com_file, self.ui.files_listWidget)
            except ValueError:
                pass
        if self.ui.files_listWidget.count(): self.ui.files_listWidget.setCurrentRow(0)
        else: self.view_file_changes()

    def change_branch_dialog(self):
        if self.ui.listWidget.currentItem().isSelected() == True:
            self.bdw = BranchesDialogWrapper(self)
            QObject.connect(self.bdw, SIGNAL('accepted()'), self.refresh_graph)
            self.bdw.exec_()
        else:
            QMessageBox.critical(self, "Error", "You must choose repository before changing branch!", QMessageBox.Ok)

    def delete_branch_dialog(self):
        if self.ui.listWidget.currentItem().isSelected() == True:
            DeleteBranchDialogWrapper(self).exec_()
        else:
            QMessageBox.critical(self, "Error", "You must choose repository before deleting branch!", QMessageBox.Ok)

    def create_branch(self):
        if self.ui.listWidget.currentItem().isSelected() == True:
            name = QInputDialog.getText(self, 'Name', 'Put your new branch name:')
            if name[1]:
                QMessageBox.information(self, 'Create branch', create_branch(self, name[0]), QMessageBox.Ok)
        else:
            QMessageBox.critical(self, "Error", "You must choose repository before creating branch!", QMessageBox.Ok)

    def about_dialog(self):
        AboutDialogWrapper(self).exec_()

    def pull(self):
        def error():
            QMessageBox.critical(self, "Error", "You must choose repository before pulling!", QMessageBox.Ok)
        if self.ui.listWidget.currentItem() != None:
            if self.ui.listWidget.currentItem().isSelected() == True:
                QMessageBox.information(self, "Pull", pull(self), QMessageBox.Ok)
                self.refresh_graph()
            else:
                error()
        else:
            error()

    def push(self):
        def error():
            QMessageBox.critical(self, "Error", "You must choose repository before pushing!", QMessageBox.Ok)
        if self.ui.listWidget.currentItem() != None:
            if self.ui.listWidget.currentItem().isSelected():
                QMessageBox.information(self, "Push", push(self), QMessageBox.Ok)
                self.view_repository()
            else:
                error()
        else:
            error()

    def settings_dialog(self):
        SettingsDialogWrapper(self).exec_()

    def view_current_staged_file_changes(self):
        self.ui.diff_local_textBrowser.clear()
        staged = self.ui.Staged_listWidget.currentItem()
        comparsion = self.ui.repositoryTableWidget.item(1,1).text()
        if staged and staged.isSelected():
            flag, path = staged.text().split(None, 1)
            path = "\ ".join(path.split())
            self.ui.diff_local_textBrowser.setText(get_staged_file_changes(flag, path, comparsion = comparsion))

    def view_current_unstaged_file_changes(self):
        self.ui.diff_local_textBrowser.clear()
        unstaged = self.ui.Unstaged_listwidget.currentItem()
        comparsion = self.ui.repositoryTableWidget.item(1,1).text()
        if unstaged and unstaged.isSelected():
            flag, path = unstaged.text().split(None, 1)
            path = "\ ".join(path.split())
            self.ui.diff_local_textBrowser.setText(get_unstaged_file_changes(flag, path, comparsion = comparsion))
    
    def view_file_changes(self):
        self.ui.diff_textBrowser.clear()
        if self.ui.files_listWidget.count():
            commit = self.ui.repositoryTableWidget.item(self.ui.repositoryTableWidget.currentRow(), 1).text()
            comparsion = None
            if self.ui.repositoryTableWidget.currentRow()+1 != self.ui.repositoryTableWidget.rowCount():
                comparsion = self.ui.repositoryTableWidget.item(self.ui.repositoryTableWidget.currentRow()+1, 1).text()
            flag, path = self.ui.files_listWidget.currentItem().text().split(None, 1)
            path = "\ ".join(path.split())
            self.ui.diff_textBrowser.setText(get_unstaged_file_changes(flag, path, commit, comparsion))

    def move_files(fwidget, twidget):
        selected = []
        for item in fwidget.selectedItems():
            selected.append(item.text().split()[1])
            QListWidgetItem(item.text(), twidget)
            fwidget.takeItem(fwidget.row(item))
        return selected

    def stage_files(self):
        if len(self.ui.Unstaged_listwidget.selectedItems()) > 0:
            for item in self.ui.Unstaged_listwidget.selectedItems():
                splited_item = item.text().split()
                if splited_item[0] == 'D':
                    git_rm(splited_item[1])
                else:
                    git_add(splited_item[1])
            self.view_current_changes()
        else:
            QMessageBox.critical(self, "Error", "You must select unstaged file(s) to stage!", QMessageBox.Ok)

    def unstage_files(self):
        if len(self.ui.Staged_listWidget.selectedItems()) > 0:
            selected = []
            for item in self.ui.Staged_listWidget.selectedItems():
                selected.append(item.text().split()[1])
                if self.ui.repositoryTableWidget.rowCount() > 1:
                    git_reset_head(selected)
                else:
                    git_rm_cached(selected)
            self.view_current_changes()
        else:
            QMessageBox.critical(self, "Error", "You must select staged file(s) to unstage!", QMessageBox.Ok)

    def discard_files(self):
        if len(self.ui.Unstaged_listwidget.selectedItems()) > 0:
            reply = QMessageBox.question(self, 'Discard', 'Do you want to discard changes?', QMessageBox.Yes, QMessageBox.No)
            if reply == QMessageBox.Yes:
                for item in self.ui.Unstaged_listwidget.selectedItems():
                    splited_item = item.text().split()
                    if splited_item[0] == '??':
                        clean(splited_item[1])
                    else:
                        git_check_out(splited_item[1])
                self.view_current_changes()
        else:
            QMessageBox.critical(self, "Error", "You must select unstaged file(s) to discard!", QMessageBox.Ok)

    def commit_files(self):
        message = self.ui.commit_lineEdit.text()
        if message == "":
            QMessageBox.critical(self, "Error", "You must write some commit message!", QMessageBox.Ok)
        else:
            if self.ui.amendCheckBox.isChecked():
                QMessageBox.information(self, "Commit", commit_amend(message), QMessageBox.Ok)
            else:
                QMessageBox.information(self, "Commit", commit(message), QMessageBox.Ok)
            self.view_repository()
            self.ui.commit_lineEdit.clear()

    def cherry_pick_menu(self, position):
        if self.ui.repositoryTableWidget.currentRow() > 0:
            menu = QMenu()
            cherry_pick_action = menu.addAction('Cherry pick') 
            QObject.connect(cherry_pick_action, SIGNAL('triggered()'), self.cherry_pick)
            menu.exec_(self.ui.repositoryTableWidget.mapToGlobal(position))

    def cherry_pick(self):
        self.cpdw = CherryPickDialogWrapper(self.ui.repositoryTableWidget.item(self.ui.repositoryTableWidget.currentRow(), 1).text(), self)
        self.cpdw.exec_()

    def stash(self):
        QMessageBox.information(self, "Stash", stash(), QMessageBox.Ok)
        self.view_repository()

    def stashes(self):
        sdw = StashesDialogWrapper(self)
        sdw.exec_()
        QObject.connect(sdw, SIGNAL('accepted()'), self.view_repository)