00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "account-quickfill.h"
00026 #include "gnc-gconf-utils.h"
00027 #include "gnc-engine.h"
00028 #include "gnc-ui-util.h"
00029
00030
00031 static QofLogModule log_module = GNC_MOD_REGISTER;
00032
00033 static void shared_quickfill_gconf_changed (GConfEntry *entry, gpointer qfb);
00034 static void listen_for_account_events (QofInstance *entity, QofEventId event_type,
00035 gpointer user_data, gpointer event_data);
00036
00037
00038 #define ACCOUNT_NAME 0
00039 #define ACCOUNT_POINTER 1
00040 #define NUM_ACCOUNT_COLUMNS 2
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 typedef struct
00053 {
00054 QuickFill *qf;
00055 gboolean load_list_store;
00056 GtkListStore *list_store;
00057 QofBook *book;
00058 Account *root;
00059 gint listener;
00060 AccountBoolCB dont_add_cb;
00061 gpointer dont_add_data;
00062 } QFB;
00063
00064 static void
00065 shared_quickfill_destroy (QofBook *book, gpointer key, gpointer user_data)
00066 {
00067 QFB *qfb = user_data;
00068 gnc_gconf_general_remove_cb(KEY_ACCOUNT_SEPARATOR,
00069 shared_quickfill_gconf_changed,
00070 qfb);
00071 gnc_gconf_general_remove_cb(KEY_SHOW_LEAF_ACCOUNT_NAMES,
00072 shared_quickfill_gconf_changed,
00073 qfb);
00074 gnc_quickfill_destroy (qfb->qf);
00075 g_object_unref(qfb->list_store);
00076 qof_event_unregister_handler (qfb->listener);
00077 g_free (qfb);
00078 }
00079
00080
00081 typedef struct find_data
00082 {
00083 GList *accounts;
00084 GList *refs;
00085 } find_data;
00086
00087 static gboolean
00088 shared_quickfill_find_accounts (GtkTreeModel *model,
00089 GtkTreePath *path,
00090 GtkTreeIter *iter,
00091 gpointer user_data)
00092 {
00093 Account *account = NULL;
00094 find_data *data = user_data;
00095 GtkTreeRowReference* ref;
00096 GList *tmp;
00097
00098 gtk_tree_model_get(model, iter, ACCOUNT_POINTER, &account, -1);
00099 for (tmp = data->accounts; tmp; tmp = g_list_next(tmp))
00100 {
00101 if (tmp->data == account)
00102 {
00103 ref = gtk_tree_row_reference_new(model, path);
00104 data->refs = g_list_append(data->refs, ref);
00105 data->accounts = g_list_remove_link(data->accounts, tmp);
00106 return (data->accounts == NULL);
00107 }
00108 }
00109
00110 return FALSE;
00111 }
00112
00113
00114
00115 static void
00116 load_shared_qf_cb (Account *account, gpointer data)
00117 {
00118 QFB *qfb = data;
00119 char *name;
00120 GtkTreeIter iter;
00121
00122 if (qfb->dont_add_cb)
00123 {
00124 gboolean skip = (qfb->dont_add_cb) (account, qfb->dont_add_data);
00125 if (skip) return;
00126 }
00127
00128 name = gnc_get_account_name_for_register (account);
00129 if (NULL == name) return;
00130 gnc_quickfill_insert (qfb->qf, name, QUICKFILL_ALPHA);
00131 if (qfb->load_list_store)
00132 {
00133 gtk_list_store_append (qfb->list_store, &iter);
00134 gtk_list_store_set (qfb->list_store, &iter,
00135 ACCOUNT_NAME, name,
00136 ACCOUNT_POINTER, account,
00137 -1);
00138 }
00139 g_free(name);
00140 }
00141
00142 static void
00143 shared_quickfill_gconf_changed (GConfEntry *entry, gpointer user_data)
00144 {
00145 QFB *qfb = user_data;
00146
00147
00148 gnc_quickfill_purge(qfb->qf);
00149 gtk_list_store_clear(qfb->list_store);
00150 qfb->load_list_store = TRUE;
00151 gnc_account_foreach_descendant(qfb->root, load_shared_qf_cb, qfb);
00152 qfb->load_list_store = FALSE;
00153 }
00154
00155
00156
00157
00158
00159 static QFB *
00160 build_shared_quickfill (QofBook *book, Account *root, const char * key,
00161 AccountBoolCB cb, gpointer data)
00162 {
00163 QFB *qfb;
00164
00165 qfb = g_new0(QFB, 1);
00166 qfb->qf = gnc_quickfill_new ();
00167 qfb->book = book;
00168 qfb->root = root;
00169 qfb->listener = 0;
00170 qfb->dont_add_cb = cb;
00171 qfb->dont_add_data = data;
00172 qfb->load_list_store = TRUE;
00173 qfb->list_store =
00174 gtk_list_store_new (NUM_ACCOUNT_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
00175
00176 gnc_gconf_general_register_cb(KEY_ACCOUNT_SEPARATOR,
00177 shared_quickfill_gconf_changed,
00178 qfb);
00179
00180 gnc_gconf_general_register_cb(KEY_SHOW_LEAF_ACCOUNT_NAMES,
00181 shared_quickfill_gconf_changed,
00182 qfb);
00183
00184 gnc_account_foreach_descendant(root, load_shared_qf_cb, qfb);
00185 qfb->load_list_store = FALSE;
00186
00187 qfb->listener =
00188 qof_event_register_handler (listen_for_account_events, qfb);
00189
00190 qof_book_set_data_fin (book, key, qfb, shared_quickfill_destroy);
00191
00192 return qfb;
00193 }
00194
00195 QuickFill *
00196 gnc_get_shared_account_name_quickfill (Account *root,
00197 const char * key,
00198 AccountBoolCB cb, gpointer cb_data)
00199 {
00200 QFB *qfb;
00201 QofBook *book;
00202
00203 book = gnc_account_get_book (root);
00204 qfb = qof_book_get_data (book, key);
00205
00206 if (qfb) return qfb->qf;
00207
00208 qfb = build_shared_quickfill (book, root, key, cb, cb_data);
00209 return qfb->qf;
00210 }
00211
00212 GtkListStore *
00213 gnc_get_shared_account_name_list_store (Account *root,
00214 const char * key,
00215 AccountBoolCB cb, gpointer cb_data)
00216 {
00217 QFB *qfb;
00218 QofBook *book;
00219
00220 book = gnc_account_get_book (root);
00221 qfb = qof_book_get_data (book, key);
00222
00223 if (qfb) return qfb->list_store;
00224
00225 qfb = build_shared_quickfill (book, root, key, cb, cb_data);
00226 return qfb->list_store;
00227 }
00228
00229
00230
00231
00232
00233 static void
00234 listen_for_account_events (QofInstance *entity, QofEventId event_type,
00235 gpointer user_data, gpointer event_data)
00236 {
00237 QFB *qfb = user_data;
00238 QuickFill *qf = qfb->qf;
00239 QuickFill *match;
00240 char * name;
00241 const char *match_str;
00242 Account *account;
00243 GtkTreeIter iter;
00244 find_data data = { 0 };
00245 GtkTreePath *path;
00246 GList *tmp;
00247
00248 if (0 == (event_type & (QOF_EVENT_MODIFY | QOF_EVENT_ADD | QOF_EVENT_REMOVE)))
00249 return;
00250
00251 if (!GNC_IS_ACCOUNT (entity))
00252 return;
00253 account = GNC_ACCOUNT (entity);
00254
00255 ENTER("entity %p, event type %x, user data %p, ecent data %p",
00256 entity, event_type, user_data, event_data);
00257
00258 if (gnc_account_get_root(account) != qfb->root)
00259 {
00260 LEAVE("root account mismatch");
00261 return;
00262 }
00263
00264 name = gnc_get_account_name_for_register(account);
00265 if (NULL == name)
00266 {
00267 LEAVE("account has no name");
00268 return;
00269 }
00270
00271 switch (event_type)
00272 {
00273 case QOF_EVENT_MODIFY:
00274 DEBUG("modify %s", name);
00275
00276
00277
00278 data.accounts = gnc_account_get_descendants(account);
00279 data.accounts = g_list_prepend(data.accounts, account);
00280 gtk_tree_model_foreach(GTK_TREE_MODEL(qfb->list_store),
00281 shared_quickfill_find_accounts, &data);
00282
00283
00284
00285
00286
00287 for (tmp = data.refs; tmp; tmp = g_list_next(tmp))
00288 {
00289 path = gtk_tree_row_reference_get_path(tmp->data);
00290 gtk_tree_row_reference_free(tmp->data);
00291 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(qfb->list_store),
00292 &iter, path))
00293 {
00294 gtk_tree_path_free(path);
00295 continue;
00296 }
00297 gtk_tree_path_free(path);
00298 gtk_tree_model_get(GTK_TREE_MODEL(qfb->list_store), &iter,
00299 ACCOUNT_POINTER, &account,
00300 -1);
00301 if (qfb->dont_add_cb &&
00302 qfb->dont_add_cb(account, qfb->dont_add_data))
00303 {
00304 gtk_list_store_remove(qfb->list_store, &iter);
00305 }
00306 else
00307 {
00308 gchar *aname = gnc_get_account_name_for_register(account);
00309 gtk_list_store_set(qfb->list_store, &iter,
00310 ACCOUNT_NAME, aname,
00311 -1);
00312 g_free(aname);
00313 }
00314 }
00315
00316
00317
00318
00319 for (tmp = data.accounts; tmp; tmp = g_list_next(tmp))
00320 {
00321 account = tmp->data;
00322 if (qfb->dont_add_cb)
00323 {
00324 if (qfb->dont_add_cb(account, qfb->dont_add_data))
00325 {
00326 continue;
00327 }
00328 }
00329 gtk_list_store_append (qfb->list_store, &iter);
00330 gtk_list_store_set (qfb->list_store, &iter,
00331 ACCOUNT_NAME, name,
00332 ACCOUNT_POINTER, account,
00333 -1);
00334 }
00335 break;
00336
00337 case QOF_EVENT_REMOVE:
00338 DEBUG("remove %s", name);
00339
00340
00341 gnc_quickfill_remove(qfb->qf, name, QUICKFILL_ALPHA);
00342
00343
00344 data.accounts = g_list_append(NULL, account);
00345 gtk_tree_model_foreach(GTK_TREE_MODEL(qfb->list_store),
00346 shared_quickfill_find_accounts, &data);
00347
00348
00349 for (tmp = data.refs; tmp; tmp = g_list_next(tmp))
00350 {
00351 path = gtk_tree_row_reference_get_path (tmp->data);
00352 gtk_tree_row_reference_free (tmp->data);
00353 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(qfb->list_store),
00354 &iter, path))
00355 {
00356 gtk_list_store_remove(qfb->list_store, &iter);
00357 }
00358 gtk_tree_path_free(path);
00359 }
00360 break;
00361
00362 case QOF_EVENT_ADD:
00363 DEBUG("add %s", name);
00364 if (qfb->dont_add_cb &&
00365 qfb->dont_add_cb(account, qfb->dont_add_data))
00366 break;
00367
00368 match = gnc_quickfill_get_string_match (qf, name);
00369 if (match)
00370 {
00371 match_str = gnc_quickfill_string (match);
00372 if (match_str && (safe_strcmp(match_str, name) != 0))
00373 {
00374 PINFO ("got match for %s", name);
00375 break;
00376 }
00377 }
00378
00379 PINFO ("insert new account %s into qf=%p", name, qf);
00380 gnc_quickfill_insert (qf, name, QUICKFILL_ALPHA);
00381 gtk_list_store_append (qfb->list_store, &iter);
00382 gtk_list_store_set (qfb->list_store, &iter,
00383 ACCOUNT_NAME, name,
00384 ACCOUNT_POINTER, account,
00385 -1);
00386 break;
00387
00388 default:
00389 DEBUG("other %s", name);
00390 break;
00391 }
00392
00393 if (data.accounts)
00394 g_list_free(data.accounts);
00395 if (data.refs)
00396 g_list_free(data.refs);
00397 g_free(name);
00398 LEAVE(" ");
00399 }
00400
00401