[gitg] Implemented better uri parsing and panel activating



commit 89922aeb0378ef5b145a0d92d2df3945139c3e51
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Sun Jun 6 23:18:50 2010 +0200

    Implemented better uri parsing and panel activating

 gitg/Makefile.am                   |    4 +
 gitg/gitg-activatable.c            |   48 +++++++++
 gitg/gitg-activatable.h            |   33 +++++++
 gitg/gitg-revision-changes-panel.c |  108 +++++++++++++++++++++-
 gitg/gitg-revision-details-panel.c |    7 ++
 gitg/gitg-revision-files-panel.c   |    7 ++
 gitg/gitg-revision-panel.c         |   15 +++
 gitg/gitg-revision-panel.h         |    2 +
 gitg/gitg-uri.c                    |  103 ++++++++++++++++++++
 gitg/gitg-uri.h                    |   17 ++++
 gitg/gitg-window.c                 |  185 +++++++++++++++++++++++-------------
 gitg/gitg-window.h                 |    3 +
 gitg/gitg.c                        |   34 +++++++-
 13 files changed, 499 insertions(+), 67 deletions(-)
---
diff --git a/gitg/Makefile.am b/gitg/Makefile.am
index b063236..7ffb604 100644
--- a/gitg/Makefile.am
+++ b/gitg/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS =							\
 	-DGITG_LOCALEDIR=\""$(datadir)/locale"\"
 
 NOINST_H_FILES = 			\
+	gitg-activatable.h		\
 	gitg-branch-actions.h		\
 	gitg-cell-renderer-path.h	\
 	gitg-commit-view.h		\
@@ -30,6 +31,7 @@ NOINST_H_FILES = 			\
 	gitg-revision-changes-panel.h	\
 	gitg-settings.h			\
 	gitg-stat-view.h		\
+	gitg-uri.h			\
 	gitg-utils.h			\
 	gitg-window.h			\
 	gseal-gtk-compat.h
@@ -37,6 +39,7 @@ NOINST_H_FILES = 			\
 gitg_SOURCES = 				\
 	$(BUILT_SOURCES)		\
 	gitg.c				\
+	gitg-activatable.c		\
 	gitg-branch-actions.c		\
 	gitg-cell-renderer-path.c	\
 	gitg-commit-view.c		\
@@ -55,6 +58,7 @@ gitg_SOURCES = 				\
 	gitg-revision-changes-panel.c	\
 	gitg-settings.c			\
 	gitg-stat-view.c		\
+	gitg-uri.c			\
 	gitg-utils.c			\
 	gitg-window.c			\
 	$(NOINST_H_FILES)
diff --git a/gitg/gitg-activatable.c b/gitg/gitg-activatable.c
new file mode 100644
index 0000000..644aaee
--- /dev/null
+++ b/gitg/gitg-activatable.c
@@ -0,0 +1,48 @@
+#include "gitg-activatable.h"
+
+G_DEFINE_INTERFACE (GitgActivatable, gitg_activatable, G_TYPE_INVALID)
+
+/* Default implementation */
+static gchar *
+gitg_activatable_get_id_default (GitgActivatable *panel)
+{
+	g_return_val_if_reached (NULL);
+}
+
+static gboolean
+gitg_activatable_activate_default (GitgActivatable *panel,
+                                      gchar const       *cmd)
+{
+	return FALSE;
+}
+
+static void
+gitg_activatable_default_init (GitgActivatableInterface *iface)
+{
+	static gboolean initialized = FALSE;
+
+	iface->get_id = gitg_activatable_get_id_default;
+	iface->activate = gitg_activatable_activate_default;
+
+	if (!initialized)
+	{
+		initialized = TRUE;
+	}
+}
+
+gchar *
+gitg_activatable_get_id (GitgActivatable *panel)
+{
+	g_return_val_if_fail (GITG_IS_ACTIVATABLE (panel), NULL);
+
+	return GITG_ACTIVATABLE_GET_INTERFACE (panel)->get_id (panel);
+}
+
+gboolean
+gitg_activatable_activate (GitgActivatable *panel,
+                           gchar const     *action)
+{
+	g_return_val_if_fail (GITG_IS_ACTIVATABLE (panel), FALSE);
+
+	return GITG_ACTIVATABLE_GET_INTERFACE (panel)->activate (panel, action);
+}
diff --git a/gitg/gitg-activatable.h b/gitg/gitg-activatable.h
new file mode 100644
index 0000000..d5cd62a
--- /dev/null
+++ b/gitg/gitg-activatable.h
@@ -0,0 +1,33 @@
+#ifndef __GITG_ACTIVATABLE_H__
+#define __GITG_ACTIVATABLE_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GITG_TYPE_ACTIVATABLE			(gitg_activatable_get_type ())
+#define GITG_ACTIVATABLE(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_ACTIVATABLE, GitgActivatable))
+#define GITG_IS_ACTIVATABLE(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_ACTIVATABLE))
+#define GITG_ACTIVATABLE_GET_INTERFACE(obj)	(G_TYPE_INSTANCE_GET_INTERFACE ((obj), GITG_TYPE_ACTIVATABLE, GitgActivatableInterface))
+
+typedef struct _GitgActivatable			GitgActivatable;
+typedef struct _GitgActivatableInterface	GitgActivatableInterface;
+
+struct _GitgActivatableInterface
+{
+	GTypeInterface parent;
+
+	gchar     *(*get_id)    (GitgActivatable *panel);
+	gboolean   (*activate)  (GitgActivatable *panel,
+	                         gchar const     *cmd);
+};
+
+GType gitg_activatable_get_type (void) G_GNUC_CONST;
+
+gchar     *gitg_activatable_get_id    (GitgActivatable *panel);
+gboolean   gitg_activatable_activate  (GitgActivatable *panel,
+                                       gchar const     *action);
+
+G_END_DECLS
+
+#endif /* __GITG_ACTIVATABLE_H__ */
diff --git a/gitg/gitg-revision-changes-panel.c b/gitg/gitg-revision-changes-panel.c
index 681adaa..bf58635 100644
--- a/gitg/gitg-revision-changes-panel.c
+++ b/gitg/gitg-revision-changes-panel.c
@@ -13,6 +13,7 @@
 #include <glib/gi18n.h>
 
 #include "gitg-revision-panel.h"
+#include "gitg-activatable.h"
 
 #define GITG_REVISION_CHANGES_PANEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_REVISION_CHANGES_PANEL, GitgRevisionChangesPanelPrivate))
 
@@ -31,6 +32,8 @@ struct _GitgRevisionChangesPanelPrivate
 	GitgRepository *repository;
 	GitgRevision *revision;
 	GSList *cached_headers;
+
+	gchar *selection;
 };
 
 typedef enum
@@ -60,6 +63,8 @@ typedef struct
 } DiffFile;
 
 static void gitg_revision_panel_iface_init (GitgRevisionPanelInterface *iface);
+static void gitg_activatable_iface_init (GitgActivatableInterface *iface);
+
 static void on_header_added (GitgDiffView *view, GitgDiffIter *iter, GitgRevisionChangesPanel *self);
 static void on_diff_files_selection_changed (GtkTreeSelection *selection, GitgRevisionChangesPanel *self);
 
@@ -68,7 +73,9 @@ G_DEFINE_TYPE_EXTENDED (GitgRevisionChangesPanel,
                         G_TYPE_OBJECT,
                         0,
                         G_IMPLEMENT_INTERFACE (GITG_TYPE_REVISION_PANEL,
-                                               gitg_revision_panel_iface_init));
+                                               gitg_revision_panel_iface_init);
+                        G_IMPLEMENT_INTERFACE (GITG_TYPE_ACTIVATABLE,
+                                               gitg_activatable_iface_init));
 
 static void set_revision (GitgRevisionChangesPanel *panel,
                           GitgRepository           *repository,
@@ -271,6 +278,24 @@ gitg_revision_panel_get_label_impl (GitgRevisionPanel *panel)
 	return g_strdup (_("Changes"));
 }
 
+static gchar *
+revision_panel_get_id (void)
+{
+	return g_strdup ("changes");
+}
+
+static gchar *
+gitg_revision_panel_get_id_impl (GitgRevisionPanel *panel)
+{
+	return revision_panel_get_id ();
+}
+
+static gchar *
+gitg_activatable_get_id_impl (GitgActivatable *activatable)
+{
+	return revision_panel_get_id ();
+}
+
 static void
 initialize_ui (GitgRevisionChangesPanel *changes_panel)
 {
@@ -385,15 +410,81 @@ gitg_revision_panel_get_panel_impl (GitgRevisionPanel *panel)
 	return ret;
 }
 
+static gboolean
+select_diff_file (GitgRevisionChangesPanel *changes_panel,
+                  gchar const              *filename)
+{
+	GtkTreeModel *store;
+	GtkTreeIter iter;
+
+	store = gtk_tree_view_get_model (changes_panel->priv->diff_files);
+
+	if (!gtk_tree_model_get_iter_first (store, &iter))
+	{
+		return FALSE;
+	}
+
+	do
+	{
+		DiffFile *file;
+
+		gtk_tree_model_get (store, &iter, 0, &file, -1);
+
+		if (g_strcmp0 (file->filename, filename) == 0)
+		{
+			GtkTreeSelection *selection;
+
+			selection = gtk_tree_view_get_selection (changes_panel->priv->diff_files);
+
+			gtk_tree_selection_unselect_all (selection);
+			gtk_tree_selection_select_iter (selection, &iter);
+
+			diff_file_unref (file);
+			return TRUE;
+		}
+
+		diff_file_unref (file);
+	} while (gtk_tree_model_iter_next (store, &iter));
+
+	return FALSE;
+}
+
+static gboolean
+gitg_activatable_activate_impl (GitgActivatable *activatable,
+                                gchar const     *action)
+{
+	GitgRevisionChangesPanel *changes_panel;
+
+	changes_panel = GITG_REVISION_CHANGES_PANEL (activatable);
+
+	if (select_diff_file (changes_panel, action))
+	{
+		return TRUE;
+	}
+
+	g_free (changes_panel->priv->selection);
+	changes_panel->priv->selection = g_strdup (action);
+
+	return TRUE;
+}
+
 static void
 gitg_revision_panel_iface_init (GitgRevisionPanelInterface *iface)
 {
+	iface->get_id = gitg_revision_panel_get_id_impl;
 	iface->update = gitg_revision_panel_update_impl;
 	iface->get_label = gitg_revision_panel_get_label_impl;
 	iface->get_panel = gitg_revision_panel_get_panel_impl;
 }
 
 static void
+gitg_activatable_iface_init (GitgActivatableInterface *iface)
+{
+	iface->get_id = gitg_activatable_get_id_impl;
+	iface->activate = gitg_activatable_activate_impl;
+}
+
+static void
 free_cached_header (gpointer header)
 {
 	g_slice_free (CachedHeader, header);
@@ -444,6 +535,13 @@ gitg_revision_changes_panel_dispose (GObject *object)
 	if (changes_panel->priv->builder)
 	{
 		g_object_unref (changes_panel->priv->builder);
+		changes_panel->priv->builder = NULL;
+	}
+
+	if (changes_panel->priv->selection)
+	{
+		g_free (changes_panel->priv->selection);
+		changes_panel->priv->selection = NULL;
 	}
 
 	G_OBJECT_CLASS (gitg_revision_changes_panel_parent_class)->dispose (object);
@@ -611,6 +709,14 @@ on_diff_files_end_loading (GitgRunner               *runner,
 {
 	gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET(self->priv->diff_files)),
 	                       NULL);
+
+	if (self->priv->selection)
+	{
+		select_diff_file (self, self->priv->selection);
+
+		g_free (self->priv->selection);
+		self->priv->selection = NULL;
+	}
 }
 
 static gboolean
diff --git a/gitg/gitg-revision-details-panel.c b/gitg/gitg-revision-details-panel.c
index 982d78e..0d0eb5f 100644
--- a/gitg/gitg-revision-details-panel.c
+++ b/gitg/gitg-revision-details-panel.c
@@ -101,6 +101,12 @@ gitg_revision_panel_update_impl (GitgRevisionPanel *panel,
 }
 
 static gchar *
+gitg_revision_panel_get_id_impl (GitgRevisionPanel *panel)
+{
+	return g_strdup ("details");
+}
+
+static gchar *
 gitg_revision_panel_get_label_impl (GitgRevisionPanel *panel)
 {
 	return g_strdup (_("Details"));
@@ -162,6 +168,7 @@ gitg_revision_panel_get_panel_impl (GitgRevisionPanel *panel)
 static void
 gitg_revision_panel_iface_init (GitgRevisionPanelInterface *iface)
 {
+	iface->get_id = gitg_revision_panel_get_id_impl;
 	iface->update = gitg_revision_panel_update_impl;
 	iface->get_label = gitg_revision_panel_get_label_impl;
 	iface->get_panel = gitg_revision_panel_get_panel_impl;
diff --git a/gitg/gitg-revision-files-panel.c b/gitg/gitg-revision-files-panel.c
index e195214..985cd1c 100644
--- a/gitg/gitg-revision-files-panel.c
+++ b/gitg/gitg-revision-files-panel.c
@@ -589,6 +589,12 @@ gitg_revision_panel_update_impl (GitgRevisionPanel *panel,
 }
 
 static gchar *
+gitg_revision_panel_get_id_impl (GitgRevisionPanel *panel)
+{
+	return g_strdup ("files");
+}
+
+static gchar *
 gitg_revision_panel_get_label_impl (GitgRevisionPanel *panel)
 {
 	return g_strdup (_("Files"));
@@ -620,6 +626,7 @@ gitg_revision_panel_get_panel_impl (GitgRevisionPanel *panel)
 static void
 gitg_revision_panel_iface_init (GitgRevisionPanelInterface *iface)
 {
+	iface->get_id = gitg_revision_panel_get_id_impl;
 	iface->update = gitg_revision_panel_update_impl;
 	iface->get_label = gitg_revision_panel_get_label_impl;
 	iface->get_panel = gitg_revision_panel_get_panel_impl;
diff --git a/gitg/gitg-revision-panel.c b/gitg/gitg-revision-panel.c
index e575be2..4a0a5a2 100644
--- a/gitg/gitg-revision-panel.c
+++ b/gitg/gitg-revision-panel.c
@@ -4,6 +4,12 @@ G_DEFINE_INTERFACE (GitgRevisionPanel, gitg_revision_panel, G_TYPE_INVALID)
 
 /* Default implementation */
 static gchar *
+gitg_revision_panel_get_id_default (GitgRevisionPanel *panel)
+{
+	g_return_val_if_reached (NULL);
+}
+
+static gchar *
 gitg_revision_panel_get_label_default (GitgRevisionPanel *panel)
 {
 	g_return_val_if_reached (NULL);
@@ -28,6 +34,7 @@ gitg_revision_panel_default_init (GitgRevisionPanelInterface *iface)
 {
 	static gboolean initialized = FALSE;
 
+	iface->get_id = gitg_revision_panel_get_id_default;
 	iface->get_label = gitg_revision_panel_get_label_default;
 	iface->get_panel = gitg_revision_panel_get_panel_default;
 	iface->update = gitg_revision_panel_update_default;
@@ -39,6 +46,14 @@ gitg_revision_panel_default_init (GitgRevisionPanelInterface *iface)
 }
 
 gchar *
+gitg_revision_panel_get_id (GitgRevisionPanel *panel)
+{
+	g_return_val_if_fail (GITG_IS_REVISION_PANEL (panel), NULL);
+
+	return GITG_REVISION_PANEL_GET_INTERFACE (panel)->get_id (panel);
+}
+
+gchar *
 gitg_revision_panel_get_label (GitgRevisionPanel *panel)
 {
 	g_return_val_if_fail (GITG_IS_REVISION_PANEL (panel), NULL);
diff --git a/gitg/gitg-revision-panel.h b/gitg/gitg-revision-panel.h
index d0a7c10..5a100a2 100644
--- a/gitg/gitg-revision-panel.h
+++ b/gitg/gitg-revision-panel.h
@@ -23,12 +23,14 @@ struct _GitgRevisionPanelInterface
 	                         GitgRevision      *revision);
 
 	gchar     *(*get_label) (GitgRevisionPanel *panel);
+	gchar     *(*get_id)    (GitgRevisionPanel *panel);
 	GtkWidget *(*get_panel) (GitgRevisionPanel *panel);
 };
 
 GType gitg_revision_panel_get_type (void) G_GNUC_CONST;
 
 GtkWidget *gitg_revision_panel_get_panel (GitgRevisionPanel *panel);
+gchar     *gitg_revision_panel_get_id    (GitgRevisionPanel *panel);
 gchar     *gitg_revision_panel_get_label (GitgRevisionPanel *panel);
 void       gitg_revision_panel_update    (GitgRevisionPanel *panel,
                                           GitgRepository    *repository,
diff --git a/gitg/gitg-uri.c b/gitg/gitg-uri.c
new file mode 100644
index 0000000..74717c3
--- /dev/null
+++ b/gitg/gitg-uri.c
@@ -0,0 +1,103 @@
+#include "gitg-uri.h"
+
+#include <string.h>
+
+gboolean
+gitg_uri_parse (gchar const  *uri,
+                gchar       **work_tree,
+                gchar       **selection,
+                gchar       **activatable,
+                gchar       **action)
+{
+	gchar *selection_sep;
+	gchar *activatable_sep;
+	gchar *action_sep;
+	gchar *dupped;
+
+	if (uri == NULL)
+	{
+		return FALSE;
+	}
+
+	if (!g_str_has_prefix (uri, "gitg://"))
+	{
+		return FALSE;
+	}
+
+	if (work_tree)
+	{
+		*work_tree = NULL;
+	}
+
+	if (selection)
+	{
+		*selection = NULL;
+	}
+
+	if (activatable)
+	{
+		*activatable = NULL;
+	}
+
+	if (action)
+	{
+		*action = NULL;
+	}
+
+	dupped = g_strdup (uri + 7);
+	selection_sep = strchr (dupped, ':');
+
+	if (selection_sep)
+	{
+		*selection_sep = '\0';
+	}
+
+	if (work_tree)
+	{
+		*work_tree = g_strdup (dupped);
+	}
+
+	if (!selection_sep)
+	{
+		g_free (dupped);
+		return TRUE;
+	}
+
+	activatable_sep = strchr (selection_sep + 1, '/');
+
+	if (activatable_sep)
+	{
+		*activatable_sep = '\0';
+	}
+
+	if (selection)
+	{
+		*selection = g_strdup (selection_sep + 1);
+	}
+
+	if (!activatable_sep)
+	{
+		g_free (dupped);
+		return TRUE;
+	}
+
+	action_sep = strchr (activatable_sep + 1, '/');
+
+	if (action_sep)
+	{
+		*action_sep = '\0';
+	}
+
+	if (activatable)
+	{
+		*activatable = g_strdup (activatable_sep + 1);
+	}
+
+	if (action_sep && action)
+	{
+		*action = g_strdup (action_sep + 1);
+	}
+
+	g_free (dupped);
+	return TRUE;
+}
diff --git a/gitg/gitg-uri.h b/gitg/gitg-uri.h
new file mode 100644
index 0000000..90001c3
--- /dev/null
+++ b/gitg/gitg-uri.h
@@ -0,0 +1,17 @@
+#ifndef __GITG_URI_H__
+#define __GITG_URI_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+gboolean gitg_uri_parse (gchar const  *uri,
+                         gchar       **work_tree,
+                         gchar       **selection,
+                         gchar       **activatable,
+                         gchar       **action);
+
+G_END_DECLS
+
+#endif /* __GITG_URI_H__ */
+
diff --git a/gitg/gitg-window.c b/gitg/gitg-window.c
index 855d94a..1ac3b19 100644
--- a/gitg/gitg-window.c
+++ b/gitg/gitg-window.c
@@ -47,6 +47,8 @@
 #include "gitg-revision-details-panel.h"
 #include "gitg-revision-changes-panel.h"
 #include "gitg-revision-files-panel.h"
+#include "gitg-activatable.h"
+#include "gitg-uri.h"
 
 #define DYNAMIC_ACTION_DATA_KEY "GitgDynamicActionDataKey"
 #define DYNAMIC_ACTION_DATA_REMOTE_KEY "GitgDynamicActionDataRemoteKey"
@@ -105,6 +107,7 @@ struct _GitgWindowPrivate
 	GitgHash select_on_load;
 
 	GSList *revision_panels;
+	GSList *activatables;
 };
 
 static gboolean on_tree_view_motion (GtkTreeView *treeview,
@@ -251,6 +254,12 @@ add_revision_panel (GitgWindow *window,
 	window->priv->revision_panels = g_slist_append (window->priv->revision_panels,
 	                                                panel);
 
+	if (GITG_IS_ACTIVATABLE (panel))
+	{
+		window->priv->activatables = g_slist_append (window->priv->activatables,
+		                                             g_object_ref (panel));
+	}
+
 	label = gitg_revision_panel_get_label (panel);
 	label_widget = gtk_label_new (label);
 	gtk_widget_show (label_widget);
@@ -478,7 +487,7 @@ build_search_entry (GitgWindow *window,
 	gtk_window_add_accel_group (GTK_WINDOW(window), group);
 }
 
-static void
+static gboolean
 goto_hash (GitgWindow  *window,
            gchar const *hash)
 {
@@ -486,7 +495,7 @@ goto_hash (GitgWindow  *window,
 
 	if (!gitg_repository_find_by_hash (window->priv->repository, hash, &iter))
 	{
-		return;
+		return FALSE;
 	}
 
 	gtk_tree_selection_select_iter (gtk_tree_view_get_selection (window->priv->tree_view),
@@ -503,6 +512,8 @@ goto_hash (GitgWindow  *window,
 	                              0.5,
 	                              0);
 	gtk_tree_path_free (path);
+
+	return TRUE;
 }
 
 static void
@@ -1068,7 +1079,12 @@ gitg_window_destroy (GtkObject *object)
 		g_slist_foreach (window->priv->revision_panels, (GFunc)g_object_unref, NULL);
 		g_slist_free (window->priv->revision_panels);
 
+		g_slist_foreach (window->priv->activatables, (GFunc)g_object_unref, NULL);
+		g_slist_free (window->priv->activatables);
+
 		window->priv->revision_panels = NULL;
+		window->priv->activatables = NULL;
+
 		window->priv->destroy_has_run = TRUE;
 	}
 
@@ -1230,65 +1246,6 @@ gitg_window_set_select_on_load (GitgWindow  *window,
 }
 
 static gboolean
-parse_gitg_uri (GFile  *file,
-                GFile **work_tree,
-                gchar **selection)
-{
-	if (selection)
-	{
-		*selection = NULL;
-	}
-
-	if (work_tree)
-	{
-		*work_tree = NULL;
-	}
-
-	if (!g_file_has_uri_scheme (file, "gitg"))
-	{
-		return FALSE;
-	}
-
-	/* Extract path and sha information */
-	gchar *uri = g_file_get_uri (file);
-	gchar *fd = strrchr (uri, ':');
-	gchar *sel = NULL;
-	gint pos = 0;
-
-	if (fd)
-	{
-		sel = strchr (fd, '/');
-
-		if (sel)
-		{
-			*sel = '\0';
-			sel += 1;
-		}
-
-		pos = fd - uri;
-	}
-
-	if (pos > 5 && strlen (uri) - pos - 1 <= 40)
-	{
-		/* It has a sha */
-		*fd = '\0';
-
-		if (selection)
-		{
-			*selection = g_strdup (fd + 1);
-		}
-	}
-
-	if (work_tree)
-	{
-		*work_tree = g_file_new_for_path (uri + 7);
-	}
-
-	g_free (uri);
-	return TRUE;
-}
-
-static gboolean
 convert_setting_to_inactive_max (GValue const *setting,
                                  GValue       *value,
                                  gpointer      userdata)
@@ -1770,6 +1727,22 @@ update_sensitivity (GitgWindow *window)
 	gtk_action_group_set_sensitive (window->priv->repository_group, sens);
 }
 
+gboolean
+gitg_window_select (GitgWindow  *window,
+                    gchar const *selection)
+{
+	g_return_val_if_fail (GITG_IS_WINDOW (window), FALSE);
+
+	gitg_window_set_select_on_load (window, selection);
+
+	if (!window->priv->repository)
+	{
+		return FALSE;
+	}
+
+	return goto_hash (window, window->priv->select_on_load);
+}
+
 static gboolean
 load_repository (GitgWindow   *window,
                  GFile        *git_dir,
@@ -1845,6 +1818,67 @@ load_repository (GitgWindow   *window,
 	return window->priv->repository != NULL;
 }
 
+static gboolean
+activate_activatable (GitgWindow      *window,
+                      GitgActivatable *activatable,
+                      gchar const     *action)
+{
+	if (!gitg_activatable_activate (activatable, action))
+	{
+		return FALSE;
+	}
+
+	if (GITG_IS_REVISION_PANEL (activatable))
+	{
+		GtkWidget *page;
+		GitgRevisionPanel *panel;
+		gint nth;
+
+		panel = GITG_REVISION_PANEL (activatable);
+		page = gitg_revision_panel_get_panel (panel);
+
+		nth = gtk_notebook_page_num (window->priv->notebook_revision,
+		                             page);
+
+		if (nth >= 0)
+		{
+			gtk_notebook_set_current_page (window->priv->notebook_revision,
+			                               nth);
+		}
+	}
+
+	return TRUE;
+}
+
+gboolean
+gitg_window_activate (GitgWindow  *window,
+                      gchar const *activatable,
+                      gchar const *action)
+{
+	GSList *item;
+
+	g_return_val_if_fail (GITG_IS_WINDOW (window), FALSE);
+	g_return_val_if_fail (activatable != NULL, FALSE);
+
+	for (item = window->priv->activatables; item; item = g_slist_next (item))
+	{
+		GitgActivatable *act = item->data;
+		gchar *id;
+		gboolean match;
+
+		id = gitg_activatable_get_id (act);
+		match = g_strcmp0 (activatable, id) == 0;
+		g_free (id);
+
+		if (match)
+		{
+			return activate_activatable (window, act, action);
+		}
+	}
+
+	return FALSE;
+}
+
 gboolean
 gitg_window_load_repository (GitgWindow   *window,
                              GFile        *git_dir,
@@ -1907,13 +1941,27 @@ load_repository_for_command_line (GitgWindow   *window,
 
 	if (argc > 0)
 	{
-		GFile *first_arg = g_file_new_for_commandline_arg (argv[0]);
-		gchar *sel;
+		GFile *first_arg;
+		gchar *uri;
+		gchar *sel = NULL;
+		gchar *work_tree_path = NULL;
+		gchar *activatable = NULL;
+		gchar *action = NULL;
+
+		first_arg = g_file_new_for_commandline_arg (argv[0]);
+		uri = g_file_get_uri (first_arg);
 
-		if (!parse_gitg_uri (first_arg, &work_tree, &sel))
+		if (!gitg_uri_parse (uri, &work_tree_path, &sel, &activatable, &action))
 		{
 			git_dir = find_dot_git (first_arg);
 		}
+		else
+		{
+			work_tree = g_file_new_for_path (work_tree_path);
+		}
+
+		g_free (uri);
+		g_object_unref (first_arg);
 
 		if (git_dir || (work_tree && g_file_query_exists (work_tree, NULL)))
 		{
@@ -1923,10 +1971,17 @@ load_repository_for_command_line (GitgWindow   *window,
 			                       argc - 1,
 			                       argv + 1,
 			                       selection ? selection : sel);
+
+			if (ret)
+			{
+				gitg_window_activate (window, activatable, action);
+			}
 		}
 
 		g_free (sel);
-		g_object_unref (first_arg);
+		g_free (activatable);
+		g_free (action);
+		g_free (work_tree_path);
 	}
 
 	if (!ret)
diff --git a/gitg/gitg-window.h b/gitg/gitg-window.h
index 8ae26ef..648f38e 100644
--- a/gitg/gitg-window.h
+++ b/gitg/gitg-window.h
@@ -76,6 +76,9 @@ void gitg_window_set_select_on_load (GitgWindow *window, gchar const *selection)
 
 gboolean gitg_window_add_branch_action (GitgWindow *window, GitgRunner *runner);
 
+gboolean gitg_window_select (GitgWindow *window, gchar const *selection);
+gboolean gitg_window_activate (GitgWindow *window, gchar const *activatable, gchar const *action);
+
 G_END_DECLS
 
 #endif /* __GITG_WINDOW_H__ */
diff --git a/gitg/gitg.c b/gitg/gitg.c
index 7070595..9b925ba 100644
--- a/gitg/gitg.c
+++ b/gitg/gitg.c
@@ -34,6 +34,7 @@
 #include "gitg-settings.h"
 #include "gitg-dirs.h"
 #include "gitg-utils.h"
+#include "gitg-uri.h"
 
 static gboolean commit_mode = FALSE;
 static gchar *select_sha1 = NULL;
@@ -173,15 +174,46 @@ link_button_uri_hook (GtkLinkButton *button,
                       GitgWindow    *window)
 {
 	GFile *file;
+	GitgRepository *repository;
 
 	file = g_file_new_for_uri (link_);
+	repository = gitg_window_get_repository (window);
 
 	if (!g_file_has_uri_scheme (file, "gitg"))
 	{
 		original_link_button_hook (button, link_, NULL);
 	}
-	else
+	else if (repository)
 	{
+		gchar *work_tree_path;
+		gchar *selection;
+		gchar *activatable;
+		gchar *action;
+
+		if (gitg_uri_parse (link_, &work_tree_path, &selection, &activatable, &action))
+		{
+			GFile *wt;
+			GFile *work_tree;
+			gboolean equal;
+
+			wt = gitg_repository_get_work_tree (repository);
+			work_tree = g_file_new_for_path (work_tree_path);
+			equal = g_file_equal (wt, work_tree);
+
+			g_object_unref (wt);
+			g_object_unref (work_tree);
+
+			if (equal)
+			{
+				gitg_window_select (window, selection);
+				gitg_window_activate (window, activatable, action);
+			}
+
+			g_free (work_tree_path);
+			g_free (selection);
+			g_free (activatable);
+			g_free (action);
+		}
 	}
 
 	g_object_unref (file);



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