[gitg] Basic start of adding DND and context menus for refs in the revision view
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: svn-commits-list gnome org
- Subject: [gitg] Basic start of adding DND and context menus for refs in the revision view
- Date: Sun, 5 Jul 2009 01:13:14 +0000 (UTC)
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]