Factorized lane calculation and added lane colors

Lane calculation is now a separate object
Lane coloring is added
This commit is contained in:
Jesse van den Kieboom 2008-07-18 11:58:04 +02:00
parent a5728d475c
commit 6779aa35d0
12 changed files with 553 additions and 243 deletions

View file

@ -23,6 +23,9 @@ gitg_SOURCES = \
gitg-runner.c \
gitg-revision-view.c \
gitg-utils.c \
gitg-lane.c \
gitg-lanes.c \
gitg-color.c \
sexy-icon-entry.c
gitg_LDADD = $(PACKAGE_LIBS)

View file

@ -1,5 +1,7 @@
#include <math.h>
#include "gitg-cell-renderer-path.h"
#include "gitg-lane.h"
#include "gitg-utils.h"
#define GITG_CELL_RENDERER_PATH_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_CELL_RENDERER_PATH, GitgCellRendererPathPrivate))
@ -21,8 +23,8 @@ enum
struct _GitgCellRendererPathPrivate
{
gint8 lane;
gint8 *lanes;
gint8 *next_lanes;
GitgLane **lanes;
GitgLane **next_lanes;
guint lane_width;
guint dot_width;
};
@ -34,16 +36,7 @@ G_DEFINE_TYPE(GitgCellRendererPath, gitg_cell_renderer_path, GTK_TYPE_CELL_RENDE
static gint
num_lanes(GitgCellRendererPath *self)
{
gint ret = 1;
gint8 *ptr = self->priv->lanes;
while (ptr && *ptr != -2)
{
if (*ptr++ == -1)
++ret;
}
return ret;
return gitg_utils_null_length((gconstpointer *)self->priv->lanes);
}
inline static gint
@ -77,7 +70,7 @@ renderer_get_size(GtkCellRenderer *renderer, GtkWidget *widget, GdkRectangle *ar
}
static void
draw_paths_real(GitgCellRendererPath *self, cairo_t *cr, GdkRectangle *area, gint8 *lanes, gboolean top, gdouble yoffset)
draw_paths_real(GitgCellRendererPath *self, cairo_t *cr, GdkRectangle *area, GitgLane **lanes, gboolean top, gdouble yoffset)
{
if (!lanes)
return;
@ -85,24 +78,27 @@ draw_paths_real(GitgCellRendererPath *self, cairo_t *cr, GdkRectangle *area, gin
gint8 to = 0;
gdouble cw = self->priv->lane_width;
gdouble ch = area->height / 2.0;
GitgLane *lane;
for (; *lanes != -2; ++lanes)
while ((lane = *lanes++))
{
if (*lanes == -1)
GSList *item;
for (item = lane->from; item; item = item->next)
{
++to;
continue;
gint8 from = (gint8)GPOINTER_TO_INT(item->data);
gdouble xf = 0.0;
if (from != to)
xf = 0.5 * (to - from);
gitg_color_set_cairo_source(lane->color, cr);
cairo_move_to(cr, area->x + (from + (top ? xf : 0)) * cw + cw / 2.0, area->y + yoffset * ch);
cairo_line_to(cr, area->x + (to - (top ? 0 : xf)) * cw + cw / 2.0, area->y + (yoffset + 1) * ch);
cairo_stroke(cr);
}
gint8 from = *lanes;
gdouble xf = 0.0;
if (from != to)
xf = 0.5 * (to - from);
cairo_move_to(cr, area->x + (from + (top ? xf : 0)) * cw + cw / 2.0, area->y + yoffset * ch);
cairo_line_to(cr, area->x + (to - (top ? 0 : xf)) * cw + cw / 2.0, area->y + (yoffset + 1) * ch);
cairo_stroke(cr);
++to;
}
}
@ -121,8 +117,8 @@ draw_bottom_paths(GitgCellRendererPath *self, cairo_t *cr, GdkRectangle *area)
static void
draw_paths(GitgCellRendererPath *self, cairo_t *cr, GdkRectangle *area)
{
cairo_set_line_width(cr, 1.5);
cairo_set_source_rgb(cr, 0.45, 0.6, 0.74);
cairo_set_line_width(cr, 2);
//cairo_set_source_rgb(cr, 0.45, 0.6, 0.74);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
draw_top_paths(self, cr, area);
draw_bottom_paths(self, cr, area);
@ -142,10 +138,11 @@ renderer_render(GtkCellRenderer *renderer, GdkDrawable *window, GtkWidget *widge
cairo_set_line_width(cr, 2.0);
cairo_arc(cr, area->x + offset + radius, area->y + area->height / 2.0, radius, 0, 2 * M_PI);
cairo_set_source_rgb(cr, 0.12, 0.24, 0.36);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke_preserve(cr);
cairo_set_source_rgb(cr, 0.3, 0.6, 0.7);
gitg_color_set_cairo_source(self->priv->lanes[self->priv->lane]->color, cr);
cairo_fill(cr);
cairo_destroy(cr);
@ -196,10 +193,10 @@ 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:
self->priv->lanes = (gint8 *)g_value_get_pointer(value);
self->priv->lanes = (GitgLane **)g_value_get_pointer(value);
break;
case PROP_NEXT_LANES:
self->priv->next_lanes = (gint8 *)g_value_get_pointer(value);
self->priv->next_lanes = (GitgLane **)g_value_get_pointer(value);
break;
case PROP_LANE_WIDTH:
self->priv->lane_width = g_value_get_uint(value);

117
gitg/gitg-color.c Normal file
View file

@ -0,0 +1,117 @@
#include "gitg-color.h"
#include <gdk/gdk.h>
static gint8 current_index = 0;
static gchar const *palette[] = {
"#c4a000",
"#4e9a06",
"#ce5c00",
"#204a87",
"#2e3436",
"#6c3566",
"#a40000",
"#8ae234",
"#fcaf3e",
"#729fcf",
"#fce94f",
"#888a85",
"#ad7fa8",
"#e9b96e",
"#ef2929"
};
void
gitg_color_reset()
{
current_index = 0;
}
void
gitg_color_get(GitgColor *color, gdouble *r, gdouble *g, gdouble *b)
{
gchar const *spec = palette[color->index];
GdkColor c;
gdk_color_parse(spec, &c);
*r = c.red / 65535.0;
*g = c.green / 65535.0;
*b = c.blue / 65535.0;
}
void
gitg_color_set_cairo_source(GitgColor *color, cairo_t *cr)
{
gdouble r, g, b;
gitg_color_get(color, &r, &g, &b);
cairo_set_source_rgb(cr, r, g, b);
}
static gint8
next_index()
{
gint8 next = current_index++;
if (current_index == sizeof(palette) / sizeof(gchar const *))
current_index = 0;
return next;
}
GitgColor *
gitg_color_next()
{
GitgColor *res = g_new(GitgColor, 1);
res->ref_count = 1;
res->index = next_index();
return res;
}
GitgColor *
gitg_color_next_index(GitgColor *color)
{
color->index = next_index();
return color;
}
GitgColor *
gitg_color_copy(GitgColor *color)
{
GitgColor *copy = g_new(GitgColor, 1);
copy->ref_count = 1;
copy->index = color->index;
return copy;
}
GitgColor *
gitg_color_ref(GitgColor *color)
{
if (!color)
return NULL;
++color->ref_count;
return color;
}
GitgColor *
gitg_color_unref(GitgColor *color)
{
if (!color)
return NULL;
--color->ref_count;
if (color->ref_count == 0)
{
g_free(color);
return NULL;
}
return color;
}

25
gitg/gitg-color.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef __GITG_COLOR_H__
#define __GITG_COLOR_H__
#include <glib.h>
#include <cairo.h>
typedef struct _GitgColor GitgColor;
struct _GitgColor
{
gulong ref_count;
gint8 index;
};
void gitg_color_reset();
void gitg_color_get(GitgColor *color, gdouble *r, gdouble *g, gdouble *b);
void gitg_color_set_cairo_source(GitgColor *color, cairo_t *cr);
GitgColor *gitg_color_next();
GitgColor *gitg_color_next_index(GitgColor *color);
GitgColor *gitg_color_ref(GitgColor *color);
GitgColor *gitg_color_copy(GitgColor *color);
GitgColor *gitg_color_unref(GitgColor *color);
#endif /* __GITG_COLOR_H__ */

39
gitg/gitg-lane.c Normal file
View file

@ -0,0 +1,39 @@
#include "gitg-lane.h"
/* GitgLane functions */
GitgLane *
gitg_lane_copy(GitgLane *lane)
{
GitgLane *copy = g_new(GitgLane, 1);
copy->color = gitg_color_ref(lane->color);
copy->from = g_slist_copy(lane->from);
return copy;
}
GitgLane *
gitg_lane_dup(GitgLane *lane)
{
GitgLane *dup = g_new(GitgLane, 1);
dup->color = gitg_color_copy(lane->color);
dup->from = g_slist_copy(lane->from);
return dup;
}
void
gitg_lane_free(GitgLane *lane)
{
gitg_color_unref(lane->color);
g_slist_free(lane->from);
}
GitgLane *
gitg_lane_new()
{
GitgLane *lane = g_new(GitgLane, 1);
lane->color = gitg_color_next();
lane->from = NULL;
return lane;
}

18
gitg/gitg-lane.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef __GITG_LANE_H__
#define __GITG_LANE_H__
#include <glib.h>
#include "gitg-color.h"
typedef struct _GitgLane
{
GitgColor *color; /** Pointer to color */
GSList *from; /** List of lanes merging on this lane */
} GitgLane;
GitgLane *gitg_lane_new();
GitgLane *gitg_lane_copy(GitgLane *lane);
GitgLane *gitg_lane_dup(GitgLane *lane);
void gitg_lane_free();
#endif /* __GITG_LANE_H__ */

240
gitg/gitg-lanes.c Normal file
View file

@ -0,0 +1,240 @@
#include "gitg-lanes.h"
#include "gitg-utils.h"
#define GITG_LANES_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_LANES, GitgLanesPrivate))
typedef struct _LaneContainer
{
GitgLane *lane;
gchar const *hash;
} LaneContainer;
struct _GitgLanesPrivate
{
GSList *lanes;
};
G_DEFINE_TYPE(GitgLanes, gitg_lanes, G_TYPE_OBJECT)
static void
lane_container_free(LaneContainer *container)
{
gitg_lane_free(container->lane);
g_free(container);
}
static void
free_lanes(GitgLanes *lanes)
{
GSList *item;
for (item = lanes->priv->lanes; item; item = item->next)
lane_container_free((LaneContainer *)item->data);
g_slist_free(lanes->priv->lanes);
}
static LaneContainer *
find_lane_by_hash(GitgLanes *lanes, gchar const *hash, gint8 *pos)
{
GSList *item;
gint8 p = 0;
if (!hash)
return NULL;
for (item = lanes->priv->lanes; item; item = item->next)
{
LaneContainer *container = (LaneContainer *)(item->data);
if (container && container->hash && gitg_utils_hash_equal(container->hash, hash))
{
if (pos)
*pos = p;
return container;
}
++p;
}
return NULL;
}
/* GitgLanes functions */
static void
gitg_lanes_finalize(GObject *object)
{
GitgLanes *self = GITG_LANES(object);
free_lanes(self);
G_OBJECT_CLASS(gitg_lanes_parent_class)->finalize(object);
}
static void
gitg_lanes_class_init(GitgLanesClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->finalize = gitg_lanes_finalize;
g_type_class_add_private(object_class, sizeof(GitgLanesPrivate));
}
static void
gitg_lanes_init(GitgLanes *self)
{
self->priv = GITG_LANES_GET_PRIVATE(self);
}
GitgLanes *
gitg_lanes_new()
{
return GITG_LANES(g_object_new(GITG_TYPE_LANES, NULL));
}
static LaneContainer *
lane_container_new(gchar const *hash)
{
LaneContainer *ret = g_new(LaneContainer, 1);
ret->hash = hash;
ret->lane = gitg_lane_new();
return ret;
}
static GitgLane **
flatten_lanes(GitgLanes *lanes)
{
gint len = g_slist_length(lanes->priv->lanes);
GitgLane **res = g_new(GitgLane *, len + 1);
GSList *item = lanes->priv->lanes;
int i;
for (i = 0; i < len; ++i)
{
res[i] = gitg_lane_copy(((LaneContainer *)(item->data))->lane);
item = item->next;
}
res[len] = NULL;
return res;
}
GitgLane **
gitg_lanes_reset(GitgLanes *lanes, gchar const *hash)
{
free_lanes(lanes);
gitg_color_reset();
lanes->priv->lanes = g_slist_prepend(NULL, lane_container_new(hash));
return flatten_lanes(lanes);
}
static void
init_next_layer(GitgLanes *lanes)
{
GSList *item;
gint8 index = 0;
// Initialize new set of lanes based on 'lanes'. It copies the lane (refs
// the color) and adds the lane index as a merge (so it basicly represents
// a passthrough)
for (item = lanes->priv->lanes; item; item = item->next)
{
LaneContainer *container = (LaneContainer *)(item->data);
GitgLane *lane = gitg_lane_copy(container->lane);
g_slist_free(lane->from);
gitg_lane_free(container->lane);
container->lane = lane;
container->lane->from = g_slist_prepend(NULL, GINT_TO_POINTER((gint)(index++)));
++lanes;
}
}
GitgLane **
gitg_lanes_next(GitgLanes *lanes, GitgRevision *previous, GitgRevision *current, gint8 *currentpos)
{
init_next_layer(lanes);
gint8 mypos;
LaneContainer *mylane = find_lane_by_hash(lanes, gitg_revision_get_hash(previous), &mypos);
if (mylane)
{
GitgColor *nc = gitg_color_copy(mylane->lane->color);
gitg_color_unref(mylane->lane->color);
mylane->lane->color = nc;
mylane->hash = NULL;
}
guint num;
Hash *parents = gitg_revision_get_parents_hash(previous, &num);
int i;
// Iterate over all parents and find them a lane
for (i = 0; i < num; ++i)
{
gint8 lnpos;
LaneContainer *lane = find_lane_by_hash(lanes, parents[i], &lnpos);
if (lane)
{
// There already is a lane for this parent. This means that we add
// mypos as a merge for the lane, also this means the color of
// this lane incluis the merge should change to one color
lane->lane->from = g_slist_append(lane->lane->from, GINT_TO_POINTER((gint)mypos));
gitg_color_next_index(lane->lane->color);
continue;
}
else if (mylane && mylane->hash == NULL)
{
// There is no parent yet which can proceed on the current
// revision lane, so set it now
mylane->hash = (gchar const *)parents[i];
// If there is more than one parent, then also change the color
// since this revision is actually a merge
if (num > 1)
{
gitg_color_unref(mylane->lane->color);
mylane->lane->color = gitg_color_next();
}
}
else
{
// Generate a new lane for this parent
LaneContainer *newlane = lane_container_new(parents[i]);
newlane->lane->from = g_slist_prepend(NULL, GINT_TO_POINTER((gint)mypos));
lanes->priv->lanes = g_slist_append(lanes->priv->lanes, newlane);
if (!mylane)
mylane = newlane;
}
}
// Remove the current lane if it is no longer needed
if (mylane && mylane->hash == NULL)
lanes->priv->lanes = g_slist_remove(lanes->priv->lanes, mylane);
// Determine the lane of the current revision
LaneContainer *lane = find_lane_by_hash(lanes, gitg_revision_get_hash(current), currentpos);
if (!lane)
{
// No lane for this revision reserved, we therefore add a new one
lanes->priv->lanes = g_slist_append(lanes->priv->lanes, lane_container_new(gitg_revision_get_hash(current)));
*currentpos = g_slist_length(lanes->priv->lanes) - 1;
}
return flatten_lanes(lanes);
}

42
gitg/gitg-lanes.h Normal file
View file

@ -0,0 +1,42 @@
#ifndef __GITG_LANES_H__
#define __GITG_LANES_H__
#include <glib-object.h>
#include "gitg-revision.h"
#include "gitg-lane.h"
G_BEGIN_DECLS
#define GITG_TYPE_LANES (gitg_lanes_get_type ())
#define GITG_LANES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_LANES, GitgLanes))
#define GITG_LANES_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_LANES, GitgLanes const))
#define GITG_LANES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_LANES, GitgLanesClass))
#define GITG_IS_LANES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_LANES))
#define GITG_IS_LANES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_LANES))
#define GITG_LANES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_LANES, GitgLanesClass))
typedef struct _GitgLanes GitgLanes;
typedef struct _GitgLanesClass GitgLanesClass;
typedef struct _GitgLanesPrivate GitgLanesPrivate;
struct _GitgLanes {
GObject parent;
GitgLanesPrivate *priv;
};
struct _GitgLanesClass {
GObjectClass parent_class;
};
GType gitg_lanes_get_type (void) G_GNUC_CONST;
GitgLanes *gitg_lanes_new(void);
GitgLane **gitg_lanes_reset(GitgLanes *lanes, gchar const *hash);
GitgLane **gitg_lanes_next(GitgLanes *lanes, GitgRevision *previous, GitgRevision *current, gint8 *mylane);
G_END_DECLS
#endif /* __GITG_LANES_H__ */

View file

@ -1,5 +1,7 @@
#include "gitg-repository.h"
#include "gitg-utils.h"
#include "gitg-lanes.h"
#include <glib/gi18n.h>
#include <time.h>
@ -36,7 +38,7 @@ struct _GitgRepositoryPrivate
GType column_types[N_COLUMNS];
GitgRevision **storage;
GSList *lanes;
GitgLanes *lanes;
gulong size;
gulong allocated;
@ -118,7 +120,9 @@ tree_model_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter)
static gchar *
timestamp_to_str(guint64 timestamp)
{
struct tm *tms = localtime((time_t *)&timestamp);
time_t t = timestamp;
struct tm *tms = localtime(&t);
char buf[255];
strftime(buf, 255, "%c", tms);
@ -241,16 +245,6 @@ tree_model_iter_parent(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter
return FALSE;
}
static GType
gitg_repository_get_column_type(GtkTreeModel *self, int column)
{
/* validate our parameters */
g_return_val_if_fail(GITG_IS_REPOSITORY(self), G_TYPE_INVALID);
g_return_val_if_fail(column >= 0 && column < N_COLUMNS, G_TYPE_INVALID);
return GITG_REPOSITORY(self)->priv->column_types[column];
}
static void
gitg_repository_tree_model_iface_init(GtkTreeModelIface *iface)
{
@ -295,9 +289,6 @@ do_clear(GitgRepository *repository, gboolean emit)
repository->priv->storage = NULL;
repository->priv->size = 0;
repository->priv->allocated = 0;
g_slist_free(repository->priv->lanes);
repository->priv->lanes = NULL;
}
static void
@ -309,6 +300,8 @@ gitg_repository_finalize(GObject *object)
gitg_runner_cancel(rp->priv->loader);
g_object_unref(rp->priv->loader);
g_object_unref(rp->priv->lanes);
// Clear the model to remove all revision objects
do_clear(rp, FALSE);
@ -397,175 +390,6 @@ hash_hash(gconstpointer v)
return h;
}
static gboolean
hash_equal(gconstpointer a, gconstpointer b)
{
return memcmp(a, b, 20) == 0;
}
static GSList *
find_lane_by_hash(GSList *lanes, gchar const *hash, gint8 *pos)
{
GSList *item;
gint8 p = 0;
if (!hash)
return NULL;
for (item = lanes; item; item = item->next)
{
if (item->data && hash_equal(item->data, hash))
{
if (pos)
*pos = p;
return item;
}
++p;
}
return NULL;
}
static GSList *
init_indices(GitgRepository *self)
{
GSList *item;
GSList *res = NULL;
gint8 num = 0;
for (item = self->priv->lanes; item; item = item->next)
{
GArray *ar = g_array_new(FALSE, FALSE, sizeof(gint8));
g_array_append_vals(ar, &num, 1);
res = g_slist_prepend(res, ar);
++num;
}
return g_slist_reverse(res);
}
static gint8 *
flatten_indices(GSList *indices)
{
gint8 *ret = g_new(gint8, 1);
GSList *item;
gint num = 0;
for (item = indices; item; item = item->next)
{
if (item != indices)
{
ret = g_renew(gint8, ret, ++num + 1);
ret[num - 1] = -1;
}
GArray *ar = (GArray *)(item->data);
int i;
for (i = 0; i < ar->len; ++i)
{
ret = g_renew(gint8, ret, ++num + 1);
ret[num - 1] = g_array_index(ar, gint8, i);
}
g_array_free(ar, TRUE);
}
ret[num] = -2;
return ret;
}
static gint8 *
calculate_lane_ids(GitgRepository *self, GitgRevision *rv)
{
// Determine the new lanes given the previous ones and the parents of the
// new revision
gint numlanes = g_slist_length(self->priv->lanes);
GSList *indices = init_indices(self);
gint8 myid;
GSList *mylane = find_lane_by_hash(self->priv->lanes, gitg_revision_get_hash(rv), &myid);
if (mylane)
mylane->data = NULL;
else
g_warning("My lane not found for %s", gitg_revision_get_sha1(rv));
guint num;
Hash *parents = gitg_revision_get_parents_hash(rv, &num);
int i;
// Iterate over all parents and find them a lane
for (i = 0; i < num; ++i)
{
gint8 lnpos;
GSList *lane = find_lane_by_hash(self->priv->lanes, parents[i], &lnpos);
if (lane)
{
// There already is a lane for this hash. Add myid to the
// list for lnpos
g_array_append_vals((GArray *)g_slist_nth_data(indices, lnpos), &myid, 1);
continue;
}
else if (mylane && mylane->data == NULL)
{
// There is no parent yet which can proceed on the current
// revision lane, so set it now
mylane->data = (gpointer)parents[i];
}
else
{
// Generate a new lane for this parent
self->priv->lanes = g_slist_append(self->priv->lanes, (gpointer)parents[i]);
GArray *n = g_array_new(FALSE, FALSE, sizeof(gint8));
g_array_append_vals(n, &myid, 1);
indices = g_slist_append(indices, n);
if (!mylane)
mylane = g_slist_last(self->priv->lanes);
}
}
if (mylane && mylane->data == NULL)
{
// Remove the current lane since it is no longer needed
gpointer item = g_slist_nth_data(indices, myid);
g_array_free((GArray *)item, TRUE);
indices = g_slist_remove(indices, item);
self->priv->lanes = g_slist_remove(self->priv->lanes, mylane->data);
}
gint8 *res = flatten_indices(indices);
g_slist_free(indices);
return res;
}
static gint8 *
append_mylane(GitgRepository *self, gint8 *indices, GitgRevision *rv)
{
gint8 *ptr = indices;
while (*ptr++ != -2)
;
gint num = ptr - indices;
self->priv->lanes = g_slist_append(self->priv->lanes, (gpointer)gitg_revision_get_hash(rv));
indices = g_renew(gint8, indices, num + 1);
indices[num - 1] = -1;
indices[num] = -2;
return indices;
}
static void
on_loader_update(GitgRunner *object, gchar **buffer, GitgRepository *self)
{
@ -586,29 +410,16 @@ on_loader_update(GitgRunner *object, gchar **buffer, GitgRepository *self)
gint64 timestamp = g_ascii_strtoll(components[4], NULL, 0);
GitgRevision *rv = gitg_revision_new(components[0], components[1], components[2], components[3], timestamp);
gint8 *indices = NULL;
GitgLane **lanes = NULL;
gint8 mylane = 0;
if (self->priv->size == 0)
{
self->priv->lanes = g_slist_append(self->priv->lanes, (gpointer)gitg_revision_get_hash(rv));
indices = g_new0(gint8, 2);
indices[1] = -2;
}
lanes = gitg_lanes_reset(self->priv->lanes, gitg_revision_get_hash(rv));
else
{
indices = calculate_lane_ids(self, self->priv->storage[self->priv->size - 1]);
if (find_lane_by_hash(self->priv->lanes, gitg_revision_get_hash(rv), &mylane) == NULL)
{
// No lane for this revision reserved, how this happens, I
// don't know
indices = append_mylane(self, indices, rv);
mylane = g_slist_length(self->priv->lanes) - 1;
}
}
lanes = gitg_lanes_next(self->priv->lanes, self->priv->storage[self->priv->size - 1], rv, &mylane);
gitg_revision_set_lanes(rv, indices);
gitg_revision_set_lanes(rv, lanes);
gitg_revision_set_mylane(rv, mylane);
gitg_repository_add(self, rv, NULL);
@ -622,13 +433,14 @@ static void
gitg_repository_init(GitgRepository *object)
{
object->priv = GITG_REPOSITORY_GET_PRIVATE(object);
object->priv->hashtable = g_hash_table_new_full(hash_hash, hash_equal, NULL, NULL);
object->priv->hashtable = g_hash_table_new_full(hash_hash, gitg_utils_hash_equal, NULL, NULL);
object->priv->column_types[0] = GITG_TYPE_REVISION;
object->priv->column_types[1] = G_TYPE_STRING;
object->priv->column_types[2] = G_TYPE_STRING;
object->priv->column_types[3] = G_TYPE_STRING;
object->priv->lanes = gitg_lanes_new();
object->priv->grow_size = 1000;
object->priv->stamp = g_random_int();

View file

@ -11,7 +11,7 @@ struct _GitgRevisionPrivate
Hash *parents;
guint num_parents;
gint8 *lanes;
GitgLane **lanes;
gint8 mylane;
gint64 timestamp;
@ -19,6 +19,21 @@ struct _GitgRevisionPrivate
G_DEFINE_TYPE(GitgRevision, gitg_revision, G_TYPE_OBJECT)
static void
free_lanes(GitgRevision *rv)
{
if (!rv->priv->lanes)
return;
GitgLane **lanes = rv->priv->lanes;
GitgLane *lane;
while ((lane = *lanes++))
gitg_lane_free(lane);
g_free(rv->priv->lanes);
}
static void
gitg_revision_finalize(GObject *object)
{
@ -27,7 +42,8 @@ gitg_revision_finalize(GObject *object)
g_free(rv->priv->author);
g_free(rv->priv->subject);
g_free(rv->priv->parents);
g_free(rv->priv->lanes);
free_lanes(rv);
G_OBJECT_CLASS(gitg_revision_parent_class)->finalize(object);
}
@ -146,7 +162,7 @@ gitg_revision_get_parents(GitgRevision *revision)
return ret;
}
gint8 *
GitgLane **
gitg_revision_get_lanes(GitgRevision *revision)
{
g_return_val_if_fail(GITG_IS_REVISION(revision), NULL);
@ -154,11 +170,11 @@ gitg_revision_get_lanes(GitgRevision *revision)
}
void
gitg_revision_set_lanes(GitgRevision *revision, gint8 *lanes)
gitg_revision_set_lanes(GitgRevision *revision, GitgLane **lanes)
{
g_return_if_fail(GITG_IS_REVISION(revision));
g_free(revision->priv->lanes);
free_lanes(revision);
revision->priv->lanes = lanes;
}

View file

@ -2,6 +2,7 @@
#define __GITG_REVISION_H__
#include <glib-object.h>
#include "gitg-lane.h"
G_BEGIN_DECLS
@ -43,8 +44,8 @@ inline Hash *gitg_revision_get_parents_hash(GitgRevision *revision, guint *num_p
gchar *gitg_revision_get_sha1(GitgRevision *revision);
gchar **gitg_revision_get_parents(GitgRevision *revision);
gint8 *gitg_revision_get_lanes(GitgRevision *revision);
void gitg_revision_set_lanes(GitgRevision *revision, gint8 *lane_ids);
GitgLane **gitg_revision_get_lanes(GitgRevision *revision);
void gitg_revision_set_lanes(GitgRevision *revision, GitgLane **lanes);
gint8 gitg_revision_get_mylane(GitgRevision *revision);
void gitg_revision_set_mylane(GitgRevision *revision, gint8 mylane);

View file

@ -214,7 +214,7 @@ on_renderer_path(GtkTreeViewColumn *column, GitgCellRendererPath *renderer, GtkT
gtk_tree_model_get(model, iter, 0, &rv, -1);
GtkTreeIter iter1 = *iter;
gint8 *next_lanes = NULL;
GitgLane **next_lanes = NULL;
if (gtk_tree_model_iter_next(model, &iter1))
{