gitview: Add key binding for F5.
[git.git] / contrib / gitview / gitview
index 5c338c0..c708534 100755 (executable)
@@ -154,7 +154,7 @@ class CellRendererGraph(gtk.GenericCellRenderer):
 
                cols = self.node[0]
                for start, end, colour in self.in_lines + self.out_lines:
-                       cols = max(cols, start, end)
+                       cols = int(max(cols, start, end))
 
                (column, colour, names) = self.node
                names_len = 0
@@ -162,7 +162,7 @@ class CellRendererGraph(gtk.GenericCellRenderer):
                        for item in names:
                                names_len += len(item)
 
-               width = box_size * (cols + 1 ) + names_len 
+               width = box_size * (cols + 1 ) + names_len
                height = box_size
 
                # FIXME I have no idea how to use cell_area properly
@@ -239,20 +239,23 @@ class CellRendererGraph(gtk.GenericCellRenderer):
                                box_size / 4, 0, 2 * math.pi)
 
 
+               self.set_colour(ctx, colour, 0.0, 0.5)
+               ctx.stroke_preserve()
+
+               self.set_colour(ctx, colour, 0.5, 1.0)
+               ctx.fill_preserve()
+
                if (len(names) != 0):
                        name = " "
                        for item in names:
                                name = name + item + " "
 
-                       ctx.select_font_face("Monospace")
                        ctx.set_font_size(13)
-                       ctx.text_path(name)
-
-               self.set_colour(ctx, colour, 0.0, 0.5)
-               ctx.stroke_preserve()
-
-               self.set_colour(ctx, colour, 0.5, 1.0)
-               ctx.fill()
+                       if (flags & 1):
+                               self.set_colour(ctx, colour, 0.5, 1.0)
+                       else:
+                               self.set_colour(ctx, colour, 0.0, 0.5)
+                       ctx.show_text(name)
 
 class Commit:
        """ This represent a commit object obtained after parsing the git-rev-list
@@ -261,11 +264,11 @@ class Commit:
        children_sha1 = {}
 
        def __init__(self, commit_lines):
-               self.message            = ""
+               self.message            = ""
                self.author             = ""
-               self.date               = ""
-               self.committer          = ""
-               self.commit_date        = ""
+               self.date               = ""
+               self.committer          = ""
+               self.commit_date        = ""
                self.commit_sha1        = ""
                self.parent_sha1        = [ ]
                self.parse_commit(commit_lines)
@@ -365,7 +368,7 @@ class DiffWindow:
                save_menu.connect("activate", self.save_menu_response, "save")
                save_menu.show()
                menu_bar.append(save_menu)
-               vbox.pack_start(menu_bar, False, False, 2)
+               vbox.pack_start(menu_bar, expand=False, fill=True)
                menu_bar.show()
 
                scrollwin = gtk.ScrolledWindow()
@@ -391,7 +394,7 @@ class DiffWindow:
                sourceview.show()
 
 
-       def set_diff(self, commit_sha1, parent_sha1):
+       def set_diff(self, commit_sha1, parent_sha1, encoding):
                """Set the differences showed by this window.
                Compares the two trees and populates the window with the
                differences.
@@ -401,7 +404,7 @@ class DiffWindow:
                        return
 
                fp = os.popen("git diff-tree -p " + parent_sha1 + " " + commit_sha1)
-               self.buffer.set_text(fp.read())
+               self.buffer.set_text(unicode(fp.read(), encoding).encode('utf-8'))
                fp.close()
                self.window.show()
 
@@ -422,14 +425,15 @@ class DiffWindow:
 class GitView:
        """ This is the main class
        """
-       version = "0.6"
+       version = "0.8"
 
        def __init__(self, with_diff=0):
                self.with_diff = with_diff
-               self.window =   gtk.Window(gtk.WINDOW_TOPLEVEL)
+               self.window =   gtk.Window(gtk.WINDOW_TOPLEVEL)
                self.window.set_border_width(0)
                self.window.set_title("Git repository browser")
 
+               self.get_encoding()
                self.get_bt_sha1()
 
                # Use three-quarters of the screen by default
@@ -445,8 +449,17 @@ class GitView:
 
                self.accel_group = gtk.AccelGroup()
                self.window.add_accel_group(self.accel_group)
+               self.accel_group.connect_group(0xffc2, 0, gtk.ACCEL_LOCKED, self.refresh);
 
-               self.construct()
+               self.window.add(self.construct())
+
+       def refresh(self, widget, event=None, *arguments, **keywords):
+               self.get_encoding()
+               self.get_bt_sha1()
+               Commit.children_sha1 = {}
+               self.set_branch(sys.argv[without_diff:])
+               self.window.show()
+               return True
 
        def get_bt_sha1(self):
                """ Update the bt_sha1 dictionary with the
@@ -454,11 +467,7 @@ class GitView:
 
                self.bt_sha1 = { }
                ls_remote = re.compile('^(.{40})\trefs/([^^]+)(?:\\^(..))?$');
-               git_dir = os.getenv("GIT_DIR")
-               if (git_dir == None):
-                       git_dir = ".git"
-
-               fp = os.popen('git ls-remote ' + git_dir)
+               fp = os.popen('git ls-remote "${GIT_DIR-.git}"')
                while 1:
                        line = string.strip(fp.readline())
                        if line == '':
@@ -472,22 +481,20 @@ class GitView:
                        self.bt_sha1[sha1].append(name)
                fp.close()
 
+       def get_encoding(self):
+               fp = os.popen("git repo-config --get i18n.commitencoding")
+               self.encoding=string.strip(fp.readline())
+               fp.close()
+               if (self.encoding == ""):
+                       self.encoding = "utf-8"
+
 
        def construct(self):
                """Construct the window contents."""
+               vbox = gtk.VBox()
                paned = gtk.VPaned()
                paned.pack1(self.construct_top(), resize=False, shrink=True)
                paned.pack2(self.construct_bottom(), resize=False, shrink=True)
-               self.window.add(paned)
-               paned.show()
-
-
-       def construct_top(self):
-               """Construct the top-half of the window."""
-               vbox = gtk.VBox(spacing=6)
-               vbox.set_border_width(12)
-               vbox.show()
-
                menu_bar = gtk.MenuBar()
                menu_bar.set_pack_direction(gtk.PACK_DIRECTION_RTL)
                help_menu = gtk.MenuItem("Help")
@@ -499,11 +506,23 @@ class GitView:
                help_menu.set_submenu(menu)
                help_menu.show()
                menu_bar.append(help_menu)
-               vbox.pack_start(menu_bar, False, False, 2)
                menu_bar.show()
+               vbox.pack_start(menu_bar, expand=False, fill=True)
+               vbox.pack_start(paned, expand=True, fill=True)
+               paned.show()
+               vbox.show()
+               return vbox
+
+
+       def construct_top(self):
+               """Construct the top-half of the window."""
+               vbox = gtk.VBox(spacing=6)
+               vbox.set_border_width(12)
+               vbox.show()
+
 
                scrollwin = gtk.ScrolledWindow()
-               scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+               scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
                scrollwin.set_shadow_type(gtk.SHADOW_IN)
                vbox.pack_start(scrollwin, expand=True, fill=True)
                scrollwin.show()
@@ -687,7 +706,7 @@ class GitView:
                self.revid_label.set_text(revid_label)
                self.committer_label.set_text(committer)
                self.timestamp_label.set_text(timestamp)
-               self.message_buffer.set_text(message)
+               self.message_buffer.set_text(unicode(message, self.encoding).encode('utf-8'))
 
                for widget in self.parents_widgets:
                        self.table.remove(widget)
@@ -732,7 +751,7 @@ class GitView:
                        button.set_relief(gtk.RELIEF_NONE)
                        button.set_sensitive(True)
                        button.connect("clicked", self._show_clicked_cb,
-                                       commit.commit_sha1, parent_id)
+                                       commit.commit_sha1, parent_id, self.encoding)
                        hbox.pack_start(button, expand=False, fill=True)
                        button.show()
 
@@ -788,7 +807,7 @@ class GitView:
                        button.set_relief(gtk.RELIEF_NONE)
                        button.set_sensitive(True)
                        button.connect("clicked", self._show_clicked_cb,
-                                       child_id, commit.commit_sha1)
+                                       child_id, commit.commit_sha1, self.encoding)
                        hbox.pack_start(button, expand=False, fill=True)
                        button.show()
 
@@ -827,6 +846,7 @@ class GitView:
                self.colours = {}
                self.nodepos = {}
                self.incomplete_line = {}
+               self.commits = []
 
                index = 0
                last_colour = 0
@@ -844,12 +864,7 @@ class GitView:
 
                        commit = Commit(commit_lines)
                        if (commit != None ):
-                               (out_line, last_colour, last_nodepos) = self.draw_graph(commit,
-                                                                               index, out_line,
-                                                                               last_colour,
-                                                                               last_nodepos)
-                               self.index[commit.commit_sha1] = index
-                               index += 1
+                               self.commits.append(commit)
 
                        # Skip the '\0
                        commit_lines = []
@@ -858,6 +873,14 @@ class GitView:
 
                fp.close()
 
+               for commit in self.commits:
+                       (out_line, last_colour, last_nodepos) = self.draw_graph(commit,
+                                                                               index, out_line,
+                                                                               last_colour,
+                                                                               last_nodepos)
+                       self.index[commit.commit_sha1] = index
+                       index += 1
+
                self.treeview.set_model(self.model)
                self.treeview.show()
 
@@ -870,28 +893,22 @@ class GitView:
 
                # Reset nodepostion
                if (last_nodepos > 5):
-                       last_nodepos = 0
+                       last_nodepos = -1
 
                # Add the incomplete lines of the last cell in this
-               for sha1 in self.incomplete_line.keys():
-                       if ( sha1 != commit.commit_sha1):
-                               for pos in self.incomplete_line[sha1]:
-                                       in_line.append((pos, pos, self.colours[sha1]))
-                       else:
-                               del self.incomplete_line[sha1]
-
                try:
                        colour = self.colours[commit.commit_sha1]
                except KeyError:
-                       last_colour +=1
-                       self.colours[commit.commit_sha1] = last_colour
-                       colour =  last_colour
+                       self.colours[commit.commit_sha1] = last_colour+1
+                       last_colour = self.colours[commit.commit_sha1]
+                       colour =   self.colours[commit.commit_sha1]
+
                try:
                        node_pos = self.nodepos[commit.commit_sha1]
                except KeyError:
-                       last_nodepos +=1
-                       self.nodepos[commit.commit_sha1] = last_nodepos
-                       node_pos = last_nodepos
+                       self.nodepos[commit.commit_sha1] = last_nodepos+1
+                       last_nodepos = self.nodepos[commit.commit_sha1]
+                       node_pos =  self.nodepos[commit.commit_sha1]
 
                #The first parent always continue on the same line
                try:
@@ -901,25 +918,26 @@ class GitView:
                        self.colours[commit.parent_sha1[0]] = colour
                        self.nodepos[commit.parent_sha1[0]] = node_pos
 
-               in_line.append((node_pos, self.nodepos[commit.parent_sha1[0]],
-                                       self.colours[commit.parent_sha1[0]]))
-
-               self.add_incomplete_line(commit.parent_sha1[0], index+1)
+               for sha1 in self.incomplete_line.keys():
+                       if (sha1 != commit.commit_sha1):
+                               self.draw_incomplete_line(sha1, node_pos,
+                                               out_line, in_line, index)
+                       else:
+                               del self.incomplete_line[sha1]
 
-               if (len(commit.parent_sha1) > 1):
-                       for parent_id in commit.parent_sha1[1:]:
-                               try:
-                                       tmp_node_pos = self.nodepos[parent_id]
-                               except KeyError:
-                                       last_colour += 1;
-                                       self.colours[parent_id] = last_colour
-                                       last_nodepos +=1
-                                       self.nodepos[parent_id] = last_nodepos
 
-                               in_line.append((node_pos, self.nodepos[parent_id],
-                                                       self.colours[parent_id]))
-                               self.add_incomplete_line(parent_id, index+1)
+               for parent_id in commit.parent_sha1:
+                       try:
+                               tmp_node_pos = self.nodepos[parent_id]
+                       except KeyError:
+                               self.colours[parent_id] = last_colour+1
+                               last_colour = self.colours[parent_id]
+                               self.nodepos[parent_id] = last_nodepos+1
+                               last_nodepos = self.nodepos[parent_id]
 
+                       in_line.append((node_pos, self.nodepos[parent_id],
+                                               self.colours[parent_id]))
+                       self.add_incomplete_line(parent_id)
 
                try:
                        branch_tag = self.bt_sha1[commit.commit_sha1]
@@ -934,12 +952,31 @@ class GitView:
 
                return (in_line, last_colour, last_nodepos)
 
-       def add_incomplete_line(self, sha1, index):
+       def add_incomplete_line(self, sha1):
                try:
                        self.incomplete_line[sha1].append(self.nodepos[sha1])
                except KeyError:
                        self.incomplete_line[sha1] = [self.nodepos[sha1]]
 
+       def draw_incomplete_line(self, sha1, node_pos, out_line, in_line, index):
+               for idx, pos in enumerate(self.incomplete_line[sha1]):
+                       if(pos == node_pos):
+                               #remove the straight line and add a slash
+                               if ((pos, pos, self.colours[sha1]) in out_line):
+                                       out_line.remove((pos, pos, self.colours[sha1]))
+                               out_line.append((pos, pos+0.5, self.colours[sha1]))
+                               self.incomplete_line[sha1][idx] = pos = pos+0.5
+                       try:
+                               next_commit = self.commits[index+1]
+                               if (next_commit.commit_sha1 == sha1 and pos != int(pos)):
+                               # join the line back to the node point
+                               # This need to be done only if we modified it
+                                       in_line.append((pos, pos-0.5, self.colours[sha1]))
+                                       continue;
+                       except IndexError:
+                               pass
+                       in_line.append((pos, pos, self.colours[sha1]))
+
 
        def _go_clicked_cb(self, widget, revid):
                """Callback for when the go button for a parent is clicked."""
@@ -953,14 +990,14 @@ class GitView:
 
                self.treeview.grab_focus()
 
-       def _show_clicked_cb(self, widget,  commit_sha1, parent_sha1):
+       def _show_clicked_cb(self, widget,  commit_sha1, parent_sha1, encoding):
                """Callback for when the show button for a parent is clicked."""
                window = DiffWindow()
-               window.set_diff(commit_sha1, parent_sha1)
+               window.set_diff(commit_sha1, parent_sha1, encoding)
                self.treeview.grab_focus()
 
+without_diff = 0
 if __name__ == "__main__":
-       without_diff = 0
 
        if (len(sys.argv) > 1 ):
                if (sys.argv[1] == "--without-diff"):