choice_model.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * cdebconf - An implementation of the Debian Configuration Management
00004  *            System
00005  *
00006  * $Id$
00007  *
00008  * cdebconf is (c) 2000-2007 Randolph Chung and others under the following
00009  * license.
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  *
00015  * 1. Redistributions of source code must retain the above copyright
00016  * notice, this list of conditions and the following disclaimer.
00017  *
00018  * 2. Redistributions in binary form must reproduce the above copyright
00019  * notice, this list of conditions and the following disclaimer in the
00020  * documentation and/or other materials provided with the distribution.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  *****************************************************************************/
00035 
00041 #include "choice_model.h"
00042 
00043 #include <string.h>
00044 #include <gtk/gtk.h>
00045 
00046 #include "frontend.h"
00047 #include "question.h"
00048 #include "strutl.h"
00049 
00052 struct search_result {
00054     const char * searched_value;
00055 
00057     GtkTreePath * path;
00058 };
00059 
00068 static gboolean is_searched_value(GtkTreeModel * model, GtkTreePath * path,
00069                                   GtkTreeIter * iter,
00070                                   struct search_result * result)
00071 {
00072     char * value;
00073 
00074     gtk_tree_model_get(model, iter,
00075                        /* column: */ CHOICE_MODEL_VALUE, &value,
00076                        -1 /* end of list */);
00077     if (0 == strcmp(value, result->searched_value)) {
00078         result->path = gtk_tree_path_copy(path);
00079     }
00080     g_free(value);
00081     return NULL != result->path;
00082 }
00083 
00091 GtkTreePath * fe_gtk_choice_model_find_value(GtkTreeModel * model,
00092                                              const char * searched_value)
00093 {
00094     struct search_result result;
00095 
00096     result.searched_value = searched_value;
00097     result.path = NULL;
00098 
00099     gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc) is_searched_value,
00100                            &result);
00101     return result.path;
00102 }
00103 
00113 GtkTreeModel * fe_gtk_choice_model_create_full(struct frontend * fe,
00114                                                struct question * question,
00115                                                parent_predicate is_parent)
00116 {
00117     GtkTreeStore * store;
00118     int count;
00119     int sorted_count;
00120     char * raw_indices;
00121     char * raw_choices;
00122     char * raw_translated_choices;
00123     int * sorted_indices;
00124     char ** choice_values;
00125     char ** choice_translated_values;
00126     char ** default_values;
00127     int default_count;
00128     int i;
00129     GtkTreeIter iter;
00130     GtkTreeIter child;
00131     GtkTreePath * path;
00132 
00133     store = gtk_tree_store_new(CHOICE_MODEL_COLUMN_COUNT,
00134                                G_TYPE_BOOLEAN /* selected */,
00135                                G_TYPE_INT /* index */,
00136                                G_TYPE_STRING /* value */,
00137                                G_TYPE_STRING /* translated value */);
00138     if (NULL == store) {
00139         g_warning("gtk_tree_store_new failed.");
00140         return NULL;
00141     };
00142    
00143     raw_indices = q_get_indices(question);
00144     raw_choices = q_get_choices_vals(question);
00145     raw_translated_choices = q_get_choices(question);
00146     count = strgetargc(raw_choices);
00147     g_assert(0 < count);
00148     /* check NULLs! */
00149     sorted_indices = g_malloc0(count * sizeof (int));
00150     choice_values = g_malloc0(count * sizeof (char *));
00151     choice_translated_values = g_malloc0(count * sizeof (char *));
00152     default_values = g_malloc0(count * sizeof (char *));
00153 
00154     /* XXX: strchoicesplitsort interface is really nasty... :(
00155      *      Maybe it would be better to re-implement something with the nifty
00156      *      glib functions... */
00157     sorted_count = strchoicesplitsort(raw_choices, raw_translated_choices,
00158                                       raw_indices, choice_values,
00159                                       choice_translated_values,
00160                                       sorted_indices, count);
00161     g_assert(sorted_count == count);
00162 
00163     default_count = strchoicesplit(question_getvalue(question, ""),
00164                                    default_values, count);
00165     g_assert(0 <= default_count);
00166 
00167     /* Populate model */
00168     for (i = 0; i < count; i++) {
00169         if (NULL == is_parent ||
00170             is_parent(sorted_indices[i], choice_values[i],
00171                       choice_translated_values[i])) {
00172             gtk_tree_store_append(store, &iter, NULL /* no parent */);
00173             gtk_tree_store_set(
00174                 store, &iter,
00175                 /* column: */ CHOICE_MODEL_SELECTED, FALSE,
00176                 /* column: */ CHOICE_MODEL_INDEX, sorted_indices[i],
00177                 /* column: */ CHOICE_MODEL_VALUE, choice_values[i],
00178                 /* column: */ CHOICE_MODEL_TRANSLATED_VALUE,
00179                               choice_translated_values[i],
00180                 -1 /* end of list */);
00181         } else {
00182             gtk_tree_store_append(store, &child, &iter);
00183             gtk_tree_store_set(
00184                 store, &child,
00185                 /* column: */ CHOICE_MODEL_SELECTED, FALSE,
00186                 /* column: */ CHOICE_MODEL_INDEX, sorted_indices[i],
00187                 /* column: */ CHOICE_MODEL_VALUE, choice_values[i],
00188                 /* column: */ CHOICE_MODEL_TRANSLATED_VALUE,
00189                               choice_translated_values[i],
00190                 -1 /* end of list */);
00191         }
00192     }
00193 
00194     /* Mark defaults as selected */
00195     for (i = 0; i < default_count; i++) {
00196         if (NULL != (path = fe_gtk_choice_model_find_value(
00197                                 GTK_TREE_MODEL(store), default_values[i]))) {
00198             if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path)) {
00199                 gtk_tree_store_set(store, &iter,
00200                                    /* column: */ CHOICE_MODEL_SELECTED, TRUE,
00201                                    -1 /* end of list */);
00202             }
00203             gtk_tree_path_free(path);
00204         }
00205     }
00206 
00207     g_free(sorted_indices);
00208     g_free(choice_values);
00209     g_free(choice_translated_values);
00210     g_free(raw_translated_choices);
00211     g_free(raw_choices);
00212     g_free(raw_indices);
00213     return GTK_TREE_MODEL(store);
00214 }
00215 
00222 GtkTreeModel * fe_gtk_choice_model_create(struct frontend * fe,
00223                                           struct question * question)
00224 {
00225     return fe_gtk_choice_model_create_full(
00226         fe, question, NULL /* no parent predicate */);
00227 }
00228 
00237 static gboolean increment_model_length(GtkTreeModel * model,
00238                                        GtkTreePath * path,
00239                                        GtkTreeIter * iter, guint * length)
00240 {
00241     *length = *length + 1;
00242     return FALSE; /* foreach should go on */
00243 }
00244 
00250 guint fe_gtk_choice_model_get_length(GtkTreeModel * model)
00251 {
00252     guint length = 0;
00253 
00254     g_assert(NULL != model);
00255 
00256     gtk_tree_model_foreach(
00257         model, (GtkTreeModelForeachFunc) increment_model_length, &length);
00258     return length;
00259 }
00260 
00269 static gboolean is_selected(GtkTreeModel * model, GtkTreePath * path,
00270                             GtkTreeIter * iter, GtkTreePath ** result)
00271 {
00272     gboolean selected;
00273 
00274     gtk_tree_model_get(model, iter,
00275                        /* column: */ CHOICE_MODEL_SELECTED, &selected,
00276                        -1 /* end of list */);
00277     if (selected) {
00278         *result = gtk_tree_path_copy(path);
00279         return TRUE /* stop here */;
00280     }
00281     return FALSE;
00282 }
00283 
00291 GtkTreePath * fe_gtk_choice_model_get_first_selected(GtkTreeModel * model)
00292 {
00293     GtkTreePath * result = NULL;
00294   
00295     gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc) is_selected,
00296                            &result);
00297     return result;
00298 }
00299 
00309 void fe_gtk_choice_model_set(GtkTreeModel * model, GtkTreeIter * iter, ...)
00310 {
00311     va_list var_args;
00312 
00313     va_start(var_args, iter);
00314     gtk_tree_store_set_valist(GTK_TREE_STORE(model), iter, var_args);
00315     va_end(var_args);
00316 }
00317 
00318 /* vim: et sw=4 si
00319  */

Generated on Sat Jul 7 23:41:41 2007 for fe_gtk by  doxygen 1.5.1