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