mirror of
https://gitlab.gnome.org/GNOME/gitg
synced 2024-08-25 02:47:01 +00:00
Added showing labels in revision view
Labels (branch/tag/remote) now show in the revision view Branch drop down is now filled by looking at the refs in the repository (fetched using ref-for-each). Same refs are used to map the labels
This commit is contained in:
parent
dadddbb7e8
commit
de526d2bdc
|
@ -15,11 +15,13 @@ INCLUDES = \
|
|||
gitg_SOURCES = \
|
||||
gitg.c \
|
||||
gitg-window.c \
|
||||
gitg-ref.c \
|
||||
gitg-revision.c \
|
||||
gitg-revision-tree-view.c \
|
||||
gitg-revision-tree-store.c \
|
||||
gitg-repository.c \
|
||||
gitg-cell-renderer-path.c \
|
||||
gitg-label-renderer.c \
|
||||
gitg-runner.c \
|
||||
gitg-revision-view.c \
|
||||
gitg-utils.c \
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "gitg-cell-renderer-path.h"
|
||||
#include "gitg-lane.h"
|
||||
#include "gitg-utils.h"
|
||||
#include "gitg-label-renderer.h"
|
||||
|
||||
#define GITG_CELL_RENDERER_PATH_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_CELL_RENDERER_PATH, GitgCellRendererPathPrivate))
|
||||
|
||||
|
@ -17,7 +18,8 @@ enum
|
|||
PROP_LANES,
|
||||
PROP_NEXT_LANES,
|
||||
PROP_LANE_WIDTH,
|
||||
PROP_DOT_WIDTH
|
||||
PROP_DOT_WIDTH,
|
||||
PROP_LABELS
|
||||
};
|
||||
|
||||
struct _GitgCellRendererPathPrivate
|
||||
|
@ -25,6 +27,7 @@ struct _GitgCellRendererPathPrivate
|
|||
gint8 lane;
|
||||
GSList *lanes;
|
||||
GSList *next_lanes;
|
||||
GSList *labels;
|
||||
guint lane_width;
|
||||
guint dot_width;
|
||||
};
|
||||
|
@ -40,14 +43,23 @@ num_lanes(GitgCellRendererPath *self)
|
|||
}
|
||||
|
||||
inline static gint
|
||||
total_width(GitgCellRendererPath *self)
|
||||
total_width(GitgCellRendererPath *self, GtkWidget *widget)
|
||||
{
|
||||
return num_lanes(self) * self->priv->lane_width;
|
||||
PangoFontDescription *font;
|
||||
g_object_get(self, "font-desc", &font, NULL);
|
||||
|
||||
return num_lanes(self) * self->priv->lane_width + gitg_label_renderer_width(widget, font, self->priv->labels);
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_cell_renderer_path_finalize(GObject *object)
|
||||
{
|
||||
GitgCellRendererPath *self = GITG_CELL_RENDERER_PATH(object);
|
||||
|
||||
g_slist_free(self->priv->lanes);
|
||||
g_slist_free(self->priv->next_lanes);
|
||||
g_slist_free(self->priv->labels);
|
||||
|
||||
G_OBJECT_CLASS(gitg_cell_renderer_path_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
|
@ -63,7 +75,7 @@ renderer_get_size(GtkCellRenderer *renderer, GtkWidget *widget, GdkRectangle *ar
|
|||
*yoffset = 0;
|
||||
|
||||
if (width)
|
||||
*width = num_lanes(self) * self->priv->lane_width;
|
||||
*width = total_width(self, widget);
|
||||
|
||||
if (height)
|
||||
*height = area ? area->height : 1;
|
||||
|
@ -172,6 +184,18 @@ draw_paths(GitgCellRendererPath *self, cairo_t *cr, GdkRectangle *area)
|
|||
draw_arrows(self, cr, area);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_labels(GitgCellRendererPath *self, GtkWidget *widget, cairo_t *context, GdkRectangle *area)
|
||||
{
|
||||
gint offset = num_lanes(self) * self->priv->lane_width;
|
||||
PangoFontDescription *font;
|
||||
|
||||
g_object_get(self, "font-desc", &font, NULL);
|
||||
|
||||
cairo_translate(context, offset, 0.0);
|
||||
gitg_label_renderer_draw(widget, font, context, self->priv->labels, area);
|
||||
}
|
||||
|
||||
static void
|
||||
renderer_render(GtkCellRenderer *renderer, GdkDrawable *window, GtkWidget *widget, GdkRectangle *area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags)
|
||||
{
|
||||
|
@ -192,11 +216,13 @@ renderer_render(GtkCellRenderer *renderer, GdkDrawable *window, GtkWidget *widge
|
|||
gitg_color_set_cairo_source(((GitgLane *)g_slist_nth_data(self->priv->lanes, self->priv->lane))->color, cr);
|
||||
|
||||
cairo_fill(cr);
|
||||
|
||||
|
||||
// draw labels
|
||||
draw_labels(self, widget, cr, area);
|
||||
cairo_destroy(cr);
|
||||
|
||||
area->x += total_width(self);
|
||||
cell_area->x += total_width(self);
|
||||
area->x += total_width(self, widget);
|
||||
cell_area->x += total_width(self, widget);
|
||||
|
||||
if (GTK_CELL_RENDERER_CLASS(parent_class)->render)
|
||||
GTK_CELL_RENDERER_CLASS(parent_class)->render(renderer, window, widget, area, cell_area, expose_area, flags);
|
||||
|
@ -224,6 +250,9 @@ gitg_cell_renderer_path_get_property(GObject *object, guint prop_id, GValue *val
|
|||
case PROP_DOT_WIDTH:
|
||||
g_value_set_uint(value, self->priv->dot_width);
|
||||
break;
|
||||
case PROP_LABELS:
|
||||
g_value_set_pointer(value, self->priv->labels);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -241,9 +270,11 @@ gitg_cell_renderer_path_set_property(GObject *object, guint prop_id, const GValu
|
|||
self->priv->lane = g_value_get_int(value);
|
||||
break;
|
||||
case PROP_LANES:
|
||||
g_slist_free(self->priv->lanes);
|
||||
self->priv->lanes = (GSList *)g_value_get_pointer(value);
|
||||
break;
|
||||
case PROP_NEXT_LANES:
|
||||
g_slist_free(self->priv->next_lanes);
|
||||
self->priv->next_lanes = (GSList *)g_value_get_pointer(value);
|
||||
break;
|
||||
case PROP_LANE_WIDTH:
|
||||
|
@ -252,6 +283,10 @@ gitg_cell_renderer_path_set_property(GObject *object, guint prop_id, const GValu
|
|||
case PROP_DOT_WIDTH:
|
||||
self->priv->dot_width = g_value_get_uint(value);
|
||||
break;
|
||||
case PROP_LABELS:
|
||||
g_slist_free(self->priv->labels);
|
||||
self->priv->labels = (GSList *)g_value_get_pointer(value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -312,6 +347,12 @@ gitg_cell_renderer_path_class_init(GitgCellRendererPathClass *klass)
|
|||
DEFAULT_DOT_WIDTH,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property(object_class, PROP_LABELS,
|
||||
g_param_spec_pointer("labels",
|
||||
"LABELS",
|
||||
"Labels",
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_type_class_add_private(object_class, sizeof(GitgCellRendererPathPrivate));
|
||||
}
|
||||
|
||||
|
|
121
gitg/gitg-label-renderer.c
Normal file
121
gitg/gitg-label-renderer.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
#include "gitg-label-renderer.h"
|
||||
#include "gitg-ref.h"
|
||||
#include <math.h>
|
||||
|
||||
#define PADDING 4
|
||||
#define MARGIN 3
|
||||
|
||||
gint
|
||||
gitg_label_renderer_width(GtkWidget *widget, PangoFontDescription *font, GSList *labels)
|
||||
{
|
||||
gint width = 0;
|
||||
GSList *item;
|
||||
|
||||
if (labels == NULL)
|
||||
return 0;
|
||||
|
||||
PangoContext *ctx = gtk_widget_get_pango_context(widget);
|
||||
PangoLayout *layout = pango_layout_new(ctx);
|
||||
pango_layout_set_font_description(layout, font);
|
||||
|
||||
for (item = labels; item; item = item->next)
|
||||
{
|
||||
gint w;
|
||||
GitgRef *ref = (GitgRef *)item->data;
|
||||
gchar *smaller = g_strdup_printf("<span size='smaller'>%s</span>", ref->shortname);
|
||||
pango_layout_set_markup(layout, smaller, -1);
|
||||
|
||||
pango_layout_get_pixel_size(layout, &w, NULL);
|
||||
|
||||
width += w + PADDING * 2 + MARGIN;
|
||||
g_free(smaller);
|
||||
}
|
||||
|
||||
g_object_unref(layout);
|
||||
//g_object_unref(ctx);
|
||||
|
||||
return width + MARGIN;
|
||||
}
|
||||
|
||||
static void
|
||||
rounded_rectangle(cairo_t *ctx, float x, float y, float width, float height, float radius)
|
||||
{
|
||||
cairo_move_to(ctx, x + radius, y);
|
||||
cairo_rel_line_to(ctx, width - 2 * radius, 0);
|
||||
cairo_arc(ctx, x + width - radius, y + radius, radius, 1.5 * M_PI, 0.0);
|
||||
|
||||
cairo_rel_line_to(ctx, 0, height - 2 * radius);
|
||||
cairo_arc(ctx, x + width - radius, y + height - radius, radius, 0.0, 0.5 * M_PI);
|
||||
|
||||
cairo_rel_line_to(ctx, -(width - radius * 2), 0);
|
||||
cairo_arc(ctx, x + radius, y + height - radius, radius, 0.5 * M_PI, M_PI);
|
||||
|
||||
cairo_rel_line_to(ctx, 0, -(height - radius * 2));
|
||||
cairo_arc(ctx, x + radius, y + radius, radius, M_PI, 1.5 * M_PI);
|
||||
}
|
||||
|
||||
static void
|
||||
set_source_for_ref_type(cairo_t *context, GitgRefType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GITG_REF_TYPE_NONE:
|
||||
cairo_set_source_rgb(context, 1, 1, 0.8);
|
||||
break;
|
||||
case GITG_REF_TYPE_BRANCH:
|
||||
cairo_set_source_rgb(context, 0.8, 1, 0.5);
|
||||
break;
|
||||
case GITG_REF_TYPE_REMOTE:
|
||||
cairo_set_source_rgb(context, 0.5, 0.8, 1);
|
||||
break;
|
||||
case GITG_REF_TYPE_TAG:
|
||||
cairo_set_source_rgb(context, 1, 1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gitg_label_renderer_draw(GtkWidget *widget, PangoFontDescription *font, cairo_t *context, GSList *labels, GdkRectangle *area)
|
||||
{
|
||||
GSList *item;
|
||||
double pos = MARGIN + 0.5;
|
||||
|
||||
cairo_save(context);
|
||||
cairo_set_line_width(context, 1.0);
|
||||
|
||||
PangoContext *ctx = gtk_widget_get_pango_context(widget);
|
||||
PangoLayout *layout = pango_layout_new(ctx);
|
||||
pango_layout_set_font_description(layout, font);
|
||||
|
||||
for (item = labels; item; item = item->next)
|
||||
{
|
||||
GitgRef *ref = (GitgRef *)item->data;
|
||||
gint w;
|
||||
gint h;
|
||||
gchar *smaller = g_strdup_printf("<span size='smaller'>%s</span>", ref->shortname);
|
||||
|
||||
pango_layout_set_markup(layout, smaller, -1);
|
||||
pango_layout_get_pixel_size(layout, &w, &h);
|
||||
|
||||
// draw rounded rectangle
|
||||
rounded_rectangle(context, pos + 0.5, area->y + MARGIN + 0.5, w + PADDING * 2, area->height - MARGIN * 2, 5);
|
||||
|
||||
|
||||
set_source_for_ref_type(context, ref->type);
|
||||
cairo_fill_preserve(context);
|
||||
|
||||
cairo_set_source_rgb(context, 0, 0, 0);
|
||||
cairo_stroke(context);
|
||||
|
||||
cairo_save(context);
|
||||
cairo_translate(context, pos + PADDING, area->y + (area->height - h) / 2.0 + 0.5);
|
||||
pango_cairo_show_layout(context, layout);
|
||||
cairo_restore(context);
|
||||
|
||||
pos += w + PADDING * 2 + MARGIN;
|
||||
g_free(smaller);
|
||||
}
|
||||
|
||||
g_object_unref(layout);
|
||||
cairo_restore(context);
|
||||
}
|
11
gitg/gitg-label-renderer.h
Normal file
11
gitg/gitg-label-renderer.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef __GITG_LABEL_RENDERER_H__
|
||||
#define __GITG_LABEL_RENDERER_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <pango/pango.h>
|
||||
|
||||
gint gitg_label_renderer_width(GtkWidget *widget, PangoFontDescription *description, GSList *labels);
|
||||
void gitg_label_renderer_draw(GtkWidget *widget, PangoFontDescription *description, cairo_t *context, GSList *labels, GdkRectangle *area);
|
||||
|
||||
#endif /* __GITG_LABEL_RENDERER_H__ */
|
||||
|
69
gitg/gitg-ref.c
Normal file
69
gitg/gitg-ref.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include "gitg-ref.h"
|
||||
#include "gitg-utils.h"
|
||||
#include <string.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar const *prefix;
|
||||
GitgRefType type;
|
||||
} PrefixTypeMap;
|
||||
|
||||
GitgRef *
|
||||
gitg_ref_new(gchar const *hash, gchar const *name)
|
||||
{
|
||||
GitgRef *inst = g_new0(GitgRef, 1);
|
||||
|
||||
gitg_utils_sha1_to_hash(hash, inst->hash);
|
||||
inst->name = g_strdup(name);
|
||||
|
||||
PrefixTypeMap map[] = {
|
||||
{"refs/heads/", GITG_REF_TYPE_BRANCH},
|
||||
{"refs/remotes/", GITG_REF_TYPE_REMOTE},
|
||||
{"refs/tags/", GITG_REF_TYPE_TAG}
|
||||
};
|
||||
|
||||
// set type from name
|
||||
int i;
|
||||
for (i = 0; i < sizeof(map) / sizeof(PrefixTypeMap); ++i)
|
||||
{
|
||||
if (!g_str_has_prefix(name, map[i].prefix))
|
||||
continue;
|
||||
|
||||
inst->type = map[i].type;
|
||||
inst->shortname = g_strdup(name + strlen(map[i].prefix));
|
||||
break;
|
||||
}
|
||||
|
||||
if (inst->shortname == NULL)
|
||||
{
|
||||
inst->type = GITG_REF_TYPE_NONE;
|
||||
inst->shortname = g_strdup(name);
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
GitgRef *
|
||||
gitg_ref_copy(GitgRef *ref)
|
||||
{
|
||||
GitgRef *ret = g_new0(GitgRef, 1);
|
||||
|
||||
ret->type = ref->type;
|
||||
ret->name = g_strdup(ref->name);
|
||||
ret->shortname = g_strdup(ref->shortname);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 20; ++i)
|
||||
ret->hash[i] = ref->hash[i];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
gitg_ref_free(GitgRef *ref)
|
||||
{
|
||||
g_free(ref->name);
|
||||
g_free(ref->shortname);
|
||||
|
||||
g_free(ref);
|
||||
}
|
27
gitg/gitg-ref.h
Normal file
27
gitg/gitg-ref.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef __GITG_REF_H__
|
||||
#define __GITG_REF_H__
|
||||
|
||||
#include "gitg-types.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GITG_REF_TYPE_NONE = 0,
|
||||
GITG_REF_TYPE_BRANCH,
|
||||
GITG_REF_TYPE_REMOTE,
|
||||
GITG_REF_TYPE_TAG
|
||||
} GitgRefType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Hash hash;
|
||||
GitgRefType type;
|
||||
gchar *name;
|
||||
gchar *shortname;
|
||||
} GitgRef;
|
||||
|
||||
GitgRef *gitg_ref_new(gchar const *hash, gchar const *name);
|
||||
void gitg_ref_free(GitgRef *ref);
|
||||
GitgRef *gitg_ref_copy(GitgRef *ref);
|
||||
|
||||
#endif /* __GITG_REF_H__ */
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
#include "gitg-repository.h"
|
||||
#include "gitg-utils.h"
|
||||
#include "gitg-lanes.h"
|
||||
#include "gitg-ref.h"
|
||||
#include "gitg-types.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <time.h>
|
||||
|
@ -39,6 +41,7 @@ struct _GitgRepositoryPrivate
|
|||
|
||||
GitgRevision **storage;
|
||||
GitgLanes *lanes;
|
||||
GHashTable *refs;
|
||||
|
||||
gulong size;
|
||||
gulong allocated;
|
||||
|
@ -289,6 +292,13 @@ do_clear(GitgRepository *repository, gboolean emit)
|
|||
repository->priv->storage = NULL;
|
||||
repository->priv->size = 0;
|
||||
repository->priv->allocated = 0;
|
||||
|
||||
/* clear hash tables */
|
||||
g_hash_table_ref(repository->priv->hashtable);
|
||||
g_hash_table_ref(repository->priv->refs);
|
||||
|
||||
g_hash_table_destroy(repository->priv->hashtable);
|
||||
g_hash_table_destroy(repository->priv->refs);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -310,6 +320,7 @@ gitg_repository_finalize(GObject *object)
|
|||
|
||||
// Free the hash
|
||||
g_hash_table_destroy(rp->priv->hashtable);
|
||||
g_hash_table_destroy(rp->priv->refs);
|
||||
|
||||
G_OBJECT_CLASS (gitg_repository_parent_class)->finalize(object);
|
||||
}
|
||||
|
@ -415,6 +426,13 @@ on_loader_update(GitgRunner *object, gchar **buffer, GitgRepository *self)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_refs(GSList *refs)
|
||||
{
|
||||
g_slist_foreach(refs, (GFunc)gitg_ref_free, NULL);
|
||||
g_slist_free(refs);
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_repository_init(GitgRepository *object)
|
||||
{
|
||||
|
@ -429,6 +447,7 @@ gitg_repository_init(GitgRepository *object)
|
|||
object->priv->lanes = gitg_lanes_new();
|
||||
object->priv->grow_size = 1000;
|
||||
object->priv->stamp = g_random_int();
|
||||
object->priv->refs = g_hash_table_new_full(gitg_utils_hash_hash, gitg_utils_hash_equal, NULL, (GDestroyNotify)free_refs);
|
||||
|
||||
object->priv->loader = gitg_runner_new(5000);
|
||||
g_signal_connect(object->priv->loader, "update", G_CALLBACK(on_loader_update), object);
|
||||
|
@ -475,6 +494,34 @@ gitg_repository_get_loader(GitgRepository *self)
|
|||
return GITG_RUNNER(g_object_ref(self->priv->loader));
|
||||
}
|
||||
|
||||
static void
|
||||
add_ref(GitgRepository *self, gchar const *sha1, gchar const *name)
|
||||
{
|
||||
GitgRef *ref = gitg_ref_new(sha1, name);
|
||||
GSList *refs = (GSList *)g_hash_table_lookup(self->priv->refs, ref->hash);
|
||||
|
||||
if (refs == NULL)
|
||||
g_hash_table_insert(self->priv->refs, ref->hash, g_slist_append(NULL, ref));
|
||||
else
|
||||
refs = g_slist_append(refs, ref);
|
||||
}
|
||||
|
||||
static void
|
||||
on_refs_update(GitgRunner *runner, gchar **buffer, GitgRepository *self)
|
||||
{
|
||||
while (*buffer)
|
||||
{
|
||||
// each line will look like <name> <hash>
|
||||
gchar **components = g_strsplit(*buffer, " ", 2);
|
||||
|
||||
if (g_strv_length(components) == 2)
|
||||
add_ref(self, components[1], components[0]);
|
||||
|
||||
g_strfreev(components);
|
||||
++buffer;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gitg_repository_load(GitgRepository *self, int argc, gchar const **av, GError **error)
|
||||
{
|
||||
|
@ -491,11 +538,24 @@ gitg_repository_load(GitgRepository *self, int argc, gchar const **av, GError **
|
|||
gitg_runner_cancel(self->priv->loader);
|
||||
gitg_repository_clear(self);
|
||||
|
||||
/* first get the refs */
|
||||
gchar *dotgit = gitg_utils_dot_git_path(self->priv->path);
|
||||
gchar const **argv = g_new0(gchar const *, 7 + (argc > 0 ? argc - 1 : 0));
|
||||
gchar const **argv;
|
||||
GitgRunner *refs_runner = gitg_runner_new_synchronized(5000);
|
||||
|
||||
g_signal_connect(refs_runner, "update", G_CALLBACK(on_refs_update), self);
|
||||
|
||||
argv = g_new0(gchar const *, 7 + (argc > 0 ? argc - 1 : 0));
|
||||
argv[0] = "git";
|
||||
argv[1] = "--git-dir";
|
||||
argv[2] = dotgit;
|
||||
argv[3] = "for-each-ref";
|
||||
argv[4] = "--format=%(refname) %(objectname)";
|
||||
argv[5] = "refs";
|
||||
|
||||
gitg_runner_run(refs_runner, argv, NULL);
|
||||
g_object_unref(refs_runner);
|
||||
|
||||
argv[3] = "log";
|
||||
argv[4] = "--pretty=format:%H\01%an\01%s\01%P\01%at";
|
||||
|
||||
|
@ -508,6 +568,7 @@ gitg_repository_load(GitgRepository *self, int argc, gchar const **av, GError **
|
|||
|
||||
gboolean ret = gitg_runner_run(self->priv->loader, argv, error);
|
||||
g_free(dotgit);
|
||||
g_free(argv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -574,3 +635,29 @@ gitg_repository_find(GitgRepository *store, GitgRevision *revision, GtkTreeIter
|
|||
return gitg_repository_find_by_hash(store, gitg_revision_get_hash(revision), iter);
|
||||
}
|
||||
|
||||
GSList *
|
||||
gitg_repository_get_refs(GitgRepository *repository)
|
||||
{
|
||||
g_return_val_if_fail(GITG_IS_REPOSITORY(repository), NULL);
|
||||
GList *values = g_hash_table_get_values(repository->priv->refs);
|
||||
GSList *ret = NULL;
|
||||
GList *item;
|
||||
|
||||
for (item = values; item; item = item->next)
|
||||
{
|
||||
GSList *val;
|
||||
|
||||
for (val = (GSList *)item->data; val; val = val->next)
|
||||
ret = g_slist_append(ret, gitg_ref_copy((GitgRef *)val->data));
|
||||
}
|
||||
|
||||
g_list_free(values);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GSList *
|
||||
gitg_repository_get_refs_for_hash(GitgRepository *repository, gchar const *hash)
|
||||
{
|
||||
g_return_val_if_fail(GITG_IS_REPOSITORY(repository), NULL);
|
||||
return g_slist_copy((GSList *)g_hash_table_lookup(repository->priv->refs, hash));
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ void gitg_repository_clear(GitgRepository *repository);
|
|||
gboolean gitg_repository_find_by_hash(GitgRepository *self, gchar const *hash, GtkTreeIter *iter);
|
||||
gboolean gitg_repository_find(GitgRepository *store, GitgRevision *revision, GtkTreeIter *iter);
|
||||
|
||||
GSList *gitg_repository_get_refs(GitgRepository *repository);
|
||||
GSList *gitg_repository_get_refs_for_hash(GitgRepository *repository, gchar const *hash);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GITG_REPOSITORY_H__ */
|
||||
|
|
|
@ -14,7 +14,7 @@ G_BEGIN_DECLS
|
|||
#define GITG_IS_REVISION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_REVISION))
|
||||
#define GITG_REVISION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_REVISION, GitgRevisionClass))
|
||||
|
||||
typedef gchar Hash[20];
|
||||
#include "gitg-types.h"
|
||||
|
||||
typedef struct _GitgRevision GitgRevision;
|
||||
typedef struct _GitgRevisionClass GitgRevisionClass;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "sexy-icon-entry.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "gitg-ref.h"
|
||||
#include "gitg-utils.h"
|
||||
#include "gitg-runner.h"
|
||||
#include "gitg-window.h"
|
||||
|
@ -19,7 +20,6 @@ struct _GitgWindowPrivate
|
|||
{
|
||||
GitgRepository *repository;
|
||||
GtkListStore *branches_store;
|
||||
GitgRunner *branches_runner;
|
||||
|
||||
// Widget placeholders
|
||||
GtkTreeView *tree_view;
|
||||
|
@ -31,7 +31,6 @@ struct _GitgWindowPrivate
|
|||
};
|
||||
|
||||
static void gitg_window_buildable_iface_init(GtkBuildableIface *iface);
|
||||
static void on_branches_update(GitgRunner *runner, gchar **buffer, GitgWindow *self);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED(GitgWindow, gitg_window, GTK_TYPE_WINDOW, 0,
|
||||
G_IMPLEMENT_INTERFACE(GTK_TYPE_BUILDABLE, gitg_window_buildable_iface_init));
|
||||
|
@ -42,10 +41,7 @@ static GtkWindowClass *parent_class = NULL;
|
|||
static void
|
||||
gitg_window_finalize(GObject *object)
|
||||
{
|
||||
GitgWindow *self = GITG_WINDOW(object);
|
||||
|
||||
gitg_runner_cancel(self->priv->branches_runner);
|
||||
g_object_unref(self->priv->branches_runner);
|
||||
//GitgWindow *self = GITG_WINDOW(object);
|
||||
|
||||
G_OBJECT_CLASS(gitg_window_parent_class)->finalize(object);
|
||||
}
|
||||
|
@ -225,7 +221,9 @@ on_renderer_path(GtkTreeViewColumn *column, GitgCellRendererPath *renderer, GtkT
|
|||
g_object_unref(next);
|
||||
}
|
||||
|
||||
g_object_set(renderer, "lane", gitg_revision_get_mylane(rv), "lanes", gitg_revision_get_lanes(rv), "next_lanes", next_lanes, NULL);
|
||||
GSList *labels = gitg_repository_get_refs_for_hash(GITG_REPOSITORY(model), gitg_revision_get_hash(rv));
|
||||
|
||||
g_object_set(renderer, "lane", gitg_revision_get_mylane(rv), "lanes", gitg_revision_get_lanes(rv), "next_lanes", next_lanes, "labels", labels, NULL);
|
||||
|
||||
g_object_unref(rv);
|
||||
}
|
||||
|
@ -270,9 +268,6 @@ build_branches_combo(GitgWindow *window, GtkBuilder *builder)
|
|||
gtk_list_store_append(window->priv->branches_store, &iter);
|
||||
gtk_list_store_set(window->priv->branches_store, &iter, 0, _("Select branch"), -1);
|
||||
|
||||
gtk_list_store_append(window->priv->branches_store, &iter);
|
||||
gtk_list_store_set(window->priv->branches_store, &iter, 0, NULL, -1);
|
||||
|
||||
gtk_combo_box_set_model(combo, GTK_TREE_MODEL(window->priv->branches_store));
|
||||
gtk_combo_box_set_active(combo, 0);
|
||||
|
||||
|
@ -340,31 +335,10 @@ gitg_window_class_init(GitgWindowClass *klass)
|
|||
g_type_class_add_private(object_class, sizeof(GitgWindowPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
on_branches_update(GitgRunner *runner, gchar **buffer, GitgWindow *self)
|
||||
{
|
||||
gchar *ptr;
|
||||
|
||||
while ((ptr = *buffer++))
|
||||
{
|
||||
while (*ptr == '*' || *ptr == ' ' || *ptr == '\t')
|
||||
++ptr;
|
||||
|
||||
GtkTreeIter iter;
|
||||
gtk_list_store_append(self->priv->branches_store, &iter);
|
||||
gtk_list_store_set(self->priv->branches_store, &iter, 0, ptr, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_window_init(GitgWindow *self)
|
||||
{
|
||||
self->priv = GITG_WINDOW_GET_PRIVATE(self);
|
||||
self->priv->branches_runner = gitg_runner_new(100);
|
||||
|
||||
g_signal_connect(self->priv->branches_runner,
|
||||
"update", G_CALLBACK(on_branches_update),
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -435,31 +409,53 @@ create_repository(GitgWindow *window, gchar const *path)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
sort_by_ref_type(GitgRef const *a, GitgRef const *b)
|
||||
{
|
||||
return a->type - b->type;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_branches_combo(GitgWindow *window)
|
||||
{
|
||||
gchar *dotgit = gitg_utils_dot_git_path(gitg_repository_get_path(window->priv->repository));
|
||||
gchar const *argv[] = {
|
||||
"git",
|
||||
"--git-dir",
|
||||
dotgit,
|
||||
"branch",
|
||||
"-a",
|
||||
"--no-color",
|
||||
NULL
|
||||
};
|
||||
|
||||
GtkTreeIter iter;
|
||||
if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(window->priv->branches_store), &iter, NULL, 2))
|
||||
if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(window->priv->branches_store), &iter, NULL, 1))
|
||||
{
|
||||
while (gtk_list_store_remove(window->priv->branches_store, &iter))
|
||||
;
|
||||
}
|
||||
|
||||
gtk_combo_box_set_active(window->priv->combo_branches, 0);
|
||||
GSList *refs = gitg_repository_get_refs(window->priv->repository);
|
||||
|
||||
refs = g_slist_sort(refs, (GCompareFunc)sort_by_ref_type);
|
||||
GSList *item;
|
||||
GitgRefType prevtype = GITG_REF_TYPE_NONE;
|
||||
|
||||
gitg_runner_run(window->priv->branches_runner, argv, NULL);
|
||||
g_free(dotgit);
|
||||
for (item = refs; item; item = item->next)
|
||||
{
|
||||
GitgRef *ref = (GitgRef *)item->data;
|
||||
|
||||
if (!(ref->type == GITG_REF_TYPE_REMOTE ||
|
||||
ref->type == GITG_REF_TYPE_BRANCH))
|
||||
continue;
|
||||
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (ref->type != prevtype)
|
||||
{
|
||||
gtk_list_store_append(window->priv->branches_store, &iter);
|
||||
gtk_list_store_set(window->priv->branches_store, &iter, 0, NULL, -1);
|
||||
|
||||
prevtype = ref->type;
|
||||
}
|
||||
|
||||
gtk_list_store_append(window->priv->branches_store, &iter);
|
||||
gtk_list_store_set(window->priv->branches_store, &iter, 0, ref->shortname, -1);
|
||||
}
|
||||
|
||||
g_slist_foreach(refs, (GFunc)gitg_ref_free, NULL);
|
||||
g_slist_free(refs);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue