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