|
GnuCash 2.4.99
|
00001 /* 00002 * gnc-tree-model-account-types.c -- GtkTreeModel implementation 00003 * to display account types in a GtkTreeView. 00004 * 00005 * Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de> 00006 * Copyright (C) 2005, 2006 Chris Shoemaker <c.shoemaker@cox.net> 00007 * Copyright (C) 2006 Eskil Bylund <eskil.bylund@gmail.com> 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License as 00011 * published by the Free Software Foundation; either version 2 of 00012 * the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, contact: 00021 * 00022 * Free Software Foundation Voice: +1-617-542-5942 00023 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 00024 * Boston, MA 02110-1301, USA gnu@gnu.org 00025 */ 00026 00027 #include "config.h" 00028 00029 #include <gtk/gtk.h> 00030 00031 #include "qof.h" 00032 #include "gnc-tree-model-account-types.h" 00033 #include "Account.h" 00034 00035 static QofLogModule log_module = GNC_MOD_GUI; 00036 static GtkTreeModel *account_types_tree_model = NULL; 00037 00038 #define TYPE_MASK "type-mask" 00039 00040 /* Functions for the type system */ 00041 static void 00042 gnc_tree_model_account_types_class_init (GncTreeModelAccountTypesClass *klass); 00043 static void 00044 gnc_tree_model_account_types_init (GncTreeModelAccountTypes * model); 00045 static void 00046 gnc_tree_model_account_types_finalize (GObject * object); 00047 00048 00049 /* Functions implementing GtkTreeModel */ 00050 static void 00051 gnc_tree_model_account_types_tree_model_init (GtkTreeModelIface * iface); 00052 00053 typedef struct GncTreeModelAccountTypesPrivate 00054 { 00055 guint32 selected; 00056 } GncTreeModelAccountTypesPrivate; 00057 00058 #define GNC_TREE_MODEL_ACCOUNT_TYPES_GET_PRIVATE(o) \ 00059 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_MODEL_ACCOUNT_TYPES, \ 00060 GncTreeModelAccountTypesPrivate)) 00061 00062 static GObjectClass *parent_class = NULL; 00063 00064 GType 00065 gnc_tree_model_account_types_get_type (void) 00066 { 00067 static GType gnc_tree_model_account_types_type = 0; 00068 00069 if (gnc_tree_model_account_types_type == 0) 00070 { 00071 static const GTypeInfo our_info = 00072 { 00073 sizeof (GncTreeModelAccountTypesClass), 00074 NULL, 00075 NULL, 00076 (GClassInitFunc) gnc_tree_model_account_types_class_init, 00077 NULL, 00078 NULL, 00079 sizeof (GncTreeModelAccountTypes), 00080 0, 00081 (GInstanceInitFunc) gnc_tree_model_account_types_init 00082 }; 00083 00084 static const GInterfaceInfo tree_model_info = 00085 { 00086 (GInterfaceInitFunc) gnc_tree_model_account_types_tree_model_init, 00087 NULL, 00088 NULL 00089 }; 00090 00091 gnc_tree_model_account_types_type = 00092 g_type_register_static (G_TYPE_OBJECT, 00093 "GncTreeModelAccountTypes", 00094 &our_info, 0); 00095 00096 g_type_add_interface_static (gnc_tree_model_account_types_type, 00097 GTK_TYPE_TREE_MODEL, &tree_model_info); 00098 } 00099 00100 return gnc_tree_model_account_types_type; 00101 } 00102 00103 static void 00104 gnc_tree_model_account_types_class_init (GncTreeModelAccountTypesClass * klass) 00105 { 00106 GObjectClass *object_class = G_OBJECT_CLASS (klass); 00107 00108 parent_class = g_type_class_peek_parent (klass); 00109 00110 object_class->finalize = gnc_tree_model_account_types_finalize; 00111 00112 g_type_class_add_private(klass, sizeof(GncTreeModelAccountTypesPrivate)); 00113 } 00114 00115 static void 00116 gnc_tree_model_account_types_init (GncTreeModelAccountTypes * model) 00117 { 00118 while (model->stamp == 0) 00119 { 00120 model->stamp = g_random_int (); 00121 } 00122 } 00123 00124 static void 00125 gnc_tree_model_account_types_finalize (GObject * object) 00126 { 00127 GncTreeModelAccountTypes *model; 00128 GncTreeModelAccountTypesPrivate *priv; 00129 00130 g_return_if_fail (object != NULL); 00131 g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (object)); 00132 00133 model = GNC_TREE_MODEL_ACCOUNT_TYPES (object); 00134 priv = GNC_TREE_MODEL_ACCOUNT_TYPES_GET_PRIVATE (model); 00135 00136 G_OBJECT_CLASS (parent_class)->finalize (object); 00137 } 00138 00139 GtkTreeModel * 00140 gnc_tree_model_account_types_new (guint32 selected) 00141 { 00142 GncTreeModelAccountTypes *model; 00143 GncTreeModelAccountTypesPrivate *priv; 00144 00145 model = g_object_new (GNC_TYPE_TREE_MODEL_ACCOUNT_TYPES, NULL); 00146 priv = GNC_TREE_MODEL_ACCOUNT_TYPES_GET_PRIVATE(model); 00147 priv->selected = selected; 00148 00149 return GTK_TREE_MODEL (model); 00150 } 00151 00152 static GtkTreeModel * 00153 gnc_tree_model_account_types_master(void) 00154 { 00155 if (!account_types_tree_model) 00156 account_types_tree_model = gnc_tree_model_account_types_new(0); 00157 return account_types_tree_model; 00158 } 00159 00160 00161 static gboolean 00162 gnc_tree_model_account_types_is_valid (GtkTreeModel *model, 00163 GtkTreeIter *iter, gpointer data) 00164 { 00165 GNCAccountType type; 00166 GObject *f_model = G_OBJECT (data); 00167 guint32 valid_types = GPOINTER_TO_UINT (g_object_get_data ( 00168 f_model, TYPE_MASK)); 00169 00170 gtk_tree_model_get (model, iter, 00171 GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE, &type, -1); 00172 return (valid_types & (1 << type)) ? TRUE : FALSE; 00173 } 00174 00175 GtkTreeModel * 00176 gnc_tree_model_account_types_filter_using_mask (guint32 types) 00177 { 00178 GtkTreeModel *f_model; 00179 00180 f_model = gtk_tree_model_filter_new (gnc_tree_model_account_types_master (), 00181 NULL); 00182 g_object_set_data (G_OBJECT (f_model), TYPE_MASK, GUINT_TO_POINTER (types)); 00183 gtk_tree_model_filter_set_visible_func ( 00184 GTK_TREE_MODEL_FILTER (f_model), gnc_tree_model_account_types_is_valid, 00185 f_model, NULL); 00186 00187 return f_model; 00188 } 00189 00190 void 00191 gnc_tree_model_account_types_set_mask (GtkTreeModel *f_model, 00192 guint32 types) 00193 { 00194 g_return_if_fail (f_model); 00195 00196 g_object_set_data (G_OBJECT (f_model), TYPE_MASK, GUINT_TO_POINTER (types)); 00197 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model)); 00198 } 00199 00200 guint32 00201 gnc_tree_model_account_types_get_mask (GtkTreeModel *f_model) 00202 { 00203 g_return_val_if_fail (f_model, 0); 00204 00205 return GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (f_model), TYPE_MASK)); 00206 } 00207 00208 guint32 00209 gnc_tree_model_account_types_get_selection (GtkTreeSelection *sel) 00210 { 00211 GtkTreeModel *f_model, *model; 00212 GtkTreePath *path; 00213 GtkTreeView *view; 00214 GList *list, *node; 00215 guint32 bits = 0; 00216 00217 g_return_val_if_fail(GTK_IS_TREE_SELECTION(sel), 0); 00218 view = gtk_tree_selection_get_tree_view(sel); 00219 g_return_val_if_fail (view, 0); 00220 00221 /* circumvent a bug in gtk+ not always filling f_model */ 00222 f_model = NULL; 00223 list = gtk_tree_selection_get_selected_rows(sel, &f_model); 00224 if (!f_model) 00225 f_model = gtk_tree_view_get_model(view); 00226 00227 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model)); 00228 if (model != account_types_tree_model) 00229 PERR("TreeSelection's TreeModel is not the account-types Model"); 00230 else 00231 { 00232 for (node = list; node; node = node->next) 00233 { 00234 path = gtk_tree_model_filter_convert_path_to_child_path( 00235 GTK_TREE_MODEL_FILTER(f_model), (GtkTreePath*)node->data); 00236 if (!path || gtk_tree_path_get_depth(path) != 1) 00237 { 00238 PERR("Invalid Account-types TreePath."); 00239 continue; 00240 } 00241 bits |= (1 << gtk_tree_path_get_indices(path)[0]); 00242 } 00243 } 00244 00245 g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL); 00246 g_list_free (list); 00247 00248 return bits; 00249 } 00250 00251 GNCAccountType 00252 gnc_tree_model_account_types_get_selection_single(GtkTreeSelection *sel) 00253 { 00254 gint i; 00255 guint32 selected = gnc_tree_model_account_types_get_selection(sel); 00256 00257 for (i = 0; i < NUM_ACCOUNT_TYPES; i++) 00258 if (selected & (1 << i)) 00259 return i; 00260 return ACCT_TYPE_NONE; 00261 } 00262 00263 void 00264 gnc_tree_model_account_types_set_selection (GtkTreeSelection *sel, 00265 guint32 selected) 00266 { 00267 GtkTreePath *path, *f_path; 00268 GtkTreeModelFilter *f_model; 00269 gint i; 00270 GtkTreeView *view; 00271 00272 g_return_if_fail(GTK_IS_TREE_SELECTION(sel)); 00273 view = gtk_tree_selection_get_tree_view(sel); 00274 g_return_if_fail (view); 00275 f_model = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(view)); 00276 g_return_if_fail(gtk_tree_model_filter_get_model(f_model) == 00277 account_types_tree_model); 00278 gtk_tree_selection_unselect_all(sel); 00279 path = gtk_tree_path_new_first(); 00280 00281 for (i = 0; i < NUM_ACCOUNT_TYPES; i++) 00282 { 00283 if (selected & (1 << i)) 00284 { 00285 f_path = gtk_tree_model_filter_convert_child_path_to_path( 00286 f_model, path); 00287 gtk_tree_selection_select_path(sel, f_path); 00288 gtk_tree_view_scroll_to_cell(view, f_path, NULL, FALSE, 0.0, 0.0); 00289 } 00290 gtk_tree_path_next(path); 00291 } 00292 gtk_tree_path_free(path); 00293 } 00294 00295 00296 /* Static functions implementing GtkTreeModel */ 00297 00298 static GtkTreeModelFlags 00299 gnc_tree_model_account_types_get_flags (GtkTreeModel * tree_model) 00300 { 00301 return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY; 00302 } 00303 00304 static int 00305 gnc_tree_model_account_types_get_n_columns (GtkTreeModel * tree_model) 00306 { 00307 return GNC_TREE_MODEL_ACCOUNT_TYPES_NUM_COLUMNS; 00308 } 00309 00310 static GType 00311 gnc_tree_model_account_types_get_column_type (GtkTreeModel * tree_model, 00312 int index) 00313 { 00314 g_return_val_if_fail(GNC_IS_TREE_MODEL_ACCOUNT_TYPES (tree_model), 00315 G_TYPE_INVALID); 00316 g_return_val_if_fail((index < GNC_TREE_MODEL_ACCOUNT_TYPES_NUM_COLUMNS) 00317 && (index >= 0), G_TYPE_INVALID); 00318 00319 switch (index) 00320 { 00321 case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE: 00322 return G_TYPE_INT; 00323 case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME: 00324 return G_TYPE_STRING; 00325 case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_SELECTED: 00326 return G_TYPE_BOOLEAN; 00327 default: 00328 g_assert_not_reached (); 00329 return G_TYPE_INVALID; 00330 } 00331 } 00332 00333 static gboolean 00334 gnc_tree_model_account_types_get_iter (GtkTreeModel * tree_model, 00335 GtkTreeIter * iter, GtkTreePath * path) 00336 { 00337 GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model); 00338 gint i; 00339 00340 g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model), FALSE); 00341 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE); 00342 00343 i = gtk_tree_path_get_indices (path)[0]; 00344 00345 if (i > ACCT_TYPE_NONE && i < NUM_ACCOUNT_TYPES) 00346 { 00347 iter->stamp = model->stamp; 00348 iter->user_data = GINT_TO_POINTER (i); 00349 return TRUE; 00350 } 00351 00352 iter->stamp = 0; 00353 return FALSE; 00354 } 00355 00356 static GtkTreePath * 00357 gnc_tree_model_account_types_get_path (GtkTreeModel * tree_model, 00358 GtkTreeIter * iter) 00359 { 00360 GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model); 00361 GtkTreePath *path; 00362 00363 g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model), NULL); 00364 g_return_val_if_fail (iter != NULL, NULL); 00365 g_return_val_if_fail (iter->stamp == model->stamp, NULL); 00366 00367 path = gtk_tree_path_new (); 00368 00369 gtk_tree_path_append_index (path, GPOINTER_TO_INT (iter->user_data)); 00370 00371 return path; 00372 } 00373 00374 static void 00375 gnc_tree_model_account_types_get_value (GtkTreeModel * tree_model, 00376 GtkTreeIter * iter, int column, 00377 GValue * value) 00378 { 00379 GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model); 00380 GncTreeModelAccountTypesPrivate *priv; 00381 00382 g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model)); 00383 g_return_if_fail (iter != NULL); 00384 g_return_if_fail (iter->stamp == model->stamp); 00385 00386 priv = GNC_TREE_MODEL_ACCOUNT_TYPES_GET_PRIVATE(model); 00387 switch (column) 00388 { 00389 case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_TYPE: 00390 g_value_init (value, G_TYPE_INT); 00391 g_value_set_int (value, GPOINTER_TO_INT (iter->user_data)); 00392 break; 00393 case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_NAME: 00394 g_value_init (value, G_TYPE_STRING); 00395 g_value_set_string (value, xaccAccountGetTypeStr ( 00396 GPOINTER_TO_INT (iter->user_data))); 00397 break; 00398 case GNC_TREE_MODEL_ACCOUNT_TYPES_COL_SELECTED: 00399 g_value_init (value, G_TYPE_BOOLEAN); 00400 g_value_set_boolean (value, priv->selected & 00401 (1 << GPOINTER_TO_INT (iter->user_data))); 00402 break; 00403 default: 00404 g_assert_not_reached (); 00405 } 00406 } 00407 00408 static gboolean 00409 gnc_tree_model_account_types_iter_next (GtkTreeModel * tree_model, 00410 GtkTreeIter * iter) 00411 { 00412 GncTreeModelAccountTypes *model = GNC_TREE_MODEL_ACCOUNT_TYPES(tree_model); 00413 00414 g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (model), FALSE); 00415 g_return_val_if_fail (iter != NULL, FALSE); 00416 g_return_val_if_fail (iter->stamp == model->stamp, FALSE); 00417 00418 if (GPOINTER_TO_INT (iter->user_data) < NUM_ACCOUNT_TYPES - 1) 00419 { 00420 iter->user_data = GINT_TO_POINTER( 00421 GPOINTER_TO_INT(iter->user_data) + 1); 00422 return TRUE; 00423 } 00424 00425 iter->stamp = 0; 00426 return FALSE; 00427 } 00428 00429 static gboolean 00430 gnc_tree_model_account_types_iter_children (GtkTreeModel * tree_model, 00431 GtkTreeIter * iter, 00432 GtkTreeIter * parent) 00433 { 00434 00435 g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES(tree_model), FALSE); 00436 00437 if (parent != NULL) 00438 return FALSE; 00439 00440 iter->stamp = GNC_TREE_MODEL_ACCOUNT_TYPES (tree_model)->stamp; 00441 iter->user_data = GINT_TO_POINTER (0); 00442 00443 return TRUE; 00444 } 00445 00446 static gboolean 00447 gnc_tree_model_account_types_iter_has_child (GtkTreeModel * tree_model, 00448 GtkTreeIter * iter) 00449 { 00450 return FALSE; 00451 } 00452 00453 static int 00454 gnc_tree_model_account_types_iter_n_children (GtkTreeModel * tree_model, 00455 GtkTreeIter * iter) 00456 { 00457 g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (tree_model), -1); 00458 00459 if (iter == NULL) 00460 return NUM_ACCOUNT_TYPES; 00461 00462 g_return_val_if_fail ( 00463 GNC_TREE_MODEL_ACCOUNT_TYPES (tree_model)->stamp == iter->stamp, -1); 00464 00465 return 0; 00466 } 00467 00468 static gboolean 00469 gnc_tree_model_account_types_iter_nth_child (GtkTreeModel * tree_model, 00470 GtkTreeIter * iter, 00471 GtkTreeIter * parent, int n) 00472 { 00473 GncTreeModelAccountTypes *model; 00474 00475 g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT_TYPES (tree_model), FALSE); 00476 00477 if (parent != NULL) 00478 return FALSE; 00479 00480 model = GNC_TREE_MODEL_ACCOUNT_TYPES (tree_model); 00481 00482 if (n > ACCT_TYPE_NONE && n < NUM_ACCOUNT_TYPES) 00483 { 00484 iter->stamp = model->stamp; 00485 iter->user_data = GINT_TO_POINTER (n); 00486 return TRUE; 00487 } 00488 00489 iter->stamp = 0; 00490 return FALSE; 00491 } 00492 00493 static gboolean 00494 gnc_tree_model_account_types_iter_parent (GtkTreeModel * tree_model, 00495 GtkTreeIter * iter, 00496 GtkTreeIter * child) 00497 { 00498 return FALSE; 00499 } 00500 00501 static void 00502 gnc_tree_model_account_types_tree_model_init (GtkTreeModelIface * iface) 00503 { 00504 iface->get_flags = gnc_tree_model_account_types_get_flags; 00505 iface->get_n_columns = gnc_tree_model_account_types_get_n_columns; 00506 iface->get_column_type = gnc_tree_model_account_types_get_column_type; 00507 iface->get_iter = gnc_tree_model_account_types_get_iter; 00508 iface->get_path = gnc_tree_model_account_types_get_path; 00509 iface->get_value = gnc_tree_model_account_types_get_value; 00510 iface->iter_next = gnc_tree_model_account_types_iter_next; 00511 iface->iter_children = gnc_tree_model_account_types_iter_children; 00512 iface->iter_has_child = gnc_tree_model_account_types_iter_has_child; 00513 iface->iter_n_children = gnc_tree_model_account_types_iter_n_children; 00514 iface->iter_nth_child = gnc_tree_model_account_types_iter_nth_child; 00515 iface->iter_parent = gnc_tree_model_account_types_iter_parent; 00516 } 00517
1.7.4