plover-gtk/packagestore.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sun Nov 01 21:44:52 2015 +0000 (2015-11-01)
changeset 29 5b85f7066d98
parent 12 1d18b9c34d26
child 30 3ee18a3a0f58
permissions -rw-r--r--
Fix package details during removal
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@24
    27
#include "plover/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
    g_return_val_if_fail(indx>=0 && indx<PLOVER_PACKAGE_STORE_NO_COLUMNS,
ali@9
   104
      G_TYPE_INVALID);
ali@9
   105
    return column_types[indx];
ali@9
   106
}
ali@9
   107
ali@9
   108
static gboolean plover_package_store_get_iter(GtkTreeModel *tree_model,
ali@9
   109
  GtkTreeIter *iter,GtkTreePath *path)
ali@9
   110
{
ali@9
   111
    int i;
ali@9
   112
    PloverPackageStorePrivate *priv;
ali@9
   113
    PloverPackageStore *store=(PloverPackageStore *)tree_model;
ali@9
   114
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
ali@9
   115
    i=gtk_tree_path_get_indices(path)[0];
ali@9
   116
    if (i>=g_sequence_get_length(priv->seq))
ali@9
   117
	return FALSE;
ali@9
   118
    iter->stamp=priv->stamp;
ali@9
   119
    iter->user_data=g_sequence_get_iter_at_pos(priv->seq,i);
ali@9
   120
    return TRUE;
ali@9
   121
}
ali@9
   122
ali@9
   123
static GtkTreePath *
ali@9
   124
  plover_package_store_get_path(GtkTreeModel *tree_model,GtkTreeIter *iter)
ali@9
   125
{
ali@9
   126
    GtkTreePath *path;
ali@9
   127
    g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL);
ali@9
   128
    if (g_sequence_iter_is_end(iter->user_data))
ali@9
   129
	return NULL;
ali@9
   130
    path=gtk_tree_path_new();
ali@9
   131
    gtk_tree_path_append_index(path,
ali@9
   132
      g_sequence_iter_get_position(iter->user_data));
ali@9
   133
    return path;
ali@9
   134
}
ali@9
   135
ali@9
   136
static void plover_package_store_get_value(GtkTreeModel *tree_model,
ali@9
   137
  GtkTreeIter *iter,gint column,GValue *value)
ali@9
   138
{
ali@10
   139
    char *s;
ali@9
   140
    PloverPackageStore *store=(PloverPackageStore *)tree_model;
ali@9
   141
    PloverPackage *package;
ali@24
   142
    GInputStream *stream;
ali@24
   143
    GdkPixbuf *icon;
ali@9
   144
    g_return_if_fail(column>=0 && column<PLOVER_PACKAGE_STORE_NO_COLUMNS);
ali@9
   145
    g_return_if_fail(VALID_ITER(iter,store));
ali@10
   146
    package=PLOVER_PACKAGE(g_sequence_get(iter->user_data));
ali@9
   147
    g_value_init(value,column_types[column]);
ali@9
   148
    switch((PloverPackageStoreColumn)column)
ali@9
   149
    {
ali@9
   150
	case PLOVER_PACKAGE_STORE_OBJ_COLUMN:
ali@9
   151
	    g_value_set_object(value,package);
ali@9
   152
	    break;
ali@9
   153
	case PLOVER_PACKAGE_STORE_INSTALLED_COLUMN:
ali@9
   154
	    break;
ali@9
   155
	case PLOVER_PACKAGE_STORE_ICON_COLUMN:
ali@24
   156
	    stream=plover_package_read_icon(package,NULL);
ali@24
   157
	    if (stream)
ali@24
   158
	    {
ali@24
   159
		icon=gdk_pixbuf_new_from_stream(stream,NULL,NULL);
ali@24
   160
		g_object_unref(stream);
ali@24
   161
	    }
ali@24
   162
	    else
ali@24
   163
		icon=NULL;
ali@24
   164
	    g_value_set_object(value,icon);
ali@9
   165
	    break;
ali@9
   166
	case PLOVER_PACKAGE_STORE_NAME_COLUMN:
ali@9
   167
	    g_value_set_string(value,plover_package_get_name(package));
ali@9
   168
	    break;
ali@9
   169
	case PLOVER_PACKAGE_STORE_VERSION_COLUMN:
ali@9
   170
	    g_value_set_string(value,plover_package_get_version(package));
ali@9
   171
	    break;
ali@9
   172
	case PLOVER_PACKAGE_STORE_SUMMARY_COLUMN:
ali@10
   173
	    s=plover_package_get_summary(package);
ali@10
   174
	    if (*s)
ali@10
   175
		g_value_set_string(value,s);
ali@10
   176
	    else
ali@10
   177
	    {
ali@10
   178
		s=g_strconcat("The ",plover_package_get_name(package),
ali@10
   179
		  " package",NULL);
ali@10
   180
		g_value_set_string(value,s);
ali@10
   181
		g_free(s);
ali@10
   182
	    }
ali@9
   183
	    break;
ali@12
   184
	case PLOVER_PACKAGE_STORE_NO_COLUMNS:
ali@12
   185
	    /* Quieten compiler warning */
ali@12
   186
	    break;
ali@9
   187
    }
ali@9
   188
}
ali@9
   189
ali@9
   190
static gboolean
ali@9
   191
  plover_package_store_iter_next(GtkTreeModel *tree_model,GtkTreeIter *iter)
ali@9
   192
{
ali@9
   193
    g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE);
ali@9
   194
    iter->user_data=g_sequence_iter_next(iter->user_data);
ali@9
   195
    return !g_sequence_iter_is_end(iter->user_data);
ali@9
   196
}
ali@9
   197
ali@9
   198
static gboolean plover_package_store_iter_children(GtkTreeModel *tree_model,
ali@9
   199
  GtkTreeIter *iter,GtkTreeIter *parent)
ali@9
   200
{
ali@9
   201
    PloverPackageStorePrivate *priv;
ali@9
   202
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
ali@9
   203
    /* this is a list, nodes have no children */
ali@9
   204
    if (parent)
ali@9
   205
	return FALSE;
ali@9
   206
    if (g_sequence_get_length(priv->seq)>0)
ali@9
   207
    {
ali@9
   208
	iter->stamp=priv->stamp;
ali@9
   209
	iter->user_data=g_sequence_get_begin_iter(priv->seq);
ali@9
   210
	return TRUE;
ali@9
   211
    }
ali@9
   212
    else
ali@9
   213
	return FALSE;
ali@9
   214
}
ali@9
   215
ali@9
   216
static gboolean plover_package_store_iter_has_child(GtkTreeModel *tree_model,
ali@9
   217
  GtkTreeIter *iter)
ali@9
   218
{
ali@9
   219
    return FALSE;
ali@9
   220
}
ali@9
   221
ali@9
   222
static gint plover_package_store_iter_n_children(GtkTreeModel *tree_model,
ali@9
   223
  GtkTreeIter *iter)
ali@9
   224
{
ali@9
   225
    PloverPackageStorePrivate *priv;
ali@9
   226
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
ali@9
   227
    if (!iter)
ali@9
   228
	return g_sequence_get_length(priv->seq);
ali@9
   229
    g_return_val_if_fail(VALID_ITER(iter,tree_model),-1);
ali@9
   230
    return 0;
ali@9
   231
}
ali@9
   232
ali@9
   233
static gboolean plover_package_store_iter_nth_child(GtkTreeModel *tree_model,
ali@9
   234
  GtkTreeIter *iter,GtkTreeIter *parent,gint n)
ali@9
   235
{
ali@9
   236
    PloverPackageStorePrivate *priv;
ali@9
   237
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
ali@9
   238
    GSequenceIter *child;
ali@9
   239
    if (parent)
ali@9
   240
	return FALSE;
ali@9
   241
    child=g_sequence_get_iter_at_pos(priv->seq,n);
ali@9
   242
    if (g_sequence_iter_is_end(child))
ali@9
   243
	return FALSE;
ali@9
   244
    iter->stamp=priv->stamp;
ali@9
   245
    iter->user_data=child;
ali@9
   246
    return TRUE;
ali@9
   247
}
ali@9
   248
ali@9
   249
static gboolean plover_package_store_iter_parent(GtkTreeModel *tree_model,
ali@9
   250
  GtkTreeIter *iter,GtkTreeIter *child)
ali@9
   251
{
ali@9
   252
    return FALSE;
ali@9
   253
}
ali@9
   254
ali@9
   255
static void plover_package_store_tree_model_init(GtkTreeModelIface *iface)
ali@9
   256
{
ali@9
   257
    iface->get_flags=plover_package_store_get_flags;
ali@9
   258
    iface->get_n_columns=plover_package_store_get_n_columns;
ali@9
   259
    iface->get_column_type=plover_package_store_get_column_type;
ali@9
   260
    iface->get_iter=plover_package_store_get_iter;
ali@9
   261
    iface->get_path=plover_package_store_get_path;
ali@9
   262
    iface->get_value=plover_package_store_get_value;
ali@9
   263
    iface->iter_next=plover_package_store_iter_next;
ali@9
   264
    iface->iter_children=plover_package_store_iter_children;
ali@9
   265
    iface->iter_has_child=plover_package_store_iter_has_child;
ali@9
   266
    iface->iter_n_children=plover_package_store_iter_n_children;
ali@9
   267
    iface->iter_nth_child=plover_package_store_iter_nth_child;
ali@9
   268
    iface->iter_parent=plover_package_store_iter_parent;
ali@9
   269
}
ali@9
   270
ali@9
   271
static void plover_package_store_init(PloverPackageStore *store)
ali@9
   272
{
ali@9
   273
    PloverPackageStorePrivate *priv;
ali@9
   274
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
ali@9
   275
    priv->seq=g_sequence_new(NULL);
ali@9
   276
    priv->stamp=g_random_int();
ali@9
   277
}
ali@9
   278
ali@9
   279
PloverPackageStore *plover_package_store_new(void)
ali@9
   280
{
ali@9
   281
    return g_object_new(PLOVER_TYPE_PACKAGE_STORE,NULL);
ali@9
   282
}
ali@9
   283
ali@9
   284
GSList *plover_package_store_get_sets(PloverPackageStore *store)
ali@9
   285
{
ali@9
   286
    PloverPackageStorePrivate *priv;
ali@9
   287
    g_return_val_if_fail(PLOVER_IS_PACKAGE_STORE(store),NULL);
ali@9
   288
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
ali@9
   289
    return priv->sets;
ali@9
   290
}
ali@9
   291
ali@9
   292
static gint
ali@9
   293
  plover__package_compar(gconstpointer a,gconstpointer b,gpointer user_data)
ali@9
   294
{
ali@9
   295
    PloverPackage *pa=PLOVER_PACKAGE(a);
ali@9
   296
    PloverPackage *pb=PLOVER_PACKAGE(b);
ali@9
   297
    return strcmp(plover_package_get_name(pa),plover_package_get_name(pb));
ali@9
   298
}
ali@9
   299
ali@9
   300
void plover_package_store_add_set(PloverPackageStore *store,
ali@9
   301
  PloverPackageSet *set)
ali@9
   302
{
ali@9
   303
    GSList *packages,*link;
ali@9
   304
    GSequenceIter *si;
ali@9
   305
    GtkTreeIter ti;
ali@9
   306
    GtkTreePath *path;
ali@9
   307
    gint *indices;
ali@9
   308
    PloverPackageStorePrivate *priv;
ali@9
   309
    g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store));
ali@9
   310
    g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
ali@9
   311
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
ali@9
   312
    g_return_if_fail(g_slist_find(priv->sets,set) == NULL);
ali@9
   313
    g_object_ref(set);
ali@9
   314
    path=gtk_tree_path_new();
ali@9
   315
    gtk_tree_path_append_index(path,0);
ali@9
   316
    indices=gtk_tree_path_get_indices(path);
ali@9
   317
    packages=plover_package_set_get_packages(set);
ali@9
   318
    for(link=packages;link;link=link->next)
ali@9
   319
    {
ali@9
   320
	si=g_sequence_insert_sorted(priv->seq,link->data,
ali@9
   321
	  plover__package_compar,NULL);
ali@9
   322
	*indices=g_sequence_iter_get_position(si);
ali@9
   323
	ti.stamp=priv->stamp;
ali@9
   324
	ti.user_data=si;
ali@9
   325
	gtk_tree_model_row_inserted(GTK_TREE_MODEL(store),path,&ti);
ali@9
   326
    }
ali@9
   327
    gtk_tree_path_free(path);
ali@9
   328
    priv->sets=g_slist_prepend(priv->sets,set);
ali@9
   329
}
ali@9
   330
ali@9
   331
void plover_package_store_remove_set(PloverPackageStore *store,
ali@9
   332
  PloverPackageSet *set)
ali@9
   333
{
ali@9
   334
    GSList *packages,*link;
ali@9
   335
    GSequence *seq;
ali@9
   336
    GSequenceIter *iter,*prev,*remove;
ali@9
   337
    GtkTreePath *path;
ali@9
   338
    gint *indices;
ali@9
   339
    PloverPackageStorePrivate *priv;
ali@9
   340
    g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store));
ali@9
   341
    g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
ali@9
   342
    priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
ali@9
   343
    g_return_if_fail(g_slist_find(priv->sets,set) != NULL);
ali@9
   344
    seq=g_sequence_new(NULL);
ali@9
   345
    path=gtk_tree_path_new();
ali@9
   346
    gtk_tree_path_append_index(path,0);
ali@9
   347
    indices=gtk_tree_path_get_indices(path);
ali@9
   348
    packages=plover_package_set_get_packages(set);
ali@9
   349
    for(link=packages;link;link=link->next)
ali@9
   350
	g_sequence_insert_sorted(seq,link->data,plover__package_compar,NULL);
ali@9
   351
    prev=NULL;
ali@9
   352
    iter=g_sequence_get_begin_iter(priv->seq);
ali@9
   353
    remove=g_sequence_get_begin_iter(seq);
ali@9
   354
    while(!g_sequence_iter_is_end(iter) && !g_sequence_iter_is_end(remove))
ali@9
   355
    {
ali@9
   356
	if (g_sequence_get(iter)==g_sequence_get(remove))
ali@9
   357
	{
ali@9
   358
	    *indices=g_sequence_iter_get_position(iter);
ali@9
   359
	    g_sequence_remove(iter);
ali@9
   360
	    remove=g_sequence_iter_next(remove);
ali@9
   361
	    gtk_tree_model_row_deleted(GTK_TREE_MODEL(store),path);
ali@9
   362
	}
ali@9
   363
	else
ali@9
   364
	    prev=iter;
ali@9
   365
	if (prev)
ali@9
   366
	    iter=g_sequence_iter_next(prev);
ali@9
   367
	else
ali@9
   368
	    iter=g_sequence_get_begin_iter(priv->seq);
ali@9
   369
    }
ali@9
   370
    gtk_tree_path_free(path);
ali@9
   371
    g_sequence_free(seq);
ali@9
   372
    priv->sets=g_slist_remove(priv->sets,set);
ali@9
   373
    g_object_unref(set);
ali@9
   374
    priv->stamp++;
ali@9
   375
}