diff -r 000000000000 -r 8d3b1ddf789c plover-gtk/packagestore.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plover-gtk/packagestore.c Sat Feb 20 12:11:02 2010 +0000 @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford + * Copyright (C) 2010 J. Ali Harlow + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include "plover/plover.h" +#include "plover-gtk/package.h" +#include "plover-gtk/packagestore.h" + +#define VALID_ITER(iter,store) ((iter) && (iter)->user_data && \ + PLOVER_PACKAGE_STORE_GET_PRIVATE(store)->stamp==(iter)->stamp && \ + !g_sequence_iter_is_end((iter)->user_data) && \ + g_sequence_iter_get_sequence((iter)->user_data)== \ + PLOVER_PACKAGE_STORE_GET_PRIVATE(store)->seq) + +static GType column_types[PLOVER_PACKAGE_STORE_NO_COLUMNS]; + +static void plover_package_store_tree_model_init(GtkTreeModelIface *iface); + +G_DEFINE_TYPE_WITH_CODE(PloverPackageStore,plover_package_store,G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL, + plover_package_store_tree_model_init)); + +typedef struct _PloverPackageStorePrivate { + GSList *sets; + GSequence *seq; + int stamp; +} PloverPackageStorePrivate; + +#define PLOVER_PACKAGE_STORE_GET_PRIVATE(obj)\ + G_TYPE_INSTANCE_GET_PRIVATE(obj,\ + PLOVER_TYPE_PACKAGE_STORE,\ + PloverPackageStorePrivate) + +static void plover_package_store_finalize(GObject *obj) +{ + PloverPackageStorePrivate *priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(obj); + g_sequence_free(priv->seq); + if (G_OBJECT_CLASS(plover_package_store_parent_class)->finalize) + G_OBJECT_CLASS(plover_package_store_parent_class)->finalize(obj); +} + +static void plover_package_store_dispose(GObject *obj) +{ + PloverPackageStorePrivate *priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(obj); + g_slist_foreach(priv->sets,(GFunc)g_object_unref,NULL); + g_slist_free(priv->sets); + priv->sets=NULL; + g_sequence_free(priv->seq); + priv->seq=g_sequence_new(NULL); + if (G_OBJECT_CLASS(plover_package_store_parent_class)->dispose) + G_OBJECT_CLASS(plover_package_store_parent_class)->dispose(obj); +} + +static void plover_package_store_class_init(PloverPackageStoreClass *klass) +{ + GObjectClass *oclass=G_OBJECT_CLASS(klass); + oclass->finalize=plover_package_store_finalize; + oclass->dispose=plover_package_store_dispose; + g_type_class_add_private(klass,sizeof(PloverPackageStorePrivate)); + column_types[PLOVER_PACKAGE_STORE_OBJ_COLUMN]=PLOVER_TYPE_PACKAGE; + column_types[PLOVER_PACKAGE_STORE_INSTALLED_COLUMN]=G_TYPE_BOOLEAN; + column_types[PLOVER_PACKAGE_STORE_ICON_COLUMN]=GDK_TYPE_PIXBUF; + column_types[PLOVER_PACKAGE_STORE_NAME_COLUMN]=G_TYPE_STRING; + column_types[PLOVER_PACKAGE_STORE_VERSION_COLUMN]=G_TYPE_STRING; + column_types[PLOVER_PACKAGE_STORE_SUMMARY_COLUMN]=G_TYPE_STRING; +} + +static GtkTreeModelFlags +plover_package_store_get_flags(GtkTreeModel *tree_model) +{ + return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY; +} + +static gint plover_package_store_get_n_columns(GtkTreeModel *tree_model) +{ + return PLOVER_PACKAGE_STORE_NO_COLUMNS; +} + +static GType + plover_package_store_get_column_type(GtkTreeModel *tree_model,gint indx) +{ + PloverPackageStore *store=(PloverPackageStore *)tree_model; + g_return_val_if_fail(indx>=0 && indx=g_sequence_get_length(priv->seq)) + return FALSE; + iter->stamp=priv->stamp; + iter->user_data=g_sequence_get_iter_at_pos(priv->seq,i); + return TRUE; +} + +static GtkTreePath * + plover_package_store_get_path(GtkTreeModel *tree_model,GtkTreeIter *iter) +{ + GtkTreePath *path; + g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL); + if (g_sequence_iter_is_end(iter->user_data)) + return NULL; + path=gtk_tree_path_new(); + gtk_tree_path_append_index(path, + g_sequence_iter_get_position(iter->user_data)); + return path; +} + +static void plover_package_store_get_value(GtkTreeModel *tree_model, + GtkTreeIter *iter,gint column,GValue *value) +{ + PloverPackageStore *store=(PloverPackageStore *)tree_model; + PloverPackage *package; + g_return_if_fail(column>=0 && columnuser_data); + g_value_init(value,column_types[column]); + switch((PloverPackageStoreColumn)column) + { + case PLOVER_PACKAGE_STORE_OBJ_COLUMN: + g_value_set_object(value,package); + break; + case PLOVER_PACKAGE_STORE_INSTALLED_COLUMN: + break; + case PLOVER_PACKAGE_STORE_ICON_COLUMN: + g_value_set_object(value,plover_package_get_icon(package)); + break; + case PLOVER_PACKAGE_STORE_NAME_COLUMN: + g_value_set_string(value,plover_package_get_name(package)); + break; + case PLOVER_PACKAGE_STORE_VERSION_COLUMN: + g_value_set_string(value,plover_package_get_version(package)); + break; + case PLOVER_PACKAGE_STORE_SUMMARY_COLUMN: + g_value_set_string(value,plover_package_get_summary(package)); + break; + } +} + +static gboolean + plover_package_store_iter_next(GtkTreeModel *tree_model,GtkTreeIter *iter) +{ + g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE); + iter->user_data=g_sequence_iter_next(iter->user_data); + return !g_sequence_iter_is_end(iter->user_data); +} + +static gboolean plover_package_store_iter_children(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *parent) +{ + PloverPackageStorePrivate *priv; + PloverPackageStore *store=(PloverPackageStore *)tree_model; + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model); + /* this is a list, nodes have no children */ + if (parent) + return FALSE; + if (g_sequence_get_length(priv->seq)>0) + { + iter->stamp=priv->stamp; + iter->user_data=g_sequence_get_begin_iter(priv->seq); + return TRUE; + } + else + return FALSE; +} + +static gboolean plover_package_store_iter_has_child(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + return FALSE; +} + +static gint plover_package_store_iter_n_children(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + PloverPackageStorePrivate *priv; + PloverPackageStore *store=(PloverPackageStore *)tree_model; + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model); + if (!iter) + return g_sequence_get_length(priv->seq); + g_return_val_if_fail(VALID_ITER(iter,tree_model),-1); + return 0; +} + +static gboolean plover_package_store_iter_nth_child(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *parent,gint n) +{ + PloverPackageStorePrivate *priv; + PloverPackageStore *store=(PloverPackageStore *)tree_model; + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model); + GSequenceIter *child; + if (parent) + return FALSE; + child=g_sequence_get_iter_at_pos(priv->seq,n); + if (g_sequence_iter_is_end(child)) + return FALSE; + iter->stamp=priv->stamp; + iter->user_data=child; + return TRUE; +} + +static gboolean plover_package_store_iter_parent(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *child) +{ + return FALSE; +} + +static void plover_package_store_tree_model_init(GtkTreeModelIface *iface) +{ + iface->get_flags=plover_package_store_get_flags; + iface->get_n_columns=plover_package_store_get_n_columns; + iface->get_column_type=plover_package_store_get_column_type; + iface->get_iter=plover_package_store_get_iter; + iface->get_path=plover_package_store_get_path; + iface->get_value=plover_package_store_get_value; + iface->iter_next=plover_package_store_iter_next; + iface->iter_children=plover_package_store_iter_children; + iface->iter_has_child=plover_package_store_iter_has_child; + iface->iter_n_children=plover_package_store_iter_n_children; + iface->iter_nth_child=plover_package_store_iter_nth_child; + iface->iter_parent=plover_package_store_iter_parent; +} + +static void plover_package_store_init(PloverPackageStore *store) +{ + PloverPackageStorePrivate *priv; + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store); + priv->seq=g_sequence_new(NULL); + priv->stamp=g_random_int(); +} + +PloverPackageStore *plover_package_store_new(void) +{ + return g_object_new(PLOVER_TYPE_PACKAGE_STORE,NULL); +} + +GSList *plover_package_store_get_sets(PloverPackageStore *store) +{ + PloverPackageStorePrivate *priv; + g_return_val_if_fail(PLOVER_IS_PACKAGE_STORE(store),NULL); + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store); + return priv->sets; +} + +static gint + plover__package_compar(gconstpointer a,gconstpointer b,gpointer user_data) +{ + PloverPackage *pa=PLOVER_PACKAGE(a); + PloverPackage *pb=PLOVER_PACKAGE(b); + return strcmp(plover_package_get_name(pa),plover_package_get_name(pb)); +} + +void plover_package_store_add_set(PloverPackageStore *store, + PloverPackageSet *set) +{ + GSList *packages,*link; + GSequenceIter *si; + GtkTreeIter ti; + GtkTreePath *path; + gint *indices; + PloverPackageStorePrivate *priv; + g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store)); + g_return_if_fail(PLOVER_IS_PACKAGE_SET(set)); + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store); + g_return_if_fail(g_slist_find(priv->sets,set) == NULL); + g_object_ref(set); + path=gtk_tree_path_new(); + gtk_tree_path_append_index(path,0); + indices=gtk_tree_path_get_indices(path); + packages=plover_package_set_get_packages(set); + for(link=packages;link;link=link->next) + { + si=g_sequence_insert_sorted(priv->seq,link->data, + plover__package_compar,NULL); + *indices=g_sequence_iter_get_position(si); + ti.stamp=priv->stamp; + ti.user_data=si; + gtk_tree_model_row_inserted(GTK_TREE_MODEL(store),path,&ti); + } + gtk_tree_path_free(path); + priv->sets=g_slist_prepend(priv->sets,set); +} + +void plover_package_store_remove_set(PloverPackageStore *store, + PloverPackageSet *set) +{ + GSList *packages,*link; + GSequence *seq; + GSequenceIter *iter,*prev,*remove; + GtkTreePath *path; + gint *indices; + PloverPackageStorePrivate *priv; + g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store)); + g_return_if_fail(PLOVER_IS_PACKAGE_SET(set)); + priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store); + g_return_if_fail(g_slist_find(priv->sets,set) != NULL); + seq=g_sequence_new(NULL); + path=gtk_tree_path_new(); + gtk_tree_path_append_index(path,0); + indices=gtk_tree_path_get_indices(path); + packages=plover_package_set_get_packages(set); + for(link=packages;link;link=link->next) + g_sequence_insert_sorted(seq,link->data,plover__package_compar,NULL); + prev=NULL; + iter=g_sequence_get_begin_iter(priv->seq); + remove=g_sequence_get_begin_iter(seq); + while(!g_sequence_iter_is_end(iter) && !g_sequence_iter_is_end(remove)) + { + if (g_sequence_get(iter)==g_sequence_get(remove)) + { + *indices=g_sequence_iter_get_position(iter); + g_sequence_remove(iter); + remove=g_sequence_iter_next(remove); + gtk_tree_model_row_deleted(GTK_TREE_MODEL(store),path); + } + else + prev=iter; + if (prev) + iter=g_sequence_iter_next(prev); + else + iter=g_sequence_get_begin_iter(priv->seq); + } + gtk_tree_path_free(path); + g_sequence_free(seq); + priv->sets=g_slist_remove(priv->sets,set); + g_object_unref(set); + priv->stamp++; +}