/* * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford * Copyright (C) 2023 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 "localdistributions.h" #define VALID_ITER(iter,local) ((iter) && (iter)->user_data && \ PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local)->stamp==(iter)->stamp) static GType column_types[PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS]; static void plover_local_distributions_tree_model_init(GtkTreeModelIface *iface); G_DEFINE_TYPE_WITH_CODE(PloverLocalDistributions,plover_local_distributions, G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL, plover_local_distributions_tree_model_init)); typedef struct _PloverLocalDistribution { gchar *vendor,*distribution,*prefix,*user_friendly,*database_uri; } PloverLocalDistribution; typedef struct _PloverLocalDistributionsPrivate { GList *distributions; int stamp; } PloverLocalDistributionsPrivate; #define PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj)\ G_TYPE_INSTANCE_GET_PRIVATE(obj,\ PLOVER_TYPE_LOCAL_DISTRIBUTIONS,\ PloverLocalDistributionsPrivate) PloverLocalDistribution *plover_local_distribution_new(const char *vendor, const char *distribution) { gchar *s; struct comps *comps; PloverLocalDistribution *ld; ld=g_new0(PloverLocalDistribution,1); ld->vendor=g_strdup(vendor); if (distribution) { ld->distribution=g_strdup(distribution); ld->user_friendly=g_strdup_printf("%s (%s)",distribution,vendor); } else ld->user_friendly=g_strdup(vendor); comps=plover_comps_new(); plover_comps_set_vendor(comps,vendor); if (distribution) plover_comps_set_distribution(comps,distribution); ld->prefix=plover_comps_get_default_prefix(comps); plover_comps_free(comps); s=g_build_filename(ld->prefix,"var","lib","razor",NULL); ld->database_uri=razor_path_to_uri(s); g_free(s); return ld; } void plover_local_distribution_free(PloverLocalDistribution *ld) { if (ld) { g_free(ld->vendor); g_free(ld->distribution); g_free(ld->prefix); g_free(ld->user_friendly); g_free(ld->database_uri); g_free(ld); } } static void plover_local_distributions_finalize(GObject *obj) { PloverLocalDistributionsPrivate *priv; priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj); g_list_foreach(priv->distributions,(GFunc)plover_local_distribution_free, NULL); g_list_free(priv->distributions); if (G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize) G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize(obj); } static void plover_local_distributions_class_init(PloverLocalDistributionsClass *klass) { GObjectClass *oclass=G_OBJECT_CLASS(klass); oclass->finalize=plover_local_distributions_finalize; g_type_class_add_private(klass,sizeof(PloverLocalDistributionsPrivate)); column_types[PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN]=G_TYPE_STRING; column_types[PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN]=G_TYPE_STRING; column_types[PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN]=G_TYPE_STRING; column_types[PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN]=G_TYPE_STRING; column_types[PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN]=G_TYPE_STRING; } static GtkTreeModelFlags plover_local_distributions_get_flags(GtkTreeModel *tree_model) { return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY; } static gint plover_local_distributions_get_n_columns(GtkTreeModel *tree_model) { return PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS; } static GType plover_local_distributions_get_column_type(GtkTreeModel *tree_model,gint indx) { g_return_val_if_fail(indx>=0 && indxdistributions,i); if (!ld) return FALSE; iter->stamp=priv->stamp; iter->user_data=ld; return TRUE; } static GtkTreePath * plover_local_distributions_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter) { GtkTreePath *path; PloverLocalDistributionsPrivate *priv; PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model; g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL); priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local); path=gtk_tree_path_new(); gtk_tree_path_append_index(path, g_list_index(priv->distributions,iter->user_data)); return path; } static void plover_local_distributions_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter,gint column,GValue *value) { gchar *s; PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model; PloverLocalDistribution *ld; g_return_if_fail(column>=0 && columnuser_data; g_value_init(value,column_types[column]); switch((PloverLocalDistributionsColumn)column) { case PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN: g_value_set_string(value,ld->vendor); break; case PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN: g_value_set_string(value,ld->distribution); break; case PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN: g_value_set_string(value,ld->prefix); break; case PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN: g_value_set_string(value,ld->user_friendly); break; case PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN: g_value_set_string(value,ld->database_uri); break; case PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS: /* Quieten compiler warning */ break; } } static gboolean plover_local_distributions_iter_next(GtkTreeModel *tree_model, GtkTreeIter *iter) { GList *lnk; PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model; PloverLocalDistributionsPrivate *priv; g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE); priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local); lnk=g_list_find(priv->distributions,iter->user_data); iter->user_data=lnk->next?lnk->next->data:NULL; return !!iter->user_data; } static gboolean plover_local_distributions_iter_children(GtkTreeModel *tree_model, GtkTreeIter *iter,GtkTreeIter *parent) { PloverLocalDistributionsPrivate *priv; priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); /* this is a list, nodes have no children */ if (parent) return FALSE; if (priv->distributions) { iter->stamp=priv->stamp; iter->user_data=priv->distributions->data; return TRUE; } else return FALSE; } static gboolean plover_local_distributions_iter_has_child(GtkTreeModel *tree_model, GtkTreeIter *iter) { PloverLocalDistributionsPrivate *priv; priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); return !!priv->distributions; } static gint plover_local_distributions_iter_n_children(GtkTreeModel *tree_model, GtkTreeIter *iter) { PloverLocalDistributionsPrivate *priv; priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); if (!iter) return g_list_length(priv->distributions); g_return_val_if_fail(VALID_ITER(iter,tree_model),-1); return 0; } static gboolean plover_local_distributions_iter_nth_child(GtkTreeModel *tree_model, GtkTreeIter *iter,GtkTreeIter *parent,gint n) { GList *lnk; PloverLocalDistributionsPrivate *priv; priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); if (parent) return FALSE; lnk=g_list_nth(priv->distributions,n); if (!lnk) return FALSE; iter->stamp=priv->stamp; iter->user_data=lnk->data; return TRUE; } static gboolean plover_local_distributions_iter_parent(GtkTreeModel *tree_model, GtkTreeIter *iter,GtkTreeIter *child) { return FALSE; } static void plover_local_distributions_tree_model_init(GtkTreeModelIface *iface) { iface->get_flags=plover_local_distributions_get_flags; iface->get_n_columns=plover_local_distributions_get_n_columns; iface->get_column_type=plover_local_distributions_get_column_type; iface->get_iter=plover_local_distributions_get_iter; iface->get_path=plover_local_distributions_get_path; iface->get_value=plover_local_distributions_get_value; iface->iter_next=plover_local_distributions_iter_next; iface->iter_children=plover_local_distributions_iter_children; iface->iter_has_child=plover_local_distributions_iter_has_child; iface->iter_n_children=plover_local_distributions_iter_n_children; iface->iter_nth_child=plover_local_distributions_iter_nth_child; iface->iter_parent=plover_local_distributions_iter_parent; } static void plover_local_distributions_init(PloverLocalDistributions *store) { gchar *s; const char *vendor_prefix,*vendor,*distribution; GDir *vendor_dir,*distribution_dir,*database_dir; PloverLocalDistributionsPrivate *priv; PloverLocalDistribution *ld; priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(store); /* * local distribution databases may be found in * /$VENDOR/$DISTRIBUTION/var/lib/razor and * /$VENDOR/var/lib/razor */ vendor_prefix=plover_get_vendor_prefix(); g_message("Vendor prefix is %s",vendor_prefix); vendor_dir=g_dir_open(vendor_prefix,0,NULL); if (!vendor_dir) { g_warning("Failed to open %s",vendor_prefix); return; } while((vendor=g_dir_read_name(vendor_dir))) { g_message("Candidate for vendor is %s",vendor); s=g_build_filename(vendor_prefix,vendor,NULL); distribution_dir=g_dir_open(s,0,NULL); g_free(s); if (!distribution_dir) { g_warning("Failed to open %s/%s",vendor_prefix,vendor); continue; } while((distribution=g_dir_read_name(distribution_dir))) { g_message("Candidate for distribution is %s",distribution); if (!strcmp(distribution,"var")) { s=g_build_filename(vendor_prefix,vendor,"var","lib","razor", NULL); database_dir=g_dir_open(s,0,NULL); g_free(s); if (database_dir) { ld=plover_local_distribution_new(vendor,NULL); g_message("Found vendor-specific razor database at %s", ld->database_uri); priv->distributions=g_list_prepend(priv->distributions,ld); g_dir_close(database_dir); } else g_warning("Failed to open %s/%s/var/lib/razor", vendor_prefix,vendor); } s=g_build_filename(vendor_prefix,vendor,distribution, "var","lib","razor",NULL); database_dir=g_dir_open(s,0,NULL); g_free(s); if (database_dir) { ld=plover_local_distribution_new(vendor,distribution); g_message("Found local-distribution razor database at %s", ld->database_uri); priv->distributions=g_list_prepend(priv->distributions,ld); g_dir_close(database_dir); } else g_warning("Failed to open %s/%s/%s/var/lib/razor", vendor_prefix,vendor,distribution); } g_dir_close(distribution_dir); } g_dir_close(vendor_dir); priv->stamp=g_random_int(); } PloverLocalDistributions *plover_local_distributions_new(void) { return g_object_new(PLOVER_TYPE_LOCAL_DISTRIBUTIONS,NULL); }