/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to viz/branchwin.py

  • Committer: Jelmer Vernooij
  • Date: 2007-10-26 17:02:18 UTC
  • Revision ID: jelmer@samba.org-20071026170218-pepec3wazqr3ghhb
Add very simple "Send Merge Directive" window.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
1
# -*- coding: UTF-8 -*-
3
2
"""Branch window.
4
3
 
10
9
__author__    = "Scott James Remnant <scott@ubuntu.com>"
11
10
 
12
11
 
13
 
import os
14
 
 
15
12
import gtk
16
13
import gobject
17
14
import pango
 
15
import treemodel
18
16
 
 
17
from bzrlib.plugins.gtk.window import Window
19
18
from bzrlib.osutils import format_date
20
19
 
21
 
from graph import graph
 
20
from linegraph import linegraph, same_branch
22
21
from graphcell import CellRendererGraph
23
 
 
24
 
 
25
 
class BranchWindow(gtk.Window):
 
22
from treemodel import TreeModel
 
23
from treeview  import TreeView
 
24
 
 
25
class BranchWindow(Window):
26
26
    """Branch window.
27
27
 
28
28
    This object represents and manages a single window containing information
29
29
    for a particular branch.
30
30
    """
31
31
 
32
 
    def __init__(self):
33
 
        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
 
32
    def __init__(self, branch, start, maxnum, parent=None):
 
33
        """Create a new BranchWindow.
 
34
 
 
35
        :param branch: Branch object for branch to show.
 
36
        :param start: Revision id of top revision.
 
37
        :param maxnum: Maximum number of revisions to display, 
 
38
                       None for no limit.
 
39
        """
 
40
 
 
41
        Window.__init__(self, parent=parent)
34
42
        self.set_border_width(0)
35
 
        self.set_title("bzrk")
 
43
 
 
44
        self.branch = branch
 
45
        self.start  = start
 
46
        self.maxnum = maxnum
 
47
 
 
48
        self.set_title(branch.nick + " - revision history")
36
49
 
37
50
        # Use three-quarters of the screen by default
38
51
        screen = self.get_screen()
39
 
        width = int(screen.get_width() * 0.75)
40
 
        height = int(screen.get_height() * 0.75)
 
52
        monitor = screen.get_monitor_geometry(0)
 
53
        width = int(monitor.width * 0.75)
 
54
        height = int(monitor.height * 0.75)
41
55
        self.set_default_size(width, height)
42
56
 
43
57
        # FIXME AndyFitz!
44
58
        icon = self.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
45
59
        self.set_icon(icon)
46
60
 
 
61
        self.accel_group = gtk.AccelGroup()
 
62
        self.add_accel_group(self.accel_group)
 
63
 
47
64
        self.construct()
48
65
 
49
66
    def construct(self):
50
67
        """Construct the window contents."""
51
 
        scrollwin = gtk.ScrolledWindow()
52
 
        scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
53
 
        scrollwin.set_shadow_type(gtk.SHADOW_IN)
54
 
        scrollwin.set_border_width(12)
55
 
        self.add(scrollwin)
56
 
        scrollwin.show()
57
 
 
58
 
        self.treeview = gtk.TreeView()
59
 
        self.treeview.set_rules_hint(True)
60
 
        self.treeview.set_search_column(4)
61
 
        scrollwin.add(self.treeview)
 
68
        vbox = gtk.VBox(spacing=0)
 
69
        self.add(vbox)
 
70
 
 
71
        vbox.pack_start(self.construct_navigation(), expand=False, fill=True)
 
72
        vbox.pack_start(self.construct_loading_msg(), expand=False, fill=True)
 
73
        
 
74
        paned = gtk.VPaned()
 
75
        paned.pack1(self.construct_top(), resize=True, shrink=False)
 
76
        paned.pack2(self.construct_bottom(), resize=False, shrink=True)
 
77
        paned.show()
 
78
        vbox.pack_start(paned, expand=True, fill=True)
 
79
        vbox.set_focus_child(paned)
 
80
 
 
81
        vbox.show()
 
82
    
 
83
    def construct_loading_msg(self):
 
84
        image_loading = gtk.image_new_from_stock(gtk.STOCK_REFRESH,
 
85
                                                 gtk.ICON_SIZE_BUTTON)
 
86
        image_loading.show()
 
87
        
 
88
        label_loading = gtk.Label(_("Please wait, loading ancestral graph..."))
 
89
        label_loading.set_alignment(0.0, 0.5)        
 
90
        label_loading.show()
 
91
        
 
92
        self.loading_msg_box = gtk.HBox()
 
93
        self.loading_msg_box.set_spacing(5)
 
94
        self.loading_msg_box.set_border_width(5)        
 
95
        self.loading_msg_box.pack_start(image_loading, False, False)
 
96
        self.loading_msg_box.pack_start(label_loading, True, True)
 
97
        self.loading_msg_box.show()
 
98
        
 
99
        return self.loading_msg_box
 
100
 
 
101
    def construct_top(self):
 
102
        """Construct the top-half of the window."""
 
103
        self.treeview = TreeView(self.branch, self.start, self.maxnum)
 
104
 
 
105
        self.treeview.connect("revision-selected",
 
106
                self._treeselection_changed_cb)
 
107
 
 
108
        self.treeview.connect('revisions-loaded', 
 
109
                lambda x: self.loading_msg_box.hide())
 
110
 
62
111
        self.treeview.show()
63
112
 
64
 
        cell = CellRendererGraph()
65
 
        column = gtk.TreeViewColumn()
66
 
        column.set_resizable(False)
67
 
        column.pack_start(cell, expand=False)
68
 
        column.add_attribute(cell, "node", 1)
69
 
        column.add_attribute(cell, "in-lines", 2)
70
 
        column.add_attribute(cell, "out-lines", 3)
71
 
        self.treeview.append_column(column)
72
 
 
73
 
        cell = gtk.CellRendererText()
74
 
        cell.set_property("width-chars", 40)
75
 
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
76
 
        column = gtk.TreeViewColumn("Message")
77
 
        column.set_resizable(True)
78
 
        column.pack_start(cell, expand=True)
79
 
        column.add_attribute(cell, "text", 4)
80
 
        self.treeview.append_column(column)
81
 
 
82
 
        cell = gtk.CellRendererText()
83
 
        cell.set_property("width-chars", 40)
84
 
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
85
 
        column = gtk.TreeViewColumn("Committer")
86
 
        column.set_resizable(True)
87
 
        column.pack_start(cell, expand=True)
88
 
        column.add_attribute(cell, "text", 5)
89
 
        self.treeview.append_column(column)
90
 
 
91
 
        cell = gtk.CellRendererText()
92
 
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
93
 
        column = gtk.TreeViewColumn("Date")
94
 
        column.set_resizable(True)
95
 
        column.pack_start(cell, expand=True)
96
 
        column.add_attribute(cell, "text", 6)
97
 
        self.treeview.append_column(column)
98
 
 
99
 
    def set_branch(self, branch, start):
100
 
        """Set the branch and start position for this window.
101
 
 
102
 
        Creates a new TreeModel and populates it with information about
103
 
        the new branch before updating the window title and model of the
104
 
        treeview itself.
105
 
        """
106
 
        # [ revision, node, last_lines, lines, message, committer, timestamp ]
107
 
        model = gtk.ListStore(gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
108
 
                              gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
109
 
                              str, str, str)
110
 
 
111
 
        last_lines = []
112
 
        for revision, node, lines in graph(branch, start):
113
 
            message = revision.message.split("\n")[0]
114
 
            if revision.committer is not None:
115
 
                timestamp = format_date(revision.timestamp, revision.timezone)
116
 
            else:
117
 
                timestamp = None
118
 
 
119
 
            model.append([ revision, node, last_lines, lines,
120
 
                           message, revision.committer, timestamp ])
121
 
            last_lines = lines
122
 
 
123
 
        self.set_title(os.path.basename(branch.base) + " - bzrk")
124
 
        self.treeview.set_model(model)
 
113
        return self.treeview
 
114
 
 
115
    def construct_navigation(self):
 
116
        """Construct the navigation buttons."""
 
117
        frame = gtk.Frame()
 
118
        frame.set_shadow_type(gtk.SHADOW_OUT)
 
119
        frame.show()
 
120
        
 
121
        hbox = gtk.HBox(spacing=12)
 
122
        frame.add(hbox)
 
123
        hbox.show()
 
124
 
 
125
        self.back_button = gtk.Button(stock=gtk.STOCK_GO_BACK)
 
126
        self.back_button.set_relief(gtk.RELIEF_NONE)
 
127
        self.back_button.add_accelerator("clicked", self.accel_group, ord('['),
 
128
                                         0, 0)
 
129
        self.back_button.connect("clicked", self._back_clicked_cb)
 
130
        hbox.pack_start(self.back_button, expand=False, fill=True)
 
131
        self.back_button.show()
 
132
 
 
133
        self.fwd_button = gtk.Button(stock=gtk.STOCK_GO_FORWARD)
 
134
        self.fwd_button.set_relief(gtk.RELIEF_NONE)
 
135
        self.fwd_button.add_accelerator("clicked", self.accel_group, ord(']'),
 
136
                                        0, 0)
 
137
        self.fwd_button.connect("clicked", self._fwd_clicked_cb)
 
138
        hbox.pack_start(self.fwd_button, expand=False, fill=True)
 
139
        self.fwd_button.show()
 
140
 
 
141
        return frame
 
142
 
 
143
    def construct_bottom(self):
 
144
        """Construct the bottom half of the window."""
 
145
        from bzrlib.plugins.gtk.logview import LogView
 
146
        self.logview = LogView(None, True, [], True)
 
147
        (width, height) = self.get_size()
 
148
        self.logview.set_size_request(width, int(height / 2.5))
 
149
        self.logview.show()
 
150
        self.logview.set_show_callback(self._show_clicked_cb)
 
151
        self.logview.set_go_callback(self._go_clicked_cb)
 
152
        return self.logview
 
153
    
 
154
    def _treeselection_changed_cb(self, selection, *args):
 
155
        """callback for when the treeview changes."""
 
156
        revision = self.treeview.get_revision()
 
157
        parents  = self.treeview.get_parents()
 
158
        children = self.treeview.get_children()
 
159
 
 
160
        if revision is not None:
 
161
            self.back_button.set_sensitive(len(parents) > 0)
 
162
            self.fwd_button.set_sensitive(len(children) > 0)
 
163
            tags = []
 
164
            if self.branch.supports_tags():
 
165
                tagdict = self.branch.tags.get_reverse_tag_dict()
 
166
                if tagdict.has_key(revision.revision_id):
 
167
                    tags = tagdict[revision.revision_id]
 
168
            self.logview.set_revision(revision, tags, children)
 
169
 
 
170
    def _back_clicked_cb(self, *args):
 
171
        """Callback for when the back button is clicked."""
 
172
        self.treeview.back()
 
173
        
 
174
    def _fwd_clicked_cb(self, *args):
 
175
        """Callback for when the forward button is clicked."""
 
176
        self.treeview.forward()
 
177
 
 
178
    def _go_clicked_cb(self, revid):
 
179
        """Callback for when the go button for a parent is clicked."""
 
180
        self.treeview.set_revision(revid)
 
181
 
 
182
    def _show_clicked_cb(self, revid, parentid):
 
183
        """Callback for when the show button for a parent is clicked."""
 
184
        self.treeview.show_diff(self.branch, revid, parentid)
 
185
        self.treeview.grab_focus()
 
186