gnucash master: Multiple changes pushed

Mike Alexander mta at code.gnucash.org
Wed Nov 11 22:54:48 EST 2015


Updated	 via  https://github.com/Gnucash/gnucash/commit/fc32f664 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/0637f65f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/7c744d64 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/ed776a73 (commit)
	from  https://github.com/Gnucash/gnucash/commit/601abdf4 (commit)



commit fc32f6640445e71516c0492b535408eddbaab623
Author: Mike Alexander <mta at umich.edu>
Date:   Wed Nov 11 22:19:19 2015 -0500

    Make indirect_balance_conversion work (and faster)
    
    extract_common_prices was only looking at the first price on the "to" list
    and there's no point in getting a to list if the from list is empty.

diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index 61375a6..88eef3d 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -2251,7 +2251,7 @@ extract_common_prices (PriceList *from_prices, PriceList *to_prices)
          from_node = g_list_next(from_node))
     {
         for (to_node = to_prices; to_node != NULL;
-             to_node = g_list_next(to_price))
+             to_node = g_list_next(to_node))
         {
             gnc_commodity *to_com, *to_cur;
             gnc_commodity *from_com, *from_cur;
@@ -2324,13 +2324,17 @@ indirect_balance_conversion (GNCPriceDB *db, gnc_numeric bal,
     if (t == NULL)
     {
         from_prices = gnc_pricedb_lookup_latest_any_currency(db, from);
-        to_prices = gnc_pricedb_lookup_latest_any_currency(db, to);
+        /* "to" is often the book currency which may have lots of prices,
+            so avoid getting them if they aren't needed. */
+        if (from_prices)
+            to_prices = gnc_pricedb_lookup_latest_any_currency(db, to);
     }
     else
     {
         from_prices = gnc_pricedb_lookup_nearest_in_time_any_currency(db,
                                                                       from, *t);
-        to_prices = gnc_pricedb_lookup_nearest_in_time_any_currency(db,
+        if (from_prices)
+            to_prices = gnc_pricedb_lookup_nearest_in_time_any_currency(db,
                                                                     to, *t);
     }
     if (from_prices == NULL || to_prices == NULL)

commit 0637f65fa36948dfa12a712f9f3198b9ee947e8b
Author: Mike Alexander <mta at umich.edu>
Date:   Wed Nov 11 21:41:17 2015 -0500

    Add debugging function price_list_dump.

diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index e94e901..61375a6 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -2830,6 +2830,11 @@ price_foreach(const QofCollection *col, QofInstanceForeachCB cb, gpointer data)
 
 /* ==================================================================== */
 
+#ifdef DUMP_FUNCTIONS
+/* For debugging only, don't delete this */
+static void price_list_dump(GList *price_list, const char *tag);
+#endif
+
 static const char *
 price_printable(gpointer obj)
 {
@@ -2841,6 +2846,13 @@ price_printable(gpointer obj)
 
     if (!pr) return "";
 
+#ifdef DUMP_FUNCTIONS
+    /* Reference it so the compiler doesn't optimize it out. bit
+       don't actually call it. */
+    if (obj == buff)
+        price_list_dump(NULL, "");
+#endif
+
     val = gnc_numeric_to_string (pr->value);
     da = qof_print_date (pr->tmspec.tv_sec);
 
@@ -2856,6 +2868,21 @@ price_printable(gpointer obj)
     return buff;
 }
 
+#ifdef DUMP_FUNCTIONS
+/* For debugging only, don't delete this */
+static void
+price_list_dump(GList *price_list, const char *tag)
+{
+    GNCPrice *price;
+    GList *node;
+    printf("Price list %s\n", tag);
+    for (node = price_list; node != NULL; node = node->next)
+    {
+        printf("%s\n", price_printable(node->data));
+    }
+}
+#endif
+
 #ifdef _MSC_VER
 /* MSVC compiler doesn't have C99 "designated initializers"
  * so we wrap them in a macro that is empty on MSVC. */

commit 7c744d644b0190bcd04e8facef95744519d9de0d
Author: Mike Alexander <mta at umich.edu>
Date:   Wed Nov 11 01:46:39 2015 -0500

    Fix the "lookuo ... any_currency" functions to work right.
    
    They were broken in 3a0ec89c due to a lack of understanding about how
    gnc_pricedb_foreach_price works.

diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index bba4f28..e94e901 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -37,6 +37,10 @@ static gboolean remove_price(GNCPriceDB *db, GNCPrice *p, gboolean cleanup);
 static GNCPrice *lookup_nearest_in_time(GNCPriceDB *db, const gnc_commodity *c,
                                         const gnc_commodity *currency,
                                         Timespec t, gboolean sameday);
+static gboolean
+pricedb_pricelist_traversal(GNCPriceDB *db,
+                            gboolean (*f)(GList *p, gpointer user_data),
+                            gpointer user_data);
 
 enum
 {
@@ -1567,117 +1571,70 @@ typedef struct
 {
     GList **list;
     const gnc_commodity *com;
-    GNCPrice *previous_price;
-    gboolean have_good_price;
     Timespec t;
-    gboolean before;
 } UsesCommodity;
 
 /* price_list_scan_any_currency is the helper function used with
- * gnc_pricedb_foreach_price by the "any_currency" price lookup functions. It 
+ * pricedb_pricelist_traversal by the "any_currency" price lookup functions. It 
  * builds a list of prices that are either to or from the commodity "com".  
- * The resulting list will include all prices newer than "t" and the first 
- * price older than "t".  All older prices will be ignored.  Since in the most 
+ * The resulting list will include the last price newer than "t" and the first 
+ * price older than "t".  All other prices will be ignored.  Since in the most 
  * common cases we will be looking for recent prices which are at the front of 
  * the various price lists, this is considerably faster than concatenating all 
  * the relevant price lists and sorting the result.  
 */
  
 static gboolean
-price_list_scan_any_currency(GNCPrice *price, gpointer data)
+price_list_scan_any_currency(GList *price_list, gpointer data)
 {
     UsesCommodity *helper = (UsesCommodity*)data;
-    gnc_commodity *com = gnc_price_get_commodity(price);
-    gnc_commodity *cur = gnc_price_get_currency(price);
-    Timespec time = gnc_price_get_time(price);
-    gnc_commodity *previous_com = NULL;
-    gnc_commodity *previous_cur = NULL;
-    Timespec previous_time;
-    gboolean same_price_list = FALSE;
-    
-    if (helper->previous_price)
-    {
-        previous_com = gnc_price_get_commodity(helper->previous_price);
-        previous_cur = gnc_price_get_currency(helper->previous_price);
-        previous_time = gnc_price_get_time(helper->previous_price);
-        if (previous_com == com && previous_cur == cur)
-            same_price_list = TRUE;
-    }
-    if (helper->have_good_price && same_price_list)
-    {
-        helper->previous_price = price;
-        /* Tell scanner to skip rest of price list */
-        return FALSE;
-    }
+    GList *node = price_list;
+    gnc_commodity *com;
+    gnc_commodity *cur;
     
-    /* If we're changing commodity or currency finish up the previous one
-       before starting the new one */
-    if (!same_price_list && !helper->have_good_price && helper->previous_price && 
-        (previous_com == helper->com || previous_cur == helper->com))
-    {
-        /* Use the last price from the previous group of prices */
-        if (! (helper->before && 
-               timespec_cmp(&previous_time, &helper->t) > 0))
-        {
-            gnc_price_ref(helper->previous_price);
-            *helper->list = g_list_prepend(*helper->list, helper->previous_price);
-        }
-    }
+    if (!price_list)
+        return TRUE;
+
+    com = gnc_price_get_commodity(node->data);
+    cur = gnc_price_get_currency(node->data);
     
-    if (!same_price_list)
-        helper->have_good_price = FALSE;
+    /* if this price list isn't for the commodity we are interested in,
+       ignore it. */
+    if (com != helper->com && cur != helper->com)
+        return TRUE;
     
-    if (helper->com == com || helper->com == cur)
+    /* The price list is sorted in decreasing order of time.  Find the first
+       price on it that is older than the requested time and add it and the
+       previous price to the result list. */
+    while (node != NULL)
     {
-        if (timespec_cmp(&time, &helper->t) < 0)
+        GNCPrice *price = node->data;
+        Timespec price_t = gnc_price_get_time(price);
+        if (timespec_cmp(&price_t, &helper->t) < 0)
         {
-            /* This price is before given time */
-            if (helper->before)
+            /* If there is a previous price add it to the results. */
+            if (node->prev)
             {
-                /* We want the first price before the given time */
-                gnc_price_ref(price);
-                *helper->list = g_list_prepend(*helper->list, price);
-            }
-            else
-            {
-                /* Previous price (if any) is after and this price is before,
-                   use the closest one */
-                if (same_price_list)
-                {
-                    Timespec diff_prev = timespec_diff(&previous_time, &helper->t);
-                    Timespec diff_next = timespec_diff(&time, &helper->t);
-                    diff_prev = timespec_abs(&diff_prev);
-                    diff_next = timespec_abs(&diff_next);
-                    if (timespec_cmp(&diff_prev, &diff_next) < 0)
-                    {
-                        gnc_price_ref(helper->previous_price);
-                        *helper->list = g_list_prepend(*helper->list, helper->previous_price);
-                    }
-                    else
-                    {
-                        gnc_price_ref(price);
-                        *helper->list = g_list_prepend(*helper->list, price);
-                    }
-                }
-                else
-                {
-                    /* First price for this commodity/currency is before the
-                       given time, it's the closest */
-                    gnc_price_ref(price);
-                    *helper->list = g_list_prepend(*helper->list, price);
-                }
+                GNCPrice *prev_price = node->prev->data;
+                gnc_price_ref(prev_price);
+                *helper->list = g_list_prepend(*helper->list, prev_price);
             }
-            helper->have_good_price = TRUE;
+            /* Add the first price before the desired time */
+            gnc_price_ref(price);
+            *helper->list = g_list_prepend(*helper->list, price);
+            /* No point in looking further, they will all be older */
+            break;
         }
+        else if (node->next == NULL)
+        {
+            /* The last price is later than given time, add it */
+            gnc_price_ref(price);
+            *helper->list = g_list_prepend(*helper->list, price);
+        }
+        node = node->next;
     }
-    else
-    {
-        /* Don't care about this commodity/currency, skip it */
-        helper->have_good_price = TRUE;
-    }
-    helper->previous_price = price;
-    /* Done with this price list if we have a good price from it. */
-    return !helper->have_good_price;
+
+    return TRUE;
 }
 
 static gboolean
@@ -1714,7 +1671,7 @@ latest_before (PriceList *prices, const gnc_commodity* target, Timespec t)
             found_coms = g_list_prepend(found_coms, com == target ? cur : com);
         }
     }
-    return retval;
+    return g_list_reverse(retval);
 }
 
 static GNCPrice**
@@ -1747,6 +1704,13 @@ add_nearest_price(GList *target_list, GPtrArray *price_array, GNCPrice *price,
             com_price = (GNCPrice**)g_slice_new(gpointer);
             *com_price = price;
             g_ptr_array_add(price_array, com_price);
+            /* If the first price we see for this commodity is not newer than
+               the target date add it to the return list. */
+            if (timespec_cmp(&price_t, &t) <= 0)
+            {
+                gnc_price_ref(price);
+                target_list = g_list_prepend(target_list, price);
+            }
             return target_list;
         }
         com_t = gnc_price_get_time(*com_price);
@@ -1810,7 +1774,7 @@ nearest_to (PriceList *prices, const gnc_commodity* target, Timespec t)
         }
     }
     g_ptr_array_free(price_array, TRUE);
-    return retval;
+    return g_list_sort(retval, compare_prices_by_date);
 }
 
 
@@ -1819,20 +1783,7 @@ PriceList *
 gnc_pricedb_lookup_latest_any_currency(GNCPriceDB *db,
                                        const gnc_commodity *commodity)
 {
-    GList *prices = NULL, *result;
-    UsesCommodity helper = {&prices, commodity, NULL, FALSE, timespec_now(), TRUE};
-    result = NULL;
-
-    if (!db || !commodity) return NULL;
-    ENTER ("db=%p commodity=%p", db, commodity);
-
-    gnc_pricedb_foreach_price(db, price_list_scan_any_currency,
-                                       &helper, FALSE);
-    prices = g_list_sort(prices, compare_prices_by_date);
-    result = latest_before(prices, commodity, timespec_now());
-    gnc_price_list_destroy(prices);
-    LEAVE(" ");
-    return result;
+    return gnc_pricedb_lookup_latest_before_any_currency(db, commodity, timespec_now());
 }
 
 PriceList *
@@ -1841,14 +1792,14 @@ gnc_pricedb_lookup_nearest_in_time_any_currency(GNCPriceDB *db,
                                                 Timespec t)
 {
     GList *prices = NULL, *result;
-    UsesCommodity helper = {&prices, commodity, NULL, FALSE, t, FALSE};
+    UsesCommodity helper = {&prices, commodity, t};
     result = NULL;
 
     if (!db || !commodity) return NULL;
     ENTER ("db=%p commodity=%p", db, commodity);
 
-    gnc_pricedb_foreach_price(db, price_list_scan_any_currency,
-                                       &helper, FALSE);
+    pricedb_pricelist_traversal(db, price_list_scan_any_currency,
+                                       &helper);
     prices = g_list_sort(prices, compare_prices_by_date);
     result = nearest_to(prices, commodity, t);
     gnc_price_list_destroy(prices);
@@ -1862,14 +1813,14 @@ gnc_pricedb_lookup_latest_before_any_currency(GNCPriceDB *db,
                                               Timespec t)
 {
     GList *prices = NULL, *result;
-    UsesCommodity helper = {&prices, commodity, NULL, FALSE, t, TRUE};
+    UsesCommodity helper = {&prices, commodity, t};
     result = NULL;
 
     if (!db || !commodity) return NULL;
     ENTER ("db=%p commodity=%p", db, commodity);
 
-    gnc_pricedb_foreach_price(db, price_list_scan_any_currency,
-                                       &helper, FALSE);
+    pricedb_pricelist_traversal(db, price_list_scan_any_currency,
+                                       &helper);
     prices = g_list_sort(prices, compare_prices_by_date);
     result = latest_before(prices, commodity, t);
     gnc_price_list_destroy(prices);
@@ -2506,6 +2457,54 @@ unstable_price_traversal(GNCPriceDB *db,
     return foreach_data.ok;
 }
 
+/* foreach_pricelist */
+typedef struct
+{
+    gboolean ok;
+    gboolean (*func)(GList *p, gpointer user_data);
+    gpointer user_data;
+} GNCPriceListForeachData;
+
+static void
+pricedb_pricelist_foreach_pricelist(gpointer key, gpointer val, gpointer user_data)
+{
+    GList *price_list = (GList *) val;
+    GNCPriceListForeachData *foreach_data = (GNCPriceListForeachData *) user_data;
+    if (foreach_data->ok)
+    {
+        foreach_data->ok = foreach_data->func(price_list, foreach_data->user_data);
+    }
+}
+
+static void
+pricedb_pricelist_foreach_currencies_hash(gpointer key, gpointer val, gpointer user_data)
+{
+    GHashTable *currencies_hash = (GHashTable *) val;
+    g_hash_table_foreach(currencies_hash, pricedb_pricelist_foreach_pricelist, user_data);
+}
+
+static gboolean
+pricedb_pricelist_traversal(GNCPriceDB *db,
+                         gboolean (*f)(GList *p, gpointer user_data),
+                         gpointer user_data)
+{
+    GNCPriceListForeachData foreach_data;
+
+    if (!db || !f) return FALSE;
+    foreach_data.ok = TRUE;
+    foreach_data.func = f;
+    foreach_data.user_data = user_data;
+    if (db->commodity_hash == NULL)
+    {
+        return FALSE;
+    }
+    g_hash_table_foreach(db->commodity_hash,
+                         pricedb_pricelist_foreach_currencies_hash,
+                         &foreach_data);
+
+    return foreach_data.ok;
+}
+
 static gint
 compare_hash_entries_by_commodity_key(gconstpointer a, gconstpointer b)
 {

commit ed776a73f0b990a05ddb9dd4a4acdee14dca2ae3
Author: Mike Alexander <mta at umich.edu>
Date:   Mon Nov 9 23:37:43 2015 -0500

    Improve performance of price editor dialog.
    
    Add new functions to get the number of prices and the get a price by
    index for a given commodity.  Use these instead of building a list of all
    prices several times for each price.

diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index 6d3c665..bba4f28 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -1407,11 +1407,21 @@ gnc_pricedb_remove_old_prices(GNCPriceDB *db,
 /* ==================================================================== */
 /* lookup/query functions */
 
+static PriceList *pricedb_price_list_merge (PriceList *a, PriceList *b);
+
 static void
 hash_values_helper(gpointer key, gpointer value, gpointer data)
 {
     GList ** l = data;
-    *l = g_list_concat(*l, g_list_copy (value));
+    if (*l)
+    {
+        GList *new_l;
+        new_l = pricedb_price_list_merge(*l, value);
+        g_list_free (*l);
+        *l = new_l;
+    }
+    else
+        *l = g_list_copy (value);
 }
 
 static PriceList *
@@ -1511,10 +1521,7 @@ pricedb_get_prices_internal(GNCPriceDB *db, const gnc_commodity *commodity,
             }
         }
     }
-    if (forward_list && !currency)
-        /* Multiple currencies, reverse_list doesn't exist and 
-           forward_list must be sorted */
-        forward_list = g_list_sort (forward_list, compare_prices_by_date);
+
     return forward_list;
 }
 
@@ -1933,7 +1940,124 @@ gnc_pricedb_get_prices(GNCPriceDB *db,
     return result;
 }
 
+/* Return the number of prices in the data base for the given commodity
+ */
+static void
+price_count_helper(gpointer key, gpointer value, gpointer data)
+{
+    int *result = data;
+    GList *price_list = value;
+    
+    *result += g_list_length(price_list);
+}
+
+int
+gnc_pricedb_num_prices(GNCPriceDB *db,
+                       const gnc_commodity *c)
+{
+    int result = 0;
+    GHashTable *currency_hash;
+    
+    if (!db || !c) return 0;
+    ENTER ("db=%p commodity=%p", db, c);
 
+    currency_hash = g_hash_table_lookup(db->commodity_hash, c);
+    if (currency_hash)
+    {
+        g_hash_table_foreach(currency_hash, price_count_helper,  (gpointer)&result);
+    }
+    
+    LEAVE ("count=%d", result);
+    return result;
+}
+
+/* Return the nth price for the given commodity
+ */
+GNCPrice *
+gnc_pricedb_nth_price (GNCPriceDB *db,
+                       const gnc_commodity *c,
+                       const int n)
+{
+    GNCPrice *result = NULL;
+    GHashTable *currency_hash;
+    
+    if (!db || !c || n < 0) return NULL;
+    ENTER ("db=%p commodity=%p index=%d", db, c, n);
+    
+    currency_hash = g_hash_table_lookup(db->commodity_hash, c);
+    if (currency_hash)
+    {
+        int num_currencies = g_hash_table_size(currency_hash);
+        if (num_currencies == 1)
+        {
+            /* Optimize the case of prices in only one currency, it's common
+               and much faster */
+            GHashTableIter iter;
+            gpointer key, value;
+            g_hash_table_iter_init(&iter, currency_hash);
+            if (g_hash_table_iter_next(&iter, &key, &value))
+            {
+                PriceList *prices = value;
+                result = g_list_nth_data(prices, n);
+            }
+        }
+        else if (num_currencies > 1)
+        {
+            /* Prices for multiple currencies, must find the nth entry in the
+               merged currency list. */
+            GList **price_array = (GList **)g_new(gpointer, num_currencies);
+            GList **next_list;
+            int i, j;
+            GHashTableIter iter;
+            gpointer key, value;
+            
+            /* Build an array of all the currencies this commodity has prices for */
+            for (i = 0, g_hash_table_iter_init(&iter, currency_hash);
+                 g_hash_table_iter_next(&iter, &key, &value) && i < num_currencies;
+                 i++)
+            {
+                price_array[i] = value;
+            }
+            
+            /* Iterate n times to get the nth price, each time finding the currency
+               with the latest price */
+            for (i = 0; i <= n; i++)
+            {
+                next_list = NULL;
+                for (j = 0; j < num_currencies; j++)
+                {
+                    /* Save this entry if it's the first one or later than
+                       the saved one. */
+                    if (price_array[j] != NULL &&
+                        (next_list == NULL || *next_list == NULL ||
+                        compare_prices_by_date((*next_list)->data, (price_array[j])->data) > 0))
+                    {
+                        next_list = &price_array[j];
+                    }
+                }
+                /* next_list points to the list with the latest price unless all
+                   the lists are empty */
+                if (next_list && *next_list)
+                {
+                    result = (*next_list)->data;
+                    *next_list = (*next_list)->next;
+                }
+                else
+                {
+                    /* all the lists are empty, "n" is greater than the number
+                       of prices for this commodity. */
+                    result = NULL;
+                    break;
+                }
+            }
+            g_free(price_array);
+        }
+    }
+
+    LEAVE ("price=%p", result);
+    return result;
+}
+                       
 GNCPrice *
 gnc_pricedb_lookup_day(GNCPriceDB *db,
                        const gnc_commodity *c,
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index 066cc81..4e3363f 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -587,6 +587,27 @@ gboolean     gnc_pricedb_foreach_price(GNCPriceDB *db,
                                        gpointer user_data,
                                        gboolean stable_order);
 
+/** @brief Get the number of prices, in any currency, for a given commodity.
+ * @param db The pricedb
+ * @param c The commodity
+ * @return The number of prices in the database for this commody, zero if none
+ */
+int
+gnc_pricedb_num_prices(GNCPriceDB *db,
+                       const gnc_commodity *c);
+
+/** @brief Get the nth price for the given commodity in  reverse date order
+ * @param db The pricedb
+ * @param c The commodity whose nth price is needed
+ * @param n Zero based index of the price wanted
+ * @return The nth price for this commodity in reverse chronological order, without
+ * regard for what currency the price is in
+ */
+GNCPrice *
+gnc_pricedb_nth_price (GNCPriceDB *db,
+                       const gnc_commodity *c,
+                       const int n);
+
 /* The following two convenience functions are used to test the xml backend */
 /** @brief Return the number of prices in the database.
  *
diff --git a/src/gnome-utils/gnc-tree-model-price.c b/src/gnome-utils/gnc-tree-model-price.c
index 20a4409..ec41172 100644
--- a/src/gnome-utils/gnc-tree-model-price.c
+++ b/src/gnome-utils/gnc-tree-model-price.c
@@ -594,10 +594,8 @@ gnc_tree_model_price_get_iter (GtkTreeModel *tree_model,
     }
 
     /* Verify the third part of the path: the price. */
-    price_list = gnc_pricedb_get_prices(priv->price_db, commodity, NULL);
     i = gtk_tree_path_get_indices (path)[2];
-    price = g_list_nth_data (price_list, i);
-    gnc_price_list_destroy(price_list);
+    price = gnc_pricedb_nth_price(priv->price_db, commodity, i);
     /* There's a race condition here that I can't resolve.
      * Comment this check out for now, and we'll handle the
      * resulting problem elsewhere. */
@@ -860,9 +858,7 @@ gnc_tree_model_price_iter_next (GtkTreeModel *tree_model,
     {
         commodity = gnc_price_get_commodity((GNCPrice*)iter->user_data2);
         n = GPOINTER_TO_INT(iter->user_data3) + 1;
-        list = gnc_pricedb_get_prices(priv->price_db, commodity, NULL);
-        iter->user_data2 = g_list_nth_data(list, n);
-        gnc_price_list_destroy(list);
+        iter->user_data2 = gnc_pricedb_nth_price(priv->price_db, commodity, n);
         if (iter->user_data2 == NULL)
         {
             LEAVE("no next iter");
@@ -936,18 +932,18 @@ gnc_tree_model_price_iter_children (GtkTreeModel *tree_model,
 
     if (parent->user_data == ITER_IS_COMMODITY)
     {
+        GNCPrice *price;
         commodity = (gnc_commodity *)parent->user_data2;
-        list = gnc_pricedb_get_prices(priv->price_db, commodity, NULL);
-        if (list == NULL)
+        price = gnc_pricedb_nth_price(priv->price_db, commodity, 0);
+        if (price == NULL)
         {
             LEAVE("no prices");
             return FALSE;
         }
         iter->stamp      = model->stamp;
         iter->user_data  = ITER_IS_PRICE;
-        iter->user_data2 = g_list_nth_data(list, 0);
+        iter->user_data2 = price;
         iter->user_data3 = GINT_TO_POINTER(0);
-        gnc_price_list_destroy(list);
         LEAVE("price iter %p (%s)", iter, iter_to_string(model, iter));
         return TRUE;
     }
@@ -1038,9 +1034,7 @@ gnc_tree_model_price_iter_n_children (GtkTreeModel *tree_model,
     if (iter->user_data == ITER_IS_COMMODITY)
     {
         commodity = (gnc_commodity *)iter->user_data2;
-        list = gnc_pricedb_get_prices(priv->price_db, commodity, NULL);
-        n = g_list_length(list);
-        gnc_price_list_destroy(list);
+        n = gnc_pricedb_num_prices(priv->price_db, commodity);
         LEAVE("price list length %d", n);
         return n;
     }
@@ -1099,13 +1093,11 @@ gnc_tree_model_price_iter_nth_child (GtkTreeModel *tree_model,
     if (parent->user_data == ITER_IS_COMMODITY)
     {
         commodity = (gnc_commodity *)parent->user_data2;
-        list = gnc_pricedb_get_prices(priv->price_db, commodity, NULL);
 
         iter->stamp      = model->stamp;
         iter->user_data  = ITER_IS_PRICE;
-        iter->user_data2 = g_list_nth_data(list, n);
+        iter->user_data2 = gnc_pricedb_nth_price(priv->price_db, commodity, n);
         iter->user_data3 = GINT_TO_POINTER(n);
-        gnc_price_list_destroy(list);
         LEAVE("price iter %p (%s)", iter, iter_to_string(model, iter));
         return iter->user_data2 != NULL;
     }



Summary of changes:
 src/engine/gnc-pricedb.c               | 392 +++++++++++++++++++++++----------
 src/engine/gnc-pricedb.h               |  21 ++
 src/gnome-utils/gnc-tree-model-price.c |  24 +-
 3 files changed, 302 insertions(+), 135 deletions(-)



More information about the gnucash-changes mailing list