plover-gtk/packagestore.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Feb 20 12:11:02 2010 +0000 (2010-02-20)
changeset 9 8d3b1ddf789c
child 10 8b50be3e2998
permissions -rw-r--r--
First cut at an applications manager
     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     PloverPackageStore *store=(PloverPackageStore *)tree_model;
   104     g_return_val_if_fail(indx>=0 && indx<PLOVER_PACKAGE_STORE_NO_COLUMNS,
   105       G_TYPE_INVALID);
   106     return column_types[indx];
   107 }
   108 
   109 static gboolean plover_package_store_get_iter(GtkTreeModel *tree_model,
   110   GtkTreeIter *iter,GtkTreePath *path)
   111 {
   112     int i;
   113     PloverPackageStorePrivate *priv;
   114     PloverPackageStore *store=(PloverPackageStore *)tree_model;
   115     priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
   116     i=gtk_tree_path_get_indices(path)[0];
   117     if (i>=g_sequence_get_length(priv->seq))
   118 	return FALSE;
   119     iter->stamp=priv->stamp;
   120     iter->user_data=g_sequence_get_iter_at_pos(priv->seq,i);
   121     return TRUE;
   122 }
   123 
   124 static GtkTreePath *
   125   plover_package_store_get_path(GtkTreeModel *tree_model,GtkTreeIter *iter)
   126 {
   127     GtkTreePath *path;
   128     g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL);
   129     if (g_sequence_iter_is_end(iter->user_data))
   130 	return NULL;
   131     path=gtk_tree_path_new();
   132     gtk_tree_path_append_index(path,
   133       g_sequence_iter_get_position(iter->user_data));
   134     return path;
   135 }
   136 
   137 static void plover_package_store_get_value(GtkTreeModel *tree_model,
   138   GtkTreeIter *iter,gint column,GValue *value)
   139 {
   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=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 	    g_value_set_string(value,plover_package_get_summary(package));
   164 	    break;
   165     }
   166 }
   167 
   168 static gboolean
   169   plover_package_store_iter_next(GtkTreeModel *tree_model,GtkTreeIter *iter)
   170 {
   171     g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE);
   172     iter->user_data=g_sequence_iter_next(iter->user_data);
   173     return !g_sequence_iter_is_end(iter->user_data);
   174 }
   175 
   176 static gboolean plover_package_store_iter_children(GtkTreeModel *tree_model,
   177   GtkTreeIter *iter,GtkTreeIter *parent)
   178 {
   179     PloverPackageStorePrivate *priv;
   180     PloverPackageStore *store=(PloverPackageStore *)tree_model;
   181     priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
   182     /* this is a list, nodes have no children */
   183     if (parent)
   184 	return FALSE;
   185     if (g_sequence_get_length(priv->seq)>0)
   186     {
   187 	iter->stamp=priv->stamp;
   188 	iter->user_data=g_sequence_get_begin_iter(priv->seq);
   189 	return TRUE;
   190     }
   191     else
   192 	return FALSE;
   193 }
   194 
   195 static gboolean plover_package_store_iter_has_child(GtkTreeModel *tree_model,
   196   GtkTreeIter *iter)
   197 {
   198     return FALSE;
   199 }
   200 
   201 static gint plover_package_store_iter_n_children(GtkTreeModel *tree_model,
   202   GtkTreeIter *iter)
   203 {
   204     PloverPackageStorePrivate *priv;
   205     PloverPackageStore *store=(PloverPackageStore *)tree_model;
   206     priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
   207     if (!iter)
   208 	return g_sequence_get_length(priv->seq);
   209     g_return_val_if_fail(VALID_ITER(iter,tree_model),-1);
   210     return 0;
   211 }
   212 
   213 static gboolean plover_package_store_iter_nth_child(GtkTreeModel *tree_model,
   214   GtkTreeIter *iter,GtkTreeIter *parent,gint n)
   215 {
   216     PloverPackageStorePrivate *priv;
   217     PloverPackageStore *store=(PloverPackageStore *)tree_model;
   218     priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
   219     GSequenceIter *child;
   220     if (parent)
   221 	return FALSE;
   222     child=g_sequence_get_iter_at_pos(priv->seq,n);
   223     if (g_sequence_iter_is_end(child))
   224 	return FALSE;
   225     iter->stamp=priv->stamp;
   226     iter->user_data=child;
   227     return TRUE;
   228 }
   229 
   230 static gboolean plover_package_store_iter_parent(GtkTreeModel *tree_model,
   231   GtkTreeIter *iter,GtkTreeIter *child)
   232 {
   233     return FALSE;
   234 }
   235 
   236 static void plover_package_store_tree_model_init(GtkTreeModelIface *iface)
   237 {
   238     iface->get_flags=plover_package_store_get_flags;
   239     iface->get_n_columns=plover_package_store_get_n_columns;
   240     iface->get_column_type=plover_package_store_get_column_type;
   241     iface->get_iter=plover_package_store_get_iter;
   242     iface->get_path=plover_package_store_get_path;
   243     iface->get_value=plover_package_store_get_value;
   244     iface->iter_next=plover_package_store_iter_next;
   245     iface->iter_children=plover_package_store_iter_children;
   246     iface->iter_has_child=plover_package_store_iter_has_child;
   247     iface->iter_n_children=plover_package_store_iter_n_children;
   248     iface->iter_nth_child=plover_package_store_iter_nth_child;
   249     iface->iter_parent=plover_package_store_iter_parent;
   250 }
   251 
   252 static void plover_package_store_init(PloverPackageStore *store)
   253 {
   254     PloverPackageStorePrivate *priv;
   255     priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
   256     priv->seq=g_sequence_new(NULL);
   257     priv->stamp=g_random_int();
   258 }
   259 
   260 PloverPackageStore *plover_package_store_new(void)
   261 {
   262     return g_object_new(PLOVER_TYPE_PACKAGE_STORE,NULL);
   263 }
   264 
   265 GSList *plover_package_store_get_sets(PloverPackageStore *store)
   266 {
   267     PloverPackageStorePrivate *priv;
   268     g_return_val_if_fail(PLOVER_IS_PACKAGE_STORE(store),NULL);
   269     priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
   270     return priv->sets;
   271 }
   272 
   273 static gint
   274   plover__package_compar(gconstpointer a,gconstpointer b,gpointer user_data)
   275 {
   276     PloverPackage *pa=PLOVER_PACKAGE(a);
   277     PloverPackage *pb=PLOVER_PACKAGE(b);
   278     return strcmp(plover_package_get_name(pa),plover_package_get_name(pb));
   279 }
   280 
   281 void plover_package_store_add_set(PloverPackageStore *store,
   282   PloverPackageSet *set)
   283 {
   284     GSList *packages,*link;
   285     GSequenceIter *si;
   286     GtkTreeIter ti;
   287     GtkTreePath *path;
   288     gint *indices;
   289     PloverPackageStorePrivate *priv;
   290     g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store));
   291     g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
   292     priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
   293     g_return_if_fail(g_slist_find(priv->sets,set) == NULL);
   294     g_object_ref(set);
   295     path=gtk_tree_path_new();
   296     gtk_tree_path_append_index(path,0);
   297     indices=gtk_tree_path_get_indices(path);
   298     packages=plover_package_set_get_packages(set);
   299     for(link=packages;link;link=link->next)
   300     {
   301 	si=g_sequence_insert_sorted(priv->seq,link->data,
   302 	  plover__package_compar,NULL);
   303 	*indices=g_sequence_iter_get_position(si);
   304 	ti.stamp=priv->stamp;
   305 	ti.user_data=si;
   306 	gtk_tree_model_row_inserted(GTK_TREE_MODEL(store),path,&ti);
   307     }
   308     gtk_tree_path_free(path);
   309     priv->sets=g_slist_prepend(priv->sets,set);
   310 }
   311 
   312 void plover_package_store_remove_set(PloverPackageStore *store,
   313   PloverPackageSet *set)
   314 {
   315     GSList *packages,*link;
   316     GSequence *seq;
   317     GSequenceIter *iter,*prev,*remove;
   318     GtkTreePath *path;
   319     gint *indices;
   320     PloverPackageStorePrivate *priv;
   321     g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store));
   322     g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
   323     priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
   324     g_return_if_fail(g_slist_find(priv->sets,set) != NULL);
   325     seq=g_sequence_new(NULL);
   326     path=gtk_tree_path_new();
   327     gtk_tree_path_append_index(path,0);
   328     indices=gtk_tree_path_get_indices(path);
   329     packages=plover_package_set_get_packages(set);
   330     for(link=packages;link;link=link->next)
   331 	g_sequence_insert_sorted(seq,link->data,plover__package_compar,NULL);
   332     prev=NULL;
   333     iter=g_sequence_get_begin_iter(priv->seq);
   334     remove=g_sequence_get_begin_iter(seq);
   335     while(!g_sequence_iter_is_end(iter) && !g_sequence_iter_is_end(remove))
   336     {
   337 	if (g_sequence_get(iter)==g_sequence_get(remove))
   338 	{
   339 	    *indices=g_sequence_iter_get_position(iter);
   340 	    g_sequence_remove(iter);
   341 	    remove=g_sequence_iter_next(remove);
   342 	    gtk_tree_model_row_deleted(GTK_TREE_MODEL(store),path);
   343 	}
   344 	else
   345 	    prev=iter;
   346 	if (prev)
   347 	    iter=g_sequence_iter_next(prev);
   348 	else
   349 	    iter=g_sequence_get_begin_iter(priv->seq);
   350     }
   351     gtk_tree_path_free(path);
   352     g_sequence_free(seq);
   353     priv->sets=g_slist_remove(priv->sets,set);
   354     g_object_unref(set);
   355     priv->stamp++;
   356 }