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