Ejemplo n.º 1
0
    def __init__(self,
                 model,
                 parent=None,
                 title=None,
                 multiselect=True,
                 syntax=True):
        QtGui.QDialog.__init__(self, parent)
        self.model = model
        if title:
            self.setWindowTitle(title)

        self.commit_list = QtGui.QListWidget()
        if multiselect:
            mode = QtGui.QAbstractItemView.ExtendedSelection
        else:
            mode = QtGui.QAbstractItemView.SingleSelection
        self.commit_list.setSelectionMode(mode)
        self.commit_list.setAlternatingRowColors(True)

        self.commit_text = DiffTextEdit(self, whitespace=False)

        self.label = QtGui.QLabel()
        self.label.setText(N_('Revision Expression:'))
        self.revision = QtGui.QLineEdit()
        self.revision.setReadOnly(True)

        self.select_button = QtGui.QPushButton(N_('Select'))
        self.select_button.setIcon(qtutils.apply_icon())
        self.select_button.setEnabled(False)
        self.select_button.setDefault(True)

        self.close_button = QtGui.QPushButton(N_('Close'))

        # Make the list widget slighty larger
        self.splitter = qtutils.splitter(Qt.Vertical, self.commit_list,
                                         self.commit_text)
        self.splitter.setSizes([100, 150])

        self.input_layout = qtutils.hbox(defs.no_margin, defs.spacing,
                                         self.label, self.revision,
                                         self.select_button, self.close_button)

        self.main_layout = qtutils.vbox(defs.margin, defs.margin,
                                        self.splitter, self.input_layout)
        self.setLayout(self.main_layout)

        self.connect(self.commit_list, SIGNAL('itemSelectionChanged()'),
                     self.commit_sha1_selected)

        self.connect(self.commit_list,
                     SIGNAL('itemDoubleClicked(QListWidgetItem*)'),
                     self.commit_sha1_double_clicked)

        qtutils.connect_button(self.select_button, self.accept)
        qtutils.connect_button(self.close_button, self.reject)

        self.resize(700, 420)
Ejemplo n.º 2
0
    def __init__(self, model,
                 parent=None, title=None, multiselect=True, syntax=True):
        QtGui.QDialog.__init__(self, parent)
        self.model = model
        if title:
            self.setWindowTitle(title)

        self.commit_list = QtGui.QListWidget()
        if multiselect:
            mode = QtGui.QAbstractItemView.ExtendedSelection
        else:
            mode = QtGui.QAbstractItemView.SingleSelection
        self.commit_list.setSelectionMode(mode)
        self.commit_list.setAlternatingRowColors(True)

        self.commit_text = DiffTextEdit(self, whitespace=False)

        self.label = QtGui.QLabel()
        self.label.setText(N_('Revision Expression:'))
        self.revision = QtGui.QLineEdit()
        self.revision.setReadOnly(True)

        self.select_button = QtGui.QPushButton(N_('Select'))
        self.select_button.setIcon(qtutils.apply_icon())
        self.select_button.setEnabled(False)
        self.select_button.setDefault(True)

        self.close_button = QtGui.QPushButton(N_('Close'))

        # Make the list widget slighty larger
        self.splitter = qtutils.splitter(Qt.Vertical,
                                         self.commit_list, self.commit_text)
        self.splitter.setSizes([100, 150])

        self.input_layout = qtutils.hbox(defs.no_margin, defs.spacing,
                                         self.label, self.revision,
                                         self.select_button, self.close_button)

        self.main_layout = qtutils.vbox(defs.margin, defs.margin,
                                        self.splitter, self.input_layout)
        self.setLayout(self.main_layout)

        self.connect(self.commit_list,
                     SIGNAL('itemSelectionChanged()'), self.commit_sha1_selected)

        self.connect(self.commit_list,
                     SIGNAL('itemDoubleClicked(QListWidgetItem*)'),
                     self.commit_sha1_double_clicked)

        qtutils.connect_button(self.select_button, self.accept)
        qtutils.connect_button(self.close_button, self.reject)

        self.resize(700, 420)
Ejemplo n.º 3
0
    def __init__(self, parent):
        standard.Dialog.__init__(self, parent)
        self.setAttribute(Qt.WA_MacMetalStyle)
        self.setWindowTitle(N_('Search'))

        self.mode_combo = QtGui.QComboBox()
        self.browse_button = create_toolbutton(icon=icons.folder(),
                                               tooltip=N_('Browse...'))
        self.query = QtGui.QLineEdit()

        self.start_date = QtGui.QDateEdit()
        self.start_date.setCurrentSection(QtGui.QDateTimeEdit.YearSection)
        self.start_date.setCalendarPopup(True)
        self.start_date.setDisplayFormat(N_('yyyy-MM-dd'))

        self.end_date = QtGui.QDateEdit()
        self.end_date.setCurrentSection(QtGui.QDateTimeEdit.YearSection)
        self.end_date.setCalendarPopup(True)
        self.end_date.setDisplayFormat(N_('yyyy-MM-dd'))

        icon = icons.search()
        self.search_button = qtutils.create_button(text=N_('Search'),
                                                   icon=icon,
                                                   default=True)

        self.max_count = QtGui.QSpinBox()
        self.max_count.setMinimum(5)
        self.max_count.setMaximum(9995)
        self.max_count.setSingleStep(5)
        self.max_count.setValue(500)

        self.commit_list = QtGui.QListWidget()
        self.commit_list.setMinimumSize(QtCore.QSize(1, 1))
        self.commit_list.setAlternatingRowColors(True)
        selection_mode = QtGui.QAbstractItemView.SingleSelection
        self.commit_list.setSelectionMode(selection_mode)

        self.commit_text = DiffTextEdit(self, whitespace=False)

        self.button_export = qtutils.create_button(text=N_('Export Patches'),
                                                   icon=icons.diff())

        self.button_cherrypick = qtutils.create_button(text=N_('Cherry Pick'),
                                                       icon=icons.save())
        self.button_close = qtutils.close_button()

        self.top_layout = qtutils.hbox(defs.no_margin, defs.button_spacing,
                                       self.query, self.start_date,
                                       self.end_date, self.browse_button,
                                       self.search_button, qtutils.STRETCH,
                                       self.mode_combo, self.max_count)

        self.splitter = qtutils.splitter(Qt.Vertical, self.commit_list,
                                         self.commit_text)

        self.bottom_layout = qtutils.hbox(defs.no_margin, defs.spacing,
                                          self.button_export,
                                          self.button_cherrypick,
                                          qtutils.STRETCH, self.button_close)

        self.main_layout = qtutils.vbox(defs.margin, defs.spacing,
                                        self.top_layout, self.splitter,
                                        self.bottom_layout)
        self.setLayout(self.main_layout)

        if self.parent():
            self.resize(self.parent().width(), self.parent().height())
        else:
            self.resize(720, 500)
Ejemplo n.º 4
0
    def __init__(self, parent):
        standard.Dialog.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_MacMetalStyle)
        self.setWindowTitle(N_('Search'))

        self.mode_combo = QtGui.QComboBox()
        self.browse_button = create_toolbutton(icon=dir_icon(),
                                               tooltip=N_('Browse...'))
        self.query = QtGui.QLineEdit()

        self.start_date = QtGui.QDateEdit()
        self.start_date.setCurrentSection(QtGui.QDateTimeEdit.YearSection)
        self.start_date.setCalendarPopup(True)
        self.start_date.setDisplayFormat(N_('yyyy-MM-dd'))

        self.end_date = QtGui.QDateEdit()
        self.end_date.setCurrentSection(QtGui.QDateTimeEdit.YearSection)
        self.end_date.setCalendarPopup(True)
        self.end_date.setDisplayFormat(N_('yyyy-MM-dd'))

        self.search_button = QtGui.QPushButton()
        self.search_button.setText(N_('Search'))
        self.search_button.setDefault(True)

        self.max_count = QtGui.QSpinBox()
        self.max_count.setMinimum(5)
        self.max_count.setMaximum(9995)
        self.max_count.setSingleStep(5)
        self.max_count.setValue(500)

        self.commit_list = QtGui.QListWidget()
        self.commit_list.setMinimumSize(QtCore.QSize(1, 1))
        self.commit_list.setAlternatingRowColors(True)
        self.commit_list.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)

        self.commit_text = DiffTextEdit(self, whitespace=False)

        self.button_export = QtGui.QPushButton()
        self.button_export.setText(N_('Export Patches'))

        self.button_cherrypick = QtGui.QPushButton()
        self.button_cherrypick.setText(N_('Cherry Pick'))

        self.button_close = QtGui.QPushButton()
        self.button_close.setText(N_('Close'))

        self.top_layout = QtGui.QHBoxLayout()
        self.top_layout.setMargin(0)
        self.top_layout.setSpacing(defs.button_spacing)

        self.top_layout.addWidget(self.query)
        self.top_layout.addWidget(self.start_date)
        self.top_layout.addWidget(self.end_date)
        self.top_layout.addWidget(self.browse_button)
        self.top_layout.addWidget(self.search_button)
        self.top_layout.addStretch()
        self.top_layout.addWidget(self.mode_combo)
        self.top_layout.addWidget(self.max_count)

        self.splitter = QtGui.QSplitter()
        self.splitter.setHandleWidth(defs.handle_width)
        self.splitter.setOrientation(QtCore.Qt.Vertical)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.addWidget(self.commit_list)
        self.splitter.addWidget(self.commit_text)

        self.bottom_layout = QtGui.QHBoxLayout()
        self.bottom_layout.setMargin(0)
        self.bottom_layout.setSpacing(defs.spacing)
        self.bottom_layout.addWidget(self.button_export)
        self.bottom_layout.addWidget(self.button_cherrypick)
        self.bottom_layout.addStretch()
        self.bottom_layout.addWidget(self.button_close)

        self.main_layout = QtGui.QVBoxLayout()
        self.main_layout.setMargin(defs.margin)
        self.main_layout.setSpacing(defs.spacing)
        self.main_layout.addLayout(self.top_layout)
        self.main_layout.addWidget(self.splitter)
        self.main_layout.addLayout(self.bottom_layout)
        self.setLayout(self.main_layout)

        if self.parent():
            self.resize(self.parent().width(), self.parent().height())
        else:
            self.resize(720, 500)
Ejemplo n.º 5
0
    def __init__(self, model, parent=None):
        Dialog.__init__(self, parent=parent)
        self.setAttribute(QtCore.Qt.WA_MacMetalStyle)
        self.model = model
        self.stashes = []
        self.revids = []
        self.names = []

        self.setWindowModality(QtCore.Qt.WindowModal)
        self.setWindowTitle(N_('Stash'))
        if parent:
            self.resize(parent.width(), 420)
        else:
            self.resize(700, 420)

        self.stash_list = QtGui.QListWidget(self)
        self.stash_text = DiffTextEdit(self)

        self.button_apply =\
            self.toolbutton(N_('Apply'),
                            N_('Apply the selected stash'),
                            qtutils.apply_icon())
        self.button_save =\
            self.toolbutton(N_('Save'),
                            N_('Save modified state to new stash'),
                            qtutils.save_icon())
        self.button_drop = \
            self.toolbutton(N_('Drop'),
                            N_('Drop the selected stash'),
                            qtutils.discard_icon())
        self.button_close = \
            self.pushbutton(N_('Close'),
                            N_('Close'), qtutils.close_icon())

        self.keep_index = QtGui.QCheckBox(self)
        self.keep_index.setText(N_('Keep Index'))
        self.keep_index.setChecked(True)

        # Arrange layouts
        self.main_layt = QtGui.QVBoxLayout()
        self.main_layt.setMargin(defs.margin)
        self.main_layt.setSpacing(defs.spacing)

        self.btn_layt = QtGui.QHBoxLayout()
        self.btn_layt.setMargin(0)
        self.btn_layt.setSpacing(defs.spacing)

        self.splitter = QtGui.QSplitter()
        self.splitter.setHandleWidth(defs.handle_width)
        self.splitter.setOrientation(QtCore.Qt.Horizontal)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.setStretchFactor(0, 1)
        self.splitter.setStretchFactor(1, 1)
        self.splitter.insertWidget(0, self.stash_list)
        self.splitter.insertWidget(1, self.stash_text)

        self.btn_layt.addWidget(self.button_save)
        self.btn_layt.addWidget(self.button_apply)
        self.btn_layt.addWidget(self.button_drop)
        self.btn_layt.addWidget(self.keep_index)
        self.btn_layt.addStretch()
        self.btn_layt.addWidget(self.button_close)

        self.main_layt.addWidget(self.splitter)
        self.main_layt.addLayout(self.btn_layt)
        self.setLayout(self.main_layt)

        self.splitter.setSizes([self.width() / 3, self.width() * 2 / 3])

        self.update_from_model()
        self.update_actions()

        self.setTabOrder(self.button_save, self.button_apply)
        self.setTabOrder(self.button_apply, self.button_drop)
        self.setTabOrder(self.button_drop, self.keep_index)
        self.setTabOrder(self.keep_index, self.button_close)

        self.connect(self.stash_list, SIGNAL('itemSelectionChanged()'),
                     self.item_selected)

        qtutils.connect_button(self.button_apply, self.stash_apply)
        qtutils.connect_button(self.button_save, self.stash_save)
        qtutils.connect_button(self.button_drop, self.stash_drop)
        qtutils.connect_button(self.button_close, self.close)
Ejemplo n.º 6
0
class StashView(Dialog):
    def __init__(self, model, parent=None):
        Dialog.__init__(self, parent=parent)
        self.setAttribute(QtCore.Qt.WA_MacMetalStyle)
        self.model = model
        self.stashes = []
        self.revids = []
        self.names = []

        self.setWindowModality(QtCore.Qt.WindowModal)
        self.setWindowTitle(N_('Stash'))
        if parent:
            self.resize(parent.width(), 420)
        else:
            self.resize(700, 420)

        self.stash_list = QtGui.QListWidget(self)
        self.stash_text = DiffTextEdit(self)

        self.button_apply =\
            self.toolbutton(N_('Apply'),
                            N_('Apply the selected stash'),
                            qtutils.apply_icon())
        self.button_save =\
            self.toolbutton(N_('Save'),
                            N_('Save modified state to new stash'),
                            qtutils.save_icon())
        self.button_drop = \
            self.toolbutton(N_('Drop'),
                            N_('Drop the selected stash'),
                            qtutils.discard_icon())
        self.button_close = \
            self.pushbutton(N_('Close'),
                            N_('Close'), qtutils.close_icon())

        self.keep_index = QtGui.QCheckBox(self)
        self.keep_index.setText(N_('Keep Index'))
        self.keep_index.setChecked(True)

        # Arrange layouts
        self.main_layt = QtGui.QVBoxLayout()
        self.main_layt.setMargin(defs.margin)
        self.main_layt.setSpacing(defs.spacing)

        self.btn_layt = QtGui.QHBoxLayout()
        self.btn_layt.setMargin(0)
        self.btn_layt.setSpacing(defs.spacing)

        self.splitter = QtGui.QSplitter()
        self.splitter.setHandleWidth(defs.handle_width)
        self.splitter.setOrientation(QtCore.Qt.Horizontal)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.setStretchFactor(0, 1)
        self.splitter.setStretchFactor(1, 1)
        self.splitter.insertWidget(0, self.stash_list)
        self.splitter.insertWidget(1, self.stash_text)

        self.btn_layt.addWidget(self.button_save)
        self.btn_layt.addWidget(self.button_apply)
        self.btn_layt.addWidget(self.button_drop)
        self.btn_layt.addWidget(self.keep_index)
        self.btn_layt.addStretch()
        self.btn_layt.addWidget(self.button_close)

        self.main_layt.addWidget(self.splitter)
        self.main_layt.addLayout(self.btn_layt)
        self.setLayout(self.main_layt)

        self.splitter.setSizes([self.width() / 3, self.width() * 2 / 3])

        self.update_from_model()
        self.update_actions()

        self.setTabOrder(self.button_save, self.button_apply)
        self.setTabOrder(self.button_apply, self.button_drop)
        self.setTabOrder(self.button_drop, self.keep_index)
        self.setTabOrder(self.keep_index, self.button_close)

        self.connect(self.stash_list, SIGNAL('itemSelectionChanged()'),
                     self.item_selected)

        qtutils.connect_button(self.button_apply, self.stash_apply)
        qtutils.connect_button(self.button_save, self.stash_save)
        qtutils.connect_button(self.button_drop, self.stash_drop)
        qtutils.connect_button(self.button_close, self.close)

    def close(self):
        self.accept()
        cmds.do(cmds.Rescan)

    def toolbutton(self, text, tooltip, icon):
        return qtutils.create_toolbutton(text=text, tooltip=tooltip, icon=icon)

    def pushbutton(self, text, tooltip, icon):
        btn = QtGui.QPushButton(self)
        btn.setText(text)
        btn.setToolTip(tooltip)
        btn.setIcon(icon)
        return btn

    def selected_stash(self):
        """Returns the stash name of the currently selected stash
        """
        list_widget = self.stash_list
        stash_list = self.revids
        return qtutils.selected_item(list_widget, stash_list)

    def selected_name(self):
        list_widget = self.stash_list
        stash_list = self.names
        return qtutils.selected_item(list_widget, stash_list)

    def item_selected(self):
        """Shows the current stash in the main view."""
        self.update_actions()
        selection = self.selected_stash()
        if not selection:
            return
        diff_text = self.model.stash_diff(selection)
        self.stash_text.setPlainText(diff_text)

    def update_actions(self):
        has_changes = self.model.has_stashable_changes()
        has_stash = bool(self.selected_stash())
        self.button_save.setEnabled(has_changes)
        self.button_apply.setEnabled(has_stash)
        self.button_drop.setEnabled(has_stash)

    def update_from_model(self):
        """Initiates git queries on the model and updates the view
        """
        stashes, revids, names = self.model.stash_info()
        self.stashes = stashes
        self.revids = revids
        self.names = names

        self.stash_list.clear()
        self.stash_list.addItems(self.stashes)

    def stash_apply(self):
        """Applies the currently selected stash
        """
        selection = self.selected_stash()
        if not selection:
            return
        index = self.keep_index.isChecked()
        cmds.do(ApplyStash, selection, index)
        self.accept()
        cmds.do(cmds.Rescan)

    def stash_save(self):
        """Saves the worktree in a stash

        This prompts the user for a stash name and creates
        a git stash named accordingly.

        """
        stash_name, ok = qtutils.prompt(N_('Save Stash'),
                                        N_('Enter a name for the stash'))
        if not ok or not stash_name:
            return
        # Sanitize the stash name
        stash_name = utils.sanitize(stash_name)
        if stash_name in self.names:
            qtutils.critical(
                N_('Error: Stash exists'),
                N_('A stash named "%s" already exists') % stash_name)
            return

        keep_index = self.keep_index.isChecked()
        cmds.do(SaveStash, stash_name, keep_index)
        self.accept()
        cmds.do(cmds.Rescan)

    def stash_drop(self):
        """Drops the currently selected stash
        """
        selection = self.selected_stash()
        name = self.selected_name()
        if not selection:
            return
        if not qtutils.confirm(
                N_('Drop Stash?'),
                N_('Recovering a dropped stash is not possible.'),
                N_('Drop the "%s" stash?') % name,
                N_('Drop Stash'),
                default=True,
                icon=qtutils.discard_icon()):
            return
        cmds.do(DropStash, selection)
        self.update_from_model()
        self.stash_text.setPlainText('')
Ejemplo n.º 7
0
class SelectCommitsDialog(QtGui.QDialog):
    def __init__(self, model,
                 parent=None, title=None, multiselect=True, syntax=True):
        QtGui.QDialog.__init__(self, parent)
        self.model = model
        if title:
            self.setWindowTitle(title)

        self.commit_list = QtGui.QListWidget()
        if multiselect:
            mode = QtGui.QAbstractItemView.ExtendedSelection
        else:
            mode = QtGui.QAbstractItemView.SingleSelection
        self.commit_list.setSelectionMode(mode)
        self.commit_list.setAlternatingRowColors(True)

        self.commit_text = DiffTextEdit(self, whitespace=False)

        self.label = QtGui.QLabel()
        self.label.setText(N_('Revision Expression:'))
        self.revision = QtGui.QLineEdit()
        self.revision.setReadOnly(True)

        self.select_button = QtGui.QPushButton(N_('Select'))
        self.select_button.setIcon(qtutils.apply_icon())
        self.select_button.setEnabled(False)
        self.select_button.setDefault(True)

        self.close_button = QtGui.QPushButton(N_('Close'))

        # Make the list widget slighty larger
        self.splitter = QtGui.QSplitter()
        self.splitter.setOrientation(QtCore.Qt.Vertical)
        self.splitter.setHandleWidth(defs.handle_width)
        self.splitter.setSizes([100, 150])
        self.splitter.addWidget(self.commit_list)
        self.splitter.addWidget(self.commit_text)

        self.input_layout = QtGui.QHBoxLayout()
        self.input_layout.setMargin(0)
        self.input_layout.setSpacing(defs.spacing)
        self.input_layout.addWidget(self.label)
        self.input_layout.addWidget(self.revision)
        self.input_layout.addWidget(self.select_button)
        self.input_layout.addWidget(self.close_button)

        self.main_layout = QtGui.QVBoxLayout()
        self.main_layout.setMargin(defs.margin)
        self.main_layout.setSpacing(defs.margin)
        self.main_layout.addWidget(self.splitter)
        self.main_layout.addLayout(self.input_layout)
        self.setLayout(self.main_layout)

        self.connect(self.commit_list,
                     SIGNAL('itemSelectionChanged()'), self.commit_sha1_selected)

        qtutils.connect_button(self.select_button, self.accept)
        qtutils.connect_button(self.close_button, self.reject)

        #self.setTabOrder(self.commit_list, self.commit_text)
        #self.setTabOrder(self.commit_text, self.revision)
        #self.setTabOrder(self.revision, self.select_button)
        #self.setTabOrder(self.select_button, self.close_button)
        #self.setTabOrder(self.close_button, self.commit_list)

        self.resize(700, 420)

    def select_commits(self):
        summaries = self.model.summaries
        if not summaries:
            msg = N_('No commits exist in this branch.')
            Interaction.log(msg)
            return []
        qtutils.set_items(self.commit_list, summaries)
        self.show()
        if self.exec_() != QtGui.QDialog.Accepted:
            return []
        revs = self.model.revisions
        return qtutils.selection_list(self.commit_list, revs)

    def commit_sha1_selected(self):
        row, selected = qtutils.selected_row(self.commit_list)
        self.select_button.setEnabled(selected)
        if not selected:
            self.commit_text.setText('')
            self.revision.setText('')
            return
        # Get the sha1 and put it in the revision line
        sha1 = self.model.revision_sha1(row)
        self.revision.setText(sha1)
        self.revision.selectAll()

        # Display the sha1's commit
        commit_diff = gitcmds.commit_diff(sha1)
        self.commit_text.setText(commit_diff)
Ejemplo n.º 8
0
    def __init__(self, model, parent=None):
        Dialog.__init__(self, parent=parent)
        self.model = model
        self.stashes = []
        self.revids = []
        self.names = []

        self.setWindowTitle(N_('Stash'))
        self.setAttribute(QtCore.Qt.WA_MacMetalStyle)
        if parent is not None:
            self.setWindowModality(QtCore.Qt.WindowModal)
            self.resize(parent.width(), 420)
        else:
            self.resize(700, 420)

        self.stash_list = QtGui.QListWidget(self)
        self.stash_text = DiffTextEdit(self)

        self.button_apply =\
            self.toolbutton(N_('Apply'),
                            N_('Apply the selected stash'),
                            qtutils.apply_icon())
        self.button_save =\
            self.toolbutton(N_('Save'),
                            N_('Save modified state to new stash'),
                            qtutils.save_icon())
        self.button_drop = \
            self.toolbutton(N_('Drop'),
                            N_('Drop the selected stash'),
                            qtutils.discard_icon())
        self.button_close = \
            self.pushbutton(N_('Close'),
                            N_('Close'), qtutils.close_icon())

        self.keep_index = QtGui.QCheckBox(self)
        self.keep_index.setText(N_('Keep Index'))
        self.keep_index.setChecked(True)

        # Arrange layouts
        self.splitter = qtutils.splitter(Qt.Horizontal, self.stash_list,
                                         self.stash_text)

        self.btn_layt = qtutils.hbox(defs.no_margin, defs.spacing,
                                     self.button_save, self.button_apply,
                                     self.button_drop, self.keep_index,
                                     qtutils.STRETCH, self.button_close)

        self.main_layt = qtutils.vbox(defs.margin, defs.spacing, self.splitter,
                                      self.btn_layt)
        self.setLayout(self.main_layt)

        self.splitter.setSizes([self.width() // 3, self.width() * 2 // 3])

        self.update_from_model()
        self.update_actions()

        self.setTabOrder(self.button_save, self.button_apply)
        self.setTabOrder(self.button_apply, self.button_drop)
        self.setTabOrder(self.button_drop, self.keep_index)
        self.setTabOrder(self.keep_index, self.button_close)

        self.connect(self.stash_list, SIGNAL('itemSelectionChanged()'),
                     self.item_selected)

        qtutils.connect_button(self.button_apply, self.stash_apply)
        qtutils.connect_button(self.button_save, self.stash_save)
        qtutils.connect_button(self.button_drop, self.stash_drop)
        qtutils.connect_button(self.button_close, self.close)
Ejemplo n.º 9
0
    def __init__(self, parent):
        super(SearchWidget, self).__init__(parent)
        self.setAttribute(QtCore.Qt.WA_MacMetalStyle)
        self.setWindowTitle(self.tr('Search'))

        self.mode_combo = QtGui.QComboBox()
        self.browse_button = create_toolbutton(icon=dir_icon(),
                                               tooltip='Browse...')
        self.query = QtGui.QLineEdit()

        self.start_date = QtGui.QDateEdit()
        self.start_date.setCurrentSection(QtGui.QDateTimeEdit.YearSection)
        self.start_date.setCalendarPopup(True)
        self.start_date.setDisplayFormat(self.tr('yyyy-MM-dd'))

        self.end_date = QtGui.QDateEdit()
        self.end_date.setCurrentSection(QtGui.QDateTimeEdit.YearSection)
        self.end_date.setCalendarPopup(True)
        self.end_date.setDisplayFormat(self.tr('yyyy-MM-dd'))

        self.search_button = QtGui.QPushButton()
        self.search_button.setText(self.tr('Search'))
        self.search_button.setDefault(True)

        self.max_count = QtGui.QSpinBox()
        self.max_count.setMinimum(5)
        self.max_count.setMaximum(9995)
        self.max_count.setSingleStep(5)
        self.max_count.setValue(500)

        self.commit_list = QtGui.QListWidget()
        self.commit_list.setMinimumSize(QtCore.QSize(1, 1))
        self.commit_list.setAlternatingRowColors(True)
        self.commit_list.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)

        self.commit_text = DiffTextEdit(self, whitespace=False)
        self.commit_text.setTabChangesFocus(True)
        self.commit_text.setReadOnly(True)

        self.button_export = QtGui.QPushButton()
        self.button_export.setText(self.tr('Export Patches'))

        self.button_cherrypick = QtGui.QPushButton()
        self.button_cherrypick.setText(self.tr('Cherry Pick'))

        self.button_close = QtGui.QPushButton()
        self.button_close.setText(self.tr('Close'))

        self.top_layout = QtGui.QHBoxLayout()
        self.top_layout.setMargin(0)
        self.top_layout.setSpacing(defs.button_spacing)

        self.top_layout.addWidget(self.query)
        self.top_layout.addWidget(self.start_date)
        self.top_layout.addWidget(self.end_date)
        self.top_layout.addWidget(self.browse_button)
        self.top_layout.addWidget(self.search_button)
        self.top_layout.addStretch()
        self.top_layout.addWidget(self.mode_combo)
        self.top_layout.addWidget(self.max_count)

        self.splitter = QtGui.QSplitter()
        self.splitter.setHandleWidth(defs.handle_width)
        self.splitter.setOrientation(QtCore.Qt.Vertical)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.addWidget(self.commit_list)
        self.splitter.addWidget(self.commit_text)

        self.bottom_layout = QtGui.QHBoxLayout()
        self.bottom_layout.setMargin(0)
        self.bottom_layout.setSpacing(defs.spacing)
        self.bottom_layout.addWidget(self.button_export)
        self.bottom_layout.addWidget(self.button_cherrypick)
        self.bottom_layout.addStretch()
        self.bottom_layout.addWidget(self.button_close)

        self.main_layout = QtGui.QVBoxLayout()
        self.main_layout.setMargin(defs.margin)
        self.main_layout.setSpacing(defs.spacing)
        self.main_layout.addLayout(self.top_layout)
        self.main_layout.addWidget(self.splitter)
        self.main_layout.addLayout(self.bottom_layout)
        self.setLayout(self.main_layout)

        if self.parent():
            self.resize(self.parent().width(), self.parent().height())
        else:
            self.resize(720, 500)
Ejemplo n.º 10
0
class SelectCommitsDialog(QtGui.QDialog):
    def __init__(self, model,
                 parent=None, title=None, multiselect=True, syntax=True):
        QtGui.QDialog.__init__(self, parent)
        self.model = model
        if title:
            self.setWindowTitle(title)

        self.commit_list = QtGui.QListWidget()
        if multiselect:
            mode = QtGui.QAbstractItemView.ExtendedSelection
        else:
            mode = QtGui.QAbstractItemView.SingleSelection
        self.commit_list.setSelectionMode(mode)
        self.commit_list.setAlternatingRowColors(True)

        self.commit_text = DiffTextEdit(self, whitespace=False)

        self.label = QtGui.QLabel()
        self.label.setText(N_('Revision Expression:'))
        self.revision = QtGui.QLineEdit()
        self.revision.setReadOnly(True)

        self.select_button = QtGui.QPushButton(N_('Select'))
        self.select_button.setIcon(qtutils.apply_icon())
        self.select_button.setEnabled(False)
        self.select_button.setDefault(True)

        self.close_button = QtGui.QPushButton(N_('Close'))

        # Make the list widget slighty larger
        self.splitter = qtutils.splitter(Qt.Vertical,
                                         self.commit_list, self.commit_text)
        self.splitter.setSizes([100, 150])

        self.input_layout = qtutils.hbox(defs.no_margin, defs.spacing,
                                         self.label, self.revision,
                                         self.select_button, self.close_button)

        self.main_layout = qtutils.vbox(defs.margin, defs.margin,
                                        self.splitter, self.input_layout)
        self.setLayout(self.main_layout)

        self.connect(self.commit_list,
                     SIGNAL('itemSelectionChanged()'), self.commit_sha1_selected)

        qtutils.connect_button(self.select_button, self.accept)
        qtutils.connect_button(self.close_button, self.reject)

        self.resize(700, 420)

    def select_commits(self):
        summaries = self.model.summaries
        if not summaries:
            msg = N_('No commits exist in this branch.')
            Interaction.log(msg)
            return []
        qtutils.set_items(self.commit_list, summaries)
        self.show()
        if self.exec_() != QtGui.QDialog.Accepted:
            return []
        revs = self.model.revisions
        return qtutils.selected_items(self.commit_list, revs)

    def commit_sha1_selected(self):
        sha1  = qtutils.selected_item(self.commit_list, self.model.revisions)
        selected = (sha1 is not None)
        self.select_button.setEnabled(selected)
        if not selected:
            self.commit_text.setText('')
            self.revision.setText('')
            return
        self.revision.setText(sha1)
        self.revision.selectAll()

        # Display the sha1's commit
        commit_diff = gitcmds.commit_diff(sha1)
        self.commit_text.setText(commit_diff)
Ejemplo n.º 11
0
    def __init__(self, model, parent):
        standard.MainWindow.__init__(self, parent)
        # Default size; this is thrown out when save/restore is used
        self.resize(987, 610)
        self.model = model
        self.prefs_model = prefs_model = PreferencesModel()

        # Internal field used by import/export_state().
        # Change this whenever dockwidgets are removed.
        self.widget_version = 1

        # Keeps track of merge messages we've seen
        self.merge_message_hash = ''

        self.setAcceptDrops(True)

        # Dockwidget options
        qtcompat.set_common_dock_options(self)

        self.classic_dockable = gitcfg.instance().get('cola.classicdockable')

        if self.classic_dockable:
            self.classicdockwidget = create_dock('Cola Classic', self)
            self.classicwidget = classic_widget(self)
            self.classicdockwidget.setWidget(self.classicwidget)

        # "Actions" widget
        self.actiondockwidget = create_dock('Actions', self)
        self.actiondockwidgetcontents = qt.QFlowLayoutWidget(self)
        layout = self.actiondockwidgetcontents.layout()
        self.stage_button = create_button('Stage', layout)
        self.unstage_button = create_button('Unstage', layout)
        self.rescan_button = create_button('Rescan', layout)
        self.fetch_button = create_button('Fetch...', layout)
        self.push_button = create_button('Push...', layout)
        self.pull_button = create_button('Pull...', layout)
        self.stash_button = create_button('Stash...', layout)
        self.alt_button = create_button('Exit Diff Mode', layout)
        self.alt_button.hide()
        layout.addStretch()
        self.actiondockwidget.setWidget(self.actiondockwidgetcontents)

        # "Repository Status" widget
        self.statusdockwidget = create_dock('Repository Status', self)
        self.statusdockwidget.setWidget(StatusWidget(self))

        # "Commit Message Editor" widget
        self.commitdockwidget = create_dock('Commit Message Editor', self)
        self.commitmsgeditor = CommitMessageEditor(model, self)
        relay_signal(self, self.commitmsgeditor, SIGNAL(signals.amend_mode))
        relay_signal(self, self.commitmsgeditor, SIGNAL(signals.signoff))
        relay_signal(self, self.commitmsgeditor,
                     SIGNAL(signals.load_previous_message))
        self.commitdockwidget.setWidget(self.commitmsgeditor)

        # "Command Output" widget
        logwidget = qtutils.logger()
        logwidget.setFont(diff_font())
        self.logdockwidget = create_dock('Command Output', self)
        self.logdockwidget.setWidget(logwidget)

        # "Diff Viewer" widget
        self.diffdockwidget = create_dock('Diff Viewer', self)
        self.diff_viewer = DiffTextEdit(self.diffdockwidget)
        self.diffdockwidget.setWidget(self.diff_viewer)

        # All Actions
        self.menu_unstage_all = add_action(self,
                'Unstage All', emit(self, signals.unstage_all))
        self.menu_unstage_all.setIcon(qtutils.icon('remove.svg'))

        self.menu_unstage_selected = add_action(self,
                'Unstage From Commit', emit(self, signals.unstage_selected))
        self.menu_unstage_selected.setIcon(qtutils.icon('remove.svg'))

        self.menu_show_diffstat = add_action(self,
                'Diffstat', emit(self, signals.diffstat), 'Ctrl+D')

        self.menu_stage_modified = add_action(self,
                'Stage Changed Files To Commit',
                emit(self, signals.stage_modified), 'Alt+A')
        self.menu_stage_modified.setIcon(qtutils.icon('add.svg'))

        self.menu_stage_untracked = add_action(self,
                'Stage All Untracked', emit(self, signals.stage_untracked), 'Alt+U')
        self.menu_stage_untracked.setIcon(qtutils.icon('add.svg'))

        self.menu_export_patches = add_action(self,
                'Export Patches...', guicmds.export_patches, 'Ctrl+E')
        self.menu_preferences = add_action(self,
                'Preferences', lambda: preferences(model=prefs_model),
                QtGui.QKeySequence.Preferences, 'Ctrl+O')

        self.menu_rescan = add_action(self,
                'Rescan', emit(self, signals.rescan), 'Ctrl+R')
        self.menu_rescan.setIcon(qtutils.reload_icon())

        self.menu_cherry_pick = add_action(self,
                'Cherry-Pick...', guicmds.cherry_pick, 'Ctrl+P')

        self.menu_load_commitmsg = add_action(self,
                'Load Commit Message...', guicmds.load_commitmsg)

        self.menu_quit = add_action(self,
                'Quit', self.close, 'Ctrl+Q')
        self.menu_manage_bookmarks = add_action(self,
                'Bookmarks...', manage_bookmarks)
        self.menu_grep = add_action(self,
                'Grep', guicmds.grep)
        self.menu_merge_local = add_action(self,
                'Merge...', merge.local_merge)

        self.menu_merge_abort = add_action(self,
                'Abort Merge...', merge.abort_merge)

        self.menu_fetch = add_action(self,
                'Fetch...', guicmds.fetch)
        self.menu_push = add_action(self,
                'Push...', guicmds.push)
        self.menu_pull = add_action(self,
                'Pull...', guicmds.pull)

        self.menu_open_repo = add_action(self,
                'Open...', guicmds.open_repo)
        self.menu_open_repo.setIcon(qtutils.open_icon())

        self.menu_stash = add_action(self,
                'Stash...', stash.stash, 'Alt+Shift+S')
        self.menu_diff_branch = add_action(self,
                'Apply Changes From Branch...', guicmds.diff_branch)
        self.menu_branch_compare = add_action(self,
                'Branches...', compare.branch_compare)

        self.menu_clone_repo = add_action(self,
                'Clone...', guicmds.clone_repo)
        self.menu_clone_repo.setIcon(qtutils.git_icon())

        self.menu_help_docs = add_action(self,
                'Documentation',
                lambda: self.model.git.web__browse(resources.html_docs()),
                QtGui.QKeySequence.HelpContents)
        self.menu_commit_compare = add_action(self,
                'Commits...', compare.compare)
        self.menu_commit_compare_file = add_action(self,
                'Commits Touching File...', compare.compare_file)
        self.menu_visualize_current = add_action(self,
                'Visualize Current Branch...',
                emit(self, signals.visualize_current))
        self.menu_visualize_all = add_action(self,
                'Visualize All Branches...',
                emit(self, signals.visualize_all))
        self.menu_search_commits = add_action(self,
                'Search...', search.search)
        self.menu_browse_branch = add_action(self,
                'Browse Current Branch...', guicmds.browse_current)
        self.menu_browse_other_branch = add_action(self,
                'Browse Other Branch...', guicmds.browse_other)
        self.menu_load_commitmsg_template = add_action(self,
                'Get Commit Message Template',
                emit(self, signals.load_commit_template))
        self.menu_help_about = add_action(self,
                'About', launch_about_dialog)
        self.menu_branch_diff = add_action(self,
                'SHA-1...', guicmds.branch_diff)
        self.menu_diff_expression = add_action(self,
                'Expression...', guicmds.diff_expression)
        self.menu_create_tag = add_action(self,
                'Create Tag...', createtag.create_tag)

        self.menu_create_branch = add_action(self,
                'Create...', create_new_branch, 'Ctrl+B')

        self.menu_delete_branch = add_action(self,
                'Delete...', guicmds.branch_delete)

        self.menu_checkout_branch = add_action(self,
                'Checkout...', guicmds.checkout_branch, 'Alt+B')
        self.menu_rebase_branch = add_action(self,
                'Rebase...', guicmds.rebase)
        self.menu_branch_review = add_action(self,
                'Review...', guicmds.review_branch)

        self.menu_classic = add_action(self,
                'Cola Classic...', cola_classic)
        self.menu_classic.setIcon(qtutils.git_icon())

        self.menu_dag = add_action(self,
                'DAG...', lambda: git_dag(self.model))
        self.menu_dag.setIcon(qtutils.git_icon())

        # Create the application menu
        self.menubar = QtGui.QMenuBar(self)

        # File Menu
        self.file_menu = create_menu('&File', self.menubar)
        self.file_menu.addAction(self.menu_preferences)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_open_repo)
        self.file_menu.addAction(self.menu_clone_repo)
        self.file_menu.addAction(self.menu_manage_bookmarks)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_rescan)
        self.file_menu.addSeparator()
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_load_commitmsg)
        self.file_menu.addAction(self.menu_load_commitmsg_template)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_quit)
        # Add to menubar
        self.menubar.addAction(self.file_menu.menuAction())

        # Commit Menu
        self.commit_menu = create_menu('Co&mmit', self.menubar)
        self.commit_menu.setTitle(tr('Commit@@verb'))
        self.commit_menu.addAction(self.menu_stage_modified)
        self.commit_menu.addAction(self.menu_stage_untracked)
        self.commit_menu.addSeparator()
        self.commit_menu.addAction(self.menu_unstage_all)
        self.commit_menu.addAction(self.menu_unstage_selected)
        self.commit_menu.addSeparator()
        self.commit_menu.addAction(self.menu_search_commits)
        # Add to menubar
        self.menubar.addAction(self.commit_menu.menuAction())

        # Branch Menu
        self.branch_menu = create_menu('B&ranch', self.menubar)
        self.branch_menu.addAction(self.menu_branch_review)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_create_branch)
        self.branch_menu.addAction(self.menu_checkout_branch)
        self.branch_menu.addAction(self.menu_rebase_branch)
        self.branch_menu.addAction(self.menu_delete_branch)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_browse_branch)
        self.branch_menu.addAction(self.menu_browse_other_branch)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_visualize_current)
        self.branch_menu.addAction(self.menu_visualize_all)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_diff_branch)
        # Add to menubar
        self.menubar.addAction(self.branch_menu.menuAction())

        # Actions menu
        self.actions_menu = create_menu('Act&ions', self.menubar)
        self.actions_menu.addAction(self.menu_merge_local)
        self.actions_menu.addAction(self.menu_stash)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_fetch)
        self.actions_menu.addAction(self.menu_push)
        self.actions_menu.addAction(self.menu_pull)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_create_tag)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_export_patches)
        self.actions_menu.addAction(self.menu_cherry_pick)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_merge_abort)
        self.actions_menu.addAction(self.menu_grep)
        # Add to menubar
        self.menubar.addAction(self.actions_menu.menuAction())

        # Diff Menu
        self.diff_menu = create_menu('&Diff', self.menubar)
        self.diff_menu.addAction(self.menu_branch_diff)
        self.diff_menu.addAction(self.menu_diff_expression)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.menu_branch_compare)
        self.diff_menu.addAction(self.menu_commit_compare)
        self.diff_menu.addAction(self.menu_commit_compare_file)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.menu_show_diffstat)
        # Add to menubar
        self.menubar.addAction(self.diff_menu.menuAction())

        # Tools Menu
        self.tools_menu = create_menu('&Tools', self.menubar)
        self.tools_menu.addAction(self.menu_classic)
        self.tools_menu.addAction(self.menu_dag)
        self.tools_menu.addSeparator()
        if self.classic_dockable:
            self.tools_menu.addAction(self.classicdockwidget.toggleViewAction())
        self.tools_menu.addAction(self.diffdockwidget.toggleViewAction())
        self.tools_menu.addAction(self.actiondockwidget.toggleViewAction())
        self.tools_menu.addAction(self.commitdockwidget.toggleViewAction())
        self.tools_menu.addAction(self.statusdockwidget.toggleViewAction())
        self.tools_menu.addAction(self.logdockwidget.toggleViewAction())
        self.menubar.addAction(self.tools_menu.menuAction())

        # Help Menu
        self.help_menu = create_menu('&Help', self.menubar)
        self.help_menu.addAction(self.menu_help_docs)
        self.help_menu.addAction(self.menu_help_about)
        # Add to menubar
        self.menubar.addAction(self.help_menu.menuAction())

        # Set main menu
        self.setMenuBar(self.menubar)

        # Arrange dock widgets
        top = Qt.TopDockWidgetArea
        bottom = Qt.BottomDockWidgetArea

        self.addDockWidget(top, self.commitdockwidget)
        if self.classic_dockable:
            self.addDockWidget(top, self.classicdockwidget)
        self.addDockWidget(top, self.statusdockwidget)
        self.addDockWidget(top, self.actiondockwidget)
        self.addDockWidget(bottom, self.logdockwidget)
        if self.classic_dockable:
            self.tabifyDockWidget(self.classicdockwidget, self.commitdockwidget)
        self.tabifyDockWidget(self.logdockwidget, self.diffdockwidget)

        # Listen for model notifications
        model.add_message_observer(model.message_mode_changed,
                                   self._mode_changed)

        model.add_message_observer(model.message_updated,
                                   self._update_view)

        prefs_model.add_message_observer(prefs_model.message_config_updated,
                                         self._config_updated)


        # Add button callbacks
        connect_button(self.rescan_button, emit(self, signals.rescan))
        connect_button(self.alt_button, emit(self, signals.reset_mode))
        connect_button(self.fetch_button, guicmds.fetch)
        connect_button(self.push_button, guicmds.push)
        connect_button(self.pull_button, guicmds.pull)
        connect_button(self.stash_button, stash.stash)

        connect_button(self.stage_button, self.stage)
        connect_button(self.unstage_button, self.unstage)

        self.connect(self, SIGNAL('update'), self._update_callback)
        self.connect(self, SIGNAL('apply_state'), self.apply_state)
        self.connect(self, SIGNAL('install_config_actions'),
                     self._install_config_actions)

        # Install .git-config-defined actions
        self._config_task = None
        self.install_config_actions()

        # Restore saved settings
        self._gui_state_task = None
        self._load_gui_state()

        log(0, self.model.git_version + '\ncola version ' + version.version())
Ejemplo n.º 12
0
class MainView(standard.MainWindow):
    def __init__(self, model, parent):
        standard.MainWindow.__init__(self, parent)
        # Default size; this is thrown out when save/restore is used
        self.resize(987, 610)
        self.model = model
        self.prefs_model = prefs_model = PreferencesModel()

        # Internal field used by import/export_state().
        # Change this whenever dockwidgets are removed.
        self.widget_version = 1

        # Keeps track of merge messages we've seen
        self.merge_message_hash = ''

        self.setAcceptDrops(True)

        # Dockwidget options
        qtcompat.set_common_dock_options(self)

        self.classic_dockable = gitcfg.instance().get('cola.classicdockable')

        if self.classic_dockable:
            self.classicdockwidget = create_dock('Cola Classic', self)
            self.classicwidget = classic_widget(self)
            self.classicdockwidget.setWidget(self.classicwidget)

        # "Actions" widget
        self.actiondockwidget = create_dock('Actions', self)
        self.actiondockwidgetcontents = qt.QFlowLayoutWidget(self)
        layout = self.actiondockwidgetcontents.layout()
        self.stage_button = create_button('Stage', layout)
        self.unstage_button = create_button('Unstage', layout)
        self.rescan_button = create_button('Rescan', layout)
        self.fetch_button = create_button('Fetch...', layout)
        self.push_button = create_button('Push...', layout)
        self.pull_button = create_button('Pull...', layout)
        self.stash_button = create_button('Stash...', layout)
        self.alt_button = create_button('Exit Diff Mode', layout)
        self.alt_button.hide()
        layout.addStretch()
        self.actiondockwidget.setWidget(self.actiondockwidgetcontents)

        # "Repository Status" widget
        self.statusdockwidget = create_dock('Repository Status', self)
        self.statusdockwidget.setWidget(StatusWidget(self))

        # "Commit Message Editor" widget
        self.commitdockwidget = create_dock('Commit Message Editor', self)
        self.commitmsgeditor = CommitMessageEditor(model, self)
        relay_signal(self, self.commitmsgeditor, SIGNAL(signals.amend_mode))
        relay_signal(self, self.commitmsgeditor, SIGNAL(signals.signoff))
        relay_signal(self, self.commitmsgeditor,
                     SIGNAL(signals.load_previous_message))
        self.commitdockwidget.setWidget(self.commitmsgeditor)

        # "Command Output" widget
        logwidget = qtutils.logger()
        logwidget.setFont(diff_font())
        self.logdockwidget = create_dock('Command Output', self)
        self.logdockwidget.setWidget(logwidget)

        # "Diff Viewer" widget
        self.diffdockwidget = create_dock('Diff Viewer', self)
        self.diff_viewer = DiffTextEdit(self.diffdockwidget)
        self.diffdockwidget.setWidget(self.diff_viewer)

        # All Actions
        self.menu_unstage_all = add_action(self,
                'Unstage All', emit(self, signals.unstage_all))
        self.menu_unstage_all.setIcon(qtutils.icon('remove.svg'))

        self.menu_unstage_selected = add_action(self,
                'Unstage From Commit', emit(self, signals.unstage_selected))
        self.menu_unstage_selected.setIcon(qtutils.icon('remove.svg'))

        self.menu_show_diffstat = add_action(self,
                'Diffstat', emit(self, signals.diffstat), 'Ctrl+D')

        self.menu_stage_modified = add_action(self,
                'Stage Changed Files To Commit',
                emit(self, signals.stage_modified), 'Alt+A')
        self.menu_stage_modified.setIcon(qtutils.icon('add.svg'))

        self.menu_stage_untracked = add_action(self,
                'Stage All Untracked', emit(self, signals.stage_untracked), 'Alt+U')
        self.menu_stage_untracked.setIcon(qtutils.icon('add.svg'))

        self.menu_export_patches = add_action(self,
                'Export Patches...', guicmds.export_patches, 'Ctrl+E')
        self.menu_preferences = add_action(self,
                'Preferences', lambda: preferences(model=prefs_model),
                QtGui.QKeySequence.Preferences, 'Ctrl+O')

        self.menu_rescan = add_action(self,
                'Rescan', emit(self, signals.rescan), 'Ctrl+R')
        self.menu_rescan.setIcon(qtutils.reload_icon())

        self.menu_cherry_pick = add_action(self,
                'Cherry-Pick...', guicmds.cherry_pick, 'Ctrl+P')

        self.menu_load_commitmsg = add_action(self,
                'Load Commit Message...', guicmds.load_commitmsg)

        self.menu_quit = add_action(self,
                'Quit', self.close, 'Ctrl+Q')
        self.menu_manage_bookmarks = add_action(self,
                'Bookmarks...', manage_bookmarks)
        self.menu_grep = add_action(self,
                'Grep', guicmds.grep)
        self.menu_merge_local = add_action(self,
                'Merge...', merge.local_merge)

        self.menu_merge_abort = add_action(self,
                'Abort Merge...', merge.abort_merge)

        self.menu_fetch = add_action(self,
                'Fetch...', guicmds.fetch)
        self.menu_push = add_action(self,
                'Push...', guicmds.push)
        self.menu_pull = add_action(self,
                'Pull...', guicmds.pull)

        self.menu_open_repo = add_action(self,
                'Open...', guicmds.open_repo)
        self.menu_open_repo.setIcon(qtutils.open_icon())

        self.menu_stash = add_action(self,
                'Stash...', stash.stash, 'Alt+Shift+S')
        self.menu_diff_branch = add_action(self,
                'Apply Changes From Branch...', guicmds.diff_branch)
        self.menu_branch_compare = add_action(self,
                'Branches...', compare.branch_compare)

        self.menu_clone_repo = add_action(self,
                'Clone...', guicmds.clone_repo)
        self.menu_clone_repo.setIcon(qtutils.git_icon())

        self.menu_help_docs = add_action(self,
                'Documentation',
                lambda: self.model.git.web__browse(resources.html_docs()),
                QtGui.QKeySequence.HelpContents)
        self.menu_commit_compare = add_action(self,
                'Commits...', compare.compare)
        self.menu_commit_compare_file = add_action(self,
                'Commits Touching File...', compare.compare_file)
        self.menu_visualize_current = add_action(self,
                'Visualize Current Branch...',
                emit(self, signals.visualize_current))
        self.menu_visualize_all = add_action(self,
                'Visualize All Branches...',
                emit(self, signals.visualize_all))
        self.menu_search_commits = add_action(self,
                'Search...', search.search)
        self.menu_browse_branch = add_action(self,
                'Browse Current Branch...', guicmds.browse_current)
        self.menu_browse_other_branch = add_action(self,
                'Browse Other Branch...', guicmds.browse_other)
        self.menu_load_commitmsg_template = add_action(self,
                'Get Commit Message Template',
                emit(self, signals.load_commit_template))
        self.menu_help_about = add_action(self,
                'About', launch_about_dialog)
        self.menu_branch_diff = add_action(self,
                'SHA-1...', guicmds.branch_diff)
        self.menu_diff_expression = add_action(self,
                'Expression...', guicmds.diff_expression)
        self.menu_create_tag = add_action(self,
                'Create Tag...', createtag.create_tag)

        self.menu_create_branch = add_action(self,
                'Create...', create_new_branch, 'Ctrl+B')

        self.menu_delete_branch = add_action(self,
                'Delete...', guicmds.branch_delete)

        self.menu_checkout_branch = add_action(self,
                'Checkout...', guicmds.checkout_branch, 'Alt+B')
        self.menu_rebase_branch = add_action(self,
                'Rebase...', guicmds.rebase)
        self.menu_branch_review = add_action(self,
                'Review...', guicmds.review_branch)

        self.menu_classic = add_action(self,
                'Cola Classic...', cola_classic)
        self.menu_classic.setIcon(qtutils.git_icon())

        self.menu_dag = add_action(self,
                'DAG...', lambda: git_dag(self.model))
        self.menu_dag.setIcon(qtutils.git_icon())

        # Create the application menu
        self.menubar = QtGui.QMenuBar(self)

        # File Menu
        self.file_menu = create_menu('&File', self.menubar)
        self.file_menu.addAction(self.menu_preferences)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_open_repo)
        self.file_menu.addAction(self.menu_clone_repo)
        self.file_menu.addAction(self.menu_manage_bookmarks)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_rescan)
        self.file_menu.addSeparator()
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_load_commitmsg)
        self.file_menu.addAction(self.menu_load_commitmsg_template)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_quit)
        # Add to menubar
        self.menubar.addAction(self.file_menu.menuAction())

        # Commit Menu
        self.commit_menu = create_menu('Co&mmit', self.menubar)
        self.commit_menu.setTitle(tr('Commit@@verb'))
        self.commit_menu.addAction(self.menu_stage_modified)
        self.commit_menu.addAction(self.menu_stage_untracked)
        self.commit_menu.addSeparator()
        self.commit_menu.addAction(self.menu_unstage_all)
        self.commit_menu.addAction(self.menu_unstage_selected)
        self.commit_menu.addSeparator()
        self.commit_menu.addAction(self.menu_search_commits)
        # Add to menubar
        self.menubar.addAction(self.commit_menu.menuAction())

        # Branch Menu
        self.branch_menu = create_menu('B&ranch', self.menubar)
        self.branch_menu.addAction(self.menu_branch_review)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_create_branch)
        self.branch_menu.addAction(self.menu_checkout_branch)
        self.branch_menu.addAction(self.menu_rebase_branch)
        self.branch_menu.addAction(self.menu_delete_branch)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_browse_branch)
        self.branch_menu.addAction(self.menu_browse_other_branch)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_visualize_current)
        self.branch_menu.addAction(self.menu_visualize_all)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_diff_branch)
        # Add to menubar
        self.menubar.addAction(self.branch_menu.menuAction())

        # Actions menu
        self.actions_menu = create_menu('Act&ions', self.menubar)
        self.actions_menu.addAction(self.menu_merge_local)
        self.actions_menu.addAction(self.menu_stash)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_fetch)
        self.actions_menu.addAction(self.menu_push)
        self.actions_menu.addAction(self.menu_pull)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_create_tag)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_export_patches)
        self.actions_menu.addAction(self.menu_cherry_pick)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_merge_abort)
        self.actions_menu.addAction(self.menu_grep)
        # Add to menubar
        self.menubar.addAction(self.actions_menu.menuAction())

        # Diff Menu
        self.diff_menu = create_menu('&Diff', self.menubar)
        self.diff_menu.addAction(self.menu_branch_diff)
        self.diff_menu.addAction(self.menu_diff_expression)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.menu_branch_compare)
        self.diff_menu.addAction(self.menu_commit_compare)
        self.diff_menu.addAction(self.menu_commit_compare_file)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.menu_show_diffstat)
        # Add to menubar
        self.menubar.addAction(self.diff_menu.menuAction())

        # Tools Menu
        self.tools_menu = create_menu('&Tools', self.menubar)
        self.tools_menu.addAction(self.menu_classic)
        self.tools_menu.addAction(self.menu_dag)
        self.tools_menu.addSeparator()
        if self.classic_dockable:
            self.tools_menu.addAction(self.classicdockwidget.toggleViewAction())
        self.tools_menu.addAction(self.diffdockwidget.toggleViewAction())
        self.tools_menu.addAction(self.actiondockwidget.toggleViewAction())
        self.tools_menu.addAction(self.commitdockwidget.toggleViewAction())
        self.tools_menu.addAction(self.statusdockwidget.toggleViewAction())
        self.tools_menu.addAction(self.logdockwidget.toggleViewAction())
        self.menubar.addAction(self.tools_menu.menuAction())

        # Help Menu
        self.help_menu = create_menu('&Help', self.menubar)
        self.help_menu.addAction(self.menu_help_docs)
        self.help_menu.addAction(self.menu_help_about)
        # Add to menubar
        self.menubar.addAction(self.help_menu.menuAction())

        # Set main menu
        self.setMenuBar(self.menubar)

        # Arrange dock widgets
        top = Qt.TopDockWidgetArea
        bottom = Qt.BottomDockWidgetArea

        self.addDockWidget(top, self.commitdockwidget)
        if self.classic_dockable:
            self.addDockWidget(top, self.classicdockwidget)
        self.addDockWidget(top, self.statusdockwidget)
        self.addDockWidget(top, self.actiondockwidget)
        self.addDockWidget(bottom, self.logdockwidget)
        if self.classic_dockable:
            self.tabifyDockWidget(self.classicdockwidget, self.commitdockwidget)
        self.tabifyDockWidget(self.logdockwidget, self.diffdockwidget)

        # Listen for model notifications
        model.add_message_observer(model.message_mode_changed,
                                   self._mode_changed)

        model.add_message_observer(model.message_updated,
                                   self._update_view)

        prefs_model.add_message_observer(prefs_model.message_config_updated,
                                         self._config_updated)


        # Add button callbacks
        connect_button(self.rescan_button, emit(self, signals.rescan))
        connect_button(self.alt_button, emit(self, signals.reset_mode))
        connect_button(self.fetch_button, guicmds.fetch)
        connect_button(self.push_button, guicmds.push)
        connect_button(self.pull_button, guicmds.pull)
        connect_button(self.stash_button, stash.stash)

        connect_button(self.stage_button, self.stage)
        connect_button(self.unstage_button, self.unstage)

        self.connect(self, SIGNAL('update'), self._update_callback)
        self.connect(self, SIGNAL('apply_state'), self.apply_state)
        self.connect(self, SIGNAL('install_config_actions'),
                     self._install_config_actions)

        # Install .git-config-defined actions
        self._config_task = None
        self.install_config_actions()

        # Restore saved settings
        self._gui_state_task = None
        self._load_gui_state()

        log(0, self.model.git_version + '\ncola version ' + version.version())

    # Qt overrides
    def closeEvent(self, event):
        """Save state in the settings manager."""
        qtutils.save_state(self)
        standard.MainWindow.closeEvent(self, event)

    # Accessors
    mode = property(lambda self: self.model.mode)

    def _mode_changed(self, mode):
        """React to mode changes; hide/show the "Exit Diff Mode" button."""
        if mode in (self.model.mode_branch,
                    self.model.mode_review,
                    self.model.mode_diff,
                    self.model.mode_diff_expr):
            height = self.stage_button.minimumHeight()
            self.alt_button.setMinimumHeight(height)
            self.alt_button.show()
        else:
            self.alt_button.setMinimumHeight(1)
            self.alt_button.hide()

    def _config_updated(self, source, config, value):
        if config == 'cola.fontdiff':
            font = QtGui.QFont()
            if not font.fromString(value):
                return
            self._set_diff_font(font)
            qtutils.logger().setFont(font)
            self.diff_viewer.setFont(font)
            self.commitmsgeditor.commitmsg.setFont(font)

        elif config == 'cola.tabwidth':
            # variable-tab-width setting
            self.diff_viewer.set_tab_width(value)

    def install_config_actions(self):
        """Install .gitconfig-defined actions"""
        self._config_task = self._start_config_actions_task()

    def _start_config_actions_task(self):
        """Do the expensive "get_config_actions()" call in the background"""
        class ConfigActionsTask(QtCore.QRunnable):
            def __init__(self, sender):
                QtCore.QRunnable.__init__(self)
                self._sender = sender
            def run(self):
                names = cfgactions.get_config_actions()
                self._sender.emit(SIGNAL('install_config_actions'), names)

        task = ConfigActionsTask(self)
        QtCore.QThreadPool.globalInstance().start(task)
        return task

    def _install_config_actions(self, names):
        """Install .gitconfig-defined actions"""
        if not names:
            return
        menu = self.actions_menu
        menu.addSeparator()
        for name in names:
            menu.addAction(name, emit(self, signals.run_config_action, name))

    def _update_view(self):
        self.emit(SIGNAL('update'))

    def _update_callback(self):
        """Update the title with the current branch and directory name."""
        branch = self.model.currentbranch
        curdir = core.decode(os.getcwd())
        msg = 'Repository: %s\nBranch: %s' % (curdir, branch)
        self.commitdockwidget.setToolTip(msg)

        title = '%s: %s' % (self.model.project, branch)
        if self.mode in (self.model.mode_diff, self.model.mode_diff_expr):
            title += ' *** diff mode***'
        elif self.mode == self.model.mode_review:
            title += ' *** review mode***'
        elif self.mode == self.model.mode_amend:
            title += ' *** amending ***'
        self.setWindowTitle(title)

        self.commitmsgeditor.set_mode(self.mode)

        if not self.model.read_only() and self.mode != self.model.mode_amend:
            # Check if there's a message file in .git/
            merge_msg_path = gitcmds.merge_message_path()
            if merge_msg_path is None:
                return
            merge_msg_hash = utils.checksum(core.decode(merge_msg_path))
            if merge_msg_hash == self.merge_message_hash:
                return
            self.merge_message_hash = merge_msg_hash
            cola.notifier().broadcast(signals.load_commit_message,
                                      core.decode(merge_msg_path))

    def apply_state(self, state):
        """Imports data for save/restore"""
        # 1 is the widget version; change when widgets are added/removed
        standard.MainWindow.apply_state(self, state)
        qtutils.apply_window_state(self, state, 1)

    def export_state(self):
        """Exports data for save/restore"""
        state = standard.MainWindow.export_state(self)
        return qtutils.export_window_state(self, state, self.widget_version)

    def _load_gui_state(self):
        """Restores the gui from the preferences file."""
        self._gui_state_task = self._start_gui_state_loading_thread()

    def _start_gui_state_loading_thread(self):
        """Do expensive file reading and json decoding in the background"""
        class LoadGUIStateTask(QtCore.QRunnable):
            def __init__(self, sender):
                QtCore.QRunnable.__init__(self)
                self._sender = sender
            def run(self):
                state = settings.Settings().get_gui_state(self._sender)
                self._sender.emit(SIGNAL('apply_state'), state)

        task = LoadGUIStateTask(self)
        QtCore.QThreadPool.globalInstance().start(task)
        return task

    def stage(self):
        """Stage selected files, or all files if no selection exists."""
        paths = cola.selection_model().unstaged
        if not paths:
            cola.notifier().broadcast(signals.stage_modified)
        else:
            cola.notifier().broadcast(signals.stage, paths)

    def unstage(self):
        """Unstage selected files, or all files if no selection exists."""
        paths = cola.selection_model().staged
        if not paths:
            cola.notifier().broadcast(signals.unstage_all)
        else:
            cola.notifier().broadcast(signals.unstage, paths)

    def dragEnterEvent(self, event):
        """Accepts drops"""
        standard.MainWindow.dragEnterEvent(self, event)
        event.acceptProposedAction()

    def dropEvent(self, event):
        """Apply dropped patches with git-am"""
        event.accept()
        urls = event.mimeData().urls()
        if not urls:
            return
        paths = map(lambda x: unicode(x.path()), urls)
        patches = [p for p in paths if p.endswith('.patch')]
        dirs = [p for p in paths if os.path.isdir(p)]
        dirs.sort()
        for d in dirs:
            patches.extend(self._gather_patches(d))
        # Broadcast the patches to apply
        cola.notifier().broadcast(signals.apply_patches, patches)

    def _gather_patches(self, path):
        """Find patches in a subdirectory"""
        patches = []
        for root, subdirs, files in os.walk(path):
            for name in [f for f in files if f.endswith('.patch')]:
                patches.append(os.path.join(root, name))
        return patches
Ejemplo n.º 13
0
Archivo: view.py Proyecto: mwh/git-cola
    def __init__(self, model, parent):
        standard.MainWindow.__init__(self, parent)
        # Default size; this is thrown out when save/restore is used
        self.resize(987, 610)
        self.model = model
        self.prefs_model = prefs_model = PreferencesModel()

        # Internal field used by import/export_state().
        # Change this whenever dockwidgets are removed.
        self.widget_version = 1

        # Keeps track of merge messages we've seen
        self.merge_message_hash = ""

        self.setAcceptDrops(True)

        # Dockwidget options
        qtcompat.set_common_dock_options(self)

        self.classic_dockable = gitcfg.instance().get("cola.classicdockable")

        if self.classic_dockable:
            self.classicdockwidget = create_dock("Cola Classic", self)
            self.classicwidget = classic_widget(self)
            self.classicdockwidget.setWidget(self.classicwidget)

        # "Actions" widget
        self.actionsdockwidget = create_dock("Actions", self)
        self.actionsdockwidgetcontents = qt.QFlowLayoutWidget(self)
        layout = self.actionsdockwidgetcontents.layout()
        self.stage_button = create_button(text="Stage", layout=layout)
        self.unstage_button = create_button(text="Unstage", layout=layout)
        self.rescan_button = create_button(text="Rescan", layout=layout)
        self.fetch_button = create_button(text="Fetch...", layout=layout)
        self.push_button = create_button(text="Push...", layout=layout)
        self.pull_button = create_button(text="Pull...", layout=layout)
        self.stash_button = create_button(text="Stash...", layout=layout)
        self.alt_button = create_button(text="Exit Diff Mode", layout=layout)
        self.alt_button.hide()
        layout.addStretch()
        self.actionsdockwidget.setWidget(self.actionsdockwidgetcontents)

        # "Repository Status" widget
        self.statusdockwidget = create_dock("Repository Status", self)
        self.statusdockwidget.setWidget(StatusWidget(self))

        # "Commit Message Editor" widget
        self.commitdockwidget = create_dock("Commit Message Editor", self)
        self.commitmsgeditor = CommitMessageEditor(model, self)
        relay_signal(self, self.commitmsgeditor, SIGNAL(signals.amend_mode))
        relay_signal(self, self.commitmsgeditor, SIGNAL(signals.signoff))
        relay_signal(self, self.commitmsgeditor, SIGNAL(signals.load_previous_message))
        self.commitdockwidget.setWidget(self.commitmsgeditor)

        # "Command Output" widget
        logwidget = qtutils.logger()
        logwidget.setFont(diff_font())
        self.logdockwidget = create_dock("Command Output", self)
        self.logdockwidget.setWidget(logwidget)

        # "Diff Viewer" widget
        self.diffdockwidget = create_dock("Diff Viewer", self)
        self.diff_viewer = DiffTextEdit(self.diffdockwidget)
        self.diffdockwidget.setWidget(self.diff_viewer)

        # All Actions
        self.menu_unstage_all = add_action(self, "Unstage All", emit(self, signals.unstage_all))
        self.menu_unstage_all.setIcon(qtutils.icon("remove.svg"))

        self.menu_unstage_selected = add_action(self, "Unstage From Commit", emit(self, signals.unstage_selected))
        self.menu_unstage_selected.setIcon(qtutils.icon("remove.svg"))

        self.menu_show_diffstat = add_action(self, "Diffstat", emit(self, signals.diffstat), "Alt+D")

        self.menu_stage_modified = add_action(
            self, "Stage Changed Files To Commit", emit(self, signals.stage_modified), "Alt+A"
        )
        self.menu_stage_modified.setIcon(qtutils.icon("add.svg"))

        self.menu_stage_untracked = add_action(
            self, "Stage All Untracked", emit(self, signals.stage_untracked), "Alt+U"
        )
        self.menu_stage_untracked.setIcon(qtutils.icon("add.svg"))

        self.menu_export_patches = add_action(self, "Export Patches...", guicmds.export_patches, "Alt+E")
        self.menu_preferences = add_action(
            self, "Preferences", lambda: preferences(model=prefs_model), QtGui.QKeySequence.Preferences, "Ctrl+O"
        )

        self.menu_rescan = add_action(self, "Rescan", emit(self, signals.rescan_and_refresh), "Ctrl+R")
        self.menu_rescan.setIcon(qtutils.reload_icon())

        self.menu_browse_recent = add_action(self, "Recently Modified Files...", browse_recent, "Shift+Ctrl+E")

        self.menu_cherry_pick = add_action(self, "Cherry-Pick...", guicmds.cherry_pick, "Ctrl+P")

        self.menu_load_commitmsg = add_action(self, "Load Commit Message...", guicmds.load_commitmsg)

        self.menu_quit = add_action(self, "Quit", self.close, "Ctrl+Q")
        self.menu_manage_bookmarks = add_action(self, "Bookmarks...", manage_bookmarks)
        self.menu_grep = add_action(self, "Grep", guicmds.grep)
        self.menu_merge_local = add_action(self, "Merge...", merge.local_merge)

        self.menu_merge_abort = add_action(self, "Abort Merge...", merge.abort_merge)

        self.menu_fetch = add_action(self, "Fetch...", guicmds.fetch)
        self.menu_push = add_action(self, "Push...", guicmds.push)
        self.menu_pull = add_action(self, "Pull...", guicmds.pull)

        self.menu_open_repo = add_action(self, "Open...", guicmds.open_repo)
        self.menu_open_repo.setIcon(qtutils.open_icon())

        self.menu_stash = add_action(self, "Stash...", stash.stash, "Alt+Shift+S")
        self.menu_diff_branch = add_action(self, "Apply Changes From Branch...", guicmds.diff_branch)
        self.menu_branch_compare = add_action(self, "Branches...", compare.branch_compare)

        self.menu_clone_repo = add_action(self, "Clone...", guicmds.clone_repo)
        self.menu_clone_repo.setIcon(qtutils.git_icon())

        self.menu_help_docs = add_action(
            self, "Documentation", resources.show_html_docs, QtGui.QKeySequence.HelpContents
        )

        self.menu_help_shortcuts = add_action(self, "Keyboard Shortcuts", show_shortcuts, QtCore.Qt.Key_Question)

        self.menu_commit_compare = add_action(self, "Commits...", compare.compare)
        self.menu_commit_compare_file = add_action(self, "Commits Touching File...", compare.compare_file)
        self.menu_visualize_current = add_action(
            self, "Visualize Current Branch...", emit(self, signals.visualize_current)
        )
        self.menu_visualize_all = add_action(self, "Visualize All Branches...", emit(self, signals.visualize_all))
        self.menu_search_commits = add_action(self, "Search...", search.search)
        self.menu_browse_branch = add_action(self, "Browse Current Branch...", guicmds.browse_current)
        self.menu_browse_other_branch = add_action(self, "Browse Other Branch...", guicmds.browse_other)
        self.menu_load_commitmsg_template = add_action(
            self, "Get Commit Message Template", emit(self, signals.load_commit_template)
        )
        self.menu_help_about = add_action(self, "About", launch_about_dialog)
        self.menu_branch_diff = add_action(self, "SHA-1...", guicmds.branch_diff)
        self.menu_diff_expression = add_action(self, "Expression...", guicmds.diff_expression)
        self.menu_create_tag = add_action(self, "Create Tag...", createtag.create_tag)

        self.menu_create_branch = add_action(self, "Create...", create_new_branch, "Ctrl+B")

        self.menu_delete_branch = add_action(self, "Delete...", guicmds.branch_delete)

        self.menu_checkout_branch = add_action(self, "Checkout...", guicmds.checkout_branch, "Alt+B")
        self.menu_rebase_branch = add_action(self, "Rebase...", guicmds.rebase)
        self.menu_branch_review = add_action(self, "Review...", guicmds.review_branch)

        self.menu_classic = add_action(self, "Cola Classic...", cola_classic)
        self.menu_classic.setIcon(qtutils.git_icon())

        self.menu_dag = add_action(self, "DAG...", lambda: git_dag(self.model))
        self.menu_dag.setIcon(qtutils.git_icon())

        # Relayed actions
        status_tree = self.statusdockwidget.widget().tree
        self.addAction(status_tree.up)
        self.addAction(status_tree.down)
        self.addAction(status_tree.process_selection)
        self.addAction(status_tree.launch_difftool)

        # Create the application menu
        self.menubar = QtGui.QMenuBar(self)

        # File Menu
        self.file_menu = create_menu("&File", self.menubar)
        self.file_menu.addAction(self.menu_preferences)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_open_repo)
        self.file_menu.addAction(self.menu_clone_repo)
        self.file_menu.addAction(self.menu_manage_bookmarks)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_rescan)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_browse_recent)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_load_commitmsg)
        self.file_menu.addAction(self.menu_load_commitmsg_template)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_quit)
        # Add to menubar
        self.menubar.addAction(self.file_menu.menuAction())

        # Commit Menu
        self.commit_menu = create_menu("Co&mmit", self.menubar)
        self.commit_menu.setTitle(tr("Commit@@verb"))
        self.commit_menu.addAction(self.menu_stage_modified)
        self.commit_menu.addAction(self.menu_stage_untracked)
        self.commit_menu.addSeparator()
        self.commit_menu.addAction(self.menu_unstage_all)
        self.commit_menu.addAction(self.menu_unstage_selected)
        self.commit_menu.addSeparator()
        self.commit_menu.addAction(self.menu_search_commits)
        # Add to menubar
        self.menubar.addAction(self.commit_menu.menuAction())

        # Branch Menu
        self.branch_menu = create_menu("B&ranch", self.menubar)
        self.branch_menu.addAction(self.menu_branch_review)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_create_branch)
        self.branch_menu.addAction(self.menu_checkout_branch)
        self.branch_menu.addAction(self.menu_rebase_branch)
        self.branch_menu.addAction(self.menu_delete_branch)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_browse_branch)
        self.branch_menu.addAction(self.menu_browse_other_branch)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_visualize_current)
        self.branch_menu.addAction(self.menu_visualize_all)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_diff_branch)
        # Add to menubar
        self.menubar.addAction(self.branch_menu.menuAction())

        # Actions menu
        self.actions_menu = create_menu("Act&ions", self.menubar)
        self.actions_menu.addAction(self.menu_merge_local)
        self.actions_menu.addAction(self.menu_stash)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_fetch)
        self.actions_menu.addAction(self.menu_push)
        self.actions_menu.addAction(self.menu_pull)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_create_tag)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_export_patches)
        self.actions_menu.addAction(self.menu_cherry_pick)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_merge_abort)
        self.actions_menu.addAction(self.menu_grep)
        # Add to menubar
        self.menubar.addAction(self.actions_menu.menuAction())

        # Diff Menu
        self.diff_menu = create_menu("&Diff", self.menubar)
        self.diff_menu.addAction(self.menu_branch_diff)
        self.diff_menu.addAction(self.menu_diff_expression)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.menu_branch_compare)
        self.diff_menu.addAction(self.menu_commit_compare)
        self.diff_menu.addAction(self.menu_commit_compare_file)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.menu_show_diffstat)
        # Add to menubar
        self.menubar.addAction(self.diff_menu.menuAction())

        # Tools Menu
        self.tools_menu = create_menu("&Tools", self.menubar)
        self.tools_menu.addAction(self.menu_classic)
        self.tools_menu.addAction(self.menu_dag)
        self.tools_menu.addSeparator()
        if self.classic_dockable:
            self.tools_menu.addAction(self.classicdockwidget.toggleViewAction())

        self.setup_dockwidget_tools_menu()
        self.menubar.addAction(self.tools_menu.menuAction())

        # Help Menu
        self.help_menu = create_menu("&Help", self.menubar)
        self.help_menu.addAction(self.menu_help_docs)
        self.help_menu.addAction(self.menu_help_shortcuts)
        self.help_menu.addAction(self.menu_help_about)
        # Add to menubar
        self.menubar.addAction(self.help_menu.menuAction())

        # Set main menu
        self.setMenuBar(self.menubar)

        # Arrange dock widgets
        top = Qt.TopDockWidgetArea
        bottom = Qt.BottomDockWidgetArea

        self.addDockWidget(top, self.commitdockwidget)
        if self.classic_dockable:
            self.addDockWidget(top, self.classicdockwidget)
        self.addDockWidget(top, self.statusdockwidget)
        self.addDockWidget(top, self.actionsdockwidget)
        self.addDockWidget(bottom, self.logdockwidget)
        if self.classic_dockable:
            self.tabifyDockWidget(self.classicdockwidget, self.commitdockwidget)
        self.tabifyDockWidget(self.logdockwidget, self.diffdockwidget)

        # Listen for model notifications
        model.add_message_observer(model.message_mode_changed, self._mode_changed)

        model.add_message_observer(model.message_updated, self._update_view)

        prefs_model.add_message_observer(prefs_model.message_config_updated, self._config_updated)

        # Add button callbacks
        connect_button(self.rescan_button, emit(self, signals.rescan_and_refresh))
        connect_button(self.alt_button, emit(self, signals.reset_mode))
        connect_button(self.fetch_button, guicmds.fetch)
        connect_button(self.push_button, guicmds.push)
        connect_button(self.pull_button, guicmds.pull)
        connect_button(self.stash_button, stash.stash)

        connect_button(self.stage_button, self.stage)
        connect_button(self.unstage_button, self.unstage)

        self.connect(self, SIGNAL("update"), self._update_callback)
        self.connect(self, SIGNAL("apply_state"), self.apply_state)
        self.connect(self, SIGNAL("install_config_actions"), self._install_config_actions)

        # Install .git-config-defined actions
        self._config_task = None
        self.install_config_actions()

        # Restore saved settings
        self._gui_state_task = None
        self._load_gui_state()

        log(0, self.model.git_version + "\ncola version " + version.version())
Ejemplo n.º 14
0
Archivo: view.py Proyecto: mwh/git-cola
class MainView(standard.MainWindow):
    def __init__(self, model, parent):
        standard.MainWindow.__init__(self, parent)
        # Default size; this is thrown out when save/restore is used
        self.resize(987, 610)
        self.model = model
        self.prefs_model = prefs_model = PreferencesModel()

        # Internal field used by import/export_state().
        # Change this whenever dockwidgets are removed.
        self.widget_version = 1

        # Keeps track of merge messages we've seen
        self.merge_message_hash = ""

        self.setAcceptDrops(True)

        # Dockwidget options
        qtcompat.set_common_dock_options(self)

        self.classic_dockable = gitcfg.instance().get("cola.classicdockable")

        if self.classic_dockable:
            self.classicdockwidget = create_dock("Cola Classic", self)
            self.classicwidget = classic_widget(self)
            self.classicdockwidget.setWidget(self.classicwidget)

        # "Actions" widget
        self.actionsdockwidget = create_dock("Actions", self)
        self.actionsdockwidgetcontents = qt.QFlowLayoutWidget(self)
        layout = self.actionsdockwidgetcontents.layout()
        self.stage_button = create_button(text="Stage", layout=layout)
        self.unstage_button = create_button(text="Unstage", layout=layout)
        self.rescan_button = create_button(text="Rescan", layout=layout)
        self.fetch_button = create_button(text="Fetch...", layout=layout)
        self.push_button = create_button(text="Push...", layout=layout)
        self.pull_button = create_button(text="Pull...", layout=layout)
        self.stash_button = create_button(text="Stash...", layout=layout)
        self.alt_button = create_button(text="Exit Diff Mode", layout=layout)
        self.alt_button.hide()
        layout.addStretch()
        self.actionsdockwidget.setWidget(self.actionsdockwidgetcontents)

        # "Repository Status" widget
        self.statusdockwidget = create_dock("Repository Status", self)
        self.statusdockwidget.setWidget(StatusWidget(self))

        # "Commit Message Editor" widget
        self.commitdockwidget = create_dock("Commit Message Editor", self)
        self.commitmsgeditor = CommitMessageEditor(model, self)
        relay_signal(self, self.commitmsgeditor, SIGNAL(signals.amend_mode))
        relay_signal(self, self.commitmsgeditor, SIGNAL(signals.signoff))
        relay_signal(self, self.commitmsgeditor, SIGNAL(signals.load_previous_message))
        self.commitdockwidget.setWidget(self.commitmsgeditor)

        # "Command Output" widget
        logwidget = qtutils.logger()
        logwidget.setFont(diff_font())
        self.logdockwidget = create_dock("Command Output", self)
        self.logdockwidget.setWidget(logwidget)

        # "Diff Viewer" widget
        self.diffdockwidget = create_dock("Diff Viewer", self)
        self.diff_viewer = DiffTextEdit(self.diffdockwidget)
        self.diffdockwidget.setWidget(self.diff_viewer)

        # All Actions
        self.menu_unstage_all = add_action(self, "Unstage All", emit(self, signals.unstage_all))
        self.menu_unstage_all.setIcon(qtutils.icon("remove.svg"))

        self.menu_unstage_selected = add_action(self, "Unstage From Commit", emit(self, signals.unstage_selected))
        self.menu_unstage_selected.setIcon(qtutils.icon("remove.svg"))

        self.menu_show_diffstat = add_action(self, "Diffstat", emit(self, signals.diffstat), "Alt+D")

        self.menu_stage_modified = add_action(
            self, "Stage Changed Files To Commit", emit(self, signals.stage_modified), "Alt+A"
        )
        self.menu_stage_modified.setIcon(qtutils.icon("add.svg"))

        self.menu_stage_untracked = add_action(
            self, "Stage All Untracked", emit(self, signals.stage_untracked), "Alt+U"
        )
        self.menu_stage_untracked.setIcon(qtutils.icon("add.svg"))

        self.menu_export_patches = add_action(self, "Export Patches...", guicmds.export_patches, "Alt+E")
        self.menu_preferences = add_action(
            self, "Preferences", lambda: preferences(model=prefs_model), QtGui.QKeySequence.Preferences, "Ctrl+O"
        )

        self.menu_rescan = add_action(self, "Rescan", emit(self, signals.rescan_and_refresh), "Ctrl+R")
        self.menu_rescan.setIcon(qtutils.reload_icon())

        self.menu_browse_recent = add_action(self, "Recently Modified Files...", browse_recent, "Shift+Ctrl+E")

        self.menu_cherry_pick = add_action(self, "Cherry-Pick...", guicmds.cherry_pick, "Ctrl+P")

        self.menu_load_commitmsg = add_action(self, "Load Commit Message...", guicmds.load_commitmsg)

        self.menu_quit = add_action(self, "Quit", self.close, "Ctrl+Q")
        self.menu_manage_bookmarks = add_action(self, "Bookmarks...", manage_bookmarks)
        self.menu_grep = add_action(self, "Grep", guicmds.grep)
        self.menu_merge_local = add_action(self, "Merge...", merge.local_merge)

        self.menu_merge_abort = add_action(self, "Abort Merge...", merge.abort_merge)

        self.menu_fetch = add_action(self, "Fetch...", guicmds.fetch)
        self.menu_push = add_action(self, "Push...", guicmds.push)
        self.menu_pull = add_action(self, "Pull...", guicmds.pull)

        self.menu_open_repo = add_action(self, "Open...", guicmds.open_repo)
        self.menu_open_repo.setIcon(qtutils.open_icon())

        self.menu_stash = add_action(self, "Stash...", stash.stash, "Alt+Shift+S")
        self.menu_diff_branch = add_action(self, "Apply Changes From Branch...", guicmds.diff_branch)
        self.menu_branch_compare = add_action(self, "Branches...", compare.branch_compare)

        self.menu_clone_repo = add_action(self, "Clone...", guicmds.clone_repo)
        self.menu_clone_repo.setIcon(qtutils.git_icon())

        self.menu_help_docs = add_action(
            self, "Documentation", resources.show_html_docs, QtGui.QKeySequence.HelpContents
        )

        self.menu_help_shortcuts = add_action(self, "Keyboard Shortcuts", show_shortcuts, QtCore.Qt.Key_Question)

        self.menu_commit_compare = add_action(self, "Commits...", compare.compare)
        self.menu_commit_compare_file = add_action(self, "Commits Touching File...", compare.compare_file)
        self.menu_visualize_current = add_action(
            self, "Visualize Current Branch...", emit(self, signals.visualize_current)
        )
        self.menu_visualize_all = add_action(self, "Visualize All Branches...", emit(self, signals.visualize_all))
        self.menu_search_commits = add_action(self, "Search...", search.search)
        self.menu_browse_branch = add_action(self, "Browse Current Branch...", guicmds.browse_current)
        self.menu_browse_other_branch = add_action(self, "Browse Other Branch...", guicmds.browse_other)
        self.menu_load_commitmsg_template = add_action(
            self, "Get Commit Message Template", emit(self, signals.load_commit_template)
        )
        self.menu_help_about = add_action(self, "About", launch_about_dialog)
        self.menu_branch_diff = add_action(self, "SHA-1...", guicmds.branch_diff)
        self.menu_diff_expression = add_action(self, "Expression...", guicmds.diff_expression)
        self.menu_create_tag = add_action(self, "Create Tag...", createtag.create_tag)

        self.menu_create_branch = add_action(self, "Create...", create_new_branch, "Ctrl+B")

        self.menu_delete_branch = add_action(self, "Delete...", guicmds.branch_delete)

        self.menu_checkout_branch = add_action(self, "Checkout...", guicmds.checkout_branch, "Alt+B")
        self.menu_rebase_branch = add_action(self, "Rebase...", guicmds.rebase)
        self.menu_branch_review = add_action(self, "Review...", guicmds.review_branch)

        self.menu_classic = add_action(self, "Cola Classic...", cola_classic)
        self.menu_classic.setIcon(qtutils.git_icon())

        self.menu_dag = add_action(self, "DAG...", lambda: git_dag(self.model))
        self.menu_dag.setIcon(qtutils.git_icon())

        # Relayed actions
        status_tree = self.statusdockwidget.widget().tree
        self.addAction(status_tree.up)
        self.addAction(status_tree.down)
        self.addAction(status_tree.process_selection)
        self.addAction(status_tree.launch_difftool)

        # Create the application menu
        self.menubar = QtGui.QMenuBar(self)

        # File Menu
        self.file_menu = create_menu("&File", self.menubar)
        self.file_menu.addAction(self.menu_preferences)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_open_repo)
        self.file_menu.addAction(self.menu_clone_repo)
        self.file_menu.addAction(self.menu_manage_bookmarks)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_rescan)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_browse_recent)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_load_commitmsg)
        self.file_menu.addAction(self.menu_load_commitmsg_template)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_quit)
        # Add to menubar
        self.menubar.addAction(self.file_menu.menuAction())

        # Commit Menu
        self.commit_menu = create_menu("Co&mmit", self.menubar)
        self.commit_menu.setTitle(tr("Commit@@verb"))
        self.commit_menu.addAction(self.menu_stage_modified)
        self.commit_menu.addAction(self.menu_stage_untracked)
        self.commit_menu.addSeparator()
        self.commit_menu.addAction(self.menu_unstage_all)
        self.commit_menu.addAction(self.menu_unstage_selected)
        self.commit_menu.addSeparator()
        self.commit_menu.addAction(self.menu_search_commits)
        # Add to menubar
        self.menubar.addAction(self.commit_menu.menuAction())

        # Branch Menu
        self.branch_menu = create_menu("B&ranch", self.menubar)
        self.branch_menu.addAction(self.menu_branch_review)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_create_branch)
        self.branch_menu.addAction(self.menu_checkout_branch)
        self.branch_menu.addAction(self.menu_rebase_branch)
        self.branch_menu.addAction(self.menu_delete_branch)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_browse_branch)
        self.branch_menu.addAction(self.menu_browse_other_branch)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_visualize_current)
        self.branch_menu.addAction(self.menu_visualize_all)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.menu_diff_branch)
        # Add to menubar
        self.menubar.addAction(self.branch_menu.menuAction())

        # Actions menu
        self.actions_menu = create_menu("Act&ions", self.menubar)
        self.actions_menu.addAction(self.menu_merge_local)
        self.actions_menu.addAction(self.menu_stash)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_fetch)
        self.actions_menu.addAction(self.menu_push)
        self.actions_menu.addAction(self.menu_pull)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_create_tag)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_export_patches)
        self.actions_menu.addAction(self.menu_cherry_pick)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_merge_abort)
        self.actions_menu.addAction(self.menu_grep)
        # Add to menubar
        self.menubar.addAction(self.actions_menu.menuAction())

        # Diff Menu
        self.diff_menu = create_menu("&Diff", self.menubar)
        self.diff_menu.addAction(self.menu_branch_diff)
        self.diff_menu.addAction(self.menu_diff_expression)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.menu_branch_compare)
        self.diff_menu.addAction(self.menu_commit_compare)
        self.diff_menu.addAction(self.menu_commit_compare_file)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.menu_show_diffstat)
        # Add to menubar
        self.menubar.addAction(self.diff_menu.menuAction())

        # Tools Menu
        self.tools_menu = create_menu("&Tools", self.menubar)
        self.tools_menu.addAction(self.menu_classic)
        self.tools_menu.addAction(self.menu_dag)
        self.tools_menu.addSeparator()
        if self.classic_dockable:
            self.tools_menu.addAction(self.classicdockwidget.toggleViewAction())

        self.setup_dockwidget_tools_menu()
        self.menubar.addAction(self.tools_menu.menuAction())

        # Help Menu
        self.help_menu = create_menu("&Help", self.menubar)
        self.help_menu.addAction(self.menu_help_docs)
        self.help_menu.addAction(self.menu_help_shortcuts)
        self.help_menu.addAction(self.menu_help_about)
        # Add to menubar
        self.menubar.addAction(self.help_menu.menuAction())

        # Set main menu
        self.setMenuBar(self.menubar)

        # Arrange dock widgets
        top = Qt.TopDockWidgetArea
        bottom = Qt.BottomDockWidgetArea

        self.addDockWidget(top, self.commitdockwidget)
        if self.classic_dockable:
            self.addDockWidget(top, self.classicdockwidget)
        self.addDockWidget(top, self.statusdockwidget)
        self.addDockWidget(top, self.actionsdockwidget)
        self.addDockWidget(bottom, self.logdockwidget)
        if self.classic_dockable:
            self.tabifyDockWidget(self.classicdockwidget, self.commitdockwidget)
        self.tabifyDockWidget(self.logdockwidget, self.diffdockwidget)

        # Listen for model notifications
        model.add_message_observer(model.message_mode_changed, self._mode_changed)

        model.add_message_observer(model.message_updated, self._update_view)

        prefs_model.add_message_observer(prefs_model.message_config_updated, self._config_updated)

        # Add button callbacks
        connect_button(self.rescan_button, emit(self, signals.rescan_and_refresh))
        connect_button(self.alt_button, emit(self, signals.reset_mode))
        connect_button(self.fetch_button, guicmds.fetch)
        connect_button(self.push_button, guicmds.push)
        connect_button(self.pull_button, guicmds.pull)
        connect_button(self.stash_button, stash.stash)

        connect_button(self.stage_button, self.stage)
        connect_button(self.unstage_button, self.unstage)

        self.connect(self, SIGNAL("update"), self._update_callback)
        self.connect(self, SIGNAL("apply_state"), self.apply_state)
        self.connect(self, SIGNAL("install_config_actions"), self._install_config_actions)

        # Install .git-config-defined actions
        self._config_task = None
        self.install_config_actions()

        # Restore saved settings
        self._gui_state_task = None
        self._load_gui_state()

        log(0, self.model.git_version + "\ncola version " + version.version())

    # Qt overrides
    def closeEvent(self, event):
        """Save state in the settings manager."""
        qtutils.save_state(self)
        standard.MainWindow.closeEvent(self, event)

    # Accessors
    mode = property(lambda self: self.model.mode)

    def _mode_changed(self, mode):
        """React to mode changes; hide/show the "Exit Diff Mode" button."""
        if mode in (self.model.mode_branch, self.model.mode_review, self.model.mode_diff, self.model.mode_diff_expr):
            height = self.stage_button.minimumHeight()
            self.alt_button.setMinimumHeight(height)
            self.alt_button.show()
        else:
            self.alt_button.setMinimumHeight(1)
            self.alt_button.hide()

    def _config_updated(self, source, config, value):
        if config == "cola.fontdiff":
            font = QtGui.QFont()
            if not font.fromString(value):
                return
            qtutils.logger().setFont(font)
            self.diff_viewer.setFont(font)
            self.commitmsgeditor.setFont(font)

        elif config == "cola.tabwidth":
            # variable-tab-width setting
            self.diff_viewer.set_tab_width(value)

    def install_config_actions(self):
        """Install .gitconfig-defined actions"""
        self._config_task = self._start_config_actions_task()

    def _start_config_actions_task(self):
        """Do the expensive "get_config_actions()" call in the background"""

        class ConfigActionsTask(QtCore.QRunnable):
            def __init__(self, sender):
                QtCore.QRunnable.__init__(self)
                self._sender = sender

            def run(self):
                names = cfgactions.get_config_actions()
                self._sender.emit(SIGNAL("install_config_actions"), names)

        task = ConfigActionsTask(self)
        QtCore.QThreadPool.globalInstance().start(task)
        return task

    def _install_config_actions(self, names):
        """Install .gitconfig-defined actions"""
        if not names:
            return
        menu = self.actions_menu
        menu.addSeparator()
        for name in names:
            menu.addAction(name, emit(self, signals.run_config_action, name))

    def _update_view(self):
        self.emit(SIGNAL("update"))

    def _update_callback(self):
        """Update the title with the current branch and directory name."""
        branch = self.model.currentbranch
        curdir = core.decode(os.getcwd())
        msg = "Repository: %s\nBranch: %s" % (curdir, branch)
        self.commitdockwidget.setToolTip(msg)

        title = "%s: %s" % (self.model.project, branch)
        if self.mode in (self.model.mode_diff, self.model.mode_diff_expr):
            title += " *** diff mode***"
        elif self.mode == self.model.mode_review:
            title += " *** review mode***"
        elif self.mode == self.model.mode_amend:
            title += " *** amending ***"
        self.setWindowTitle(title)

        self.commitmsgeditor.set_mode(self.mode)

        if not self.model.read_only() and self.mode != self.model.mode_amend:
            # Check if there's a message file in .git/
            merge_msg_path = gitcmds.merge_message_path()
            if merge_msg_path is None:
                return
            merge_msg_hash = utils.checksum(core.decode(merge_msg_path))
            if merge_msg_hash == self.merge_message_hash:
                return
            self.merge_message_hash = merge_msg_hash
            cola.notifier().broadcast(signals.load_commit_message, core.decode(merge_msg_path))

    def apply_state(self, state):
        """Imports data for save/restore"""
        # 1 is the widget version; change when widgets are added/removed
        standard.MainWindow.apply_state(self, state)
        qtutils.apply_window_state(self, state, 1)

    def export_state(self):
        """Exports data for save/restore"""
        state = standard.MainWindow.export_state(self)
        return qtutils.export_window_state(self, state, self.widget_version)

    def _load_gui_state(self):
        """Restores the gui from the preferences file."""
        self._gui_state_task = self._start_gui_state_loading_thread()

    def _start_gui_state_loading_thread(self):
        """Do expensive file reading and json decoding in the background"""

        class LoadGUIStateTask(QtCore.QRunnable):
            def __init__(self, sender):
                QtCore.QRunnable.__init__(self)
                self._sender = sender

            def run(self):
                state = settings.Settings().get_gui_state(self._sender)
                self._sender.emit(SIGNAL("apply_state"), state)

        task = LoadGUIStateTask(self)
        QtCore.QThreadPool.globalInstance().start(task)
        return task

    def setup_dockwidget_tools_menu(self):
        # Hotkeys for toggling the dock widgets
        dockwidgets = (
            (self.logdockwidget, "Alt+0"),
            (self.commitdockwidget, "Alt+1"),
            (self.statusdockwidget, "Alt+2"),
            (self.diffdockwidget, "Alt+3"),
            (self.actionsdockwidget, "Alt+4"),
        )
        for dockwidget, shortcut in dockwidgets:
            # Associate the action with the shortcut
            action = dockwidget.toggleViewAction()
            action.setShortcut(shortcut)
            self.tools_menu.addAction(action)

            def showdock(show, dockwidget=dockwidget):
                if show:
                    dockwidget.raise_()
                    dockwidget.widget().setFocus(True)
                else:
                    self.setFocus(True)

            self.addAction(action)
            connect_action_bool(action, showdock)

            # Create a new shortcut Shift+<shortcut> that gives focus
            action = QtGui.QAction(self)
            action.setShortcut("Shift+" + shortcut)

            def focusdock(dockwidget=dockwidget, showdock=showdock):
                if dockwidget.toggleViewAction().isChecked():
                    showdock(True)
                else:
                    dockwidget.toggleViewAction().trigger()

            self.addAction(action)
            connect_action(action, focusdock)

    def stage(self):
        """Stage selected files, or all files if no selection exists."""
        paths = cola.selection_model().unstaged
        if not paths:
            cola.notifier().broadcast(signals.stage_modified)
        else:
            cola.notifier().broadcast(signals.stage, paths)

    def unstage(self):
        """Unstage selected files, or all files if no selection exists."""
        paths = cola.selection_model().staged
        if not paths:
            cola.notifier().broadcast(signals.unstage_all)
        else:
            cola.notifier().broadcast(signals.unstage, paths)

    def dragEnterEvent(self, event):
        """Accepts drops"""
        standard.MainWindow.dragEnterEvent(self, event)
        event.acceptProposedAction()

    def dropEvent(self, event):
        """Apply dropped patches with git-am"""
        event.accept()
        urls = event.mimeData().urls()
        if not urls:
            return
        paths = map(lambda x: unicode(x.path()), urls)
        patches = [p for p in paths if p.endswith(".patch")]
        dirs = [p for p in paths if os.path.isdir(p)]
        dirs.sort()
        for d in dirs:
            patches.extend(self._gather_patches(d))
        # Broadcast the patches to apply
        cola.notifier().broadcast(signals.apply_patches, patches)

    def _gather_patches(self, path):
        """Find patches in a subdirectory"""
        patches = []
        for root, subdirs, files in os.walk(path):
            for name in [f for f in files if f.endswith(".patch")]:
                patches.append(os.path.join(root, name))
        return patches
Ejemplo n.º 15
0
    def __init__(self, model, parent=None):
        Dialog.__init__(self, parent=parent)
        self.model = model
        self.stashes = []
        self.revids = []
        self.names = []

        self.setWindowTitle(N_('Stash'))
        self.setAttribute(QtCore.Qt.WA_MacMetalStyle)
        if parent is not None:
            self.setWindowModality(QtCore.Qt.WindowModal)
            self.resize(parent.width(), 420)
        else:
            self.resize(700, 420)

        self.stash_list = QtGui.QListWidget(self)
        self.stash_text = DiffTextEdit(self)

        self.button_apply = qtutils.create_toolbutton(
            text=N_('Apply'),
            tooltip=N_('Apply the selected stash'),
            icon=icons.ok())

        self.button_save = qtutils.create_toolbutton(
            text=N_('Save'),
            tooltip=N_('Save modified state to new stash'),
            icon=icons.save())

        self.button_drop = qtutils.create_toolbutton(
            text=N_('Drop'),
            tooltip=N_('Drop the selected stash'),
            icon=icons.discard())

        self.button_close = qtutils.close_button()

        self.keep_index = qtutils.checkbox(text=N_('Keep Index'), checked=True)

        # Arrange layouts
        self.splitter = qtutils.splitter(Qt.Horizontal,
                                         self.stash_list, self.stash_text)

        self.btn_layt = qtutils.hbox(defs.no_margin, defs.spacing,
                                     self.button_save, self.button_apply,
                                     self.button_drop, self.keep_index,
                                     qtutils.STRETCH, self.button_close)

        self.main_layt = qtutils.vbox(defs.margin, defs.spacing,
                                      self.splitter, self.btn_layt)
        self.setLayout(self.main_layt)

        self.splitter.setSizes([self.width()//3, self.width()*2//3])

        self.update_from_model()
        self.update_actions()

        self.setTabOrder(self.button_save, self.button_apply)
        self.setTabOrder(self.button_apply, self.button_drop)
        self.setTabOrder(self.button_drop, self.keep_index)
        self.setTabOrder(self.keep_index, self.button_close)

        self.connect(self.stash_list, SIGNAL('itemSelectionChanged()'),
                     self.item_selected)

        qtutils.connect_button(self.button_apply, self.stash_apply)
        qtutils.connect_button(self.button_save, self.stash_save)
        qtutils.connect_button(self.button_drop, self.stash_drop)
        qtutils.connect_button(self.button_close, self.close)
Ejemplo n.º 16
0
class StashView(Dialog):
    def __init__(self, model, parent=None):
        Dialog.__init__(self, parent=parent)
        self.model = model
        self.stashes = []
        self.revids = []
        self.names = []

        self.setWindowTitle(N_('Stash'))
        self.setAttribute(QtCore.Qt.WA_MacMetalStyle)
        if parent is not None:
            self.setWindowModality(QtCore.Qt.WindowModal)
            self.resize(parent.width(), 420)
        else:
            self.resize(700, 420)

        self.stash_list = QtGui.QListWidget(self)
        self.stash_text = DiffTextEdit(self)

        self.button_apply =\
            self.toolbutton(N_('Apply'),
                            N_('Apply the selected stash'),
                            qtutils.apply_icon())
        self.button_save =\
            self.toolbutton(N_('Save'),
                            N_('Save modified state to new stash'),
                            qtutils.save_icon())
        self.button_drop = \
            self.toolbutton(N_('Drop'),
                            N_('Drop the selected stash'),
                            qtutils.discard_icon())
        self.button_close = \
            self.pushbutton(N_('Close'),
                            N_('Close'), qtutils.close_icon())

        self.keep_index = QtGui.QCheckBox(self)
        self.keep_index.setText(N_('Keep Index'))
        self.keep_index.setChecked(True)

        # Arrange layouts
        self.main_layt = QtGui.QVBoxLayout()
        self.main_layt.setMargin(defs.margin)
        self.main_layt.setSpacing(defs.spacing)

        self.btn_layt = QtGui.QHBoxLayout()
        self.btn_layt.setMargin(defs.no_margin)
        self.btn_layt.setSpacing(defs.spacing)

        self.splitter = QtGui.QSplitter()
        self.splitter.setHandleWidth(defs.handle_width)
        self.splitter.setOrientation(QtCore.Qt.Horizontal)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.setStretchFactor(0, 1)
        self.splitter.setStretchFactor(1, 1)
        self.splitter.insertWidget(0, self.stash_list)
        self.splitter.insertWidget(1, self.stash_text)

        self.btn_layt.addWidget(self.button_save)
        self.btn_layt.addWidget(self.button_apply)
        self.btn_layt.addWidget(self.button_drop)
        self.btn_layt.addWidget(self.keep_index)
        self.btn_layt.addStretch()
        self.btn_layt.addWidget(self.button_close)

        self.main_layt.addWidget(self.splitter)
        self.main_layt.addLayout(self.btn_layt)
        self.setLayout(self.main_layt)

        self.splitter.setSizes([self.width()//3, self.width()*2//3])

        self.update_from_model()
        self.update_actions()

        self.setTabOrder(self.button_save, self.button_apply)
        self.setTabOrder(self.button_apply, self.button_drop)
        self.setTabOrder(self.button_drop, self.keep_index)
        self.setTabOrder(self.keep_index, self.button_close)

        self.connect(self.stash_list, SIGNAL('itemSelectionChanged()'),
                     self.item_selected)

        qtutils.connect_button(self.button_apply, self.stash_apply)
        qtutils.connect_button(self.button_save, self.stash_save)
        qtutils.connect_button(self.button_drop, self.stash_drop)
        qtutils.connect_button(self.button_close, self.close)

    def close(self):
        self.accept()
        cmds.do(cmds.Rescan)

    def toolbutton(self, text, tooltip, icon):
        return qtutils.create_toolbutton(text=text, tooltip=tooltip, icon=icon)

    def pushbutton(self, text, tooltip, icon):
        btn = QtGui.QPushButton(self)
        btn.setText(text)
        btn.setToolTip(tooltip)
        btn.setIcon(icon)
        return btn

    def selected_stash(self):
        """Returns the stash name of the currently selected stash
        """
        list_widget = self.stash_list
        stash_list = self.revids
        return qtutils.selected_item(list_widget, stash_list)

    def selected_name(self):
        list_widget = self.stash_list
        stash_list = self.names
        return qtutils.selected_item(list_widget, stash_list)

    def item_selected(self):
        """Shows the current stash in the main view."""
        self.update_actions()
        selection = self.selected_stash()
        if not selection:
            return
        diff_text = self.model.stash_diff(selection)
        self.stash_text.setPlainText(diff_text)

    def update_actions(self):
        has_changes = self.model.has_stashable_changes()
        has_stash = bool(self.selected_stash())
        self.button_save.setEnabled(has_changes)
        self.button_apply.setEnabled(has_stash)
        self.button_drop.setEnabled(has_stash)

    def update_from_model(self):
        """Initiates git queries on the model and updates the view
        """
        stashes, revids, names = self.model.stash_info()
        self.stashes = stashes
        self.revids = revids
        self.names = names

        self.stash_list.clear()
        self.stash_list.addItems(self.stashes)

    def stash_apply(self):
        """Applies the currently selected stash
        """
        selection = self.selected_stash()
        if not selection:
            return
        index = self.keep_index.isChecked()
        cmds.do(ApplyStash, selection, index)
        self.accept()
        cmds.do(cmds.Rescan)

    def stash_save(self):
        """Saves the worktree in a stash

        This prompts the user for a stash name and creates
        a git stash named accordingly.

        """
        stash_name, ok = qtutils.prompt(N_('Save Stash'),
                                        N_('Enter a name for the stash'))
        if not ok or not stash_name:
            return
        # Sanitize the stash name
        stash_name = utils.sanitize(stash_name)
        if stash_name in self.names:
            qtutils.critical(N_('Error: Stash exists'),
                             N_('A stash named "%s" already exists') % stash_name)
            return

        keep_index = self.keep_index.isChecked()
        cmds.do(SaveStash, stash_name, keep_index)
        self.accept()
        cmds.do(cmds.Rescan)

    def stash_drop(self):
        """Drops the currently selected stash
        """
        selection = self.selected_stash()
        name = self.selected_name()
        if not selection:
            return
        if not qtutils.confirm(N_('Drop Stash?'),
                               N_('Recovering a dropped stash is not possible.'),
                               N_('Drop the "%s" stash?') % name,
                               N_('Drop Stash'),
                               default=True,
                               icon=qtutils.discard_icon()):
            return
        cmds.do(DropStash, selection)
        self.update_from_model()
        self.stash_text.setPlainText('')
Ejemplo n.º 17
0
    def __init__(self, model, parent=None):
        Dialog.__init__(self, parent=parent)
        self.model = model
        self.stashes = []
        self.revids = []
        self.names = []

        self.setWindowTitle(N_('Stash'))
        self.setAttribute(QtCore.Qt.WA_MacMetalStyle)
        if parent is not None:
            self.setWindowModality(QtCore.Qt.WindowModal)
            self.resize(parent.width(), 420)
        else:
            self.resize(700, 420)

        self.stash_list = QtGui.QListWidget(self)
        self.stash_text = DiffTextEdit(self)

        self.button_apply =\
            self.toolbutton(N_('Apply'),
                            N_('Apply the selected stash'),
                            qtutils.apply_icon())
        self.button_save =\
            self.toolbutton(N_('Save'),
                            N_('Save modified state to new stash'),
                            qtutils.save_icon())
        self.button_drop = \
            self.toolbutton(N_('Drop'),
                            N_('Drop the selected stash'),
                            qtutils.discard_icon())
        self.button_close = \
            self.pushbutton(N_('Close'),
                            N_('Close'), qtutils.close_icon())

        self.keep_index = QtGui.QCheckBox(self)
        self.keep_index.setText(N_('Keep Index'))
        self.keep_index.setChecked(True)

        # Arrange layouts
        self.main_layt = QtGui.QVBoxLayout()
        self.main_layt.setMargin(defs.margin)
        self.main_layt.setSpacing(defs.spacing)

        self.btn_layt = QtGui.QHBoxLayout()
        self.btn_layt.setMargin(defs.no_margin)
        self.btn_layt.setSpacing(defs.spacing)

        self.splitter = QtGui.QSplitter()
        self.splitter.setHandleWidth(defs.handle_width)
        self.splitter.setOrientation(QtCore.Qt.Horizontal)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.setStretchFactor(0, 1)
        self.splitter.setStretchFactor(1, 1)
        self.splitter.insertWidget(0, self.stash_list)
        self.splitter.insertWidget(1, self.stash_text)

        self.btn_layt.addWidget(self.button_save)
        self.btn_layt.addWidget(self.button_apply)
        self.btn_layt.addWidget(self.button_drop)
        self.btn_layt.addWidget(self.keep_index)
        self.btn_layt.addStretch()
        self.btn_layt.addWidget(self.button_close)

        self.main_layt.addWidget(self.splitter)
        self.main_layt.addLayout(self.btn_layt)
        self.setLayout(self.main_layt)

        self.splitter.setSizes([self.width()//3, self.width()*2//3])

        self.update_from_model()
        self.update_actions()

        self.setTabOrder(self.button_save, self.button_apply)
        self.setTabOrder(self.button_apply, self.button_drop)
        self.setTabOrder(self.button_drop, self.keep_index)
        self.setTabOrder(self.keep_index, self.button_close)

        self.connect(self.stash_list, SIGNAL('itemSelectionChanged()'),
                     self.item_selected)

        qtutils.connect_button(self.button_apply, self.stash_apply)
        qtutils.connect_button(self.button_save, self.stash_save)
        qtutils.connect_button(self.button_drop, self.stash_drop)
        qtutils.connect_button(self.button_close, self.close)
Ejemplo n.º 18
0
class SelectCommitsDialog(QtGui.QDialog):

    def __init__(self, model,
                 parent=None, title=None, multiselect=True, syntax=True):
        QtGui.QDialog.__init__(self, parent)
        self.model = model
        if title:
            self.setWindowTitle(title)

        self.commit_list = QtGui.QListWidget()
        if multiselect:
            mode = QtGui.QAbstractItemView.ExtendedSelection
        else:
            mode = QtGui.QAbstractItemView.SingleSelection
        self.commit_list.setSelectionMode(mode)
        self.commit_list.setAlternatingRowColors(True)

        self.commit_text = DiffTextEdit(self, whitespace=False)

        self.label = QtGui.QLabel()
        self.label.setText(N_('Revision Expression:'))
        self.revision = QtGui.QLineEdit()
        self.revision.setReadOnly(True)

        self.select_button = qtutils.ok_button(N_('Select'),
                                               enabled=False, default=True)
        self.close_button = qtutils.close_button()

        # Make the list widget slighty larger
        self.splitter = qtutils.splitter(Qt.Vertical,
                                         self.commit_list, self.commit_text)
        self.splitter.setSizes([100, 150])

        self.input_layout = qtutils.hbox(defs.no_margin, defs.spacing,
                                         self.label, self.revision,
                                         self.select_button, self.close_button)

        self.main_layout = qtutils.vbox(defs.margin, defs.margin,
                                        self.splitter, self.input_layout)
        self.setLayout(self.main_layout)

        self.connect(self.commit_list, SIGNAL('itemSelectionChanged()'),
                     self.commit_sha1_selected)

        self.connect(self.commit_list,
                     SIGNAL('itemDoubleClicked(QListWidgetItem*)'),
                     self.commit_sha1_double_clicked)

        qtutils.connect_button(self.select_button, self.accept)
        qtutils.connect_button(self.close_button, self.reject)

        self.resize(700, 420)

    def selected_commit(self):
        return qtutils.selected_item(self.commit_list, self.model.revisions)

    def selected_commits(self):
        return qtutils.selected_items(self.commit_list, self.model.revisions)

    def select_commits(self):
        summaries = self.model.summaries
        if not summaries:
            msg = N_('No commits exist in this branch.')
            Interaction.log(msg)
            return []
        qtutils.set_items(self.commit_list, summaries)
        self.show()
        if self.exec_() != QtGui.QDialog.Accepted:
            return []
        return self.selected_commits()

    def commit_sha1_selected(self):
        sha1 = self.selected_commit()
        selected = sha1 is not None
        self.select_button.setEnabled(selected)
        if not selected:
            self.commit_text.setText('')
            self.revision.setText('')
            return
        self.revision.setText(sha1)
        self.revision.selectAll()
        # Display the sha1's commit
        commit_diff = gitcmds.commit_diff(sha1)
        self.commit_text.setText(commit_diff)

    def commit_sha1_double_clicked(self, item):
        sha1 = self.selected_commit()
        if sha1:
            self.accept()