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