plover-gtk/packagefilestore.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Jul 16 11:07:18 2016 +0100 (2016-07-16)
changeset 61 31fb35727621
parent 24 2b9f54d14cc2
permissions -rw-r--r--
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.
     1 /*
     2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
     3  * Copyright (C) 2010  J. Ali Harlow <ali@juiblex.co.uk>
     4  *
     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.
     9  *
    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.
    14  *
    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.
    18  */
    19 
    20 #include "config.h"
    21 #include <stdlib.h>
    22 #include <string.h>
    23 #include <glib-object.h>
    24 #include <gtk/gtk.h>
    25 #include "plover-gtk/packagefilestore.h"
    26 
    27 #define VALID_ITER(iter,store) ((iter) && (iter)->user_data && \
    28 	PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(store)->stamp==(iter)->stamp && \
    29 	!g_sequence_iter_is_end((iter)->user_data) && \
    30 	g_sequence_iter_get_sequence((iter)->user_data)== \
    31 	PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(store)->seq)
    32 
    33 static GType column_types[PLOVER_PACKAGE_FILE_STORE_NO_COLUMNS];
    34 
    35 static void plover_package_file_store_tree_model_init(GtkTreeModelIface *iface);
    36 
    37 G_DEFINE_TYPE_WITH_CODE(PloverPackageFileStore,plover_package_file_store,
    38   G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL,
    39   plover_package_file_store_tree_model_init));
    40 
    41 typedef struct _PloverPackageFileStorePrivate {
    42     GSequence *seq;
    43     int stamp;
    44 } PloverPackageFileStorePrivate;
    45 
    46 #define PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(obj)\
    47 				G_TYPE_INSTANCE_GET_PRIVATE(obj,\
    48 				  PLOVER_TYPE_PACKAGE_FILE_STORE,\
    49 				  PloverPackageFileStorePrivate)
    50 
    51 static void plover_package_file_store_finalize(GObject *obj)
    52 {
    53     PloverPackageFileStorePrivate *priv=
    54       PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(obj);
    55     g_sequence_free(priv->seq);
    56     if (G_OBJECT_CLASS(plover_package_file_store_parent_class)->finalize)
    57 	G_OBJECT_CLASS(plover_package_file_store_parent_class)->finalize(obj);
    58 }
    59 
    60 static void
    61   plover_package_file_store_class_init(PloverPackageFileStoreClass *klass)
    62 {
    63     GObjectClass *oclass=G_OBJECT_CLASS(klass);
    64     oclass->finalize=plover_package_file_store_finalize;
    65     g_type_class_add_private(klass,sizeof(PloverPackageFileStorePrivate));
    66     column_types[PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN]=G_TYPE_STRING;
    67 }
    68 
    69 static GtkTreeModelFlags
    70 plover_package_file_store_get_flags(GtkTreeModel *tree_model)
    71 {
    72     return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY;
    73 }
    74 
    75 static gint plover_package_file_store_get_n_columns(GtkTreeModel *tree_model)
    76 {
    77     return PLOVER_PACKAGE_FILE_STORE_NO_COLUMNS;
    78 }
    79 
    80 static GType
    81   plover_package_file_store_get_column_type(GtkTreeModel *tree_model,gint indx)
    82 {
    83     g_return_val_if_fail(indx>=0 && indx<PLOVER_PACKAGE_FILE_STORE_NO_COLUMNS,
    84       G_TYPE_INVALID);
    85     return column_types[indx];
    86 }
    87 
    88 static gboolean plover_package_file_store_get_iter(GtkTreeModel *tree_model,
    89   GtkTreeIter *iter,GtkTreePath *path)
    90 {
    91     int i;
    92     PloverPackageFileStorePrivate *priv;
    93     PloverPackageFileStore *store=(PloverPackageFileStore *)tree_model;
    94     priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(store);
    95     i=gtk_tree_path_get_indices(path)[0];
    96     if (i>=g_sequence_get_length(priv->seq))
    97 	return FALSE;
    98     iter->stamp=priv->stamp;
    99     iter->user_data=g_sequence_get_iter_at_pos(priv->seq,i);
   100     return TRUE;
   101 }
   102 
   103 static GtkTreePath *
   104   plover_package_file_store_get_path(GtkTreeModel *tree_model,GtkTreeIter *iter)
   105 {
   106     GtkTreePath *path;
   107     g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL);
   108     if (g_sequence_iter_is_end(iter->user_data))
   109 	return NULL;
   110     path=gtk_tree_path_new();
   111     gtk_tree_path_append_index(path,
   112       g_sequence_iter_get_position(iter->user_data));
   113     return path;
   114 }
   115 
   116 static void plover_package_file_store_get_value(GtkTreeModel *tree_model,
   117   GtkTreeIter *iter,gint column,GValue *value)
   118 {
   119     PloverPackageFileStore *store=(PloverPackageFileStore *)tree_model;
   120     char *name;
   121     g_return_if_fail(column>=0 && column<PLOVER_PACKAGE_FILE_STORE_NO_COLUMNS);
   122     g_return_if_fail(VALID_ITER(iter,store));
   123     name=g_sequence_get(iter->user_data);
   124     g_value_init(value,column_types[column]);
   125     switch((PloverPackageFileStoreColumn)column)
   126     {
   127 	case PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN:
   128 	    g_value_set_string(value,name);
   129 	    break;
   130 	case PLOVER_PACKAGE_FILE_STORE_NO_COLUMNS:
   131 	    /* Quieten compiler warning */
   132 	    break;
   133     }
   134 }
   135 
   136 static gboolean plover_package_file_store_iter_next(GtkTreeModel *tree_model,
   137   GtkTreeIter *iter)
   138 {
   139     g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE);
   140     iter->user_data=g_sequence_iter_next(iter->user_data);
   141     return !g_sequence_iter_is_end(iter->user_data);
   142 }
   143 
   144 static gboolean
   145   plover_package_file_store_iter_children(GtkTreeModel *tree_model,
   146   GtkTreeIter *iter,GtkTreeIter *parent)
   147 {
   148     PloverPackageFileStorePrivate *priv;
   149     priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(tree_model);
   150     /* this is a list, nodes have no children */
   151     if (parent)
   152 	return FALSE;
   153     if (g_sequence_get_length(priv->seq)>0)
   154     {
   155 	iter->stamp=priv->stamp;
   156 	iter->user_data=g_sequence_get_begin_iter(priv->seq);
   157 	return TRUE;
   158     }
   159     else
   160 	return FALSE;
   161 }
   162 
   163 static gboolean
   164   plover_package_file_store_iter_has_child(GtkTreeModel *tree_model,
   165   GtkTreeIter *iter)
   166 {
   167     return FALSE;
   168 }
   169 
   170 static gint plover_package_file_store_iter_n_children(GtkTreeModel *tree_model,
   171   GtkTreeIter *iter)
   172 {
   173     PloverPackageFileStorePrivate *priv;
   174     priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(tree_model);
   175     if (!iter)
   176 	return g_sequence_get_length(priv->seq);
   177     g_return_val_if_fail(VALID_ITER(iter,tree_model),-1);
   178     return 0;
   179 }
   180 
   181 static gboolean
   182   plover_package_file_store_iter_nth_child(GtkTreeModel *tree_model,
   183   GtkTreeIter *iter,GtkTreeIter *parent,gint n)
   184 {
   185     PloverPackageFileStorePrivate *priv;
   186     priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(tree_model);
   187     GSequenceIter *child;
   188     if (parent)
   189 	return FALSE;
   190     child=g_sequence_get_iter_at_pos(priv->seq,n);
   191     if (g_sequence_iter_is_end(child))
   192 	return FALSE;
   193     iter->stamp=priv->stamp;
   194     iter->user_data=child;
   195     return TRUE;
   196 }
   197 
   198 static gboolean plover_package_file_store_iter_parent(GtkTreeModel *tree_model,
   199   GtkTreeIter *iter,GtkTreeIter *child)
   200 {
   201     return FALSE;
   202 }
   203 
   204 static void plover_package_file_store_tree_model_init(GtkTreeModelIface *iface)
   205 {
   206     iface->get_flags=plover_package_file_store_get_flags;
   207     iface->get_n_columns=plover_package_file_store_get_n_columns;
   208     iface->get_column_type=plover_package_file_store_get_column_type;
   209     iface->get_iter=plover_package_file_store_get_iter;
   210     iface->get_path=plover_package_file_store_get_path;
   211     iface->get_value=plover_package_file_store_get_value;
   212     iface->iter_next=plover_package_file_store_iter_next;
   213     iface->iter_children=plover_package_file_store_iter_children;
   214     iface->iter_has_child=plover_package_file_store_iter_has_child;
   215     iface->iter_n_children=plover_package_file_store_iter_n_children;
   216     iface->iter_nth_child=plover_package_file_store_iter_nth_child;
   217     iface->iter_parent=plover_package_file_store_iter_parent;
   218 }
   219 
   220 static void plover_package_file_store_init(PloverPackageFileStore *store)
   221 {
   222     PloverPackageFileStorePrivate *priv;
   223     priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(store);
   224     priv->seq=g_sequence_new(g_free);
   225     priv->stamp=g_random_int();
   226 }
   227 
   228 PloverPackageFileStore *
   229   plover_package_file_store_new(struct razor_file_iterator *files)
   230 {
   231     const char *name;
   232     char *s;
   233     GSequenceIter *si;
   234     GtkTreeIter ti;
   235     GtkTreePath *path;
   236     gint *indices;
   237     PloverPackageFileStore *store;
   238     PloverPackageFileStorePrivate *priv;
   239     store=g_object_new(PLOVER_TYPE_PACKAGE_FILE_STORE,NULL);
   240     priv=PLOVER_PACKAGE_FILE_STORE_GET_PRIVATE(store);
   241     path=gtk_tree_path_new();
   242     gtk_tree_path_append_index(path,0);
   243     indices=gtk_tree_path_get_indices(path);
   244     while(razor_file_iterator_next(files,&name))
   245     {
   246 	s=g_strdup(name);
   247 #ifdef WIN32
   248 	s=g_strdelimit(s,"/",'\\');
   249 #endif
   250 	si=g_sequence_insert_sorted(priv->seq,s,(GCompareDataFunc)g_strcmp0,
   251 	  NULL);
   252 	*indices=g_sequence_iter_get_position(si);
   253 	ti.stamp=priv->stamp;
   254 	ti.user_data=si;
   255 	gtk_tree_model_row_inserted(GTK_TREE_MODEL(store),path,&ti);
   256     }
   257     gtk_tree_path_free(path);
   258     return store;
   259 }
   260 
   261 PloverPackageFileStore *
   262   plover_package_file_store_new_from_package(PloverPackage *package)
   263 {
   264     PloverPackageFileStore *store;
   265     g_return_val_if_fail(PLOVER_IS_PACKAGE(package),NULL);
   266     struct razor_file_iterator *iter;
   267     iter=plover_package_file_iterator_create(package,FALSE);
   268     store=plover_package_file_store_new(iter);
   269     razor_file_iterator_destroy(iter);
   270     return store;
   271 }