Updating branch refs/heads/master to cb88c8658fc271103f0cc3db15c834e60f312daa (commit) from 796cb565a69eb7f417a8ea66d6e12f9861106d5d (commit)
commit cb88c8658fc271103f0cc3db15c834e60f312daa Author: Peter de Ridder <pe...@xfce.org> Date: Mon Dec 7 00:43:00 2009 +0100 Show revision graph in log dialog. Graph cell renderer draws a graph of the log revisions based on parent commits. The renderer uses the fg style to draw lines and bg style to fill boxes. tvp-git-helper/Makefile.am | 4 +- tvp-git-helper/tgh-cell-renderer-graph.c | 404 ++++++++++++++++++++++++++++++ tvp-git-helper/tgh-cell-renderer-graph.h | 53 ++++ tvp-git-helper/tgh-common.c | 33 +++- tvp-git-helper/tgh-log-dialog.c | 122 +++++++++- tvp-git-helper/tgh-log-dialog.h | 1 + tvp-git-helper/tgh-log.c | 8 +- 7 files changed, 617 insertions(+), 8 deletions(-) diff --git a/tvp-git-helper/Makefile.am b/tvp-git-helper/Makefile.am index 475f01f..fe616e8 100644 --- a/tvp-git-helper/Makefile.am +++ b/tvp-git-helper/Makefile.am @@ -55,7 +55,9 @@ tvp_git_helper_SOURCES = \ tgh-status-dialog.h \ tgh-status-dialog.c \ tgh-transfer-dialog.h \ - tgh-transfer-dialog.c + tgh-transfer-dialog.c \ + tgh-cell-renderer-graph.h \ + tgh-cell-renderer-graph.c tvp_git_helper_CPPFLAGS = \ -DG_LOG_DOMAIN=\"tvp-git-helper\" \ diff --git a/tvp-git-helper/tgh-cell-renderer-graph.c b/tvp-git-helper/tgh-cell-renderer-graph.c new file mode 100644 index 0000000..147da86 --- /dev/null +++ b/tvp-git-helper/tgh-cell-renderer-graph.c @@ -0,0 +1,404 @@ +/*- + * Copyright (c) 2006 Peter de Ridder <pe...@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-cell-renderer-graph.h" + +struct _TghCellRendererGraph +{ + GtkCellRenderer cell; + + GList *graph_iter; + guint junction_size; + guint spacing; +}; + +struct _TghCellRendererGraphClass +{ + GtkCellRendererClass cell_class; +}; + +enum { + PROPERTY_GRAPH_ITER = 1 +}; + +static void tgh_cell_renderer_graph_get_property (GObject*, guint, GValue*, GParamSpec*); +static void tgh_cell_renderer_graph_set_property (GObject*, guint, const GValue*, GParamSpec*); + +static void tgh_cell_renderer_graph_get_size (GtkCellRenderer*, GtkWidget*, GdkRectangle*, gint*, gint*, gint*, gint*); +static void tgh_cell_renderer_graph_render (GtkCellRenderer*, GdkDrawable*, GtkWidget*, GdkRectangle*, GdkRectangle*, GdkRectangle*, GtkCellRendererState); + +G_DEFINE_TYPE (TghCellRendererGraph, tgh_cell_renderer_graph, GTK_TYPE_CELL_RENDERER) + +static void +tgh_cell_renderer_graph_class_init (TghCellRendererGraphClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass); + + object_class->get_property = tgh_cell_renderer_graph_get_property; + object_class->set_property = tgh_cell_renderer_graph_set_property; + + cell_class->get_size = tgh_cell_renderer_graph_get_size; + cell_class->render = tgh_cell_renderer_graph_render; + + g_object_class_install_property (object_class, PROPERTY_GRAPH_ITER, + g_param_spec_pointer ("graph-iter", "", "", G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROPERTY_GRAPH_ITER, + g_param_spec_uint ("junction-size", "", "", 1, G_MAXUINT, 5, G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROPERTY_GRAPH_ITER, + g_param_spec_uint ("spacing", "", "", 1, G_MAXUINT, 4, G_PARAM_READWRITE)); +} + +static void +tgh_cell_renderer_graph_init (TghCellRendererGraph *renderer) +{ + renderer->junction_size = 5; + renderer->spacing = 4; +} + +GtkCellRenderer* +tgh_cell_renderer_graph_new (void) +{ + return g_object_new (TGH_TYPE_CELL_RENDERER_GRAPH, NULL); +} + +static void +tgh_cell_renderer_graph_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + TghCellRendererGraph *renderer = TGH_CELL_RENDERER_GRAPH (object); + + switch (property_id) + { + case PROPERTY_GRAPH_ITER: + g_value_set_pointer (value, renderer->graph_iter); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +tgh_cell_renderer_graph_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + TghCellRendererGraph *renderer = TGH_CELL_RENDERER_GRAPH (object); + + switch (property_id) + { + case PROPERTY_GRAPH_ITER: + renderer->graph_iter = g_value_get_pointer (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +tgh_cell_renderer_graph_get_size (GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) +{ + TghCellRendererGraph *renderer = TGH_CELL_RENDERER_GRAPH (cell); + gint graph_width = 0; + gint graph_height = 0; + gint calc_width; + gint calc_height; + + if (renderer->graph_iter) + { + gint count; + TghGraphNode *node_iter; + + for (node_iter = renderer->graph_iter->data, count = 0; node_iter; node_iter = node_iter->next, count++) + { + switch (node_iter->type) + { + case TGH_GRAPH_LINE: + break; + case TGH_GRAPH_JUNCTION: + graph_height = renderer->junction_size; + break; + } + } + + if (count) + { + graph_width = renderer->spacing + renderer->spacing * count + count; + } + } + + calc_width = (gint) cell->xpad * 2 + graph_width; + calc_height = (gint) cell->ypad * 2 + graph_height; + + if (cell_area && graph_width > 0 && graph_height > 0) + { + if (x_offset) + { + *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? + (1.0 - cell->xalign) : cell->xalign) * (cell_area->width - calc_width)); + if (*x_offset < 0) + *x_offset = 0; + } + if (y_offset) + { + *y_offset = (cell->yalign * (cell_area->height - calc_height)); + if (*y_offset < 0) + *y_offset = 0; + } + } + else + { + if (x_offset) + *x_offset = 0; + if (y_offset) + *y_offset = 0; + } + + if (width) + *width = calc_width; + + if (height) + *height = calc_height; +} + +static gint +tgh_graph_node_length (TghGraphNode *list) +{ + TghGraphNode *iter; + gint count; + + for (iter = list, count = 0; iter; iter = iter->next, count++); + + return count; +} + +static gint +tgh_graph_node_index_of (TghGraphNode *list, const gchar *name) +{ + TghGraphNode *iter; + gint index1; + + for (iter = list, index1 = 0; iter; iter = iter->next, index1++) + { + if (0 == strcmp (name, iter->name)) + return index1; + } + + return -1; +} + +static void +draw_node (gint index1, TghGraphNode *node_list, const gchar *name, gint x1_offset, gint x2_offset, gint y_offset, gint height, guint spacing, gboolean bottom, gboolean rtl, cairo_t *cr) +{ + gint index2; + + index2 = tgh_graph_node_index_of (node_list, name); + + if (index2 >= 0) + { + double x1, x2; + if (rtl) + { + x1 = x1_offset - (spacing + spacing * index1 + index1) + 0.5; + x2 = x2_offset - (spacing + spacing * index2 + index2) + 0.5; + } + else + { + x1 = x1_offset + spacing + spacing * index1 + index1 + 0.5; + x2 = x2_offset + spacing + spacing * index2 + index2 + 0.5; + } + + if (bottom) + x2 = (x1+x2)/2; + else + x1 = (x1+x2)/2; + + cairo_move_to (cr, x1, y_offset); + cairo_line_to (cr, x2, y_offset + height); + } +} + +static void +tgh_cell_renderer_graph_render (GtkCellRenderer *cell, GdkDrawable *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags) +{ + TghCellRendererGraph *renderer = TGH_CELL_RENDERER_GRAPH (cell); + gint x_offset; + gint width; + + tgh_cell_renderer_graph_get_size (cell, widget, cell_area, &x_offset, NULL, &width, NULL); + + if (renderer->graph_iter) + { + cairo_t *cr; + GdkGC *gc; + GList *graph_iter; + TghGraphNode *node_iter; + TghGraphNode *node_list; + gchar **junction_iter; + gint index1; + gint line_height, line_offset; + guint spacing = renderer->spacing; + guint junction_size = renderer->junction_size; + gint y_offset; + gint height; + gint x2_offset; + gint x; + gboolean rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); + GtkStateType state; + + if (flags & GTK_CELL_RENDERER_INSENSITIVE) + state = GTK_STATE_INSENSITIVE; + else if (flags & GTK_CELL_RENDERER_SELECTED) + state = GTK_STATE_SELECTED; + else if (flags & GTK_CELL_RENDERER_PRELIT) + state = GTK_STATE_PRELIGHT; + else + state = GTK_STATE_NORMAL; + + x_offset += cell_area->x + cell->xpad; + y_offset = background_area->y; + height = background_area->height; + + if (rtl) + x_offset += width - cell->xpad * 2; + + cr = gdk_cairo_create (window); + cairo_set_line_width (cr, 1); + gdk_cairo_set_source_color (cr, &widget->style->fg[state]); + + gc = widget->style->fg_gc[state]; + + if (expose_area) + gdk_gc_set_clip_rectangle (gc, expose_area); + + node_list = renderer->graph_iter->data; + graph_iter = g_list_next (renderer->graph_iter); + if (graph_iter) + { + line_height = (height - junction_size) / 2; + line_offset = y_offset; + + x2_offset = tgh_graph_node_length (graph_iter->data); + x2_offset = renderer->spacing + renderer->spacing * x2_offset + x2_offset; + x2_offset = x2_offset; + x2_offset = ((rtl ? (1.0 - cell->xalign) : cell->xalign) * (cell_area->width - x2_offset)) + (rtl ? x2_offset : 0); + if (x2_offset < 0) + x2_offset = 0; + x2_offset += cell_area->x; + + index1 = 0; + for (node_iter = graph_iter->data; node_iter; node_iter = node_iter->next) + { + switch (node_iter->type) + { + case TGH_GRAPH_LINE: + draw_node (index1, node_list, node_iter->name, x2_offset, x_offset, line_offset, line_height, spacing, FALSE, rtl, cr); + index1++; + break; + case TGH_GRAPH_JUNCTION: + if (node_iter->junction) + { + for (junction_iter = node_iter->junction; *junction_iter; junction_iter++) + { + draw_node (index1, node_list, *junction_iter, x2_offset, x_offset, line_offset, line_height, spacing, FALSE, rtl, cr); + } + } + index1++; + break; + } + } + } + + graph_iter = g_list_previous (renderer->graph_iter); + if (graph_iter) + { + node_list = graph_iter->data; + + x2_offset = tgh_graph_node_length (graph_iter->data); + x2_offset = renderer->spacing + renderer->spacing * x2_offset + x2_offset; + x2_offset = x2_offset; + x2_offset = ((rtl ? (1.0 - cell->xalign) : cell->xalign) * (cell_area->width - x2_offset)) + (rtl ? x2_offset : 0); + if (x2_offset < 0) + x2_offset = 0; + x2_offset += cell_area->x; + } + else + node_list = NULL; + + line_height = (height - junction_size) / 2; + line_offset = y_offset + height - line_height; + + index1 = 0; + for (node_iter = renderer->graph_iter->data; node_iter; node_iter = node_iter->next) + { + switch (node_iter->type) + { + case TGH_GRAPH_LINE: + if (rtl) + x = x_offset - (spacing + spacing * index1 + index1); + else + x = x_offset + spacing + spacing * index1 + index1; + gdk_draw_line (window, gc, x, y_offset + line_height, x, line_offset); + + draw_node (index1, node_list, node_iter->name, x_offset, x2_offset, line_offset, line_height, spacing, TRUE, rtl, cr); + index1++; + break; + case TGH_GRAPH_JUNCTION: + if (rtl) + x = x_offset - (spacing + spacing * index1 + index1); + else + x = x_offset + spacing + spacing * index1 + index1; + gdk_draw_rectangle (window, widget->style->bg_gc[state], TRUE, + x - (junction_size/2), + y_offset + line_height, + junction_size, junction_size); + gdk_draw_rectangle (window, gc, FALSE, + x - (junction_size/2), + y_offset + line_height, + junction_size - 1, junction_size - 1); + + if (node_iter->junction) + { + for (junction_iter = node_iter->junction; *junction_iter; junction_iter++) + { + draw_node (index1, node_list, *junction_iter, x_offset, x2_offset, line_offset, line_height, spacing, TRUE, rtl, cr); + } + } + index1++; + break; + } + } + + if (expose_area) + gdk_gc_set_clip_rectangle (gc, NULL); + + cairo_stroke (cr); + cairo_destroy (cr); + } +} + diff --git a/tvp-git-helper/tgh-cell-renderer-graph.h b/tvp-git-helper/tgh-cell-renderer-graph.h new file mode 100644 index 0000000..567cc21 --- /dev/null +++ b/tvp-git-helper/tgh-cell-renderer-graph.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2006 Peter de Ridder <pe...@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_CELL_RENDERER_GRAPH_H__ +#define __TGH_CELL_RENDERER_GRAPH_H__ + +#include <gtk/gtk.h> + +G_BEGIN_DECLS; + +typedef struct _TghCellRendererGraphClass TghCellRendererGraphClass; +typedef struct _TghCellRendererGraph TghCellRendererGraph; + +#define TGH_TYPE_CELL_RENDERER_GRAPH (tgh_cell_renderer_graph_get_type ()) +#define TGH_CELL_RENDERER_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TGH_TYPE_CELL_RENDERER_GRAPH, TghCellRendererGraph)) +#define TGH_CELL_RENDERER_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TGH_TYPE_CELL_RENDERER_GRAPH, TghCellRendererGraphClass)) +#define TGH_IS_CELL_RENDERER_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TGH_TYPE_CELL_RENDERER_GRAPH)) +#define TGH_IS_CELL_RENDERER_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TGH_TYPE_CELL_RENDERER_GRAPH)) +#define TGH_CELL_RENDERER_GRAPH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TGH_TYPE_CELL_RENDERER_GRAPH, TghCellRendererGraphClass)) + +typedef struct _TghGraphNode TghGraphNode; + +struct _TghGraphNode +{ + TghGraphNode *next; + enum {TGH_GRAPH_LINE, TGH_GRAPH_JUNCTION} type; + gchar *name; + gchar **junction; +}; + +GType tgh_cell_renderer_graph_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; + +GtkCellRenderer* tgh_cell_renderer_graph_new (void) G_GNUC_MALLOC G_GNUC_INTERNAL; + +G_END_DECLS; + +#endif /* !__TGH_CELL_RENDERER_GRAPH_H__ */ diff --git a/tvp-git-helper/tgh-common.c b/tvp-git-helper/tgh-common.c index 62fd1d0..7ae58c9 100644 --- a/tvp-git-helper/tgh-common.c +++ b/tvp-git-helper/tgh-common.c @@ -242,6 +242,7 @@ typedef struct { TghOutputParser parent; GtkWidget *dialog; gchar *revision; + gchar **parents; gchar *author; gchar *author_date; gchar *commit; @@ -256,6 +257,7 @@ log_parser_add_entry(TghLogParser *parser, TghLogDialog *dialog) tgh_log_dialog_add(dialog, g_slist_reverse(parser->files), parser->revision, + parser->parents, parser->author, parser->author_date, parser->commit, @@ -265,6 +267,8 @@ log_parser_add_entry(TghLogParser *parser, TghLogDialog *dialog) parser->files = NULL; g_free(parser->revision); parser->revision = NULL; + g_strfreev(parser->parents); + parser->parents = NULL; parser->author = NULL; g_free(parser->author_date); parser->author_date = NULL; @@ -284,14 +288,39 @@ log_parser_func(TghLogParser *parser, gchar *line) { if(strncmp(line, "commit ", 7) == 0) { - gchar *revision; + gchar *revision, *parent; + GSList *parent_list = NULL; + guint parent_count = 0; if(parser->revision) log_parser_add_entry(parser, dialog); + revision = g_strstrip (line+6); + parent = revision; + + while ((parent = strchr (parent, ' '))) + { + *parent++ = '\0'; + parent = g_strchug (parent); + parent_list = g_slist_prepend (parent_list, parent); + parent_count++; + } + // read first 6 chars of hash? - revision = g_strstrip(line+6); parser->revision = g_strndup(revision, revision[0]=='-'?7:6); + + if (parent_count) + { + gchar **parents = g_new (char*, parent_count+1); + parents[parent_count] = NULL; + while (parent_list) + { + // read first 6 chars of hash? + parents[--parent_count] = g_strndup (parent_list->data, 6);; + parent_list = g_slist_delete_link (parent_list, parent_list); + } + parser->parents = parents; + } } else if(strncmp(line, "Author:", 7) == 0) { diff --git a/tvp-git-helper/tgh-log-dialog.c b/tvp-git-helper/tgh-log-dialog.c index f7938c9..f38507b 100644 --- a/tvp-git-helper/tgh-log-dialog.c +++ b/tvp-git-helper/tgh-log-dialog.c @@ -25,6 +25,7 @@ #include <gtk/gtk.h> #include "tgh-common.h" +#include "tgh-cell-renderer-graph.h" #include "tgh-log-dialog.h" static void selection_changed (GtkTreeView*, gpointer); @@ -35,6 +36,8 @@ struct _TghLogDialog { GtkDialog dialog; + GList *graph; + GtkWidget *tree_view; GtkWidget *text_view; GtkWidget *file_view; @@ -84,6 +87,7 @@ enum { COLUMN_MESSAGE, COLUMN_FULL_MESSAGE, COLUMN_FILE_LIST, + COLUMN_GRAPH, COLUMN_COUNT }; @@ -114,6 +118,13 @@ tgh_log_dialog_init (TghLogDialog *dialog) dialog->tree_view = tree_view = gtk_tree_view_new (); + renderer = tgh_cell_renderer_graph_new (); + g_object_set (G_OBJECT (renderer), "xalign", 0.5f, NULL); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), + -1, "", renderer, + "graph-iter", COLUMN_GRAPH, + NULL); + renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), -1, _("Revision"), @@ -132,6 +143,7 @@ tgh_log_dialog_init (TghLogDialog *dialog) renderer, "text", COLUMN_AUTHOR_DATE, NULL); +#if 0 renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), -1, _("Commit"), @@ -143,6 +155,7 @@ tgh_log_dialog_init (TghLogDialog *dialog) -1, _("CommitDate"), renderer, "text", COLUMN_COMMIT_DATE, NULL); +#endif renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), @@ -150,7 +163,7 @@ tgh_log_dialog_init (TghLogDialog *dialog) 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)); + 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, G_TYPE_POINTER)); gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model); @@ -255,19 +268,119 @@ tgh_log_dialog_new (const gchar *title, GtkWindow *parent, GtkDialogFlags flags) return GTK_WIDGET(dialog); } +static void +tgh_graph_node_free (TghGraphNode *node) +{ + TghGraphNode *next; + + while (node) + { + g_free (node->name); + g_strfreev (node->junction); + + next = node->next; + g_free (node); + node = next; + } +} + +static TghGraphNode* +tgh_graph_node_add (TghGraphNode *prev) +{ + TghGraphNode *node = g_new0 (TghGraphNode, 1); + if (prev) + prev->next = node; + return node; +} + +static TghGraphNode* +add_n_check_node (TghGraphNode *node_iter, TghGraphNode **node_list, const gchar *name, const gchar *revision, gchar **parents, gboolean *found) +{ + TghGraphNode *iter; + + for (iter = *node_list; iter; iter = iter->next) + { + if (G_UNLIKELY(0 == strcmp (iter->name, name))) + return node_iter; + } + + node_iter = tgh_graph_node_add (node_iter); + + if (G_UNLIKELY (!*node_list)) + *node_list = node_iter; + + node_iter->name = g_strdup (name); + + if (G_UNLIKELY (0 == strcmp (revision, name))) + { + *found = TRUE; + node_iter->type = TGH_GRAPH_JUNCTION; + node_iter->junction = g_strdupv (parents); + } + + return node_iter; +} + 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) +tgh_log_dialog_add (TghLogDialog *dialog, GSList *files, const gchar *revision, gchar **parents, 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; + GList *graph; + TghGraphNode *next_node_list; + TghGraphNode *next_node_iter; + TghGraphNode *node_list = NULL; + TghGraphNode *node_iter = NULL; + gchar **junction_iter; + gboolean found = FALSE; g_return_if_fail (TGH_IS_LOG_DIALOG (dialog)); model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view)); + graph = dialog->graph; + + if (graph) + { + next_node_list = graph->data; + + for (next_node_iter = next_node_list; next_node_iter; next_node_iter = next_node_iter->next) + { + switch (next_node_iter->type) + { + case TGH_GRAPH_LINE: + node_iter = add_n_check_node (node_iter, &node_list, next_node_iter->name, revision, parents, &found); + break; + case TGH_GRAPH_JUNCTION: + if (G_LIKELY (next_node_iter->junction)) + { + for (junction_iter = next_node_iter->junction; *junction_iter; junction_iter++) + { + node_iter = add_n_check_node (node_iter, &node_list, *junction_iter, revision, parents, &found); + } + } + break; + } + } + } + + if (!found) + { + node_iter = g_new0 (TghGraphNode, 1); + node_iter->next = node_list; + node_iter->name = g_strdup (revision); + node_iter->type = TGH_GRAPH_JUNCTION; + node_iter->junction = g_strdupv (parents); + node_list = node_iter; + } + + graph = g_list_prepend (graph, node_list); + + dialog->graph = graph; + if(message) { lines = g_strsplit_set (message, "\r\n", -1); @@ -293,6 +406,7 @@ tgh_log_dialog_add (TghLogDialog *dialog, GSList *files, const gchar *revision, COLUMN_MESSAGE, first_line, COLUMN_FULL_MESSAGE, message, COLUMN_FILE_LIST, files, + COLUMN_GRAPH, graph, -1); g_strfreev (lines); @@ -372,6 +486,10 @@ refresh_clicked (GtkButton *button, gpointer user_data) model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view)); gtk_list_store_clear (GTK_LIST_STORE (model)); + g_list_foreach(dialog->graph, (GFunc)tgh_graph_node_free, NULL); + g_list_free (dialog->graph); + dialog->graph = NULL; + 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)); diff --git a/tvp-git-helper/tgh-log-dialog.h b/tvp-git-helper/tgh-log-dialog.h index 11e4426..7adf604 100644 --- a/tvp-git-helper/tgh-log-dialog.h +++ b/tvp-git-helper/tgh-log-dialog.h @@ -52,6 +52,7 @@ GtkWidget* tgh_log_dialog_new (const gchar *title, void tgh_log_dialog_add (TghLogDialog *dialog, GSList *files, const gchar *revision, + gchar ** parents, const gchar *author, const gchar *author_date, const gchar *commit, diff --git a/tvp-git-helper/tgh-log.c b/tvp-git-helper/tgh-log.c index 403fe4f..0959030 100644 --- a/tvp-git-helper/tgh-log.c +++ b/tvp-git-helper/tgh-log.c @@ -43,7 +43,7 @@ static gboolean log_spawn (TghLogDialog *dialog, gchar **files, GPid *pid) gint i; gchar **argv; - length = 8; + length = 10; if(files) length += g_strv_length(files); @@ -55,10 +55,12 @@ static gboolean log_spawn (TghLogDialog *dialog, gchar **files, GPid *pid) argv[3] = "--numstat"; argv[4] = "--parents"; argv[5] = "--pretty=fuller"; - argv[6] = "--"; + argv[6] = "--boundary"; + argv[7] = "--date-order"; + argv[8] = "--"; argv[length-1] = NULL; - i = 7; + i = 9; if(files) while(*files) argv[i++] = *files++; _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits