[anjuta] git: Implement file and folder log viewing



commit 8d5f6559fb0d4a1f3254aabad33f1548cd75e7b7
Author: James Liggett <jrliggett cox net>
Date:   Fri Dec 10 20:42:33 2010 -0800

    git: Implement file and folder log viewing
    
    File browsing is handled via DnD from the file manager. Manally entering files
    isn't working yet.

 plugins/git/anjuta-git.ui  |    3 +-
 plugins/git/git-log-pane.c |  151 +++++++++++++++++++++++++++++++++++++++++++-
 plugins/git/git-log-pane.h |    1 +
 3 files changed, 153 insertions(+), 2 deletions(-)
---
diff --git a/plugins/git/anjuta-git.ui b/plugins/git/anjuta-git.ui
index 8c8ea9b..42e211e 100644
--- a/plugins/git/anjuta-git.ui
+++ b/plugins/git/anjuta-git.ui
@@ -1066,7 +1066,8 @@
                         <property name="can_focus">True</property>
                         <property name="invisible_char">â?¢</property>
                         <property name="text" translatable="yes">Whole project; Drop a file here or type a path to view a file or folder log</property>
-                        <property name="help_text" translatable="yes">Whole project; Drop a file here or type a path to view a file or folder log</property>
+                        <property name="help_text" translatable="yes">Whole project; Drop a file here to view a file or folder log</property>
+                        <property name="editable">False</property>
                       </object>
                       <packing>
                         <property name="position">0</property>
diff --git a/plugins/git/git-log-pane.c b/plugins/git/git-log-pane.c
index 9b57fb5..1cdd0a5 100644
--- a/plugins/git/git-log-pane.c
+++ b/plugins/git/git-log-pane.c
@@ -57,12 +57,23 @@ static GtkTargetEntry drag_source_targets[] =
 	}
 };
 
+/* DnD target targets */
+static GtkTargetEntry drag_target_targets[] =
+{
+	{
+		"text/uri-list",
+		0,
+		0
+	}
+};
+
 struct _GitLogPanePriv
 {
 	GtkBuilder *builder;
 	GtkListStore *log_model;
 	GtkCellRenderer *graph_renderer;
 	GHashTable *refs;
+	gchar *path;
 
 	/* This table maps branch names and iters in the branch combo model. When
 	 * branches get refreshed, use this to make sure that the same branch the
@@ -302,14 +313,17 @@ static void
 refresh_log (GitLogPane *self)
 {
 	Git *plugin;
+	GtkTreeViewColumn *graph_column;
 	GitLogCommand *log_command;
 
 	plugin = ANJUTA_PLUGIN_GIT (anjuta_dock_pane_get_plugin (ANJUTA_DOCK_PANE (self)));
+	graph_column = GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (self->priv->builder,
+	                                                             "graph_column"));
 	
 	/* We don't support filters for now */
 	log_command = git_log_command_new (plugin->project_root_directory,
 	                                   self->priv->selected_branch,
-	                                   NULL,
+	                                   self->priv->path,
 	                                   NULL,
 	                                   NULL,
 	                                   NULL,
@@ -317,6 +331,13 @@ refresh_log (GitLogPane *self)
 	                                   NULL,
 	                                   NULL);
 
+	/* Hide the graph column if we're looking at the log of a path. The graph
+	 * won't be correct in this case. */
+	if (self->priv->path)
+		gtk_tree_view_column_set_visible (graph_column, FALSE);
+	else
+		gtk_tree_view_column_set_visible (graph_column, TRUE);
+
 	g_signal_connect (G_OBJECT (log_command), "command-finished",
 	                  G_CALLBACK (on_log_command_finished),
 	                  self);
@@ -657,6 +678,105 @@ on_log_view_drag_data_get (GtkWidget *log_view,
 }
 
 static void
+on_log_pane_drag_data_received (GtkWidget *widget,
+                                GdkDragContext *context, gint x, gint y,
+                                GtkSelectionData *data, guint target_type,
+                                guint time, GitLogPane *self)
+{
+	Git *plugin;
+	AnjutaEntry *path_entry;
+	gboolean success;
+	gchar **uri_list;
+	GFile *parent_file;
+	GFile *file;
+	gchar *path;
+
+	plugin = ANJUTA_PLUGIN_GIT (anjuta_dock_pane_get_plugin (ANJUTA_DOCK_PANE (self)));
+	path_entry = ANJUTA_ENTRY (gtk_builder_get_object (self->priv->builder,
+	                                                   "path_entry"));
+	success = FALSE;
+
+	if ((data != NULL) && 
+	    (gtk_selection_data_get_length (data) >= 0))
+	{
+		if (target_type == 0)
+		{
+			uri_list = gtk_selection_data_get_uris (data);
+			parent_file = NULL;
+			
+			parent_file = g_file_new_for_path (plugin->project_root_directory);
+
+			/* Take only the first file */
+			file = g_file_new_for_uri (uri_list[0]);
+
+			if (parent_file)
+			{
+				path = g_file_get_relative_path (parent_file, file);
+
+				g_object_unref (parent_file);
+			}
+			else
+				path = g_file_get_path (file);
+
+			if (path)
+			{
+				anjuta_entry_set_text (path_entry, path);
+
+				g_free (self->priv->path);
+				self->priv->path = g_strdup (path);
+
+				refresh_log (self);
+
+				g_free (path);
+			}
+			
+			success = TRUE;
+
+			g_object_unref (file);
+			g_strfreev (uri_list);
+		}
+	}
+
+	/* Do not delete source data */
+	gtk_drag_finish (context, success, FALSE, time);
+}
+
+static gboolean
+on_log_pane_drag_drop (GtkWidget *widget, GdkDragContext *context, 
+                       gint x, gint y, guint time,
+                       GitLogPane *self)
+{
+	GdkAtom target_type;
+
+	target_type = gtk_drag_dest_find_target (widget, context, NULL);
+
+	if (target_type != GDK_NONE)
+		gtk_drag_get_data (widget, context, target_type, time);
+	else
+		gtk_drag_finish (context, FALSE, FALSE, time);
+
+	return TRUE;
+}
+
+static void
+on_path_entry_icon_release (GtkEntry *entry, 
+                            GtkEntryIconPosition position,
+                            GdkEvent *event,
+                            GitLogPane *self)
+{	
+	if (position == GTK_ENTRY_ICON_SECONDARY)
+	{
+		if (self->priv->path)
+		{
+			g_free (self->priv->path);
+			self->priv->path = NULL;
+
+			refresh_log (self);
+		}
+	}
+}
+
+static void
 git_log_pane_init (GitLogPane *self)
 {
 	gchar *objects[] = {"log_pane",
@@ -665,6 +785,8 @@ git_log_pane_init (GitLogPane *self)
 						"find_button_image",
 						NULL};
 	GError *error = NULL;
+	GtkWidget *log_pane;
+	GtkWidget *path_entry;
 	GtkTreeView *log_view;
 	GtkTreeViewColumn *ref_icon_column;
 	GtkTreeViewColumn *graph_column;
@@ -695,6 +817,10 @@ git_log_pane_init (GitLogPane *self)
 		g_error_free (error);
 	}
 
+	log_pane = GTK_WIDGET (gtk_builder_get_object (self->priv->builder,
+	                                               "log_pane"));
+	path_entry = GTK_WIDGET (gtk_builder_get_object (self->priv->builder,
+	                                                 "path_entry"));
 	log_view = GTK_TREE_VIEW (gtk_builder_get_object (self->priv->builder,
 	                                                  "log_view"));
 	ref_icon_column = GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (self->priv->builder,
@@ -719,6 +845,11 @@ git_log_pane_init (GitLogPane *self)
 	                                                                       "loading_spinner_column"));
 	selection = gtk_tree_view_get_selection (log_view);
 
+	/* Path entry */
+	g_signal_connect (G_OBJECT (path_entry), "icon-release",
+	                  G_CALLBACK (on_path_entry_icon_release),
+	                  self);
+
 	/* Set up the log model */
 	self->priv->log_model = gtk_list_store_new (1, GIT_TYPE_REVISION);
 
@@ -796,6 +927,23 @@ git_log_pane_init (GitLogPane *self)
 	                  G_CALLBACK (on_log_view_drag_data_get),
 	                  self);
 
+	/* DnD target. Use this as a means of selecting a file to view the 
+	 * log of. Files or folders would normally be dragged in from the file 
+	 * manager, but they can come from any source that supports URI's. */
+	gtk_drag_dest_set (log_pane, 
+	                   GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT, 
+	                   drag_target_targets,
+	                   G_N_ELEMENTS (drag_target_targets), 
+	                   GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+	g_signal_connect (G_OBJECT (log_pane), "drag-data-received",
+	                  G_CALLBACK (on_log_pane_drag_data_received),
+	                  self);
+
+	g_signal_connect (G_OBJECT (log_pane), "drag-drop",
+	                  G_CALLBACK (on_log_pane_drag_drop),
+	                  self);
+
 	/* The loading view always has one row. Cache a copy of its iter for easy
 	 * access. */
 	gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->log_loading_model), 
@@ -842,6 +990,7 @@ git_log_pane_finalize (GObject *object)
 	self = GIT_LOG_PANE (object);
 
 	g_object_unref (self->priv->builder);
+	g_free (self->priv->path);
 	g_hash_table_destroy (self->priv->branches_table);
 	g_hash_table_unref (self->priv->refs);
 	g_free (self->priv->selected_branch);
diff --git a/plugins/git/git-log-pane.h b/plugins/git/git-log-pane.h
index 4845f84..0b112c6 100644
--- a/plugins/git/git-log-pane.h
+++ b/plugins/git/git-log-pane.h
@@ -21,6 +21,7 @@
 #define _GIT_LOG_PANE_H_
 
 #include <glib-object.h>
+#include <libanjuta/anjuta-entry.h>
 #include "git-pane.h"
 #include "git-log-command.h"
 #include "git-log-message-command.h"



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