[gitg] Implemented multiple selection for commit view (allows dragging/dropping multiple items)



commit 007b4c5df3bcfea6c4eb39e220bad0a3d91179d1
Author: Jesse van den Kieboom <jvanden grijpc10 epfl ch>
Date:   Thu Apr 23 13:25:54 2009 +0200

    Implemented multiple selection for commit view (allows dragging/dropping multiple items)
---
 gitg/gitg-commit-view.c |  160 ++++++++++++++++++++++++++++++++++++----------
 1 files changed, 125 insertions(+), 35 deletions(-)

diff --git a/gitg/gitg-commit-view.c b/gitg/gitg-commit-view.c
index f7417e1..74ae75b 100644
--- a/gitg/gitg-commit-view.c
+++ b/gitg/gitg-commit-view.c
@@ -269,7 +269,84 @@ set_current_file(GitgCommitView *view, GitgChangedFile *file, GitgChangedFileCha
 }
 
 static gboolean
-check_selection(GtkTreeSelection *selection, GtkTreeModel **model, GtkTreeIter *iter, GitgCommitView *view)
+get_selected_files(GtkTreeView             *tree_view,
+                   GList                  **files,
+                   GList                  **paths,
+                   GitgChangedFileChanges  *changes,
+                   GitgChangedFileStatus   *status)
+{
+	GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+
+	if (files == NULL && changes == NULL && status == NULL && paths == NULL)
+		return gtk_tree_selection_count_selected_rows(selection) != 0;
+	
+	GtkTreeModel *model;
+	GList *items = gtk_tree_selection_get_selected_rows(selection, &model);
+	
+	if (files)
+		*files = NULL;
+	
+	if (paths)
+		*paths = NULL;
+	
+	if (!items)
+		return FALSE;
+	
+	if (changes)
+		*changes = ~0;
+	
+	if (status)
+		*status = -1;
+	
+	GList *item;
+	GitgChangedFile *file;
+
+	for (item = items; item; item = g_list_next(item))
+	{
+		GtkTreeIter iter;
+
+		gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)item->data);
+		gtk_tree_model_get(model, &iter, COLUMN_FILE, &file, -1);
+		
+		if (changes)
+			*changes &= gitg_changed_file_get_status(file);
+		
+		GitgChangedFileStatus s = gitg_changed_file_get_status(file);
+		
+		if (status)
+		{
+			if (*status != -1 && *status != s)
+				*status = GITG_CHANGED_FILE_STATUS_NONE;
+			else
+				*status = s;
+		}
+		
+		if (files)
+			*files = g_list_prepend(*files, file);
+		else
+			g_object_unref(file);
+	}
+	
+	if (paths)
+	{
+		*paths = items;
+	}
+	else
+	{
+		g_list_foreach(items, (GFunc)gtk_tree_path_free, NULL);
+		g_list_free(items);
+	}
+	
+	if (files)
+		*files = g_list_reverse(*files);
+	
+	return TRUE;
+}
+
+static gboolean
+check_selection(GtkTreeView    *tree_view, 
+                GtkTreeIter    *iter, 
+                GitgCommitView *view)
 {
 	if (view->priv->update_id)
 		g_signal_handler_disconnect(view->priv->runner, view->priv->update_id);
@@ -287,14 +364,28 @@ check_selection(GtkTreeSelection *selection, GtkTreeModel **model, GtkTreeIter *
 	gtk_source_buffer_remove_source_marks(GTK_SOURCE_BUFFER(buffer), &start, &end, CATEGORY_STAGE_HUNK);
 	gtk_text_buffer_set_text(gtk_text_view_get_buffer(tv), "", -1);
 	
-	if (!gtk_tree_selection_get_selected(selection, model, iter))
+	GList *paths;
+	gboolean ret;
+	get_selected_files(tree_view, NULL, &paths, NULL, NULL);
+	
+	if (g_list_length(paths) != 1)
 	{
 		set_current_file(view, NULL, GITG_CHANGED_FILE_CHANGES_NONE);
 		gtk_widget_set_sensitive(GTK_WIDGET(view->priv->hscale_context), FALSE);
-		return FALSE;
+		ret = FALSE;
+	}
+	else
+	{
+		if (iter)
+			gtk_tree_model_get_iter(gtk_tree_view_get_model(tree_view),
+			                        iter,
+			                        (GtkTreePath *)paths->data);
+		ret = TRUE;
 	}
 	
-	return TRUE;
+	g_list_foreach(paths, (GFunc)gtk_tree_path_free, NULL);
+	g_list_free(paths);
+	return ret;
 }
 
 static void
@@ -309,9 +400,10 @@ unstaged_selection_changed(GtkTreeSelection *selection, GitgCommitView *view)
 	GtkTreeModel *model;
 	GtkTreeIter iter;
 	
-	if (!check_selection(selection, &model, &iter, view))
+	if (!check_selection(view->priv->tree_view_unstaged, &iter, view))
 		return;
 	
+	model = gtk_tree_view_get_model(view->priv->tree_view_unstaged);
 	unselect_tree_view(view->priv->tree_view_staged);
 	
 	GitgChangedFile *file;
@@ -377,10 +469,12 @@ staged_selection_changed(GtkTreeSelection *selection, GitgCommitView *view)
 	GtkTreeModel *model;
 	GtkTreeIter iter;
 	
-	if (!check_selection(selection, &model, &iter, view))
+	if (!check_selection(view->priv->tree_view_staged, &iter, view))
 		return;
 	
+	model = gtk_tree_view_get_model(view->priv->tree_view_staged);
 	unselect_tree_view(view->priv->tree_view_unstaged);
+
 	GitgChangedFile *file;
 	
 	gtk_tree_model_get(model, &iter, COLUMN_FILE, &file, -1);
@@ -685,23 +779,21 @@ on_tree_view_drag_data_get (GtkWidget        *widget,
 {
 	GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
 	GtkTreeModel *model;
-	GList *selected = gtk_tree_selection_get_selected_rows(sel, &model);
+	GList *selected;
 	GList *item;
-	gchar **uris = g_new(gchar *, g_list_length(selected) + 1);
+	gchar **uris;
 	guint i = 0;
+
+	get_selected_files(GTK_TREE_VIEW(widget), &selected, NULL, NULL, NULL);	
+	uris = g_new(gchar *, g_list_length(selected) + 1);
 	
 	for (item = selected; item; item = g_list_next(item))
 	{
-		GitgChangedFile *file;
-		GFile *gf;
-		GtkTreeIter iter;
-		
-		gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)item->data);
-		gtk_tree_model_get(model, &iter, COLUMN_FILE, &file, -1);
-
-		gf = gitg_changed_file_get_file(file);
+		GitgChangedFile *file = GITG_CHANGED_FILE (item->data);
+		GFile *gf = gitg_changed_file_get_file(file);
 	
 		uris[i++] = g_file_get_uri(gf);
+		g_object_unref(gf);
 	}
 	
 	uris[i] = NULL;
@@ -709,7 +801,7 @@ on_tree_view_drag_data_get (GtkWidget        *widget,
 
 	g_strfreev(uris);
 
-	g_list_foreach(selected, (GFunc)gtk_tree_path_free, NULL);
+	g_list_foreach(selected, (GFunc)g_object_unref, NULL);
 	g_list_free(selected);
 }
 
@@ -870,8 +962,16 @@ gitg_commit_view_parser_finished(GtkBuildable *buildable, GtkBuilder *builder)
 	set_icon_data_func(self, self->priv->tree_view_unstaged, GTK_CELL_RENDERER(gtk_builder_get_object(builder, "unstaged_cell_renderer_icon")));
 	set_icon_data_func(self, self->priv->tree_view_staged, GTK_CELL_RENDERER(gtk_builder_get_object(builder, "staged_cell_renderer_icon")));
 	
-	g_signal_connect(gtk_tree_view_get_selection(self->priv->tree_view_unstaged), "changed", G_CALLBACK(unstaged_selection_changed), self);
-	g_signal_connect(gtk_tree_view_get_selection(self->priv->tree_view_staged), "changed", G_CALLBACK(staged_selection_changed), self);
+	GtkTreeSelection *selection;
+	
+	selection = gtk_tree_view_get_selection(self->priv->tree_view_unstaged);
+	
+	gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
+	g_signal_connect(selection, "changed", G_CALLBACK(unstaged_selection_changed), self);
+	
+	selection = gtk_tree_view_get_selection(self->priv->tree_view_staged);
+	gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
+	g_signal_connect(selection, "changed", G_CALLBACK(staged_selection_changed), self);
 	
 	g_signal_connect(self->priv->tree_view_unstaged, "event-after", G_CALLBACK(on_unstaged_button_press), self);
 	g_signal_connect(self->priv->tree_view_staged, "event-after", G_CALLBACK(on_staged_button_press), self);
@@ -1355,36 +1455,26 @@ on_context_value_changed(GtkHScale *scale, GitgCommitView *view)
 static gboolean
 set_unstaged_popup_status(GitgCommitView *view)
 {
-	GtkTreeSelection *selection = gtk_tree_view_get_selection(view->priv->tree_view_unstaged);
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	
-	if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+	GitgChangedFileChanges changes;
+	GitgChangedFileStatus status;
+
+	if (!get_selected_files(view->priv->tree_view_unstaged, NULL, NULL, &changes, &status))
 		return FALSE;
 	
-	GitgChangedFile *file;
-	gtk_tree_model_get(model, &iter, COLUMN_FILE, &file, -1);
-	
 	GtkAction *revert = gtk_ui_manager_get_action(view->priv->ui_manager, "/ui/popup_commit_stage/RevertChangesAction");
 	GtkAction *ignore = gtk_ui_manager_get_action(view->priv->ui_manager, "/ui/popup_commit_stage/IgnoreFileAction");
-	gboolean isnew = gitg_changed_file_get_status(file) == GITG_CHANGED_FILE_STATUS_NEW;
+	gboolean isnew = status == GITG_CHANGED_FILE_STATUS_NEW;
 
 	gtk_action_set_visible(revert, !isnew);
 	gtk_action_set_visible(ignore, isnew);
 	
-	g_object_unref(file);
-	
 	return TRUE;
 }
 
 static gboolean
 set_staged_popup_status(GitgCommitView *view)
 {
-	GtkTreeSelection *selection = gtk_tree_view_get_selection(view->priv->tree_view_staged);
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	
-	if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+	if (!get_selected_files(view->priv->tree_view_staged, NULL, NULL, NULL, NULL))
 		return FALSE;
 	
 	return TRUE;	



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