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