ali@109: /* ali@109: * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford ali@109: * Copyright (C) 2023 J. Ali Harlow ali@109: * ali@109: * This program is free software; you can redistribute it and/or modify ali@109: * it under the terms of the GNU General Public License as published by ali@109: * the Free Software Foundation; either version 2 of the License, or ali@109: * (at your option) any later version. ali@109: * ali@109: * This program is distributed in the hope that it will be useful, ali@109: * but WITHOUT ANY WARRANTY; without even the implied warranty of ali@109: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ali@109: * GNU General Public License for more details. ali@109: * ali@109: * You should have received a copy of the GNU General Public License along ali@109: * with this program; if not, write to the Free Software Foundation, Inc., ali@109: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ali@109: */ ali@109: ali@109: #include "config.h" ali@109: #include ali@109: #include ali@109: #include ali@109: #include ali@109: #include ali@109: #include "localdistributions.h" ali@109: ali@109: #define VALID_ITER(iter,local) ((iter) && (iter)->user_data && \ ali@109: PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local)->stamp==(iter)->stamp) ali@109: ali@109: static GType column_types[PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS]; ali@109: ali@109: static void ali@109: plover_local_distributions_tree_model_init(GtkTreeModelIface *iface); ali@109: ali@109: G_DEFINE_TYPE_WITH_CODE(PloverLocalDistributions,plover_local_distributions, ali@109: G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL, ali@109: plover_local_distributions_tree_model_init)); ali@109: ali@109: typedef struct _PloverLocalDistribution { ali@109: gchar *vendor,*distribution,*prefix,*user_friendly,*database_uri; ali@109: } PloverLocalDistribution; ali@109: ali@109: typedef struct _PloverLocalDistributionsPrivate { ali@109: GList *distributions; ali@109: int stamp; ali@109: } PloverLocalDistributionsPrivate; ali@109: ali@109: #define PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj)\ ali@109: G_TYPE_INSTANCE_GET_PRIVATE(obj,\ ali@109: PLOVER_TYPE_LOCAL_DISTRIBUTIONS,\ ali@109: PloverLocalDistributionsPrivate) ali@109: ali@109: PloverLocalDistribution *plover_local_distribution_new(const char *vendor, ali@109: const char *distribution) ali@109: { ali@109: gchar *s; ali@109: struct comps *comps; ali@109: PloverLocalDistribution *ld; ali@109: ld=g_new0(PloverLocalDistribution,1); ali@109: ld->vendor=g_strdup(vendor); ali@109: if (distribution) ali@109: { ali@109: ld->distribution=g_strdup(distribution); ali@109: ld->user_friendly=g_strdup_printf("%s (%s)",distribution,vendor); ali@109: } ali@109: else ali@109: ld->user_friendly=g_strdup(vendor); ali@109: comps=plover_comps_new(); ali@109: plover_comps_set_vendor(comps,vendor); ali@109: if (distribution) ali@109: plover_comps_set_distribution(comps,distribution); ali@109: ld->prefix=plover_comps_get_default_prefix(comps); ali@109: plover_comps_free(comps); ali@109: s=g_build_filename(ld->prefix,"var","lib","razor",NULL); ali@109: ld->database_uri=razor_path_to_uri(s); ali@109: g_free(s); ali@109: return ld; ali@109: } ali@109: ali@109: void plover_local_distribution_free(PloverLocalDistribution *ld) ali@109: { ali@109: if (ld) ali@109: { ali@109: g_free(ld->vendor); ali@109: g_free(ld->distribution); ali@109: g_free(ld->prefix); ali@109: g_free(ld->user_friendly); ali@109: g_free(ld->database_uri); ali@109: g_free(ld); ali@109: } ali@109: } ali@109: ali@109: static void plover_local_distributions_finalize(GObject *obj) ali@109: { ali@109: PloverLocalDistributionsPrivate *priv; ali@109: priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj); ali@109: g_list_foreach(priv->distributions,(GFunc)plover_local_distribution_free, ali@109: NULL); ali@109: g_list_free(priv->distributions); ali@109: if (G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize) ali@109: G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize(obj); ali@109: } ali@109: ali@109: static void ali@109: plover_local_distributions_class_init(PloverLocalDistributionsClass *klass) ali@109: { ali@109: GObjectClass *oclass=G_OBJECT_CLASS(klass); ali@109: oclass->finalize=plover_local_distributions_finalize; ali@109: g_type_class_add_private(klass,sizeof(PloverLocalDistributionsPrivate)); ali@109: column_types[PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN]=G_TYPE_STRING; ali@109: column_types[PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN]=G_TYPE_STRING; ali@109: column_types[PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN]=G_TYPE_STRING; ali@109: column_types[PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN]=G_TYPE_STRING; ali@109: column_types[PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN]=G_TYPE_STRING; ali@109: } ali@109: ali@109: static GtkTreeModelFlags ali@109: plover_local_distributions_get_flags(GtkTreeModel *tree_model) ali@109: { ali@109: return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY; ali@109: } ali@109: ali@109: static gint plover_local_distributions_get_n_columns(GtkTreeModel *tree_model) ali@109: { ali@109: return PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS; ali@109: } ali@109: ali@109: static GType ali@109: plover_local_distributions_get_column_type(GtkTreeModel *tree_model,gint indx) ali@109: { ali@109: g_return_val_if_fail(indx>=0 && indxdistributions,i); ali@109: if (!ld) ali@109: return FALSE; ali@109: iter->stamp=priv->stamp; ali@109: iter->user_data=ld; ali@109: return TRUE; ali@109: } ali@109: ali@109: static GtkTreePath * ali@109: plover_local_distributions_get_path(GtkTreeModel *tree_model, ali@109: GtkTreeIter *iter) ali@109: { ali@109: GtkTreePath *path; ali@109: PloverLocalDistributionsPrivate *priv; ali@109: PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model; ali@109: g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL); ali@109: priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local); ali@109: path=gtk_tree_path_new(); ali@109: gtk_tree_path_append_index(path, ali@109: g_list_index(priv->distributions,iter->user_data)); ali@109: return path; ali@109: } ali@109: ali@109: static void plover_local_distributions_get_value(GtkTreeModel *tree_model, ali@109: GtkTreeIter *iter,gint column,GValue *value) ali@109: { ali@109: gchar *s; ali@109: PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model; ali@109: PloverLocalDistribution *ld; ali@109: g_return_if_fail(column>=0 && columnuser_data; ali@109: g_value_init(value,column_types[column]); ali@109: switch((PloverLocalDistributionsColumn)column) ali@109: { ali@109: case PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN: ali@109: g_value_set_string(value,ld->vendor); ali@109: break; ali@109: case PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN: ali@109: g_value_set_string(value,ld->distribution); ali@109: break; ali@109: case PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN: ali@109: g_value_set_string(value,ld->prefix); ali@109: break; ali@109: case PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN: ali@109: g_value_set_string(value,ld->user_friendly); ali@109: break; ali@109: case PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN: ali@109: g_value_set_string(value,ld->database_uri); ali@109: break; ali@109: case PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS: ali@109: /* Quieten compiler warning */ ali@109: break; ali@109: } ali@109: } ali@109: ali@109: static gboolean ali@109: plover_local_distributions_iter_next(GtkTreeModel *tree_model, ali@109: GtkTreeIter *iter) ali@109: { ali@109: GList *lnk; ali@109: PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model; ali@109: PloverLocalDistributionsPrivate *priv; ali@109: g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE); ali@109: priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local); ali@109: lnk=g_list_find(priv->distributions,iter->user_data); ali@109: iter->user_data=lnk->next?lnk->next->data:NULL; ali@109: return !!iter->user_data; ali@109: } ali@109: ali@109: static gboolean ali@109: plover_local_distributions_iter_children(GtkTreeModel *tree_model, ali@109: GtkTreeIter *iter,GtkTreeIter *parent) ali@109: { ali@109: PloverLocalDistributionsPrivate *priv; ali@109: priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); ali@109: /* this is a list, nodes have no children */ ali@109: if (parent) ali@109: return FALSE; ali@109: if (priv->distributions) ali@109: { ali@109: iter->stamp=priv->stamp; ali@109: iter->user_data=priv->distributions->data; ali@109: return TRUE; ali@109: } ali@109: else ali@109: return FALSE; ali@109: } ali@109: ali@109: static gboolean ali@109: plover_local_distributions_iter_has_child(GtkTreeModel *tree_model, ali@109: GtkTreeIter *iter) ali@109: { ali@109: PloverLocalDistributionsPrivate *priv; ali@109: priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); ali@109: return !!priv->distributions; ali@109: } ali@109: ali@109: static gint plover_local_distributions_iter_n_children(GtkTreeModel *tree_model, ali@109: GtkTreeIter *iter) ali@109: { ali@109: PloverLocalDistributionsPrivate *priv; ali@109: priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); ali@109: if (!iter) ali@109: return g_list_length(priv->distributions); ali@109: g_return_val_if_fail(VALID_ITER(iter,tree_model),-1); ali@109: return 0; ali@109: } ali@109: ali@109: static gboolean ali@109: plover_local_distributions_iter_nth_child(GtkTreeModel *tree_model, ali@109: GtkTreeIter *iter,GtkTreeIter *parent,gint n) ali@109: { ali@109: GList *lnk; ali@109: PloverLocalDistributionsPrivate *priv; ali@109: priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); ali@109: if (parent) ali@109: return FALSE; ali@109: lnk=g_list_nth(priv->distributions,n); ali@109: if (!lnk) ali@109: return FALSE; ali@109: iter->stamp=priv->stamp; ali@109: iter->user_data=lnk->data; ali@109: return TRUE; ali@109: } ali@109: ali@109: static gboolean plover_local_distributions_iter_parent(GtkTreeModel *tree_model, ali@109: GtkTreeIter *iter,GtkTreeIter *child) ali@109: { ali@109: return FALSE; ali@109: } ali@109: ali@109: static void plover_local_distributions_tree_model_init(GtkTreeModelIface *iface) ali@109: { ali@109: iface->get_flags=plover_local_distributions_get_flags; ali@109: iface->get_n_columns=plover_local_distributions_get_n_columns; ali@109: iface->get_column_type=plover_local_distributions_get_column_type; ali@109: iface->get_iter=plover_local_distributions_get_iter; ali@109: iface->get_path=plover_local_distributions_get_path; ali@109: iface->get_value=plover_local_distributions_get_value; ali@109: iface->iter_next=plover_local_distributions_iter_next; ali@109: iface->iter_children=plover_local_distributions_iter_children; ali@109: iface->iter_has_child=plover_local_distributions_iter_has_child; ali@109: iface->iter_n_children=plover_local_distributions_iter_n_children; ali@109: iface->iter_nth_child=plover_local_distributions_iter_nth_child; ali@109: iface->iter_parent=plover_local_distributions_iter_parent; ali@109: } ali@109: ali@109: static void plover_local_distributions_init(PloverLocalDistributions *store) ali@109: { ali@109: gchar *s; ali@109: const char *vendor_prefix,*vendor,*distribution; ali@109: GDir *vendor_dir,*distribution_dir,*database_dir; ali@109: PloverLocalDistributionsPrivate *priv; ali@109: PloverLocalDistribution *ld; ali@109: priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(store); ali@109: /* ali@109: * local distribution databases may be found in ali@109: * /$VENDOR/$DISTRIBUTION/var/lib/razor and ali@109: * /$VENDOR/var/lib/razor ali@109: */ ali@109: vendor_prefix=plover_get_vendor_prefix(); ali@109: g_message("Vendor prefix is %s",vendor_prefix); ali@109: vendor_dir=g_dir_open(vendor_prefix,0,NULL); ali@109: if (!vendor_dir) ali@109: { ali@109: g_warning("Failed to open %s",vendor_prefix); ali@109: return; ali@109: } ali@109: while((vendor=g_dir_read_name(vendor_dir))) ali@109: { ali@109: g_message("Candidate for vendor is %s",vendor); ali@109: s=g_build_filename(vendor_prefix,vendor,NULL); ali@109: distribution_dir=g_dir_open(s,0,NULL); ali@109: g_free(s); ali@109: if (!distribution_dir) ali@109: { ali@109: g_warning("Failed to open %s/%s",vendor_prefix,vendor); ali@109: continue; ali@109: } ali@109: while((distribution=g_dir_read_name(distribution_dir))) ali@109: { ali@109: g_message("Candidate for distribution is %s",distribution); ali@109: if (!strcmp(distribution,"var")) ali@109: { ali@109: s=g_build_filename(vendor_prefix,vendor,"var","lib","razor", ali@109: NULL); ali@109: database_dir=g_dir_open(s,0,NULL); ali@109: g_free(s); ali@109: if (database_dir) ali@109: { ali@109: ld=plover_local_distribution_new(vendor,NULL); ali@109: g_message("Found vendor-specific razor database at %s", ali@109: ld->database_uri); ali@109: priv->distributions=g_list_prepend(priv->distributions,ld); ali@109: g_dir_close(database_dir); ali@109: } ali@109: else ali@109: g_warning("Failed to open %s/%s/var/lib/razor", ali@109: vendor_prefix,vendor); ali@109: } ali@109: s=g_build_filename(vendor_prefix,vendor,distribution, ali@109: "var","lib","razor",NULL); ali@109: database_dir=g_dir_open(s,0,NULL); ali@109: g_free(s); ali@109: if (database_dir) ali@109: { ali@109: ld=plover_local_distribution_new(vendor,distribution); ali@109: g_message("Found local-distribution razor database at %s", ali@109: ld->database_uri); ali@109: priv->distributions=g_list_prepend(priv->distributions,ld); ali@109: g_dir_close(database_dir); ali@109: } ali@109: else ali@109: g_warning("Failed to open %s/%s/%s/var/lib/razor", ali@109: vendor_prefix,vendor,distribution); ali@109: } ali@109: g_dir_close(distribution_dir); ali@109: } ali@109: g_dir_close(vendor_dir); ali@109: priv->stamp=g_random_int(); ali@109: } ali@109: ali@109: PloverLocalDistributions *plover_local_distributions_new(void) ali@109: { ali@109: return g_object_new(PLOVER_TYPE_LOCAL_DISTRIBUTIONS,NULL); ali@109: }