/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 branchview/treeview.py

  • Committer: Jelmer Vernooij
  • Date: 2008-06-29 15:47:30 UTC
  • mto: This revision was merged to the branch mainline in revision 519.
  • Revision ID: jelmer@samba.org-20080629154730-xfsotoxwkiytf0ph
Pass graph object rather than full repository to linegraph.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
__copyright__ = "Copyright © 2005 Canonical Ltd."
7
7
__author__    = "Daniel Schierbeck <daniel.schierbeck@gmail.com>"
8
8
 
 
9
import sys
 
10
import string
9
11
import gtk
10
12
import gobject
11
13
import pango
 
14
import re
12
15
import treemodel
13
 
from bzrlib import ui
14
16
 
15
 
from bzrlib.plugins.gtk.ui import ProgressPanel
 
17
from bzrlib.plugins.gtk import _i18n
16
18
from linegraph import linegraph, same_branch
17
19
from graphcell import CellRendererGraph
18
20
from treemodel import TreeModel
19
21
from bzrlib.revision import NULL_REVISION
20
 
from bzrlib.plugins.gtk import lock
21
 
 
22
22
 
23
23
class TreeView(gtk.VBox):
24
24
 
82
82
    }
83
83
 
84
84
    __gsignals__ = {
 
85
        'revisions-loaded': (gobject.SIGNAL_RUN_FIRST, 
 
86
                             gobject.TYPE_NONE,
 
87
                             ()),
85
88
        'revision-selected': (gobject.SIGNAL_RUN_FIRST,
86
89
                              gobject.TYPE_NONE,
87
90
                              ()),
90
93
                              (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)),
91
94
        'tag-added': (gobject.SIGNAL_RUN_FIRST,
92
95
                              gobject.TYPE_NONE,
93
 
                              (gobject.TYPE_STRING, gobject.TYPE_STRING)),
94
 
        'refreshed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
95
 
                              ())
 
96
                              (gobject.TYPE_STRING, gobject.TYPE_STRING))
96
97
    }
97
98
 
98
99
    def __init__(self, branch, start, maxnum, compact=True):
107
108
        """
108
109
        gtk.VBox.__init__(self, spacing=0)
109
110
 
110
 
        self.progress_widget = ProgressPanel()
111
 
        self.pack_start(self.progress_widget, expand=False, fill=True)
112
 
        if getattr(ui.ui_factory, "set_progress_bar_widget", None) is not None:
113
 
            # We'are using our own ui, let's tell it to use our widget.
114
 
            ui.ui_factory.set_progress_bar_widget(self.progress_widget)
 
111
        self.pack_start(self.construct_loading_msg(), expand=False, fill=True)
 
112
        self.connect('revisions-loaded', 
 
113
                lambda x: self.loading_msg_box.hide())
115
114
 
116
115
        self.scrolled_window = gtk.ScrolledWindow()
117
116
        self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
121
120
        self.pack_start(self.scrolled_window, expand=True, fill=True)
122
121
 
123
122
        self.scrolled_window.add(self.construct_treeview())
 
123
        
124
124
 
125
 
        self.path = None
 
125
        self.iter = None
126
126
        self.branch = branch
127
127
        self.revision = None
128
 
        self.index = {}
129
128
 
130
129
        self.start = start
131
130
        self.maxnum = maxnum
133
132
 
134
133
        gobject.idle_add(self.populate)
135
134
 
136
 
        self.connect("destroy", self._on_destroy)
137
 
 
138
 
    def _on_destroy(self, *ignored):
139
 
        self.branch.unlock()
140
 
        if getattr(ui.ui_factory, "set_progress_bar_widget", None) is not None:
141
 
            # We'are using our own ui, let's tell it to stop using our widget.
142
 
            ui.ui_factory.set_progress_bar_widget(None)
 
135
        self.connect("destroy", lambda x: self.branch.unlock())
143
136
 
144
137
    def do_get_property(self, property):
145
138
        if property.name == 'revno-column-visible':
155
148
        elif property.name == 'branch':
156
149
            return self.branch
157
150
        elif property.name == 'revision':
158
 
            return self.model.get_value(self.model.get_iter(self.path),
159
 
                                        treemodel.REVISION)
 
151
            return self.model.get_value(self.iter, treemodel.REVISION)
160
152
        elif property.name == 'revision-number':
161
 
            return self.model.get_value(self.model.get_iter(self.path),
162
 
                                        treemodel.REVNO)
 
153
            return self.model.get_value(self.iter, treemodel.REVNO)
163
154
        elif property.name == 'children':
164
 
            return self.model.get_value(self.model.get_iter(self.path),
165
 
                                        treemodel.CHILDREN)
 
155
            return self.model.get_value(self.iter, treemodel.CHILDREN)
166
156
        elif property.name == 'parents':
167
 
            return self.model.get_value(self.model.get_iter(self.path),
168
 
                                        treemodel.PARENTS)
 
157
            return self.model.get_value(self.iter, treemodel.PARENTS)
169
158
        else:
170
159
            raise AttributeError, 'unknown property %s' % property.name
171
160
 
191
180
        """Return revision id of currently selected revision, or None."""
192
181
        return self.get_property('revision')
193
182
 
194
 
    def has_revision_id(self, revision_id):
195
 
        return (revision_id in self.index)
196
 
 
197
183
    def set_revision(self, revision):
198
184
        self.set_property('revision', revision)
199
185
 
222
208
    def add_tag(self, tag, revid=None):
223
209
        if revid is None: revid = self.revision.revision_id
224
210
 
225
 
        if lock.release(self.branch):
 
211
        try:
 
212
            self.branch.unlock()
 
213
 
226
214
            try:
227
 
                lock.acquire(self.branch, lock.WRITE)
 
215
                self.branch.lock_write()
228
216
                self.model.add_tag(tag, revid)
229
217
            finally:
230
 
                lock.release(self.branch)
231
 
 
232
 
            lock.acquire(self.branch, lock.READ)
233
 
 
234
 
            self.emit('tag-added', tag, revid)
 
218
                self.branch.unlock()
 
219
 
 
220
        finally:
 
221
            self.branch.lock_read()
 
222
 
 
223
        self.emit('tag-added', tag, revid)
235
224
        
236
225
    def refresh(self):
 
226
        self.loading_msg_box.show()
237
227
        gobject.idle_add(self.populate, self.get_revision())
238
228
 
239
229
    def update(self):
287
277
                       should be broken.
288
278
        """
289
279
 
290
 
        if getattr(ui.ui_factory, "set_progress_bar_widget", None) is not None:
291
 
            # We'are using our own ui, let's tell it to use our widget.
292
 
            ui.ui_factory.set_progress_bar_widget(self.progress_widget)
293
 
        self.progress_bar = ui.ui_factory.nested_progress_bar()
294
 
        self.progress_bar.update("Loading ancestry graph", 0, 5)
295
 
 
296
 
        try:
297
 
            if self.compact:
298
 
                broken_line_length = 32
299
 
            else:
300
 
                broken_line_length = None
301
 
            
302
 
            show_graph = self.graph_column.get_visible()
303
 
 
304
 
            self.branch.lock_read()
305
 
            (linegraphdata, index, columns_len) = linegraph(self.branch.repository.get_graph(),
306
 
                                                            self.start,
307
 
                                                            self.maxnum, 
308
 
                                                            broken_line_length,
309
 
                                                            show_graph,
310
 
                                                            self.mainline_only,
311
 
                                                            self.progress_bar)
312
 
 
313
 
            self.model = TreeModel(self.branch, linegraphdata)
314
 
            self.graph_cell.columns_len = columns_len
315
 
            width = self.graph_cell.get_size(self.treeview)[2]
316
 
            if width > 500:
317
 
                width = 500
318
 
            self.graph_column.set_fixed_width(width)
319
 
            self.graph_column.set_max_width(width)
320
 
            self.index = index
321
 
            self.treeview.set_model(self.model)
322
 
 
323
 
            if not revision or revision == NULL_REVISION:
324
 
                self.treeview.set_cursor(0)
325
 
            else:
326
 
                self.set_revision(revision)
327
 
 
328
 
            self.emit('refreshed')
329
 
            return False
330
 
        finally:
331
 
            self.progress_bar.finished()
 
280
        if self.compact:
 
281
            broken_line_length = 32
 
282
        else:
 
283
            broken_line_length = None
 
284
        
 
285
        show_graph = self.graph_column.get_visible()
 
286
 
 
287
        self.branch.lock_read()
 
288
        (linegraphdata, index, columns_len) = linegraph(self.branch.repository.get_graph(),
 
289
                                                        (self.start,) , # Sequence of start revisions
 
290
                                                        self.maxnum, 
 
291
                                                        broken_line_length,
 
292
                                                        show_graph,
 
293
                                                        self.mainline_only)
 
294
 
 
295
        self.model = TreeModel(self.branch, linegraphdata)
 
296
        self.graph_cell.columns_len = columns_len
 
297
        width = self.graph_cell.get_size(self.treeview)[2]
 
298
        if width > 500:
 
299
            width = 500
 
300
        self.graph_column.set_fixed_width(width)
 
301
        self.graph_column.set_max_width(width)
 
302
        self.index = index
 
303
        self.treeview.set_model(self.model)
 
304
 
 
305
        if not revision or revision == NULL_REVISION:
 
306
            self.treeview.set_cursor(0)
 
307
        else:
 
308
            self.set_revision(revision)
 
309
 
 
310
        self.emit('revisions-loaded')
 
311
 
 
312
        return False
332
313
 
333
314
    def construct_treeview(self):
334
315
        self.treeview = gtk.TreeView()
341
322
        if set_tooltip is not None:
342
323
            set_tooltip(treemodel.MESSAGE)
343
324
 
344
 
        self._prev_cursor_path = None
345
325
        self.treeview.connect("cursor-changed",
346
326
                self._on_selection_changed)
347
327
 
392
372
        cell = gtk.CellRendererText()
393
373
        cell.set_property("width-chars", 15)
394
374
        cell.set_property("ellipsize", pango.ELLIPSIZE_END)
395
 
        self.authors_column = gtk.TreeViewColumn("Author(s)")
396
 
        self.authors_column.set_resizable(False)
397
 
        self.authors_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
398
 
        self.authors_column.set_fixed_width(200)
399
 
        self.authors_column.pack_start(cell, expand=True)
400
 
        self.authors_column.add_attribute(cell, "text", treemodel.AUTHORS)
401
 
        self.treeview.append_column(self.authors_column)
 
375
        self.committer_column = gtk.TreeViewColumn("Committer")
 
376
        self.committer_column.set_resizable(False)
 
377
        self.committer_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
378
        self.committer_column.set_fixed_width(200)
 
379
        self.committer_column.pack_start(cell, expand=True)
 
380
        self.committer_column.add_attribute(cell, "text", treemodel.COMMITTER)
 
381
        self.treeview.append_column(self.committer_column)
402
382
 
403
383
        cell = gtk.CellRendererText()
404
384
        cell.set_property("width-chars", 20)
414
394
        
415
395
        return self.treeview
416
396
    
 
397
    def construct_loading_msg(self):
 
398
        image_loading = gtk.image_new_from_stock(gtk.STOCK_REFRESH,
 
399
                                                 gtk.ICON_SIZE_BUTTON)
 
400
        image_loading.show()
 
401
        
 
402
        label_loading = gtk.Label(
 
403
            _i18n("Please wait, loading ancestral graph..."))
 
404
        label_loading.set_alignment(0.0, 0.5)
 
405
        label_loading.show()
 
406
        
 
407
        self.loading_msg_box = gtk.HBox()
 
408
        self.loading_msg_box.set_spacing(5)
 
409
        self.loading_msg_box.set_border_width(5)        
 
410
        self.loading_msg_box.pack_start(image_loading, False, False)
 
411
        self.loading_msg_box.pack_start(label_loading, True, True)
 
412
        self.loading_msg_box.show()
 
413
        
 
414
        return self.loading_msg_box
 
415
 
417
416
    def _on_selection_changed(self, treeview):
418
417
        """callback for when the treeview changes."""
419
418
        (path, focus) = treeview.get_cursor()
420
 
        if (path is not None) and (path != self._prev_cursor_path):
421
 
            self._prev_cursor_path = path # avoid emitting twice per click
422
 
            self.path = path
 
419
        if path is not None:
 
420
            self.iter = self.model.get_iter(path)
423
421
            self.emit('revision-selected')
424
422
 
425
423
    def _on_revision_selected(self, widget, event):
426
 
        from bzrlib.plugins.gtk.revisionmenu import RevisionMenu
 
424
        from bzrlib.plugins.gtk.revisionmenu import RevisionPopupMenu
427
425
        if event.button == 3:
428
 
            menu = RevisionMenu(self.branch.repository, 
 
426
            menu = RevisionPopupMenu(self.branch.repository, 
429
427
                [self.get_revision().revision_id],
430
428
                self.branch)
431
429
            menu.connect('tag-added', lambda w, t, r: self.add_tag(t, r))