r14899 - gnucash/trunk - Ease account type changes in the account dialog after OK is clicked.

Andreas Köhler andi5 at cvs.gnucash.org
Tue Sep 26 18:09:08 EDT 2006


Author: andi5
Date: 2006-09-26 18:09:06 -0400 (Tue, 26 Sep 2006)
New Revision: 14899
Trac: http://svn.gnucash.org/trac/changeset/14899

Modified:
   gnucash/trunk/
   gnucash/trunk/src/gnome-utils/dialog-account.c
Log:
Ease account type changes in the account dialog after OK is clicked.
Before, we did not enforce compatibility with the parent account and
suggested to change only children or children and all parent accounts up
to the top-level one. We do enforce it now and only need to look at the
children.

The filling of the hash of (children) account (type) changes has been
replaced by showing the user a filtered account tree and the types are
adjusted recursively once the user verified the change.

This is another attempt to resolve #337189.



Property changes on: gnucash/trunk
___________________________________________________________________
Name: svk:merge
   - 3889ce50-311e-0410-a464-f059747ec5d1:/local/gnucash/trunk:646
d2ab10a8-8a95-4986-baff-8d511d9f15b2:/local/gnucash/trunk:13351
   + 3889ce50-311e-0410-a464-f059747ec5d1:/local/gnucash/trunk:647
d2ab10a8-8a95-4986-baff-8d511d9f15b2:/local/gnucash/trunk:13351

Modified: gnucash/trunk/src/gnome-utils/dialog-account.c
===================================================================
--- gnucash/trunk/src/gnome-utils/dialog-account.c	2006-09-26 22:08:52 UTC (rev 14898)
+++ gnucash/trunk/src/gnome-utils/dialog-account.c	2006-09-26 22:09:06 UTC (rev 14899)
@@ -136,7 +136,6 @@
 
 /** Declarations *********************************************************/
 static void gnc_account_window_set_name (AccountWindow *aw);
-static void make_account_changes(GHashTable *change_type);
 
 void gnc_account_renumber_prefix_changed_cb (GtkEditable *editable, RenumberDialog *data);
 void gnc_account_renumber_interval_changed_cb (GtkSpinButton *spinbutton, RenumberDialog *data);
@@ -319,6 +318,11 @@
     return;
   }
 
+  if (aw->type != xaccAccountGetType (account)) {
+    /* Just refreshing won't work. */
+    aw_call_destroy_callbacks (account);
+  }
+
   xaccAccountBeginEdit (account);
 
   if (aw->type != xaccAccountGetType (account))
@@ -436,15 +440,57 @@
 }
 
 
-static void 
-gnc_finish_ok (AccountWindow *aw,
-               GHashTable *change_type)
+static void
+set_children_types (Account *account, GNCAccountType type)
 {
-  ENTER("aw %p, hash table %p", aw, change_type);
+  AccountGroup *children;
+  GList *iter;
+
+  children = xaccAccountGetChildren (account);
+  if (children == NULL)
+    return;
+
+  for (iter=xaccGroupGetAccountList (children); iter; iter=iter->next) {
+    account = iter->data;
+    if (type == xaccAccountGetType(account))
+      continue;
+
+    /* Just refreshing won't work. */
+    aw_call_destroy_callbacks (account);
+
+    xaccAccountBeginEdit (account);
+    xaccAccountSetType (account, type);
+    xaccAccountCommitEdit (account);
+
+    set_children_types (account, type);
+  }
+}
+
+static void
+make_children_compatible (AccountWindow *aw)
+{
+  Account *account;
+
+  g_return_if_fail (aw);
+
+  account = aw_get_account (aw);
+  g_return_if_fail (account);
+
+  if (xaccAccountTypesCompatible (xaccAccountGetType (account), aw->type))
+    return;
+
+  set_children_types (account, aw->type);
+}
+
+
+static void
+gnc_finish_ok (AccountWindow *aw)
+{
+  ENTER("aw %p", aw);
   gnc_suspend_gui_refresh ();
 
   /* make the account changes */
-  make_account_changes (change_type);
+  make_children_compatible (aw);
   gnc_ui_to_account (aw);
 
   gnc_resume_gui_refresh ();
@@ -494,141 +540,43 @@
 }
 
 
-/* Record all of the children of the given account as needing their
- * type changed to the one specified. */
 static void
-gnc_edit_change_account_types(GHashTable *change_type, Account *account,
-                              Account *except, GNCAccountType type)
+add_children_to_expander (GObject *object, GParamSpec *param_spec, gpointer data)
 {
-  AccountGroup *children;
-  GList *list;
-  GList *node;
+  GtkExpander *expander = GTK_EXPANDER (object);
+  Account *account = data;
+  GtkWidget *scrolled_window;
+  GtkTreeView *view;
 
-  if ((change_type == NULL) || (account == NULL))
-    return;
+  if (gtk_expander_get_expanded (expander) &&
+      !gtk_bin_get_child (GTK_BIN (expander))) {
 
-  if (account == except)
-    return;
+    view = gnc_tree_view_account_new_with_group (
+      xaccAccountGetChildren (account), FALSE);
 
-  g_hash_table_insert(change_type, account, GINT_TO_POINTER(type));
+    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                         GTK_SHADOW_IN);
+    gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (view));
 
-  children = xaccAccountGetChildren(account);
-  if (children == NULL)
-    return;
-
-  list = xaccGroupGetAccountList (children);
-
-  for (node= list; node; node = node->next)
-  {
-    account = node->data;
-    gnc_edit_change_account_types(change_type, account, except, type);
+    gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
+    gtk_widget_show_all (scrolled_window);
   }
 }
 
-
-/* helper function to perform changes to accounts */
-static void
-change_func (gpointer key, gpointer value, gpointer unused)
-{
-  Account *account = key;
-  int type;
- 
-  if (account == NULL)
-    return;
-
-  xaccAccountBeginEdit(account);
-
-  type = GPOINTER_TO_INT(value);
-
-  if (type == xaccAccountGetType(account))
-    return;
-
-  /* Just refreshing won't work. */
-  aw_call_destroy_callbacks (account);
-
-  xaccAccountSetType(account, type);
-
-  xaccAccountCommitEdit(account);
-}
-
-
-/* Perform the changes to accounts dictated by the hash tables */
-static void
-make_account_changes(GHashTable *change_type)
-{
-  if (change_type != NULL)
-    g_hash_table_foreach(change_type, change_func, NULL);
-}
-
-
-typedef struct
-{
-  Account *account;
-  GtkListStore *list;
-  guint count;
-} FillStruct;
-
-static void
-fill_helper(gpointer key, gpointer value, gpointer data)
-{
-  Account *account = key;
-  FillStruct *fs = data;
-  gchar *full_name;
-  const gchar *account_field_name;
-  const gchar *account_field_value;
-  const gchar *value_str;
-  GtkTreeIter iter;
-
-  if (fs == NULL) return;
-  if (fs->account == account) return;
-
-  full_name = xaccAccountGetFullName(account);
-  account_field_name = _("Type");
-  account_field_value = xaccAccountGetTypeStr(xaccAccountGetType(account));
-  value_str = xaccAccountGetTypeStr(GPOINTER_TO_INT(value));
-
-  gtk_list_store_append(fs->list, &iter);
-  gtk_list_store_set(fs->list, &iter,
-		     ACCOUNT_COL_FULLNAME,  full_name,
-		     ACCOUNT_COL_FIELDNAME, account_field_name,
-		     ACCOUNT_COL_OLD_VALUE, account_field_value,
-		     ACCOUNT_COL_NEW_VALUE, value_str,
-		     -1);
-  g_free(full_name);
-  fs->count++;
-}
-
-static guint
-fill_list(Account *account, GtkListStore *list,
-          GHashTable *change)
-{
-  FillStruct fs;
-
-  if (change == NULL)
-    return 0;
-
-  fs.account = account;
-  fs.list = list;
-  fs.count = 0;
-
-  g_hash_table_foreach(change, fill_helper, &fs);
-
-  return fs.count;
-}
-
-
-/* Present a dialog of proposed account changes for the user's ok */
+/* Check whether there are children needing a type adjustment because of a
+   a change to an incompatible type (like after some reparenting) and let the
+   user decide whether he wants that */
 static gboolean
-extra_change_verify (AccountWindow *aw,
-                     GHashTable *change_type)
+verify_children_compatible (AccountWindow *aw)
 {
   Account *account;
-  GtkCellRenderer *renderer;
-  GtkTreeViewColumn *column;
-  GtkTreeView *view;
-  GtkListStore *store;
+  AccountGroup *children;
+  GtkWidget *dialog, *vbox, *hbox, *label, *expander;
+  gchar *str;
   gboolean result;
-  guint size;
 
   if (aw == NULL)
     return FALSE;
@@ -637,89 +585,88 @@
   if (!account)
     return FALSE;
 
-  store = gtk_list_store_new(NUM_ACCOUNT_COLS, G_TYPE_STRING, G_TYPE_STRING,
-			     G_TYPE_STRING, G_TYPE_STRING);
+  if (xaccAccountTypesCompatible (xaccAccountGetType (account), aw->type))
+    return TRUE;
 
-  size = 0;
-  size += fill_list(account, GTK_LIST_STORE(store), change_type);
-
-  if (size == 0)
-  {
-    g_object_unref(store);
+  children = xaccAccountGetChildren (account);
+  if (!children ||
+      !xaccGroupGetNumAccounts (children))
     return TRUE;
-  }
 
-  gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store),
-				       ACCOUNT_COL_FULLNAME,
-				       GTK_SORT_ASCENDING);
+  dialog = gtk_dialog_new_with_buttons ("",
+                                        GTK_WINDOW(aw->dialog),
+                                        GTK_DIALOG_DESTROY_WITH_PARENT |
+                                        GTK_DIALOG_MODAL,
+                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                        GTK_STOCK_OK, GTK_RESPONSE_OK,
+                                        NULL);
 
-  view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)));
-  g_object_unref(store);
-  renderer = gtk_cell_renderer_text_new();
-  column = gtk_tree_view_column_new_with_attributes(_("Account"), renderer,
-						    "text", ACCOUNT_COL_FULLNAME,
-						    NULL);
-  gtk_tree_view_append_column(view, column);
+  gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
 
-  renderer = gtk_cell_renderer_text_new();
-  column = gtk_tree_view_column_new_with_attributes(_("Field"), renderer,
-						    "text", ACCOUNT_COL_FIELDNAME,
-						    NULL);
-  gtk_tree_view_append_column(view, column);
+  hbox = gtk_hbox_new (FALSE, 12);
+  vbox = gtk_vbox_new (FALSE, 12);
 
-  renderer = gtk_cell_renderer_text_new();
-  column = gtk_tree_view_column_new_with_attributes(_("Old Value"), renderer,
-						    "text", ACCOUNT_COL_OLD_VALUE,
-						    NULL);
-  gtk_tree_view_append_column(view, column);
+  gtk_box_pack_start (
+    GTK_BOX (hbox),
+    gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG),
+    FALSE, FALSE, 0);
 
-  renderer = gtk_cell_renderer_text_new();
-  column = gtk_tree_view_column_new_with_attributes(_("New Value"), renderer,
-						    "text", ACCOUNT_COL_NEW_VALUE,
-						    NULL);
-  gtk_tree_view_append_column(view, column);
-
+  /* primary label */
+  label = gtk_label_new (_("Give the children the same type?"));
+  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+  gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
   {
-    GtkWidget *dialog;
-    GtkWidget *scroll;
-    GtkWidget *label;
-    GtkWidget *frame;
-    GtkWidget *vbox;
+    gint size;
+    PangoFontDescription *font_desc;
 
-    dialog = gtk_dialog_new_with_buttons (_("Verify Changes"),
-		    			  GTK_WINDOW(aw->dialog),
-					  GTK_DIALOG_DESTROY_WITH_PARENT |
-					  GTK_DIALOG_MODAL,
-					  GTK_STOCK_OK, GTK_RESPONSE_OK,
-					  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-					  NULL);
+    size = pango_font_description_get_size (label->style->font_desc);
+    font_desc = pango_font_description_new ();
+    pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD);
+    pango_font_description_set_size (font_desc, size * PANGO_SCALE_LARGE);
+    gtk_widget_modify_font (label, font_desc);
+    pango_font_description_free (font_desc);
+  }
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
-    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-    gtk_window_set_default_size (GTK_WINDOW (dialog), 0, 300);
+  /* secondary label */
+  str = g_strdup_printf (_("The children of the edited account have to be "
+                           "changed to type \"%s\" to make them compatible."),
+                         xaccAccountGetTypeStr (aw->type));
+  label = gtk_label_new (str);
+  g_free (str);
+  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+  gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
-    vbox = GTK_DIALOG (dialog)->vbox;
+  /* children */
+  expander = gtk_expander_new_with_mnemonic (_("_Show children accounts"));
+  gtk_expander_set_spacing (GTK_EXPANDER (expander), 6);
+  g_signal_connect (G_OBJECT (expander), "notify::expanded",
+                    G_CALLBACK (add_children_to_expander), account);
+  gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
 
-    label = gtk_label_new(_("The following changes must be made. Continue?"));
-    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
 
-    frame = gtk_frame_new(NULL);
-    gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
+                      TRUE, TRUE, 0);
 
-    scroll = gtk_scrolled_window_new(NULL, NULL);
-    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
-                                   GTK_POLICY_NEVER, 
-                                   GTK_POLICY_AUTOMATIC);
+  /* spacings */
+  gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14);
+  gtk_container_set_border_width (
+    GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 5);
+  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
 
-    gtk_container_add(GTK_CONTAINER(frame), scroll);
-    gtk_container_set_border_width(GTK_CONTAINER(scroll), 5);
-    gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(view));
+  gtk_widget_show_all (hbox);
 
-    gtk_widget_show_all(vbox);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
 
-    result = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK);
+  result = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK);
 
-    gtk_widget_destroy(dialog);
-  }
+  gtk_widget_destroy(dialog);
 
   return result;
 }
@@ -811,6 +758,15 @@
     return FALSE;
   }
 
+  /* check whether the types of child and parent are compatible */
+  if (!xaccAccountTypesCompatible (aw->type, xaccAccountGetType (parent))) {
+    const char *message = _("The selected account type is incompatible with "
+                            "the one of the selected parent.");
+    gnc_error_dialog(aw->dialog, message);
+    LEAVE("incompatible types");
+    return FALSE;
+  }
+
   /* check for commodity */
   commodity = (gnc_commodity *)
     gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
@@ -828,18 +784,8 @@
 static void
 gnc_edit_account_ok(AccountWindow *aw)
 {
-  GHashTable *change_type;
-
-  gboolean change_children;
-  gboolean has_children;
-  gboolean change_all;
-
-  Account *new_parent;
   Account *account;
-  AccountGroup *children;
 
-  GNCAccountType current_type;
-
   ENTER("aw %p", aw);
 
   account = aw_get_account (aw);
@@ -853,73 +799,12 @@
     return;
   }
 
-  change_type = g_hash_table_new (NULL, NULL);
-
-  children = xaccAccountGetChildren(account);
-  if (children == NULL)
-    has_children = FALSE;
-  else if (xaccGroupGetNumAccounts(children) == 0)
-    has_children = FALSE;
-  else
-    has_children = TRUE;
-
-  current_type = xaccAccountGetType(account);
-
-  /* If the account has children and the new type isn't compatible
-   * with the old type, the children's types must be changed. */
-  change_children = (has_children &&
-                     !xaccAccountTypesCompatible(current_type, aw->type));
-
-  /* If the new parent's type is not compatible with the new type,
-   * the whole sub-tree containing the account must be re-typed. */
-  new_parent = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree));
-  if (new_parent != aw->top_level_account)
-  {
-    int parent_type;
-
-    parent_type = xaccAccountGetType(new_parent);
-
-    if (!xaccAccountTypesCompatible(parent_type, aw->type))
-      change_all = TRUE;
-    else
-      change_all = FALSE;
-  }
-  else
-    change_all = FALSE;
-
-  if (change_children)
-    gnc_edit_change_account_types(change_type, account, NULL, aw->type);
-
-  if (change_all)
-  {
-    Account *ancestor;
-    Account *temp;
-
-    temp = new_parent;
-
-    do
-    {
-      ancestor = temp;
-      temp = xaccAccountGetParentAccount(ancestor);
-    } while (temp != NULL);
-
-    gnc_edit_change_account_types(change_type, ancestor, account, aw->type);
-  }
-
-  if (!extra_change_verify(aw, change_type))
-  {
-    g_hash_table_destroy(change_type);
+  if (!verify_children_compatible (aw)) {
     LEAVE(" ");
     return;
   }
 
-  if (current_type != aw->type)
-    /* Just refreshing won't work. */
-    aw_call_destroy_callbacks (account);
-
-  gnc_finish_ok (aw, change_type);
-
-  g_hash_table_destroy (change_type);
+  gnc_finish_ok (aw);
   LEAVE(" ");
 }
 
@@ -971,7 +856,7 @@
     }
   }
 
-  gnc_finish_ok (aw, NULL);
+  gnc_finish_ok (aw);
   LEAVE(" ");
 }
 



More information about the gnucash-changes mailing list