Exemplo n.º 1
0
    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
Exemplo n.º 2
0
    def get_body(self, vbox):
        rev0, rev1 = self.revs
        prevs = [ctx.rev() for ctx in self.repo.parents()]
        if len(prevs) > 1:
            rev0, rev1 = prevs
        elif (not rev1 and rev1 != 0):
            gdialog.Prompt(_('Unable to merge'),
                           _('Must supply a target revision'), self).run()
            gtklib.idle_add_single_call(self.hide)
            return False
        elif (not rev0 and rev0 != 0):
            rev0 = prevs[0]
        elif rev1 == prevs[0]:
            # selected pair was backwards
            rev0, rev1 = rev1, rev0
        elif rev0 != prevs[0]:
            # working parent not in selected revision pair
            modified, added, removed, deleted = self.repo.status()[:4]
            if modified or added or removed or deleted:
                gdialog.Prompt(_('Unable to merge'),
                               _('Outstanding uncommitted changes'), self).run()
                gtklib.idle_add_single_call(self.hide)
                return False
            self.repo.ui.quiet = True
            commands.update(self.repo.ui, self.repo, rev=str(rev0), check=True)
            self.repo.ui.quiet = False

        # changeset info
        style = csinfo.panelstyle(contents=csinfo.PANEL_DEFAULT + ('ishead',),
                                  margin=5, padding=2)
        def markup_func(widget, item, value):
            if item == 'ishead' and value is False:
                text = _('Not a head revision!')
                return gtklib.markup(text, weight='bold')
            raise csinfo.UnknownItem(item)
        custom = csinfo.custom(markup=markup_func)
        factory = csinfo.factory(self.repo, custom, style, withupdate=True)

        info = factory(rev1, style={'label': _('Merge target (other)')})
        self.vbox.pack_start(info, False, False)
        self.otherframe = info
        self.otherrev = str(info.get_data('revnum'))

        info = factory(rev0, style={'label': _('Current revision (local)')})
        self.vbox.pack_start(info, False, False)
        self.localframe = info
        self.localrev = str(info.get_data('revnum'))

        # expander for advanced options
        expander = gtk.Expander(_('Advanced options'))
        self.vbox.pack_start(expander, False, False)

        # layout table for advanced options
        table = gtklib.LayoutTable()
        expander.add(table)
        
        vlist = gtk.ListStore(str,  # tool name
                              bool) # separator
        combo = gtk.ComboBoxEntry(vlist, 0)
        self.mergetool = combo
        combo.set_row_separator_func(lambda model, path: model[path][1])
        combo.child.set_width_chars(16)
        chtool = gtk.RadioButton(None, _('Use merge tool:'))
        self.mergelabel = chtool
        table.add_row(chtool, combo)
        prev = False
        for tool in hglib.mergetools(self.repo.ui):
            cur = tool.startswith('internal:')
            vlist.append((hglib.toutf(tool), prev != cur))
            prev = cur
        mtool = self.repo.ui.config('ui', 'merge', None)
        if mtool:
            combo.child.set_text(hglib.toutf(mtool))
        else:
            combo.child.set_text('')

        discard = gtk.RadioButton(chtool,
            _('Discard all changes from merge target (other) revision'))
        self.discard = discard
        table.add_row(discard)

        # prepare to show
        if len(self.repo.parents()) == 2:
            self.mergetool.set_sensitive(False)
            self.mergelabel.set_sensitive(False)
            self.discard.set_sensitive(False)
            self.buttons['merge'].set_sensitive(False)
            self.buttons['commit'].set_sensitive(True)
            self.buttons['undo'].set_sensitive(True)
        else:
            self.buttons['commit'].set_sensitive(False)
            self.buttons['undo'].set_sensitive(False)