[gitg] Added support for select commit on load



commit 36a4730e44db326a42a923993c81bf2b90b43815
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Sat Jan 9 20:18:10 2010 +0100

    Added support for select commit on load

 gitg/gitg-repository.c |   23 +++++++++-
 gitg/gitg-repository.h |    4 +-
 gitg/gitg-utils.c      |   36 ++++++++++++++-
 gitg/gitg-utils.h      |    4 ++
 gitg/gitg-window.c     |  112 ++++++++++++++++++++++++++++++++++++++++++-----
 gitg/gitg-window.h     |    2 +
 gitg/gitg.c            |   12 ++++-
 7 files changed, 175 insertions(+), 18 deletions(-)
---
diff --git a/gitg/gitg-repository.c b/gitg/gitg-repository.c
index ce8797e..d197a5d 100644
--- a/gitg/gitg-repository.c
+++ b/gitg/gitg-repository.c
@@ -55,6 +55,7 @@ enum
 enum
 {
 	LOAD,
+	LOADED,
 	LAST_SIGNAL
 };
 
@@ -550,7 +551,7 @@ gitg_repository_class_init(GitgRepositoryClass *klass)
 								      G_PARAM_READABLE));
 
 	repository_signals[LOAD] =
-   		g_signal_new ("load",
+		g_signal_new ("load",
 			      G_OBJECT_CLASS_TYPE (object_class),
 			      G_SIGNAL_RUN_LAST,
 			      G_STRUCT_OFFSET (GitgRepositoryClass, load),
@@ -559,6 +560,16 @@ gitg_repository_class_init(GitgRepositoryClass *klass)
 			      G_TYPE_NONE,
 			      0);
 
+	repository_signals[LOADED] =
+		g_signal_new ("loaded",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GitgRepositoryClass, loaded),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE,
+			      0);
+
 	g_type_class_add_private(object_class, sizeof(GitgRepositoryPrivate));
 }
 
@@ -649,6 +660,8 @@ on_loader_end_loading(GitgRunner *object, gboolean cancelled, GitgRepository *re
 			gitg_repository_run_command(repository, object, (gchar const **)repository->priv->last_args, NULL);
 
 		break;
+		case LOAD_STAGE_LAST:
+			g_signal_emit (repository, repository_signals[LOADED], 0);
 		default:
 		break;
 	}
@@ -1570,3 +1583,11 @@ gitg_repository_get_remotes (GitgRepository *repository)
 	g_object_unref (config);
 	return remotes;
 }
+
+gboolean
+gitg_repository_get_loaded (GitgRepository *repository)
+{
+	g_return_val_if_fail (GITG_IS_REPOSITORY (repository), FALSE);
+	return repository->priv->load_stage == LOAD_STAGE_LAST &&
+	       !gitg_runner_running (repository->priv->loader);
+}
diff --git a/gitg/gitg-repository.h b/gitg/gitg-repository.h
index ab7ff30..ab55b9c 100644
--- a/gitg/gitg-repository.h
+++ b/gitg/gitg-repository.h
@@ -59,7 +59,8 @@ struct _GitgRepositoryClass
 {
 	GObjectClass parent_class;
 
-	void (*load) (GitgRepository *);
+	void (*load) (GitgRepository *repository);
+	void (*loaded) (GitgRepository *repository);
 };
 
 GType gitg_repository_get_type (void) G_GNUC_CONST;
@@ -68,6 +69,7 @@ gchar const *gitg_repository_get_path(GitgRepository *repository);
 GitgRunner *gitg_repository_get_loader(GitgRepository *repository);
 
 gboolean gitg_repository_load(GitgRepository *repository, int argc, gchar const **argv, GError **error);
+gboolean gitg_repository_get_loaded(GitgRepository *repository);
 
 void gitg_repository_add(GitgRepository *repository, GitgRevision *revision, GtkTreeIter *iter);
 void gitg_repository_clear(GitgRepository *repository);
diff --git a/gitg/gitg-utils.c b/gitg/gitg-utils.c
index afe7b95..c8d1e97 100644
--- a/gitg/gitg-utils.c
+++ b/gitg/gitg-utils.c
@@ -40,11 +40,16 @@ atoh(gchar c)
 }
 
 void
-gitg_utils_sha1_to_hash(gchar const *sha, gchar *hash)
+gitg_utils_partial_sha1_to_hash(gchar const *sha, gint length, gchar *hash)
 {
+	if (length % 2 == 1)
+	{
+		--length;
+	}
+
 	int i;
 
-	for (i = 0; i < HASH_BINARY_SIZE; ++i)
+	for (i = 0; i < length / 2; ++i)
 	{
 		gchar h = atoh(*(sha++)) << 4;
 		hash[i] = h | atoh(*(sha++));
@@ -52,6 +57,12 @@ gitg_utils_sha1_to_hash(gchar const *sha, gchar *hash)
 }
 
 void
+gitg_utils_sha1_to_hash(gchar const *sha, gchar *hash)
+{
+	gitg_utils_partial_sha1_to_hash (sha, HASH_SHA_SIZE, hash);
+}
+
+void
 gitg_utils_hash_to_sha1(gchar const *hash, gchar *sha)
 {
 	char const *repr = "0123456789abcdef";
@@ -76,6 +87,27 @@ gitg_utils_hash_to_sha1_new(gchar const *hash)
 }
 
 gchar *
+gitg_utils_partial_sha1_to_hash_new (gchar const *sha, gint length, gint *retlen)
+{
+	if (length == -1)
+	{
+		length = strlen (sha);
+	}
+
+	if (length % 2 != 0)
+	{
+		--length;
+	}
+
+	*retlen = length / 2;
+	gchar *ret = g_new (gchar, *retlen);
+
+	gitg_utils_partial_sha1_to_hash (sha, length, ret);
+
+	return ret;
+}
+
+gchar *
 gitg_utils_sha1_to_hash_new(gchar const *sha1)
 {
 	gchar *ret = g_new(gchar, HASH_BINARY_SIZE);
diff --git a/gitg/gitg-utils.h b/gitg/gitg-utils.h
index 4cb2d16..e5d8e27 100644
--- a/gitg/gitg-utils.h
+++ b/gitg/gitg-utils.h
@@ -33,9 +33,13 @@
 void gitg_utils_sha1_to_hash(gchar const *sha, gchar *hash);
 void gitg_utils_hash_to_sha1(gchar const *hash, gchar *sha);
 
+void gitg_utils_partial_sha1_to_hash (gchar const *sha, gint length, gchar *hash);
+
 gchar *gitg_utils_sha1_to_hash_new(gchar const *sha);
 gchar *gitg_utils_hash_to_sha1_new(gchar const *hash);
 
+gchar *gitg_utils_partial_sha1_to_hash_new (gchar const *sha, gint length, gint *retlen);
+
 gchar *gitg_utils_find_git(gchar const *path);
 gchar *gitg_utils_dot_git_path(gchar const *path);
 
diff --git a/gitg/gitg-window.c b/gitg/gitg-window.c
index dde9b44..822ff94 100644
--- a/gitg/gitg-window.c
+++ b/gitg/gitg-window.c
@@ -51,6 +51,10 @@
 
 #define GITG_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_WINDOW, GitgWindowPrivate))
 
+static void on_repository_row_inserted (GitgRepository *repository,
+                                        GtkTreePath    *path,
+                                        GtkTreeIter    *iter,
+                                        GitgWindow     *window);
 enum
 {
 	COLUMN_BRANCHES_NAME,
@@ -95,6 +99,8 @@ struct _GitgWindowPrivate
 	GitgRef *popup_refs[2];
 
 	GList *branch_actions;
+	gchar *select_on_load;
+	gint select_on_load_length;
 };
 
 static gboolean on_tree_view_motion(GtkTreeView *treeview, GdkEventMotion *event, GitgWindow *window);
@@ -134,10 +140,28 @@ add_branch_action (GitgWindow *window, GitgRunner *runner)
 }
 
 static void
+remove_select_on_load (GitgWindow *window)
+{
+	if (!window->priv->select_on_load || !window->priv->repository)
+	{
+		return;
+	}
+
+	g_signal_handlers_disconnect_by_func (window->priv->repository,
+	                                      G_CALLBACK (on_repository_row_inserted),
+	                                      window);
+
+	g_free (window->priv->select_on_load);
+	window->priv->select_on_load = NULL;
+}
+
+static void
 gitg_window_finalize(GObject *object)
 {
 	GitgWindow *self = GITG_WINDOW(object);
 
+	remove_select_on_load (self);
+
 	g_timer_destroy(self->priv->load_timer);
 	gdk_cursor_unref(self->priv->hand);
 
@@ -765,27 +789,41 @@ gitg_window_init(GitgWindow *self)
 }
 
 static void
-on_begin_loading(GitgRunner *loader, GitgWindow *window)
+on_repository_row_inserted (GitgRepository *repository,
+                            GtkTreePath    *path,
+                            GtkTreeIter    *iter,
+                            GitgWindow     *window)
 {
-	GdkCursor *cursor = gdk_cursor_new(GDK_WATCH);
-	gdk_window_set_cursor(GTK_WIDGET(window->priv->tree_view)->window, cursor);
-	gdk_cursor_unref(cursor);
+	GitgRevision *revision;
+	gchar const *hash;
 
-	gtk_statusbar_push(window->priv->statusbar, 0, _("Begin loading repository"));
+	gtk_tree_model_get (GTK_TREE_MODEL (repository), iter, 0, &revision, -1);
+	hash = gitg_revision_get_hash (revision);
 
-	g_timer_reset(window->priv->load_timer);
-	g_timer_start(window->priv->load_timer);
+	if (strncmp (hash, window->priv->select_on_load, window->priv->select_on_load_length) == 0)
+	{
+		/* Select this row */
+		GtkTreeSelection *selection = gtk_tree_view_get_selection (window->priv->tree_view);
+		gtk_tree_selection_select_path (selection, path);
+		gtk_tree_view_scroll_to_cell(window->priv->tree_view, path, NULL, FALSE, 0, 0);
+
+		remove_select_on_load (window);
+	}
 }
 
 static void
-on_end_loading(GitgRunner *loader, gboolean cancelled, GitgWindow *window)
+on_repository_loaded (GitgRepository *repository, GitgWindow *window)
 {
-	gchar *msg = g_strdup_printf(_("Loaded %d revisions in %.2fs"), gtk_tree_model_iter_n_children(GTK_TREE_MODEL(window->priv->repository), NULL), g_timer_elapsed(window->priv->load_timer, NULL));
+	gchar *msg = g_strdup_printf(_("Loaded %d revisions in %.2fs"),
+	                             gtk_tree_model_iter_n_children(GTK_TREE_MODEL(window->priv->repository), NULL),
+	                             g_timer_elapsed(window->priv->load_timer, NULL));
 
 	gtk_statusbar_push(window->priv->statusbar, 0, msg);
 
 	g_free(msg);
 	gdk_window_set_cursor(GTK_WIDGET(window->priv->tree_view)->window, NULL);
+
+	remove_select_on_load (window);
 }
 
 static void
@@ -806,6 +844,23 @@ handle_no_gitdir(GitgWindow *window)
 	gtk_widget_destroy(dlg);
 }
 
+void
+gitg_window_set_select_on_load (GitgWindow  *window,
+                                gchar const *sha1)
+{
+	if (!sha1)
+	{
+		return;
+	}
+
+	g_free (window->priv->select_on_load);
+
+	window->priv->select_on_load =
+			gitg_utils_partial_sha1_to_hash_new (sha1,
+				                                 -1,
+				                                 &window->priv->select_on_load_length);
+}
+
 static gboolean
 create_repository(GitgWindow *window, gchar const *path, gboolean usewd)
 {
@@ -877,6 +932,13 @@ create_repository(GitgWindow *window, gchar const *path, gboolean usewd)
 		}
 	}
 
+	if (ret)
+	{
+		gitg_window_set_select_on_load (window, select_sha1);
+
+		g_free (select_sha1);
+	}
+
 	return ret;
 }
 
@@ -1060,6 +1122,15 @@ update_window_title (GitgWindow *window)
 static void
 on_repository_load(GitgRepository *repository, GitgWindow *window)
 {
+	GdkCursor *cursor = gdk_cursor_new(GDK_WATCH);
+	gdk_window_set_cursor(GTK_WIDGET(window->priv->tree_view)->window, cursor);
+	gdk_cursor_unref(cursor);
+
+	gtk_statusbar_push(window->priv->statusbar, 0, _("Begin loading repository"));
+
+	g_timer_reset(window->priv->load_timer);
+	g_timer_start(window->priv->load_timer);
+
 	g_signal_handlers_block_by_func(window->priv->combo_branches, on_branches_combo_changed, window);
 	clear_branches_combo(window);
 	fill_branches_combo(window);
@@ -1098,7 +1169,9 @@ load_repository(GitgWindow *window, gchar const *path, gint argc, gchar const **
 	if (window->priv->repository)
 	{
 		gtk_tree_view_set_model(window->priv->tree_view, NULL);
+
 		g_signal_handlers_disconnect_by_func(window->priv->repository, G_CALLBACK(on_repository_load), window);
+		g_signal_handlers_disconnect_by_func(window->priv->repository, G_CALLBACK(on_repository_loaded), window);
 
 		g_object_unref(window->priv->repository);
 		window->priv->repository = NULL;
@@ -1113,8 +1186,6 @@ load_repository(GitgWindow *window, gchar const *path, gint argc, gchar const **
 		gtk_tree_view_set_model(window->priv->tree_view, GTK_TREE_MODEL(window->priv->repository));
 		GitgRunner *loader = gitg_repository_get_loader(window->priv->repository);
 
-		g_signal_connect(loader, "begin-loading", G_CALLBACK(on_begin_loading), window);
-		g_signal_connect(loader, "end-loading", G_CALLBACK(on_end_loading), window);
 		g_signal_connect(loader, "update", G_CALLBACK(on_update), window);
 
 		g_object_unref(loader);
@@ -1132,7 +1203,24 @@ load_repository(GitgWindow *window, gchar const *path, gint argc, gchar const **
 			ar[argc - 1] = path;
 		}
 
-		g_signal_connect(window->priv->repository, "load", G_CALLBACK(on_repository_load), window);
+		g_signal_connect (window->priv->repository,
+		                  "load",
+		                  G_CALLBACK (on_repository_load),
+		                  window);
+
+		g_signal_connect (window->priv->repository,
+		                  "loaded",
+		                  G_CALLBACK (on_repository_loaded),
+		                  window);
+
+		if (window->priv->select_on_load)
+		{
+			g_signal_connect_after (window->priv->repository,
+			                        "row-inserted",
+			                        G_CALLBACK (on_repository_row_inserted),
+			                        window);
+		}
+
 		clear_branches_combo(window);
 
 		gitg_repository_load(window->priv->repository, argc, ar, NULL);
diff --git a/gitg/gitg-window.h b/gitg/gitg-window.h
index e4e21a1..18af1f4 100644
--- a/gitg/gitg-window.h
+++ b/gitg/gitg-window.h
@@ -54,7 +54,9 @@ GType gitg_window_get_type (void) G_GNUC_CONST;
 
 void gitg_window_load_repository(GitgWindow *window, gchar const *path, gint argc, gchar const **argv);
 void gitg_window_show_commit(GitgWindow *window);
+
 GitgRepository *gitg_window_get_repository(GitgWindow *window);
+void gitg_window_set_select_on_load (GitgWindow *window, gchar const *sha1);
 
 G_END_DECLS
 
diff --git a/gitg/gitg.c b/gitg/gitg.c
index 5132cf2..a0a8d7a 100644
--- a/gitg/gitg.c
+++ b/gitg/gitg.c
@@ -37,6 +37,7 @@
 #include "gitg-utils.h"
 
 static gboolean commit_mode = FALSE;
+static gchar *select_sha1 = NULL;
 
 static void
 show_version_and_quit (void)
@@ -50,7 +51,8 @@ static GOptionEntry entries[] =
 {
 	{ "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
 	  show_version_and_quit, N_("Show the application's version"), NULL },
-	{ "commit", 'c', 0, G_OPTION_ARG_NONE, &commit_mode, N_("Start gitg in commit mode") }, 
+	{ "commit", 'c', 0, G_OPTION_ARG_NONE, &commit_mode, N_("Start gitg in commit mode") },
+	{ "select", 's', 0, G_OPTION_ARG_STRING, &select_sha1, N_("Select commit after loading the repository") },
 	{ NULL }
 };
 
@@ -189,7 +191,13 @@ main(int argc, char **argv)
 	GitgSettings *settings = gitg_settings_get_default();
 
 	GitgWindow *window = build_ui();
-	gitg_window_load_repository(window, argc > 1 ? argv[1] : NULL, argc - 2, (gchar const **)&argv[2]);
+
+	if (select_sha1)
+	{
+		gitg_window_set_select_on_load (window, select_sha1);
+	}
+
+	gitg_window_load_repository(window, argc > 1 ? argv[1] : NULL, argc - 2, argc > 1 ? (gchar const **)&argv[2] : NULL);
 
 	if (commit_mode)
 		gitg_window_show_commit(window);



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