[gitg] Added stat to revision details panel
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gitg] Added stat to revision details panel
- Date: Sun, 6 Jun 2010 18:59:35 +0000 (UTC)
commit 042917d2750e6002b2734f520cb7c5d64b7c567c
Author: Jesse van den Kieboom <jessevdk gnome org>
Date: Sun Jun 6 20:59:28 2010 +0200
Added stat to revision details panel
gitg/Makefile.am | 2 +
gitg/gitg-revision-changes-panel.c | 6 +-
gitg/gitg-revision-details-panel.c | 320 ++++++++++++++++++++++
gitg/gitg-revision-details-panel.ui | 25 ++-
gitg/gitg-stat-view.c | 510 +++++++++++++++++++++++++++++++++++
gitg/gitg-stat-view.h | 37 +++
gitg/gitg-window.c | 16 +-
gitg/gitg.c | 25 ++
8 files changed, 936 insertions(+), 5 deletions(-)
---
diff --git a/gitg/Makefile.am b/gitg/Makefile.am
index 8156966..b063236 100644
--- a/gitg/Makefile.am
+++ b/gitg/Makefile.am
@@ -29,6 +29,7 @@ NOINST_H_FILES = \
gitg-revision-files-panel.h \
gitg-revision-changes-panel.h \
gitg-settings.h \
+ gitg-stat-view.h \
gitg-utils.h \
gitg-window.h \
gseal-gtk-compat.h
@@ -53,6 +54,7 @@ gitg_SOURCES = \
gitg-revision-files-panel.c \
gitg-revision-changes-panel.c \
gitg-settings.c \
+ gitg-stat-view.c \
gitg-utils.c \
gitg-window.c \
$(NOINST_H_FILES)
diff --git a/gitg/gitg-revision-changes-panel.c b/gitg/gitg-revision-changes-panel.c
index 8689233..681adaa 100644
--- a/gitg/gitg-revision-changes-panel.c
+++ b/gitg/gitg-revision-changes-panel.c
@@ -504,7 +504,7 @@ reload_diff (GitgRevisionChangesPanel *changes_panel)
"diff",
"--cached",
"-M",
- "--pretty=format:%s%n%n%b",
+ "--pretty=format:",
"--encoding=UTF-8",
"--no-color",
NULL);
@@ -515,7 +515,7 @@ reload_diff (GitgRevisionChangesPanel *changes_panel)
NULL,
"diff",
"-M",
- "--pretty=format:%s%n%n%b",
+ "--pretty=format:",
"--encoding=UTF-8",
"--no-color",
NULL);
@@ -528,7 +528,7 @@ reload_diff (GitgRevisionChangesPanel *changes_panel)
NULL,
"show",
"-M",
- "--pretty=format:%s%n%n%b",
+ "--pretty=format:",
"--encoding=UTF-8",
"--no-color",
hash,
diff --git a/gitg/gitg-revision-details-panel.c b/gitg/gitg-revision-details-panel.c
index fc79f14..982d78e 100644
--- a/gitg/gitg-revision-details-panel.c
+++ b/gitg/gitg-revision-details-panel.c
@@ -24,11 +24,20 @@
#include "gitg-revision-details-panel.h"
#include "gitg-utils.h"
#include "gitg-revision-panel.h"
+#include "gitg-stat-view.h"
#include <glib/gi18n.h>
+#include <stdlib.h>
#define GITG_REVISION_DETAILS_PANEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_REVISION_DETAILS_PANEL, GitgRevisionDetailsPanelPrivate))
+typedef struct
+{
+ gchar *file;
+ guint added;
+ guint removed;
+} StatInfo;
+
struct _GitgRevisionDetailsPanelPrivate
{
GtkLabel *sha;
@@ -38,10 +47,17 @@ struct _GitgRevisionDetailsPanelPrivate
GtkTable *parents;
GtkWidget *panel_widget;
+ GtkTextView *text_view;
+
GtkBuilder *builder;
GitgRepository *repository;
GitgRevision *revision;
+
+ GitgRunner *runner;
+ gboolean in_stat;
+
+ GSList *stats;
};
static void gitg_revision_panel_iface_init (GitgRevisionPanelInterface *iface);
@@ -100,6 +116,7 @@ initialize_ui (GitgRevisionDetailsPanel *panel)
priv->date = GTK_LABEL (gtk_builder_get_object (priv->builder, "label_date"));
priv->subject = GTK_LABEL (gtk_builder_get_object (priv->builder, "label_subject"));
priv->parents = GTK_TABLE (gtk_builder_get_object (priv->builder, "table_parents"));
+ priv->text_view = GTK_TEXT_VIEW (gtk_builder_get_object (priv->builder, "text_view_details"));
gchar const *lbls[] = {
"label_subject_lbl",
@@ -169,6 +186,14 @@ gitg_revision_details_panel_dispose (GObject *object)
panel->priv->builder = NULL;
}
+ if (panel->priv->runner)
+ {
+ gitg_runner_cancel (panel->priv->runner);
+ g_object_unref (panel->priv->runner);
+
+ panel->priv->runner = NULL;
+ }
+
G_OBJECT_CLASS (gitg_revision_details_panel_parent_class)->dispose (object);
}
static void
@@ -183,10 +208,274 @@ gitg_revision_details_panel_class_init (GitgRevisionDetailsPanelClass *klass)
}
static void
+on_runner_begin (GitgRunner *runner,
+ GitgRevisionDetailsPanel *panel)
+{
+ GdkCursor *cursor;
+
+ cursor = gdk_cursor_new (GDK_WATCH);
+ gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (panel->priv->text_view)),
+ cursor);
+
+ panel->priv->in_stat = FALSE;
+
+ gdk_cursor_unref (cursor);
+}
+
+static void
+make_stats_table (GitgRevisionDetailsPanel *panel)
+{
+ guint num;
+ GtkTable *table;
+ GSList *item;
+ guint i;
+ guint max_lines = 0;
+ GtkTextChildAnchor *anchor;
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ gchar *path;
+ gchar *repo_uri;
+ gchar *sha1;
+ GFile *work_tree;
+
+ if (!panel->priv->stats)
+ {
+ return;
+ }
+
+ num = g_slist_length (panel->priv->stats);
+ table = GTK_TABLE (gtk_table_new (num, 3, FALSE));
+ gtk_table_set_row_spacings (table, 3);
+ gtk_table_set_col_spacings (table, 6);
+
+ for (item = panel->priv->stats; item; item = g_slist_next (item))
+ {
+ StatInfo *info = item->data;
+ guint total = info->added + info->removed;
+
+ if (total > max_lines)
+ {
+ max_lines = total;
+ }
+ }
+
+ item = panel->priv->stats;
+ work_tree = gitg_repository_get_work_tree (panel->priv->repository);
+ path = g_file_get_path (work_tree);
+ sha1 = gitg_revision_get_sha1 (panel->priv->revision);
+
+ g_object_unref (work_tree);
+
+ repo_uri = g_strdup_printf ("gitg://%s:%s", path, sha1);
+
+ g_free (sha1);
+ g_free (path);
+
+ for (i = 0; i < num; ++i)
+ {
+ StatInfo *info = item->data;
+ GtkWidget *view;
+ GtkWidget *file;
+ GtkWidget *total;
+ GtkWidget *align;
+ gchar *total_str;
+ gchar *uri;
+
+ view = gitg_stat_view_new (info->added,
+ info->removed,
+ max_lines);
+
+ align = gtk_alignment_new (0, 0.5, 1, 0);
+ gtk_widget_set_size_request (view, 300, 18);
+
+ gtk_container_add (GTK_CONTAINER (align), view);
+
+ uri = g_strdup_printf ("%s/changes/%s", repo_uri, info->file);
+
+ file = gtk_link_button_new_with_label (uri,
+ info->file);
+
+ g_free (uri);
+
+ gtk_button_set_alignment (GTK_BUTTON (file),
+ 0,
+ 0.5);
+
+ total_str = g_strdup_printf ("%d", info->added + info->removed);
+ total = gtk_label_new (total_str);
+ g_free (total_str);
+
+ g_free (info->file);
+ g_slice_free (StatInfo, info);
+
+ gtk_table_attach (table, file,
+ 0, 1, i, i + 1,
+ GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL,
+ 0, 0);
+
+ gtk_table_attach (table, align,
+ 1, 2, i, i + 1,
+ GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL,
+ 0, 0);
+
+ gtk_table_attach (table, total,
+ 2, 3, i, i + 1,
+ GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL,
+ 0, 0);
+
+ gtk_widget_show (view);
+ gtk_widget_show (file);
+ gtk_widget_show (total);
+ gtk_widget_show (align);
+
+ item = g_slist_next (item);
+ }
+
+ gtk_widget_show (GTK_WIDGET (table));
+
+ buffer = gtk_text_view_get_buffer (panel->priv->text_view);
+
+ gtk_text_buffer_get_end_iter (buffer, &iter);
+ gtk_text_buffer_insert (buffer, &iter, "\n\n", 2);
+
+ anchor = gtk_text_buffer_create_child_anchor (buffer,
+ &iter);
+
+ gtk_text_view_add_child_at_anchor (panel->priv->text_view,
+ GTK_WIDGET (table),
+ anchor);
+}
+
+static void
+on_runner_end (GitgRunner *runner,
+ gboolean cancelled,
+ GitgRevisionDetailsPanel *panel)
+{
+ gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (panel->priv->text_view)),
+ NULL);
+
+ panel->priv->stats = g_slist_reverse (panel->priv->stats);
+
+ make_stats_table (panel);
+
+ g_slist_free (panel->priv->stats);
+ panel->priv->stats = NULL;
+}
+
+static void
+strip_trailing_newlines (GtkTextBuffer *buffer)
+{
+ GtkTextIter iter;
+ GtkTextIter end;
+
+ gtk_text_buffer_get_end_iter (buffer, &iter);
+
+ if (!gtk_text_iter_starts_line (&iter))
+ {
+ return;
+ }
+
+ while (!gtk_text_iter_is_start (&iter) &&
+ gtk_text_iter_ends_line (&iter))
+ {
+ if (!gtk_text_iter_backward_line (&iter))
+ {
+ break;
+ }
+ }
+
+ gtk_text_iter_forward_to_line_end (&iter);
+
+ gtk_text_buffer_get_end_iter (buffer, &end);
+ gtk_text_buffer_delete (buffer, &iter, &end);
+}
+
+static void
+add_stat (GitgRevisionDetailsPanel *panel,
+ gchar const *line)
+{
+ gchar **parts;
+
+ parts = g_strsplit_set (line, "\t ", -1);
+
+ if (g_strv_length (parts) == 3)
+ {
+ StatInfo *stat;
+
+ stat = g_slice_new (StatInfo);
+
+ stat->added = (guint)atoi (parts[0]);
+ stat->removed = (guint)atoi (parts[1]);
+ stat->file = g_strdup (parts[2]);
+
+ panel->priv->stats = g_slist_prepend (panel->priv->stats,
+ stat);
+ }
+
+ g_strfreev (parts);
+}
+
+static void
+on_runner_update (GitgRunner *runner,
+ gchar **lines,
+ GitgRevisionDetailsPanel *panel)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter end;
+
+ buffer = gtk_text_view_get_buffer (panel->priv->text_view);
+ gtk_text_buffer_get_end_iter (buffer, &end);
+
+ while (lines && *lines)
+ {
+ gchar const *line = *lines;
+ ++lines;
+
+ if (panel->priv->in_stat)
+ {
+ add_stat (panel, line);
+ }
+ else
+ {
+ if (!gtk_text_iter_is_start (&end))
+ {
+ gtk_text_buffer_insert (buffer, &end, "\n", 1);
+ }
+
+ if (line[0] == '\x01' && !line[1])
+ {
+ panel->priv->in_stat = TRUE;
+ strip_trailing_newlines (buffer);
+ }
+ else
+ {
+ gtk_text_buffer_insert (buffer, &end, line, -1);
+ }
+ }
+ }
+}
+
+static void
gitg_revision_details_panel_init (GitgRevisionDetailsPanel *self)
{
self->priv = GITG_REVISION_DETAILS_PANEL_GET_PRIVATE(self);
+ self->priv->runner = gitg_runner_new (1000);
+
+ g_signal_connect (self->priv->runner,
+ "begin-loading",
+ G_CALLBACK (on_runner_begin),
+ self);
+
+ g_signal_connect (self->priv->runner,
+ "end-loading",
+ G_CALLBACK (on_runner_end),
+ self);
+
+ g_signal_connect (self->priv->runner,
+ "update",
+ G_CALLBACK (on_runner_update),
+ self);
}
#define HASH_KEY "GitgRevisionDetailsPanelHashKey"
@@ -333,6 +622,36 @@ update_parents (GitgRevisionDetailsPanel *self)
}
static void
+update_details (GitgRevisionDetailsPanel *panel)
+{
+ gchar *sha1;
+
+ gitg_runner_cancel (panel->priv->runner);
+
+ gtk_text_buffer_set_text (gtk_text_view_get_buffer (panel->priv->text_view),
+ "",
+ 0);
+
+ if (!panel->priv->revision)
+ {
+ return;
+ }
+
+ sha1 = gitg_revision_get_sha1 (panel->priv->revision);
+
+ gitg_repository_run_commandv (panel->priv->repository,
+ panel->priv->runner,
+ NULL,
+ "show",
+ "--numstat",
+ "--pretty=format:%s%n%n%b%n\x01",
+ sha1,
+ NULL);
+
+ g_free (sha1);
+}
+
+static void
reload (GitgRevisionDetailsPanel *panel)
{
GtkClipboard *cb;
@@ -373,6 +692,7 @@ reload (GitgRevisionDetailsPanel *panel)
// Update parents
update_parents (panel);
+ update_details (panel);
}
static void
diff --git a/gitg/gitg-revision-details-panel.ui b/gitg/gitg-revision-details-panel.ui
index 0b2ce4a..103d7b0 100644
--- a/gitg/gitg-revision-details-panel.ui
+++ b/gitg/gitg-revision-details-panel.ui
@@ -1,5 +1,7 @@
<?xml version="1.0"?>
<interface>
+ <!-- interface-requires gtk+ 2.12 -->
+ <!-- interface-naming-policy toplevel-contextual -->
<object class="GtkVBox" id="revision_details_page">
<property name="visible">True</property>
<property name="spacing">3</property>
@@ -36,7 +38,7 @@
<property name="xalign">0</property>
<property name="use_markup">True</property>
<property name="selectable">True</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_END</property>
+ <property name="ellipsize">end</property>
</object>
<packing>
<property name="left_attach">1</property>
@@ -158,5 +160,26 @@
<property name="position">0</property>
</packing>
</child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolled_window_details">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">etched-in</property>
+ <child>
+ <object class="GtkTextView" id="text_view_details">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="cursor_visible">False</property>
+ <property name="accepts_tab">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
</interface>
diff --git a/gitg/gitg-stat-view.c b/gitg/gitg-stat-view.c
new file mode 100644
index 0000000..a04f9b2
--- /dev/null
+++ b/gitg/gitg-stat-view.c
@@ -0,0 +1,510 @@
+#include "gitg-stat-view.h"
+
+#include "gitg-utils.h"
+#include <math.h>
+#include <cairo.h>
+
+#define GITG_STAT_VIEW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_STAT_VIEW, GitgStatViewPrivate))
+
+enum
+{
+ PROP_0,
+ PROP_LINES_ADDED,
+ PROP_LINES_REMOVED,
+ PROP_MAX_LINES
+};
+
+struct _GitgStatViewPrivate
+{
+ gdouble color_added[3];
+ gdouble color_removed[3];
+
+ cairo_pattern_t *gradient_added;
+ cairo_pattern_t *gradient_removed;
+
+ guint lines_added;
+ guint lines_removed;
+ guint max_lines;
+
+ guint radius;
+ guint stat_padding;
+ gboolean show_lines;
+ guint lines_spacing;
+};
+
+G_DEFINE_TYPE (GitgStatView, gitg_stat_view, GTK_TYPE_DRAWING_AREA)
+
+static void
+clear_gradients (GitgStatView *view)
+{
+ if (view->priv->gradient_added)
+ {
+ cairo_pattern_destroy (view->priv->gradient_added);
+ view->priv->gradient_added = NULL;
+ }
+
+ if (view->priv->gradient_removed)
+ {
+ cairo_pattern_destroy (view->priv->gradient_removed);
+ view->priv->gradient_removed = NULL;
+ }
+}
+
+static void
+gitg_stat_view_finalize (GObject *object)
+{
+ GitgStatView *view = GITG_STAT_VIEW (object);
+
+ clear_gradients (view);
+
+ G_OBJECT_CLASS (gitg_stat_view_parent_class)->finalize (object);
+}
+
+static void
+update_colors (GitgStatView *view)
+{
+ GtkStyle *style;
+ GdkColor bg_color;
+ gdouble r, g, b;
+ gdouble hue, sat, val;
+
+ if (!gtk_widget_get_realized (GTK_WIDGET (view)))
+ {
+ return;
+ }
+
+ style = gtk_widget_get_style (GTK_WIDGET (view));
+ bg_color = style->base[gtk_widget_get_state (GTK_WIDGET (view))];
+
+ r = bg_color.red / 65535.0;
+ g = bg_color.green / 65535.0;
+ b = bg_color.blue / 65535.0;
+
+ gtk_rgb_to_hsv (r, g, b, &hue, &sat, &val);
+
+ sat = MIN(sat * 0.5 + 0.5, 1);
+ val = MIN((pow(val + 1, 3) - 1) / 7 * 0.6 + 0.2, 1);
+
+ gtk_hsv_to_rgb (0,
+ sat,
+ val,
+ &(view->priv->color_removed[0]),
+ &(view->priv->color_removed[1]),
+ &(view->priv->color_removed[2]));
+
+ gtk_hsv_to_rgb (0.3,
+ sat,
+ val,
+ &(view->priv->color_added[0]),
+ &(view->priv->color_added[1]),
+ &(view->priv->color_added[2]));
+
+ clear_gradients (view);
+}
+
+static void
+gitg_stat_view_realize (GtkWidget *widget)
+{
+ if (GTK_WIDGET_CLASS (gitg_stat_view_parent_class)->realize)
+ {
+ GTK_WIDGET_CLASS (gitg_stat_view_parent_class)->realize (widget);
+ }
+
+ update_colors (GITG_STAT_VIEW (widget));
+}
+
+static void
+update_styles (GitgStatView *view)
+{
+ gtk_style_get (gtk_widget_get_style (GTK_WIDGET (view)),
+ GITG_TYPE_STAT_VIEW,
+ "radius", &view->priv->radius,
+ "stat-padding", &view->priv->stat_padding,
+ "show-lines", &view->priv->show_lines,
+ "lines-spacing", &view->priv->lines_spacing,
+ NULL);
+}
+
+static void
+gitg_stat_view_style_set (GtkWidget *widget, GtkStyle *prev_style)
+{
+ if (GTK_WIDGET_CLASS (gitg_stat_view_parent_class)->style_set)
+ {
+ GTK_WIDGET_CLASS (gitg_stat_view_parent_class)->style_set (widget, prev_style);
+ }
+
+ update_colors (GITG_STAT_VIEW (widget));
+ update_styles (GITG_STAT_VIEW (widget));
+}
+
+static void
+multiply_color (gdouble *color, gdouble factor, gdouble *ret)
+{
+ guint i;
+
+ for (i = 0; i < 3; ++i)
+ {
+ ret[i] = color[i] * factor;
+ }
+}
+
+static cairo_pattern_t *
+create_gradient (gdouble *base_color,
+ gint y,
+ gint height)
+{
+ cairo_pattern_t *gradient;
+ gdouble ret[3];
+
+ gradient = cairo_pattern_create_linear (0, y, 0, height);
+
+ cairo_pattern_add_color_stop_rgb (gradient,
+ 0,
+ base_color[0],
+ base_color[1],
+ base_color[2]);
+
+ multiply_color (base_color, 1.3, ret);
+
+ cairo_pattern_add_color_stop_rgb (gradient,
+ 1,
+ ret[0],
+ ret[1],
+ ret[2]);
+
+ return gradient;
+}
+
+static void
+update_gradients (GitgStatView *view,
+ GdkRectangle *alloc)
+{
+ if (view->priv->gradient_added == NULL)
+ {
+ view->priv->gradient_added = create_gradient (view->priv->color_added,
+ 0,
+ alloc->height);
+ }
+
+ if (view->priv->gradient_removed == NULL)
+ {
+ view->priv->gradient_removed = create_gradient (view->priv->color_removed,
+ 0,
+ alloc->height);
+ }
+}
+
+static void
+draw_stat (GitgStatView *view,
+ cairo_t *ctx,
+ gdouble *color,
+ cairo_pattern_t *gradient,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ gdouble darker[3];
+ gdouble xoff;
+ cairo_matrix_t mat;
+
+ x += 0.5;
+ y += 0.5;
+ width -= 1;
+ height -= 1;
+
+ gitg_utils_rounded_rectangle (ctx,
+ x,
+ y,
+ width,
+ height,
+ view->priv->radius);
+
+ cairo_set_source (ctx, gradient);
+ cairo_fill_preserve (ctx);
+
+ multiply_color (color, 0.4, darker);
+
+ cairo_set_line_width (ctx, 1);
+
+ cairo_set_source_rgb (ctx, darker[0], darker[1], darker[2]);
+ cairo_stroke (ctx);
+
+ if (view->priv->show_lines)
+ {
+ xoff = x + view->priv->lines_spacing;
+
+ cairo_matrix_init_rotate (&mat, M_PI);
+ cairo_pattern_set_matrix (gradient, &mat);
+
+ cairo_set_source (ctx, gradient);
+
+ while (xoff < x + width - view->priv->lines_spacing / 2)
+ {
+ cairo_move_to (ctx, xoff, y + 2);
+ cairo_line_to (ctx, xoff, y + height - 2);
+ cairo_stroke (ctx);
+
+ xoff += view->priv->lines_spacing;
+ }
+
+ cairo_matrix_init_identity (&mat);
+ cairo_pattern_set_matrix (gradient, &mat);
+ }
+}
+
+static gboolean
+gitg_stat_view_expose (GtkWidget *widget, GdkEventExpose *event)
+{
+ cairo_t *ctx;
+ GdkRectangle alloc;
+ guint added_width;
+ guint removed_width;
+ gdouble unit;
+ GitgStatView *view;
+ guint padding;
+
+ if (GTK_WIDGET_CLASS (gitg_stat_view_parent_class)->expose_event)
+ {
+ GTK_WIDGET_CLASS (gitg_stat_view_parent_class)->expose_event (widget, event);
+ }
+
+ view = GITG_STAT_VIEW (widget);
+
+ if (view->priv->max_lines == 0 ||
+ (view->priv->lines_added == 0 && view->priv->lines_removed == 0))
+ {
+ return TRUE;
+ }
+
+ if (view->priv->lines_added == 0 || view->priv->lines_removed == 0)
+ {
+ padding = 0;
+ }
+ else
+ {
+ padding = 2;
+ }
+
+ ctx = gdk_cairo_create (event->window);
+
+ gdk_cairo_rectangle (ctx, &event->area);
+ cairo_clip (ctx);
+
+ gtk_widget_get_allocation (widget, &alloc);
+
+ update_gradients (view, &alloc);
+
+ unit = (alloc.width - padding) / (gdouble)view->priv->max_lines;
+
+ added_width = MAX(view->priv->radius * 2 + 1, (guint)(unit * view->priv->lines_added));
+ removed_width = MAX(view->priv->radius * 2 + 1, (guint)(unit * view->priv->lines_removed));
+
+ if (view->priv->lines_added > 0)
+ {
+ draw_stat (view,
+ ctx,
+ view->priv->color_added,
+ view->priv->gradient_added,
+ 0,
+ 0,
+ added_width,
+ alloc.height);
+ }
+ else
+ {
+ added_width = 0;
+ }
+
+ if (view->priv->lines_removed > 0)
+ {
+ draw_stat (view,
+ ctx,
+ view->priv->color_removed,
+ view->priv->gradient_removed,
+ added_width + padding,
+ 0,
+ removed_width,
+ alloc.height);
+ }
+
+ cairo_destroy (ctx);
+
+ return TRUE;
+}
+
+static void
+gitg_stat_view_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GitgStatView *self = GITG_STAT_VIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_LINES_ADDED:
+ self->priv->lines_added = g_value_get_uint (value);
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+ break;
+ case PROP_LINES_REMOVED:
+ self->priv->lines_removed = g_value_get_uint (value);
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+ break;
+ case PROP_MAX_LINES:
+ self->priv->max_lines = g_value_get_uint (value);
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gitg_stat_view_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GitgStatView *self = GITG_STAT_VIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_LINES_ADDED:
+ g_value_set_uint (value, self->priv->lines_added);
+ break;
+ case PROP_LINES_REMOVED:
+ g_value_set_uint (value, self->priv->lines_removed);
+ break;
+ case PROP_MAX_LINES:
+ g_value_set_uint (value, self->priv->max_lines);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gitg_stat_view_configure (GtkWidget *widget,
+ GdkEventConfigure *event)
+{
+ gboolean ret;
+
+ if (GTK_WIDGET_CLASS (gitg_stat_view_parent_class)->configure_event)
+ {
+ ret = GTK_WIDGET_CLASS (gitg_stat_view_parent_class)->configure_event (widget, event);
+ }
+ else
+ {
+ ret = FALSE;
+ }
+
+ clear_gradients (GITG_STAT_VIEW (widget));
+
+ return ret;
+}
+
+static void
+gitg_stat_view_class_init (GitgStatViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->expose_event = gitg_stat_view_expose;
+ widget_class->style_set = gitg_stat_view_style_set;
+ widget_class->realize = gitg_stat_view_realize;
+ widget_class->configure_event = gitg_stat_view_configure;
+
+ object_class->finalize = gitg_stat_view_finalize;
+ object_class->set_property = gitg_stat_view_set_property;
+ object_class->get_property = gitg_stat_view_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_LINES_ADDED,
+ g_param_spec_uint ("lines-added",
+ "Lines Added",
+ "Lines added",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_LINES_REMOVED,
+ g_param_spec_uint ("lines-removed",
+ "Lines Removed",
+ "Lines removed",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_MAX_LINES,
+ g_param_spec_uint ("max-lines",
+ "Max Lines",
+ "Max lines",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_uint ("radius",
+ "Radius",
+ "Radius",
+ 0,
+ G_MAXUINT,
+ 4,
+ G_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_uint ("stat-padding",
+ "Stat padding",
+ "Stat padding",
+ 0,
+ G_MAXUINT,
+ 2,
+ G_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boolean ("show-lines",
+ "Show lines",
+ "Show lines",
+ TRUE,
+ G_PARAM_READWRITE));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_uint ("lines-spacing",
+ "Lines spacing",
+ "Lines spacing",
+ 1,
+ G_MAXUINT,
+ 10,
+ G_PARAM_READWRITE));
+
+ g_type_class_add_private (object_class, sizeof(GitgStatViewPrivate));
+}
+
+static void
+gitg_stat_view_init (GitgStatView *self)
+{
+ self->priv = GITG_STAT_VIEW_GET_PRIVATE (self);
+}
+
+GtkWidget *
+gitg_stat_view_new (guint lines_added,
+ guint lines_removed,
+ guint max_lines)
+{
+ return g_object_new (GITG_TYPE_STAT_VIEW,
+ "lines-added",
+ lines_added,
+ "lines-removed",
+ lines_removed,
+ "max-lines",
+ max_lines,
+ NULL);
+}
diff --git a/gitg/gitg-stat-view.h b/gitg/gitg-stat-view.h
new file mode 100644
index 0000000..e78a636
--- /dev/null
+++ b/gitg/gitg-stat-view.h
@@ -0,0 +1,37 @@
+#ifndef __GITG_STAT_VIEW_H__
+#define __GITG_STAT_VIEW_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GITG_TYPE_STAT_VIEW (gitg_stat_view_get_type ())
+#define GITG_STAT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_STAT_VIEW, GitgStatView))
+#define GITG_STAT_VIEW_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_STAT_VIEW, GitgStatView const))
+#define GITG_STAT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_STAT_VIEW, GitgStatViewClass))
+#define GITG_IS_STAT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_STAT_VIEW))
+#define GITG_IS_STAT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_STAT_VIEW))
+#define GITG_STAT_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_STAT_VIEW, GitgStatViewClass))
+
+typedef struct _GitgStatView GitgStatView;
+typedef struct _GitgStatViewClass GitgStatViewClass;
+typedef struct _GitgStatViewPrivate GitgStatViewPrivate;
+
+struct _GitgStatView {
+ GtkDrawingArea parent;
+
+ GitgStatViewPrivate *priv;
+};
+
+struct _GitgStatViewClass {
+ GtkDrawingAreaClass parent_class;
+};
+
+GType gitg_stat_view_get_type (void) G_GNUC_CONST;
+GtkWidget *gitg_stat_view_new (guint lines_added,
+ guint lines_removed,
+ guint max_lines);
+
+G_END_DECLS
+
+#endif /* __GITG_STAT_VIEW_H__ */
diff --git a/gitg/gitg-window.c b/gitg/gitg-window.c
index dc035bb..855d94a 100644
--- a/gitg/gitg-window.c
+++ b/gitg/gitg-window.c
@@ -1252,7 +1252,21 @@ parse_gitg_uri (GFile *file,
/* Extract path and sha information */
gchar *uri = g_file_get_uri (file);
gchar *fd = strrchr (uri, ':');
- gint pos = fd ? fd - uri : 0;
+ gchar *sel = NULL;
+ gint pos = 0;
+
+ if (fd)
+ {
+ sel = strchr (fd, '/');
+
+ if (sel)
+ {
+ *sel = '\0';
+ sel += 1;
+ }
+
+ pos = fd - uri;
+ }
if (pos > 5 && strlen (uri) - pos - 1 <= 40)
{
diff --git a/gitg/gitg.c b/gitg/gitg.c
index 555060e..7070595 100644
--- a/gitg/gitg.c
+++ b/gitg/gitg.c
@@ -37,6 +37,7 @@
static gboolean commit_mode = FALSE;
static gchar *select_sha1 = NULL;
+static GtkLinkButtonUriFunc original_link_button_hook;
static void
show_version_and_quit (void)
@@ -166,6 +167,26 @@ set_icons ()
g_list_free (icons);
}
+static void
+link_button_uri_hook (GtkLinkButton *button,
+ gchar const *link_,
+ GitgWindow *window)
+{
+ GFile *file;
+
+ file = g_file_new_for_uri (link_);
+
+ if (!g_file_has_uri_scheme (file, "gitg"))
+ {
+ original_link_button_hook (button, link_, NULL);
+ }
+ else
+ {
+ }
+
+ g_object_unref (file);
+}
+
int
main (int argc, char **argv)
{
@@ -205,6 +226,10 @@ main (int argc, char **argv)
gitg_window_show_commit (window);
}
+ original_link_button_hook = gtk_link_button_set_uri_hook ((GtkLinkButtonUriFunc)link_button_uri_hook,
+ window,
+ NULL);
+
gtk_main ();
/* Finalize settings */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]