def get_accelgroup(self): accelgroup = gtk.AccelGroup() mod = gtklib.get_thg_modifier() gtklib.add_accelerator(self.filetree, 'thg-diff', accelgroup, mod+'d') self.filetree.connect('thg-diff', self.thgdiff) self.connect('thg-refresh', self.thgrefresh) # set CTRL-c accelerator for copy-clipboard gtklib.add_accelerator(self.chunks.difftree(), 'copy-clipboard', accelgroup, mod+'c') def scroll_diff_notebook(widget, direction=gtk.SCROLL_PAGE_DOWN): page_num = self.diff_notebook.get_current_page() page = self.diff_notebook.get_nth_page(page_num) page.emit("scroll-child", direction, False) def toggle_filetree_selection(*arguments): self.sel_clicked(not self.selcb.get_active()) def next_diff_notebook_page(*arguments): notebook = self.diff_notebook if notebook.get_current_page() >= len(notebook) - 1: notebook.set_current_page(0) else: notebook.next_page() def previous_diff_notebook_page(*arguments): notebook = self.diff_notebook if notebook.get_current_page() <= 0: notebook.set_current_page(len(notebook) - 1) else: notebook.prev_page() # signal, accelerator key, handler, (parameters) status_accelerators = [ ('status-scroll-down', 'bracketright', scroll_diff_notebook, (gtk.SCROLL_PAGE_DOWN,)), ('status-scroll-up', 'bracketleft', scroll_diff_notebook, (gtk.SCROLL_PAGE_UP,)), ('status-next-file', 'period', gtklib.move_treeview_selection, (self.filetree, 1)), ('status-previous-file', 'comma', gtklib.move_treeview_selection, (self.filetree, -1)), ('status-select-all', 'u', toggle_filetree_selection, ()), ('status-next-page', 'p', next_diff_notebook_page, ()), ('status-previous-page', '<Shift>p', previous_diff_notebook_page, ()), ] for signal, accelerator, handler, parameters in status_accelerators: gtklib.add_accelerator(self, signal, accelgroup, mod + accelerator) self.connect(signal, handler, *parameters) return accelgroup
def get_body(self): embedded = bool(self.stbar) use_expander = embedded and self.ui.configbool( 'tortoisehg', 'changeset-expander') self.curfile = '' if self.repo.ui.configbool('tortoisehg', 'copyhash'): sel = (os.name == 'nt') and 'CLIPBOARD' or 'PRIMARY' self.clipboard = gtk.Clipboard(selection=sel) else: self.clipboard = None self.filemenu = self.file_context_menu() details_frame_parent = gtk.VBox() # changeset frame details_frame = gtk.Frame() details_frame.set_shadow_type(gtk.SHADOW_ETCHED_IN) scroller = gtk.ScrolledWindow() scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) details_frame.add(scroller) self.diffscroller = scroller details_box = gtk.VBox() scroller.add_with_viewport(details_box) scroller.child.set_shadow_type(gtk.SHADOW_NONE) ## changeset panel def revid_markup(revid, **kargs): opts = dict(face='monospace', size='9000') opts.update(kargs) return gtklib.markup(revid, **opts) def data_func(widget, item, ctx): def summary_line(desc): desc = hglib.tounicode(desc.replace('\0', '').split('\n')[0]) return hglib.toutf(desc[:80]) def revline_data(ctx, hl=False, branch=None): if isinstance(ctx, basestring): return ctx desc = ctx.description() return (str(ctx.rev()), str(ctx), summary_line(desc), hl, branch) if item == 'cset': return revline_data(ctx) elif item == 'branch': value = hglib.toutf(ctx.branch()) return value != 'default' and value or None elif item == 'parents': pindex = self.diff_other_parent() and 1 or 0 pctxs = ctx.parents() parents = [] for pctx in pctxs: highlight = len(pctxs) == 2 and pctx == pctxs[pindex] branch = None if hasattr(pctx, 'branch') and pctx.branch() != ctx.branch(): branch = pctx.branch() parents.append(revline_data(pctx, highlight, branch)) return parents elif item == 'children': children = [] for cctx in ctx.children(): branch = None if hasattr(cctx, 'branch') and cctx.branch() != ctx.branch(): branch = cctx.branch() children.append(revline_data(cctx, branch=branch)) return children elif item in ('transplant', 'p4', 'svn'): ts = widget.get_data(item, usepreset=True) if not ts: return None try: tctx = self.repo[ts] return revline_data(tctx) except (error.LookupError, error.RepoLookupError, error.RepoError): return ts elif item == 'patch': if hasattr(ctx, '_patchname'): desc = ctx.description() return (ctx._patchname, str(ctx), summary_line(desc)) return None raise csinfo.UnknownItem(item) def label_func(widget, item): if item == 'cset': return _('Changeset:') elif item == 'parents': return _('Parent:') elif item == 'children': return _('Child:') elif item == 'patch': return _('Patch:') raise csinfo.UnknownItem(item) def markup_func(widget, item, value): def revline_markup(revnum, revid, summary, highlight=None, branch=None): revnum = gtklib.markup(revnum) summary = gtklib.markup(summary) if revid: revid = revid_markup(revid) if branch: return '%s (%s) %s %s' % (revnum, revid, branch, summary) return '%s (%s) %s' % (revnum, revid, summary) else: if branch: return '%s - %s %s' % (revnum, branch, summary) return '%s - %s' % (revnum, summary) if item in ('cset', 'transplant', 'patch', 'p4', 'svn'): if isinstance(value, basestring): return revid_markup(value) return revline_markup(*value) elif item in ('parents', 'children'): csets = [] for cset in value: if isinstance(cset, basestring): csets.append(revid_markup(cset)) else: csets.append(revline_markup(*cset)) return csets raise csinfo.UnknownItem(item) def widget_func(widget, item, markups): def linkwidget(revnum, revid, summary, highlight=None, branch=None): # revision label opts = dict(underline='single', color=gtklib.BLUE) if highlight: opts['weight'] = 'bold' rev = '%s (%s)' % (gtklib.markup(revnum, **opts), revid_markup(revid, **opts)) revlabel = gtk.Label() revlabel.set_markup(rev) revlabel.set_selectable(True) revlabel.connect('button-release-event', self.link_event, revnum) # summary & branch label sum = gtklib.markup(summary) if branch: sum = gtklib.markup(branch, color=gtklib.NORMAL, background=gtklib.PGREEN) + ' ' + sum sumlabel = gtk.Label() sumlabel.set_markup(sum) sumlabel.set_selectable(True) box = gtk.HBox() box.pack_start(revlabel, False, False) box.pack_start(sumlabel, True, True, 4) return box def genwidget(param): if isinstance(param, basestring): label = gtk.Label() label.set_markup(param) label.set_selectable(True) return label return linkwidget(*param) if item in ('parents', 'children'): csets = widget.get_data(item) return [genwidget(cset) for cset in csets] elif item == 'transplant': cset = widget.get_data(item) return genwidget(cset) raise csinfo.UnknownItem(item) custom = csinfo.custom(data=data_func, label=label_func, markup=markup_func, widget=widget_func) self.csetstyle = csinfo.panelstyle(contents=('cset', 'branch', 'user', 'dateage', 'parents', 'children', 'tags', 'transplant', 'p4', 'svn'), selectable=True) self.patchstyle = csinfo.panelstyle(contents=('patch', 'branch', 'user', 'dateage', 'parents'), selectable=True) if use_expander: self.csetstyle['expander'] = True self.patchstyle['expander'] = True self.summarypanel = csinfo.create(self.repo, custom=custom) ## summary box (summarypanel + separator) self.summarybox = gtk.VBox() if use_expander: # don't scroll summarybox details_frame_parent.pack_start(self.summarybox, False, False) else: # scroll summarybox details_box.pack_start(self.summarybox, False, False) self.summarybox.pack_start(self.summarypanel, False, False) self.summarybox.pack_start(gtk.HSeparator(), False, False) ## changeset diff details_text = gtk.TextView() details_text.set_wrap_mode(gtk.WRAP_NONE) details_text.connect('populate-popup', self.add_to_popup) details_text.set_editable(False) details_text.modify_font(self.fonts['comment']) details_box.pack_start(details_text) self._buffer = gtk.TextBuffer() self.setup_tags() details_text.set_buffer(self._buffer) self.textview = details_text ## file list filelist_tree = gtk.TreeView() filelist_tree.set_headers_visible(False) filesel = filelist_tree.get_selection() filesel.connect('changed', self.filelist_rowchanged) self._filesel = filesel filelist_tree.connect('button-release-event', self.file_button_release) filelist_tree.connect('popup-menu', self.file_popup_menu) filelist_tree.connect('row-activated', self.file_row_act) filelist_tree.set_search_equal_func(self.search_filelist) filelist_tree.modify_font(self.fonts['list']) self._filelist_tree = filelist_tree accelgroup = gtk.AccelGroup() if self.glog_parent: self.glog_parent.add_accel_group(accelgroup) else: self.add_accel_group(accelgroup) mod = gtklib.get_thg_modifier() key, modifier = gtk.accelerator_parse(mod+'d') filelist_tree.add_accelerator('thg-diff', accelgroup, key, modifier, gtk.ACCEL_VISIBLE) filelist_tree.connect('thg-diff', self.thgdiff) def scroll_details(widget, direction=gtk.SCROLL_PAGE_DOWN): self.diffscroller.emit("scroll-child", direction, False) # signal, accelerator key, handler, (parameters,) status_accelerators = [ ('status-scroll-down', 'bracketright', scroll_details, (gtk.SCROLL_PAGE_DOWN,)), ('status-scroll-up', 'bracketleft', scroll_details, (gtk.SCROLL_PAGE_UP,)), ('status-next-file', 'period', gtklib.move_treeview_selection, (filelist_tree, 1)), ('status-previous-file', 'comma', gtklib.move_treeview_selection, (filelist_tree, -1)), ] for signal, accelerator, handler, param in status_accelerators: root = self.glog_parent or self gtklib.add_accelerator(root, signal, accelgroup, mod + accelerator) root.connect(signal, handler, *param) self._filelist = gtk.ListStore( gobject.TYPE_STRING, # MAR status gobject.TYPE_STRING, # filename (utf-8 encoded) gobject.TYPE_STRING, # filename ) filelist_tree.set_model(self._filelist) column = gtk.TreeViewColumn() filelist_tree.append_column(column) iconcell = gtk.CellRendererPixbuf() filecell = gtk.CellRendererText() column.pack_start(iconcell, expand=False) column.pack_start(filecell, expand=False) column.add_attribute(filecell, 'text', 1) size = gtk.ICON_SIZE_SMALL_TOOLBAR addedpixbuf = gtklib.get_icon_pixbuf('fileadd.ico', size) removedpixbuf = gtklib.get_icon_pixbuf('filedelete.ico', size) modifiedpixbuf = gtklib.get_icon_pixbuf('filemodify.ico', size) def cell_seticon(column, cell, model, iter): state = model.get_value(iter, 0) pixbuf = None if state == 'A': pixbuf = addedpixbuf elif state == 'R': pixbuf = removedpixbuf elif state == 'M': pixbuf = modifiedpixbuf cell.set_property('pixbuf', pixbuf) column.set_cell_data_func(iconcell, cell_seticon) list_frame = gtk.Frame() list_frame.set_shadow_type(gtk.SHADOW_ETCHED_IN) scroller = gtk.ScrolledWindow() scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroller.add(filelist_tree) flbox = gtk.VBox() list_frame.add(flbox) self.parent_box = gtk.VBox() flbox.pack_start(self.parent_box, False, False) flbox.pack_start(scroller) btn = gtk.CheckButton(_('Diff to second Parent')) btn.connect('toggled', self.parent_toggled) # don't pack btn yet to keep it initially invisible self.parent_button = btn self._hpaned = gtk.HPaned() self._hpaned.pack1(list_frame, True, True) self._hpaned.pack2(details_frame_parent, True, True) self._hpaned.set_position(self._setting_hpos) details_frame_parent.pack_start(details_frame, True, True) if embedded: # embedded by changelog browser return self._hpaned else: # add status bar for main app vbox = gtk.VBox() vbox.pack_start(self._hpaned, True, True) self.stbar = statusbar.StatusBar() self.stbar.show() vbox.pack_start(gtk.HSeparator(), False, False) vbox.pack_start(self.stbar, False, False) return vbox