Example #1
0
    def _create_unstaged_context_menu(self, menu, s):
        modified_submodule = (s.modified and
                              s.modified[0] in self.m.submodules)
        if modified_submodule:
            return self._create_modified_submodule_context_menu(menu, s)

        if self.unstaged():
            action = menu.addAction(qtutils.options_icon(),
                                    cmds.LaunchEditor.name(),
                                    cmds.run(cmds.LaunchEditor))
            action.setShortcut(cmds.Edit.SHORTCUT)

        if s.modified and self.m.stageable():
            action = menu.addAction(qtutils.git_icon(),
                                    cmds.LaunchDifftool.name(),
                                    cmds.run(cmds.LaunchDifftool))
            action.setShortcut(cmds.LaunchDifftool.SHORTCUT)

        if self.m.stageable():
            menu.addSeparator()
            action = menu.addAction(qtutils.icon('add.svg'),
                                    N_('Stage Selected'),
                                    cmds.run(cmds.Stage, self.unstaged()))
            action.setShortcut(cmds.Stage.SHORTCUT)

        if s.modified and self.m.stageable():
            if self.m.undoable():
                menu.addSeparator()
                menu.addAction(qtutils.icon('undo.svg'),
                               N_('Revert Unstaged Edits...'),
                               self._revert_unstaged_edits)
                menu.addAction(qtutils.icon('undo.svg'),
                               N_('Revert Uncommited Edits...'),
                               lambda: self._revert_uncommitted_edits(
                                            self.modified()))

        if self.unstaged() and not utils.is_win32():
            menu.addSeparator()
            action = menu.addAction(qtutils.file_icon(),
                    cmds.OpenDefaultApp.name(),
                    cmds.run(cmds.OpenDefaultApp, self.unstaged()))
            action.setShortcut(cmds.OpenDefaultApp.SHORTCUT)

            action = menu.addAction(qtutils.open_file_icon(),
                    cmds.OpenParentDir.name(),
                    self._open_parent_dir)
            action.setShortcut(cmds.OpenParentDir.SHORTCUT)

        if s.untracked:
            menu.addSeparator()
            menu.addAction(qtutils.discard_icon(),
                           N_('Delete File(s)...'), self._delete_files)
            menu.addSeparator()
            menu.addAction(qtutils.icon('edit-clear.svg'),
                           N_('Add to .gitignore'),
                           cmds.run(cmds.Ignore,
                                map(lambda x: '/' + x, self.untracked())))
        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        return menu
Example #2
0
    def _create_staged_context_menu(self, menu, s):
        if s.staged[0] in self.m.submodules:
            return self._create_staged_submodule_context_menu(menu, s)

        if self.m.unstageable():
            action = menu.addAction(
                qtutils.remove_icon(), N_("Unstage Selected"), cmds.run(cmds.Unstage, self.staged())
            )
            action.setShortcut(cmds.Unstage.SHORTCUT)

        # Do all of the selected items exist?
        all_exist = all(not i in self.m.staged_deleted and core.exists(i) for i in self.staged())

        if all_exist:
            menu.addAction(self.launch_editor_action)
            menu.addAction(self.launch_difftool_action)

        if all_exist and not utils.is_win32():
            menu.addSeparator()
            action = menu.addAction(
                qtutils.file_icon(), cmds.OpenDefaultApp.name(), cmds.run(cmds.OpenDefaultApp, self.staged())
            )
            action.setShortcut(cmds.OpenDefaultApp.SHORTCUT)

            action = menu.addAction(qtutils.open_file_icon(), cmds.OpenParentDir.name(), self._open_parent_dir)
            action.setShortcut(cmds.OpenParentDir.SHORTCUT)

        if self.m.undoable():
            menu.addSeparator()
            menu.addAction(self.revert_unstaged_edits_action)

        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        menu.addAction(self.copy_relpath_action)
        return menu
Example #3
0
    def _create_header_context_menu(self, menu, idx):
        if idx == self.idx_staged:
            menu.addAction(qtutils.remove_icon(),
                           N_('Unstage All'),
                           cmds.run(cmds.UnstageAll))
            return menu
        elif idx == self.idx_unmerged:
            action = menu.addAction(qtutils.add_icon(),
                                    cmds.StageUnmerged.name(),
                                    cmds.run(cmds.StageUnmerged))
            action.setShortcut(hotkeys.STAGE_SELECTION)
            return menu
        elif idx == self.idx_modified:
            action = menu.addAction(qtutils.add_icon(),
                                    cmds.StageModified.name(),
                                    cmds.run(cmds.StageModified))
            action.setShortcut(hotkeys.STAGE_SELECTION)
            return menu

        elif idx == self.idx_untracked:
            action = menu.addAction(qtutils.add_icon(),
                                    cmds.StageUntracked.name(),
                                    cmds.run(cmds.StageUntracked))
            action.setShortcut(hotkeys.STAGE_SELECTION)
            return menu
Example #4
0
    def __init__(self, parent, titlebar):
        DiffTextEdit.__init__(self, parent)
        self.model = model = main.model()

        # "Diff Options" tool menu
        self.diff_ignore_space_at_eol_action = add_action(self,
                N_('Ignore changes in whitespace at EOL'),
                self._update_diff_opts)
        self.diff_ignore_space_at_eol_action.setCheckable(True)

        self.diff_ignore_space_change_action = add_action(self,
                N_('Ignore changes in amount of whitespace'),
                self._update_diff_opts)
        self.diff_ignore_space_change_action.setCheckable(True)

        self.diff_ignore_all_space_action = add_action(self,
                N_('Ignore all whitespace'),
                self._update_diff_opts)
        self.diff_ignore_all_space_action.setCheckable(True)

        self.diff_function_context_action = add_action(self,
                N_('Show whole surrounding functions of changes'),
                self._update_diff_opts)
        self.diff_function_context_action.setCheckable(True)

        self.diffopts_button = create_action_button(
                tooltip=N_('Diff Options'), icon=options_icon())
        self.diffopts_menu = create_menu(N_('Diff Options'),
                                         self.diffopts_button)

        self.diffopts_menu.addAction(self.diff_ignore_space_at_eol_action)
        self.diffopts_menu.addAction(self.diff_ignore_space_change_action)
        self.diffopts_menu.addAction(self.diff_ignore_all_space_action)
        self.diffopts_menu.addAction(self.diff_function_context_action)
        self.diffopts_button.setMenu(self.diffopts_menu)
        qtutils.hide_button_menu_indicator(self.diffopts_button)

        titlebar.add_corner_widget(self.diffopts_button)

        self.action_apply_selection = qtutils.add_action(self, '',
                self.apply_selection, Qt.Key_S)

        self.action_revert_selection = qtutils.add_action(self, '',
                self.revert_selection)
        self.action_revert_selection.setIcon(qtutils.icon('undo.svg'))

        self.launch_editor = qtutils.add_action(self,
                cmds.LaunchEditor.name(), run(cmds.LaunchEditor),
                cmds.LaunchEditor.SHORTCUT,
                'Return', 'Enter')
        self.launch_editor.setIcon(qtutils.options_icon())

        self.launch_difftool = qtutils.add_action(self,
                cmds.LaunchDifftool.name(), run(cmds.LaunchDifftool),
                cmds.LaunchDifftool.SHORTCUT)
        self.launch_difftool.setIcon(qtutils.icon('git.svg'))

        model.add_observer(model.message_diff_text_changed, self._emit_text)

        self.connect(self, SIGNAL('set_text'), self.setPlainText)
Example #5
0
    def _create_staged_context_menu(self, menu, s):
        if s.staged[0] in self.m.submodules:
            return self._create_staged_submodule_context_menu(menu, s)

        if self.m.unstageable():
            action = menu.addAction(qtutils.icon('remove.svg'),
                                    N_('Unstage Selected'),
                                    cmds.run(cmds.Unstage, self.staged()))
            action.setShortcut(cmds.Unstage.SHORTCUT)

        menu.addAction(self.launch_editor)
        menu.addAction(self.launch_difftool)

        if not utils.is_win32():
            menu.addSeparator()
            action = menu.addAction(qtutils.file_icon(),
                    cmds.OpenDefaultApp.name(),
                    cmds.run(cmds.OpenDefaultApp, self.staged()))
            action.setShortcut(cmds.OpenDefaultApp.SHORTCUT)

            action = menu.addAction(qtutils.open_file_icon(),
                    cmds.OpenParentDir.name(),
                    self._open_parent_dir)
            action.setShortcut(cmds.OpenParentDir.SHORTCUT)

        if self.m.undoable():
            menu.addSeparator()
            menu.addAction(self.revert_unstaged_edits_action)
            menu.addAction(qtutils.icon('undo.svg'),
                           N_('Revert Uncommited Edits...'),
                           lambda: self._revert_uncommitted_edits(
                                        self.staged()))
        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        return menu
Example #6
0
    def _create_header_context_menu(self, menu, idx):
        if idx == self.idx_staged:
            menu.addAction(qtutils.icon('remove.svg'),
                           N_('Unstage All'),
                           cmds.run(cmds.UnstageAll))
            return menu
        elif idx == self.idx_unmerged:
            action = menu.addAction(qtutils.icon('add.svg'),
                                    cmds.StageUnmerged.name(),
                                    cmds.run(cmds.StageUnmerged))
            action.setShortcut(cmds.StageUnmerged.SHORTCUT)
            return menu
        elif idx == self.idx_modified:
            action = menu.addAction(qtutils.icon('add.svg'),
                                    cmds.StageModified.name(),
                                    cmds.run(cmds.StageModified))
            action.setShortcut(cmds.StageModified.SHORTCUT)
            return menu

        elif idx == self.idx_untracked:
            action = menu.addAction(qtutils.icon('add.svg'),
                                    cmds.StageUntracked.name(),
                                    cmds.run(cmds.StageUntracked))
            action.setShortcut(cmds.StageUntracked.SHORTCUT)
            return menu
Example #7
0
    def _create_unmerged_context_menu(self, menu, s):
        menu.addAction(self.launch_difftool_action)

        action = menu.addAction(icons.add(), N_('Stage Selected'),
                                cmds.run(cmds.Stage, self.unstaged()))
        action.setShortcut(hotkeys.STAGE_SELECTION)
        menu.addSeparator()
        menu.addAction(self.launch_editor_action)

        if not utils.is_win32():
            menu.addSeparator()
            open_default = cmds.run(cmds.OpenDefaultApp, self.unmerged())
            action = menu.addAction(icons.default_app(),
                                    cmds.OpenDefaultApp.name(), open_default)
            action.setShortcut(hotkeys.PRIMARY_ACTION)

            action = menu.addAction(icons.folder(),
                                    cmds.OpenParentDir.name(),
                                    self._open_parent_dir)
            action.setShortcut(hotkeys.SECONDARY_ACTION)

        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        menu.addAction(self.copy_relpath_action)
        menu.addAction(self.view_history_action)
        menu.addAction(self.view_blame_action)
        return menu
Example #8
0
    def _create_unmerged_context_menu(self, menu, s):
        menu.addAction(self.launch_difftool_action)

        action = menu.addAction(qtutils.icon('add.svg'),
                                N_('Stage Selected'),
                                cmds.run(cmds.Stage, self.unstaged()))
        action.setShortcut(cmds.Stage.SHORTCUT)
        menu.addSeparator()
        menu.addAction(self.launch_editor_action)

        if not utils.is_win32():
            menu.addSeparator()
            action = menu.addAction(qtutils.file_icon(),
                    cmds.OpenDefaultApp.name(),
                    cmds.run(cmds.OpenDefaultApp, self.unmerged()))
            action.setShortcut(cmds.OpenDefaultApp.SHORTCUT)

            action = menu.addAction(qtutils.open_file_icon(),
                    cmds.OpenParentDir.name(),
                    self._open_parent_dir)
            action.setShortcut(cmds.OpenParentDir.SHORTCUT)

        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        menu.addAction(self.copy_relpath_action)
        return menu
Example #9
0
    def _create_unmerged_context_menu(self, menu, s):
        menu.addAction(qtutils.git_icon(),
                       self.tr('Launch Merge Tool'),
                       cmds.run(cmds.Mergetool, self.unmerged()))

        action = menu.addAction(qtutils.icon('add.svg'),
                                self.tr('Stage Selected'),
                                cmds.run(cmds.Stage, self.unstaged()))
        action.setShortcut(cmds.Stage.SHORTCUT)
        menu.addSeparator()
        action = menu.addAction(qtutils.options_icon(),
                                self.tr(cmds.LaunchEditor.NAME),
                                cmds.run(cmds.LaunchEditor))
        action.setShortcut(cmds.LaunchEditor.SHORTCUT)

        if not utils.is_win32():
            menu.addSeparator()
            action = menu.addAction(qtutils.file_icon(),
                    self.tr(cmds.OpenDefaultApp.NAME),
                    cmds.run(cmds.OpenDefaultApp, self.unmerged()))
            action.setShortcut(cmds.OpenDefaultApp.SHORTCUT)

            action = menu.addAction(qtutils.open_file_icon(),
                    self.tr(cmds.OpenParentDir.NAME),
                    self._open_parent_dir)
            action.setShortcut(cmds.OpenParentDir.SHORTCUT)

        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        return menu
Example #10
0
    def _create_staged_context_menu(self, menu, s):
        if s.staged[0] in self.m.submodules:
            return self._create_staged_submodule_context_menu(menu, s)

        if self.m.unstageable():
            action = menu.addAction(icons.remove(), N_("Unstage Selected"), cmds.run(cmds.Unstage, self.staged()))
            action.setShortcut(hotkeys.STAGE_SELECTION)

        # Do all of the selected items exist?
        all_exist = all(not i in self.m.staged_deleted and core.exists(i) for i in self.staged())

        if all_exist:
            menu.addAction(self.launch_editor_action)
            menu.addAction(self.launch_difftool_action)

        if all_exist and not utils.is_win32():
            menu.addSeparator()
            open_default = cmds.run(cmds.OpenDefaultApp, self.staged())
            action = menu.addAction(icons.default_app(), cmds.OpenDefaultApp.name(), open_default)
            action.setShortcut(hotkeys.PRIMARY_ACTION)

            action = menu.addAction(icons.folder(), cmds.OpenParentDir.name(), self._open_parent_dir)
            action.setShortcut(hotkeys.SECONDARY_ACTION)

        if self.m.undoable():
            menu.addSeparator()
            menu.addAction(self.revert_unstaged_edits_action)

        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        menu.addAction(self.copy_relpath_action)
        menu.addAction(self.view_history_action)
        menu.addAction(self.view_blame_action)
        return menu
Example #11
0
    def __init__(self, parent):
        standard.TreeView.__init__(self, parent)

        self.setSortingEnabled(False)
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)

        # Observe model updates
        model = cola.model()
        model.add_observer(model.message_updated, self.update_actions)

        # The non-Qt cola application model
        self.connect(self, SIGNAL('expanded(QModelIndex)'), self.size_columns)
        self.connect(self, SIGNAL('collapsed(QModelIndex)'), self.size_columns)

        # Sync selection before the key press event changes the model index
        self.connect(self, SIGNAL('indexAboutToChange()'), self.sync_selection)

        self.action_history =\
                self._create_action(
                        N_('View History...'),
                        N_('View history for selected path(s).'),
                        self.view_history,
                        'Shift+Ctrl+H')
        self.action_stage =\
                self._create_action(N_('Stage Selected'),
                                    N_('Stage selected path(s) for commit.'),
                                    self.stage_selected,
                                    cmds.Stage.SHORTCUT)
        self.action_unstage =\
                self._create_action(
                        N_('Unstage Selected'),
                        N_('Remove selected path(s) from the staging area.'),
                        self.unstage_selected,
                        'Ctrl+U')

        self.action_untrack =\
                self._create_action(N_('Untrack Selected'),
                                    N_('Stop tracking path(s)'),
                                    self.untrack_selected)

        self.action_difftool =\
                self._create_action(cmds.LaunchDifftool.name(),
                                    N_('Launch git-difftool on the current path.'),
                                    run(cmds.LaunchDifftool),
                                    cmds.LaunchDifftool.SHORTCUT)
        self.action_difftool_predecessor =\
                self._create_action(N_('Diff Against Predecessor...'),
                                    N_('Launch git-difftool against previous versions.'),
                                    self.difftool_predecessor,
                                    'Shift+Ctrl+D')
        self.action_revert =\
                self._create_action(N_('Revert Uncommitted Changes...'),
                                    N_('Revert changes to selected path(s).'),
                                    self.revert,
                                    'Ctrl+Z')
        self.action_editor =\
                self._create_action(cmds.LaunchEditor.name(),
                                    N_('Edit selected path(s).'),
                                    run(cmds.LaunchEditor),
                                    cmds.LaunchDifftool.SHORTCUT)
Example #12
0
    def contextMenuEvent(self, event):
        """Create the context menu for the diff display."""
        menu = QtGui.QMenu(self)
        s = selection.selection()

        if self.model.stageable():
            if s.modified and s.modified[0] in main.model().submodules:
                action = menu.addAction(qtutils.icon('add.svg'),
                                        cmds.Stage.name(),
                                        cmds.run(cmds.Stage, s.modified))
                action.setShortcut(cmds.Stage.SHORTCUT)
                menu.addAction(qtutils.git_icon(),
                               N_('Launch git-cola'),
                               cmds.run(cmds.OpenRepo,
                                        core.abspath(s.modified[0])))
            elif s.modified:
                action = menu.addAction(qtutils.icon('add.svg'),
                                        N_('Stage Section'),
                                        self.stage_section)
                action.setShortcut(Qt.Key_H)
                menu.addAction(self.action_stage_selection)
                menu.addSeparator()
                menu.addAction(qtutils.icon('undo.svg'),
                               N_('Revert Section...'),
                               self.revert_section)
                menu.addAction(self.action_revert_selection)

        if self.model.unstageable():
            if s.staged and s.staged[0] in main.model().submodules:
                action = menu.addAction(qtutils.icon('remove.svg'),
                                        cmds.Unstage.name(),
                                        cmds.do(cmds.Unstage, s.staged))
                action.setShortcut(cmds.Unstage.SHORTCUT)
                menu.addAction(qtutils.git_icon(),
                               N_('Launch git-cola'),
                               cmds.do(cmds.OpenRepo,
                                       core.abspath(s.staged[0])))
            elif s.staged:
                action = menu.addAction(qtutils.icon('remove.svg'),
                                        N_('Unstage Section'),
                                        self.unstage_section)
                action.setShortcut(Qt.Key_H)
                menu.addAction(self.action_unstage_selection)

        if self.model.stageable() or self.model.unstageable():
            menu.addSeparator()
            menu.addAction(self.launch_editor)
            menu.addAction(self.launch_difftool)

        menu.addSeparator()
        action = menu.addAction(qtutils.icon('edit-copy.svg'),
                                N_('Copy'), self.copy)
        action.setShortcut(QtGui.QKeySequence.Copy)

        action = menu.addAction(qtutils.icon('edit-select-all.svg'),
                                N_('Select All'), self.selectAll)
        action.setShortcut(QtGui.QKeySequence.SelectAll)
        menu.exec_(self.mapToGlobal(event.pos()))
Example #13
0
    def __init__(self, parent):
        standard.TreeView.__init__(self, parent)

        self.setRootIsDecorated(True)
        self.setSortingEnabled(False)
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)

        # Observe model updates
        model = main.model()
        model.add_observer(model.message_updated, self.update_actions)

        # The non-Qt cola application model
        self.connect(self, SIGNAL("expanded(QModelIndex)"), self.size_columns)
        self.connect(self, SIGNAL("collapsed(QModelIndex)"), self.size_columns)

        # Sync selection before the key press event changes the model index
        self.connect(self, SIGNAL("indexAboutToChange()"), self.sync_selection)

        self.action_history = self._create_action(
            N_("View History..."), N_("View history for selected path(s)."), self.view_history, "Shift+Ctrl+H"
        )
        self.action_stage = self._create_action(
            N_("Stage Selected"), N_("Stage selected path(s) for commit."), self.stage_selected, cmds.Stage.SHORTCUT
        )
        self.action_unstage = self._create_action(
            N_("Unstage Selected"),
            N_("Remove selected path(s) from the staging area."),
            self.unstage_selected,
            "Ctrl+U",
        )

        self.action_untrack = self._create_action(
            N_("Untrack Selected"), N_("Stop tracking path(s)"), self.untrack_selected
        )

        self.action_difftool = self._create_action(
            cmds.LaunchDifftool.name(),
            N_("Launch git-difftool on the current path."),
            cmds.run(cmds.LaunchDifftool),
            cmds.LaunchDifftool.SHORTCUT,
        )

        self.action_difftool_predecessor = self._create_action(
            N_("Diff Against Predecessor..."),
            N_("Launch git-difftool against previous versions."),
            self.difftool_predecessor,
            "Shift+Ctrl+D",
        )
        self.action_revert = self._create_action(
            N_("Revert Uncommitted Changes..."), N_("Revert changes to selected path(s)."), self.revert, "Ctrl+Z"
        )
        self.action_editor = self._create_action(
            cmds.LaunchEditor.name(),
            N_("Edit selected path(s)."),
            cmds.run(cmds.LaunchEditor),
            cmds.LaunchEditor.SHORTCUT,
        )
Example #14
0
    def _create_unstaged_context_menu(self, menu, s):
        modified_submodule = (s.modified and
                              s.modified[0] in self.m.submodules)
        if modified_submodule:
            return self._create_modified_submodule_context_menu(menu, s)

        if self.m.stageable():
            action = menu.addAction(qtutils.icon('add.svg'),
                                    N_('Stage Selected'),
                                    cmds.run(cmds.Stage, self.unstaged()))
            action.setShortcut(cmds.Stage.SHORTCUT)

        # Do all of the selected items exist?
        unstaged_items = self.unstaged_items()
        all_exist = all([i.exists for i in unstaged_items])

        if all_exist and self.unstaged():
            menu.addAction(self.launch_editor_action)

        if all_exist and s.modified and self.m.stageable():
            menu.addAction(self.launch_difftool_action)

        if s.modified and self.m.stageable():
            if self.m.undoable():
                menu.addSeparator()
                menu.addAction(self.revert_unstaged_edits_action)
                menu.addAction(qtutils.icon('undo.svg'),
                               N_('Revert Uncommited Edits...'),
                               lambda: self._revert_uncommitted_edits(
                                            self.modified()))

        if all_exist and self.unstaged() and not utils.is_win32():
            menu.addSeparator()
            action = menu.addAction(qtutils.file_icon(),
                    cmds.OpenDefaultApp.name(),
                    cmds.run(cmds.OpenDefaultApp, self.unstaged()))
            action.setShortcut(cmds.OpenDefaultApp.SHORTCUT)

            action = menu.addAction(qtutils.open_file_icon(),
                    cmds.OpenParentDir.name(),
                    self._open_parent_dir)
            action.setShortcut(cmds.OpenParentDir.SHORTCUT)

        if all_exist and s.untracked:
            menu.addSeparator()
            if self.move_to_trash_action is not None:
                menu.addAction(self.move_to_trash_action)
            menu.addAction(self.delete_untracked_files_action)
            menu.addSeparator()
            menu.addAction(qtutils.icon('edit-clear.svg'),
                           N_('Add to .gitignore'),
                           cmds.run(cmds.Ignore,
                                map(lambda x: '/' + x, self.untracked())))
        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        return menu
Example #15
0
    def _create_unstaged_context_menu(self, menu, s):
        modified_submodule = (s.modified and
                              s.modified[0] in self.m.submodules)
        if modified_submodule:
            return self._create_modified_submodule_context_menu(menu, s)

        if self.m.stageable():
            action = menu.addAction(icons.add(), N_('Stage Selected'),
                                    cmds.run(cmds.Stage, self.unstaged()))
            action.setShortcut(hotkeys.STAGE_SELECTION)

        # Do all of the selected items exist?
        all_exist = all(i not in self.m.unstaged_deleted and core.exists(i)
                        for i in self.staged())

        if all_exist and self.unstaged():
            menu.addAction(self.launch_editor_action)

        if all_exist and s.modified and self.m.stageable():
            menu.addAction(self.launch_difftool_action)

        if s.modified and self.m.stageable():
            if self.m.undoable():
                menu.addSeparator()
                menu.addAction(self.revert_unstaged_edits_action)

        if all_exist and self.unstaged() and not utils.is_win32():
            menu.addSeparator()
            open_default = cmds.run(cmds.OpenDefaultApp, self.unstaged())
            action = menu.addAction(icons.default_app(),
                                    cmds.OpenDefaultApp.name(), open_default)
            action.setShortcut(hotkeys.PRIMARY_ACTION)

            action = menu.addAction(icons.folder(),
                                    cmds.OpenParentDir.name(),
                                    self._open_parent_dir)
            action.setShortcut(hotkeys.SECONDARY_ACTION)

        if all_exist and s.untracked:
            menu.addSeparator()
            if self.move_to_trash_action is not None:
                menu.addAction(self.move_to_trash_action)
            menu.addAction(self.delete_untracked_files_action)
            menu.addSeparator()
            menu.addAction(icons.edit(),
                           N_('Add to .gitignore'),
                           cmds.run(cmds.Ignore,
                                    [('/' + x) for x in self.untracked()]))
        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        menu.addAction(self.copy_relpath_action)
        if not selection.selection_model().is_empty():
            menu.addAction(self.view_history_action)
            menu.addAction(self.view_blame_action)
        return menu
Example #16
0
    def __init__(self, parent):
        DiffTextEdit.__init__(self, parent)
        self.model = model = main.model()
        self.mode = self.model.mode_none

        self.action_process_section = qtutils.add_action(self,
                N_('Process Section'),
                self.apply_section, Qt.Key_H)
        self.action_process_selection = qtutils.add_action(self,
                N_('Process Selection'),
                self.apply_selection, Qt.Key_S)

        self.launch_editor = qtutils.add_action(self,
                cmds.LaunchEditor.name(), run(cmds.LaunchEditor),
                cmds.LaunchEditor.SHORTCUT,
                'Return', 'Enter')
        self.launch_editor.setIcon(qtutils.options_icon())

        self.launch_difftool = qtutils.add_action(self,
                cmds.LaunchDifftool.name(), run(cmds.LaunchDifftool),
                cmds.LaunchDifftool.SHORTCUT)
        self.launch_difftool.setIcon(qtutils.icon('git.svg'))

        self.action_stage_selection = qtutils.add_action(self,
                N_('Stage &Selected Lines'),
                self.stage_selection)
        self.action_stage_selection.setIcon(qtutils.icon('add.svg'))
        self.action_stage_selection.setShortcut(Qt.Key_S)

        self.action_revert_selection = qtutils.add_action(self,
                N_('Revert Selected Lines...'),
                self.revert_selection)
        self.action_revert_selection.setIcon(qtutils.icon('undo.svg'))

        self.action_unstage_selection = qtutils.add_action(self,
                N_('Unstage &Selected Lines'),
                self.unstage_selection)
        self.action_unstage_selection.setIcon(qtutils.icon('remove.svg'))
        self.action_unstage_selection.setShortcut(Qt.Key_S)

        self.action_apply_selection = qtutils.add_action(self,
                N_('Apply Diff Selection to Work Tree'),
                self.stage_selection)
        self.action_apply_selection.setIcon(qtutils.apply_icon())

        model.add_observer(model.message_mode_about_to_change,
                           self._mode_about_to_change)
        model.add_observer(model.message_diff_text_changed, self._emit_text)

        self.connect(self, SIGNAL('copyAvailable(bool)'),
                     self.enable_selection_actions)

        self.connect(self, SIGNAL('set_text'), self.setPlainText)
Example #17
0
    def _create_unstaged_context_menu(self, menu, s):
        modified_submodule = s.modified and s.modified[0] in self.m.submodules
        if modified_submodule:
            return self._create_modified_submodule_context_menu(menu, s)

        if self.m.stageable():
            action = menu.addAction(
                qtutils.icon("add.svg"), N_("Stage Selected"), cmds.run(cmds.Stage, self.unstaged())
            )
            action.setShortcut(cmds.Stage.SHORTCUT)

        # Do all of the selected items exist?
        unstaged_items = self.unstaged_items()
        all_exist = all([i.exists for i in unstaged_items])

        if all_exist and self.unstaged():
            menu.addAction(self.launch_editor)

        if all_exist and s.modified and self.m.stageable():
            menu.addAction(self.launch_difftool)

        if s.modified and self.m.stageable():
            if self.m.undoable():
                menu.addSeparator()
                menu.addAction(self.revert_unstaged_edits_action)
                menu.addAction(
                    qtutils.icon("undo.svg"),
                    N_("Revert Uncommited Edits..."),
                    lambda: self._revert_uncommitted_edits(self.modified()),
                )

        if all_exist and self.unstaged() and not utils.is_win32():
            menu.addSeparator()
            action = menu.addAction(
                qtutils.file_icon(), cmds.OpenDefaultApp.name(), cmds.run(cmds.OpenDefaultApp, self.unstaged())
            )
            action.setShortcut(cmds.OpenDefaultApp.SHORTCUT)

            action = menu.addAction(qtutils.open_file_icon(), cmds.OpenParentDir.name(), self._open_parent_dir)
            action.setShortcut(cmds.OpenParentDir.SHORTCUT)

        if all_exist and s.untracked:
            menu.addSeparator()
            menu.addAction(qtutils.discard_icon(), N_("Delete File(s)..."), self._delete_files)
            menu.addSeparator()
            menu.addAction(
                qtutils.icon("edit-clear.svg"),
                N_("Add to .gitignore"),
                cmds.run(cmds.Ignore, map(lambda x: "/" + x, self.untracked())),
            )
        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        return menu
Example #18
0
    def _create_staged_submodule_context_menu(self, menu, s):
        menu.addAction(qtutils.git_icon(), N_("Launch git-cola"), cmds.run(cmds.OpenRepo, core.abspath(s.staged[0])))

        menu.addAction(self.launch_editor_action)
        menu.addSeparator()

        action = menu.addAction(qtutils.remove_icon(), N_("Unstage Selected"), cmds.run(cmds.Unstage, self.staged()))
        action.setShortcut(cmds.Unstage.SHORTCUT)
        menu.addSeparator()

        menu.addAction(self.copy_path_action)
        menu.addAction(self.copy_relpath_action)
        return menu
Example #19
0
    def _create_staged_submodule_context_menu(self, menu, s):
        menu.addAction(icons.cola(), N_("Launch git-cola"), cmds.run(cmds.OpenRepo, core.abspath(s.staged[0])))

        menu.addAction(self.launch_editor_action)
        menu.addSeparator()

        action = menu.addAction(icons.remove(), N_("Unstage Selected"), cmds.run(cmds.Unstage, self.staged()))
        action.setShortcut(hotkeys.STAGE_SELECTION)
        menu.addSeparator()

        menu.addAction(self.copy_path_action)
        menu.addAction(self.copy_relpath_action)
        menu.addAction(self.view_history_action)
        return menu
Example #20
0
    def _create_modified_submodule_context_menu(self, menu, s):
        menu.addAction(qtutils.git_icon(), N_("Launch git-cola"), cmds.run(cmds.OpenRepo, core.abspath(s.modified[0])))

        menu.addAction(self.launch_editor)

        if self.m.stageable():
            menu.addSeparator()
            action = menu.addAction(
                qtutils.icon("add.svg"), N_("Stage Selected"), cmds.run(cmds.Stage, self.unstaged())
            )
            action.setShortcut(cmds.Stage.SHORTCUT)

        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        return menu
Example #21
0
    def _create_unstaged_context_menu(self, menu, s):
        modified_submodule = s.modified and s.modified[0] in self.m.submodules
        if modified_submodule:
            return self._create_modified_submodule_context_menu(menu, s)

        if self.m.stageable():
            action = menu.addAction(qtutils.add_icon(), N_("Stage Selected"), cmds.run(cmds.Stage, self.unstaged()))
            action.setShortcut(cmds.Stage.SHORTCUT)

        # Do all of the selected items exist?
        all_exist = all(not i in self.m.unstaged_deleted and core.exists(i) for i in self.staged())

        if all_exist and self.unstaged():
            menu.addAction(self.launch_editor_action)

        if all_exist and s.modified and self.m.stageable():
            menu.addAction(self.launch_difftool_action)

        if s.modified and self.m.stageable():
            if self.m.undoable():
                menu.addSeparator()
                menu.addAction(self.revert_unstaged_edits_action)

        if all_exist and self.unstaged() and not utils.is_win32():
            menu.addSeparator()
            action = menu.addAction(
                qtutils.file_icon(), cmds.OpenDefaultApp.name(), cmds.run(cmds.OpenDefaultApp, self.unstaged())
            )
            action.setShortcut(cmds.OpenDefaultApp.SHORTCUT)

            action = menu.addAction(qtutils.open_file_icon(), cmds.OpenParentDir.name(), self._open_parent_dir)
            action.setShortcut(cmds.OpenParentDir.SHORTCUT)

        if all_exist and s.untracked:
            menu.addSeparator()
            if self.move_to_trash_action is not None:
                menu.addAction(self.move_to_trash_action)
            menu.addAction(self.delete_untracked_files_action)
            menu.addSeparator()
            menu.addAction(
                qtutils.theme_icon("edit-clear.svg"),
                N_("Add to .gitignore"),
                cmds.run(cmds.Ignore, map(lambda x: "/" + x, self.untracked())),
            )
        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        menu.addAction(self.copy_relpath_action)
        return menu
Example #22
0
 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, cmds.run(cmds.RunConfigAction, name))
Example #23
0
 def _build_recent_menu(self, menu, cmd):
     recent = settings.Settings().recent
     menu.clear()
     for r in recent:
         name = os.path.basename(r)
         directory = os.path.dirname(r)
         text = '%s %s %s' % (name, unichr(0x2192), directory)
         menu.addAction(text, cmds.run(cmd, r))
Example #24
0
 def build_recent_menu(self):
     recent = settings.Settings().recent
     menu = self.menu_open_recent
     menu.clear()
     for r in recent:
         name = os.path.basename(r)
         directory = os.path.dirname(r)
         text = "%s %s %s" % (name, unichr(0x2192), directory)
         menu.addAction(text, cmds.run(cmds.OpenRepo, r))
Example #25
0
    def _create_modified_submodule_context_menu(self, menu, s):
        menu.addAction(qtutils.git_icon(),
                       N_('Launch git-cola'),
                       cmds.run(cmds.OpenRepo, core.abspath(s.modified[0])))

        menu.addAction(self.launch_editor_action)

        if self.m.stageable():
            menu.addSeparator()
            action = menu.addAction(qtutils.add_icon(),
                                    N_('Stage Selected'),
                                    cmds.run(cmds.Stage, self.unstaged()))
            action.setShortcut(hotkeys.STAGE_SELECTION)

        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        menu.addAction(self.copy_relpath_action)
        menu.addAction(self.view_history_action)
        return menu
Example #26
0
 def _install_config_actions(self, names_and_shortcuts):
     """Install .gitconfig-defined actions"""
     if not names_and_shortcuts:
         return
     menu = self.actions_menu
     menu.addSeparator()
     for (name, shortcut) in names_and_shortcuts:
         action = menu.addAction(name, cmds.run(cmds.RunConfigAction, name))
         if shortcut:
             action.setShortcut(shortcut)
Example #27
0
    def _create_staged_submodule_context_menu(self, menu, s):
        menu.addAction(qtutils.git_icon(),
                       N_('Launch git-cola'),
                       cmds.run(cmds.OpenRepo,
                                os.path.abspath(s.staged[0])))

        action = menu.addAction(qtutils.options_icon(),
                                cmds.LaunchEditor.name(),
                                cmds.run(cmds.LaunchEditor))
        action.setShortcut(cmds.LaunchEditor.SHORTCUT)

        menu.addSeparator()
        action = menu.addAction(qtutils.icon('remove.svg'),
                                N_('Unstage Selected'),
                                cmds.run(cmds.Unstage, self.staged()))
        action.setShortcut(cmds.Unstage.SHORTCUT)

        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        return menu
Example #28
0
 def build_recent_menu(self):
     settings = Settings()
     settings.load()
     recent = settings.recent
     cmd = cmds.OpenRepo
     menu = self.open_recent_menu
     menu.clear()
     for r in recent:
         name = os.path.basename(r)
         directory = os.path.dirname(r)
         text = '%s %s %s' % (name, unichr(0x2192), directory)
         menu.addAction(text, cmds.run(cmd, r))
Example #29
0
    def _create_modified_submodule_context_menu(self, menu, s):
        menu.addAction(qtutils.git_icon(),
                       self.tr('Launch git-cola'),
                       cmds.run(cmds.OpenRepo,
                            os.path.abspath(s.modified[0])))

        action = menu.addAction(qtutils.options_icon(),
                                self.tr(cmds.LaunchEditor.NAME),
                                cmds.run(cmds.LaunchEditor))
        action.setShortcut(cmds.Edit.SHORTCUT)

        if self.m.stageable():
            menu.addSeparator()
            action = menu.addAction(qtutils.icon('add.svg'),
                                    self.tr('Stage Selected'),
                                    cmds.run(cmds.Stage, self.unstaged()))
            action.setShortcut(cmds.Stage.SHORTCUT)

        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        return menu
Example #30
0
    def _create_staged_context_menu(self, menu, s):
        if s.staged[0] in self.m.submodules:
            return self._create_staged_submodule_context_menu(menu, s)

        if self.m.unstageable():
            action = menu.addAction(
                qtutils.icon("remove.svg"), N_("Unstage Selected"), cmds.run(cmds.Unstage, self.staged())
            )
            action.setShortcut(cmds.Unstage.SHORTCUT)

        # Do all of the selected items exist?
        staged_items = self.staged_items()
        all_exist = all([i.exists for i in staged_items])

        if all_exist:
            menu.addAction(self.launch_editor)
            menu.addAction(self.launch_difftool)

        if all_exist and not utils.is_win32():
            menu.addSeparator()
            action = menu.addAction(
                qtutils.file_icon(), cmds.OpenDefaultApp.name(), cmds.run(cmds.OpenDefaultApp, self.staged())
            )
            action.setShortcut(cmds.OpenDefaultApp.SHORTCUT)

            action = menu.addAction(qtutils.open_file_icon(), cmds.OpenParentDir.name(), self._open_parent_dir)
            action.setShortcut(cmds.OpenParentDir.SHORTCUT)

        if self.m.undoable():
            menu.addSeparator()
            menu.addAction(self.revert_unstaged_edits_action)
            menu.addAction(
                qtutils.icon("undo.svg"),
                N_("Revert Uncommited Edits..."),
                lambda: self._revert_uncommitted_edits(self.staged()),
            )
        menu.addSeparator()
        menu.addAction(self.copy_path_action)
        return menu
Example #31
0
    def __init__(self, parent):
        standard.TreeView.__init__(self, parent)

        self.setRootIsDecorated(True)
        self.setSortingEnabled(False)
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)

        # Observe model updates
        model = main.model()
        model.add_observer(model.message_updated, self.update_actions)

        # The non-Qt cola application model
        self.connect(self, SIGNAL('expanded(QModelIndex)'), self.size_columns)
        self.connect(self, SIGNAL('collapsed(QModelIndex)'), self.size_columns)

        # Sync selection before the key press event changes the model index
        self.connect(self, SIGNAL('indexAboutToChange()'), self.sync_selection)

        self.action_history =\
                self._create_action(
                        N_('View History...'),
                        N_('View history for selected path(s).'),
                        self.view_history,
                        'Shift+Ctrl+H')
        self.action_stage =\
                self._create_action(N_('Stage Selected'),
                                    N_('Stage selected path(s) for commit.'),
                                    self.stage_selected,
                                    cmds.Stage.SHORTCUT)
        self.action_unstage =\
                self._create_action(
                        N_('Unstage Selected'),
                        N_('Remove selected path(s) from the staging area.'),
                        self.unstage_selected,
                        'Ctrl+U')

        self.action_untrack =\
                self._create_action(N_('Untrack Selected'),
                                    N_('Stop tracking path(s)'),
                                    self.untrack_selected)

        self.action_difftool =\
                self._create_action(cmds.LaunchDifftool.name(),
                                    N_('Launch git-difftool on the current path.'),
                                    cmds.run(cmds.LaunchDifftool),
                                    cmds.LaunchDifftool.SHORTCUT)
        self.action_difftool_predecessor =\
                self._create_action(N_('Diff Against Predecessor...'),
                                    N_('Launch git-difftool against previous versions.'),
                                    self.difftool_predecessor,
                                    'Shift+Ctrl+D')
        self.action_revert =\
                self._create_action(N_('Revert Uncommitted Changes...'),
                                    N_('Revert changes to selected path(s).'),
                                    self.revert,
                                    'Ctrl+Z')
        self.action_editor =\
                self._create_action(cmds.LaunchEditor.name(),
                                    N_('Edit selected path(s).'),
                                    cmds.run(cmds.LaunchEditor),
                                    cmds.LaunchDifftool.SHORTCUT)
Example #32
0
    def __init__(self, parent=None):
        QtGui.QTreeWidget.__init__(self, parent)

        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.headerItem().setHidden(True)
        self.setAllColumnsShowFocus(True)
        self.setSortingEnabled(False)
        self.setUniformRowHeights(True)
        self.setAnimated(True)
        self.setRootIsDecorated(False)
        self.setIndentation(0)
        self.setDragEnabled(True)

        self.add_item(N_('Staged'), hide=True)
        self.add_item(N_('Unmerged'), hide=True)
        self.add_item(N_('Modified'), hide=True)
        self.add_item(N_('Untracked'), hide=True)

        # Used to restore the selection
        self.old_scroll = None
        self.old_selection = None
        self.old_contents = None
        self.old_current_item = None
        self.expanded_items = set()

        self.process_selection_action = qtutils.add_action(self,
                cmds.StageOrUnstage.name(),
                cmds.run(cmds.StageOrUnstage),
                cmds.StageOrUnstage.SHORTCUT)

        self.revert_unstaged_edits_action = qtutils.add_action(self,
                cmds.RevertUnstagedEdits.name(),
                cmds.run(cmds.RevertUnstagedEdits),
                cmds.RevertUnstagedEdits.SHORTCUT)
        self.revert_unstaged_edits_action.setIcon(qtutils.icon('undo.svg'))

        self.revert_uncommitted_edits_action = qtutils.add_action(self,
                cmds.RevertUncommittedEdits.name(),
                cmds.run(cmds.RevertUncommittedEdits),
                cmds.RevertUncommittedEdits.SHORTCUT)
        self.revert_uncommitted_edits_action.setIcon(qtutils.icon('undo.svg'))

        self.launch_difftool_action = qtutils.add_action(self,
                cmds.LaunchDifftool.name(),
                cmds.run(cmds.LaunchDifftool),
                cmds.LaunchDifftool.SHORTCUT)
        self.launch_difftool_action.setIcon(qtutils.git_icon())

        self.launch_editor_action = qtutils.add_action(self,
                cmds.LaunchEditor.name(),
                cmds.run(cmds.LaunchEditor),
                cmds.LaunchEditor.SHORTCUT,
                'Return', 'Enter')
        self.launch_editor_action.setIcon(qtutils.options_icon())

        if not utils.is_win32():
            self.open_using_default_app = qtutils.add_action(self,
                    cmds.OpenDefaultApp.name(),
                    self._open_using_default_app,
                    cmds.OpenDefaultApp.SHORTCUT)
            self.open_using_default_app.setIcon(qtutils.file_icon())

            self.open_parent_dir_action = qtutils.add_action(self,
                    cmds.OpenParentDir.name(),
                    self._open_parent_dir,
                    cmds.OpenParentDir.SHORTCUT)
            self.open_parent_dir_action.setIcon(qtutils.open_file_icon())

        self.up_action = qtutils.add_action(self,
                N_('Move Up'), self.move_up, Qt.Key_K)

        self.down_action = qtutils.add_action(self,
                N_('Move Down'), self.move_down, Qt.Key_J)

        self.copy_path_action = qtutils.add_action(self,
                N_('Copy Path to Clipboard'),
                self.copy_path, QtGui.QKeySequence.Copy)
        self.copy_path_action.setIcon(qtutils.theme_icon('edit-copy.svg'))

        self.copy_relpath_action = qtutils.add_action(self,
                N_('Copy Relative Path to Clipboard'),
                self.copy_relpath, QtGui.QKeySequence.Cut)
        self.copy_relpath_action.setIcon(qtutils.theme_icon('edit-copy.svg'))

        if cmds.MoveToTrash.AVAILABLE:
            self.move_to_trash_action = qtutils.add_action(self,
                    N_('Move file(s) to trash'),
                    self._trash_untracked_files, cmds.MoveToTrash.SHORTCUT)
            self.move_to_trash_action.setIcon(qtutils.discard_icon())
            delete_shortcut = cmds.Delete.SHORTCUT
        else:
            self.move_to_trash_action = None
            delete_shortcut = cmds.Delete.ALT_SHORTCUT

        self.delete_untracked_files_action = qtutils.add_action(self,
                N_('Delete File(s)...'),
                self._delete_untracked_files, delete_shortcut)
        self.delete_untracked_files_action.setIcon(qtutils.discard_icon())

        self.connect(self, SIGNAL('about_to_update'), self._about_to_update)
        self.connect(self, SIGNAL('updated'), self._updated)

        self.m = main.model()
        self.m.add_observer(self.m.message_about_to_update,
                            self.about_to_update)
        self.m.add_observer(self.m.message_updated, self.updated)

        self.connect(self, SIGNAL('itemSelectionChanged()'),
                     self.show_selection)

        self.connect(self, SIGNAL('itemDoubleClicked(QTreeWidgetItem*,int)'),
                     self.double_clicked)

        self.connect(self, SIGNAL('itemCollapsed(QTreeWidgetItem*)'),
                     lambda x: self.update_column_widths())

        self.connect(self, SIGNAL('itemExpanded(QTreeWidgetItem*)'),
                     lambda x: self.update_column_widths())
Example #33
0
    def __init__(self, model, parent):
        QtGui.QWidget.__init__(self, parent)

        self.model = model
        self.notifying = False
        self.spellcheck_initialized = False

        self._linebreak = None
        self._textwidth = None
        self._tabwidth = None

        # Actions
        self.signoff_action = add_action(self, cmds.SignOff.name(),
                                         cmds.run(cmds.SignOff),
                                         cmds.SignOff.SHORTCUT)
        self.signoff_action.setToolTip(N_('Sign off on this commit'))

        self.commit_action = add_action(self, N_('Commit@@verb'), self.commit,
                                        cmds.Commit.SHORTCUT)
        self.commit_action.setToolTip(N_('Commit staged changes'))

        # Widgets
        self.summary = CommitSummaryLineEdit()
        self.summary.extra_actions.append(self.signoff_action)
        self.summary.extra_actions.append(self.commit_action)

        self.description = CommitMessageTextEdit()
        self.description.extra_actions.append(self.signoff_action)
        self.description.extra_actions.append(self.commit_action)

        commit_button_tooltip = N_('Commit staged changes\n'
                                   'Shortcut: Ctrl+Enter')
        self.commit_button = create_toolbutton(text=N_('Commit@@verb'),
                                               tooltip=commit_button_tooltip,
                                               icon=save_icon())

        self.actions_menu = QtGui.QMenu()
        self.actions_button = create_toolbutton(icon=options_icon(),
                                                tooltip=N_('Actions...'))
        self.actions_button.setMenu(self.actions_menu)
        self.actions_button.setPopupMode(QtGui.QToolButton.InstantPopup)

        self.actions_menu.addAction(self.signoff_action)
        self.actions_menu.addAction(self.commit_action)
        self.actions_menu.addSeparator()

        # Amend checkbox
        self.amend_action = self.actions_menu.addAction(
            N_('Amend Last Commit'))
        self.amend_action.setCheckable(True)
        self.amend_action.setShortcut(cmds.AmendMode.SHORTCUT)
        self.amend_action.setShortcutContext(Qt.ApplicationShortcut)

        # Spell checker
        self.check_spelling_action = self.actions_menu.addAction(
            N_('Check Spelling'))
        self.check_spelling_action.setCheckable(True)
        self.check_spelling_action.setChecked(False)

        # Line wrapping
        self.autowrap_action = self.actions_menu.addAction(
            N_('Auto-Wrap Lines'))
        self.autowrap_action.setCheckable(True)
        self.autowrap_action.setChecked(linebreak())

        # Commit message
        self.actions_menu.addSeparator()
        self.load_commitmsg_menu = self.actions_menu.addMenu(
            N_('Load Previous Commit Message'))
        self.connect(self.load_commitmsg_menu, SIGNAL('aboutToShow()'),
                     self.build_commitmsg_menu)

        self.fixup_commit_menu = self.actions_menu.addMenu(
            N_('Fixup Previous Commit'))
        self.connect(self.fixup_commit_menu, SIGNAL('aboutToShow()'),
                     self.build_fixup_menu)

        self.toplayout = QtGui.QHBoxLayout()
        self.toplayout.setMargin(0)
        self.toplayout.setSpacing(defs.spacing)
        self.toplayout.addWidget(self.actions_button)
        self.toplayout.addWidget(self.summary)
        self.toplayout.addWidget(self.commit_button)

        self.mainlayout = QtGui.QVBoxLayout()
        self.mainlayout.setMargin(defs.margin)
        self.mainlayout.setSpacing(defs.spacing)
        self.mainlayout.addLayout(self.toplayout)
        self.mainlayout.addWidget(self.description)
        self.setLayout(self.mainlayout)

        connect_button(self.commit_button, self.commit)

        # Broadcast the amend mode
        connect_action_bool(self.amend_action, cmds.run(cmds.AmendMode))
        connect_action_bool(self.check_spelling_action,
                            self.toggle_check_spelling)

        # Handle the one-off autowrapping
        connect_action_bool(self.autowrap_action, self.set_linebreak)

        add_action(self.summary, N_('Move Down'), self.focus_description,
                   Qt.Key_Down, Qt.Key_Return, Qt.Key_Enter)

        self.model.add_observer(self.model.message_commit_message_changed,
                                self.set_commit_message)

        self.connect(self.summary, SIGNAL('cursorPosition(int,int)'),
                     self.emit_position)

        self.connect(
            self.description,
            SIGNAL('cursorPosition(int,int)'),
            # description starts at line 2
            lambda row, col: self.emit_position(row + 2, col))

        # Keep model informed of changes
        self.connect(self.summary, SIGNAL('textChanged(QString)'),
                     self.commit_message_changed)

        self.connect(self.description, SIGNAL('textChanged()'),
                     self.commit_message_changed)

        self.connect(self.description, SIGNAL('leave()'), self.focus_summary)

        self.setFont(diff_font())

        self.summary.enable_hint(True)
        self.description.enable_hint(True)

        self.commit_button.setEnabled(False)
        self.commit_action.setEnabled(False)

        self.setFocusProxy(self.summary)

        self.set_tabwidth(tabwidth())
        self.set_textwidth(textwidth())
        self.set_linebreak(linebreak())

        # Loading message
        commit_msg = ''
        commit_msg_path = commit_message_path()
        if commit_msg_path:
            commit_msg = core.read(commit_msg_path)
        self.set_commit_message(commit_msg)

        # Allow tab to jump from the summary to the description
        self.setTabOrder(self.summary, self.description)
Example #34
0
    def __init__(self, model, parent=None, settings=None):
        standard.MainWindow.__init__(self, parent)
        self.setAttribute(Qt.WA_MacMetalStyle)

        # Default size; this is thrown out when save/restore is used
        self.model = model
        self.settings = settings
        self.prefs_model = prefs_model = prefs.PreferencesModel()

        # The widget version is used by import/export_state().
        # Change this whenever dockwidgets are removed.
        self.widget_version = 2

        # Runs asynchronous tasks
        self.runtask = qtutils.RunTask()
        self.progress = standard.ProgressDialog('', '', self)

        create_dock = qtutils.create_dock
        cfg = gitcfg.current()
        self.browser_dockable = (cfg.get('cola.browserdockable')
                                 or cfg.get('cola.classicdockable'))
        if self.browser_dockable:
            self.browserdockwidget = create_dock(N_('Browser'), self)
            self.browserwidget = browse.worktree_browser_widget(self)
            self.browserdockwidget.setWidget(self.browserwidget)

        # "Actions" widget
        self.actionsdockwidget = create_dock(N_('Actions'), self)
        self.actionsdockwidgetcontents = action.ActionButtons(self)
        self.actionsdockwidget.setWidget(self.actionsdockwidgetcontents)
        self.actionsdockwidget.toggleViewAction().setChecked(False)
        self.actionsdockwidget.hide()

        # "Repository Status" widget
        self.statusdockwidget = create_dock(N_('Status'), self)
        titlebar = self.statusdockwidget.titleBarWidget()
        self.statuswidget = status.StatusWidget(titlebar,
                                                parent=self.statusdockwidget)
        self.statusdockwidget.setWidget(self.statuswidget)

        # "Switch Repository" widgets
        self.bookmarksdockwidget = create_dock(N_('Favorites'), self)
        self.bookmarkswidget = bookmarks.BookmarksWidget(
            bookmarks.BOOKMARKS, parent=self.bookmarksdockwidget)
        self.bookmarksdockwidget.setWidget(self.bookmarkswidget)

        self.recentdockwidget = create_dock(N_('Recent'), self)
        self.recentwidget = bookmarks.BookmarksWidget(
            bookmarks.RECENT_REPOS, parent=self.recentdockwidget)
        self.recentdockwidget.setWidget(self.recentwidget)
        self.recentdockwidget.hide()

        # "Commit Message Editor" widget
        self.position_label = QtGui.QLabel()
        self.position_label.setAlignment(Qt.AlignCenter)
        font = qtutils.default_monospace_font()
        font.setPointSize(int(font.pointSize() * 0.8))
        self.position_label.setFont(font)

        # make the position label fixed size to avoid layout issues
        fm = self.position_label.fontMetrics()
        width = fm.width('99:999') + defs.spacing
        self.position_label.setMinimumWidth(width)

        self.commitdockwidget = create_dock(N_('Commit'), self)
        titlebar = self.commitdockwidget.titleBarWidget()
        titlebar.add_corner_widget(self.position_label)

        self.commitmsgeditor = commitmsg.CommitMessageEditor(model, self)
        self.commitdockwidget.setWidget(self.commitmsgeditor)

        # "Console" widget
        self.logwidget = log.LogWidget()
        self.logdockwidget = create_dock(N_('Console'), self)
        self.logdockwidget.setWidget(self.logwidget)
        self.logdockwidget.toggleViewAction().setChecked(False)
        self.logdockwidget.hide()

        # "Diff Viewer" widget
        self.diffdockwidget = create_dock(N_('Diff'), self)
        self.diffeditorwidget = diff.DiffEditorWidget(self.diffdockwidget)
        self.diffeditor = self.diffeditorwidget.editor
        self.diffdockwidget.setWidget(self.diffeditorwidget)

        # All Actions
        add_action = qtutils.add_action
        self.unstage_all_action = add_action(self, N_('Unstage All'),
                                             cmds.run(cmds.UnstageAll))
        self.unstage_all_action.setIcon(icons.remove())

        self.unstage_selected_action = add_action(
            self, N_('Unstage From Commit'), cmds.run(cmds.UnstageSelected))
        self.unstage_selected_action.setIcon(icons.remove())

        self.show_diffstat_action = add_action(self, N_('Diffstat'),
                                               cmds.run(cmds.Diffstat),
                                               hotkeys.DIFFSTAT)

        self.stage_modified_action = add_action(
            self, N_('Stage Changed Files To Commit'),
            cmds.run(cmds.StageModified), hotkeys.STAGE_MODIFIED)
        self.stage_modified_action.setIcon(icons.add())

        self.stage_untracked_action = add_action(self,
                                                 N_('Stage All Untracked'),
                                                 cmds.run(cmds.StageUntracked),
                                                 hotkeys.STAGE_UNTRACKED)
        self.stage_untracked_action.setIcon(icons.add())

        self.apply_patches_action = add_action(self, N_('Apply Patches...'),
                                               patch.apply_patches)

        self.export_patches_action = add_action(self, N_('Export Patches...'),
                                                guicmds.export_patches,
                                                hotkeys.EXPORT)

        self.new_repository_action = add_action(self, N_('New Repository...'),
                                                guicmds.open_new_repo)
        self.new_repository_action.setIcon(icons.new())

        self.preferences_action = add_action(self, N_('Preferences'),
                                             self.preferences,
                                             QtGui.QKeySequence.Preferences)

        self.edit_remotes_action = add_action(
            self, N_('Edit Remotes...'),
            lambda: editremotes.remote_editor().exec_())

        self.rescan_action = add_action(self, cmds.Refresh.name(),
                                        cmds.run(cmds.Refresh),
                                        *hotkeys.REFRESH_HOTKEYS)
        self.rescan_action.setIcon(icons.sync())

        self.find_files_action = add_action(self, N_('Find Files'),
                                            finder.finder, hotkeys.FINDER,
                                            hotkeys.FINDER_SECONDARY)
        self.find_files_action.setIcon(icons.zoom_in())

        self.browse_recently_modified_action = add_action(
            self, N_('Recently Modified Files...'), recent.browse_recent_files,
            hotkeys.EDIT_SECONDARY)

        self.cherry_pick_action = add_action(self, N_('Cherry-Pick...'),
                                             guicmds.cherry_pick,
                                             hotkeys.CHERRY_PICK)

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

        self.save_tarball_action = add_action(self,
                                              N_('Save As Tarball/Zip...'),
                                              self.save_archive)

        self.quit_action = add_action(self, N_('Quit'), self.close,
                                      hotkeys.QUIT)
        self.grep_action = add_action(self, N_('Grep'), grep.grep,
                                      hotkeys.GREP)
        self.merge_local_action = add_action(self, N_('Merge...'),
                                             merge.local_merge, hotkeys.MERGE)

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

        self.fetch_action = add_action(self, N_('Fetch...'), remote.fetch,
                                       hotkeys.FETCH)
        self.push_action = add_action(self, N_('Push...'), remote.push,
                                      hotkeys.PUSH)
        self.pull_action = add_action(self, N_('Pull...'), remote.pull,
                                      hotkeys.PULL)

        self.open_repo_action = add_action(self, N_('Open...'),
                                           guicmds.open_repo, hotkeys.OPEN)
        self.open_repo_action.setIcon(icons.folder())

        self.open_repo_new_action = add_action(self,
                                               N_('Open in New Window...'),
                                               guicmds.open_repo_in_new_window)
        self.open_repo_new_action.setIcon(icons.folder())

        self.stash_action = add_action(self, N_('Stash...'), stash.stash,
                                       hotkeys.STASH)

        self.clone_repo_action = add_action(self, N_('Clone...'),
                                            self.clone_repo)
        self.clone_repo_action.setIcon(icons.repo())

        self.help_docs_action = add_action(self, N_('Documentation'),
                                           resources.show_html_docs,
                                           QtGui.QKeySequence.HelpContents)

        self.help_shortcuts_action = add_action(self, N_('Keyboard Shortcuts'),
                                                about.show_shortcuts,
                                                hotkeys.QUESTION)

        self.visualize_current_action = add_action(
            self, N_('Visualize Current Branch...'),
            cmds.run(cmds.VisualizeCurrent))
        self.visualize_all_action = add_action(self,
                                               N_('Visualize All Branches...'),
                                               cmds.run(cmds.VisualizeAll))
        self.search_commits_action = add_action(self, N_('Search...'),
                                                search.search)
        self.browse_branch_action = add_action(self,
                                               N_('Browse Current Branch...'),
                                               guicmds.browse_current)
        self.browse_other_branch_action = add_action(
            self, N_('Browse Other Branch...'), guicmds.browse_other)
        self.load_commitmsg_template_action = add_action(
            self, N_('Get Commit Message Template'),
            cmds.run(cmds.LoadCommitMessageFromTemplate))
        self.help_about_action = add_action(self, N_('About'),
                                            about.launch_about_dialog)

        self.diff_expression_action = add_action(self, N_('Expression...'),
                                                 guicmds.diff_expression)
        self.branch_compare_action = add_action(self, N_('Branches...'),
                                                compare.compare_branches)

        self.create_tag_action = add_action(
            self, N_('Create Tag...'),
            lambda: createtag.create_tag(settings=settings))

        self.create_branch_action = add_action(
            self, N_('Create...'),
            lambda: createbranch.create_new_branch(settings=settings),
            hotkeys.BRANCH)

        self.delete_branch_action = add_action(self, N_('Delete...'),
                                               guicmds.delete_branch)

        self.delete_remote_branch_action = add_action(
            self, N_('Delete Remote Branch...'), guicmds.delete_remote_branch)

        self.rename_branch_action = add_action(self, N_('Rename Branch...'),
                                               guicmds.rename_branch)

        self.checkout_branch_action = add_action(self, N_('Checkout...'),
                                                 guicmds.checkout_branch,
                                                 hotkeys.CHECKOUT)
        self.branch_review_action = add_action(self, N_('Review...'),
                                               guicmds.review_branch)

        self.browse_action = add_action(self, N_('File Browser...'),
                                        browse.worktree_browser)
        self.browse_action.setIcon(icons.cola())

        self.dag_action = add_action(self, N_('DAG...'), self.git_dag)
        self.dag_action.setIcon(icons.cola())

        self.rebase_start_action = add_action(
            self, N_('Start Interactive Rebase...'), self.rebase_start)

        self.rebase_edit_todo_action = add_action(self, N_('Edit...'),
                                                  self.rebase_edit_todo)

        self.rebase_continue_action = add_action(self, N_('Continue'),
                                                 self.rebase_continue)

        self.rebase_skip_action = add_action(self, N_('Skip Current Patch'),
                                             self.rebase_skip)

        self.rebase_abort_action = add_action(self, N_('Abort'),
                                              self.rebase_abort)

        # For "Start Rebase" only, reverse the first argument to setEnabled()
        # so that we can operate on it as a group.
        # We can do this because can_rebase == not is_rebasing
        set_disabled = lambda x: self.rebase_start_action.setEnabled(not x)
        self.rebase_start_action_proxy = utils.Proxy(self.rebase_start_action,
                                                     setEnabled=set_disabled)

        self.rebase_group = utils.Group(self.rebase_start_action_proxy,
                                        self.rebase_edit_todo_action,
                                        self.rebase_continue_action,
                                        self.rebase_skip_action,
                                        self.rebase_abort_action)

        self.lock_layout_action = qtutils.add_action_bool(
            self, N_('Lock Layout'), self.set_lock_layout, False)

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

        # File Menu
        create_menu = qtutils.create_menu
        self.file_menu = create_menu(N_('File'), self.menubar)
        self.file_menu.addAction(self.new_repository_action)
        self.open_recent_menu = self.file_menu.addMenu(N_('Open Recent'))
        self.open_recent_menu.setIcon(icons.folder())
        self.file_menu.addAction(self.open_repo_action)
        self.file_menu.addAction(self.open_repo_new_action)
        self.file_menu.addAction(self.clone_repo_action)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.rescan_action)
        self.file_menu.addAction(self.find_files_action)
        self.file_menu.addAction(self.edit_remotes_action)
        self.file_menu.addAction(self.browse_recently_modified_action)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.load_commitmsg_action)
        self.file_menu.addAction(self.load_commitmsg_template_action)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.apply_patches_action)
        self.file_menu.addAction(self.export_patches_action)
        self.file_menu.addAction(self.save_tarball_action)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.preferences_action)
        self.file_menu.addAction(self.quit_action)
        self.menubar.addAction(self.file_menu.menuAction())

        # Actions menu
        self.actions_menu = create_menu(N_('Actions'), self.menubar)
        self.actions_menu.addAction(self.fetch_action)
        self.actions_menu.addAction(self.push_action)
        self.actions_menu.addAction(self.pull_action)
        self.actions_menu.addAction(self.stash_action)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.create_tag_action)
        self.actions_menu.addAction(self.cherry_pick_action)
        self.actions_menu.addAction(self.merge_local_action)
        self.actions_menu.addAction(self.merge_abort_action)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.grep_action)
        self.actions_menu.addAction(self.search_commits_action)
        self.menubar.addAction(self.actions_menu.menuAction())

        # Staging Area Menu
        self.commit_menu = create_menu(N_('Staging Area'), self.menubar)
        self.commit_menu.setTitle(N_('Staging Area'))
        self.commit_menu.addAction(self.stage_modified_action)
        self.commit_menu.addAction(self.stage_untracked_action)
        self.commit_menu.addSeparator()
        self.commit_menu.addAction(self.unstage_all_action)
        self.commit_menu.addAction(self.unstage_selected_action)
        self.menubar.addAction(self.commit_menu.menuAction())

        # Diff Menu
        self.diff_menu = create_menu(N_('Diff'), self.menubar)
        self.diff_menu.addAction(self.diff_expression_action)
        self.diff_menu.addAction(self.branch_compare_action)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.show_diffstat_action)
        self.menubar.addAction(self.diff_menu.menuAction())

        # Branch Menu
        self.branch_menu = create_menu(N_('Branch'), self.menubar)
        self.branch_menu.addAction(self.branch_review_action)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.create_branch_action)
        self.branch_menu.addAction(self.checkout_branch_action)
        self.branch_menu.addAction(self.delete_branch_action)
        self.branch_menu.addAction(self.delete_remote_branch_action)
        self.branch_menu.addAction(self.rename_branch_action)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.browse_branch_action)
        self.branch_menu.addAction(self.browse_other_branch_action)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.visualize_current_action)
        self.branch_menu.addAction(self.visualize_all_action)
        self.menubar.addAction(self.branch_menu.menuAction())

        # Rebase menu
        self.rebase_menu = create_menu(N_('Rebase'), self.actions_menu)
        self.rebase_menu.addAction(self.rebase_start_action)
        self.rebase_menu.addAction(self.rebase_edit_todo_action)
        self.rebase_menu.addSeparator()
        self.rebase_menu.addAction(self.rebase_continue_action)
        self.rebase_menu.addAction(self.rebase_skip_action)
        self.rebase_menu.addSeparator()
        self.rebase_menu.addAction(self.rebase_abort_action)
        self.menubar.addAction(self.rebase_menu.menuAction())

        # View Menu
        self.view_menu = create_menu(N_('View'), self.menubar)
        self.view_menu.addAction(self.browse_action)
        self.view_menu.addAction(self.dag_action)
        self.view_menu.addSeparator()
        if self.browser_dockable:
            self.view_menu.addAction(self.browserdockwidget.toggleViewAction())

        self.setup_dockwidget_view_menu()
        self.view_menu.addSeparator()
        self.view_menu.addAction(self.lock_layout_action)
        self.menubar.addAction(self.view_menu.menuAction())

        # Help Menu
        self.help_menu = create_menu(N_('Help'), self.menubar)
        self.help_menu.addAction(self.help_docs_action)
        self.help_menu.addAction(self.help_shortcuts_action)
        self.help_menu.addAction(self.help_about_action)
        self.menubar.addAction(self.help_menu.menuAction())

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

        # Arrange dock widgets
        left = Qt.LeftDockWidgetArea
        right = Qt.RightDockWidgetArea
        bottom = Qt.BottomDockWidgetArea

        self.addDockWidget(left, self.commitdockwidget)
        if self.browser_dockable:
            self.addDockWidget(left, self.browserdockwidget)
            self.tabifyDockWidget(self.browserdockwidget,
                                  self.commitdockwidget)
        self.addDockWidget(left, self.diffdockwidget)
        self.addDockWidget(right, self.statusdockwidget)
        self.addDockWidget(right, self.bookmarksdockwidget)
        self.addDockWidget(right, self.recentdockwidget)
        self.addDockWidget(bottom, self.actionsdockwidget)
        self.addDockWidget(bottom, self.logdockwidget)
        self.tabifyDockWidget(self.actionsdockwidget, self.logdockwidget)

        # Listen for model notifications
        model.add_observer(model.message_updated, self._update)
        model.add_observer(model.message_mode_changed,
                           lambda x: self._update())

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

        # Set a default value
        self.show_cursor_position(1, 0)

        self.connect(self.open_recent_menu, SIGNAL('aboutToShow()'),
                     self.build_recent_menu)

        self.connect(self.commitmsgeditor, SIGNAL('cursorPosition(int,int)'),
                     self.show_cursor_position)

        self.connect(self.diffeditor, SIGNAL('diff_options_updated()'),
                     self.statuswidget.refresh)

        self.connect(self.diffeditor, SIGNAL('move_down()'),
                     self.statuswidget.move_down)

        self.connect(self.diffeditor, SIGNAL('move_up()'),
                     self.statuswidget.move_up)

        self.connect(self.commitmsgeditor, SIGNAL('move_down()'),
                     self.statuswidget.move_down)

        self.connect(self.commitmsgeditor, SIGNAL('move_up()'),
                     self.statuswidget.move_up)

        self.connect(self, SIGNAL('update()'), self._update_callback,
                     Qt.QueuedConnection)

        self.connect(self, SIGNAL('install_cfg_actions(PyQt_PyObject)'),
                     self._install_config_actions, Qt.QueuedConnection)

        # Install .git-config-defined actions
        self.init_config_actions()

        # Restore saved settings
        if not self.restore_state(settings=settings):
            self.resize(987, 610)
            self.set_initial_size()

        self.statusdockwidget.widget().setFocus()

        # Route command output here
        Interaction.log_status = self.logwidget.log_status
        Interaction.log = self.logwidget.log
        Interaction.safe_log = self.logwidget.safe_log
        Interaction.log(version.git_version_str() + '\n' +
                        N_('git cola version %s') % version.version())
Example #35
0
    def __init__(self, parent=None):
        QtGui.QTreeWidget.__init__(self, parent)

        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.headerItem().setHidden(True)
        self.setAllColumnsShowFocus(True)
        self.setSortingEnabled(False)
        self.setUniformRowHeights(True)
        self.setAnimated(True)
        self.setRootIsDecorated(False)
        self.setIndentation(0)
        self.setDragEnabled(True)
        self.setAutoScroll(False)

        ok = icons.ok()
        compare = icons.compare()
        question = icons.question()
        self.add_toplevel_item(N_('Staged'), ok, hide=True)
        self.add_toplevel_item(N_('Unmerged'), compare, hide=True)
        self.add_toplevel_item(N_('Modified'), compare, hide=True)
        self.add_toplevel_item(N_('Untracked'), question, hide=True)

        # Used to restore the selection
        self.old_vscroll = None
        self.old_hscroll = None
        self.old_selection = None
        self.old_contents = None
        self.old_current_item = None
        self.expanded_items = set()

        self.process_selection_action = qtutils.add_action(
            self, cmds.StageOrUnstage.name(), cmds.run(cmds.StageOrUnstage),
            hotkeys.STAGE_SELECTION)

        self.revert_unstaged_edits_action = qtutils.add_action(
            self, cmds.RevertUnstagedEdits.name(),
            cmds.run(cmds.RevertUnstagedEdits), hotkeys.REVERT)
        self.revert_unstaged_edits_action.setIcon(icons.undo())

        self.launch_difftool_action = qtutils.add_action(
            self, cmds.LaunchDifftool.name(), cmds.run(cmds.LaunchDifftool),
            hotkeys.DIFF)
        self.launch_difftool_action.setIcon(icons.diff())

        self.launch_editor_action = qtutils.add_action(
            self, cmds.LaunchEditor.name(), cmds.run(cmds.LaunchEditor),
            hotkeys.EDIT, *hotkeys.ACCEPT)
        self.launch_editor_action.setIcon(icons.edit())

        if not utils.is_win32():
            self.open_using_default_app = qtutils.add_action(
                self, cmds.OpenDefaultApp.name(), self._open_using_default_app,
                hotkeys.PRIMARY_ACTION)
            self.open_using_default_app.setIcon(icons.default_app())

            self.open_parent_dir_action = qtutils.add_action(
                self, cmds.OpenParentDir.name(), self._open_parent_dir,
                hotkeys.SECONDARY_ACTION)
            self.open_parent_dir_action.setIcon(icons.folder())

        self.up_action = qtutils.add_action(self, N_('Move Up'), self.move_up,
                                            hotkeys.MOVE_UP,
                                            hotkeys.MOVE_UP_SECONDARY)

        self.down_action = qtutils.add_action(self, N_('Move Down'),
                                              self.move_down,
                                              hotkeys.MOVE_DOWN,
                                              hotkeys.MOVE_DOWN_SECONDARY)

        self.copy_path_action = qtutils.add_action(
            self, N_('Copy Path to Clipboard'), self.copy_path, hotkeys.COPY)
        self.copy_path_action.setIcon(icons.copy())

        self.copy_relpath_action = qtutils.add_action(
            self, N_('Copy Relative Path to Clipboard'), self.copy_relpath,
            hotkeys.CUT)
        self.copy_relpath_action.setIcon(icons.copy())

        self.view_history_action = qtutils.add_action(self,
                                                      N_('View History...'),
                                                      self.view_history,
                                                      hotkeys.HISTORY)

        self.view_blame_action = qtutils.add_action(self, N_('Blame...'),
                                                    self.view_blame,
                                                    hotkeys.BLAME)

        # MoveToTrash and Delete use the same shortcut.
        # We will only bind one of them, depending on whether or not the
        # MoveToTrash command is avaialble.  When available, the hotkey
        # is bound to MoveToTrash, otherwise it is bound to Delete.
        if cmds.MoveToTrash.AVAILABLE:
            self.move_to_trash_action = qtutils.add_action(
                self, N_('Move file(s) to trash'), self._trash_untracked_files,
                hotkeys.TRASH)
            self.move_to_trash_action.setIcon(icons.discard())
            delete_shortcut = hotkeys.DELETE_FILE
        else:
            self.move_to_trash_action = None
            delete_shortcut = hotkeys.DELETE_FILE_SECONDARY

        self.delete_untracked_files_action = qtutils.add_action(
            self, N_('Delete File(s)...'), self._delete_untracked_files,
            delete_shortcut)
        self.delete_untracked_files_action.setIcon(icons.discard())

        self.connect(self, SIGNAL('about_to_update()'), self._about_to_update,
                     Qt.QueuedConnection)
        self.connect(self, SIGNAL('updated()'), self._updated,
                     Qt.QueuedConnection)

        self.m = main.model()
        self.m.add_observer(self.m.message_about_to_update,
                            self.about_to_update)
        self.m.add_observer(self.m.message_updated, self.updated)

        self.connect(self, SIGNAL('itemSelectionChanged()'),
                     self.show_selection)

        self.connect(self, SIGNAL('itemDoubleClicked(QTreeWidgetItem*,int)'),
                     self.double_clicked)

        self.connect(self, SIGNAL('itemCollapsed(QTreeWidgetItem*)'),
                     lambda x: self.update_column_widths())

        self.connect(self, SIGNAL('itemExpanded(QTreeWidgetItem*)'),
                     lambda x: self.update_column_widths())
Example #36
0
def cmd_action(widget, cmd, icon, *shortcuts):
    action = qtutils.add_action(widget, cmd.name(), cmds.run(cmd), *shortcuts)
    action.setIcon(icon)
    return action
Example #37
0
    def __init__(self, parent):
        standard.TreeView.__init__(self, parent)

        self.saved_selection = []
        self.saved_current_path = None
        self.saved_open_folders = set()
        self.restoring_selection = False

        self.setDragEnabled(True)
        self.setRootIsDecorated(False)
        self.setSortingEnabled(False)
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)

        # Observe model updates
        model = main.model()
        model.add_observer(model.message_about_to_update,
                           self.emit_about_to_update)
        model.add_observer(model.message_updated, self.emit_update)

        self.connect(self, SIGNAL('about_to_update()'), self.save_selection,
                     Qt.QueuedConnection)
        self.connect(self, SIGNAL('update()'), self.update_actions,
                     Qt.QueuedConnection)

        # The non-Qt cola application model
        self.connect(self, SIGNAL('expanded(QModelIndex)'), self.size_columns)
        self.connect(self, SIGNAL('expanded(QModelIndex)'), self.expanded)

        self.connect(self, SIGNAL('collapsed(QModelIndex)'), self.size_columns)
        self.connect(self, SIGNAL('collapsed(QModelIndex)'), self.collapsed)

        # Sync selection before the key press event changes the model index
        self.connect(self, SIGNAL('indexAboutToChange()'), self.sync_selection,
                     Qt.QueuedConnection)

        self.action_history = qtutils.add_action_with_status_tip(
                self, N_('View History...'),
                N_('View history for selected path(s)'),
                self.view_history, hotkeys.HISTORY)

        self.action_stage = qtutils.add_action_with_status_tip(
                self, cmds.StageOrUnstage.name(),
                N_('Stage/unstage selected path(s) for commit'),
                cmds.run(cmds.StageOrUnstage), hotkeys.STAGE_SELECTION)

        self.action_untrack = qtutils.add_action_with_status_tip(
                self, N_('Untrack Selected'),
                N_('Stop tracking path(s)'),
                self.untrack_selected)

        self.action_difftool = qtutils.add_action_with_status_tip(
                self, cmds.LaunchDifftool.name(),
                N_('Launch git-difftool on the current path.'),
                cmds.run(cmds.LaunchDifftool), hotkeys.DIFF)

        self.action_difftool_predecessor = qtutils.add_action_with_status_tip(
                self, N_('Diff Against Predecessor...'),
                N_('Launch git-difftool against previous versions.'),
                self.difftool_predecessor, hotkeys.DIFF_SECONDARY)

        self.action_revert_unstaged = qtutils.add_action_with_status_tip(
                self, cmds.RevertUnstagedEdits.name(),
                N_('Revert unstaged changes to selected paths.'),
                cmds.run(cmds.RevertUnstagedEdits), hotkeys.REVERT)

        self.action_revert_uncommitted = qtutils.add_action_with_status_tip(
                self, cmds.RevertUncommittedEdits.name(),
                N_('Revert uncommitted changes to selected paths.'),
                cmds.run(cmds.RevertUncommittedEdits), hotkeys.UNDO)

        self.action_editor = qtutils.add_action_with_status_tip(
                self, cmds.LaunchEditor.name(),
                N_('Edit selected path(s).'),
                cmds.run(cmds.LaunchEditor), hotkeys.EDIT)

        self.action_refresh  = qtutils.add_action(
                self, N_('Refresh'), cmds.run(cmds.Refresh), hotkeys.REFRESH)

        self.x_width = QtGui.QFontMetrics(self.font()).width('x')
        self.size_columns()
Example #38
0
    def __init__(self, model, parent=None, settings=None):
        standard.MainWindow.__init__(self, parent)
        self.setAttribute(Qt.WA_MacMetalStyle)

        # Default size; this is thrown out when save/restore is used
        self.model = model
        self.settings = settings
        self.prefs_model = prefs_model = prefs.PreferencesModel()

        # The widget version is used by import/export_state().
        # Change this whenever dockwidgets are removed.
        self.widget_version = 2

        # Runs asynchronous tasks
        self.task_runner = TaskRunner(self)
        self.progress = standard.ProgressDialog('', '', self)

        cfg = gitcfg.current()
        self.browser_dockable = (cfg.get('cola.browserdockable')
                                 or cfg.get('cola.classicdockable'))
        if self.browser_dockable:
            self.browserdockwidget = create_dock(N_('Browser'), self)
            self.browserwidget = browse.worktree_browser_widget(self)
            self.browserdockwidget.setWidget(self.browserwidget)

        # "Actions" widget
        self.actionsdockwidget = create_dock(N_('Actions'), self)
        self.actionsdockwidgetcontents = action.ActionButtons(self)
        self.actionsdockwidget.setWidget(self.actionsdockwidgetcontents)
        self.actionsdockwidget.toggleViewAction().setChecked(False)
        self.actionsdockwidget.hide()

        # "Repository Status" widget
        self.statusdockwidget = create_dock(N_('Status'), self)
        titlebar = self.statusdockwidget.titleBarWidget()
        self.statuswidget = status.StatusWidget(titlebar,
                                                parent=self.statusdockwidget)
        self.statusdockwidget.setWidget(self.statuswidget)

        # "Switch Repository" widgets
        self.bookmarksdockwidget = create_dock(N_('Favorites'), self)
        self.bookmarkswidget = bookmarks.BookmarksWidget(
            bookmarks.BOOKMARKS, parent=self.bookmarksdockwidget)
        self.bookmarksdockwidget.setWidget(self.bookmarkswidget)

        self.recentdockwidget = create_dock(N_('Recent'), self)
        self.recentwidget = bookmarks.BookmarksWidget(
            bookmarks.RECENT_REPOS, parent=self.recentdockwidget)
        self.recentdockwidget.setWidget(self.recentwidget)
        self.recentdockwidget.hide()

        # "Commit Message Editor" widget
        self.position_label = QtGui.QLabel()
        font = qtutils.default_monospace_font()
        font.setPointSize(int(font.pointSize() * 0.8))
        self.position_label.setFont(font)

        # make the position label fixed size to avoid layout issues
        fm = self.position_label.fontMetrics()
        width = fm.width('999:999')
        height = self.position_label.sizeHint().height()
        self.position_label.setFixedSize(width, height)

        self.commitdockwidget = create_dock(N_('Commit'), self)
        titlebar = self.commitdockwidget.titleBarWidget()
        titlebar.add_corner_widget(self.position_label)

        self.commitmsgeditor = commitmsg.CommitMessageEditor(model, self)
        self.commitdockwidget.setWidget(self.commitmsgeditor)

        # "Console" widget
        self.logwidget = log.LogWidget()
        self.logdockwidget = create_dock(N_('Console'), self)
        self.logdockwidget.setWidget(self.logwidget)
        self.logdockwidget.toggleViewAction().setChecked(False)
        self.logdockwidget.hide()

        # "Diff Viewer" widget
        self.diffdockwidget = create_dock(N_('Diff'), self)
        self.diffeditorwidget = diff.DiffEditorWidget(self.diffdockwidget)
        self.diffeditor = self.diffeditorwidget.editor
        self.diffdockwidget.setWidget(self.diffeditorwidget)

        # All Actions
        self.unstage_all_action = add_action(self, N_('Unstage All'),
                                             cmds.run(cmds.UnstageAll))
        self.unstage_all_action.setIcon(qtutils.icon('remove.svg'))

        self.unstage_selected_action = add_action(
            self, N_('Unstage From Commit'), cmds.run(cmds.UnstageSelected))
        self.unstage_selected_action.setIcon(qtutils.icon('remove.svg'))

        self.show_diffstat_action = add_action(self, N_('Diffstat'),
                                               cmds.run(cmds.Diffstat),
                                               'Alt+D')

        self.stage_modified_action = add_action(
            self, N_('Stage Changed Files To Commit'),
            cmds.run(cmds.StageModified), 'Alt+A')
        self.stage_modified_action.setIcon(qtutils.icon('add.svg'))

        self.stage_untracked_action = add_action(self,
                                                 N_('Stage All Untracked'),
                                                 cmds.run(cmds.StageUntracked),
                                                 'Alt+U')
        self.stage_untracked_action.setIcon(qtutils.icon('add.svg'))

        self.apply_patches_action = add_action(self, N_('Apply Patches...'),
                                               patch.apply_patches)

        self.export_patches_action = add_action(self, N_('Export Patches...'),
                                                guicmds.export_patches,
                                                'Alt+E')

        self.new_repository_action = add_action(self, N_('New Repository...'),
                                                guicmds.open_new_repo)
        self.new_repository_action.setIcon(qtutils.new_icon())

        self.preferences_action = add_action(self, N_('Preferences'),
                                             self.preferences,
                                             QtGui.QKeySequence.Preferences)

        self.edit_remotes_action = add_action(
            self, N_('Edit Remotes...'),
            lambda: editremotes.remote_editor().exec_())

        self.rescan_action = add_action(self, cmds.Refresh.name(),
                                        cmds.run(cmds.Refresh),
                                        *cmds.Refresh.SHORTCUTS)
        self.rescan_action.setIcon(qtutils.reload_icon())

        self.find_files_action = add_action(self, N_('Find Files'),
                                            finder.finder, 'Ctrl+T', 'T')
        self.find_files_action.setIcon(qtutils.theme_icon('zoom-in.png'))

        self.browse_recently_modified_action = add_action(
            self, N_('Recently Modified Files...'), recent.browse_recent_files,
            'Shift+Ctrl+E')

        self.cherry_pick_action = add_action(self, N_('Cherry-Pick...'),
                                             guicmds.cherry_pick,
                                             'Shift+Ctrl+C')

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

        self.save_tarball_action = add_action(self,
                                              N_('Save As Tarball/Zip...'),
                                              self.save_archive)

        self.quit_action = add_action(self, N_('Quit'), self.close, 'Ctrl+Q')
        self.grep_action = add_action(self, N_('Grep'), grep.grep, 'Ctrl+G')
        self.merge_local_action = add_action(self, N_('Merge...'),
                                             merge.local_merge, 'Shift+Ctrl+M')

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

        self.fetch_action = add_action(self, N_('Fetch...'), remote.fetch,
                                       'Ctrl+F')
        self.push_action = add_action(self, N_('Push...'), remote.push,
                                      'Ctrl+P')
        self.pull_action = add_action(self, N_('Pull...'), remote.pull,
                                      'Shift+Ctrl+P')

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

        self.open_repo_new_action = add_action(self,
                                               N_('Open in New Window...'),
                                               guicmds.open_repo_in_new_window)
        self.open_repo_new_action.setIcon(qtutils.open_icon())

        self.stash_action = add_action(self, N_('Stash...'), stash.stash,
                                       'Alt+Shift+S')

        self.clone_repo_action = add_action(self, N_('Clone...'),
                                            self.clone_repo)
        self.clone_repo_action.setIcon(qtutils.git_icon())

        self.help_docs_action = add_action(self, N_('Documentation'),
                                           resources.show_html_docs,
                                           QtGui.QKeySequence.HelpContents)

        self.help_shortcuts_action = add_action(self, N_('Keyboard Shortcuts'),
                                                about.show_shortcuts,
                                                Qt.Key_Question)

        self.visualize_current_action = add_action(
            self, N_('Visualize Current Branch...'),
            cmds.run(cmds.VisualizeCurrent))
        self.visualize_all_action = add_action(self,
                                               N_('Visualize All Branches...'),
                                               cmds.run(cmds.VisualizeAll))
        self.search_commits_action = add_action(self, N_('Search...'),
                                                search.search)
        self.browse_branch_action = add_action(self,
                                               N_('Browse Current Branch...'),
                                               guicmds.browse_current)
        self.browse_other_branch_action = add_action(
            self, N_('Browse Other Branch...'), guicmds.browse_other)
        self.load_commitmsg_template_action = add_action(
            self, N_('Get Commit Message Template'),
            cmds.run(cmds.LoadCommitMessageFromTemplate))
        self.help_about_action = add_action(self, N_('About'),
                                            about.launch_about_dialog)

        self.diff_expression_action = add_action(self, N_('Expression...'),
                                                 guicmds.diff_expression)
        self.branch_compare_action = add_action(self, N_('Branches...'),
                                                compare.compare_branches)

        self.create_tag_action = add_action(self, N_('Create Tag...'),
                                            createtag.create_tag)

        self.create_branch_action = add_action(self, N_('Create...'),
                                               createbranch.create_new_branch,
                                               'Ctrl+B')

        self.delete_branch_action = add_action(self, N_('Delete...'),
                                               guicmds.delete_branch)

        self.delete_remote_branch_action = add_action(
            self, N_('Delete Remote Branch...'), guicmds.delete_remote_branch)

        self.rename_branch_action = add_action(self, N_('Rename Branch...'),
                                               guicmds.rename_branch)

        self.checkout_branch_action = add_action(self, N_('Checkout...'),
                                                 guicmds.checkout_branch,
                                                 'Alt+B')
        self.branch_review_action = add_action(self, N_('Review...'),
                                               guicmds.review_branch)

        self.browse_action = add_action(self, N_('File Browser...'),
                                        browse.worktree_browser)
        self.browse_action.setIcon(qtutils.git_icon())

        self.dag_action = add_action(self, N_('DAG...'), self.git_dag)
        self.dag_action.setIcon(qtutils.git_icon())

        self.rebase_start_action = add_action(
            self, N_('Start Interactive Rebase...'), self.rebase_start)

        self.rebase_edit_todo_action = add_action(self, N_('Edit...'),
                                                  self.rebase_edit_todo)

        self.rebase_continue_action = add_action(self, N_('Continue'),
                                                 self.rebase_continue)

        self.rebase_skip_action = add_action(self, N_('Skip Current Patch'),
                                             self.rebase_skip)

        self.rebase_abort_action = add_action(self, N_('Abort'),
                                              self.rebase_abort)

        # Relayed actions
        status_tree = self.statusdockwidget.widget().tree
        self.addAction(status_tree.delete_untracked_files_action)

        if not self.browser_dockable:
            # These shortcuts conflict with those from the
            # 'Browser' widget so don't register them when
            # the browser is a dockable tool.
            self.addAction(status_tree.revert_unstaged_edits_action)
            self.addAction(status_tree.up_action)
            self.addAction(status_tree.down_action)
            self.addAction(status_tree.process_selection_action)

        self.lock_layout_action = add_action_bool(self, N_('Lock Layout'),
                                                  self.set_lock_layout, False)

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

        # File Menu
        self.file_menu = create_menu(N_('File'), self.menubar)
        self.file_menu.addAction(self.new_repository_action)
        self.open_recent_menu = self.file_menu.addMenu(N_('Open Recent'))
        self.open_recent_menu.setIcon(qtutils.open_icon())
        self.file_menu.addAction(self.open_repo_action)
        self.file_menu.addAction(self.open_repo_new_action)
        self.file_menu.addAction(self.clone_repo_action)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.rescan_action)
        self.file_menu.addAction(self.find_files_action)
        self.file_menu.addAction(self.edit_remotes_action)
        self.file_menu.addAction(self.browse_recently_modified_action)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.load_commitmsg_action)
        self.file_menu.addAction(self.load_commitmsg_template_action)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.apply_patches_action)
        self.file_menu.addAction(self.export_patches_action)
        self.file_menu.addAction(self.save_tarball_action)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.preferences_action)
        self.file_menu.addAction(self.quit_action)
        self.menubar.addAction(self.file_menu.menuAction())

        # Actions menu
        self.actions_menu = create_menu(N_('Actions'), self.menubar)
        self.actions_menu.addAction(self.fetch_action)
        self.actions_menu.addAction(self.push_action)
        self.actions_menu.addAction(self.pull_action)
        self.actions_menu.addAction(self.stash_action)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.create_tag_action)
        self.actions_menu.addAction(self.cherry_pick_action)
        self.actions_menu.addAction(self.merge_local_action)
        self.actions_menu.addAction(self.merge_abort_action)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.grep_action)
        self.actions_menu.addAction(self.search_commits_action)
        self.menubar.addAction(self.actions_menu.menuAction())

        # Staging Area Menu
        self.commit_menu = create_menu(N_('Staging Area'), self.menubar)
        self.commit_menu.setTitle(N_('Staging Area'))
        self.commit_menu.addAction(self.stage_modified_action)
        self.commit_menu.addAction(self.stage_untracked_action)
        self.commit_menu.addSeparator()
        self.commit_menu.addAction(self.unstage_all_action)
        self.commit_menu.addAction(self.unstage_selected_action)
        self.menubar.addAction(self.commit_menu.menuAction())

        # Diff Menu
        self.diff_menu = create_menu(N_('Diff'), self.menubar)
        self.diff_menu.addAction(self.diff_expression_action)
        self.diff_menu.addAction(self.branch_compare_action)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.show_diffstat_action)
        self.menubar.addAction(self.diff_menu.menuAction())

        # Branch Menu
        self.branch_menu = create_menu(N_('Branch'), self.menubar)
        self.branch_menu.addAction(self.branch_review_action)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.create_branch_action)
        self.branch_menu.addAction(self.checkout_branch_action)
        self.branch_menu.addAction(self.delete_branch_action)
        self.branch_menu.addAction(self.delete_remote_branch_action)
        self.branch_menu.addAction(self.rename_branch_action)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.browse_branch_action)
        self.branch_menu.addAction(self.browse_other_branch_action)
        self.branch_menu.addSeparator()
        self.branch_menu.addAction(self.visualize_current_action)
        self.branch_menu.addAction(self.visualize_all_action)
        self.menubar.addAction(self.branch_menu.menuAction())

        # Rebase menu
        self.rebase_menu = create_menu(N_('Rebase'), self.actions_menu)
        self.rebase_menu.addAction(self.rebase_start_action)
        self.rebase_menu.addAction(self.rebase_edit_todo_action)
        self.rebase_menu.addSeparator()
        self.rebase_menu.addAction(self.rebase_continue_action)
        self.rebase_menu.addAction(self.rebase_skip_action)
        self.rebase_menu.addSeparator()
        self.rebase_menu.addAction(self.rebase_abort_action)
        self.menubar.addAction(self.rebase_menu.menuAction())

        # View Menu
        self.view_menu = create_menu(N_('View'), self.menubar)
        self.view_menu.addAction(self.browse_action)
        self.view_menu.addAction(self.dag_action)
        self.view_menu.addSeparator()
        if self.browser_dockable:
            self.view_menu.addAction(self.browserdockwidget.toggleViewAction())

        self.setup_dockwidget_view_menu()
        self.view_menu.addSeparator()
        self.view_menu.addAction(self.lock_layout_action)
        self.menubar.addAction(self.view_menu.menuAction())

        # Help Menu
        self.help_menu = create_menu(N_('Help'), self.menubar)
        self.help_menu.addAction(self.help_docs_action)
        self.help_menu.addAction(self.help_shortcuts_action)
        self.help_menu.addAction(self.help_about_action)
        self.menubar.addAction(self.help_menu.menuAction())

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

        # Arrange dock widgets
        left = Qt.LeftDockWidgetArea
        right = Qt.RightDockWidgetArea
        bottom = Qt.BottomDockWidgetArea

        self.addDockWidget(left, self.commitdockwidget)
        if self.browser_dockable:
            self.addDockWidget(left, self.browserdockwidget)
            self.tabifyDockWidget(self.browserdockwidget,
                                  self.commitdockwidget)
        self.addDockWidget(left, self.diffdockwidget)
        self.addDockWidget(right, self.statusdockwidget)
        self.addDockWidget(right, self.bookmarksdockwidget)
        self.addDockWidget(right, self.recentdockwidget)
        self.addDockWidget(bottom, self.actionsdockwidget)
        self.addDockWidget(bottom, self.logdockwidget)
        self.tabifyDockWidget(self.actionsdockwidget, self.logdockwidget)

        # Listen for model notifications
        model.add_observer(model.message_updated, self._update)
        model.add_observer(model.message_mode_changed,
                           lambda x: self._update())

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

        # Set a default value
        self.show_cursor_position(1, 0)

        self.connect(self.open_recent_menu, SIGNAL('aboutToShow()'),
                     self.build_recent_menu)

        self.connect(self.commitmsgeditor, SIGNAL('cursorPosition(int,int)'),
                     self.show_cursor_position)

        self.connect(self.diffeditor, SIGNAL('diff_options_updated()'),
                     self.statuswidget.refresh)

        self.connect(self, SIGNAL('update()'), self._update_callback,
                     Qt.QueuedConnection)

        self.connect(self, SIGNAL('install_cfg_actions(PyQt_PyObject)'),
                     self._install_config_actions, Qt.QueuedConnection)

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

        # Restore saved settings
        if not self.restore_state(settings=settings):
            self.resize(987, 610)
            self.set_initial_size()

        self.statusdockwidget.widget().setFocus()

        # Route command output here
        Interaction.log_status = self.logwidget.log_status
        Interaction.log = self.logwidget.log
        Interaction.log(version.git_version_str() + '\n' +
                        N_('git cola version %s') % version.version())
Example #39
0
    def __init__(self, model, parent):
        QtGui.QWidget.__init__(self, parent)

        self.model = model
        self.spellcheck_initialized = False

        self._linebreak = None
        self._textwidth = None
        self._tabwidth = None

        # Actions
        self.signoff_action = qtutils.add_action(self, cmds.SignOff.name(),
                                                 cmds.run(cmds.SignOff),
                                                 hotkeys.SIGNOFF)
        self.signoff_action.setToolTip(N_('Sign off on this commit'))

        self.commit_action = qtutils.add_action(self, N_('Commit@@verb'),
                                                self.commit, hotkeys.COMMIT)
        self.commit_action.setToolTip(N_('Commit staged changes'))
        self.clear_action = qtutils.add_action(self, N_('Clear...'),
                                               self.clear)

        self.launch_editor = actions.launch_editor(self)
        self.launch_difftool = actions.launch_difftool(self)
        self.stage_or_unstage = actions.stage_or_unstage(self)

        self.move_up = actions.move_up(self)
        self.move_down = actions.move_down(self)

        # Widgets
        self.summary = CommitSummaryLineEdit()
        self.summary.setMinimumHeight(defs.tool_button_height)
        self.summary.extra_actions.append(self.clear_action)
        self.summary.extra_actions.append(None)
        self.summary.extra_actions.append(self.signoff_action)
        self.summary.extra_actions.append(self.commit_action)
        self.summary.extra_actions.append(None)
        self.summary.extra_actions.append(self.launch_editor)
        self.summary.extra_actions.append(self.launch_difftool)
        self.summary.extra_actions.append(self.stage_or_unstage)
        self.summary.extra_actions.append(None)
        self.summary.extra_actions.append(self.move_up)
        self.summary.extra_actions.append(self.move_down)

        self.description = CommitMessageTextEdit()
        self.description.extra_actions.append(self.clear_action)
        self.description.extra_actions.append(None)
        self.description.extra_actions.append(self.signoff_action)
        self.description.extra_actions.append(self.commit_action)
        self.description.extra_actions.append(None)
        self.description.extra_actions.append(self.launch_editor)
        self.description.extra_actions.append(self.launch_difftool)
        self.description.extra_actions.append(self.stage_or_unstage)
        self.description.extra_actions.append(None)
        self.description.extra_actions.append(self.move_up)
        self.description.extra_actions.append(self.move_down)

        commit_button_tooltip = N_('Commit staged changes\n'
                                   'Shortcut: Ctrl+Enter')
        self.commit_button = qtutils.create_toolbutton(
            text=N_('Commit@@verb'),
            tooltip=commit_button_tooltip,
            icon=icons.download())
        self.commit_group = Group(self.commit_action, self.commit_button)

        self.actions_menu = qtutils.create_menu(N_('Actions'), self)
        self.actions_button = qtutils.create_toolbutton(
            icon=icons.configure(), tooltip=N_('Actions...'))
        self.actions_button.setMenu(self.actions_menu)
        self.actions_button.setPopupMode(QtGui.QToolButton.InstantPopup)
        qtutils.hide_button_menu_indicator(self.actions_button)

        self.actions_menu.addAction(self.signoff_action)
        self.actions_menu.addAction(self.commit_action)
        self.actions_menu.addSeparator()

        # Amend checkbox
        self.amend_action = self.actions_menu.addAction(
            N_('Amend Last Commit'))
        self.amend_action.setCheckable(True)
        self.amend_action.setShortcut(hotkeys.AMEND)
        self.amend_action.setShortcutContext(Qt.ApplicationShortcut)

        # Bypass hooks
        self.bypass_commit_hooks_action = self.actions_menu.addAction(
            N_('Bypass Commit Hooks'))
        self.bypass_commit_hooks_action.setCheckable(True)
        self.bypass_commit_hooks_action.setChecked(False)

        # Sign commits
        cfg = gitcfg.current()
        self.sign_action = self.actions_menu.addAction(
            N_('Create Signed Commit'))
        self.sign_action.setCheckable(True)
        self.sign_action.setChecked(cfg.get('cola.signcommits', False))

        # Spell checker
        self.check_spelling_action = self.actions_menu.addAction(
            N_('Check Spelling'))
        self.check_spelling_action.setCheckable(True)
        self.check_spelling_action.setChecked(False)

        # Line wrapping
        self.autowrap_action = self.actions_menu.addAction(
            N_('Auto-Wrap Lines'))
        self.autowrap_action.setCheckable(True)
        self.autowrap_action.setChecked(prefs.linebreak())

        # Commit message
        self.actions_menu.addSeparator()
        self.load_commitmsg_menu = self.actions_menu.addMenu(
            N_('Load Previous Commit Message'))
        self.connect(self.load_commitmsg_menu, SIGNAL('aboutToShow()'),
                     self.build_commitmsg_menu)

        self.fixup_commit_menu = self.actions_menu.addMenu(
            N_('Fixup Previous Commit'))
        self.connect(self.fixup_commit_menu, SIGNAL('aboutToShow()'),
                     self.build_fixup_menu)

        self.toplayout = qtutils.hbox(defs.no_margin, defs.spacing,
                                      self.actions_button, self.summary,
                                      self.commit_button)
        self.toplayout.setContentsMargins(defs.margin, defs.no_margin,
                                          defs.no_margin, defs.no_margin)

        self.mainlayout = qtutils.vbox(defs.no_margin, defs.spacing,
                                       self.toplayout, self.description)
        self.setLayout(self.mainlayout)

        qtutils.connect_button(self.commit_button, self.commit)

        # Broadcast the amend mode
        qtutils.connect_action_bool(self.amend_action,
                                    cmds.run(cmds.AmendMode))
        qtutils.connect_action_bool(self.check_spelling_action,
                                    self.toggle_check_spelling)

        # Handle the one-off autowrapping
        qtutils.connect_action_bool(self.autowrap_action, self.set_linebreak)

        qtutils.add_action(self.summary, N_('Move Down'),
                           self.focus_description, *hotkeys.ACCEPT)

        qtutils.add_action(self.summary, N_('Move Down'),
                           self.summary_cursor_down, hotkeys.DOWN)

        self.selection_model = selection_model = selection.selection_model()
        selection_model.add_observer(selection_model.message_selection_changed,
                                     self._update)

        self.model.add_observer(self.model.message_commit_message_changed,
                                self._set_commit_message)

        self.connect(self, SIGNAL('set_commit_message(PyQt_PyObject)'),
                     self.set_commit_message, Qt.QueuedConnection)

        self.connect(self.summary, SIGNAL('cursorPosition(int,int)'),
                     self.emit_position)

        self.connect(
            self.description,
            SIGNAL('cursorPosition(int,int)'),
            # description starts at line 2
            lambda row, col: self.emit_position(row + 2, col))

        # Keep model informed of changes
        self.connect(self.summary, SIGNAL('textChanged(QString)'),
                     self.commit_summary_changed)

        self.connect(self.description, SIGNAL('textChanged()'),
                     self.commit_message_changed)

        self.connect(self.description, SIGNAL('leave()'), self.focus_summary)

        self.connect(self, SIGNAL('update()'), self._update_callback,
                     Qt.QueuedConnection)

        self.setFont(qtutils.diff_font())

        self.summary.hint.enable(True)
        self.description.hint.enable(True)

        self.commit_group.setEnabled(False)

        self.setFocusProxy(self.summary)

        self.set_tabwidth(prefs.tabwidth())
        self.set_textwidth(prefs.textwidth())
        self.set_linebreak(prefs.linebreak())

        # Loading message
        commit_msg = ''
        commit_msg_path = commit_message_path()
        if commit_msg_path:
            commit_msg = core.read(commit_msg_path)
        self.set_commit_message(commit_msg)

        # Allow tab to jump from the summary to the description
        self.setTabOrder(self.summary, self.description)
Example #40
0
    def contextMenuEvent(self, event):
        """Create the context menu for the diff display."""
        menu = QtGui.QMenu(self)
        s = selection.selection()
        filename = selection.filename()

        if self.model.stageable() or self.model.unstageable():
            if self.model.stageable():
                self.stage_or_unstage.setText(N_('Stage'))
            else:
                self.stage_or_unstage.setText(N_('Unstage'))
            menu.addAction(self.stage_or_unstage)

        if s.modified and self.model.stageable():
            if s.modified[0] in main.model().submodules:
                action = menu.addAction(icons.add(), cmds.Stage.name(),
                                        cmds.run(cmds.Stage, s.modified))
                action.setShortcut(hotkeys.STAGE_SELECTION)
                menu.addAction(
                    icons.cola(), N_('Launch git-cola'),
                    cmds.run(cmds.OpenRepo, core.abspath(s.modified[0])))
            elif s.modified[0] not in main.model().unstaged_deleted:
                if self.has_selection():
                    apply_text = N_('Stage Selected Lines')
                    revert_text = N_('Revert Selected Lines...')
                else:
                    apply_text = N_('Stage Diff Hunk')
                    revert_text = N_('Revert Diff Hunk...')

                self.action_apply_selection.setText(apply_text)
                self.action_apply_selection.setIcon(icons.add())

                self.action_revert_selection.setText(revert_text)

                menu.addAction(self.action_apply_selection)
                menu.addAction(self.action_revert_selection)

        if s.staged and self.model.unstageable():
            if s.staged[0] in main.model().submodules:
                action = menu.addAction(icons.remove(), cmds.Unstage.name(),
                                        cmds.do(cmds.Unstage, s.staged))
                action.setShortcut(hotkeys.STAGE_SELECTION)
                menu.addAction(
                    icons.cola(), N_('Launch git-cola'),
                    cmds.do(cmds.OpenRepo, core.abspath(s.staged[0])))
            elif s.staged[0] not in main.model().staged_deleted:
                if self.has_selection():
                    apply_text = N_('Unstage Selected Lines')
                else:
                    apply_text = N_('Unstage Diff Hunk')

                self.action_apply_selection.setText(apply_text)
                self.action_apply_selection.setIcon(icons.remove())
                menu.addAction(self.action_apply_selection)

        if self.model.stageable() or self.model.unstageable():
            # Do not show the "edit" action when the file does not exist.
            # Untracked files exist by definition.
            if filename and core.exists(filename):
                menu.addSeparator()
                menu.addAction(self.launch_editor)

            # Removed files can still be diffed.
            menu.addAction(self.launch_difftool)

        # Add the Previous/Next File actions, which improves discoverability
        # of their associated shortcuts
        menu.addSeparator()
        menu.addAction(self.move_up)
        menu.addAction(self.move_down)

        menu.addSeparator()
        action = menu.addAction(icons.copy(), N_('Copy'), self.copy)
        action.setShortcut(QtGui.QKeySequence.Copy)

        action = menu.addAction(icons.select_all(), N_('Select All'),
                                self.selectAll)
        action.setShortcut(QtGui.QKeySequence.SelectAll)
        menu.exec_(self.mapToGlobal(event.pos()))
Example #41
0
    def __init__(self, parent):
        DiffTextEdit.__init__(self, parent)
        self.model = model = main.model()

        # "Diff Options" tool menu
        self.diff_ignore_space_at_eol_action = add_action(
            self, N_('Ignore changes in whitespace at EOL'),
            self._update_diff_opts)
        self.diff_ignore_space_at_eol_action.setCheckable(True)

        self.diff_ignore_space_change_action = add_action(
            self, N_('Ignore changes in amount of whitespace'),
            self._update_diff_opts)
        self.diff_ignore_space_change_action.setCheckable(True)

        self.diff_ignore_all_space_action = add_action(
            self, N_('Ignore all whitespace'), self._update_diff_opts)
        self.diff_ignore_all_space_action.setCheckable(True)

        self.diff_function_context_action = add_action(
            self, N_('Show whole surrounding functions of changes'),
            self._update_diff_opts)
        self.diff_function_context_action.setCheckable(True)

        self.diffopts_button = create_action_button(tooltip=N_('Diff Options'),
                                                    icon=options_icon())
        self.diffopts_menu = create_menu(N_('Diff Options'),
                                         self.diffopts_button)

        self.diffopts_menu.addAction(self.diff_ignore_space_at_eol_action)
        self.diffopts_menu.addAction(self.diff_ignore_space_change_action)
        self.diffopts_menu.addAction(self.diff_ignore_all_space_action)
        self.diffopts_menu.addAction(self.diff_function_context_action)
        self.diffopts_button.setMenu(self.diffopts_menu)
        qtutils.hide_button_menu_indicator(self.diffopts_button)

        titlebar = parent.titleBarWidget()
        titlebar.add_corner_widget(self.diffopts_button)

        self.action_apply_selection = qtutils.add_action(
            self, '', self.apply_selection, Qt.Key_S)

        self.action_revert_selection = qtutils.add_action(
            self, '', self.revert_selection)
        self.action_revert_selection.setIcon(qtutils.icon('undo.svg'))

        self.launch_editor = qtutils.add_action(self, cmds.LaunchEditor.name(),
                                                run(cmds.LaunchEditor),
                                                cmds.LaunchEditor.SHORTCUT,
                                                'Return', 'Enter')
        self.launch_editor.setIcon(qtutils.options_icon())

        self.launch_difftool = qtutils.add_action(self,
                                                  cmds.LaunchDifftool.name(),
                                                  run(cmds.LaunchDifftool),
                                                  cmds.LaunchDifftool.SHORTCUT)
        self.launch_difftool.setIcon(qtutils.icon('git.svg'))

        model.add_observer(model.message_diff_text_changed, self._emit_text)

        self.connect(self, SIGNAL('set_text'), self.setPlainText)
Example #42
0
    def __init__(self, model, parent=None):
        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 = prefs.PreferencesModel()

        # The widget version is used by import/export_state().
        # Change this whenever dockwidgets are removed.
        self.widget_version = 2

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

        self.setAcceptDrops(True)
        self.setAttribute(Qt.WA_MacMetalStyle)

        cfg = gitcfg.instance()
        self.browser_dockable = (cfg.get('cola.browserdockable')
                                 or cfg.get('cola.classicdockable'))
        if self.browser_dockable:
            self.browserdockwidget = create_dock(N_('Browser'), self)
            self.browserwidget = worktree_browser_widget(self)
            self.browserdockwidget.setWidget(self.browserwidget)

        # "Actions" widget
        self.actionsdockwidget = create_dock(N_('Actions'), self)
        self.actionsdockwidgetcontents = action.ActionButtons(self)
        self.actionsdockwidget.setWidget(self.actionsdockwidgetcontents)
        self.actionsdockwidget.toggleViewAction().setChecked(False)
        self.actionsdockwidget.hide()

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

        # "Commit Message Editor" widget
        self.position_label = QtGui.QLabel()
        font = qtutils.default_monospace_font()
        font.setPointSize(int(font.pointSize() * 0.8))
        self.position_label.setFont(font)
        self.commitdockwidget = create_dock(N_('Commit'), self)
        titlebar = self.commitdockwidget.titleBarWidget()
        titlebar.add_corner_widget(self.position_label)

        self.commitmsgeditor = CommitMessageEditor(model, self)
        self.commitdockwidget.setWidget(self.commitmsgeditor)

        # "Console" widget
        self.logwidget = LogWidget()
        self.logdockwidget = create_dock(N_('Console'), self)
        self.logdockwidget.setWidget(self.logwidget)
        self.logdockwidget.toggleViewAction().setChecked(False)
        self.logdockwidget.hide()

        # "Diff Viewer" widget
        self.diffdockwidget = create_dock(N_('Diff'), self)
        self.diffeditor = DiffEditor(self.diffdockwidget)
        self.diffdockwidget.setWidget(self.diffeditor)

        # "Diff Options" tool menu
        self.diff_ignore_space_at_eol_action = add_action(
            self, N_('Ignore changes in whitespace at EOL'),
            self._update_diff_opts)
        self.diff_ignore_space_at_eol_action.setCheckable(True)

        self.diff_ignore_space_change_action = add_action(
            self, N_('Ignore changes in amount of whitespace'),
            self._update_diff_opts)
        self.diff_ignore_space_change_action.setCheckable(True)

        self.diff_ignore_all_space_action = add_action(
            self, N_('Ignore all whitespace'), self._update_diff_opts)
        self.diff_ignore_all_space_action.setCheckable(True)

        self.diff_function_context_action = add_action(
            self, N_('Show whole surrounding functions of changes'),
            self._update_diff_opts)
        self.diff_function_context_action.setCheckable(True)

        self.diffopts_button = create_toolbutton(text=N_('Options'),
                                                 icon=options_icon(),
                                                 tooltip=N_('Diff Options'))
        self.diffopts_menu = create_menu(N_('Diff Options'),
                                         self.diffopts_button)

        self.diffopts_menu.addAction(self.diff_ignore_space_at_eol_action)
        self.diffopts_menu.addAction(self.diff_ignore_space_change_action)
        self.diffopts_menu.addAction(self.diff_ignore_all_space_action)
        self.diffopts_menu.addAction(self.diff_function_context_action)
        self.diffopts_button.setMenu(self.diffopts_menu)
        self.diffopts_button.setPopupMode(QtGui.QToolButton.InstantPopup)

        titlebar = self.diffdockwidget.titleBarWidget()
        titlebar.add_corner_widget(self.diffopts_button)

        # All Actions
        self.menu_unstage_all = add_action(self, N_('Unstage All'),
                                           cmds.run(cmds.UnstageAll))
        self.menu_unstage_all.setIcon(qtutils.icon('remove.svg'))

        self.menu_unstage_selected = add_action(self,
                                                N_('Unstage From Commit'),
                                                cmds.run(cmds.UnstageSelected))
        self.menu_unstage_selected.setIcon(qtutils.icon('remove.svg'))

        self.menu_show_diffstat = add_action(self, N_('Diffstat'),
                                             cmds.run(cmds.Diffstat), 'Alt+D')

        self.menu_stage_modified = add_action(
            self, N_('Stage Changed Files To Commit'),
            cmds.run(cmds.StageModified), 'Alt+A')
        self.menu_stage_modified.setIcon(qtutils.icon('add.svg'))

        self.menu_stage_untracked = add_action(self, N_('Stage All Untracked'),
                                               cmds.run(cmds.StageUntracked),
                                               'Alt+U')
        self.menu_stage_untracked.setIcon(qtutils.icon('add.svg'))

        self.menu_export_patches = add_action(self, N_('Export Patches...'),
                                              guicmds.export_patches, 'Alt+E')

        self.new_repository = add_action(self, N_('New Repository...'),
                                         guicmds.open_new_repo)
        self.new_repository.setIcon(qtutils.new_icon())

        self.menu_preferences = add_action(self, N_('Preferences'),
                                           self.preferences,
                                           QtGui.QKeySequence.Preferences,
                                           'Ctrl+O')

        self.menu_edit_remotes = add_action(self, N_('Edit Remotes...'),
                                            lambda: editremotes.edit().exec_())
        self.menu_rescan = add_action(self, cmds.Refresh.name(),
                                      cmds.run(cmds.Refresh),
                                      cmds.Refresh.SHORTCUT)
        self.menu_rescan.setIcon(qtutils.reload_icon())

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

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

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

        self.menu_save_tarball = add_action(self, N_('Save As Tarball/Zip...'),
                                            self.save_archive)

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

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

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

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

        self.menu_stash = add_action(self, N_('Stash...'), stash,
                                     'Alt+Shift+S')

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

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

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

        self.menu_visualize_current = add_action(
            self, N_('Visualize Current Branch...'),
            cmds.run(cmds.VisualizeCurrent))
        self.menu_visualize_all = add_action(self,
                                             N_('Visualize All Branches...'),
                                             cmds.run(cmds.VisualizeAll))
        self.menu_search_commits = add_action(self, N_('Search...'), search)
        self.menu_browse_branch = add_action(self,
                                             N_('Browse Current Branch...'),
                                             guicmds.browse_current)
        self.menu_browse_other_branch = add_action(
            self, N_('Browse Other Branch...'), guicmds.browse_other)
        self.menu_load_commitmsg_template = add_action(
            self, N_('Get Commit Message Template'),
            cmds.run(cmds.LoadCommitMessageFromTemplate))
        self.menu_help_about = add_action(self, N_('About'),
                                          launch_about_dialog)

        self.menu_diff_expression = add_action(self, N_('Expression...'),
                                               guicmds.diff_expression)
        self.menu_branch_compare = add_action(self, N_('Branches...'),
                                              compare_branches)

        self.menu_create_tag = add_action(self, N_('Create Tag...'),
                                          create_tag)

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

        self.menu_delete_branch = add_action(self, N_('Delete...'),
                                             guicmds.delete_branch)

        self.menu_delete_remote_branch = add_action(
            self, N_('Delete Remote Branch...'), guicmds.delete_remote_branch)

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

        self.menu_browse = add_action(self, N_('Browser...'), worktree_browser)
        self.menu_browse.setIcon(qtutils.git_icon())

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

        self.rebase_start_action = add_action(
            self, N_('Start Interactive Rebase...'), self.rebase_start)

        self.rebase_edit_todo_action = add_action(self, N_('Edit...'),
                                                  self.rebase_edit_todo)

        self.rebase_continue_action = add_action(self, N_('Continue'),
                                                 self.rebase_continue)

        self.rebase_skip_action = add_action(self, N_('Skip Current Patch'),
                                             self.rebase_skip)

        self.rebase_abort_action = add_action(self, N_('Abort'),
                                              self.rebase_abort)

        # Relayed actions
        if not self.browser_dockable:
            # These shortcuts conflict with those from the
            # 'Browser' widget so don't register them when
            # the browser is a dockable tool.
            status_tree = self.statusdockwidget.widget().tree
            self.addAction(status_tree.up)
            self.addAction(status_tree.down)
            self.addAction(status_tree.process_selection)

        self.lock_layout_action = add_action_bool(self, N_('Lock Layout'),
                                                  self.set_lock_layout, False)

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

        # File Menu
        self.file_menu = create_menu(N_('File'), self.menubar)
        self.file_menu.addAction(self.new_repository)
        self.file_menu.addAction(self.menu_open_repo)
        self.menu_open_recent = self.file_menu.addMenu(N_('Open Recent'))
        self.file_menu.addSeparator()
        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_edit_remotes)
        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_save_tarball)
        self.file_menu.addAction(self.menu_export_patches)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.menu_preferences)
        self.file_menu.addAction(self.menu_quit)
        self.menubar.addAction(self.file_menu.menuAction())

        # Actions menu
        self.actions_menu = create_menu(N_('Actions'), self.menubar)
        self.actions_menu.addAction(self.menu_fetch)
        self.actions_menu.addAction(self.menu_push)
        self.actions_menu.addAction(self.menu_pull)
        self.actions_menu.addAction(self.menu_stash)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_create_tag)
        self.actions_menu.addAction(self.menu_cherry_pick)
        self.actions_menu.addAction(self.menu_merge_local)
        self.actions_menu.addAction(self.menu_merge_abort)
        self.actions_menu.addSeparator()
        self.actions_menu.addAction(self.menu_grep)
        self.actions_menu.addAction(self.menu_search_commits)
        self.menubar.addAction(self.actions_menu.menuAction())

        # Index Menu
        self.commit_menu = create_menu(N_('Index'), self.menubar)
        self.commit_menu.setTitle(N_('Index'))
        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.menubar.addAction(self.commit_menu.menuAction())

        # Diff Menu
        self.diff_menu = create_menu(N_('Diff'), self.menubar)
        self.diff_menu.addAction(self.menu_diff_expression)
        self.diff_menu.addAction(self.menu_branch_compare)
        self.diff_menu.addSeparator()
        self.diff_menu.addAction(self.menu_show_diffstat)
        self.menubar.addAction(self.diff_menu.menuAction())

        # Branch Menu
        self.branch_menu = create_menu(N_('Branch'), 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_delete_branch)
        self.branch_menu.addAction(self.menu_delete_remote_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.menubar.addAction(self.branch_menu.menuAction())

        # Rebase menu
        self.rebase_menu = create_menu(N_('Rebase'), self.actions_menu)
        self.rebase_menu.addAction(self.rebase_start_action)
        self.rebase_menu.addAction(self.rebase_edit_todo_action)
        self.rebase_menu.addSeparator()
        self.rebase_menu.addAction(self.rebase_continue_action)
        self.rebase_menu.addAction(self.rebase_skip_action)
        self.rebase_menu.addSeparator()
        self.rebase_menu.addAction(self.rebase_abort_action)
        self.menubar.addAction(self.rebase_menu.menuAction())

        # View Menu
        self.view_menu = create_menu(N_('View'), self.menubar)
        self.view_menu.addAction(self.menu_browse)
        self.view_menu.addAction(self.menu_dag)
        self.view_menu.addSeparator()
        if self.browser_dockable:
            self.view_menu.addAction(self.browserdockwidget.toggleViewAction())

        self.setup_dockwidget_view_menu()
        self.view_menu.addSeparator()
        self.view_menu.addAction(self.lock_layout_action)
        self.menubar.addAction(self.view_menu.menuAction())

        # Help Menu
        self.help_menu = create_menu(N_('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)
        self.menubar.addAction(self.help_menu.menuAction())

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

        # Arrange dock widgets
        left = Qt.LeftDockWidgetArea
        right = Qt.RightDockWidgetArea
        bottom = Qt.BottomDockWidgetArea

        self.addDockWidget(left, self.commitdockwidget)
        if self.browser_dockable:
            self.addDockWidget(left, self.browserdockwidget)
            self.tabifyDockWidget(self.browserdockwidget,
                                  self.commitdockwidget)
        self.addDockWidget(left, self.diffdockwidget)
        self.addDockWidget(bottom, self.actionsdockwidget)
        self.addDockWidget(bottom, self.logdockwidget)
        self.tabifyDockWidget(self.actionsdockwidget, self.logdockwidget)

        self.addDockWidget(right, self.statusdockwidget)

        # Listen for model notifications
        model.add_observer(model.message_updated, self._update)
        model.add_observer(model.message_mode_changed,
                           lambda x: self._update())

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

        # Set a default value
        self.show_cursor_position(1, 0)

        self.connect(self.menu_open_recent, SIGNAL('aboutToShow()'),
                     self.build_recent_menu)

        self.connect(self.commitmsgeditor, SIGNAL('cursorPosition(int,int)'),
                     self.show_cursor_position)
        self.connect(self, SIGNAL('update'), self._update_callback)
        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
        if not qtutils.apply_state(self):
            self.set_initial_size()

        self.statusdockwidget.widget().setFocus()

        # Route command output here
        Interaction.log_status = self.logwidget.log_status
        Interaction.log = self.logwidget.log
        Interaction.log(version.git_version_str() + '\n' +
                        N_('git cola version %s') % version.version())
Example #43
0
    def contextMenuEvent(self, event):
        """Create the context menu for the diff display."""
        menu = QtGui.QMenu(self)
        s = selection.selection()
        filename = selection.filename()

        if self.model.stageable() and s.modified:
            if s.modified[0] in main.model().submodules:
                action = menu.addAction(qtutils.icon('add.svg'),
                                        cmds.Stage.name(),
                                        cmds.run(cmds.Stage, s.modified))
                action.setShortcut(cmds.Stage.SHORTCUT)
                menu.addAction(
                    qtutils.git_icon(), N_('Launch git-cola'),
                    cmds.run(cmds.OpenRepo, core.abspath(s.modified[0])))
            else:
                if self.has_selection():
                    apply_text = N_('Stage Selected Lines')
                    revert_text = N_('Revert Selected Lines...')
                else:
                    apply_text = N_('Stage Diff Hunk')
                    revert_text = N_('Revert Diff Hunk...')

                self.action_apply_selection.setText(apply_text)
                self.action_apply_selection.setIcon(qtutils.icon('add.svg'))

                self.action_revert_selection.setText(revert_text)

                menu.addAction(self.action_apply_selection)
                menu.addAction(self.action_revert_selection)

        if self.model.unstageable():
            if s.staged and s.staged[0] in main.model().submodules:
                action = menu.addAction(qtutils.icon('remove.svg'),
                                        cmds.Unstage.name(),
                                        cmds.do(cmds.Unstage, s.staged))
                action.setShortcut(cmds.Unstage.SHORTCUT)
                menu.addAction(
                    qtutils.git_icon(), N_('Launch git-cola'),
                    cmds.do(cmds.OpenRepo, core.abspath(s.staged[0])))
            elif s.staged:
                if self.has_selection():
                    apply_text = N_('Unstage Selected Lines')
                else:
                    apply_text = N_('Unstage Diff Hunk')

                self.action_apply_selection.setText(apply_text)
                self.action_apply_selection.setIcon(qtutils.icon('remove.svg'))

                menu.addAction(self.action_apply_selection)

        if self.model.stageable() or self.model.unstageable():
            # Do not show the "edit" action when the file does not exist.
            # Untracked files exist by definition.
            if filename and core.exists(filename):
                menu.addSeparator()
                menu.addAction(self.launch_editor)

            # Removed files can still be diffed.
            menu.addAction(self.launch_difftool)

        menu.addSeparator()
        action = menu.addAction(qtutils.icon('edit-copy.svg'), N_('Copy'),
                                self.copy)
        action.setShortcut(QtGui.QKeySequence.Copy)

        action = menu.addAction(qtutils.icon('edit-select-all.svg'),
                                N_('Select All'), self.selectAll)
        action.setShortcut(QtGui.QKeySequence.SelectAll)
        menu.exec_(self.mapToGlobal(event.pos()))
Example #44
0
    def __init__(self, parent):
        QtGui.QTreeWidget.__init__(self, parent)

        self.setCursor(Qt.PointingHandCursor)
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.setItemDelegateForColumn(0, ItemDelegate(self))
        self.headerItem().setHidden(True)
        self.setAllColumnsShowFocus(True)
        self.setSortingEnabled(False)
        self.setUniformRowHeights(True)
        self.setAnimated(True)
        self.setRootIsDecorated(False)
        self.setIndentation(0)

        self.add_item('Staged', hide=True)
        self.add_item('Unmerged', hide=True)
        self.add_item('Modified', hide=True)
        self.add_item('Untracked', hide=True)

        # Used to restore the selection
        self.old_scroll = None
        self.old_selection = None
        self.old_contents = None

        self.expanded_items = set()

        self.process_selection = qtutils.add_action(self, 'Stage/Unstage',
                                                    self._process_selection,
                                                    cmds.Stage.SHORTCUT)

        self.launch_difftool = qtutils.add_action(
            self, self.tr(cmds.LaunchDifftool.NAME),
            cmds.run(cmds.LaunchDifftool), cmds.LaunchDifftool.SHORTCUT)
        self.launch_difftool.setIcon(qtutils.icon('git.svg'))

        self.launch_editor = qtutils.add_action(
            self, self.tr(cmds.LaunchEditor.NAME), cmds.run(cmds.LaunchEditor),
            cmds.LaunchEditor.SHORTCUT, 'Return', 'Enter')
        self.launch_editor.setIcon(qtutils.options_icon())

        if not utils.is_win32():
            self.open_using_default_app = qtutils.add_action(
                self, self.tr(cmds.OpenDefaultApp.NAME),
                self._open_using_default_app, cmds.OpenDefaultApp.SHORTCUT)
            self.open_using_default_app.setIcon(qtutils.file_icon())

            self.open_parent_dir = qtutils.add_action(
                self, self.tr(cmds.OpenParentDir.NAME), self._open_parent_dir,
                cmds.OpenParentDir.SHORTCUT)
            self.open_parent_dir.setIcon(qtutils.open_file_icon())

        self.up = qtutils.add_action(self, 'Move Up', self.move_up, Qt.Key_K)
        self.down = qtutils.add_action(self, 'Move Down', self.move_down,
                                       Qt.Key_J)

        self.copy_path_action = qtutils.add_action(self,
                                                   'Copy Path to Clipboard',
                                                   self.copy_path,
                                                   QtGui.QKeySequence.Copy)
        self.copy_path_action.setIcon(qtutils.theme_icon('edit-copy.svg'))

        self.connect(self, SIGNAL('about_to_update'), self._about_to_update)
        self.connect(self, SIGNAL('updated'), self._updated)

        self.m = cola.model()
        self.m.add_observer(self.m.message_about_to_update,
                            self.about_to_update)
        self.m.add_observer(self.m.message_updated, self.updated)

        self.connect(self, SIGNAL('itemSelectionChanged()'),
                     self.show_selection)

        self.connect(self, SIGNAL('itemDoubleClicked(QTreeWidgetItem*,int)'),
                     self.double_clicked)

        self.connect(self, SIGNAL('itemCollapsed(QTreeWidgetItem*)'),
                     lambda x: self.update_column_widths())

        self.connect(self, SIGNAL('itemExpanded(QTreeWidgetItem*)'),
                     lambda x: self.update_column_widths())