[gitg] Use nested branches in combo
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: svn-commits-list gnome org
- Subject: [gitg] Use nested branches in combo
- Date: Tue, 23 Jun 2009 15:56:09 -0400 (EDT)
commit 75b5b5b90c5c8e5b1afc13be94ebf133ecb646ef
Author: Jesse van den Kieboom <jesse icecrew nl>
Date: Tue Jun 23 21:47:38 2009 +0200
Use nested branches in combo
GitgRef is now also a proper GType (Boxed)
gitg/gitg-commit-view.c | 3 -
gitg/gitg-label-renderer.c | 8 ++-
gitg/gitg-ref.c | 92 +++++++++++++++++++++++++
gitg/gitg-ref.h | 42 +++++++++---
gitg/gitg-repository.c | 14 +++-
gitg/gitg-window.c | 161 ++++++++++++++++++++++++++++++++++----------
6 files changed, 264 insertions(+), 56 deletions(-)
---
diff --git a/gitg/gitg-commit-view.c b/gitg/gitg-commit-view.c
index e5fd8de..64fa73d 100644
--- a/gitg/gitg-commit-view.c
+++ b/gitg/gitg-commit-view.c
@@ -777,8 +777,6 @@ on_tree_view_drag_data_get (GtkWidget *widget,
guint time,
GitgCommitView *view)
{
- GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
- GtkTreeModel *model;
GList *selected;
GList *item;
gchar **uris;
@@ -818,7 +816,6 @@ on_tree_view_staged_drag_data_received(GtkWidget *widget,
/* Stage all the files dropped on this */
gchar **uris = gtk_selection_data_get_uris(data);
gchar **uri;
- GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
for (uri = uris; *uri; ++uri)
{
diff --git a/gitg/gitg-label-renderer.c b/gitg/gitg-label-renderer.c
index c2fe041..43f5e92 100644
--- a/gitg/gitg-label-renderer.c
+++ b/gitg/gitg-label-renderer.c
@@ -44,7 +44,8 @@ gitg_label_renderer_width(GtkWidget *widget, PangoFontDescription *font, GSList
{
gint w;
GitgRef *ref = (GitgRef *)item->data;
- gchar *smaller = g_strdup_printf("<span size='smaller'>%s</span>", ref->shortname);
+ gchar *smaller = g_strdup_printf("<span size='smaller'>%s</span>",
+ gitg_ref_get_shortname(ref));
pango_layout_set_markup(layout, smaller, -1);
pango_layout_get_pixel_size(layout, &w, NULL);
@@ -114,7 +115,8 @@ gitg_label_renderer_draw(GtkWidget *widget, PangoFontDescription *font, cairo_t
GitgRef *ref = (GitgRef *)item->data;
gint w;
gint h;
- gchar *smaller = g_strdup_printf("<span size='smaller'>%s</span>", ref->shortname);
+ gchar *smaller = g_strdup_printf("<span size='smaller'>%s</span>",
+ gitg_ref_get_shortname(ref));
pango_layout_set_markup(layout, smaller, -1);
pango_layout_get_pixel_size(layout, &w, &h);
@@ -123,7 +125,7 @@ gitg_label_renderer_draw(GtkWidget *widget, PangoFontDescription *font, cairo_t
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);
+ set_source_for_ref_type(context, gitg_ref_get_ref_type(ref));
cairo_fill_preserve(context);
cairo_set_source_rgb(context, 0, 0, 0);
diff --git a/gitg/gitg-ref.c b/gitg/gitg-ref.c
index f681893..2e5f826 100644
--- a/gitg/gitg-ref.c
+++ b/gitg/gitg-ref.c
@@ -30,6 +30,32 @@ typedef struct
GitgRefType type;
} PrefixTypeMap;
+struct _GitgRef
+{
+ Hash hash;
+ GitgRefType type;
+
+ gchar *name;
+ gchar *shortname;
+
+ gchar *prefix;
+};
+
+GType
+gitg_ref_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (!our_type)
+ {
+ our_type = g_boxed_type_register_static("GitGRef",
+ (GBoxedCopyFunc)gitg_ref_copy,
+ (GBoxedFreeFunc)gitg_ref_free);
+ }
+
+ return our_type;
+}
+
GitgRef *
gitg_ref_new(gchar const *hash, gchar const *name)
{
@@ -43,16 +69,26 @@ gitg_ref_new(gchar const *hash, gchar const *name)
{"refs/remotes/", GITG_REF_TYPE_REMOTE},
{"refs/tags/", GITG_REF_TYPE_TAG}
};
+
+ inst->prefix = NULL;
// set type from name
int i;
for (i = 0; i < sizeof(map) / sizeof(PrefixTypeMap); ++i)
{
+ gchar *pos;
+
if (!g_str_has_prefix(name, map[i].prefix))
continue;
inst->type = map[i].type;
inst->shortname = g_strdup(name + strlen(map[i].prefix));
+
+ if (map[i].type == GITG_REF_TYPE_REMOTE && (pos = strchr(inst->shortname, '/')))
+ {
+ inst->prefix = g_strndup(inst->shortname, pos - inst->shortname);
+ }
+
break;
}
@@ -73,6 +109,7 @@ gitg_ref_copy(GitgRef *ref)
ret->type = ref->type;
ret->name = g_strdup(ref->name);
ret->shortname = g_strdup(ref->shortname);
+ ret->prefix = g_strdup(ref->prefix);
int i;
for (i = 0; i < HASH_BINARY_SIZE; ++i)
@@ -89,6 +126,61 @@ gitg_ref_free(GitgRef *ref)
g_free(ref->name);
g_free(ref->shortname);
+ g_free(ref->prefix);
g_slice_free(GitgRef, ref);
}
+
+gboolean
+gitg_ref_equal(GitgRef *ref, GitgRef *other)
+{
+ if (ref == NULL && other == NULL)
+ return TRUE;
+
+ if (ref == NULL || other == NULL)
+ return FALSE;
+
+ return strcmp(ref->name, other->name) == 0;
+}
+
+gboolean
+gitg_ref_equal_prefix(GitgRef *ref, GitgRef *other)
+{
+ if (ref == NULL && other == NULL)
+ return TRUE;
+
+ if (ref == NULL || other == NULL)
+ return FALSE;
+
+ return strcmp(ref->prefix, other->prefix) == 0;
+}
+
+gchar const *
+gitg_ref_get_hash(GitgRef *ref)
+{
+ return ref->hash;
+}
+
+GitgRefType
+gitg_ref_get_ref_type(GitgRef *ref)
+{
+ return ref->type;
+}
+
+gchar const *
+gitg_ref_get_name(GitgRef *ref)
+{
+ return ref->name;
+}
+
+gchar const *
+gitg_ref_get_shortname(GitgRef *ref)
+{
+ return ref->shortname;
+}
+
+gchar const *
+gitg_ref_get_prefix(GitgRef *ref)
+{
+ return ref->prefix;
+}
diff --git a/gitg/gitg-ref.h b/gitg/gitg-ref.h
index 32adae7..0948b64 100644
--- a/gitg/gitg-ref.h
+++ b/gitg/gitg-ref.h
@@ -23,8 +23,15 @@
#ifndef __GITG_REF_H__
#define __GITG_REF_H__
+#include <glib-object.h>
#include "gitg-types.h"
+G_BEGIN_DECLS
+
+#define GITG_TYPE_REF (gitg_ref_get_type ())
+#define GITG_REF(obj) ((GitgRef *)obj)
+#define GITG_REF_CONST(obj) ((GitgRef const *)obj)
+
typedef enum
{
GITG_REF_TYPE_NONE = 0,
@@ -33,17 +40,30 @@ typedef enum
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);
+typedef struct _GitgRef GitgRef;
+
+GType gitg_ref_get_type (void) G_GNUC_CONST;
+
+GitgRef *gitg_ref_new (gchar const *hash,
+ gchar const *name);
+
+gchar const *gitg_ref_get_hash (GitgRef *ref);
+GitgRefType gitg_ref_get_ref_type (GitgRef *ref);
+gchar const *gitg_ref_get_name (GitgRef *ref);
+
+gchar const *gitg_ref_get_shortname (GitgRef *ref);
+gchar const *gitg_ref_get_prefix (GitgRef *ref);
+
+GitgRef *gitg_ref_copy (GitgRef *ref);
+void gitg_ref_free (GitgRef *ref);
+
+gboolean gitg_ref_equal (GitgRef *ref,
+ GitgRef *other);
+
+gboolean gitg_ref_equal_prefix (GitgRef *ref,
+ GitgRef *other);
+
+G_END_DECLS
#endif /* __GITG_REF_H__ */
diff --git a/gitg/gitg-repository.c b/gitg/gitg-repository.c
index 3a0a860..0ea9d7d 100644
--- a/gitg/gitg-repository.c
+++ b/gitg/gitg-repository.c
@@ -589,10 +589,11 @@ loader_update_commits(GitgRepository *self, gchar **buffer)
gint64 timestamp = g_ascii_strtoll(components[4], NULL, 0);
GitgRevision *rv = gitg_revision_new(components[0], components[1], components[2], components[3], timestamp);
- GSList *lanes;
if (len > 5 && strlen(components[5]) == 1 && strchr("<>-^", *components[5]) != NULL)
+ {
gitg_revision_set_sign(rv, *components[5]);
+ }
append_revision(self, rv);
g_strfreev(components);
@@ -830,12 +831,19 @@ static GitgRef *
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);
+ GSList *refs = (GSList *)g_hash_table_lookup(self->priv->refs,
+ gitg_ref_get_hash(ref));
if (refs == NULL)
- g_hash_table_insert(self->priv->refs, ref->hash, g_slist_append(NULL, ref));
+ {
+ g_hash_table_insert(self->priv->refs,
+ (gpointer)gitg_ref_get_hash(ref),
+ g_slist_append(NULL, ref));
+ }
else
+ {
refs = g_slist_append(refs, ref);
+ }
return ref;
}
diff --git a/gitg/gitg-window.c b/gitg/gitg-window.c
index c439012..83faea0 100644
--- a/gitg/gitg-window.c
+++ b/gitg/gitg-window.c
@@ -42,11 +42,17 @@
#define GITG_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_WINDOW, GitgWindowPrivate))
+enum
+{
+ COLUMN_BRANCHES_NAME,
+ COLUMN_BRANCHES_REF
+};
+
struct _GitgWindowPrivate
{
GitgRepository *repository;
- GtkListStore *branches_store;
+ GtkTreeStore *branches_store;
/* Widget placeholders */
GtkNotebook *notebook_main;
@@ -64,7 +70,8 @@ struct _GitgWindowPrivate
GtkActionGroup *edit_group;
GtkWidget *open_dialog;
- gchar *current_branch;
+
+ GitgRef *current_branch;
GitgCellRendererPath *renderer_path;
GTimer *load_timer;
@@ -89,7 +96,8 @@ gitg_window_finalize(GObject *object)
{
GitgWindow *self = GITG_WINDOW(object);
- g_free(self->priv->current_branch);
+ gitg_ref_free(self->priv->current_branch);
+
g_timer_destroy(self->priv->load_timer);
gdk_cursor_unref(self->priv->hand);
@@ -304,12 +312,20 @@ on_renderer_path(GtkTreeViewColumn *column, GitgCellRendererPath *renderer, GtkT
static gboolean
branches_separator_func(GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
{
- gchar *t;
+ gchar *name;
+ GitgRef *ref;
- gtk_tree_model_get(model, iter, 0, &t, -1);
- gboolean ret = t == NULL;
+ gtk_tree_model_get(model,
+ iter,
+ COLUMN_BRANCHES_NAME, &name,
+ COLUMN_BRANCHES_REF, &ref,
+ -1);
+
+ gboolean ret = (name == NULL && ref == NULL);
- g_free(t);
+ g_free(name);
+ gitg_ref_free(ref);
+
return ret;
}
@@ -327,9 +343,26 @@ on_branches_combo_changed(GtkComboBox *combo, GitgWindow *window)
next = iter;
if (!gtk_tree_model_iter_next(gtk_combo_box_get_model(combo), &next))
+ {
name = g_strdup("--all");
+ }
else
- gtk_tree_model_get(gtk_combo_box_get_model(combo), &iter, 0, &name, -1);
+ {
+ GitgRef *ref;
+
+ gtk_tree_model_get(gtk_combo_box_get_model(combo),
+ &iter,
+ COLUMN_BRANCHES_REF, &ref,
+ -1);
+
+ if (ref == NULL)
+ {
+ return;
+ }
+
+ name = g_strdup(gitg_ref_get_name(ref));
+ gitg_ref_free(ref);
+ }
gitg_repository_load(window->priv->repository, 1, (gchar const **)&name, NULL);
g_free(name);
@@ -339,12 +372,16 @@ static void
build_branches_combo(GitgWindow *window, GtkBuilder *builder)
{
GtkComboBox *combo = GTK_COMBO_BOX(gtk_builder_get_object(builder, "combo_box_branches"));
- window->priv->branches_store = gtk_list_store_new(1, G_TYPE_STRING);
+ window->priv->branches_store = gtk_tree_store_new(2, G_TYPE_STRING, GITG_TYPE_REF);
window->priv->combo_branches = combo;
GtkTreeIter iter;
- gtk_list_store_append(window->priv->branches_store, &iter);
- gtk_list_store_set(window->priv->branches_store, &iter, 0, _("Select branch"), -1);
+ gtk_tree_store_append(window->priv->branches_store, &iter, NULL);
+ gtk_tree_store_set(window->priv->branches_store,
+ &iter,
+ COLUMN_BRANCHES_NAME, _("Select branch"),
+ COLUMN_BRANCHES_REF, NULL,
+ -1);
gtk_combo_box_set_model(combo, GTK_TREE_MODEL(window->priv->branches_store));
gtk_combo_box_set_active(combo, 0);
@@ -606,20 +643,26 @@ create_repository(GitgWindow *window, gchar const *path, gboolean usewd)
}
static int
-sort_by_ref_type(GitgRef const *a, GitgRef const *b)
+sort_by_ref_type(GitgRef *a, GitgRef *b)
{
- if (a->type == b->type)
+ if (gitg_ref_get_ref_type(a) == gitg_ref_get_ref_type(b))
{
- if (g_ascii_strcasecmp(a->shortname, "master") == 0)
+ if (g_ascii_strcasecmp(gitg_ref_get_shortname(a), "master") == 0)
+ {
return -1;
- else if (g_ascii_strcasecmp(b->shortname, "master") == 0)
+ }
+ else if (g_ascii_strcasecmp(gitg_ref_get_shortname(b), "master") == 0)
+ {
return 1;
+ }
else
- return g_ascii_strcasecmp(a->shortname, b->shortname);
+ {
+ return g_ascii_strcasecmp(gitg_ref_get_shortname(a), gitg_ref_get_shortname(b));
+ }
}
else
{
- return a->type - b->type;
+ return gitg_ref_get_ref_type(a) - gitg_ref_get_ref_type(b);
}
}
@@ -631,19 +674,24 @@ clear_branches_combo(GitgWindow *window, gboolean keepselection)
GtkTreeIter iter;
gtk_combo_box_get_active_iter(GTK_COMBO_BOX(window->priv->combo_branches), &iter);
- g_free(window->priv->current_branch);
- gtk_tree_model_get(GTK_TREE_MODEL(window->priv->branches_store), &iter, 0, &window->priv->current_branch, -1);
+ gitg_ref_free(window->priv->current_branch);
+
+ gtk_tree_model_get(GTK_TREE_MODEL(window->priv->branches_store),
+ &iter,
+ COLUMN_BRANCHES_REF, &window->priv->current_branch,
+ -1);
}
else
{
- g_free(window->priv->current_branch);
+ gitg_ref_free(window->priv->current_branch);
window->priv->current_branch = NULL;
}
GtkTreeIter iter;
+
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))
+ while (gtk_tree_store_remove(window->priv->branches_store, &iter))
;
}
@@ -665,37 +713,78 @@ fill_branches_combo(GitgWindow *window)
refs = g_slist_sort(refs, (GCompareFunc)sort_by_ref_type);
GSList *item;
+
GitgRefType prevtype = GITG_REF_TYPE_NONE;
GtkTreeIter iter;
-
+ GtkTreeIter parent;
+ GitgRef *parentref = NULL;
+ GtkTreeStore *store = window->priv->branches_store;
+
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))
+ if (!(gitg_ref_get_ref_type(ref) == GITG_REF_TYPE_REMOTE ||
+ gitg_ref_get_ref_type(ref) == GITG_REF_TYPE_BRANCH))
continue;
- if (ref->type != prevtype)
+ if (gitg_ref_get_ref_type(ref) != prevtype)
+ {
+ gtk_tree_store_append(store, &iter, NULL);
+ gtk_tree_store_set(store,
+ &iter,
+ COLUMN_BRANCHES_NAME, NULL,
+ COLUMN_BRANCHES_REF, NULL,
+ -1);
+
+ prevtype = gitg_ref_get_ref_type(ref);
+ }
+
+ if (gitg_ref_get_prefix(ref))
{
- gtk_list_store_append(window->priv->branches_store, &iter);
- gtk_list_store_set(window->priv->branches_store, &iter, 0, NULL, -1);
+ if (!parentref || !gitg_ref_equal_prefix(parentref, ref))
+ {
+ parentref = ref;
+
+ gtk_tree_store_append(store, &parent, NULL);
+ gtk_tree_store_set(store,
+ &parent,
+ COLUMN_BRANCHES_NAME, gitg_ref_get_prefix(ref),
+ COLUMN_BRANCHES_REF, NULL,
+ -1);
+ }
- prevtype = ref->type;
+ gtk_tree_store_append(window->priv->branches_store, &iter, &parent);
+ }
+ else
+ {
+ gtk_tree_store_append(window->priv->branches_store, &iter, NULL);
}
- gtk_list_store_append(window->priv->branches_store, &iter);
- gtk_list_store_set(window->priv->branches_store, &iter, 0, ref->shortname, -1);
+ gtk_tree_store_set(window->priv->branches_store,
+ &iter,
+ COLUMN_BRANCHES_NAME, gitg_ref_get_shortname(ref),
+ COLUMN_BRANCHES_REF, ref,
+ -1);
- if (g_strcmp0(window->priv->current_branch, ref->shortname) == 0)
+ if (window->priv->current_branch && gitg_ref_equal(window->priv->current_branch, ref) == 0)
+ {
gtk_combo_box_set_active_iter(window->priv->combo_branches, &iter);
+ }
}
- gtk_list_store_append(window->priv->branches_store, &iter);
- gtk_list_store_set(window->priv->branches_store, &iter, 0, NULL, -1);
-
- gtk_list_store_append(window->priv->branches_store, &iter);
- gtk_list_store_set(window->priv->branches_store, &iter, 0, _("All branches"), -1);
+ gtk_tree_store_append(store, &iter, NULL);
+ gtk_tree_store_set(store,
+ &iter,
+ COLUMN_BRANCHES_NAME, NULL,
+ COLUMN_BRANCHES_REF, NULL, -1);
+
+ gtk_tree_store_append(store, &iter, NULL);
+ gtk_tree_store_set(store,
+ &iter,
+ COLUMN_BRANCHES_NAME, _("All branches"),
+ COLUMN_BRANCHES_REF, NULL,
+ -1);
if (!window->priv->current_branch)
gtk_combo_box_set_active(window->priv->combo_branches, 0);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]