2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
3 * Copyright (C) 2023 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>
25 #include <plover/plover.h>
26 #include "localdistributions.h"
28 #define VALID_ITER(iter,local) ((iter) && (iter)->user_data && \
29 PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local)->stamp==(iter)->stamp)
31 static GType column_types[PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS];
34 plover_local_distributions_tree_model_init(GtkTreeModelIface *iface);
36 G_DEFINE_TYPE_WITH_CODE(PloverLocalDistributions,plover_local_distributions,
37 G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL,
38 plover_local_distributions_tree_model_init));
40 typedef struct _PloverLocalDistribution {
41 gchar *vendor,*distribution,*prefix,*user_friendly,*database_uri;
42 } PloverLocalDistribution;
44 typedef struct _PloverLocalDistributionsPrivate {
47 } PloverLocalDistributionsPrivate;
49 #define PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj)\
50 G_TYPE_INSTANCE_GET_PRIVATE(obj,\
51 PLOVER_TYPE_LOCAL_DISTRIBUTIONS,\
52 PloverLocalDistributionsPrivate)
54 PloverLocalDistribution *plover_local_distribution_new(const char *vendor,
55 const char *distribution)
59 PloverLocalDistribution *ld;
60 ld=g_new0(PloverLocalDistribution,1);
61 ld->vendor=g_strdup(vendor);
64 ld->distribution=g_strdup(distribution);
65 ld->user_friendly=g_strdup_printf("%s (%s)",distribution,vendor);
68 ld->user_friendly=g_strdup(vendor);
69 comps=plover_comps_new();
70 plover_comps_set_vendor(comps,vendor);
72 plover_comps_set_distribution(comps,distribution);
73 ld->prefix=plover_comps_get_default_prefix(comps);
74 plover_comps_free(comps);
75 s=g_build_filename(ld->prefix,"var","lib","razor",NULL);
76 ld->database_uri=razor_path_to_uri(s);
81 void plover_local_distribution_free(PloverLocalDistribution *ld)
86 g_free(ld->distribution);
88 g_free(ld->user_friendly);
89 g_free(ld->database_uri);
94 static void plover_local_distributions_finalize(GObject *obj)
96 PloverLocalDistributionsPrivate *priv;
97 priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj);
98 g_list_foreach(priv->distributions,(GFunc)plover_local_distribution_free,
100 g_list_free(priv->distributions);
101 if (G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize)
102 G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize(obj);
106 plover_local_distributions_class_init(PloverLocalDistributionsClass *klass)
108 GObjectClass *oclass=G_OBJECT_CLASS(klass);
109 oclass->finalize=plover_local_distributions_finalize;
110 g_type_class_add_private(klass,sizeof(PloverLocalDistributionsPrivate));
111 column_types[PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN]=G_TYPE_STRING;
112 column_types[PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN]=G_TYPE_STRING;
113 column_types[PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN]=G_TYPE_STRING;
114 column_types[PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN]=G_TYPE_STRING;
115 column_types[PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN]=G_TYPE_STRING;
118 static GtkTreeModelFlags
119 plover_local_distributions_get_flags(GtkTreeModel *tree_model)
121 return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY;
124 static gint plover_local_distributions_get_n_columns(GtkTreeModel *tree_model)
126 return PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS;
130 plover_local_distributions_get_column_type(GtkTreeModel *tree_model,gint indx)
132 g_return_val_if_fail(indx>=0 && indx<PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS,
134 return column_types[indx];
137 static gboolean plover_local_distributions_get_iter(GtkTreeModel *tree_model,
138 GtkTreeIter *iter,GtkTreePath *path)
141 PloverLocalDistributionsPrivate *priv;
142 PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
143 PloverLocalDistribution *ld;
144 priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local);
145 i=gtk_tree_path_get_indices(path)[0];
146 ld=g_list_nth_data(priv->distributions,i);
149 iter->stamp=priv->stamp;
155 plover_local_distributions_get_path(GtkTreeModel *tree_model,
159 PloverLocalDistributionsPrivate *priv;
160 PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
161 g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL);
162 priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local);
163 path=gtk_tree_path_new();
164 gtk_tree_path_append_index(path,
165 g_list_index(priv->distributions,iter->user_data));
169 static void plover_local_distributions_get_value(GtkTreeModel *tree_model,
170 GtkTreeIter *iter,gint column,GValue *value)
173 PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
174 PloverLocalDistribution *ld;
175 g_return_if_fail(column>=0 && column<PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS);
176 g_return_if_fail(VALID_ITER(iter,local));
178 g_value_init(value,column_types[column]);
179 switch((PloverLocalDistributionsColumn)column)
181 case PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN:
182 g_value_set_string(value,ld->vendor);
184 case PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN:
185 g_value_set_string(value,ld->distribution);
187 case PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN:
188 g_value_set_string(value,ld->prefix);
190 case PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN:
191 g_value_set_string(value,ld->user_friendly);
193 case PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN:
194 g_value_set_string(value,ld->database_uri);
196 case PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS:
197 /* Quieten compiler warning */
203 plover_local_distributions_iter_next(GtkTreeModel *tree_model,
207 PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
208 PloverLocalDistributionsPrivate *priv;
209 g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE);
210 priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local);
211 lnk=g_list_find(priv->distributions,iter->user_data);
212 iter->user_data=lnk->next?lnk->next->data:NULL;
213 return !!iter->user_data;
217 plover_local_distributions_iter_children(GtkTreeModel *tree_model,
218 GtkTreeIter *iter,GtkTreeIter *parent)
220 PloverLocalDistributionsPrivate *priv;
221 priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
222 /* this is a list, nodes have no children */
225 if (priv->distributions)
227 iter->stamp=priv->stamp;
228 iter->user_data=priv->distributions->data;
236 plover_local_distributions_iter_has_child(GtkTreeModel *tree_model,
239 PloverLocalDistributionsPrivate *priv;
240 priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
241 return !!priv->distributions;
244 static gint plover_local_distributions_iter_n_children(GtkTreeModel *tree_model,
247 PloverLocalDistributionsPrivate *priv;
248 priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
250 return g_list_length(priv->distributions);
251 g_return_val_if_fail(VALID_ITER(iter,tree_model),-1);
256 plover_local_distributions_iter_nth_child(GtkTreeModel *tree_model,
257 GtkTreeIter *iter,GtkTreeIter *parent,gint n)
260 PloverLocalDistributionsPrivate *priv;
261 priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
264 lnk=g_list_nth(priv->distributions,n);
267 iter->stamp=priv->stamp;
268 iter->user_data=lnk->data;
272 static gboolean plover_local_distributions_iter_parent(GtkTreeModel *tree_model,
273 GtkTreeIter *iter,GtkTreeIter *child)
278 static void plover_local_distributions_tree_model_init(GtkTreeModelIface *iface)
280 iface->get_flags=plover_local_distributions_get_flags;
281 iface->get_n_columns=plover_local_distributions_get_n_columns;
282 iface->get_column_type=plover_local_distributions_get_column_type;
283 iface->get_iter=plover_local_distributions_get_iter;
284 iface->get_path=plover_local_distributions_get_path;
285 iface->get_value=plover_local_distributions_get_value;
286 iface->iter_next=plover_local_distributions_iter_next;
287 iface->iter_children=plover_local_distributions_iter_children;
288 iface->iter_has_child=plover_local_distributions_iter_has_child;
289 iface->iter_n_children=plover_local_distributions_iter_n_children;
290 iface->iter_nth_child=plover_local_distributions_iter_nth_child;
291 iface->iter_parent=plover_local_distributions_iter_parent;
294 static void plover_local_distributions_init(PloverLocalDistributions *store)
297 const char *vendor_prefix,*vendor,*distribution;
298 GDir *vendor_dir,*distribution_dir,*database_dir;
299 PloverLocalDistributionsPrivate *priv;
300 PloverLocalDistribution *ld;
301 priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(store);
303 * local distribution databases may be found in
304 * <vendor-prefix>/$VENDOR/$DISTRIBUTION/var/lib/razor and
305 * <vendor-prefix>/$VENDOR/var/lib/razor
307 vendor_prefix=plover_get_vendor_prefix();
308 g_message("Vendor prefix is %s",vendor_prefix);
309 vendor_dir=g_dir_open(vendor_prefix,0,NULL);
312 g_warning("Failed to open %s",vendor_prefix);
315 while((vendor=g_dir_read_name(vendor_dir)))
317 g_message("Candidate for vendor is %s",vendor);
318 s=g_build_filename(vendor_prefix,vendor,NULL);
319 distribution_dir=g_dir_open(s,0,NULL);
321 if (!distribution_dir)
323 g_warning("Failed to open %s/%s",vendor_prefix,vendor);
326 while((distribution=g_dir_read_name(distribution_dir)))
328 g_message("Candidate for distribution is %s",distribution);
329 if (!strcmp(distribution,"var"))
331 s=g_build_filename(vendor_prefix,vendor,"var","lib","razor",
333 database_dir=g_dir_open(s,0,NULL);
337 ld=plover_local_distribution_new(vendor,NULL);
338 g_message("Found vendor-specific razor database at %s",
340 priv->distributions=g_list_prepend(priv->distributions,ld);
341 g_dir_close(database_dir);
344 g_warning("Failed to open %s/%s/var/lib/razor",
345 vendor_prefix,vendor);
347 s=g_build_filename(vendor_prefix,vendor,distribution,
348 "var","lib","razor",NULL);
349 database_dir=g_dir_open(s,0,NULL);
353 ld=plover_local_distribution_new(vendor,distribution);
354 g_message("Found local-distribution razor database at %s",
356 priv->distributions=g_list_prepend(priv->distributions,ld);
357 g_dir_close(database_dir);
360 g_warning("Failed to open %s/%s/%s/var/lib/razor",
361 vendor_prefix,vendor,distribution);
363 g_dir_close(distribution_dir);
365 g_dir_close(vendor_dir);
366 priv->stamp=g_random_int();
369 PloverLocalDistributions *plover_local_distributions_new(void)
371 return g_object_new(PLOVER_TYPE_LOCAL_DISTRIBUTIONS,NULL);