[Xfce4-commits] <thunar-vcs-plugin:master> * thunar-vcs-lpugin/tvp-git-action.c tvp-git-helper/Makefile.am tvp-git-helper/main.c tvp-git-helper/tgh-common.[ch] tvp-git-helper/tgh-log{-dialog, }.[ch]: Added log action.

Peter de Ridder noreply at xfce.org
Wed Oct 14 22:20:01 CEST 2009


Updating branch refs/heads/master
         to ce00efd125e8de3f51d7625d67aed6a31d252bc8 (commit)
       from 956d4903bccd42425a79ae546d0ae2dabdff1317 (commit)

commit ce00efd125e8de3f51d7625d67aed6a31d252bc8
Author: Peter de Ridder <peter at xfce.org>
Date:   Wed Oct 14 22:13:28 2009 +0200

    * thunar-vcs-lpugin/tvp-git-action.c tvp-git-helper/Makefile.am
      tvp-git-helper/main.c tvp-git-helper/tgh-common.[ch]
      tvp-git-helper/tgh-log{-dialog,}.[ch]: Added log action.

 thunar-vcs-plugin/tvp-git-action.c         |    2 +-
 tvp-git-helper/Makefile.am                 |    4 +
 tvp-git-helper/main.c                      |   17 ++
 tvp-git-helper/tgh-common.c                |  112 ++++++++
 tvp-git-helper/tgh-common.h                |    2 +
 tvp-git-helper/tgh-log-dialog.c            |  382 ++++++++++++++++++++++++++++
 tvp-git-helper/tgh-log-dialog.h            |   64 +++++
 tvp-git-helper/{tgh-branch.c => tgh-log.c} |   66 ++++--
 tvp-git-helper/{tgh-add.h => tgh-log.h}    |    8 +-
 9 files changed, 633 insertions(+), 24 deletions(-)

diff --git a/thunar-vcs-plugin/tvp-git-action.c b/thunar-vcs-plugin/tvp-git-action.c
index f0b32c5..792e545 100644
--- a/thunar-vcs-plugin/tvp-git-action.c
+++ b/thunar-vcs-plugin/tvp-git-action.c
@@ -255,7 +255,7 @@ tvp_git_action_create_menu_item (GtkAction *action)
     add_subaction_u(GTK_MENU_SHELL(menu), "tvp::fetch", Q_("Menu|Fetch"), _("Fetch"), NULL, _("Fetch"));
     add_subaction_u(GTK_MENU_SHELL(menu), "tvp::grep", Q_("Menu|Grep"), _("Grep"), NULL, _("Grep"));
     add_subaction_u(GTK_MENU_SHELL(menu), "tvp::init", Q_("Menu|Init"), _("Init"), NULL, _("Init"));
-    add_subaction_u(GTK_MENU_SHELL(menu), "tvp::log", Q_("Menu|Log"), _("Log"), GTK_STOCK_INDEX, _("Log"));
+  add_subaction (action, GTK_MENU_SHELL(menu), "tvp::log", Q_("Menu|Log"), _("Log"), GTK_STOCK_INDEX, "--log");
     add_subaction_u(GTK_MENU_SHELL(menu), "tvp::merge", Q_("Menu|Merge"), _("Merge"), NULL, _("Merge"));
     add_subaction_u(GTK_MENU_SHELL(menu), "tvp::move", Q_("Menu|Move"), _("Move"), GTK_STOCK_DND_MULTIPLE, _("Move"));
     add_subaction_u(GTK_MENU_SHELL(menu), "tvp::pull", Q_("Menu|Pull"), _("Pull"), NULL, _("Pull"));
diff --git a/tvp-git-helper/Makefile.am b/tvp-git-helper/Makefile.am
index 8b3a59c..838b0ca 100644
--- a/tvp-git-helper/Makefile.am
+++ b/tvp-git-helper/Makefile.am
@@ -22,6 +22,8 @@ tvp_git_helper_SOURCES =						\
 	tgh-clone.c							\
 	tgh-common.h							\
 	tgh-common.c							\
+	tgh-log.h							\
+	tgh-log.c							\
 	tgh-reset.h							\
 	tgh-reset.c							\
 	tgh-status.h							\
@@ -32,6 +34,8 @@ tvp_git_helper_SOURCES =						\
 	tgh-branch-dialog.c						\
 	tgh-file-selection-dialog.h					\
 	tgh-file-selection-dialog.c					\
+	tgh-log-dialog.h						\
+	tgh-log-dialog.c						\
 	tgh-reset-dialog.h						\
 	tgh-reset-dialog.c						\
 	tgh-status-dialog.h						\
diff --git a/tvp-git-helper/main.c b/tvp-git-helper/main.c
index d770ae0..6824ded 100644
--- a/tvp-git-helper/main.c
+++ b/tvp-git-helper/main.c
@@ -33,6 +33,7 @@
 #include "tgh-add.h"
 #include "tgh-branch.h"
 #include "tgh-clone.h"
+#include "tgh-log.h"
 #include "tgh-reset.h"
 #include "tgh-status.h"
 
@@ -55,6 +56,7 @@ int main (int argc, char *argv[])
   gboolean add = FALSE;
   gboolean branch = FALSE;
   gboolean clone = FALSE;
+  gboolean log = FALSE;
   gboolean reset = FALSE;
   gboolean status = FALSE;
   gchar **files = NULL;
@@ -88,6 +90,12 @@ int main (int argc, char *argv[])
     { NULL, '\0', 0, 0, NULL, NULL, NULL }
   };
 
+  GOptionEntry log_options_table[] =
+  {
+    { "log", '\0', 0, G_OPTION_ARG_NONE, &log, N_("Execute log action"), NULL },
+    { NULL, '\0', 0, 0, NULL, NULL, NULL }
+  };
+
   GOptionEntry reset_options_table[] =
   {
     { "reset", '\0', 0, G_OPTION_ARG_NONE, &reset, N_("Execute reset action"), NULL },
@@ -120,6 +128,10 @@ int main (int argc, char *argv[])
   g_option_group_add_entries(option_group, clone_options_table);
   g_option_context_add_group(option_context, option_group);
 
+  option_group = g_option_group_new("log", N_("Log Related Options:"), N_("Log"), NULL, NULL);
+  g_option_group_add_entries(option_group, log_options_table);
+  g_option_context_add_group(option_context, option_group);
+
   option_group = g_option_group_new("reset", N_("Reset Related Options:"), N_("Reset"), NULL, NULL);
   g_option_group_add_entries(option_group, reset_options_table);
   g_option_context_add_group(option_context, option_group);
@@ -155,6 +167,11 @@ int main (int argc, char *argv[])
     has_child = tgh_clone(files, &pid);
   }
 
+  if(log)
+  {
+    has_child = tgh_log(files, &pid);
+  }
+
   if(reset)
   {
     has_child = tgh_reset(files, &pid);
diff --git a/tvp-git-helper/tgh-common.c b/tvp-git-helper/tgh-common.c
index 3d2d854..a5facf8 100644
--- a/tvp-git-helper/tgh-common.c
+++ b/tvp-git-helper/tgh-common.c
@@ -37,6 +37,7 @@
 
 #include "tgh-dialog-common.h"
 #include "tgh-status-dialog.h"
+#include "tgh-log-dialog.h"
 #include "tgh-branch-dialog.h"
 
 #include "tgh-common.h"
@@ -155,6 +156,117 @@ tgh_status_parser_new (GtkWidget *dialog)
 typedef struct {
   TghOutputParser parent;
   GtkWidget *dialog;
+  gchar *revision;
+  gchar *author;
+  gchar *author_date;
+  gchar *commit;
+  gchar *commit_date;
+  gchar *message;
+  GSList *files;
+} TghLogParser;
+
+static void
+log_parser_add_entry(TghLogParser *parser, TghLogDialog *dialog)
+{
+  tgh_log_dialog_add(dialog,
+      g_slist_reverse(parser->files),
+      parser->revision,
+      parser->author,
+      parser->author_date,
+      parser->commit,
+      parser->commit_date,
+      parser->message);
+
+  parser->files = NULL;
+  g_free(parser->revision);
+  parser->revision = NULL;
+  parser->author = NULL;
+  g_free(parser->author_date);
+  parser->author_date = NULL;
+  g_free(parser->commit);
+  parser->commit = NULL;
+  g_free(parser->commit_date);
+  parser->commit_date = NULL;
+  g_free(parser->message);
+  parser->message = NULL;
+}
+
+static void
+log_parser_func(TghLogParser *parser, gchar *line)
+{
+  TghLogDialog *dialog = TGH_LOG_DIALOG(parser->dialog);
+  if(line)
+  {
+    if(strncmp(line, "commit ", 7) == 0)
+    {
+      gchar *revision;
+
+      if(parser->revision)
+        log_parser_add_entry(parser, dialog);
+
+      // read first 6 chars of hash?
+      revision = g_strstrip(line+6);
+      parser->revision = g_strndup(revision, revision[0]=='-'?7:6);
+    }
+    else if(strncmp(line, "Author:", 7) == 0)
+    {
+      parser->author = g_strdup(g_strstrip(line+7));
+    }
+    else if(strncmp(line, "AuthorDate:", 11) == 0)
+    {
+      parser->author_date = g_strdup(g_strstrip(line+11));
+    }
+    else if(strncmp(line, "Commit:", 7) == 0)
+    {
+      parser->commit = g_strdup(g_strstrip(line+7));
+    }
+    else if(strncmp(line, "CommitDate:", 11) == 0)
+    {
+      parser->commit_date = g_strdup(g_strstrip(line+11));
+    }
+    else if(strncmp(line, "    ", 4) == 0)
+    {
+      if(parser->message)
+        parser->message = g_strconcat(parser->message, line+4, NULL);
+      else
+        parser->message = g_strdup(line+4);
+    }
+    else if(g_ascii_isdigit(line[0]))
+    {
+      gchar *ptr, *path;
+      TghLogFile *file;
+      file = g_new(TghLogFile, 1);
+      file->insertions = strtoul(line, &ptr, 10);
+      file->deletions = strtoul(ptr, &path, 10);
+      path++;
+      file->file = g_strndup (path, strlen(path)-1);
+      parser->files = g_slist_prepend (parser->files, file);
+    }
+  }
+  else
+  {
+    if(parser->revision)
+      log_parser_add_entry(parser, dialog);
+    tgh_log_dialog_done(dialog);
+    g_free(parser);
+  }
+}
+
+TghOutputParser*
+tgh_log_parser_new (GtkWidget *dialog)
+{
+  TghLogParser *parser = g_new0(TghLogParser,1);
+
+  TGH_OUTPUT_PARSER(parser)->parse = TGH_OUTPUT_PARSER_FUNC(log_parser_func);
+
+  parser->dialog = dialog;
+
+  return TGH_OUTPUT_PARSER(parser);
+}
+
+typedef struct {
+  TghOutputParser parent;
+  GtkWidget *dialog;
 } TghBranchParser;
 
 static void
diff --git a/tvp-git-helper/tgh-common.h b/tvp-git-helper/tgh-common.h
index caacc93..1f62d25 100644
--- a/tvp-git-helper/tgh-common.h
+++ b/tvp-git-helper/tgh-common.h
@@ -38,6 +38,8 @@ TghOutputParser* tgh_error_parser_new  (GtkWidget *);
 
 TghOutputParser* tgh_status_parser_new (GtkWidget *);
 
+TghOutputParser* tgh_log_parser_new    (GtkWidget *);
+
 TghOutputParser* tgh_branch_parser_new (GtkWidget *);
 
 gboolean tgh_parse_output_func  (GIOChannel *, GIOCondition, gpointer);
diff --git a/tvp-git-helper/tgh-log-dialog.c b/tvp-git-helper/tgh-log-dialog.c
new file mode 100644
index 0000000..62e4bd3
--- /dev/null
+++ b/tvp-git-helper/tgh-log-dialog.c
@@ -0,0 +1,382 @@
+/*-
+ * Copyright (c) 2006 Peter de Ridder <peter at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <thunar-vfs/thunar-vfs.h>
+#include <gtk/gtk.h>
+
+#include "tgh-common.h"
+#include "tgh-log-dialog.h"
+
+static void selection_changed (GtkTreeView*, gpointer);
+static void cancel_clicked (GtkButton*, gpointer);
+static void refresh_clicked (GtkButton*, gpointer);
+
+struct _TghLogDialog
+{
+  GtkDialog dialog;
+
+  GtkWidget *tree_view;
+  GtkWidget *text_view;
+  GtkWidget *file_view;
+  GtkWidget *close;
+  GtkWidget *cancel;
+  GtkWidget *refresh;
+};
+
+struct _TghLogDialogClass
+{
+  GtkDialogClass dialog_class;
+};
+
+G_DEFINE_TYPE (TghLogDialog, tgh_log_dialog, GTK_TYPE_DIALOG)
+
+enum {
+  SIGNAL_CANCEL = 0,
+  SIGNAL_REFRESH,
+  SIGNAL_COUNT
+};
+
+static guint signals[SIGNAL_COUNT];
+
+static void
+tgh_log_dialog_class_init (TghLogDialogClass *klass)
+{
+  signals[SIGNAL_CANCEL] = g_signal_new("cancel-clicked",
+      G_OBJECT_CLASS_TYPE (klass),
+      G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+      0, NULL, NULL,
+      g_cclosure_marshal_VOID__VOID,
+      G_TYPE_NONE, 0);
+  signals[SIGNAL_REFRESH] = g_signal_new("refresh-clicked",
+      G_OBJECT_CLASS_TYPE (klass),
+      G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+      0, NULL, NULL,
+      g_cclosure_marshal_VOID__VOID,
+      G_TYPE_NONE, 0);
+}
+
+enum {
+  COLUMN_REVISION = 0,
+  COLUMN_AUTHOR,
+  COLUMN_AUTHOR_DATE,
+  COLUMN_COMMIT,
+  COLUMN_COMMIT_DATE,
+  COLUMN_MESSAGE,
+  COLUMN_FULL_MESSAGE,
+  COLUMN_FILE_LIST,
+  COLUMN_COUNT
+};
+
+enum {
+  FILE_COLUMN_FILE = 0,
+  FILE_COLUMN_PERCENTAGE,
+  FILE_COLUMN_CHANGES,
+  FILE_COLUMN_COUNT
+};
+
+static void
+tgh_log_dialog_init (TghLogDialog *dialog)
+{
+  GtkWidget *button;
+  GtkWidget *tree_view;
+  GtkWidget *text_view;
+  GtkWidget *file_view;
+  GtkWidget *scroll_window;
+  GtkWidget *pane;
+  GtkWidget *vpane;
+  GtkCellRenderer *renderer;
+  GtkTreeModel *model;
+  gint n_columns;
+
+  pane = gtk_vpaned_new ();
+
+  scroll_window = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+  dialog->tree_view = tree_view = gtk_tree_view_new ();
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
+      -1, _("Revision"),
+      renderer, "text",
+      COLUMN_REVISION, NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
+      -1, _("Author"),
+      renderer, "text",
+      COLUMN_AUTHOR, NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
+      -1, _("AuthorDate"),
+      renderer, "text",
+      COLUMN_AUTHOR_DATE, NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
+      -1, _("Commit"),
+      renderer, "text",
+      COLUMN_COMMIT, NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
+      -1, _("CommitDate"),
+      renderer, "text",
+      COLUMN_COMMIT_DATE, NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
+      -1, _("Message"),
+      renderer, "text",
+      COLUMN_MESSAGE, NULL);
+
+  model = GTK_TREE_MODEL (gtk_list_store_new (COLUMN_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER));
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model);
+
+  g_object_unref (model);
+
+  g_signal_connect (G_OBJECT (tree_view), "cursor-changed", G_CALLBACK (selection_changed), dialog); 
+
+  gtk_container_add (GTK_CONTAINER (scroll_window), tree_view);
+  gtk_paned_pack1 (GTK_PANED(pane), scroll_window, TRUE, FALSE);
+  gtk_widget_show (tree_view);
+  gtk_widget_show (scroll_window);
+
+  scroll_window = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+  vpane = gtk_vpaned_new ();
+
+  dialog->text_view = text_view = gtk_text_view_new ();
+  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), GTK_WRAP_WORD_CHAR);
+  gtk_text_view_set_editable (GTK_TEXT_VIEW (text_view), FALSE);
+
+  gtk_container_add (GTK_CONTAINER (scroll_window), text_view);
+  gtk_paned_pack1 (GTK_PANED(vpane), scroll_window, TRUE, FALSE);
+  gtk_widget_show (text_view);
+  gtk_widget_show (scroll_window);
+
+  scroll_window = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+  dialog->file_view = file_view = gtk_tree_view_new ();
+
+  renderer = gtk_cell_renderer_progress_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (file_view),
+      -1, _("Changes"), renderer,
+      "value", FILE_COLUMN_PERCENTAGE,
+      "text", FILE_COLUMN_CHANGES,
+      NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  n_columns = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (file_view),
+      -1, _("File"),
+      renderer, "text",
+      FILE_COLUMN_FILE, NULL);
+  gtk_tree_view_set_expander_column (GTK_TREE_VIEW (file_view), gtk_tree_view_get_column (GTK_TREE_VIEW (file_view), n_columns - 1));
+
+  model = GTK_TREE_MODEL (gtk_list_store_new (FILE_COLUMN_COUNT, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING));
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (file_view), model);
+
+  g_object_unref (model);
+
+  gtk_container_add (GTK_CONTAINER (scroll_window), file_view);
+  gtk_paned_pack2 (GTK_PANED(vpane), scroll_window, TRUE, FALSE);
+  gtk_widget_show (file_view);
+  gtk_widget_show (scroll_window);
+
+  gtk_paned_pack2 (GTK_PANED(pane), vpane, TRUE, FALSE);
+  gtk_widget_show (vpane);
+
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), pane, TRUE, TRUE, 0);
+  gtk_widget_show (pane);
+
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Log"));
+
+  gtk_button_box_set_layout(GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), GTK_BUTTONBOX_EDGE);
+
+  dialog->cancel = button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, FALSE, TRUE, 0);
+  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (cancel_clicked), dialog);
+  gtk_widget_show (button);
+
+  dialog->refresh = button = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, FALSE, TRUE, 0);
+  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (refresh_clicked), dialog);
+  gtk_widget_hide (button);
+
+  dialog->close = button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
+  gtk_widget_show (button);
+
+  gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400);
+}
+
+GtkWidget*
+tgh_log_dialog_new (const gchar *title, GtkWindow *parent, GtkDialogFlags flags)
+{
+  TghLogDialog *dialog = g_object_new (TGH_TYPE_LOG_DIALOG, NULL);
+
+  if(title)
+    gtk_window_set_title (GTK_WINDOW(dialog), title);
+
+  if(parent)
+    gtk_window_set_transient_for (GTK_WINDOW(dialog), parent);
+
+  if(flags & GTK_DIALOG_MODAL)
+    gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+
+  if(flags & GTK_DIALOG_DESTROY_WITH_PARENT)
+    gtk_window_set_destroy_with_parent (GTK_WINDOW(dialog), TRUE);
+
+  if(flags & GTK_DIALOG_NO_SEPARATOR)
+    gtk_dialog_set_has_separator (GTK_DIALOG(dialog), FALSE);
+
+  return GTK_WIDGET(dialog);
+}
+
+void     
+tgh_log_dialog_add (TghLogDialog *dialog, GSList *files, const gchar *revision, const gchar *author, const gchar *author_date, const gchar *commit, const gchar *commit_date, const gchar *message)
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  gchar **lines = NULL;
+  gchar **line_iter;
+  gchar *first_line = NULL;
+
+  g_return_if_fail (TGH_IS_LOG_DIALOG (dialog));
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view));
+
+  if(message)
+  {
+    lines = g_strsplit_set (message, "\r\n", -1);
+    line_iter = lines;
+    while (*line_iter)
+    {
+      if (g_strstrip (*line_iter)[0])
+        break;
+      line_iter++;
+    }
+    if (!line_iter)
+      line_iter = lines;
+    first_line = *line_iter;
+  }
+
+  gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+      COLUMN_REVISION, revision,
+      COLUMN_AUTHOR, author,
+      COLUMN_AUTHOR_DATE, author_date,
+      COLUMN_COMMIT, commit,
+      COLUMN_COMMIT_DATE, commit_date,
+      COLUMN_MESSAGE, first_line,
+      COLUMN_FULL_MESSAGE, message,
+      COLUMN_FILE_LIST, files,
+      -1);
+
+  g_strfreev (lines);
+}
+
+void
+tgh_log_dialog_done (TghLogDialog *dialog)
+{
+  g_return_if_fail (TGH_IS_LOG_DIALOG (dialog));
+
+  gtk_widget_hide (dialog->cancel);
+  gtk_widget_show (dialog->refresh);
+}
+
+static void
+selection_changed (GtkTreeView *tree_view, gpointer user_data)
+{
+  GtkTreeIter iter;
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  gchar *message;
+  GSList *files;
+
+  TghLogDialog *dialog = TGH_LOG_DIALOG (user_data);
+
+  selection = gtk_tree_view_get_selection (tree_view);
+
+  if (gtk_tree_selection_get_selected (selection, &model, &iter))
+  {
+    gtk_tree_model_get (model, &iter, COLUMN_FULL_MESSAGE, &message, COLUMN_FILE_LIST, &files, -1);
+    gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->text_view)), message?message:"", -1);
+    g_free (message);
+
+    model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->file_view));
+    gtk_list_store_clear (GTK_LIST_STORE (model));
+
+    while(files)
+    {
+      gchar *changes = g_strdup_printf ("+%u -%u", TGH_LOG_FILE (files->data)->insertions, TGH_LOG_FILE (files->data)->deletions);
+      guint sum = TGH_LOG_FILE (files->data)->insertions + TGH_LOG_FILE (files->data)->deletions;
+      gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+          FILE_COLUMN_FILE, TGH_LOG_FILE (files->data)->file,
+          FILE_COLUMN_PERCENTAGE, sum?TGH_LOG_FILE (files->data)->insertions * 100 / sum:0,
+          FILE_COLUMN_CHANGES, changes,
+          -1);
+      g_free (changes);
+      files = files->next;
+    }
+
+    gtk_tree_view_expand_all (GTK_TREE_VIEW (dialog->file_view));
+  }
+}
+
+static void
+cancel_clicked (GtkButton *button, gpointer user_data)
+{
+  TghLogDialog *dialog = TGH_LOG_DIALOG (user_data);
+
+  gtk_widget_hide (dialog->cancel);
+  gtk_widget_show (dialog->refresh);
+
+  g_signal_emit (dialog, signals[SIGNAL_CANCEL], 0);
+}
+
+static void
+refresh_clicked (GtkButton *button, gpointer user_data)
+{
+  GtkTreeModel *model;
+  TghLogDialog *dialog = TGH_LOG_DIALOG (user_data);
+
+  gtk_widget_hide (dialog->refresh);
+  gtk_widget_show (dialog->cancel);
+
+  g_signal_emit (dialog, signals[SIGNAL_REFRESH], 0);
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view));
+  gtk_list_store_clear (GTK_LIST_STORE (model));
+
+  gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->text_view)), "", -1);
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->file_view));
+  gtk_list_store_clear (GTK_LIST_STORE (model));
+}
+
diff --git a/tvp-git-helper/tgh-log-dialog.h b/tvp-git-helper/tgh-log-dialog.h
new file mode 100644
index 0000000..11e4426
--- /dev/null
+++ b/tvp-git-helper/tgh-log-dialog.h
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2006 Peter de Ridder <peter at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TGH_LOG_DIALOG_H__
+#define __TGH_LOG_DIALOG_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _TghLogDialogClass TghLogDialogClass;
+typedef struct _TghLogDialog      TghLogDialog;
+
+#define TGH_TYPE_LOG_DIALOG             (tgh_log_dialog_get_type ())
+#define TGH_LOG_DIALOG(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), TGH_TYPE_LOG_DIALOG, TghLogDialog))
+#define TGH_LOG_DIALOG_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), TGH_TYPE_LOG_DIALOG, TghLogDialogClass))
+#define TGH_IS_LOG_DIALOG(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TGH_TYPE_LOG_DIALOG))
+#define TGH_IS_LOG_DIALOG_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), TGH_TYPE_LOG_DIALOG))
+#define TGH_LOG_DIALOG_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), TGH_TYPE_LOG_DIALOG, TghLogDialogClass))
+
+typedef struct
+{
+  guint insertions;
+  guint deletions;
+  gchar *file;
+} TghLogFile;
+
+#define TGH_LOG_FILE(p) ((TghLogFile*)p)
+
+GType        tgh_log_dialog_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL;
+
+GtkWidget*   tgh_log_dialog_new      (const gchar *title,
+                                      GtkWindow *parent,
+                                      GtkDialogFlags flags) G_GNUC_MALLOC G_GNUC_INTERNAL;
+
+void         tgh_log_dialog_add      (TghLogDialog *dialog,
+                                      GSList *files,
+                                      const gchar *revision,
+                                      const gchar *author,
+                                      const gchar *author_date,
+                                      const gchar *commit,
+                                      const gchar *commit_date,
+                                      const gchar *message);
+void         tgh_log_dialog_done     (TghLogDialog *dialog);
+
+G_END_DECLS;
+
+#endif /* !__TGH_LOG_DIALOG_H__ */
diff --git a/tvp-git-helper/tgh-branch.c b/tvp-git-helper/tgh-log.c
similarity index 62%
copy from tvp-git-helper/tgh-branch.c
copy to tvp-git-helper/tgh-log.c
index 9e3c652..a3a7727 100644
--- a/tvp-git-helper/tgh-branch.c
+++ b/tvp-git-helper/tgh-log.c
@@ -29,25 +29,45 @@
 
 #include "tgh-common.h"
 #include "tgh-dialog-common.h"
-#include "tgh-branch-dialog.h"
+#include "tgh-log-dialog.h"
 
-#include "tgh-branch.h"
+#include "tgh-log.h"
 
-static gchar *argv[] = {"git", "branch", NULL};
-
-static gboolean branch_spawn (TghBranchDialog *dialog, GPid *pid)
+static gboolean log_spawn (TghLogDialog *dialog, gchar **files, GPid *pid)
 {
   GError *error = NULL;
-  gint fd_out;
-  gint fd_err;
-  GIOChannel *chan_out;
-  GIOChannel *chan_err;
+  gint fd_out, fd_err;
+  GIOChannel *chan_out, *chan_err;
   TghOutputParser *parser;
+  gsize length;
+  gint i;
+  gchar **argv;
+
+  length = 7;
+  if(files)
+    length += g_strv_length(files);
+
+  argv = g_new(gchar*, length);
+
+  argv[0] = "git";
+  argv[1] = "log";
+  argv[2] = "--numstat";
+  argv[3] = "--pretty=fuller";
+  argv[4] = "--boundary";
+  argv[5] = "--";
+  argv[length-1] = NULL;
+
+  i = 6;
+  if(files)
+    while(*files)
+      argv[i++] = *files++;
 
   if(!g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, pid, NULL, &fd_out, &fd_err, &error))
   {
+    g_free (argv);
     return FALSE;
   }
+  g_free (argv);
 
   parser = tgh_error_parser_new(GTK_WIDGET(dialog));
 
@@ -55,35 +75,43 @@ static gboolean branch_spawn (TghBranchDialog *dialog, GPid *pid)
 
   chan_out = g_io_channel_unix_new(fd_out);
   chan_err = g_io_channel_unix_new(fd_err);
-  g_io_add_watch(chan_out, G_IO_IN|G_IO_HUP, (GIOFunc)tgh_parse_output_func, tgh_branch_parser_new(GTK_WIDGET(dialog)));
+  g_io_add_watch(chan_out, G_IO_IN|G_IO_HUP, (GIOFunc)tgh_parse_output_func, tgh_log_parser_new(GTK_WIDGET(dialog)));
   g_io_add_watch(chan_err, G_IO_IN|G_IO_HUP, (GIOFunc)tgh_parse_output_func, parser);
 
   return TRUE;
 }
 
-static void create_branch_child(TghBranchDialog *dialog, gpointer user_data)
+static void create_log_child(TghLogDialog *dialog, gpointer user_data)
 {
   GPid pid;
-  if (branch_spawn(dialog, &pid))
+  if (log_spawn(dialog, user_data, &pid))
     tgh_replace_child(TRUE, pid);
   else
-    tgh_branch_dialog_done(dialog);
+    tgh_log_dialog_done(dialog);
 }
 
-gboolean tgh_branch (gchar **files, GPid *pid)
+gboolean tgh_log (gchar **files, GPid *pid)
 {
   GtkWidget *dialog;
 
-  dialog = tgh_branch_dialog_new (NULL, NULL, 0);
+  dialog = tgh_log_dialog_new (NULL, NULL, 0);
   g_signal_connect(dialog, "cancel-clicked", tgh_cancel, NULL);
   tgh_dialog_start (GTK_DIALOG (dialog), TRUE);
 
-  g_signal_connect(dialog, "refresh-clicked", G_CALLBACK(create_branch_child), NULL);
+  g_signal_connect(dialog, "refresh-clicked", G_CALLBACK(create_log_child), files);
 
   if (files)
     if (chdir(files[0]))
-      return FALSE;
-
-  return branch_spawn(TGH_BRANCH_DIALOG(dialog), pid);
+    {
+      gchar *dirname = g_dirname (files[0]);
+      if (chdir(dirname))
+      {
+        g_free (dirname);
+        return FALSE;
+      }
+      g_free (dirname);
+    }
+
+  return log_spawn(TGH_LOG_DIALOG(dialog), files, pid);
 }
 
diff --git a/tvp-git-helper/tgh-add.h b/tvp-git-helper/tgh-log.h
similarity index 87%
copy from tvp-git-helper/tgh-add.h
copy to tvp-git-helper/tgh-log.h
index 618b78b..4dc7265 100644
--- a/tvp-git-helper/tgh-add.h
+++ b/tvp-git-helper/tgh-log.h
@@ -14,14 +14,14 @@
  * Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef __TGH_ADD_H__
-#define __TGH_ADD_H__
+#ifndef __TGH_LOG_H__
+#define __TGH_LOG_H__
 
 G_BEGIN_DECLS
 
-gboolean tgh_add (gchar **, GPid *);
+gboolean tgh_log (gchar**, GPid*);
 
 G_END_DECLS
 
-#endif /*__TGH_ADD_H__*/
+#endif /*__TGH_LOG_H__*/
 



More information about the Xfce4-commits mailing list