[gitg] Basic start of adding DND and context menus for refs in the revision view



commit cfcb51861b9902ab00205e6f4865e3871f631082
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Sun Jun 28 23:49:04 2009 +0200

    Basic start of adding DND and context menus for refs in the revision view

 gitg/Makefile.am           |    4 +
 gitg/gitg-branch-actions.c |  334 +++++++++++++++++++++++++++
 gitg/gitg-branch-actions.h |   39 ++++
 gitg/gitg-dnd.c            |  536 ++++++++++++++++++++++++++++++++++++++++++++
 gitg/gitg-dnd.h            |   17 ++
 gitg/gitg-menus.xml        |   56 +++++
 gitg/gitg-window.c         |  323 +++++++++++++++++++++++++-
 gitg/gitg-window.ui        |  178 ++++++++-------
 8 files changed, 1397 insertions(+), 90 deletions(-)
---
diff --git a/gitg/Makefile.am b/gitg/Makefile.am
index c0ca9c0..f890554 100644
--- a/gitg/Makefile.am
+++ b/gitg/Makefile.am
@@ -15,6 +15,7 @@ BUILT_SOURCES = 				\
 	gitg-enum-types.h
 
 NOINST_H_FILES = 			\
+	gitg-branch-actions.h		\
 	gitg-cell-renderer-path.h	\
 	gitg-changed-file.h		\
 	gitg-color.h			\
@@ -25,6 +26,7 @@ NOINST_H_FILES = 			\
 	gitg-debug.h			\
 	gitg-diff-view.h		\
 	gitg-dirs.h			\
+	gitg-dnd.h			\
 	gitg-label-renderer.h		\
 	gitg-lane.h			\
 	gitg-lanes.h			\
@@ -47,6 +49,7 @@ NOINST_H_FILES = 			\
 gitg_SOURCES = 				\
 	$(BUILT_SOURCES)		\
 	gitg.c				\
+	gitg-branch-actions.c		\
 	gitg-cell-renderer-path.c	\
 	gitg-changed-file.c		\
 	gitg-color.c			\
@@ -57,6 +60,7 @@ gitg_SOURCES = 				\
 	gitg-debug.c			\
 	gitg-diff-view.c		\
 	gitg-dirs.c			\
+	gitg-dnd.c			\
 	gitg-label-renderer.c		\
 	gitg-lane.c			\
 	gitg-lanes.c			\
diff --git a/gitg/gitg-branch-actions.c b/gitg/gitg-branch-actions.c
new file mode 100644
index 0000000..e485383
--- /dev/null
+++ b/gitg/gitg-branch-actions.c
@@ -0,0 +1,334 @@
+#include <glib/gi18n.h>
+
+#include "gitg-branch-actions.h"
+
+static gint
+message_dialog (GitgWindow     *window,
+                GtkMessageType  type,
+                gchar const    *primary,
+                gchar const    *secondary,
+                gchar const    *accept,
+                ...)
+{
+	GtkWidget *dlg;
+	va_list ap;
+	
+	va_start (ap, accept);
+	gchar *prim = g_strdup_vprintf (primary, ap);
+	va_end (ap);
+	
+	GtkDialogFlags flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
+	dlg = gtk_message_dialog_new (GTK_WINDOW (window),
+	                              flags,
+	                              type,
+	                              GTK_BUTTONS_NONE,
+	                              "%s",
+	                              prim);
+
+	g_free (prim);
+	
+	if (secondary)
+	{
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dlg),
+		                                          "%s",
+		                                          secondary);
+	}
+	
+	GtkWidget *button;
+	
+	button = gtk_button_new_from_stock (accept ? GTK_STOCK_CANCEL : GTK_STOCK_OK);
+	gtk_widget_show (button);
+	gtk_dialog_add_action_widget (GTK_DIALOG (dlg), 
+	                              button, 
+	                              accept ? GTK_RESPONSE_CANCEL : GTK_RESPONSE_ACCEPT);
+
+	if (accept)
+	{
+		button = gtk_button_new_with_label (accept);
+		gtk_widget_show (button);
+	
+		GtkWidget *image = gtk_image_new_from_stock (GTK_STOCK_OK, 
+			                                         GTK_ICON_SIZE_BUTTON);
+		gtk_widget_show (image);
+	
+		gtk_button_set_image (GTK_BUTTON (button), image);
+		gtk_dialog_add_action_widget (GTK_DIALOG (dlg), 
+			                          button, 
+			                          GTK_RESPONSE_ACCEPT);
+	}
+
+	gint ret = gtk_dialog_run (GTK_DIALOG (dlg));
+	gtk_widget_destroy (dlg);
+	
+	return ret;
+}                
+
+static gboolean
+remove_local_branch (GitgWindow *window,
+                     GitgRef    *ref)
+{
+	gchar const *name = gitg_ref_get_shortname (ref);
+	GitgRepository *repository = gitg_window_get_repository (window);
+
+	if (!gitg_repository_commandv (repository, NULL, "branch", "-d", name, NULL))
+	{
+		gint ret = message_dialog (window,
+		                           GTK_MESSAGE_ERROR,
+		                           _("Branch <%s> could not be removed"),
+		                           _("This usually means that the branch is not fully merged in HEAD. Do you want to forcefully remove the branch?"),
+		                           _("Force remove"),
+		                           name);
+
+		if (ret == GTK_RESPONSE_ACCEPT)
+		{
+			if (!gitg_repository_commandv (repository, NULL, "branch", "-D", name, NULL))
+			{
+				message_dialog (window, 
+				                GTK_MESSAGE_ERROR,
+				                _("Branch <%s> could not be forcefully removed"),
+				                NULL,
+				                NULL,
+				                name);
+
+				return FALSE;
+			}
+			else
+			{
+				gitg_repository_reload (repository);
+				return TRUE;
+			}
+		}
+	}
+	else
+	{
+		gitg_repository_reload (repository);
+		return TRUE;
+	}
+}
+
+static gboolean
+remove_remote_branch (GitgWindow *window,
+                      GitgRef    *ref)
+{
+	gchar const *name = gitg_ref_get_shortname (ref);
+	GitgRepository *repository = gitg_window_get_repository (window);
+
+	gint ret = message_dialog (window,
+	                          GTK_MESSAGE_QUESTION,
+	                          _("Are you sure you want to remove the remote branch <%s>?"),
+	                          _("This permanently removes the remote branch."),
+	                          _("Remove remote branch"),
+	                          name);
+	
+	if (ret == GTK_RESPONSE_ACCEPT)
+	{
+		gchar *local = gitg_ref_get_local_name (ref);
+		gchar *rm = g_strconcat (":", local, NULL);
+		g_free (local);
+		
+		if (!gitg_repository_commandv (repository,
+		                               NULL,
+		                               "push",
+		                               gitg_ref_get_prefix (ref),
+		                               rm,
+		                               NULL))
+		{
+			message_dialog (window, 
+			                GTK_MESSAGE_ERROR,
+			                _("Failed to remove remote branch <%s>."),
+			                NULL,
+			                NULL,
+			                name);
+			return FALSE;
+		}
+		else
+		{
+			gitg_repository_reload (repository);
+			return TRUE;
+		}
+	}
+	
+	return FALSE;
+}
+
+gboolean 
+gitg_branch_actions_remove (GitgWindow *window,
+                            GitgRef    *ref)
+{
+	GitgRef *cp = gitg_ref_copy (ref);
+	gboolean ret = FALSE;
+	
+	switch (gitg_ref_get_ref_type (cp))
+	{
+		case GITG_REF_TYPE_BRANCH:
+			ret = remove_local_branch (window, cp);
+		break;
+		case GITG_REF_TYPE_REMOTE:
+			ret = remove_remote_branch (window, cp);
+		break;
+		default:
+		break;
+	}
+	
+	gitg_ref_free (cp);
+	return ret;
+}
+
+static gboolean
+stash_changes (GitgWindow *window,
+               GitgRef    *ref)
+{
+	GitgRepository *repository = gitg_window_get_repository (window);
+	
+	gchar **output = gitg_repository_command_with_outputv (repository,
+	                                                       NULL,
+	                                                       "diff-files",
+	                                                       NULL);
+
+	if (output && *output && **output)
+	{
+		gint ret = message_dialog (window,
+		                           GTK_MESSAGE_QUESTION,
+		                           _("You have uncommited changes in your current working copy"),
+		                           _("Do you want to temporarily stash these changes?"),
+		                           _("Stash changes"));
+
+		if (ret != GTK_RESPONSE_ACCEPT)
+		{
+			return FALSE;
+		}
+		
+		if (!gitg_repository_commandv (repository, NULL, "stash", NULL))
+		{
+			message_dialog (window,
+			                GTK_MESSAGE_ERROR,
+			                _("Could not stash changes from your current working copy."),
+			                NULL,
+			                NULL);
+			return FALSE;
+		}
+	}
+
+	if (output)
+	{
+		g_strfreev (output);
+	}
+	
+	return TRUE;
+}
+
+static gboolean
+checkout_local_branch (GitgWindow *window,
+                       GitgRef    *ref)
+{
+	if (!stash_changes (window, ref))
+	{
+		return FALSE;
+	}
+		
+	GitgRepository *repository = gitg_window_get_repository (window);
+	gchar const *name = gitg_ref_get_shortname (ref);
+	
+	if (!gitg_repository_commandv (repository, NULL, "checkout", name, NULL))
+	{
+		message_dialog (window,
+		                GTK_MESSAGE_ERROR,
+		                _("Failed to checkout local branch <%s>"),
+		                NULL,
+		                NULL,
+		                name);
+	}
+	else
+	{
+		gitg_repository_load (repository, 1, (gchar const **)&name, NULL);
+	}
+}
+
+static gboolean
+checkout_remote_branch (GitgWindow *window,
+                        GitgRef    *ref)
+{
+	if (!stash_changes (window, ref))
+	{
+		return FALSE;
+	}
+		
+	GitgRepository *repository = gitg_window_get_repository (window);
+	gchar const *name = gitg_ref_get_shortname (ref);
+	gchar *local = gitg_ref_get_local_name (ref);
+	gboolean ret;
+	
+	if (!gitg_repository_commandv (repository, 
+	                               NULL, 
+	                               "checkout", 
+	                               "--track", 
+	                               "-b",
+	                               local,
+	                               name,
+	                               NULL))
+	{
+		message_dialog (window,
+		                GTK_MESSAGE_ERROR,
+		                _("Failed to checkout remote branch <%s> to local branch <%s>"),
+		                NULL,
+		                NULL,
+		                name,
+		                local);
+		ret = FALSE;
+	}
+	else
+	{
+		gitg_repository_load (repository, 1, (gchar const **)&local, NULL);
+		ret = TRUE;
+	}
+	
+	g_free (local);
+	return ret;
+}
+
+gboolean
+gitg_branch_actions_checkout (GitgWindow *window,
+                              GitgRef    *ref)
+{
+	GitgRef *cp = gitg_ref_copy (ref);
+	gboolean ret = FALSE;
+	
+	switch (gitg_ref_get_ref_type (cp))
+	{
+		case GITG_REF_TYPE_BRANCH:
+			ret = checkout_local_branch (window, cp);
+		break;
+		case GITG_REF_TYPE_REMOTE:
+			ret = checkout_remote_branch (window, cp);
+		break;
+		default:
+		break;
+	}
+	
+	gitg_ref_free (cp);
+	return ret;
+}
+
+gboolean
+gitg_branch_actions_merge (GitgWindow *window,
+                           GitgRef    *source,
+                           GitgRef    *dest)
+{
+	return FALSE;
+}
+
+gboolean
+gitg_branch_actions_rebase (GitgWindow *window,
+                            GitgRef    *source,
+                            GitgRef    *dest)
+{
+	return FALSE;
+}
+
+gboolean
+gitg_branch_actions_apply_stash (GitgWindow *window,
+                                 GitgRef    *stash)
+{
+	return FALSE;
+}
+
diff --git a/gitg/gitg-branch-actions.h b/gitg/gitg-branch-actions.h
new file mode 100644
index 0000000..3a8eb4e
--- /dev/null
+++ b/gitg/gitg-branch-actions.h
@@ -0,0 +1,39 @@
+/*
+ * gitg-branch-actions.h
+ * This file is part of gitg
+ *
+ * Copyright (C) 2009 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GITG_BRANCH_ACTIONS_H__
+#define __GITG_BRANCH_ACTIONS_H__
+
+#include "gitg-window.h"
+#include "gitg-ref.h"
+
+G_BEGIN_DECLS
+
+gboolean gitg_branch_actions_remove (GitgWindow *window, GitgRef *ref);
+gboolean gitg_branch_actions_checkout (GitgWindow *window, GitgRef *ref);
+gboolean gitg_branch_actions_merge (GitgWindow *window, GitgRef *source, GitgRef *dest);
+gboolean gitg_branch_actions_rebase (GitgWindow *window, GitgRef *source, GitgRef *dest);
+
+G_END_DECLS
+
+#endif /* __GITG_BRANCH_ACTIONS_H__ */
+
diff --git a/gitg/gitg-dnd.c b/gitg/gitg-dnd.c
new file mode 100644
index 0000000..9ffe0f9
--- /dev/null
+++ b/gitg/gitg-dnd.c
@@ -0,0 +1,536 @@
+#include "gitg-dnd.h"
+#include "gitg-ref.h"
+#include "gitg-cell-renderer-path.h"
+#include "gitg-utils.h"
+
+enum
+{
+	DRAG_TARGET_REF = 1
+};
+
+static GtkTargetEntry target_entries[] = {
+	{"gitg-ref", GTK_TARGET_SAME_WIDGET, DRAG_TARGET_REF}
+};
+
+typedef struct
+{
+	GtkTreeView *tree_view;
+	GitgRef *ref;
+	GitgRef *target;
+	GitgRef *cursor_ref;
+	
+	GitgDndCallback callback;
+	gpointer callback_data;
+	
+	gdouble x;
+	gdouble y;
+	
+	gboolean is_drag;
+	GtkTargetList *target_list;
+	
+	guint scroll_timeout;
+} GitgDndData;
+
+#define GITG_DND_DATA_KEY "GitgDndDataKey"
+
+#define GITG_DND_GET_DATA(widget) ((GitgDndData *)g_object_get_data(G_OBJECT(widget), GITG_DND_DATA_KEY))
+
+static void
+remove_scroll_timeout (GitgDndData *data)
+{
+	if (data->scroll_timeout != 0)
+	{
+		g_source_remove (data->scroll_timeout);
+		data->scroll_timeout = 0;
+	}
+}
+
+
+static GitgDndData *
+gitg_dnd_data_new ()
+{
+	GitgDndData *data = g_slice_new0 (GitgDndData);
+	
+	data->target_list = gtk_target_list_new (target_entries,
+	                                         G_N_ELEMENTS (target_entries));
+
+	return data;
+}
+
+static void
+gitg_dnd_data_free (GitgDndData *data)
+{
+	gtk_target_list_unref (data->target_list);
+	remove_scroll_timeout (data);
+
+	g_slice_free (GitgDndData, data);
+}
+
+static GitgRef *
+get_ref_at_pos (GtkTreeView *tree_view, gint x, gint y, gint *hot_x, gint *hot_y, GitgCellRendererPath **renderer, GtkTreePath **tp)
+{
+	gint cell_x;
+	gint cell_y;
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+
+	if (!gtk_tree_view_get_path_at_pos (tree_view,
+	                                    x,
+	                                    y,
+	                                    &path,
+	                                    &column,
+	                                    &cell_x,
+	                                    &cell_y))
+	{
+		return NULL;
+	}
+	
+	if (hot_y)
+	{
+		*hot_y = cell_y;
+	}
+	
+	GtkCellRenderer *cell = gitg_utils_find_cell_at_pos (tree_view, column, path, cell_x);
+	
+	if (!cell || !GITG_IS_CELL_RENDERER_PATH (cell))
+	{
+		return NULL;
+	}
+	
+	if (renderer)
+	{
+		*renderer = GITG_CELL_RENDERER_PATH (cell);
+	}
+	
+	GitgRef *ref = gitg_cell_renderer_path_get_ref_at_pos (GTK_WIDGET (tree_view),
+	                                                       GITG_CELL_RENDERER_PATH (cell),
+	                                                       cell_x,
+	                                                       hot_x);
+
+	if (tp)
+	{
+		*tp = path;
+	}
+	else
+	{
+		gtk_tree_path_free (path);
+	}
+
+	return ref;
+}
+
+static gboolean
+can_drag (GitgRef *ref)
+{
+	GitgRefType type = gitg_ref_get_ref_type (ref);
+	
+	switch (type)
+	{
+		case GITG_REF_TYPE_BRANCH:
+		case GITG_REF_TYPE_REMOTE:
+			return TRUE;
+		break;
+		default:
+			return FALSE;
+		break;
+	}
+}
+
+static gboolean
+can_drop (GitgRef *source, GitgRef *dest)
+{
+	if (gitg_ref_equal (source, dest))
+	{
+		return FALSE;
+	}
+
+	GitgRefType source_type = gitg_ref_get_ref_type (source);
+	GitgRefType dest_type = gitg_ref_get_ref_type (dest);
+	
+	if (source_type == GITG_REF_TYPE_BRANCH)
+	{
+		return dest_type ==  GITG_REF_TYPE_BRANCH || dest_type == GITG_REF_TYPE_REMOTE;
+	}
+	else if (source_type == GITG_REF_TYPE_REMOTE)
+	{
+		return dest_type == GITG_REF_TYPE_BRANCH;
+	}
+	
+	return FALSE;
+}
+
+static void
+begin_drag (GtkWidget   *widget,
+            GdkEvent    *event,
+            GitgDndData *data)
+{
+
+	GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
+	gint hot_x;
+	gint hot_y;
+	GitgCellRendererPath *cell;
+	GitgRef *ref = get_ref_at_pos (tree_view, 
+	                               (gint)data->x, 
+	                               (gint)data->y, 
+	                               &hot_x, 
+	                               &hot_y,
+	                               &cell,
+	                               NULL);
+
+	if (!ref || !can_drag (ref))
+	{
+		return;
+	}
+	
+	data->ref = ref;
+	gitg_ref_set_state (ref, GITG_REF_STATE_NONE);
+
+	GdkDragContext *context = gtk_drag_begin (widget,
+	                                          data->target_list,
+	                                          GDK_ACTION_MOVE,
+	                                          1,
+	                                          event);
+
+	gint minwidth;
+	gint h;
+	gdk_display_get_maximal_cursor_size (gtk_widget_get_display (widget), &minwidth, &h);
+
+	GdkPixbuf *pixbuf = gitg_cell_renderer_path_render_ref (GTK_WIDGET (tree_view),
+	                                                        cell,
+	                                                        ref,
+	                                                        minwidth + 1);
+
+	if (pixbuf)
+	{
+		gtk_drag_set_icon_pixbuf (context, pixbuf, hot_x, hot_y);
+		g_object_unref (pixbuf);
+	}
+	
+}
+
+static void
+update_highlight (GitgDndData *data, gint x, gint y)
+{
+	GitgRef *ref = get_ref_at_pos (data->tree_view, 
+	                               x, 
+	                               y, 
+	                               NULL,
+	                               NULL,
+	                               NULL,
+	                               NULL);
+
+	if (ref && !can_drag (ref))
+	{
+		ref = NULL;
+	}
+
+	if (ref != data->cursor_ref)
+	{
+		if (data->cursor_ref)
+		{
+			gitg_ref_set_state (data->cursor_ref, GITG_REF_STATE_NONE);
+		}
+		
+		if (ref)
+		{
+			gitg_ref_set_state (ref, GITG_REF_STATE_PRELIGHT);
+			
+			gdk_window_set_cursor (gtk_tree_view_get_bin_window (data->tree_view),
+			                       gdk_cursor_new (GDK_HAND2));
+		}
+		else
+		{
+			gdk_window_set_cursor (gtk_tree_view_get_bin_window (data->tree_view),
+			                       NULL);
+		}
+		
+		data->cursor_ref = ref;
+		gtk_widget_queue_draw (GTK_WIDGET (data->tree_view));
+	}	
+}
+
+static gboolean
+vertical_autoscroll (GitgDndData *data)
+{
+	GdkRectangle visible_rect;
+	gint y;
+	gint offset;
+	gfloat value;
+
+	gdk_window_get_pointer (gtk_tree_view_get_bin_window (data->tree_view), NULL, &y, NULL);
+	gtk_tree_view_convert_bin_window_to_tree_coords (data->tree_view, 0, y, NULL, &y);
+
+	gtk_tree_view_get_visible_rect (data->tree_view, &visible_rect);
+
+	/* see if we are near the edge. */
+	offset = y - (visible_rect.y + 2 * 15);
+
+	if (offset > 0)
+	{
+		offset = y - (visible_rect.y + visible_rect.height - 2 * 15);
+		
+		if (offset < 0)
+		{
+			return;
+		}
+	}
+
+	GtkAdjustment *adj = gtk_tree_view_get_vadjustment (data->tree_view);
+	
+	value = CLAMP (gtk_adjustment_get_value (adj) + offset, 0.0,
+	               gtk_adjustment_get_upper (adj) - gtk_adjustment_get_page_size (adj));
+
+	gtk_adjustment_set_value (adj, value);	
+	return TRUE;
+}
+
+static void
+add_scroll_timeout (GitgDndData *data)
+{
+	if (data->scroll_timeout == 0)
+    {
+		data->scroll_timeout = g_timeout_add (50, 
+		                                      (GSourceFunc)vertical_autoscroll, 
+		                                      data);
+    }
+}
+
+
+static gboolean
+gitg_drag_source_event_cb (GtkWidget   *widget,
+                           GdkEvent    *event,
+                           GitgDndData *data)
+{
+	gboolean retval = FALSE;
+	
+	switch (event->type)
+	{
+		case GDK_BUTTON_PRESS:
+			if (event->button.button == 1)
+			{
+				data->x = event->button.x;
+				data->y = event->button.y;
+
+				data->is_drag = TRUE;
+				data->ref = NULL;
+				data->target = NULL;
+			}
+		break;
+		case GDK_BUTTON_RELEASE:
+			if (event->button.button == 1)
+			{
+				data->is_drag = FALSE;
+				
+				if (data->target)
+				{
+					gitg_ref_set_state (data->target, GITG_REF_STATE_NONE);
+				}
+				
+				remove_scroll_timeout (data);
+			}
+		break;
+		case GDK_MOTION_NOTIFY:
+			if (data->is_drag && (event->motion.state & GDK_BUTTON1_MASK))
+			{
+				if (gtk_drag_check_threshold (widget, data->x, data->y, event->motion.x, event->motion.y))
+				{
+					data->is_drag = FALSE;
+					begin_drag (widget, event, data);
+
+					retval = TRUE;
+				}
+			}
+			else if (!data->is_drag && !(event->motion.state & GDK_BUTTON1_MASK))
+			{
+				update_highlight (data, (gint)event->motion.x, (gint)event->motion.y);
+			}
+		break;
+		default:
+		break;
+	}
+  
+	return retval;
+}
+
+static gboolean
+gitg_drag_source_motion_cb (GtkWidget       *widget,
+                            GdkDragContext  *context,
+                            gint             x,
+                            gint             y,
+                            guint            time,
+                            GitgDndData     *data)
+{
+	if (!data->ref)
+	{
+		return FALSE;
+	}
+	
+	GitgRef *ref;
+	gint dx;
+	gint dy;
+
+	gtk_tree_view_convert_widget_to_bin_window_coords (data->tree_view,
+	                                                   x,
+	                                                   y,
+	                                                   &dx,
+	                                                   &dy);
+	
+	ref = get_ref_at_pos (GTK_TREE_VIEW (widget),
+	                      dx,
+	                      dy,
+	                      NULL,
+	                      NULL,
+	                      NULL,
+	                      NULL);
+
+	gboolean ret = FALSE;
+
+	if (ref != data->target)
+	{
+		if (data->target)
+		{
+			gitg_ref_set_state (data->target, GITG_REF_STATE_NONE);
+			gtk_widget_queue_draw (widget);
+		}
+		
+		if (data->callback)
+		{
+			data->callback (data->ref, ref, FALSE, data->callback_data);	
+		}
+	}
+		
+	if (ref && can_drop (data->ref, ref))
+	{
+		if (ref != data->target)
+		{
+			gitg_ref_set_state (ref, GITG_REF_STATE_SELECTED);
+			data->target = ref;
+			
+			gtk_widget_queue_draw (widget);
+		}
+		
+		gdk_drag_status (context, GDK_ACTION_MOVE, time);
+		ret = TRUE;
+	}
+	else
+	{
+		if (data->target)
+		{
+			data->target = NULL;
+			gtk_widget_queue_draw (widget);
+		}
+	}
+
+	add_scroll_timeout (data);
+	return ret;
+}
+
+static gboolean
+gitg_drag_source_drop_cb (GtkWidget *widget,
+                          GdkDragContext *context,
+                          gint x,
+                          gint y,
+                          guint time,
+                          GitgDndData *data)
+{
+	if (!data->ref || !data->target)
+	{
+		return FALSE;
+	}
+
+	gboolean ret = FALSE;
+	
+	if (data->callback)
+	{
+		ret = data->callback (data->ref, data->target, TRUE, data->callback_data);	
+	}
+	
+	gtk_drag_finish (context, ret, FALSE, time);
+}
+
+static gboolean
+gitg_drag_source_leave_cb (GtkWidget       *widget,
+                           GdkDragContext  *context,
+                           guint            time,
+                           GitgDndData     *data)
+{
+	remove_scroll_timeout (data);
+}
+
+void 
+gitg_dnd_enable (GtkTreeView *tree_view, GitgDndCallback callback, gpointer callback_data)
+{
+	if (GITG_DND_GET_DATA (tree_view))
+	{
+		return;
+	}
+	
+	GitgDndData *data = gitg_dnd_data_new ();
+	
+	data->tree_view = tree_view;
+	data->callback = callback;
+	data->callback_data = callback_data;
+
+	g_object_set_data_full (G_OBJECT (tree_view),
+	                        GITG_DND_DATA_KEY,
+	                        data,
+	                        (GDestroyNotify)gitg_dnd_data_free);
+	
+	gtk_widget_add_events (GTK_WIDGET (tree_view), 
+	                       gtk_widget_get_events (GTK_WIDGET (tree_view)) |
+	                       GDK_BUTTON_PRESS_MASK | 
+	                       GDK_BUTTON_RELEASE_MASK |
+	                       GDK_BUTTON_MOTION_MASK);
+
+	gtk_drag_dest_set (GTK_WIDGET (tree_view),
+	                   0,
+	                   target_entries,
+	                   G_N_ELEMENTS (target_entries),
+	                   GDK_ACTION_MOVE);
+	                   
+	g_signal_connect (tree_view, 
+	                  "button-press-event",
+	                  G_CALLBACK (gitg_drag_source_event_cb),
+	                  data);
+
+	g_signal_connect (tree_view,
+	                  "button-release-event",
+	                  G_CALLBACK (gitg_drag_source_event_cb),
+	                  data);
+
+	g_signal_connect (tree_view,
+	                  "motion-notify-event",
+	                  G_CALLBACK (gitg_drag_source_event_cb),
+	                  data);
+
+	g_signal_connect (tree_view,
+	                  "drag-motion",
+	                  G_CALLBACK (gitg_drag_source_motion_cb),
+	                  data);
+
+	g_signal_connect (tree_view,
+	                  "drag-drop",
+	                  G_CALLBACK (gitg_drag_source_drop_cb),
+	                  data);
+
+	g_signal_connect (tree_view,
+	                  "drag-leave",
+	                  G_CALLBACK (gitg_drag_source_leave_cb),
+	                  data);
+}
+
+void
+gitg_dnd_disable (GtkTreeView *tree_view)
+{
+	GitgDndData *data = GITG_DND_GET_DATA (tree_view);
+	
+	if (data)
+	{
+		g_signal_handlers_disconnect_by_func (tree_view, gitg_drag_source_event_cb, data);
+		g_signal_handlers_disconnect_by_func (tree_view, gitg_drag_source_motion_cb, data);
+		g_signal_handlers_disconnect_by_func (tree_view, gitg_drag_source_drop_cb, data);
+		g_signal_handlers_disconnect_by_func (tree_view, gitg_drag_source_leave_cb, data);
+		
+		g_object_set_data (G_OBJECT (tree_view), GITG_DND_DATA_KEY, NULL);
+	}
+}
diff --git a/gitg/gitg-dnd.h b/gitg/gitg-dnd.h
new file mode 100644
index 0000000..37a211b
--- /dev/null
+++ b/gitg/gitg-dnd.h
@@ -0,0 +1,17 @@
+#ifndef __GITG_DND_H__
+#define __GITG_DND_H__
+
+#include <gtk/gtk.h>
+#include "gitg-ref.h"
+
+G_BEGIN_DECLS
+
+typedef gboolean (*GitgDndCallback)(GitgRef *source, GitgRef *dest, gboolean dropped, gpointer callback_data);
+
+void gitg_dnd_enable (GtkTreeView *tree_view, GitgDndCallback callback, gpointer callback_data);
+void gitg_dnd_disable (GtkTreeView *tree_view);
+
+G_END_DECLS
+
+#endif /* __GITG_DND_H__ */
+
diff --git a/gitg/gitg-menus.xml b/gitg/gitg-menus.xml
index abc27bd..d1fbb59 100644
--- a/gitg/gitg-menus.xml
+++ b/gitg/gitg-menus.xml
@@ -34,6 +34,46 @@
         </child>
       </object>
     </child>
+    <child>
+      <object class="GtkActionGroup" id="action_group_revision">
+        <child>
+          <object class="GtkAction" id="CheckoutAction">
+            <property name="label">Checkout branch</property>
+            <signal name="activate" handler="on_checkout_branch_action_activate"/>
+          </object>
+        </child>
+        <child>
+          <object class="GtkAction" id="RemoveAction">
+            <property name="label">Remove branch</property>
+            <signal name="activate" handler="on_remove_branch_action_activate"/>
+          </object>
+        </child>
+        <child>
+          <object class="GtkAction" id="MergeAction">
+            <property name="label">Merge branch onto...</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkAction" id="RebaseAction">
+            <property name="label">Rebase branch onto...</property>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkActionGroup" id="action_group_dnd">
+        <child>
+          <object class="GtkAction" id="MergeDndAction">
+            <property name="label">Merge</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkAction" id="RebaseDndAction">
+            <property name="label">Rebase</property>
+          </object>
+        </child>
+      </object>
+    </child>
     <ui>
       <popup name="search_popup">
         <menuitem action="subject"/>
@@ -41,6 +81,22 @@
         <menuitem action="date"/>
         <menuitem action="hash"/>
       </popup>
+      <popup name="revision_popup">
+        <menuitem action="CheckoutAction"/>
+        <menuitem action="RemoveAction"/>
+        <separator/>
+        <menu name="Rebase" action="RebaseAction">
+          <placeholder name="Placeholder"/>
+        </menu>
+        <separator/>
+        <menu name="Merge" action="MergeAction">
+          <placeholder name="Placeholder"/>
+        </menu>
+      </popup>
+      <popup name="dnd_popup">
+        <menuitem action="RebaseDndAction"/>
+        <menuitem action="MergeDndAction"/>
+      </popup>
     </ui>
   </object>
 </interface>
diff --git a/gitg/gitg-window.c b/gitg/gitg-window.c
index 217c366..f7d8ad5 100644
--- a/gitg/gitg-window.c
+++ b/gitg/gitg-window.c
@@ -40,6 +40,8 @@
 #include "gitg-settings.h"
 #include "gitg-preferences-dialog.h"
 #include "gitg-repository-dialog.h"
+#include "gitg-dnd.h"
+#include "gitg-branch-actions.h"
 
 #define GITG_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_WINDOW, GitgWindowPrivate))
 
@@ -66,6 +68,8 @@ struct _GitgWindowPrivate
 	GtkWidget *search_popup;
 	GtkComboBox *combo_branches;
 	
+	GtkUIManager *menus_ui_manager;
+	
 	GtkWidget *vpaned_main;
 	GtkWidget *hpaned_commit;
 	GtkWidget *vpaned_commit;
@@ -79,6 +83,9 @@ struct _GitgWindowPrivate
 	GdkCursor *hand;
 	
 	gboolean destroy_has_run;
+	guint merge_rebase_uid;
+	GtkActionGroup *merge_rebase_action_group;
+	GitgRef *popup_ref;
 };
 
 static gboolean on_tree_view_motion(GtkTreeView *treeview, GdkEventMotion *event, GitgWindow *window);
@@ -212,14 +219,8 @@ build_search_entry(GitgWindow *window, GtkBuilder *builder)
 	gtk_tree_view_set_search_entry(window->priv->tree_view, GTK_ENTRY(entry));
 	gtk_widget_show(entry);
 	gtk_box_pack_end(GTK_BOX(box), entry, FALSE, FALSE, 0);
-	
-	GtkBuilder *b = gitg_utils_new_builder("gitg-menus.xml");
-	GtkUIManager *manager = GTK_UI_MANAGER(gtk_builder_get_object(b, "uiman"));
 
-	window->priv->search_popup = GTK_WIDGET(g_object_ref(gtk_ui_manager_get_widget(manager, "/ui/search_popup")));
-	
-	gtk_builder_connect_signals(b, window);
-	g_object_unref(b);
+	window->priv->search_popup = GTK_WIDGET(g_object_ref(gtk_ui_manager_get_widget(window->priv->menus_ui_manager, "/ui/search_popup")));
 	
 	g_signal_connect(entry, "icon-pressed", G_CALLBACK(on_search_icon_pressed), window);
 	gtk_tree_view_set_search_column(window->priv->tree_view, 1);
@@ -421,6 +422,68 @@ restore_state(GitgWindow *window)
 }
 
 static void
+update_dnd_status (GitgWindow *window, GitgRef *source, GitgRef *dest)
+{
+	if (!dest)
+	{
+		gtk_statusbar_push (window->priv->statusbar, 0, "");
+	}
+	else
+	{
+		gchar *message = NULL;
+		
+		if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_BRANCH &&
+		    gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_REMOTE)
+		{
+			message = g_strdup_printf (_("Push local branch <%s> to remote branch <%s>"), gitg_ref_get_shortname (source), gitg_ref_get_shortname (dest));
+		}
+		else if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_BRANCH &&
+		         gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_BRANCH)
+		{
+			message = g_strdup_printf (_("Merge/rebase local branch <%s> with/on local branch <%s>"), gitg_ref_get_shortname (source), gitg_ref_get_shortname (dest));
+		}
+		else if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_REMOTE &&
+		         gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_BRANCH)
+		{
+			message = g_strdup_printf (_("Merge/rebase remote branch <%s> with/on local branch <%s>"), gitg_ref_get_shortname (source), gitg_ref_get_shortname (dest));
+		}
+		
+		if (message)
+		{
+			gtk_statusbar_push (window->priv->statusbar, 0, message);
+		}
+		
+		g_free (message);
+	}
+}
+
+static gboolean
+on_refs_dnd (GitgRef *source, GitgRef *dest, gboolean dropped, GitgWindow *window)
+{
+	if (!dropped)
+	{
+		update_dnd_status (window, source, dest);
+		return FALSE;
+	}
+
+	gtk_statusbar_push (window->priv->statusbar, 0, "");
+	
+	return FALSE;
+}
+
+static void
+init_tree_view (GitgWindow *window, GtkBuilder *builder)
+{
+	GtkTreeViewColumn *col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "rv_column_subject"));
+	
+	window->priv->renderer_path = GITG_CELL_RENDERER_PATH(gtk_builder_get_object(builder, "rv_renderer_subject"));
+
+	gtk_tree_view_column_set_cell_data_func(col, GTK_CELL_RENDERER(window->priv->renderer_path), (GtkTreeCellDataFunc)on_renderer_path, window, NULL);
+	
+	gitg_dnd_enable (window->priv->tree_view, (GitgDndCallback)on_refs_dnd, window);
+}
+
+static void
 gitg_window_parser_finished(GtkBuildable *buildable, GtkBuilder *builder)
 {
 	if (parent_iface.parser_finished)
@@ -460,15 +523,19 @@ gitg_window_parser_finished(GtkBuildable *buildable, GtkBuilder *builder)
 	window->priv->commit_view = GITG_COMMIT_VIEW(gtk_builder_get_object(builder, "hpaned_commit"));
 
 	restore_state(window);
-
-	GtkTreeViewColumn *col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "rv_column_subject"));
 	
-	window->priv->renderer_path = GITG_CELL_RENDERER_PATH(gtk_builder_get_object(builder, "rv_renderer_subject"));
-	gtk_tree_view_column_set_cell_data_func(col, GTK_CELL_RENDERER(window->priv->renderer_path), (GtkTreeCellDataFunc)on_renderer_path, window, NULL);
+	init_tree_view (window, builder);
 	
 	// Intialize branches
 	build_branches_combo(window, builder);
 
+	// Get menus ui
+	b = gitg_utils_new_builder("gitg-menus.xml");
+	window->priv->menus_ui_manager = GTK_UI_MANAGER(g_object_ref(gtk_builder_get_object(b, "uiman")));
+
+	gtk_builder_connect_signals (b, window);
+	g_object_unref (b);
+
 	// Create search entry
 	build_search_entry(window, builder);
 	
@@ -1247,3 +1314,237 @@ on_repository_properties(GtkAction *action, GitgWindow *window)
 {
 	gitg_repository_dialog_present (window);
 }
+
+static void
+update_merge_rebase (GitgWindow *window, GitgRef *ref)
+{
+	if (window->priv->merge_rebase_uid != 0)
+	{
+		gtk_ui_manager_remove_ui (window->priv->menus_ui_manager, 
+		                          window->priv->merge_rebase_uid);
+	}
+
+	GtkActionGroup *ac = window->priv->merge_rebase_action_group;
+	
+	if (ac)
+	{
+		GList *actions = gtk_action_group_list_actions (ac);
+		GList *item;
+		
+		for (item = actions; item; item = g_list_next (item))
+		{
+			gtk_action_group_remove_action (ac, (GtkAction *)item->data);
+		}
+		
+		g_list_free (actions);
+	}
+	
+	if (gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_BRANCH)
+	{
+		return;
+	}
+	
+	if (window->priv->merge_rebase_uid == 0)
+	{
+		window->priv->merge_rebase_uid = gtk_ui_manager_new_merge_id (window->priv->menus_ui_manager);
+	}
+	
+	if (ac == NULL)
+	{
+		ac = gtk_action_group_new ("GitgMergeRebaseActions");
+		window->priv->merge_rebase_action_group = ac;
+		gtk_ui_manager_insert_action_group (window->priv->menus_ui_manager,
+		                                    ac,
+		                                    0);
+	}
+	
+	GSList *refs = gitg_repository_get_refs (window->priv->repository);
+	GSList *item;
+	
+	for (item = refs; item; item = g_slist_next (item))
+	{
+		GitgRef *r = GITG_REF (item->data);
+		
+		if (gitg_ref_get_ref_type (r) == GITG_REF_TYPE_BRANCH && !gitg_ref_equal (r, ref))
+		{
+			gchar *rebase = g_strdup_printf ("Rebase%sAction", gitg_ref_get_shortname (r));
+			gchar *merge = g_strdup_printf ("Merge%sAction", gitg_ref_get_shortname (r));
+			
+			GtkAction *rebaseac = gtk_action_new (rebase, gitg_ref_get_shortname (r), NULL, NULL);
+			GtkAction *mergeac = gtk_action_new (merge, gitg_ref_get_shortname (r), NULL, NULL);
+
+			gtk_action_group_add_action (ac, rebaseac);
+			gtk_action_group_add_action (ac, mergeac);
+			
+			gchar *name = g_strconcat ("Rebase", gitg_ref_get_shortname (r), NULL);
+
+			gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
+			                       window->priv->merge_rebase_uid,
+			                       "/ui/revision_popup/Rebase/Placeholder",
+			                       name,
+			                       rebase,
+			                       GTK_UI_MANAGER_MENUITEM,
+			                       FALSE);
+			g_free (name);
+			
+			name = g_strconcat ("Merge", gitg_ref_get_shortname (r), NULL);
+
+			gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
+			                       window->priv->merge_rebase_uid,
+			                       "/ui/revision_popup/Merge/Placeholder",
+			                       name,
+			                       merge,
+			                       GTK_UI_MANAGER_MENUITEM,
+			                       FALSE);
+			g_free (name);
+
+			g_object_unref (rebaseac);
+			g_object_unref (mergeac);
+		}
+	}
+	
+	g_slist_foreach (refs, (GFunc)gitg_ref_free, NULL);
+	g_slist_free (refs);
+
+	gtk_ui_manager_ensure_update (window->priv->menus_ui_manager);
+}
+
+static gboolean
+has_local_ref (GitgWindow  *window,
+               gchar const *name)
+{
+	GSList *refs = gitg_repository_get_refs (window->priv->repository);
+	GSList *item;
+	gboolean ret = FALSE;
+	
+	for (item = refs; item; item = g_slist_next (item))
+	{
+		GitgRef *ref = GITG_REF (item->data);
+		
+		if (gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_BRANCH)
+		{
+			continue;
+		}
+		
+		gchar const *nm = gitg_ref_get_shortname (ref);
+		
+		if (g_strcmp0 (name, nm) == 0)
+		{
+			ret = TRUE;
+			break;
+		}
+	}
+	
+	g_slist_foreach (refs, (GFunc)gitg_ref_free, NULL);
+	g_slist_free (refs);
+	
+	return ret;
+}
+
+static gboolean
+popup_revision (GitgWindow *window, GdkEventButton *event)
+{
+	gint cell_x;
+	gint cell_y;
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+	
+	GtkTreeView *tree_view = window->priv->tree_view;
+
+	if (!gtk_tree_view_get_path_at_pos (tree_view,
+	                                    (gint)event->x,
+	                                    (gint)event->y,
+	                                    &path,
+	                                    &column,
+	                                    &cell_x,
+	                                    &cell_y))
+	{
+		return FALSE;
+	}
+	
+	GtkCellRenderer *cell = gitg_utils_find_cell_at_pos (tree_view, column, path, cell_x);
+	
+	if (!cell || !GITG_IS_CELL_RENDERER_PATH (cell))
+	{
+		return FALSE;
+	}
+	
+	GitgRef *ref = gitg_cell_renderer_path_get_ref_at_pos (GTK_WIDGET (tree_view),
+	                                                       GITG_CELL_RENDERER_PATH (cell),
+	                                                       cell_x,
+	                                                       NULL);
+	gtk_tree_path_free (path);
+	
+	if (!ref || (gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_BRANCH && 
+	             gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_REMOTE))
+	{
+		return FALSE;
+	}
+	
+	GtkWidget *popup = gtk_ui_manager_get_widget (window->priv->menus_ui_manager,
+	                                              "/ui/revision_popup");
+
+	GtkAction *checkout = gtk_ui_manager_get_action (window->priv->menus_ui_manager, "/ui/revision_popup/CheckoutAction");
+	GtkAction *remove = gtk_ui_manager_get_action (window->priv->menus_ui_manager, "/ui/revision_popup/RemoveAction");
+
+	if (gitg_ref_get_ref_type (ref) == GITG_REF_TYPE_REMOTE)
+	{
+		gchar *local = gitg_ref_get_local_name (ref);
+
+		if (!has_local_ref (window, local))
+		{
+			gchar *label = g_strdup_printf (_("New local branch <%s>"), local);
+		
+			gtk_action_set_label (checkout, label);
+			gtk_action_set_visible (checkout, TRUE);
+			g_free (label);
+		}
+		else
+		{
+			gtk_action_set_visible (checkout, FALSE);
+		}
+		
+		g_free (local);
+		gtk_action_set_label (remove, _("Remove remote branch"));
+	}
+	else if (gitg_ref_get_ref_type (ref) == GITG_REF_TYPE_BRANCH)
+	{
+		gtk_action_set_label (checkout, _("Checkout working copy"));
+		gtk_action_set_label (remove, _("Remove local branch"));
+		
+		GitgRef *working = gitg_repository_get_current_working_ref (window->priv->repository);
+
+		gtk_action_set_visible (checkout, !gitg_ref_equal (working, ref));		
+	}
+	
+	update_merge_rebase (window, ref);
+	window->priv->popup_ref = ref;
+
+	gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, window, event->button, event->time);
+	return TRUE;
+}
+
+gboolean
+on_tree_view_rv_button_press_event (GtkWidget *widget, GdkEventButton *event, GitgWindow *window)
+{
+	if (event->button == 3)
+	{
+		// Check to find a ref
+		return popup_revision (window, event);
+	}
+	
+	return FALSE;
+}
+
+void
+on_checkout_branch_action_activate (GtkAction *action, GitgWindow *window)
+{
+	gitg_branch_actions_checkout (window, window->priv->popup_ref);
+}
+
+
+void
+on_remove_branch_action_activate (GtkAction *action, GitgWindow *window)
+{
+	gitg_branch_actions_remove (window, window->priv->popup_ref);
+}
diff --git a/gitg/gitg-window.ui b/gitg/gitg-window.ui
index d4984a5..b37587d 100644
--- a/gitg/gitg-window.ui
+++ b/gitg/gitg-window.ui
@@ -1,25 +1,27 @@
 <?xml version="1.0"?>
 <interface>
+  <!-- interface-requires gtk+ 2.12 -->
+  <!-- interface-requires gitg 0.2 -->
+  <!-- interface-requires sourceview2 0.0 -->
+  <!-- interface-naming-policy toplevel-contextual -->
   <object class="GtkImage" id="image_commit">
     <property name="visible">True</property>
     <property name="stock">gtk-apply</property>
-    <property name="icon-size">4</property>
   </object>
   <object class="GtkAdjustment" id="adjustment_context">
+    <property name="value">3</property>
     <property name="lower">1</property>
     <property name="upper">10</property>
     <property name="step_increment">1</property>
     <property name="page_increment">1</property>
     <property name="page_size">1</property>
-    <property name="value">3</property>
   </object>
   <object class="GitgWindow" id="window">
     <property name="title" translatable="yes">gitg</property>
     <property name="default_width">800</property>
     <property name="default_height">800</property>
-    <property name="visible">False</property>
-    <signal name="set-focus" handler="on_window_set_focus"/>
-    <signal name="window-state-event" handler="on_window_state_event"/>
+    <signal name="set_focus" handler="on_window_set_focus"/>
+    <signal name="window_state_event" handler="on_window_state_event"/>
     <child>
       <object class="GtkVBox" id="vbox_main">
         <property name="visible">True</property>
@@ -29,7 +31,7 @@
             <property name="can_focus">True</property>
             <child>
               <object class="GtkVBox" id="vbox_history">
-              <property name="visible">True</property>
+                <property name="visible">True</property>
                 <child>
                   <object class="GtkVPaned" id="vpaned_main">
                     <property name="visible">True</property>
@@ -48,6 +50,7 @@
                               </object>
                               <packing>
                                 <property name="expand">False</property>
+                                <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
@@ -67,12 +70,14 @@
                               </object>
                               <packing>
                                 <property name="expand">False</property>
+                                <property name="position">1</property>
                               </packing>
                             </child>
                           </object>
                           <packing>
                             <property name="expand">False</property>
                             <property name="padding">3</property>
+                            <property name="position">0</property>
                           </packing>
                         </child>
                         <child>
@@ -86,16 +91,16 @@
                               <object class="GtkTreeView" id="tree_view_rv">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="headers_clickable">True</property>
                                 <property name="rules_hint">True</property>
                                 <property name="search_column">1</property>
                                 <property name="fixed_height_mode">True</property>
+                                <signal name="button_press_event" handler="on_tree_view_rv_button_press_event"/>
                                 <child>
                                   <object class="GtkTreeViewColumn" id="rv_column_subject">
-                                    <property name="title" translatable="yes">Subject</property>
-                                    <property name="fixed-width">400</property>
-                                    <property name="sizing">fixed</property>
                                     <property name="resizable">True</property>
+                                    <property name="sizing">fixed</property>
+                                    <property name="fixed_width">400</property>
+                                    <property name="title">Subject</property>
                                     <property name="expand">True</property>
                                     <child>
                                       <object class="GitgCellRendererPath" id="rv_renderer_subject"/>
@@ -107,10 +112,10 @@
                                 </child>
                                 <child>
                                   <object class="GtkTreeViewColumn" id="rv_column2">
-                                    <property name="title" translatable="yes">Author</property>
-                                    <property name="fixed-width">200</property>
-                                    <property name="sizing">fixed</property>
                                     <property name="resizable">True</property>
+                                    <property name="sizing">fixed</property>
+                                    <property name="fixed_width">200</property>
+                                    <property name="title">Author</property>
                                     <child>
                                       <object class="GtkCellRendererText" id="rv_renderer_author"/>
                                       <attributes>
@@ -121,10 +126,10 @@
                                 </child>
                                 <child>
                                   <object class="GtkTreeViewColumn" id="rv_column3">
-                                    <property name="title" translatable="yes">Date</property>
-                                    <property name="fixed-width">200</property>
-                                    <property name="sizing">fixed</property>
                                     <property name="resizable">True</property>
+                                    <property name="sizing">fixed</property>
+                                    <property name="fixed_width">200</property>
+                                    <property name="title">Date</property>
                                     <child>
                                       <object class="GtkCellRendererText" id="rv_renderer_date"/>
                                       <attributes>
@@ -164,10 +169,15 @@
                                 <child>
                                   <object class="GtkTable" id="table_parents">
                                     <property name="visible">True</property>
-                                    <property name="n_rows">1</property>
                                     <property name="n_columns">2</property>
                                     <property name="column_spacing">3</property>
                                     <property name="row_spacing">2</property>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
                                   </object>
                                   <packing>
                                     <property name="left_attach">1</property>
@@ -228,7 +238,7 @@
                                   <packing>
                                     <property name="left_attach">1</property>
                                     <property name="right_attach">2</property>
-                                    <property name="y_options">fill</property>
+                                    <property name="y_options">GTK_FILL</property>
                                   </packing>
                                 </child>
                                 <child>
@@ -241,8 +251,8 @@
                                   <packing>
                                     <property name="top_attach">4</property>
                                     <property name="bottom_attach">5</property>
-                                    <property name="x_options">fill</property>
-                                    <property name="y_options">fill</property>
+                                    <property name="x_options">GTK_FILL</property>
+                                    <property name="y_options">GTK_FILL</property>
                                   </packing>
                                 </child>
                                 <child>
@@ -254,8 +264,8 @@
                                   <packing>
                                     <property name="top_attach">3</property>
                                     <property name="bottom_attach">4</property>
-                                    <property name="x_options">fill</property>
-                                    <property name="y_options">fill</property>
+                                    <property name="x_options">GTK_FILL</property>
+                                    <property name="y_options">GTK_FILL</property>
                                   </packing>
                                 </child>
                                 <child>
@@ -267,8 +277,8 @@
                                   <packing>
                                     <property name="top_attach">2</property>
                                     <property name="bottom_attach">3</property>
-                                    <property name="x_options">fill</property>
-                                    <property name="y_options">fill</property>
+                                    <property name="x_options">GTK_FILL</property>
+                                    <property name="y_options">GTK_FILL</property>
                                   </packing>
                                 </child>
                                 <child>
@@ -280,8 +290,8 @@
                                   <packing>
                                     <property name="top_attach">1</property>
                                     <property name="bottom_attach">2</property>
-                                    <property name="x_options">fill</property>
-                                    <property name="y_options">fill</property>
+                                    <property name="x_options">GTK_FILL</property>
+                                    <property name="y_options">GTK_FILL</property>
                                   </packing>
                                 </child>
                                 <child>
@@ -292,14 +302,15 @@
                                     <property name="use_markup">True</property>
                                   </object>
                                   <packing>
-                                    <property name="x_options">fill</property>
-                                    <property name="y_options">fill</property>
+                                    <property name="x_options">GTK_FILL</property>
+                                    <property name="y_options">GTK_FILL</property>
                                   </packing>
                                 </child>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
                                 <property name="padding">3</property>
+                                <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
@@ -330,10 +341,9 @@
                                         <property name="headers_visible">False</property>
                                         <child>
                                           <object class="GtkTreeViewColumn" id="revision_files_column_icon">
-                                            <property name="title" translatable="no">Icon</property>
-                                            <property name="resizable">False</property>
-                                            <property name="fixed-width">20</property>
                                             <property name="sizing">fixed</property>
+                                            <property name="fixed_width">20</property>
+                                            <property name="title">Icon</property>
                                             <child>
                                               <object class="GtkCellRendererPixbuf" id="revision_files_cell_renderer_icon"/>
                                             </child>
@@ -341,8 +351,7 @@
                                         </child>
                                         <child>
                                           <object class="GtkTreeViewColumn" id="revision_files_column_name">
-                                            <property name="title" translatable="no">Filename</property>
-                                            <property name="resizable">False</property>
+                                            <property name="title">Filename</property>
                                             <child>
                                               <object class="GtkCellRendererText" id="revision_files_cell_renderer_name"/>
                                             </child>
@@ -351,6 +360,10 @@
                                       </object>
                                     </child>
                                   </object>
+                                  <packing>
+                                    <property name="resize">False</property>
+                                    <property name="shrink">True</property>
+                                  </packing>
                                 </child>
                                 <child>
                                   <object class="GtkScrolledWindow" id="scrolled_window_details">
@@ -361,14 +374,17 @@
                                     <property name="shadow_type">etched-in</property>
                                     <child>
                                       <object class="GitgDiffView" id="revision_diff">
-                                      	<property name="tab-width">4</property>
-                                      	<property name="editable">False</property>
-                                      	<property name="cursor-visible">False</property>
-                                      	<property name="diff-enabled">True</property>
-                                      	<property name="show-line-numbers">True</property>
+                                        <property name="editable">False</property>
+                                        <property name="cursor_visible">False</property>
+                                        <property name="show_line_numbers">True</property>
+                                        <property name="tab_width">4</property>
                                       </object>
                                     </child>
                                   </object>
+                                  <packing>
+                                    <property name="resize">True</property>
+                                    <property name="shrink">True</property>
+                                  </packing>
                                 </child>
                               </object>
                               <packing>
@@ -402,10 +418,10 @@
                                   <object class="GtkTreeView" id="revision_tree">
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
-                                    <property name="headers-visible">False</property>
+                                    <property name="headers_visible">False</property>
                                     <child>
                                       <object class="GtkTreeViewColumn" id="revision_tree_column">
-                                        <property name="title" translatable="yes">Filename</property>
+                                        <property name="title">Filename</property>
                                         <child>
                                           <object class="GtkCellRendererPixbuf" id="renderer_icon"/>
                                           <attributes>
@@ -438,7 +454,7 @@
                                 <child>
                                   <object class="GtkSourceView" id="revision_tree_contents">
                                     <property name="editable">False</property>
-                                    <property name="show-line-numbers">True</property>
+                                    <property name="show_line_numbers">True</property>
                                   </object>
                                 </child>
                               </object>
@@ -448,6 +464,9 @@
                               </packing>
                             </child>
                           </object>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
                         </child>
                         <child type="tab">
                           <object class="GtkLabel" id="label2">
@@ -466,6 +485,9 @@
                       </packing>
                     </child>
                   </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
                 </child>
               </object>
             </child>
@@ -515,10 +537,8 @@
                             <property name="headers_visible">False</property>
                             <child>
                               <object class="GtkTreeViewColumn" id="unstaged_column_icon">
-                                <property name="title" translatable="no"></property>
-                                <property name="resizable">False</property>
-                                <property name="fixed-width">20</property>
                                 <property name="sizing">fixed</property>
+                                <property name="fixed_width">20</property>
                                 <child>
                                   <object class="GtkCellRendererPixbuf" id="unstaged_cell_renderer_icon"/>
                                 </child>
@@ -526,8 +546,8 @@
                             </child>
                             <child>
                               <object class="GtkTreeViewColumn" id="unstaged_column_name">
-                                <property name="title" translatable="yes">Unstaged</property>
                                 <property name="resizable">True</property>
+                                <property name="title">Unstaged</property>
                                 <child>
                                   <object class="GtkCellRendererText" id="unstaged_cell_renderer"/>
                                   <attributes>
@@ -570,10 +590,8 @@
                             <property name="headers_visible">False</property>
                             <child>
                               <object class="GtkTreeViewColumn" id="staged_column_icon">
-                                <property name="title" translatable="no"></property>
-                                <property name="resizable">False</property>
-                                <property name="fixed-width">20</property>
                                 <property name="sizing">fixed</property>
+                                <property name="fixed_width">20</property>
                                 <child>
                                   <object class="GtkCellRendererPixbuf" id="staged_cell_renderer_icon"/>
                                 </child>
@@ -581,7 +599,6 @@
                             </child>
                             <child>
                               <object class="GtkTreeViewColumn" id="staged_column_name">
-                                <property name="title" translatable="no"></property>
                                 <property name="resizable">True</property>
                                 <child>
                                   <object class="GtkCellRendererText" id="staged_cell_renderer_name"/>
@@ -632,32 +649,33 @@
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHScale" id="hscale_context">
-                                <property name="value-pos">right</property>
-                                <property name="digits">0</property>
-                                <property name="adjustment">adjustment_context</property>
-                                <property name="width-request">200</property>
-                                <property name="sensitive">False</property>
-                                <property name="show-fill-level">False</property>
+                              <object class="GtkLabel" id="label_context">
+                                <property name="label" translatable="yes">Context:</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="pack-type">end</property>
+                                <property name="pack_type">end</property>
+                                <property name="position">2</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkLabel" id="label_context">
-                                <property name="label" translatable="yes">Context:</property>
+                              <object class="GtkHScale" id="hscale_context">
+                                <property name="width_request">200</property>
+                                <property name="sensitive">False</property>
+                                <property name="adjustment">adjustment_context</property>
+                                <property name="digits">0</property>
+                                <property name="value_pos">right</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
-                                <property name="pack-type">end</property>
+                                <property name="pack_type">end</property>
+                                <property name="position">1</property>
                               </packing>
                             </child>
                           </object>
                           <packing>
                             <property name="expand">False</property>
+                            <property name="position">0</property>
                           </packing>
                         </child>
                         <child>
@@ -669,10 +687,10 @@
                             <property name="shadow_type">etched-in</property>
                             <child>
                               <object class="GitgDiffView" id="source_view_changes">
-                                <property name="tab-width">4</property>
                                 <property name="editable">False</property>
-                                <property name="cursor-visible">False</property>
-                                <property name="show-line-numbers">True</property>
+                                <property name="cursor_visible">False</property>
+                                <property name="show_line_numbers">True</property>
+                                <property name="tab_width">4</property>
                               </object>
                             </child>
                           </object>
@@ -728,6 +746,18 @@
                             <property name="visible">True</property>
                             <property name="spacing">3</property>
                             <child>
+                              <object class="GtkCheckButton" id="check_button_signed_off_by">
+                                <property name="label" translatable="yes">Add signed-off-by</property>
+                                <property name="can_focus">False</property>
+                                <property name="receives_default">False</property>
+                                <property name="draw_indicator">False</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
                               <object class="GtkButton" id="button_commit">
                                 <property name="label" translatable="yes">Commit</property>
                                 <property name="visible">True</property>
@@ -736,19 +766,9 @@
                                 <property name="image">image_commit</property>
                               </object>
                               <packing>
+                                <property name="expand">False</property>
+                                <property name="pack_type">end</property>
                                 <property name="position">0</property>
-                                <property name="pack-type">end</property>
-                                <property name="expand">false</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkCheckButton" id="check_button_signed_off_by">
-                                <property name="visible">true</property>
-                                <property name="label" translatable="yes">Add signed-off-by</property>
-                              </object>
-                              <packing>
-                                <property name="pack-type">start</property>
-                                <property name="expand">false</property>
                               </packing>
                             </child>
                           </object>
@@ -770,6 +790,9 @@
                   </packing>
                 </child>
               </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
             </child>
             <child type="tab">
               <object class="GtkLabel" id="label_commit">
@@ -783,7 +806,6 @@
             </child>
           </object>
           <packing>
-            <property name="expand">True</property>
             <property name="position">1</property>
           </packing>
         </child>
@@ -801,5 +823,3 @@
     </child>
   </object>
 </interface>
-
-<!-- vi:ts=2:et -->



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]