Exemple #1
0
    def __init__(self, model, parent):
        standard.MainWindow.__init__(self, parent)
        # Default size; this is thrown out when save/restore is used
        self.resize(987, 610)
        self.model = model
        self.prefs_model = prefs_model = PreferencesModel()

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

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

        self.setAcceptDrops(True)

        # Dockwidget options
        qtcompat.set_common_dock_options(self)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

        log(0, self.model.git_version + '\ncola version ' + version.version())
Exemple #2
0
    def __init__(self, parent=None):
        MainWindow.__init__(self, parent)
        self.setAcceptDrops(True)

        # Qt does not support noun/verbs
        self.commit_button.setText(qtutils.tr('Commit@@verb'))
        self.commit_menu.setTitle(qtutils.tr('Commit@@verb'))

        self._has_threadpool = hasattr(QtCore, 'QThreadPool')

        # Diff/patch syntax highlighter
        self.syntax = DiffSyntaxHighlighter(self.display_text.document())

        # Display the current column
        self.connect(self.commitmsg,
                     SIGNAL('cursorPositionChanged()'),
                     self.show_cursor_position)

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

        # Initialize the seen tree widget indexes
        self._seen_indexes = set()

        # Initialize the GUI to show 'Column: 00'
        self.show_cursor_position()

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

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

        # Listen for text and amend messages
        cola.notifier().connect(signals.diff_text, self.set_display)
        cola.notifier().connect(signals.mode, self._mode_changed)
        cola.notifier().connect(signals.amend, self.amend_checkbox.setChecked)

        # Broadcast the amend mode
        self.connect(self.amend_checkbox, SIGNAL('toggled(bool)'),
                     SLOT(signals.amend_mode))

        # Add button callbacks
        self._relay_button(self.alt_button, signals.reset_mode)
        self._relay_button(self.rescan_button, signals.rescan)

        self._connect_button(self.signoff_button, self.signoff)
        self._connect_button(self.stage_button, self.stage)
        self._connect_button(self.unstage_button, self.unstage)
        self._connect_button(self.commit_button, self.commit)
        self._connect_button(self.fetch_button, guicmds.fetch_slot(self))
        self._connect_button(self.push_button, guicmds.push_slot(self))
        self._connect_button(self.pull_button, guicmds.pull_slot(self))
        self._connect_button(self.stash_button, lambda: stash.stash(parent=self))

        # Menu actions
        actions = [
            (self.menu_quit, self.close),
            (self.menu_branch_compare, compare.branch_compare),
            (self.menu_branch_diff, guicmds.branch_diff),
            (self.menu_branch_review, guicmds.review_branch),
            (self.menu_browse_branch, guicmds.browse_current),
            (self.menu_browse_other_branch, guicmds.browse_other),
            (self.menu_browse_commits, guicmds.browse_commits),
            (self.menu_create_tag, createtag.create_tag),
            (self.menu_create_branch, create_new_branch),
            (self.menu_checkout_branch, guicmds.checkout_branch),
            (self.menu_delete_branch, guicmds.branch_delete),
            (self.menu_rebase_branch, guicmds.rebase),
            (self.menu_clone_repo, guicmds.clone_repo),
            (self.menu_commit_compare, compare.compare),
            (self.menu_commit_compare_file, compare.compare_file),
            (self.menu_cherry_pick, guicmds.cherry_pick),
            (self.menu_diff_expression, guicmds.diff_expression),
            (self.menu_diff_branch, guicmds.diff_branch),
            (self.menu_export_patches, guicmds.export_patches),
            (self.menu_help_about, about.launch_about_dialog),
            (self.menu_help_docs,
                lambda: self.model.git.web__browse(resources.html_docs())),
            (self.menu_load_commitmsg, guicmds.load_commitmsg_slot(self)),
            (self.menu_load_commitmsg_template,
                SLOT(signals.load_commit_template)),
            (self.menu_manage_bookmarks, manage_bookmarks),
            (self.menu_save_bookmark, save_bookmark),
            (self.menu_merge_local, merge.local_merge),
            (self.menu_merge_abort, merge.abort_merge),
            (self.menu_fetch, guicmds.fetch_slot(self)),
            (self.menu_push, guicmds.push_slot(self)),
            (self.menu_pull, guicmds.pull_slot(self)),
            (self.menu_open_repo, guicmds.open_repo_slot(self)),
            (self.menu_options, update_options),
            (self.menu_rescan, SLOT(signals.rescan)),
            (self.menu_grep, guicmds.grep),
            (self.menu_search_commits, smod.search),
            (self.menu_show_diffstat, SLOT(signals.diffstat)),
            (self.menu_stash, lambda: stash.stash(parent=self)),
            (self.menu_stage_modified, SLOT(signals.stage_modified)),
            (self.menu_stage_untracked, SLOT(signals.stage_untracked)),
            (self.menu_unstage_selected, SLOT(signals.unstage_selected)),
            (self.menu_unstage_all, SLOT(signals.unstage_all)),
            (self.menu_visualize_all, SLOT(signals.visualize_all)),
            (self.menu_visualize_current, SLOT(signals.visualize_current)),
            # TODO This edit menu stuff should/could be command objects
            (self.menu_cut, self.action_cut),
            (self.menu_copy, self.action_copy),
            (self.menu_paste, self.commitmsg.paste),
            (self.menu_delete, self.action_delete),
            (self.menu_select_all, self.commitmsg.selectAll),
            (self.menu_undo, self.commitmsg.undo),
            (self.menu_redo, self.commitmsg.redo),
            (self.menu_classic, classic.cola_classic),
            (self.menu_dag, dag.git_dag),
        ]

        # Diff Actions
        if hasattr(Qt, 'WidgetWithChildrenShortcut'):
            # We can only enable this shortcut on newer versions of Qt
            # that support WidgetWithChildrenShortcut otherwise we get
            # an ambiguous shortcut error.
            self.diff_copy = QtGui.QAction(self.display_text)
            self.diff_copy.setShortcut(QtGui.QKeySequence.Copy)
            self.diff_copy.setShortcutContext(Qt.WidgetWithChildrenShortcut)
            self.display_text.addAction(self.diff_copy)
            actions.append((self.diff_copy, self.copy_display,))

        for menu, callback in actions:
            self.connect(menu, SIGNAL('triggered()'), callback)

        # Install UI wrappers for command objects
        actionsmod.install_command_wrapper(self)
        guicmds.install_command_wrapper(self)

        # Install diff shortcut keys for stage/unstage
        self.display_text.keyPressEvent = self.diff_key_press_event
        self.display_text.contextMenuEvent = self.diff_context_menu_event

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

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

        # Restore saved settings
        self._gui_state_task = None
        self._load_gui_state()
Exemple #3
0
    def __init__(self, parent=None):
        MainWindow.__init__(self, parent)
        self.setAcceptDrops(True)

        # Qt does not support noun/verbs
        self.commit_button.setText(qtutils.tr('Commit@@verb'))
        self.commit_menu.setTitle(qtutils.tr('Commit@@verb'))

        # Diff/patch syntax highlighter
        self.syntax = DiffSyntaxHighlighter(self.display_text.document())

        # Display the current column
        self.connect(self.commitmsg,
                     SIGNAL('cursorPositionChanged()'),
                     self.show_cursor_position)

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

        # Initialize the seen tree widget indexes
        self._seen_indexes = set()

        # Initialize the GUI to show 'Column: 00'
        self.show_cursor_position()

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

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

        # Listen for text and amend messages
        cola.notifier().listen(signals.diff_text, self.set_display)
        cola.notifier().listen(signals.mode, self._mode_changed)
        cola.notifier().listen(signals.inotify, self._inotify_enabled)
        cola.notifier().listen(signals.amend, self.amend_checkbox.setChecked)

        # Broadcast the amend mode
        self.connect(self.amend_checkbox, SIGNAL('toggled(bool)'),
                     SLOT(signals.amend_mode))

        # Add button callbacks
        self._relay_button(self.alt_button, signals.reset_mode)
        self._relay_button(self.rescan_button, signals.rescan)
        self._relay_button(self.signoff_button, signals.add_signoff)

        self._connect_button(self.stage_button, self.stage)
        self._connect_button(self.unstage_button, self.unstage)
        self._connect_button(self.commit_button, self.commit)
        self._connect_button(self.fetch_button, self.fetch)
        self._connect_button(self.push_button, self.push)
        self._connect_button(self.pull_button, self.pull)
        self._connect_button(self.stash_button, stash)

        # Menu actions
        actions = (
            (self.menu_quit, self.close),
            (self.menu_branch_compare, compare.branch_compare),
            (self.menu_branch_diff, self.branch_diff),
            (self.menu_branch_review, self.review_branch),
            (self.menu_browse_branch, self.browse_current),
            (self.menu_browse_other_branch, self.browse_other),
            (self.menu_browse_commits, self.browse_commits),
            (self.menu_create_tag, createtag.create_tag),
            (self.menu_create_branch, create_new_branch),
            (self.menu_checkout_branch, self.checkout_branch),
            (self.menu_delete_branch, self.branch_delete),
            (self.menu_rebase_branch, self.rebase),
            (self.menu_clone_repo, guicmds.clone_repo),
            (self.menu_commit_compare, compare.compare),
            (self.menu_commit_compare_file, compare.compare_file),
            (self.menu_cherry_pick, self.cherry_pick),
            (self.menu_diff_expression, self.diff_expression),
            (self.menu_diff_branch, self.diff_branch),
            (self.menu_export_patches, self.export_patches),
            (self.menu_help_about, about.launch_about_dialog),
            (self.menu_help_docs,
                lambda: self.model.git.web__browse(resources.html_docs())),
            (self.menu_load_commitmsg, self.load_commitmsg),
            (self.menu_load_commitmsg_template,
                SLOT(signals.load_commit_template)),
            (self.menu_manage_bookmarks, manage_bookmarks),
            (self.menu_save_bookmark, save_bookmark),
            (self.menu_merge_local, local_merge),
            (self.menu_merge_abort, abort_merge),
            (self.menu_open_repo, self.open_repo),
            (self.menu_options, update_options),
            (self.menu_rescan, SLOT(signals.rescan)),
            (self.menu_search_grep, self.grep),
            (self.menu_search_revision, smod.search(smod.REVISION_ID)),
            (self.menu_search_revision_range, smod.search(smod.REVISION_RANGE)),
            (self.menu_search_message, smod.search(smod.MESSAGE)),
            (self.menu_search_path, smod.search(smod.PATH, True)),
            (self.menu_search_date_range, smod.search(smod.DATE_RANGE)),
            (self.menu_search_diff, smod.search(smod.DIFF)),
            (self.menu_search_author, smod.search(smod.AUTHOR)),
            (self.menu_search_committer, smod.search(smod.COMMITTER)),
            (self.menu_show_diffstat, SLOT(signals.diffstat)),
            (self.menu_stash, stash),
            (self.menu_stage_modified, SLOT(signals.stage_modified)),
            (self.menu_stage_untracked, SLOT(signals.stage_untracked)),
            (self.menu_unstage_selected, SLOT(signals.unstage_selected)),
            (self.menu_unstage_all, SLOT(signals.unstage_all)),
            (self.menu_visualize_all, SLOT(signals.visualize_all)),
            (self.menu_visualize_current, SLOT(signals.visualize_current)),
            # TODO This edit menu stuff should/could be command objects
            (self.menu_cut, self.action_cut),
            (self.menu_copy, self.action_copy),
            (self.menu_paste, self.commitmsg.paste),
            (self.menu_delete, self.action_delete),
            (self.menu_select_all, self.commitmsg.selectAll),
            (self.menu_undo, self.commitmsg.undo),
            (self.menu_redo, self.commitmsg.redo),
            (self.menu_classic, classic.cola_classic),
        )
        for menu, callback in actions:
            self.connect(menu, SIGNAL('triggered()'), callback)

        # Install diff shortcut keys for stage/unstage
        self.display_text.keyPressEvent = self.diff_key_press_event
        self.display_text.contextMenuEvent = self.diff_context_menu_event

        # Restore saved settings
        self._load_gui_state()