def _send_msg(): if git.GIT_COLA_TRACE == 'trace': msg = ('info: Trace enabled. ' 'Many of commands reported with "trace" use git\'s stable ' '"plumbing" API and are not intended for typical ' 'day-to-day use. Here be dragons') Interaction.log(msg)
def action_completed(self, task, status, out, err): # Grab the results of the action and finish up self.action_button.setEnabled(True) self.close_button.setEnabled(True) already_up_to_date = N_('Already up-to-date.') if not out: # git fetch --tags --verbose doesn't print anything... out = already_up_to_date command = 'git %s' % self.action.lower() message = (N_('"%(command)s" returned exit status %(status)d') % dict(command=command, status=status)) details = '' if out: details = out if err: details += '\n\n' + err log_message = message if details: log_message += '\n\n' + details Interaction.log(log_message) if status == 0: self.accept() return if self.action == PUSH: message += '\n\n' message += N_('Have you rebased/pulled lately?') Interaction.critical(self.windowTitle(), message=message, details=details)
def action_completed(self, task, status, output): # Grab the results of the action and finish up self.progress_thread.stop() self.progress_thread.wait() if task in self.tasks: self.tasks.remove(task) already_up_to_date = N_('Already up-to-date.') if not output: # git fetch --tags --verbose doesn't print anything... output = already_up_to_date self.setEnabled(True) self.progress.close() QtGui.QApplication.restoreOverrideCursor() command = 'git %s' % self.action.lower() message = (N_('"%(command)s" returned exit status %(status)d') % dict(command=command, status=status)) if output: message += '\n\n' + output Interaction.log(message) if status == 0: self.accept() return if self.action == PUSH: message += '\n\n' message += N_('Have you rebased/pulled lately?') Interaction.critical(self.windowTitle(), message=message, details=output)
def start(): global _thread if not AVAILABLE: if utils.is_win32(): msg = ('file notification: disabled\n' 'Note: install pywin32 to enable.\n') elif utils.is_linux(): msg = ('inotify: disabled\n' 'Note: install python-pyinotify to enable inotify.\n') else: return if utils.is_debian(): msg += ('On Debian systems ' 'try: sudo aptitude install python-pyinotify') Interaction.log(msg) return # Start the notification thread _thread = GitNotifier() _thread.start() if utils.is_win32(): msg = 'file notification: enabled' else: msg = 'inotify support: enabled' Interaction.log(msg)
def action_completed(self, task, status, output): # Grab the results of the action and finish up self.progress_thread.stop() self.progress_thread.wait() if task in self.tasks: self.tasks.remove(task) already_up_to_date = self.tr('Already up-to-date.') if not output: # git fetch --tags --verbose doesn't print anything... output = already_up_to_date self.setEnabled(True) self.progress.close() QtGui.QApplication.restoreOverrideCursor() result = 'returned exit status %d' % status message = '"git %s" %s' % (self.action.lower(), result) if output: message += '\n\n' + output # Force the status to 1 so that we always display the log Interaction.log(message) if status == 0: self.accept() return if self.action == PUSH: message += '\n\nHave you rebased/pulled lately?' Interaction.critical(self.windowTitle(), message=message, details=output)
def action_callback(self): action = self.action if action == FETCH: model_action = self.model.fetch elif action == PUSH: model_action = self.push_to_all else: # if action == PULL: model_action = self.model.pull remote_name = ustr(self.remote_name.text()) if not remote_name: errmsg = N_("No repository selected.") Interaction.log(errmsg) return remote, kwargs = self.common_args() self.selected_remotes = qtutils.selected_items(self.remotes, self.model.remotes) # Check if we're about to create a new branch and warn. remote_branch = ustr(self.remote_branch.text()) local_branch = ustr(self.local_branch.text()) if action == PUSH and not remote_branch: branch = local_branch candidate = "%s/%s" % (remote, branch) if candidate not in self.model.remote_branches: title = N_("Push") args = dict(branch=branch, remote=remote) msg = ( N_('Branch "%(branch)s" does not exist in "%(remote)s".\n' "A new remote branch will be published.") % args ) info_txt = N_("Create a new remote branch?") ok_text = N_("Create Remote Branch") if not qtutils.confirm(title, msg, info_txt, ok_text, icon=icons.cola()): return if not self.ffwd_only_checkbox.isChecked(): if action == FETCH: title = N_("Force Fetch?") msg = N_("Non-fast-forward fetch overwrites local history!") info_txt = N_("Force fetching from %s?") % remote ok_text = N_("Force Fetch") elif action == PUSH: title = N_("Force Push?") msg = N_("Non-fast-forward push overwrites published " "history!\n(Did you pull first?)") info_txt = N_("Force push to %s?") % remote ok_text = N_("Force Push") else: # pull: shouldn't happen since the controls are hidden msg = "You probably don't want to do this.\n\tContinue?" return if not qtutils.confirm(title, msg, info_txt, ok_text, default=False, icon=icons.discard()): return # Disable the GUI by default self.buttons.setEnabled(False) # Use a thread to update in the background task = ActionTask(self.task_runner, model_action, remote, kwargs) self.task_runner.start(task, progress=self.progress, finish=self.action_completed)
def _revert_unstaged_edits(self, staged=False): if not self.m.undoable(): return if staged: items_to_undo = self.staged() else: items_to_undo = self.modified() if items_to_undo: if not qtutils.confirm( N_('Revert Unstaged Changes?'), N_('This operation drops unstaged changes.\n' 'These changes cannot be recovered.'), N_('Revert the unstaged changes?'), N_('Revert Unstaged Changes'), default=True, icon=qtutils.icon('undo.svg')): return args = [] if not staged and self.m.amending(): args.append(self.m.head) cmds.do(cmds.Checkout, args + ['--'] + items_to_undo) else: msg = N_('No files selected for checkout from HEAD.') Interaction.log(msg)
def do(self): if not self.model.undoable(): return s = selection.selection() if s.staged: items_to_undo = s.staged else: items_to_undo = s.modified if items_to_undo: if not Interaction.confirm( N_('Revert Unstaged Changes?'), N_('This operation drops unstaged changes.\n' 'These changes cannot be recovered.'), N_('Revert the unstaged changes?'), N_('Revert Unstaged Changes'), default=True, icon=resources.icon('undo.svg')): return args = [] if not s.staged and self.model.amending(): args.append(self.model.head) do(Checkout, args + ['--'] + items_to_undo) else: msg = N_('No files selected for checkout from HEAD.') Interaction.log(msg)
def do(self): msg = N_('Staging: %s') % (', '.join(self.paths)) Interaction.log(msg) # Prevent external updates while we are staging files. # We update file stats at the end of this operation # so there's no harm in ignoring updates from other threads # (e.g. inotify). with CommandDisabled(UpdateFileStatus): self.model.stage_paths(self.paths)
def clone_repo(spawn=True): """ Present GUI controls for cloning a repository A new cola session is invoked when 'spawn' is True. """ url, ok = qtutils.prompt(N_('Path or URL to clone (Env. $VARS okay)')) url = os.path.expandvars(core.encode(url)) if not ok or not url: return None try: # Pick a suitable basename by parsing the URL newurl = url.replace('\\', '/').rstrip('/') default = newurl.rsplit('/', 1)[-1] if default == '.git': # The end of the URL is /.git, so assume it's a file path default = os.path.basename(os.path.dirname(newurl)) if default.endswith('.git'): # The URL points to a bare repo default = default[:-4] if url == '.': # The URL is the current repo default = os.path.basename(os.getcwd()) if not default: raise except: Interaction.information( N_('Error Cloning'), N_('Could not parse Git URL: "%s"') % url) Interaction.log(N_('Could not parse Git URL: "%s"') % url) return None # Prompt the user for a directory to use as the parent directory msg = N_('Select a parent directory for the new clone') dirname = qtutils.opendir_dialog(msg, cola.model().getcwd()) if not dirname: return None count = 1 dirname = core.decode(dirname) destdir = os.path.join(dirname, core.decode(default)) olddestdir = destdir if os.path.exists(destdir): # An existing path can be specified msg = (N_('"%s" already exists, cola will create a new directory') % destdir) Interaction.information('Directory Exists', msg) # Make sure the new destdir doesn't exist while os.path.exists(destdir): destdir = olddestdir + str(count) count += 1 if cmds.do(cmds.Clone, core.decode(url), destdir, spawn=spawn): return destdir return None
def select_commits(self): summaries = self.model.summaries if not summaries: msg = N_('No commits exist in this branch.') Interaction.log(msg) return [] qtutils.set_items(self.commit_list, summaries) self.show() if self.exec_() != QtGui.QDialog.Accepted: return [] return self.selected_commits()
def clone_repo(spawn=True): """ Present GUI controls for cloning a repository A new cola session is invoked when 'spawn' is True. """ url, ok = qtutils.prompt(N_('Path or URL to clone (Env. $VARS okay)')) url = os.path.expandvars(core.encode(url)) if not ok or not url: return None try: # Pick a suitable basename by parsing the URL newurl = url.replace('\\', '/').rstrip('/') default = newurl.rsplit('/', 1)[-1] if default == '.git': # The end of the URL is /.git, so assume it's a file path default = os.path.basename(os.path.dirname(newurl)) if default.endswith('.git'): # The URL points to a bare repo default = default[:-4] if url == '.': # The URL is the current repo default = os.path.basename(os.getcwd()) if not default: raise except: Interaction.information(N_('Error Cloning'), N_('Could not parse Git URL: "%s"') % url) Interaction.log(N_('Could not parse Git URL: "%s"') % url) return None # Prompt the user for a directory to use as the parent directory msg = N_('Select a parent directory for the new clone') dirname = qtutils.opendir_dialog(msg, cola.model().getcwd()) if not dirname: return None count = 1 dirname = core.decode(dirname) destdir = os.path.join(dirname, core.decode(default)) olddestdir = destdir if os.path.exists(destdir): # An existing path can be specified msg = (N_('"%s" already exists, cola will create a new directory') % destdir) Interaction.information('Directory Exists', msg) # Make sure the new destdir doesn't exist while os.path.exists(destdir): destdir = olddestdir + str(count) count += 1 if cmds.do(cmds.Clone, core.decode(url), destdir, spawn=spawn): return destdir return None
def prompt_for_clone(): """ Present a GUI for cloning a repository. Returns the target directory and URL """ url, ok = qtutils.prompt(N_('Path or URL to clone (Env. $VARS okay)')) url = utils.expandpath(url) if not ok or not url: return None try: # Pick a suitable basename by parsing the URL newurl = url.replace('\\', '/').rstrip('/') default = newurl.rsplit('/', 1)[-1] if default == '.git': # The end of the URL is /.git, so assume it's a file path default = os.path.basename(os.path.dirname(newurl)) if default.endswith('.git'): # The URL points to a bare repo default = default[:-4] if url == '.': # The URL is the current repo default = os.path.basename(core.getcwd()) if not default: raise except: Interaction.information( N_('Error Cloning'), N_('Could not parse Git URL: "%s"') % url) Interaction.log(N_('Could not parse Git URL: "%s"') % url) return None # Prompt the user for a directory to use as the parent directory msg = N_('Select a parent directory for the new clone') dirname = qtutils.opendir_dialog(msg, main.model().getcwd()) if not dirname: return None count = 1 destdir = os.path.join(dirname, default) olddestdir = destdir if core.exists(destdir): # An existing path can be specified msg = (N_('"%s" already exists, cola will create a new directory') % destdir) Interaction.information(N_('Directory Exists'), msg) # Make sure the new destdir doesn't exist while core.exists(destdir): destdir = olddestdir + str(count) count += 1 return url, destdir
def select_commits(self): summaries = self.model.summaries if not summaries: msg = self.tr("No commits exist in this branch.") Interaction.log(msg) return [] qtutils.set_items(self.commit_list, summaries) self.show() if self.exec_() != QtGui.QDialog.Accepted: return [] revs = self.model.revisions return qtutils.selection_list(self.commit_list, revs)
def _revert_uncommitted_edits(self, items_to_undo): if items_to_undo: if not qtutils.confirm( N_("Revert Uncommitted Changes?"), N_("This operation drops uncommitted changes.\n" "These changes cannot be recovered."), N_("Revert the uncommitted changes?"), N_("Revert Uncommitted Changes"), default=True, icon=qtutils.icon("undo.svg"), ): return cmds.do(cmds.Checkout, [self.m.head, "--"] + items_to_undo) else: msg = N_("No files selected for checkout from HEAD.") Interaction.log(msg)
def _revert_uncommitted_edits(self, items_to_undo): if items_to_undo: if not qtutils.confirm( N_('Revert Uncommitted Changes?'), N_('This operation drops uncommitted changes.\n' 'These changes cannot be recovered.'), N_('Revert the uncommitted changes?'), N_('Revert Uncommitted Changes'), default=True, icon=qtutils.icon('undo.svg')): return cmds.do(cmds.Checkout, [self.m.head, '--'] + items_to_undo) else: msg = N_('No files selected for checkout from HEAD.') Interaction.log(msg)
def start(): global _thread cfg = gitcfg.instance() if not cfg.get('cola.inotify', True): msg = N_('inotify is disabled because "cola.inotify" is false') Interaction.log(msg) return if not AVAILABLE: if utils.is_win32(): msg = N_('file notification: disabled\n' 'Note: install pywin32 to enable.\n') elif utils.is_linux(): msg = N_('inotify: disabled\n' 'Note: install python-pyinotify to enable inotify.\n') else: return if utils.is_debian(): msg += N_('On Debian systems ' 'try: sudo aptitude install python-pyinotify') Interaction.log(msg) return # Start the notification thread _thread = GitNotifier() _thread.start() if utils.is_win32(): msg = N_('File notification enabled.') else: msg = N_('inotify enabled.') Interaction.log(msg)
def action_completed(self, task, status, out, err): # Grab the results of the action and finish up self.action_button.setEnabled(True) self.close_button.setEnabled(True) QtGui.QApplication.restoreOverrideCursor() self.progress_thread.stop() self.progress_thread.wait() self.progress.close() if task in self.tasks: self.tasks.remove(task) already_up_to_date = N_("Already up-to-date.") if not out: # git fetch --tags --verbose doesn't print anything... out = already_up_to_date command = "git %s" % self.action.lower() message = N_('"%(command)s" returned exit status %(status)d') % dict(command=command, status=status) details = "" if out: details = out if err: details += "\n\n" + err log_message = message if details: log_message += "\n\n" + details Interaction.log(log_message) if status == 0: self.accept() return if self.action == PUSH: message += "\n\n" message += N_("Have you rebased/pulled lately?") Interaction.critical(self.windowTitle(), message=message, details=details)
def _revert_unstaged_edits(self, staged=False): if not self.m.undoable(): return if staged: items_to_undo = self.staged() else: items_to_undo = self.modified() if items_to_undo: if not qtutils.confirm('Revert Unstaged Changes?', 'This operation drops unstaged changes.' '\nThese changes cannot be recovered.', 'Revert the unstaged changes?', 'Revert Unstaged Changes', default=True, icon=qtutils.icon('undo.svg')): return args = [] if not staged and self.m.amending(): args.append(self.m.head) cmds.do(cmds.Checkout, args + ['--'] + items_to_undo) else: msg = self.tr('No files selected for checkout from HEAD.') Interaction.log(msg)
def do(self): if not self.model.undoable(): return s = selection.selection() if s.staged: items_to_undo = s.staged else: items_to_undo = s.modified if items_to_undo: if not Interaction.confirm(N_('Revert Unstaged Changes?'), N_('This operation drops unstaged changes.\n' 'These changes cannot be recovered.'), N_('Revert the unstaged changes?'), N_('Revert Unstaged Changes'), default=True, icon=resources.icon('undo.svg')): return args = [] if not s.staged and self.model.amending(): args.append(self.model.head) do(Checkout, args + ['--'] + items_to_undo) else: msg = N_('No files selected for checkout from HEAD.') Interaction.log(msg)
def _create_instance(): thread_class = None cfg = gitcfg.current() if not cfg.get('cola.inotify', True): msg = N_('File system change monitoring: disabled because' ' "cola.inotify" is false.\n') Interaction.log(msg) elif AVAILABLE == 'inotify': thread_class = _InotifyThread elif AVAILABLE == 'pywin32': thread_class = _Win32Thread else: if utils.is_win32(): msg = N_('File system change monitoring: disabled because pywin32' ' is not installed.\n') Interaction.log(msg) elif utils.is_linux(): msg = N_('File system change monitoring: disabled because libc' ' does not support the inotify system calls.\n') Interaction.log(msg) return _Monitor(thread_class)
def do(self): msg = N_('Untracking: %s') % (', '.join(self.paths)) Interaction.log(msg) with CommandDisabled(UpdateFileStatus): status, out, err = self.model.untrack_paths(self.paths) Interaction.log_status(status, out, err)
def do(self): msg = N_('Unstaging: %s') % (', '.join(self.paths)) Interaction.log(msg) with CommandDisabled(UpdateFileStatus): self.model.unstage_paths(self.paths)
def do(self): msg = 'Untracking: %s' % (', '.join(self.paths)) Interaction.log(msg) status, out = self.model.untrack_paths(self.paths) Interaction.log_status(status, out, '')
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) 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.log(version.git_version_str() + '\n' + N_('git cola version %s') % version.version())
def do(self): for env in ('FILENAME', 'REVISION', 'ARGS'): try: compat.unsetenv(env) except KeyError: pass rev = None args = None opts = _config.get_guitool_opts(self.action_name) cmd = opts.get('cmd') if 'title' not in opts: opts['title'] = cmd if 'prompt' not in opts or opts.get('prompt') is True: prompt = N_('Run "%s"?') % cmd opts['prompt'] = prompt if opts.get('needsfile'): filename = selection.filename() if not filename: Interaction.information( N_('Please select a file'), N_('"%s" requires a selected file.') % cmd) return False compat.setenv('FILENAME', filename) if opts.get('revprompt') or opts.get('argprompt'): while True: ok = Interaction.confirm_config_action(cmd, opts) if not ok: return False rev = opts.get('revision') args = opts.get('args') if opts.get('revprompt') and not rev: title = N_('Invalid Revision') msg = N_('The revision expression cannot be empty.') Interaction.critical(title, msg) continue break elif opts.get('confirm'): title = os.path.expandvars(opts.get('title')) prompt = os.path.expandvars(opts.get('prompt')) if Interaction.question(title, prompt): return if rev: compat.setenv('REVISION', rev) if args: compat.setenv('ARGS', args) title = os.path.expandvars(cmd) Interaction.log(N_('Running command: %s') % title) cmd = ['sh', '-c', cmd] if opts.get('noconsole'): status, out, err = core.run_command(cmd) else: status, out, err = Interaction.run_command(title, cmd) Interaction.log_status(status, out and (N_('Output: %s') % out) or '', err and (N_('Errors: %s') % err) or '') if not opts.get('norescan'): self.model.update_status() return status
def do(self): for env in ('FILENAME', 'REVISION', 'ARGS'): try: compat.unsetenv(env) except KeyError: pass rev = None args = None opts = _config.get_guitool_opts(self.name) cmd = opts.get('cmd') if 'title' not in opts: opts['title'] = cmd if 'prompt' not in opts or opts.get('prompt') is True: prompt = i18n.gettext('Are you sure you want to run %s?') % cmd opts['prompt'] = prompt if opts.get('needsfile'): filename = selection.filename() if not filename: Interaction.information('Please select a file', '"%s" requires a selected file' % cmd) return False compat.putenv('FILENAME', filename) if opts.get('revprompt') or opts.get('argprompt'): while True: ok = Interaction.confirm_config_action(cmd, opts) if not ok: return False rev = opts.get('revision') args = opts.get('args') if opts.get('revprompt') and not rev: title = 'Invalid Revision' msg = 'The revision expression cannot be empty.' Interaction.critical(title, msg) continue break elif opts.get('confirm'): title = os.path.expandvars(opts.get('title')) prompt = os.path.expandvars(opts.get('prompt')) if Interaction.question(title, prompt): return if rev: compat.putenv('REVISION', rev) if args: compat.putenv('ARGS', args) title = os.path.expandvars(cmd) Interaction.log('running: ' + title) cmd = ['sh', '-c', cmd] if opts.get('noconsole'): status, out, err = utils.run_command(cmd) else: status, out, err = Interaction.run_command(title, cmd) Interaction.log_status(status, out and 'stdout: %s' % out, err and 'stderr: %s' % err) if not opts.get('norescan'): self.model.update_status() return status
def __init__(self, model, parent): 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() # 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) self.setAttribute(Qt.WA_MacMetalStyle) # Dockwidget options qtcompat.set_common_dock_options(self) cfg = gitcfg.instance() self.classic_dockable = (cfg.get('cola.browserdockable') or cfg.get('cola.classicdockable')) if self.classic_dockable: self.classicdockwidget = create_dock('Browser', self) self.classicwidget = classic_widget(self) self.classicdockwidget.setWidget(self.classicwidget) # "Actions" widget self.actionsdockwidget = create_dock('Action', self) self.actionsdockwidgetcontents = qt.QFlowLayoutWidget(self) layout = self.actionsdockwidgetcontents.layout() self.stage_button = create_button(text='Stage', layout=layout) self.unstage_button = create_button(text='Unstage', layout=layout) self.rescan_button = create_button(text='Rescan', layout=layout) self.fetch_button = create_button(text='Fetch...', layout=layout) self.push_button = create_button(text='Push...', layout=layout) self.pull_button = create_button(text='Pull...', layout=layout) self.stash_button = create_button(text='Stash...', layout=layout) layout.addStretch() self.actionsdockwidget.setWidget(self.actionsdockwidgetcontents) # "Repository Status" widget self.statusdockwidget = create_dock('Status', self) self.statusdockwidget.setWidget(StatusWidget(self)) # "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('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('Console', self) self.logdockwidget.setWidget(self.logwidget) # "Diff Viewer" widget self.diffdockwidget = create_dock('Diff', self) self.diffeditor = DiffEditor(self.diffdockwidget) self.diffdockwidget.setWidget(self.diffeditor) # All Actions self.menu_unstage_all = add_action(self, 'Unstage All', cmds.run(cmds.UnstageAll)) self.menu_unstage_all.setIcon(qtutils.icon('remove.svg')) self.menu_unstage_selected = add_action(self, 'Unstage From Commit', cmds.run(cmds.UnstageSelected)) self.menu_unstage_selected.setIcon(qtutils.icon('remove.svg')) self.menu_show_diffstat = add_action(self, 'Diffstat', cmds.run(cmds.Diffstat), 'Alt+D') self.menu_stage_modified = add_action(self, '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, '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, 'Export Patches...', guicmds.export_patches, 'Alt+E') self.menu_preferences = add_action(self, 'Preferences', self.preferences, QtGui.QKeySequence.Preferences, 'Ctrl+O') self.menu_edit_remotes = add_action(self, 'Edit Remotes...', lambda: editremotes.edit().exec_()) self.menu_rescan = add_action(self, cmds.RescanAndRefresh.NAME, cmds.run(cmds.RescanAndRefresh), cmds.RescanAndRefresh.SHORTCUT) self.menu_rescan.setIcon(qtutils.reload_icon()) self.menu_browse_recent = add_action(self, 'Recently Modified Files...', browse_recent, 'Shift+Ctrl+E') self.menu_cherry_pick = add_action(self, 'Cherry-Pick...', guicmds.cherry_pick, 'Ctrl+P') self.menu_load_commitmsg = add_action(self, 'Load Commit Message...', guicmds.load_commitmsg) self.menu_save_tarball = add_action(self, 'Save As Tarball/Zip...', self.save_archive) 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, 'Ctrl+G') 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...', remote.fetch) self.menu_push = add_action(self, 'Push...', remote.push) self.menu_pull = add_action(self, 'Pull...', remote.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_clone_repo = add_action(self, 'Clone...', guicmds.clone_repo) self.menu_clone_repo.setIcon(qtutils.git_icon()) self.menu_help_docs = add_action(self, 'Documentation', resources.show_html_docs, QtGui.QKeySequence.HelpContents) self.menu_help_shortcuts = add_action(self, 'Keyboard Shortcuts', show_shortcuts, QtCore.Qt.Key_Question) self.menu_visualize_current = add_action( self, 'Visualize Current Branch...', cmds.run(cmds.VisualizeCurrent)) self.menu_visualize_all = add_action(self, 'Visualize All Branches...', cmds.run(cmds.VisualizeAll)) self.menu_search_commits = add_action(self, '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', cmds.run(cmds.LoadCommitTemplate)) self.menu_help_about = add_action(self, 'About', launch_about_dialog) self.menu_branch_diff = add_action(self, 'SHA-1...', guicmds.diff_revision) self.menu_diff_expression = add_action(self, 'Expression...', guicmds.diff_expression) self.menu_branch_compare = add_action(self, 'Branches...', compare_branches) self.menu_create_tag = add_action(self, 'Create Tag...', 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, 'Browser...', cola_classic) self.menu_classic.setIcon(qtutils.git_icon()) self.menu_dag = add_action(self, 'DAG...', lambda: git_dag(self.model)) self.menu_dag.setIcon(qtutils.git_icon()) # Relayed actions if not self.classic_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) # 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.menu_open_recent = self.file_menu.addMenu(tr('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_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) # 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.addAction(self.menu_branch_compare) self.diff_menu.addSeparator() self.diff_menu.addAction(self.menu_show_diffstat) # Add to menubar self.menubar.addAction(self.diff_menu.menuAction()) # Tools Menu self.tools_menu = create_menu('&Tools', self.menubar) self.tools_menu.addAction(self.menu_classic) self.tools_menu.addAction(self.menu_dag) self.tools_menu.addSeparator() if self.classic_dockable: self.tools_menu.addAction( self.classicdockwidget.toggleViewAction()) self.setup_dockwidget_tools_menu() self.menubar.addAction(self.tools_menu.menuAction()) # Help Menu self.help_menu = create_menu('&Help', self.menubar) self.help_menu.addAction(self.menu_help_docs) self.help_menu.addAction(self.menu_help_shortcuts) self.help_menu.addAction(self.menu_help_about) # Add to menubar self.menubar.addAction(self.help_menu.menuAction()) # Set main menu self.setMenuBar(self.menubar) # Arrange dock widgets top = Qt.TopDockWidgetArea bottom = Qt.BottomDockWidgetArea self.addDockWidget(top, self.commitdockwidget) if self.classic_dockable: self.addDockWidget(top, self.classicdockwidget) self.addDockWidget(top, self.statusdockwidget) self.addDockWidget(top, self.actionsdockwidget) self.addDockWidget(bottom, self.logdockwidget) if self.classic_dockable: self.tabifyDockWidget(self.classicdockwidget, self.commitdockwidget) self.tabifyDockWidget(self.logdockwidget, self.diffdockwidget) # Listen for model notifications model.add_observer(model.message_updated, self._update_view) prefs_model.add_observer(prefs_model.message_config_updated, self._config_updated) # Set a default value self.show_cursor_position(1, 0) # Add button callbacks connect_button(self.rescan_button, cmds.run(cmds.RescanAndRefresh)) connect_button(self.fetch_button, remote.fetch) connect_button(self.push_button, remote.push) connect_button(self.pull_button, remote.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.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() self.dockwidgets = ( self.logdockwidget, self.commitdockwidget, self.statusdockwidget, self.diffdockwidget, self.actionsdockwidget, ) # Restore saved settings qtutils.apply_state(self) 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() + '\ncola version ' + version.version())
def action_callback(self): action = self.action if action == FETCH: model_action = self.model.fetch elif action == PUSH: model_action = self.push_to_all else: # if action == PULL: model_action = self.model.pull remote_name = unicode(self.remote_name.text()) if not remote_name: errmsg = N_('No repository selected.') Interaction.log(errmsg) return remote, kwargs = self.common_args() self.selected_remotes = qtutils.selected_items(self.remotes, self.model.remotes) # Check if we're about to create a new branch and warn. remote_branch = unicode(self.remote_branch.text()) local_branch = unicode(self.local_branch.text()) if action == PUSH and not remote_branch: branch = local_branch candidate = '%s/%s' % (remote, branch) if candidate not in self.model.remote_branches: title = N_('Push') args = dict(branch=branch, remote=remote) msg = N_('Branch "%(branch)s" does not exist in "%(remote)s".\n' 'A new remote branch will be published.') % args info_txt= N_('Create a new remote branch?') ok_text = N_('Create Remote Branch') if not qtutils.confirm(title, msg, info_txt, ok_text, default=False, icon=qtutils.git_icon()): return if not self.ffwd_only_checkbox.isChecked(): if action == FETCH: title = N_('Force Fetch?') msg = N_('Non-fast-forward fetch overwrites local history!') info_txt = N_('Force fetching from %s?') % remote ok_text = N_('Force Fetch') elif action == PUSH: title = N_('Force Push?') msg = N_('Non-fast-forward push overwrites published ' 'history!\n(Did you pull first?)') info_txt = N_('Force push to %s?') % remote ok_text = N_('Force Push') else: # pull: shouldn't happen since the controls are hidden msg = "You probably don't want to do this.\n\tContinue?" return if not qtutils.confirm(title, msg, info_txt, ok_text, default=False, icon=qtutils.discard_icon()): return # Disable the GUI by default self.action_button.setEnabled(False) self.close_button.setEnabled(False) QtGui.QApplication.setOverrideCursor(Qt.WaitCursor) # Show a nice progress bar self.progress.show() self.progress_thread.start() # Use a thread to update in the background task = ActionTask(self, model_action, remote, kwargs) self.tasks.append(task) QtCore.QThreadPool.globalInstance().start(task)
def __init__(self, model, parent=None, settings=None): 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 # Keeps track of merge messages we've seen self.merge_message_hash = '' 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) # "Switch Repository" widget self.bookmarksdockwidget = create_dock(N_('Bookmarks'), self) self.bookmarkswidget = BookmarksWidget(parent=self.bookmarksdockwidget) self.bookmarksdockwidget.setWidget(self.bookmarkswidget) # "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 = 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) # 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...'), 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, 'Ctrl+O') 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.SHORTCUT) self.rescan_action.setIcon(qtutils.reload_icon()) self.browse_recently_modified_action = add_action( self, N_('Recently Modified Files...'), 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.manage_bookmarks_action = add_action(self, N_('Bookmarks...'), self.manage_bookmarks) self.grep_action = add_action(self, N_('Grep'), grep, 'Ctrl+G') self.merge_local_action = add_action(self, N_('Merge...'), merge.local_merge) 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, 'Alt+Shift+S') self.clone_repo_action = add_action(self, N_('Clone...'), guicmds.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'), show_shortcuts, QtCore.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) 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'), 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_branches) self.create_tag_action = add_action(self, N_('Create Tag...'), create_tag) self.create_branch_action = add_action(self, N_('Create...'), 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.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...'), 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.revert_unstaged_edits_action) 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.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.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.addAction(self.new_repository_action) self.file_menu.addSeparator() self.file_menu.addAction(self.rescan_action) self.file_menu.addAction(self.edit_remotes_action) self.file_menu.addAction(self.browse_recently_modified_action) self.file_menu.addAction(self.manage_bookmarks_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.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(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) 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 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())
def action_callback(self): action = self.action if action == FETCH: model_action = self.model.fetch elif action == PUSH: model_action = self.push_to_all else: # if action == PULL: model_action = self.model.pull remote_name = ustr(self.remote_name.text()) if not remote_name: errmsg = N_('No repository selected.') Interaction.log(errmsg) return remote, kwargs = self.common_args() self.selected_remotes = qtutils.selected_items(self.remotes, self.model.remotes) # Check if we're about to create a new branch and warn. remote_branch = ustr(self.remote_branch.text()) local_branch = ustr(self.local_branch.text()) if action == PUSH and not remote_branch: branch = local_branch candidate = '%s/%s' % (remote, branch) if candidate not in self.model.remote_branches: title = N_('Push') args = dict(branch=branch, remote=remote) msg = N_( 'Branch "%(branch)s" does not exist in "%(remote)s".\n' 'A new remote branch will be published.') % args info_txt = N_('Create a new remote branch?') ok_text = N_('Create Remote Branch') if not qtutils.confirm( title, msg, info_txt, ok_text, icon=qtutils.git_icon()): return if not self.ffwd_only_checkbox.isChecked(): if action == FETCH: title = N_('Force Fetch?') msg = N_('Non-fast-forward fetch overwrites local history!') info_txt = N_('Force fetching from %s?') % remote ok_text = N_('Force Fetch') elif action == PUSH: title = N_('Force Push?') msg = N_('Non-fast-forward push overwrites published ' 'history!\n(Did you pull first?)') info_txt = N_('Force push to %s?') % remote ok_text = N_('Force Push') else: # pull: shouldn't happen since the controls are hidden msg = "You probably don't want to do this.\n\tContinue?" return if not qtutils.confirm(title, msg, info_txt, ok_text, default=False, icon=qtutils.discard_icon()): return # Disable the GUI by default self.action_button.setEnabled(False) self.close_button.setEnabled(False) # Use a thread to update in the background task = ActionTask(self.task_runner, model_action, remote, kwargs) self.task_runner.start(task, progress=self.progress, finish=self.action_completed)
def do(self): msg = 'Unstaging: %s' % (', '.join(self.paths)) Interaction.log(msg) self.model.unstage_paths(self.paths)
def __init__(self, model, parent=None, settings=None): 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 # Keeps track of merge messages we've seen self.merge_message_hash = '' # Runs asynchronous tasks self.task_runner = TaskRunner(self) self.progress = 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 = 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) self.statuswidget = StatusWidget(self.statusdockwidget.titleBarWidget(), parent=self.statusdockwidget) self.statusdockwidget.setWidget(self.statuswidget) # "Switch Repository" widgets self.bookmarksdockwidget = create_dock(N_('Bookmarks'), 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 = 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.diffeditorwidget = 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...'), 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.SHORTCUT) self.rescan_action.setIcon(qtutils.reload_icon()) self.browse_recently_modified_action = add_action(self, N_('Recently Modified Files...'), 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, '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, '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'), 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) 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'), 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_branches) self.create_tag_action = add_action(self, N_('Create Tag...'), create_tag) self.create_branch_action = add_action(self, N_('Create...'), 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.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...'), 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.revert_uncommitted_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.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.addAction(self.new_repository_action) self.file_menu.addSeparator() self.file_menu.addAction(self.rescan_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.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) 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 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())
def do(self): msg = N_('Untracking: %s') % (', '.join(self.paths)) Interaction.log(msg) status, out = self.model.untrack_paths(self.paths) Interaction.log_status(status, out, '')
def action_callback(self): action = self.action if action == FETCH: model_action = self.model.fetch elif action == PUSH: model_action = self.model.push else: # if action == PULL: model_action = self.model.pull remote_name = unicode(self.remote_name.text()) if not remote_name: errmsg = self.tr('No repository selected.') Interaction.log(errmsg) return remote, kwargs = self.common_args() # Check if we're about to create a new branch and warn. remote_branch = unicode(self.remote_branch.text()) local_branch = unicode(self.local_branch.text()) if action == PUSH and not remote_branch: branch = local_branch candidate = '%s/%s' % (remote, branch) if candidate not in self.model.remote_branches: title = self.tr(PUSH) msg = 'Branch "%s" does not exist in %s.' % (branch, remote) msg += '\nA new remote branch will be published.' info_txt = 'Create a new remote branch?' ok_text = 'Create Remote Branch' if not qtutils.confirm(title, msg, info_txt, ok_text, default=False, icon=qtutils.git_icon()): return if not self.ffwd_only_checkbox.isChecked(): title = 'Force %s?' % action.title() ok_text = 'Force %s' % action.title() if action == FETCH: msg = 'Non-fast-forward fetch overwrites local history!' info_txt = 'Force fetching from %s?' % remote elif action == PUSH: msg = ('Non-fast-forward push overwrites published ' 'history!\n(Did you pull first?)') info_txt = 'Force push to %s?' % remote else: # pull: shouldn't happen since the controls are hidden msg = "You probably don't want to do this.\n\tContinue?" return if not qtutils.confirm(title, msg, info_txt, ok_text, default=False, icon=qtutils.discard_icon()): return # Disable the GUI by default self.setEnabled(False) self.progress.setEnabled(True) QtGui.QApplication.setOverrideCursor(Qt.WaitCursor) # Show a nice progress bar self.progress_thread.start() self.progress.show() # Use a thread to update in the background task = ActionTask(self, model_action, remote, kwargs) self.tasks.append(task) QtCore.QThreadPool.globalInstance().start(task)
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() self.bookmarkswidget.connect_to(self.recentwidget) # "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.reset_branch_head_action = add_action(self, N_('Reset Branch Head'), guicmds.reset_branch_head) self.reset_worktree_action = add_action(self, N_('Reset Worktree'), guicmds.reset_worktree) 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_reset_menu = self.actions_menu.addMenu(N_('Reset')) self.actions_reset_menu.addAction(self.reset_branch_head_action) self.actions_reset_menu.addAction(self.reset_worktree_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())
def do(self): for env in ('FILENAME', 'REVISION', 'ARGS'): try: compat.unsetenv(env) except KeyError: pass rev = None args = None cfg = gitcfg.current() opts = cfg.get_guitool_opts(self.action_name) cmd = opts.get('cmd') if 'title' not in opts: opts['title'] = cmd if 'prompt' not in opts or opts.get('prompt') is True: prompt = N_('Run "%s"?') % cmd opts['prompt'] = prompt if opts.get('needsfile'): filename = selection.filename() if not filename: Interaction.information( N_('Please select a file'), N_('"%s" requires a selected file.') % cmd) return False compat.setenv('FILENAME', filename) if opts.get('revprompt') or opts.get('argprompt'): while True: ok = Interaction.confirm_config_action(cmd, opts) if not ok: return False rev = opts.get('revision') args = opts.get('args') if opts.get('revprompt') and not rev: title = N_('Invalid Revision') msg = N_('The revision expression cannot be empty.') Interaction.critical(title, msg) continue break elif opts.get('confirm'): title = os.path.expandvars(opts.get('title')) prompt = os.path.expandvars(opts.get('prompt')) if Interaction.question(title, prompt): return if rev: compat.setenv('REVISION', rev) if args: compat.setenv('ARGS', args) title = os.path.expandvars(cmd) Interaction.log(N_('Running command: %s') % title) cmd = ['sh', '-c', cmd] if opts.get('background'): core.fork(cmd) status, out, err = (0, '', '') elif opts.get('noconsole'): status, out, err = core.run_command(cmd) else: status, out, err = Interaction.run_command(title, cmd) Interaction.log_status(status, out and (N_('Output: %s') % out) or '', err and (N_('Errors: %s') % err) or '') if not opts.get('background') and not opts.get('norescan'): self.model.update_status() return status
def do(self): msg = N_('Unstaging: %s') % (', '.join(self.paths)) Interaction.log(msg) self.model.unstage_paths(self.paths)
def _send_msg(): if git.GIT_COLA_TRACE == 'trace': msg = 'info: debug mode enabled using GIT_COLA_TRACE=trace' Interaction.log(msg)
def do(self): msg = 'Staging: %s' % (', '.join(self.paths)) Interaction.log(msg) self.model.stage_paths(self.paths)
def _send_msg(): if git.GIT_COLA_TRACE == "trace": msg = "info: debug mode enabled using GIT_COLA_TRACE=trace" Interaction.log(msg)
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_view) 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())