plover-gtk/packagestore.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Feb 20 12:11:02 2010 +0000 (2010-02-20)
changeset 9 8d3b1ddf789c
child 10 8b50be3e2998
permissions -rw-r--r--
First cut at an applications manager
ali@9
     1
/*
ali@9
     2
 * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
ali@9
     3
 * Copyright (C) 2010  J. Ali Harlow <ali@juiblex.co.uk>
ali@9
     4
 *
ali@9
     5
 * This program is free software; you can redistribute it and/or modify
ali@9
     6
 * it under the terms of the GNU General Public License as published by
ali@9
     7
 * the Free Software Foundation; either version 2 of the License, or
ali@9
     8
 * (at your option) any later version.
ali@9
     9
 *
ali@9
    10
 * This program is distributed in the hope that it will be useful,
ali@9
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@9
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@9
    13
 * GNU General Public License for more details.
ali@9
    14
 *
ali@9
    15
 * You should have received a copy of the GNU General Public License along
ali@9
    16
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@9
    17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@9
    18
 */
ali@9
    19
ali@9
    20
#include "config.h"
ali@9
    21
#include <stdlib.h>
ali@9
    22
#include <string.h>
ali@9
    23
#include <glib-object.h>
ali@9
    24
#include <gtk/gtk.h>
ali@9
    25
#include <razor.h>
ali@9
    26
#include "plover/plover.h"
ali@9
    27
#include "plover-gtk/package.h"
ali@9
    28
#include "plover-gtk/packagestore.h"
ali@9
    29
ali@9
    30
#define VALID_ITER(iter,store) ((iter) && (iter)->user_data && \
ali@9
    31
	PLOVER_PACKAGE_STORE_GET_PRIVATE(store)->stamp==(iter)->stamp && \
ali@9
    32
	!g_sequence_iter_is_end((iter)->user_data) && \
ali@9
    33
	g_sequence_iter_get_sequence((iter)->user_data)== \
ali@9
    34
	PLOVER_PACKAGE_STORE_GET_PRIVATE(store)->seq)
ali@9
    35
ali@9
    36
static GType column_types[PLOVER_PACKAGE_STORE_NO_COLUMNS];
ali@9
    37
ali@9
    38
static void plover_package_store_tree_model_init(GtkTreeModelIface *iface);
ali@9
    39
ali@9
    40
G_DEFINE_TYPE_WITH_CODE(PloverPackageStore,plover_package_store,G_TYPE_OBJECT,
ali@9
    41
  G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL,
ali@9
    42
  plover_package_store_tree_model_init));
ali@9
    43
ali@9
    44
typedef struct _PloverPackageStorePrivate {
ali@9
    45
    GSList *sets;
ali@9
    46
    GSequence *seq;
ali@9
    47
    int stamp;
ali@9
    48
} PloverPackageStorePrivate;
ali@9
    49
ali@9
    50
#define PLOVER_PACKAGE_STORE_GET_PRIVATE(obj)\
ali@9
    51
				G_TYPE_INSTANCE_GET_PRIVATE(obj,\
ali@9
    52
				  PLOVER_TYPE_PACKAGE_STORE,\
ali@9
    53
				  PloverPackageStorePrivate)
ali@9
    54
ali@9
    55
static void plover_package_store_finalize(GObject *obj)
ali@9
    56
{
ali@9
    57
    PloverPackageStorePrivate *priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(obj);
ali@9
    58
    g_sequence_free(priv->seq);
ali@9
    59
    if (G_OBJECT_CLASS(plover_package_store_parent_class)->finalize)
ali@9
    60
	G_OBJECT_CLASS(plover_package_store_parent_class)->finalize(obj);
ali@9
    61
}
ali@9
    62
ali@9
    63
static void plover_package_store_dispose(GObject *obj)
ali@9
    64
{
ali@9
    65
    PloverPackageStorePrivate *priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(obj);
ali@9
    66
    g_slist_foreach(priv->sets,(GFunc)g_object_unref,NULL);
ali@9
    67
    g_slist_free(priv->sets);
ali@9
    68
    priv->sets=NULL;
ali@9
    69
    g_sequence_free(priv->seq);
ali@9
    70
    priv->seq=g_sequence_new(NULL);
ali@9
    71
    if (G_OBJECT_CLASS(plover_package_store_parent_class)->dispose)
ali@9
    72
	G_OBJECT_CLASS(plover_package_store_parent_class)->dispose(obj);
ali@9
    73
}
ali@9
    74
ali@9
    75
static void plover_package_store_class_init(PloverPackageStoreClass *klass)
ali@9
    76
{
ali@9
    77
    GObjectClass *oclass=G_OBJECT_CLASS(klass);
ali@9
    78
    oclass->finalize=plover_package_store_finalize;
ali@9
    79
    oclass->dispose=plover_package_store_dispose;
ali@9
    80
    g_type_class_add_private(klass,sizeof(PloverPackageStorePrivate));
ali@9
    81
    column_types[PLOVER_PACKAGE_STORE_OBJ_COLUMN]=PLOVER_TYPE_PACKAGE;
ali@9
    82
    column_types[PLOVER_PACKAGE_STORE_INSTALLED_COLUMN]=G_TYPE_BOOLEAN;
ali@9
    83
    column_types[PLOVER_PACKAGE_STORE_ICON_COLUMN]=GDK_TYPE_PIXBUF;
ali@9
    84
    column_types[PLOVER_PACKAGE_STORE_NAME_COLUMN]=G_TYPE_STRING;
ali@9
    85
    column_types[PLOVER_PACKAGE_STORE_VERSION_COLUMN]=G_TYPE_STRING;
ali@9
    86
    column_types[PLOVER_PACKAGE_STORE_SUMMARY_COLUMN]=G_TYPE_STRING;
ali@9
    87
}
ali@9
    88
ali@9
    89
static GtkTreeModelFlags
ali@9
    90
plover_package_store_get_flags(GtkTreeModel *tree_model)
ali@9
    91
{
ali@9
    92
    return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY;
ali@9
    93
}
ali@9
    94
ali@9
    95
static gint plover_package_store_get_n_columns(GtkTreeModel *tree_model)
ali@9
    96
{
ali@9
    97
    return PLOVER_PACKAGE_STORE_NO_COLUMNS;
ali@9
    98
}
ali@9
    99
ali@9
   100
static GType
ali@9
   101
  plover_package_store_get_column_type(GtkTreeModel *tree_model,gint indx)
ali@9
   102
{
ali@9
   103
    PloverPackageStore *store=(PloverPackageStore *)tree_model;
ali@9
   104
    g_return_val_if_fail(indx>=0 && indx<PLOVER_PACKAGE_STORE_NO_COLUMNS,
ali@9
   105
      G_TYPE_INVALID);
ali@9
   106
    return column_types[indx];
ali@9
   107
}
ali@9
   108
ali@9
   109
static gboolean plover_package_store_get_iter(GtkTreeModel *tree_model,
ali@9
   110
  GtkTreeIter *iter,GtkTreePath *path)
ali@9
   111
{
ali@9
   112
    int i;
ali@9
   113
    PloverPackageStorePrivate *priv;
ali@9
   114
    PloverPackageStore *store=(PloverPackageStore *)tree_model;
ali@9
   115
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
ali@9
   116
    i=gtk_tree_path_get_indices(path)[0];
ali@9
   117
    if (i>=g_sequence_get_length(priv->seq))
ali@9
   118
	return FALSE;
ali@9
   119
    iter->stamp=priv->stamp;
ali@9
   120
    iter->user_data=g_sequence_get_iter_at_pos(priv->seq,i);
ali@9
   121
    return TRUE;
ali@9
   122
}
ali@9
   123
ali@9
   124
static GtkTreePath *
ali@9
   125
  plover_package_store_get_path(GtkTreeModel *tree_model,GtkTreeIter *iter)
ali@9
   126
{
ali@9
   127
    GtkTreePath *path;
ali@9
   128
    g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL);
ali@9
   129
    if (g_sequence_iter_is_end(iter->user_data))
ali@9
   130
	return NULL;
ali@9
   131
    path=gtk_tree_path_new();
ali@9
   132
    gtk_tree_path_append_index(path,
ali@9
   133
      g_sequence_iter_get_position(iter->user_data));
ali@9
   134
    return path;
ali@9
   135
}
ali@9
   136
ali@9
   137
static void plover_package_store_get_value(GtkTreeModel *tree_model,
ali@9
   138
  GtkTreeIter *iter,gint column,GValue *value)
ali@9
   139
{
ali@9
   140
    PloverPackageStore *store=(PloverPackageStore *)tree_model;
ali@9
   141
    PloverPackage *package;
ali@9
   142
    g_return_if_fail(column>=0 && column<PLOVER_PACKAGE_STORE_NO_COLUMNS);
ali@9
   143
    g_return_if_fail(VALID_ITER(iter,store));
ali@9
   144
    package=g_sequence_get(iter->user_data);
ali@9
   145
    g_value_init(value,column_types[column]);
ali@9
   146
    switch((PloverPackageStoreColumn)column)
ali@9
   147
    {
ali@9
   148
	case PLOVER_PACKAGE_STORE_OBJ_COLUMN:
ali@9
   149
	    g_value_set_object(value,package);
ali@9
   150
	    break;
ali@9
   151
	case PLOVER_PACKAGE_STORE_INSTALLED_COLUMN:
ali@9
   152
	    break;
ali@9
   153
	case PLOVER_PACKAGE_STORE_ICON_COLUMN:
ali@9
   154
	    g_value_set_object(value,plover_package_get_icon(package));
ali@9
   155
	    break;
ali@9
   156
	case PLOVER_PACKAGE_STORE_NAME_COLUMN:
ali@9
   157
	    g_value_set_string(value,plover_package_get_name(package));
ali@9
   158
	    break;
ali@9
   159
	case PLOVER_PACKAGE_STORE_VERSION_COLUMN:
ali@9
   160
	    g_value_set_string(value,plover_package_get_version(package));
ali@9
   161
	    break;
ali@9
   162
	case PLOVER_PACKAGE_STORE_SUMMARY_COLUMN:
ali@9
   163
	    g_value_set_string(value,plover_package_get_summary(package));
ali@9
   164
	    break;
ali@9
   165
    }
ali@9
   166
}
ali@9
   167
ali@9
   168
static gboolean
ali@9
   169
  plover_package_store_iter_next(GtkTreeModel *tree_model,GtkTreeIter *iter)
ali@9
   170
{
ali@9
   171
    g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE);
ali@9
   172
    iter->user_data=g_sequence_iter_next(iter->user_data);
ali@9
   173
    return !g_sequence_iter_is_end(iter->user_data);
ali@9
   174
}
ali@9
   175
ali@9
   176
static gboolean plover_package_store_iter_children(GtkTreeModel *tree_model,
ali@9
   177
  GtkTreeIter *iter,GtkTreeIter *parent)
ali@9
   178
{
ali@9
   179
    PloverPackageStorePrivate *priv;
ali@9
   180
    PloverPackageStore *store=(PloverPackageStore *)tree_model;
ali@9
   181
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
ali@9
   182
    /* this is a list, nodes have no children */
ali@9
   183
    if (parent)
ali@9
   184
	return FALSE;
ali@9
   185
    if (g_sequence_get_length(priv->seq)>0)
ali@9
   186
    {
ali@9
   187
	iter->stamp=priv->stamp;
ali@9
   188
	iter->user_data=g_sequence_get_begin_iter(priv->seq);
ali@9
   189
	return TRUE;
ali@9
   190
    }
ali@9
   191
    else
ali@9
   192
	return FALSE;
ali@9
   193
}
ali@9
   194
ali@9
   195
static gboolean plover_package_store_iter_has_child(GtkTreeModel *tree_model,
ali@9
   196
  GtkTreeIter *iter)
ali@9
   197
{
ali@9
   198
    return FALSE;
ali@9
   199
}
ali@9
   200
ali@9
   201
static gint plover_package_store_iter_n_children(GtkTreeModel *tree_model,
ali@9
   202
  GtkTreeIter *iter)
ali@9
   203
{
ali@9
   204
    PloverPackageStorePrivate *priv;
ali@9
   205
    PloverPackageStore *store=(PloverPackageStore *)tree_model;
ali@9
   206
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
ali@9
   207
    if (!iter)
ali@9
   208
	return g_sequence_get_length(priv->seq);
ali@9
   209
    g_return_val_if_fail(VALID_ITER(iter,tree_model),-1);
ali@9
   210
    return 0;
ali@9
   211
}
ali@9
   212
ali@9
   213
static gboolean plover_package_store_iter_nth_child(GtkTreeModel *tree_model,
ali@9
   214
  GtkTreeIter *iter,GtkTreeIter *parent,gint n)
ali@9
   215
{
ali@9
   216
    PloverPackageStorePrivate *priv;
ali@9
   217
    PloverPackageStore *store=(PloverPackageStore *)tree_model;
ali@9
   218
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
ali@9
   219
    GSequenceIter *child;
ali@9
   220
    if (parent)
ali@9
   221
	return FALSE;
ali@9
   222
    child=g_sequence_get_iter_at_pos(priv->seq,n);
ali@9
   223
    if (g_sequence_iter_is_end(child))
ali@9
   224
	return FALSE;
ali@9
   225
    iter->stamp=priv->stamp;
ali@9
   226
    iter->user_data=child;
ali@9
   227
    return TRUE;
ali@9
   228
}
ali@9
   229
ali@9
   230
static gboolean plover_package_store_iter_parent(GtkTreeModel *tree_model,
ali@9
   231
  GtkTreeIter *iter,GtkTreeIter *child)
ali@9
   232
{
ali@9
   233
    return FALSE;
ali@9
   234
}
ali@9
   235
ali@9
   236
static void plover_package_store_tree_model_init(GtkTreeModelIface *iface)
ali@9
   237
{
ali@9
   238
    iface->get_flags=plover_package_store_get_flags;
ali@9
   239
    iface->get_n_columns=plover_package_store_get_n_columns;
ali@9
   240
    iface->get_column_type=plover_package_store_get_column_type;
ali@9
   241
    iface->get_iter=plover_package_store_get_iter;
ali@9
   242
    iface->get_path=plover_package_store_get_path;
ali@9
   243
    iface->get_value=plover_package_store_get_value;
ali@9
   244
    iface->iter_next=plover_package_store_iter_next;
ali@9
   245
    iface->iter_children=plover_package_store_iter_children;
ali@9
   246
    iface->iter_has_child=plover_package_store_iter_has_child;
ali@9
   247
    iface->iter_n_children=plover_package_store_iter_n_children;
ali@9
   248
    iface->iter_nth_child=plover_package_store_iter_nth_child;
ali@9
   249
    iface->iter_parent=plover_package_store_iter_parent;
ali@9
   250
}
ali@9
   251
ali@9
   252
static void plover_package_store_init(PloverPackageStore *store)
ali@9
   253
{
ali@9
   254
    PloverPackageStorePrivate *priv;
ali@9
   255
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
ali@9
   256
    priv->seq=g_sequence_new(NULL);
ali@9
   257
    priv->stamp=g_random_int();
ali@9
   258
}
ali@9
   259
ali@9
   260
PloverPackageStore *plover_package_store_new(void)
ali@9
   261
{
ali@9
   262
    return g_object_new(PLOVER_TYPE_PACKAGE_STORE,NULL);
ali@9
   263
}
ali@9
   264
ali@9
   265
GSList *plover_package_store_get_sets(PloverPackageStore *store)
ali@9
   266
{
ali@9
   267
    PloverPackageStorePrivate *priv;
ali@9
   268
    g_return_val_if_fail(PLOVER_IS_PACKAGE_STORE(store),NULL);
ali@9
   269
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
ali@9
   270
    return priv->sets;
ali@9
   271
}
ali@9
   272
ali@9
   273
static gint
ali@9
   274
  plover__package_compar(gconstpointer a,gconstpointer b,gpointer user_data)
ali@9
   275
{
ali@9
   276
    PloverPackage *pa=PLOVER_PACKAGE(a);
ali@9
   277
    PloverPackage *pb=PLOVER_PACKAGE(b);
ali@9
   278
    return strcmp(plover_package_get_name(pa),plover_package_get_name(pb));
ali@9
   279
}
ali@9
   280
ali@9
   281
void plover_package_store_add_set(PloverPackageStore *store,
ali@9
   282
  PloverPackageSet *set)
ali@9
   283
{
ali@9
   284
    GSList *packages,*link;
ali@9
   285
    GSequenceIter *si;
ali@9
   286
    GtkTreeIter ti;
ali@9
   287
    GtkTreePath *path;
ali@9
   288
    gint *indices;
ali@9
   289
    PloverPackageStorePrivate *priv;
ali@9
   290
    g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store));
ali@9
   291
    g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
ali@9
   292
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
ali@9
   293
    g_return_if_fail(g_slist_find(priv->sets,set) == NULL);
ali@9
   294
    g_object_ref(set);
ali@9
   295
    path=gtk_tree_path_new();
ali@9
   296
    gtk_tree_path_append_index(path,0);
ali@9
   297
    indices=gtk_tree_path_get_indices(path);
ali@9
   298
    packages=plover_package_set_get_packages(set);
ali@9
   299
    for(link=packages;link;link=link->next)
ali@9
   300
    {
ali@9
   301
	si=g_sequence_insert_sorted(priv->seq,link->data,
ali@9
   302
	  plover__package_compar,NULL);
ali@9
   303
	*indices=g_sequence_iter_get_position(si);
ali@9
   304
	ti.stamp=priv->stamp;
ali@9
   305
	ti.user_data=si;
ali@9
   306
	gtk_tree_model_row_inserted(GTK_TREE_MODEL(store),path,&ti);
ali@9
   307
    }
ali@9
   308
    gtk_tree_path_free(path);
ali@9
   309
    priv->sets=g_slist_prepend(priv->sets,set);
ali@9
   310
}
ali@9
   311
ali@9
   312
void plover_package_store_remove_set(PloverPackageStore *store,
ali@9
   313
  PloverPackageSet *set)
ali@9
   314
{
ali@9
   315
    GSList *packages,*link;
ali@9
   316
    GSequence *seq;
ali@9
   317
    GSequenceIter *iter,*prev,*remove;
ali@9
   318
    GtkTreePath *path;
ali@9
   319
    gint *indices;
ali@9
   320
    PloverPackageStorePrivate *priv;
ali@9
   321
    g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store));
ali@9
   322
    g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
ali@9
   323
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
ali@9
   324
    g_return_if_fail(g_slist_find(priv->sets,set) != NULL);
ali@9
   325
    seq=g_sequence_new(NULL);
ali@9
   326
    path=gtk_tree_path_new();
ali@9
   327
    gtk_tree_path_append_index(path,0);
ali@9
   328
    indices=gtk_tree_path_get_indices(path);
ali@9
   329
    packages=plover_package_set_get_packages(set);
ali@9
   330
    for(link=packages;link;link=link->next)
ali@9
   331
	g_sequence_insert_sorted(seq,link->data,plover__package_compar,NULL);
ali@9
   332
    prev=NULL;
ali@9
   333
    iter=g_sequence_get_begin_iter(priv->seq);
ali@9
   334
    remove=g_sequence_get_begin_iter(seq);
ali@9
   335
    while(!g_sequence_iter_is_end(iter) && !g_sequence_iter_is_end(remove))
ali@9
   336
    {
ali@9
   337
	if (g_sequence_get(iter)==g_sequence_get(remove))
ali@9
   338
	{
ali@9
   339
	    *indices=g_sequence_iter_get_position(iter);
ali@9
   340
	    g_sequence_remove(iter);
ali@9
   341
	    remove=g_sequence_iter_next(remove);
ali@9
   342
	    gtk_tree_model_row_deleted(GTK_TREE_MODEL(store),path);
ali@9
   343
	}
ali@9
   344
	else
ali@9
   345
	    prev=iter;
ali@9
   346
	if (prev)
ali@9
   347
	    iter=g_sequence_iter_next(prev);
ali@9
   348
	else
ali@9
   349
	    iter=g_sequence_get_begin_iter(priv->seq);
ali@9
   350
    }
ali@9
   351
    gtk_tree_path_free(path);
ali@9
   352
    g_sequence_free(seq);
ali@9
   353
    priv->sets=g_slist_remove(priv->sets,set);
ali@9
   354
    g_object_unref(set);
ali@9
   355
    priv->stamp++;
ali@9
   356
}