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