Support parallel installations. The idea is that for CAD screener, we want
to be able to install this on the same machine as a standard AVOT setup
(most notably for John's laptop). To allow for the possibility of a second
application that might have the same requirements, we add the concept of
vendor-specific distributions. Thus we can have one distribution for CAD
screener and one for The Next Big Thing. It doesn't seem trivial to have
both CAD screener and AVOT under the same vendor tag so we'll have to have
AVOT under "City Occupational" and CAD screener under "City Occupational Ltd"
or some such kludge.
Most of this is done although we are very short of test cases (in particular
we don't test that it's actually possible to install CAD screener in parallel
with AVOT or to update either of them once installed, which is fundamental).
We also have a lot of baggage left over, including an intercept of razor_set.
The problem that this was introduced to debug has been fixed but it looks
like there are a number of memory leaks which it might be useful to help
track down so it has been left in place for now.
There is still a lot of confusion in plover between path-based and URI-based
API. We should review the API, decide what we want and have a general clear up.
There is also confusion as to the purpose of RAZOR_ROOT (and meaning; path or
URI). This is not used at all in librazor (although it is used in razor.exe).
Ideally we shouldn't use it in plover or plover-gtk either although again, we
might want to support it or an equivalent in (some of) the various executables.
Work that would still to nice to do for CAD screener:
- uninstall (ideally as an installed program that hooks into Add/Remove programs
but even re-running the installer would be acceptable).
- xz support (smaller packages).
- repomd.xml and xml:base (would be needed for an Internet installer).
- graphical installer.
2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
3 * Copyright (C) 2010 J. Ali Harlow <ali@juiblex.co.uk>
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.
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.
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.
23 #include <glib-object.h>
26 #include "plover/plover.h"
27 #include "plover/package.h"
28 #include "plover-gtk/packagestore.h"
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)
36 static GType column_types[PLOVER_PACKAGE_STORE_NO_COLUMNS];
38 static void plover_package_store_tree_model_init(GtkTreeModelIface *iface);
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));
44 typedef struct _PloverPackageStorePrivate {
48 } PloverPackageStorePrivate;
50 #define PLOVER_PACKAGE_STORE_GET_PRIVATE(obj)\
51 G_TYPE_INSTANCE_GET_PRIVATE(obj,\
52 PLOVER_TYPE_PACKAGE_STORE,\
53 PloverPackageStorePrivate)
55 static void plover_package_store_finalize(GObject *obj)
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);
63 static void plover_package_store_dispose(GObject *obj)
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);
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);
75 static void plover_package_store_class_init(PloverPackageStoreClass *klass)
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;
89 static GtkTreeModelFlags
90 plover_package_store_get_flags(GtkTreeModel *tree_model)
92 return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY;
95 static gint plover_package_store_get_n_columns(GtkTreeModel *tree_model)
97 return PLOVER_PACKAGE_STORE_NO_COLUMNS;
101 plover_package_store_get_column_type(GtkTreeModel *tree_model,gint indx)
103 g_return_val_if_fail(indx>=0 && indx<PLOVER_PACKAGE_STORE_NO_COLUMNS,
105 return column_types[indx];
108 static gboolean plover_package_store_get_iter(GtkTreeModel *tree_model,
109 GtkTreeIter *iter,GtkTreePath *path)
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))
118 iter->stamp=priv->stamp;
119 iter->user_data=g_sequence_get_iter_at_pos(priv->seq,i);
124 plover_package_store_get_path(GtkTreeModel *tree_model,GtkTreeIter *iter)
127 g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL);
128 if (g_sequence_iter_is_end(iter->user_data))
130 path=gtk_tree_path_new();
131 gtk_tree_path_append_index(path,
132 g_sequence_iter_get_position(iter->user_data));
136 static void plover_package_store_get_value(GtkTreeModel *tree_model,
137 GtkTreeIter *iter,gint column,GValue *value)
141 PloverPackageStore *store=(PloverPackageStore *)tree_model;
142 PloverPackage *package;
143 GInputStream *stream;
145 g_return_if_fail(column>=0 && column<PLOVER_PACKAGE_STORE_NO_COLUMNS);
146 g_return_if_fail(VALID_ITER(iter,store));
147 package=PLOVER_PACKAGE(g_sequence_get(iter->user_data));
148 g_value_init(value,column_types[column]);
149 switch((PloverPackageStoreColumn)column)
151 case PLOVER_PACKAGE_STORE_OBJ_COLUMN:
152 g_value_set_object(value,package);
154 case PLOVER_PACKAGE_STORE_INSTALLED_COLUMN:
156 case PLOVER_PACKAGE_STORE_ICON_COLUMN:
157 stream=plover_package_read_icon(package,NULL);
160 icon=gdk_pixbuf_new_from_stream(stream,NULL,NULL);
161 g_object_unref(stream);
165 g_value_set_object(value,icon);
167 case PLOVER_PACKAGE_STORE_NAME_COLUMN:
168 g_value_set_string(value,plover_package_get_name(package));
170 case PLOVER_PACKAGE_STORE_VERSION_COLUMN:
171 g_value_set_string(value,plover_package_get_version(package));
173 case PLOVER_PACKAGE_STORE_SUMMARY_COLUMN:
174 summary=plover_package_get_summary(package);
176 g_value_set_string(value,summary);
179 s=g_strconcat("The ",plover_package_get_name(package),
181 g_value_set_string(value,s);
185 case PLOVER_PACKAGE_STORE_NO_COLUMNS:
186 /* Quieten compiler warning */
192 plover_package_store_iter_next(GtkTreeModel *tree_model,GtkTreeIter *iter)
194 g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE);
195 iter->user_data=g_sequence_iter_next(iter->user_data);
196 return !g_sequence_iter_is_end(iter->user_data);
199 static gboolean plover_package_store_iter_children(GtkTreeModel *tree_model,
200 GtkTreeIter *iter,GtkTreeIter *parent)
202 PloverPackageStorePrivate *priv;
203 priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
204 /* this is a list, nodes have no children */
207 if (g_sequence_get_length(priv->seq)>0)
209 iter->stamp=priv->stamp;
210 iter->user_data=g_sequence_get_begin_iter(priv->seq);
217 static gboolean plover_package_store_iter_has_child(GtkTreeModel *tree_model,
223 static gint plover_package_store_iter_n_children(GtkTreeModel *tree_model,
226 PloverPackageStorePrivate *priv;
227 priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
229 return g_sequence_get_length(priv->seq);
230 g_return_val_if_fail(VALID_ITER(iter,tree_model),-1);
234 static gboolean plover_package_store_iter_nth_child(GtkTreeModel *tree_model,
235 GtkTreeIter *iter,GtkTreeIter *parent,gint n)
237 PloverPackageStorePrivate *priv;
238 priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(tree_model);
239 GSequenceIter *child;
242 child=g_sequence_get_iter_at_pos(priv->seq,n);
243 if (g_sequence_iter_is_end(child))
245 iter->stamp=priv->stamp;
246 iter->user_data=child;
250 static gboolean plover_package_store_iter_parent(GtkTreeModel *tree_model,
251 GtkTreeIter *iter,GtkTreeIter *child)
256 static void plover_package_store_tree_model_init(GtkTreeModelIface *iface)
258 iface->get_flags=plover_package_store_get_flags;
259 iface->get_n_columns=plover_package_store_get_n_columns;
260 iface->get_column_type=plover_package_store_get_column_type;
261 iface->get_iter=plover_package_store_get_iter;
262 iface->get_path=plover_package_store_get_path;
263 iface->get_value=plover_package_store_get_value;
264 iface->iter_next=plover_package_store_iter_next;
265 iface->iter_children=plover_package_store_iter_children;
266 iface->iter_has_child=plover_package_store_iter_has_child;
267 iface->iter_n_children=plover_package_store_iter_n_children;
268 iface->iter_nth_child=plover_package_store_iter_nth_child;
269 iface->iter_parent=plover_package_store_iter_parent;
272 static void plover_package_store_init(PloverPackageStore *store)
274 PloverPackageStorePrivate *priv;
275 priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
276 priv->seq=g_sequence_new(NULL);
277 priv->stamp=g_random_int();
280 PloverPackageStore *plover_package_store_new(void)
282 return g_object_new(PLOVER_TYPE_PACKAGE_STORE,NULL);
285 GSList *plover_package_store_get_sets(PloverPackageStore *store)
287 PloverPackageStorePrivate *priv;
288 g_return_val_if_fail(PLOVER_IS_PACKAGE_STORE(store),NULL);
289 priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
294 plover__package_compar(gconstpointer a,gconstpointer b,gpointer user_data)
296 PloverPackage *pa=PLOVER_PACKAGE(a);
297 PloverPackage *pb=PLOVER_PACKAGE(b);
298 return strcmp(plover_package_get_name(pa),plover_package_get_name(pb));
301 void plover_package_store_add_set(PloverPackageStore *store,
302 PloverPackageSet *set)
304 GSList *packages,*link;
309 PloverPackageStorePrivate *priv;
310 g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store));
311 g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
312 priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
313 g_return_if_fail(g_slist_find(priv->sets,set) == NULL);
315 path=gtk_tree_path_new();
316 gtk_tree_path_append_index(path,0);
317 indices=gtk_tree_path_get_indices(path);
318 packages=plover_package_set_get_packages(set);
319 for(link=packages;link;link=link->next)
321 si=g_sequence_insert_sorted(priv->seq,link->data,
322 plover__package_compar,NULL);
323 *indices=g_sequence_iter_get_position(si);
324 ti.stamp=priv->stamp;
326 gtk_tree_model_row_inserted(GTK_TREE_MODEL(store),path,&ti);
328 gtk_tree_path_free(path);
329 priv->sets=g_slist_prepend(priv->sets,set);
332 void plover_package_store_remove_set(PloverPackageStore *store,
333 PloverPackageSet *set)
335 GSList *packages,*link;
337 GSequenceIter *iter,*prev,*remove;
340 PloverPackageStorePrivate *priv;
341 g_return_if_fail(PLOVER_IS_PACKAGE_STORE(store));
342 g_return_if_fail(PLOVER_IS_PACKAGE_SET(set));
343 priv=PLOVER_PACKAGE_STORE_GET_PRIVATE(store);
344 g_return_if_fail(g_slist_find(priv->sets,set) != NULL);
345 seq=g_sequence_new(NULL);
346 path=gtk_tree_path_new();
347 gtk_tree_path_append_index(path,0);
348 indices=gtk_tree_path_get_indices(path);
349 packages=plover_package_set_get_packages(set);
350 for(link=packages;link;link=link->next)
351 g_sequence_insert_sorted(seq,link->data,plover__package_compar,NULL);
353 iter=g_sequence_get_begin_iter(priv->seq);
354 remove=g_sequence_get_begin_iter(seq);
355 while(!g_sequence_iter_is_end(iter) && !g_sequence_iter_is_end(remove))
357 if (g_sequence_get(iter)==g_sequence_get(remove))
359 *indices=g_sequence_iter_get_position(iter);
360 g_sequence_remove(iter);
361 remove=g_sequence_iter_next(remove);
362 gtk_tree_model_row_deleted(GTK_TREE_MODEL(store),path);
367 iter=g_sequence_iter_next(prev);
369 iter=g_sequence_get_begin_iter(priv->seq);
371 gtk_tree_path_free(path);
372 g_sequence_free(seq);
373 priv->sets=g_slist_remove(priv->sets,set);