diff --git a/CMakeLists.txt b/CMakeLists.txt index cdfba7e233..b8e0adf461 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,14 +13,14 @@ ENABLE_TESTING() # Version number of gnucash SET (GNUCASH_MAJOR_VERSION 2) SET (GNUCASH_MINOR_VERSION 7) -SET (GNUCASH_MICRO_VERSION 7) +SET (GNUCASH_MICRO_VERSION 8) SET (GNUCASH_NANO_VERSION 0) SET (VERSION "${GNUCASH_MAJOR_VERSION}.${GNUCASH_MINOR_VERSION}.${GNUCASH_MICRO_VERSION}") SET (GNUCASH_LATEST_STABLE_SERIES 2.6) SET (PACKAGE gnucash) SET (PACKAGE_NAME GnuCash) -SET (PACKAGE_VERSION 2.7.7) +SET (PACKAGE_VERSION 2.7.8) SET (PACKAGE_BUGREPORT gnucash-devel@gnucash.org) SET (PACKAGE_TARNAME ${PACKAGE}) SET (PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") diff --git a/NEWS b/NEWS index c79d29893c..ed44f6084b 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,40 @@ Version history: ------- ------- +2.7.8 - 25 March 2018 + + The Gnucash Development Team is pleased to release Gnucash 2.7.8, + the ninth release of an unstable series leading to Gnucash 3.0. This + release is a Release Candidate: If no bugs requiring major work are + reported the next release will be 3.0. + + This release changes file locations, binding APIs, report options, + and can make your data file no longer compatible with previous + versions. See https://wiki.gnucash.org/wiki/UpdateNotes for + details. + +The following bugs are fixed only in unstable/master: + Bug 787439 - Segmentation Fault in Transfer dialog after clearing + Date field and pressing escape. + Bug 794242 - Remove keep above setting for assistant hierarchy + +Other repairs not marked as bugs in git: + When doing a file save from the a new start we have no key file + Test for Key_file not being NULL before trying to free it. + Stop critical error due to testing null filename + g_filename_from_uri returns NULL if it is not a file uri so test + for the file:// prefix before doing g_file_test + More transient-parent fixes. + Add missing response section to the account picker dialog. + Glade 3.20 adds surplus padding option to action area + When glade files are saved which have GtkAssistants defined a packing + section is added to the assistant action area which then causes a + warning so remove them. + Add XML namespaces for all Account Hierarchy Templates. + Increase default options dialog size: The old 400x400 was woefully + inadequate for most options especially options involving account trees. + +Updated Translations: None. + 2.7.7 - 18 March 2018 The Gnucash Development Team is pleased to release Gnucash 2.7.7, diff --git a/bindings/python/example_scripts/account_analysis.py b/bindings/python/example_scripts/account_analysis.py index dd7fc4a9a0..87e1dfe7b7 100644 --- a/bindings/python/example_scripts/account_analysis.py +++ b/bindings/python/example_scripts/account_analysis.py @@ -152,13 +152,13 @@ def account_from_path(top_account, account_path, original_path=None): def main(): if len(argv) < 10: - print 'not enough parameters' - print 'usage: account_analysis.py {book url} {start year} {start month, numeric} {period type: monthly, quarterly, or yearly} {number of periods to show, from start year and month} {whether to show debits: debits-show for true, all other values false} {whether to show credits: credits-show for true, all other values false} {space separated account path, as many nested levels as desired} ' - print 'examples:\n' - print "The following example analyzes 12 months of 'Assets:Test Account' from /home/username/test.gnucash, starting in January of 2010, and shows both credits and debits" - print "gnucash-env python account_analysis.py '/home/username/test.gnucash' 2010 1 monthly 12 debits-show credits-show Assets 'Test Account'\n" - print "The following example analyzes 2 quarters of 'Liabilities:First Level:Second Level' from /home/username/test.gnucash, starting March 2011, and shows credits but not debits" - print "gnucash-env python account_analysis.py '/home/username/test.gnucash' 2011 3 quarterly 2 debits-noshow credits-show Liabilities 'First Level' 'Second Level" + print('not enough parameters') + print('usage: account_analysis.py {book url} {start year} {start month, numeric} {period type: monthly, quarterly, or yearly} {number of periods to show, from start year and month} {whether to show debits: debits-show for true, all other values false} {whether to show credits: credits-show for true, all other values false} {space separated account path, as many nested levels as desired} ') + print('examples:\n') + print("The following example analyzes 12 months of 'Assets:Test Account' from /home/username/test.gnucash, starting in January of 2010, and shows both credits and debits") + print("gnucash-env python account_analysis.py '/home/username/test.gnucash' 2010 1 monthly 12 debits-show credits-show Assets 'Test Account'\n") + print("The following example analyzes 2 quarters of 'Liabilities:First Level:Second Level' from /home/username/test.gnucash, starting March 2011, and shows credits but not debits") + print("gnucash-env python account_analysis.py '/home/username/test.gnucash' 2011 3 quarterly 2 debits-noshow credits-show Liabilities 'First Level' 'Second Level") return try: diff --git a/bindings/python/example_scripts/gncinvoice_jinja.py b/bindings/python/example_scripts/gncinvoice_jinja.py index 6e4eaff5c0..ec93ed030f 100644 --- a/bindings/python/example_scripts/gncinvoice_jinja.py +++ b/bindings/python/example_scripts/gncinvoice_jinja.py @@ -39,8 +39,8 @@ try: import jinja2 from gncinvoicefkt import * except ImportError as import_error: - print "Problem importing modules." - print import_error + print("Problem importing modules.") + print(import_error) sys.exit(2) class Usage(Exception): @@ -68,26 +68,26 @@ def main(argv=None): for opt in opts: if opt[0] in ["-f"]: - print "ignoring lock" + print("ignoring lock") ignore_lock = True if opt[0] in ["-h","--help"]: raise Usage("Help:") if opt[0] in ["-I"]: invoice_id = opt[1] - print "using invoice ID '" + str(invoice_id) + "'." + print("using invoice ID '" + str(invoice_id) + "'.") if opt[0] in ["-o"]: filename_output = opt[1] - print "using output file", filename_output + print("using output file", filename_output) if opt[0] in ["-t"]: filename_template = opt[1] - print "using template file", filename_template + print("using template file", filename_template) if opt[0] in ["-l"]: list_invoices = True - print "listing invoices" + print("listing invoices") # Check for correct input if len(args)>1: - print "opts:",opts,"args:",args + print("opts:",opts,"args:",args) raise Usage("Only one input possible !") if len(args)==0: raise Usage("No input given !") @@ -103,41 +103,41 @@ def main(argv=None): if not filename_output: if filename_template: filename_output = filename_template + ".out" - print "no output filename given, will be:", filename_output + print("no output filename given, will be:", filename_output) except Usage, err: if err.msg == "Help:": retcode=0 else: - print >>sys.stderr, "Error:",err.msg - print >>sys.stderr, "for help use --help" + print(>>sys.stderr, "Error:",err.msg) + print(>>sys.stderr, "for help use --help") retcode=2 - print - print "Usage:" - print - print "Invoke with",prog_name,"gnucash_url." - print "where input is" - print " filename" - print "or file://filename" - print "or mysql://user:password@host/databasename" - print - print "-f force open = ignore lock" - print "-l list all invoices" - print "-h or --help for this help" - print "-I ID use invoice ID" - print "-t filename use filename as template file" - print "-o filename use filename as output file" + print() + print("Usage:") + print() + print("Invoke with",prog_name,"gnucash_url.") + print("where input is") + print(" filename") + print("or file://filename") + print("or mysql://user:password@host/databasename") + print() + print("-f force open = ignore lock") + print("-l list all invoices") + print("-h or --help for this help") + print("-I ID use invoice ID") + print("-t filename use filename as template file") + print("-o filename use filename as output file") return retcode # Try to open the given input try: - print "Opening", input_url, "." + print("Opening", input_url, ".") session = gnucash.Session(input_url, ignore_lock=ignore_lock) except Exception as exception: - print "Problem opening input." - print exception + print("Problem opening input.") + print(exception) return 2 book = session.book @@ -149,22 +149,22 @@ def main(argv=None): if list_invoices: for number,invoice in enumerate(invoice_list): - print str(number)+")" - print invoice + print(str(number)+")") + print(invoice) if not (no_output): if invoice_id: invoice = book.InvoiceLookupByID(invoice_id) if not invoice: - print "ID not found." + print("ID not found.") return 2 if invoice_number: invoice = invoice_list[invoice_number] - print "Using the following invoice:" - print invoice + print("Using the following invoice:") + print(invoice) loader = jinja2.FileSystemLoader('.') env = jinja2.Environment(loader=loader) @@ -174,7 +174,7 @@ def main(argv=None): #IPython.embed() output = template.render(invoice=invoice, locale=locale) - print "Writing output", filename_output, "." + print("Writing output", filename_output, ".") with open(filename_output, 'w') as f: f.write(output.encode('utf-8')) diff --git a/bindings/python/example_scripts/gncinvoicefkt.py b/bindings/python/example_scripts/gncinvoicefkt.py index 9e0ffa05a0..ef778b4370 100644 --- a/bindings/python/example_scripts/gncinvoicefkt.py +++ b/bindings/python/example_scripts/gncinvoicefkt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- ##@file # @brief some help for working with invoices, used in \ref py_invoice_export @@ -22,8 +22,8 @@ try: GNC_DISC_PRETAX import str_methods except ImportError as import_error: - print "Problem importing modules." - print import_error + print("Problem importing modules.") + print(import_error) sys.exit(2) def get_all_lots(account): diff --git a/bindings/python/example_scripts/latex_invoices.py b/bindings/python/example_scripts/latex_invoices.py index 8b738fa715..4c6c1d45fb 100644 --- a/bindings/python/example_scripts/latex_invoices.py +++ b/bindings/python/example_scripts/latex_invoices.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- ##@file # @brief Exports an invoice to lco-file for use with LaTeX, see \ref py_invoice_export @@ -66,8 +66,8 @@ try: GNC_DISC_PRETAX import locale except ImportError as import_error: - print "Problem importing modules." - print import_error + print("Problem importing modules.") + print(import_error) sys.exit(2) class Usage(Exception): @@ -157,7 +157,7 @@ def invoice_to_lco(invoice): line_str += uprice line_str += u"}" - #print line_str + #print(line_str) ent_str += line_str lco_out += write_variable("entries",ent_str) @@ -184,25 +184,25 @@ def main(argv=None): for opt in opts: if opt[0] in ["-f"]: - print "ignoring lock" + print("ignoring lock") ignore_lock = True if opt[0] in ["-h","--help"]: raise Usage("Help:") if opt[0] in ["-i"]: - print "Using ipshell" + print("Using ipshell") with_ipshell = True if opt[0] in ["-l"]: - print "listing all invoices" + print("listing all invoices") list_invoices=True if opt[0] in ["-n"]: invoice_number = int(opt[1]) - print "using invoice number", invoice_number + print("using invoice number", invoice_number) no_latex_output = False if opt[0] in ["-o"]: output_file_name = opt[1] - print "using output file", output_file_name + print("using output file", output_file_name) if len(args)>1: - print "opts:",opts,"args:",args + print("opts:",opts,"args:",args) raise Usage("Only one input can be accepted !") if len(args)==0: raise Usage("No input given !") @@ -211,26 +211,26 @@ def main(argv=None): if err.msg == "Help:": retcode=0 else: - print >>sys.stderr, "Error:",err.msg - print >>sys.stderr, "for help use --help" + print(>>sys.stderr, "Error:",err.msg) + print(>>sys.stderr, "for help use --help") retcode=2 - print "Generate a LaTeX invoice or print out all invoices." - print - print "Usage:" - print - print "Invoke with",prog_name,"input." - print "where input is" - print " filename" - print "or file://filename" - print "or mysql://user:password@host/databasename" - print - print "-f force open = ignore lock" - print "-h or --help for this help" - print "-i for ipython shell" - print "-l list all invoices" - print "-n number use invoice number (no. from previous run with -l)" - print "-o name use name as outputfile. default: data.lco" + print("Generate a LaTeX invoice or print out all invoices.") + print() + print("Usage:") + print() + print("Invoke with",prog_name,"input.") + print("where input is") + print(" filename") + print("or file://filename") + print("or mysql://user:password@host/databasename") + print() + print("-f force open = ignore lock") + print("-h or --help for this help") + print("-i for ipython shell") + print("-l list all invoices") + print("-n number use invoice number (no. from previous run with -l)") + print("-o name use name as outputfile. default: data.lco") return retcode @@ -238,8 +238,8 @@ def main(argv=None): try: session = gnucash.Session(input_url,ignore_lock=ignore_lock) except Exception as exception: - print "Problem opening input." - print exception + print("Problem opening input.") + print(exception) return 2 book = session.book @@ -251,18 +251,18 @@ def main(argv=None): if list_invoices: for number,invoice in enumerate(invoice_list): - print str(number)+")" - print invoice + print(str(number)+")") + print(invoice) if not (no_latex_output): if invoice_number == None: - print "Using the first invoice:" + print("Using the first invoice:") invoice_number=0 invoice=invoice_list[invoice_number] - print "Using the following invoice:" - print invoice + print("Using the following invoice:") + print(invoice) lco_str=invoice_to_lco(invoice) diff --git a/bindings/python/example_scripts/new_book_with_opening_balances.py b/bindings/python/example_scripts/new_book_with_opening_balances.py index 08a08deca5..0ee02c4031 100644 --- a/bindings/python/example_scripts/new_book_with_opening_balances.py +++ b/bindings/python/example_scripts/new_book_with_opening_balances.py @@ -290,11 +290,11 @@ def create_opening_balance_transaction(commodtable, namespace, mnemonic, def main(): if len(argv) < 3: - print 'not enough parameters' - print 'usage: new_book_with_opening_balances.py {source_book_url} {destination_book_url}' - print 'examples:' - print "gnucash-env python new_book_with_opening_balances.py '/home/username/test.gnucash' 'sqlite3:///home/username/new_test.gnucash'" - print "gnucash-env python new_book_with_opening_balances.py '/home/username/test.gnucash' 'xml:///crypthome/username/finances/new_test.gnucash'" + print('not enough parameters') + print('usage: new_book_with_opening_balances.py {source_book_url} {destination_book_url}') + print('examples:') + print("gnucash-env python new_book_with_opening_balances.py '/home/username/test.gnucash' 'sqlite3:///home/username/new_test.gnucash'") + print("gnucash-env python new_book_with_opening_balances.py '/home/username/test.gnucash' 'xml:///crypthome/username/finances/new_test.gnucash'") return #have everything in a try block to unable us to release our hold on stuff to the extent possible diff --git a/bindings/python/example_scripts/priceDB_test.py b/bindings/python/example_scripts/priceDB_test.py index fcd30e2750..41f42fb95b 100644 --- a/bindings/python/example_scripts/priceDB_test.py +++ b/bindings/python/example_scripts/priceDB_test.py @@ -41,11 +41,11 @@ for pr in pl: time = pr.get_time() v=pr.get_value() price = float(v.num)/v.denom - print time, source, price + print(time, source, price) if len(pl) > 0: v0 = pl[0].get_value() - print arm.get_fullname(), float(v0.num) / float(v0.denom ) + print(arm.get_fullname(), float(v0.num) / float(v0.denom )) session.end() session.destroy() diff --git a/bindings/python/example_scripts/price_database_example.py b/bindings/python/example_scripts/price_database_example.py index 86db03328e..b9b10e85ce 100755 --- a/bindings/python/example_scripts/price_database_example.py +++ b/bindings/python/example_scripts/price_database_example.py @@ -57,12 +57,12 @@ for namespace in namespaces: if len(commodities) == 0 : - print "No commodity in namespace "+namespace_name+"." + print("No commodity in namespace "+namespace_name+".") else: if commodity_fullname: - print "Searching commodity '"+commodity_fullname+"' in namespace "+namespace_name + print("Searching commodity '"+commodity_fullname+"' in namespace "+namespace_name) else: - print "Commoditys in namespace "+namespace_name+":" + print("Commoditys in namespace "+namespace_name+":") for i, c in enumerate(commodities): @@ -70,12 +70,12 @@ for namespace in namespaces: c_fullname = c.get_fullname() if not(commodity_fullname) or (commodity_fullname == c_fullname): - print "["+str(i)+"] Full Name :", c.get_fullname() + print("["+str(i)+"] Full Name :", c.get_fullname()) if show_prices: pl = pdb.get_prices(c,cur) if len(pl) > 0 : - print "{0} {1:20}{2:>10} {3}".format("Time ","Source","Price","Currency") + print("{0} {1:20}{2:>10} {3}".format("Time ","Source","Price","Currency")) for pr in pl: source = pr.get_source() @@ -83,7 +83,7 @@ for namespace in namespaces: v=pr.get_value() price = float(v.num)/v.denom - print "{0} {1:20}{2:10.4f} {3}".format(time,source,price,cur_name) + print("{0} {1:20}{2:10.4f} {3}".format(time,source,price,cur_name)) # I didn't find out how to format the time option... session.end() diff --git a/bindings/python/example_scripts/quotes_historic.py b/bindings/python/example_scripts/quotes_historic.py index da70cc7fe1..964c70f029 100644 --- a/bindings/python/example_scripts/quotes_historic.py +++ b/bindings/python/example_scripts/quotes_historic.py @@ -60,14 +60,14 @@ stock = ac.GetCommodity() # Add the prices pdb = book.get_price_db() if len(ac.GetSplitList())<1: - print 'Need at least one Split to get currency info ... ' + print('Need at least one Split to get currency info ... ') raise SystemExit cur = ac.GetSplitList()[0].GetParent().GetCurrency() # Get stock data pl = pdb.get_prices(stock,cur) if len(pl)<1: - print 'Need at least one database entry to clone ...' + print('Need at least one database entry to clone ...') raise SystemExit pl0 = pl[0] @@ -77,7 +77,7 @@ for i in range(1,len(pl)): for i in range(0,len(stock_date)): p_new = pl0.clone(book) p_new = gnucash.GncPrice(instance=p_new) - print 'Adding',i,stock_date[i],stock_price[i] + print('Adding',i,stock_date[i],stock_price[i]) p_new.set_time(stock_date[i]) v = p_new.get_value() v.num = int(Fraction.from_float(stock_price[i]).limit_denominator(100000).numerator) diff --git a/bindings/python/example_scripts/rest-api/gnucash_rest.py b/bindings/python/example_scripts/rest-api/gnucash_rest.py index f6a4dc99cd..5444b98e98 100644 --- a/bindings/python/example_scripts/rest-api/gnucash_rest.py +++ b/bindings/python/example_scripts/rest-api/gnucash_rest.py @@ -835,7 +835,7 @@ def getAccountsFlat(book): for n, account in enumerate(flat_accounts): if account['type_id'] in type_ids: filtered_flat_account.append(account) - print account['name'] + ' ' + str(account['type_id']) + print(account['name'] + ' ' + str(account['type_id'])) return filtered_flat_account @@ -1846,7 +1846,7 @@ def shutdown(): session.save() session.end() session.destroy() - print 'Shutdown' + print('Shutdown') class Error(Exception): """Base class for exceptions in this module.""" @@ -1858,12 +1858,12 @@ class Error(Exception): try: options, arguments = getopt.getopt(sys.argv[1:], 'nh:', ['host=', 'new=']) except getopt.GetoptError as err: - print str(err) # will print something like "option -a not recognized" - print 'Usage: python-rest.py ' + print(str(err) # will print something like "option -a not recognized") + print('Usage: python-rest.py ') sys.exit(2) if len(arguments) == 0: - print 'Usage: python-rest.py ' + print('Usage: python-rest.py ') sys.exit(2) #set default host for Flask diff --git a/bindings/python/example_scripts/simple_book.py b/bindings/python/example_scripts/simple_book.py index bbc33546b0..4bde60817e 100644 --- a/bindings/python/example_scripts/simple_book.py +++ b/bindings/python/example_scripts/simple_book.py @@ -10,16 +10,16 @@ from gnucash import Session # We need to tell GnuCash the data format to create the new file as (xml://) uri = "xml:///tmp/simple_book.gnucash" -print "uri:", uri +print("uri:", uri) ses = Session(uri, is_new=True) book = ses.get_book() #Call some methods that produce output to show that Book works book.get_root_account().SetDescription("hello, book") -print "Book is saved:", not book.session_not_saved() +print("Book is saved:", not book.session_not_saved()) -print "saving..." +print("saving...") ses.save() -print "Book is saved:", not book.session_not_saved() +print("Book is saved:", not book.session_not_saved()) ses.end() diff --git a/bindings/python/example_scripts/simple_business_create.py b/bindings/python/example_scripts/simple_business_create.py index 40a2c3a02b..75a00228bb 100644 --- a/bindings/python/example_scripts/simple_business_create.py +++ b/bindings/python/example_scripts/simple_business_create.py @@ -62,10 +62,10 @@ from gnucash.gnucash_core_c import \ GNC_OWNER_CUSTOMER, ACCT_TYPE_LIABILITY if len(argv) < 2: - print 'not enough parameters' - print 'usage: simple_business_create.py {new_book_url}' - print 'example:' - print "gnucash-env python simple_business_create.py sqlite3:///home/blah/blah.gnucash" + print('not enough parameters') + print('usage: simple_business_create.py {new_book_url}') + print('example:') + print("gnucash-env python simple_business_create.py sqlite3:///home/blah/blah.gnucash") exit() diff --git a/bindings/python/example_scripts/simple_test.py b/bindings/python/example_scripts/simple_test.py index 7156fd9f3a..274164168d 100644 --- a/bindings/python/example_scripts/simple_test.py +++ b/bindings/python/example_scripts/simple_test.py @@ -61,9 +61,11 @@ split3.SetAccount(savings_acct) split3.SetParent(trans2) trans1.SetCurrency(cad) +trans1.SetDate(14, 3, 2006) trans1.SetDescription("Groceries") trans2.SetCurrency(cad) +trans2.SetDate(7, 11, 1995) trans2.SetDescription("Opening Savings Balance") split2 = Split(book) diff --git a/bindings/python/example_scripts/test_imbalance_transaction.py b/bindings/python/example_scripts/test_imbalance_transaction.py index f50dea946f..d22072867d 100644 --- a/bindings/python/example_scripts/test_imbalance_transaction.py +++ b/bindings/python/example_scripts/test_imbalance_transaction.py @@ -42,10 +42,10 @@ from gnucash import Session, Transaction, Split, Account, GncNumeric, \ # and trading accounts disabled if len(argv) < 2: - print 'not enough parameters' - print 'usage: test_imbalance_transaction.py {book_url}' - print 'examples:' - print "gnucash-env python test_imbalance_transaction.py '/home/username/test.gnucash'" + print('not enough parameters') + print('usage: test_imbalance_transaction.py {book_url}') + print('examples:') + print("gnucash-env python test_imbalance_transaction.py '/home/username/test.gnucash'") exit() @@ -86,12 +86,12 @@ try: s2.SetAccount(account2) s2.SetValue(GncNumeric(4)) s2.SetAmount(GncNumeric(4)) - print 'overall imbalance', a.GetImbalanceValue().to_string() + print('overall imbalance', a.GetImbalanceValue().to_string()) - print 'per-currency imbalances' + print('per-currency imbalances') imbalance_list = a.GetImbalance() for (commod, value) in imbalance_list: - print value.to_string(), commod.get_mnemonic() + print(value.to_string(), commod.get_mnemonic()) a.CommitEdit() diff --git a/gnucash/gnome/dialog-price-edit-db.c b/gnucash/gnome/dialog-price-edit-db.c index f6d5efb695..4fdcc0971e 100644 --- a/gnucash/gnome/dialog-price-edit-db.c +++ b/gnucash/gnome/dialog-price-edit-db.c @@ -387,6 +387,7 @@ gnc_prices_dialog_remove_old_clicked (GtkWidget *widget, gpointer data) { PricesDialog *pdb_dialog = data; GtkBuilder *builder; + GtkTreeModel *model; GtkWidget *date, *label, *box; GtkWidget *button; GtkTreeSelection *selection; @@ -459,6 +460,11 @@ gnc_prices_dialog_remove_old_clicked (GtkWidget *widget, gpointer data) PriceRemoveSourceFlags source = PRICE_REMOVE_SOURCE_FQ; PriceRemoveKeepOptions keep = PRICE_REMOVE_KEEP_NONE; + // disconnect the model to the price treeview + model = gtk_tree_view_get_model (GTK_TREE_VIEW(pdb_dialog->price_tree)); + g_object_ref (G_OBJECT(model)); + gtk_tree_view_set_model (GTK_TREE_VIEW(pdb_dialog->price_tree), NULL); + DEBUG("deleting prices"); last_ts.tv_sec = gnc_date_edit_get_date (GNC_DATE_EDIT (date)); last_ts.tv_nsec = 0; @@ -498,6 +504,9 @@ gnc_prices_dialog_remove_old_clicked (GtkWidget *widget, gpointer data) gnc_pricedb_remove_old_prices (pdb_dialog->price_db, comm_list, &fiscal_end_date, tmp_ts, pdb_dialog->remove_source, PRICE_REMOVE_KEEP_LAST_MONTHLY); } + // reconnect the model to the price treeview + gtk_tree_view_set_model (GTK_TREE_VIEW(pdb_dialog->price_tree), model); + g_object_unref(G_OBJECT(model)); } g_list_free (comm_list); } diff --git a/gnucash/gnome/gnc-plugin-page-account-tree.c b/gnucash/gnome/gnc-plugin-page-account-tree.c index d4dbd5cd2a..5913b7513e 100644 --- a/gnucash/gnome/gnc-plugin-page-account-tree.c +++ b/gnucash/gnome/gnc-plugin-page-account-tree.c @@ -82,6 +82,8 @@ static QofLogModule log_module = GNC_MOD_GUI; #define DELETE_DIALOG_TRANS_MAS "trans_mas" #define DELETE_DIALOG_SA_MAS "sa_mas" #define DELETE_DIALOG_SA_TRANS_MAS "sa_trans_mas" +#define DELETE_DIALOG_SA_TRANS "sa_trans" +#define DELETE_DIALOG_SA_SPLITS "sa_has_split" #define DELETE_DIALOG_OK_BUTTON "deletebutton" enum @@ -1286,8 +1288,36 @@ gppat_populate_trans_mas_list(GtkToggleButton *sa_mrb, void gppat_set_insensitive_iff_rb_active(GtkWidget *widget, GtkToggleButton *b) { + GtkWidget *dialog = gtk_widget_get_toplevel(widget); + GtkWidget *subaccount_trans = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_TRANS); + GtkWidget *sa_mas = g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_MAS); + gboolean have_splits = GPOINTER_TO_INT (g_object_get_data(G_OBJECT(dialog), DELETE_DIALOG_SA_SPLITS)); + gtk_widget_set_sensitive(widget, !gtk_toggle_button_get_active(b)); - set_ok_sensitivity(gtk_widget_get_toplevel(widget)); + + // If we have subaccount splits & delete subaccounts, enable subaccount_trans + if ((have_splits) && !gtk_widget_is_sensitive(sa_mas)) + gtk_widget_set_sensitive(subaccount_trans, TRUE); + else + gtk_widget_set_sensitive(subaccount_trans, FALSE); + + set_ok_sensitivity(dialog); +} + +static GtkWidget * +gppat_setup_account_selector (GtkBuilder *builder, GtkWidget *dialog, + const gchar *hbox, const gchar *sel_name) +{ + GtkWidget *selector = gnc_account_sel_new(); + GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder, hbox)); + + gtk_box_pack_start (GTK_BOX(box), selector, TRUE, TRUE, 0); + g_object_set_data(G_OBJECT(dialog), sel_name, selector); + + gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(selector), TRUE); + gtk_widget_show_all(box); + + return selector; } static void @@ -1315,9 +1345,9 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag list = qof_instance_get_referring_object_list(QOF_INSTANCE(account)); if (list != NULL) { -#define EXPLANATION "The list below shows objects which make use of the account which you want to delete.\nBefore you can delete it, you must either delete those objects or else modify them so they make use\nof another account" +#define EXPLANATION _("The list below shows objects which make use of the account which you want to delete.\nBefore you can delete it, you must either delete those objects or else modify them so they make use\nof another account") - gnc_ui_object_references_show( _(EXPLANATION), list); + gnc_ui_object_references_show(EXPLANATION, list); g_list_free(list); return; } @@ -1332,7 +1362,7 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag splits = xaccAccountGetSplitList(account); /* - * If the account has transactions or child accounts then conduct a + * If the account has transactions or child accounts then present a * dialog to allow the user to specify what should be done with them. */ if ((NULL != splits) || (gnc_account_n_children(account) > 0)) @@ -1340,7 +1370,6 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag GList *filter = NULL; GtkBuilder *builder = NULL; GtkWidget *dialog = NULL; - GtkWidget *box = NULL; GtkWidget *widget = NULL; gchar *title = NULL; @@ -1366,78 +1395,70 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_FILTER, filter); g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_ACCOUNT, account); - /* - * Adjust the dialog based on whether the account has - * transactions. - */ + // Add the account selectors and enable sections as appropiate + // setup transactions selector + trans_mas = gppat_setup_account_selector (builder, dialog, "trans_mas_hbox", DELETE_DIALOG_TRANS_MAS); + + // Does the selected account have splits if (splits) { delete_helper_t delete_res2 = { FALSE, FALSE }; - trans_mas = gnc_account_sel_new(); - box = GTK_WIDGET(gtk_builder_get_object (builder, "trans_mas_hbox")); - gtk_box_pack_start (GTK_BOX(box), trans_mas, TRUE, TRUE, 0); - g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_TRANS_MAS, trans_mas); - gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(trans_mas), FALSE); - delete_account_helper(account, &delete_res2); if (delete_res2.has_ro_splits) { - gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "trans_rw"))); + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "trans_rw"))); widget = GTK_WIDGET(gtk_builder_get_object (builder, "trans_drb")); gtk_widget_set_sensitive(widget, FALSE); } else - { - gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "trans_ro"))); - } + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "trans_ro"))); } else { - gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "transactions"))); + gtk_widget_set_sensitive (GTK_WIDGET(gtk_builder_get_object (builder, "transactions")), FALSE); + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "trans_ro"))); } - /* - * Adjust the dialog based on whether the account has children. - */ + // setup subaccount account selector + sa_mas = gppat_setup_account_selector (builder, dialog, "sa_mas_hbox", DELETE_DIALOG_SA_MAS); + + // setup subaccount transaction selector + sa_trans_mas = gppat_setup_account_selector (builder, dialog, "sa_trans_mas_hbox", DELETE_DIALOG_SA_TRANS_MAS); + g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_SA_TRANS, + GTK_WIDGET(gtk_builder_get_object (builder, "subaccount_trans"))); + + // Does the selected account have sub accounts if (gnc_account_n_children(account) > 0) { - /* - * Check for RO txns in descendants - */ + // Check for RO txns in descendants gnc_account_foreach_descendant_until(account, delete_account_helper, &delete_res); - if (delete_res.has_ro_splits) + if (delete_res.has_splits) { - gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_rw"))); - widget = GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_drb")); - gtk_widget_set_sensitive(widget, FALSE); - } - else if (delete_res.has_splits) - { - gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_ro"))); + if (delete_res.has_ro_splits) + { + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_rw"))); + widget = GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_drb")); + gtk_widget_set_sensitive(widget, FALSE); + } + else + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_ro"))); + + g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_SA_SPLITS, GINT_TO_POINTER(1)); } else { - gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "subaccount_trans"))); + g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_SA_SPLITS, GINT_TO_POINTER(0)); + gtk_widget_set_sensitive (GTK_WIDGET(gtk_builder_get_object (builder, "subaccount_trans")), FALSE); + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_ro"))); } - - sa_mas = gnc_account_sel_new(); - box = GTK_WIDGET(gtk_builder_get_object (builder, "sa_mas_hbox")); - gtk_box_pack_start (GTK_BOX(box), sa_mas, TRUE, TRUE, 0); - g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_SA_MAS, sa_mas); - gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(sa_mas), TRUE); - - sa_trans_mas = gnc_account_sel_new(); - box = GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_mas_hbox")); - gtk_box_pack_start (GTK_BOX(box), sa_trans_mas, TRUE, TRUE, 0); - g_object_set_data(G_OBJECT(dialog), DELETE_DIALOG_SA_TRANS_MAS, sa_trans_mas); - gppat_populate_gas_list(dialog, GNC_ACCOUNT_SEL(sa_trans_mas), TRUE); } else { - gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "subaccounts"))); - gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "subaccount_trans"))); + gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object (builder, "subaccounts")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object (builder, "subaccount_trans")), FALSE); + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "sa_trans_ro"))); } /* default to cancel */ @@ -1450,7 +1471,6 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag * Note that one effect of the modal dialog is preventing * the account selectors from being repopulated. */ - gtk_widget_show_all(dialog); response = gtk_dialog_run(GTK_DIALOG(dialog)); if (GTK_RESPONSE_ACCEPT != response) { diff --git a/gnucash/gnome/gnc-split-reg.c b/gnucash/gnome/gnc-split-reg.c index 1cb02f2c2a..ac909430e8 100644 --- a/gnucash/gnome/gnc-split-reg.c +++ b/gnucash/gnome/gnc-split-reg.c @@ -786,7 +786,7 @@ gnc_split_reg_reverse_trans_cb (GtkWidget *w, gpointer data) static gboolean -is_trans_readonly_and_warn (const Transaction *trans) +is_trans_readonly_and_warn (GtkWindow *parent, const Transaction *trans) { GtkWidget *dialog; const gchar *reason; @@ -798,7 +798,7 @@ is_trans_readonly_and_warn (const Transaction *trans) if (xaccTransIsReadonlyByPostedDate (trans)) { - dialog = gtk_message_dialog_new(NULL, + dialog = gtk_message_dialog_new(parent, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, @@ -814,7 +814,7 @@ is_trans_readonly_and_warn (const Transaction *trans) reason = xaccTransGetReadOnly (trans); if (reason) { - dialog = gtk_message_dialog_new(NULL, + dialog = gtk_message_dialog_new(parent, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, @@ -848,7 +848,7 @@ gsr_default_reinit_handler( GNCSplitReg *gsr, gpointer data ) reg = gnc_ledger_display_get_split_register( gsr->ledger ); trans = gnc_split_register_get_current_trans (reg); - if (is_trans_readonly_and_warn(trans)) + if (is_trans_readonly_and_warn(GTK_WINDOW(gsr->window), trans)) return; dialog = gtk_message_dialog_new(GTK_WINDOW(gsr->window), GTK_DIALOG_DESTROY_WITH_PARENT, @@ -1056,7 +1056,7 @@ gsr_default_associate_handler (GNCSplitReg *gsr, gboolean uri_is_file) if (cursor_class == CURSOR_CLASS_NONE) return; - if (is_trans_readonly_and_warn (trans)) + if (is_trans_readonly_and_warn (GTK_WINDOW(gsr->window), trans)) return; // get the existing uri @@ -1183,7 +1183,7 @@ gsr_default_delete_handler( GNCSplitReg *gsr, gpointer data ) if (cursor_class == CURSOR_CLASS_NONE) return; - if (is_trans_readonly_and_warn(trans)) + if (is_trans_readonly_and_warn(GTK_WINDOW(gsr->window), trans)) return; /* On a split cursor, just delete the one split. */ diff --git a/gnucash/gtkbuilder/dialog-account.glade b/gnucash/gtkbuilder/dialog-account.glade index 9569ca71ad..5a9c21007c 100644 --- a/gnucash/gtkbuilder/dialog-account.glade +++ b/gnucash/gtkbuilder/dialog-account.glade @@ -195,7 +195,7 @@ False False - 1 + 2 @@ -302,7 +302,7 @@ False False - 2 + 1 diff --git a/gnucash/python/pycons/ishell.py b/gnucash/python/pycons/ishell.py index aa84467b67..371f32c4a4 100644 --- a/gnucash/python/pycons/ishell.py +++ b/gnucash/python/pycons/ishell.py @@ -125,10 +125,10 @@ class Shell: def shell(self, cmd,verbose=0,debug=0,header=''): stat = 0 - if verbose or debug: print header+cmd + if verbose or debug: print(header+cmd) if not debug: input, output = os.popen4(cmd) - print output.read() + print(output.read()) output.close() input.close() diff --git a/gnucash/python/pycons/shell.py b/gnucash/python/pycons/shell.py index 6569d17cb0..d50043eb95 100644 --- a/gnucash/python/pycons/shell.py +++ b/gnucash/python/pycons/shell.py @@ -153,7 +153,7 @@ class Shell: console.write (buf, 'output') if len(buf) < 256: break # Command output - print `r` + print(`r`) except SyntaxError: exec self.command in self.globals except: @@ -166,8 +166,8 @@ class Shell: tb = sys.exc_traceback if tb: tb=tb.tb_next - traceback.print_exception (sys.exc_type, sys.exc_value, tb) + traceback.print(_exception (sys.exc_type, sys.exc_value, tb)) except: sys.stderr, console.stderr = console.stderr, sys.stderr - traceback.print_exc() + traceback.print(_exc()) diff --git a/gnucash/register/ledger-core/gnc-ledger-display.c b/gnucash/register/ledger-core/gnc-ledger-display.c index ea390ee1e1..c84c1f7cd7 100644 --- a/gnucash/register/ledger-core/gnc-ledger-display.c +++ b/gnucash/register/ledger-core/gnc-ledger-display.c @@ -594,6 +594,7 @@ close_handler (gpointer user_data) return; gnc_unregister_gui_component (ld->component_id); + ld->component_id = NO_COMPONENT; if (ld->destroy) ld->destroy (ld); diff --git a/gnucash/register/ledger-core/split-register-model.c b/gnucash/register/ledger-core/split-register-model.c index 48d7a0b2ac..bd132953ca 100644 --- a/gnucash/register/ledger-core/split-register-model.c +++ b/gnucash/register/ledger-core/split-register-model.c @@ -1957,7 +1957,7 @@ gnc_split_register_get_security_io_flags (VirtualLocation virt_loc, } static gboolean -xaccTransWarnReadOnly (const Transaction *trans) +xaccTransWarnReadOnly (GtkWidget *parent, const Transaction *trans) { GtkWidget *dialog; const gchar *reason; @@ -1970,7 +1970,7 @@ xaccTransWarnReadOnly (const Transaction *trans) reason = xaccTransGetReadOnly (trans); if (reason) { - dialog = gtk_message_dialog_new(NULL, + dialog = gtk_message_dialog_new(GTK_WINDOW(parent), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, @@ -2007,7 +2007,7 @@ gnc_split_register_confirm (VirtualLocation virt_loc, gpointer user_data) return TRUE; trans = xaccSplitGetParent (split); - if (xaccTransWarnReadOnly(trans)) + if (xaccTransWarnReadOnly(gnc_split_register_get_parent(reg), trans)) return FALSE; if (!xaccTransHasReconciledSplits (trans)) diff --git a/gnucash/ui/gnc-sxed-window-ui-full.xml b/gnucash/ui/gnc-sxed-window-ui-full.xml index 65ea884554..df8a774d97 100644 --- a/gnucash/ui/gnc-sxed-window-ui-full.xml +++ b/gnucash/ui/gnc-sxed-window-ui-full.xml @@ -45,7 +45,6 @@ - diff --git a/libgnucash/app-utils/date-utilities.scm b/libgnucash/app-utils/date-utilities.scm index 1729d0869a..1e6b2f6a8d 100644 --- a/libgnucash/app-utils/date-utilities.scm +++ b/libgnucash/app-utils/date-utilities.scm @@ -634,10 +634,10 @@ (set-tm:mon now 11) (set-tm:year now (- (tm:year now) 1))) (set-tm:mon now (- (tm:mon now) 1))) - (let ((month-length (gnc:days-in-month (+ (tm:mon now) 1) - (+ (tm:year now) 1900)))) - (if (> month-length (tm:mday now)) - (set-tm:mday now month-length)) + (let ((month-days (gnc:days-in-month (+ (tm:mon now) 1) + (+ (tm:year now) 1900)))) + (if (< month-days (tm:mday now)) + (set-tm:mday now month-days)) (set-tm:isdst now -1) (gnc-mktime now)))) @@ -650,7 +650,7 @@ (set:tm-mon now (- (tm:mon now) 3)) (let ((month-days (gnc:days-in-month (+ (tm:mon now) 1) (+ (tm:year now) 1900)))) - (if (> month-days (tm:mday now)) + (if (< month-days (tm:mday now)) (set-tm:mday now month-days)) (set-tm:isdst now -1) (gnc-mktime now)))) @@ -664,7 +664,7 @@ (set:tm-mon now (- (tm:mon now) 6)) (let ((month-days (gnc:days-in-month (+ (tm:mon now) 1) (+ (tm:year now) 1900)))) - (if (> month-days (tm:mday now)) + (if (< month-days (tm:mday now)) (set-tm:mday now month-days)) (set-tm:isdst now -1) (gnc-mktime now)))) @@ -673,8 +673,8 @@ (let ((now (gnc-localtime (current-time)))) (set:tm-year now (- (tm:year now) 1)) (let ((month-days (gnc:days-in-month (+ (tm:mon now) 1) - (+ (tm:year now) 1900)))) - (if (> month-days (tm:mday now)) + (+ (tm:year now) 1900)))) + (if (< month-days (tm:mday now)) (set-tm:mday now month-days)) (set-tm:isdst now -1) (gnc-mktime now)))) @@ -686,10 +686,10 @@ (set-tm:mon now 0) (set-tm:year now (+ (tm:year now) 1))) (set-tm:mon now (+ (tm:mon now) 1))) - (let ((month-length (gnc:days-in-month (+ (tm:mon now) 1) - (+ (tm:year now) 1900)))) - (if (> month-length (tm:mday now)) - (set-tm:mday now month-length)) + (let ((month-days (gnc:days-in-month (+ (tm:mon now) 1) + (+ (tm:year now) 1900)))) + (if (< month-days (tm:mday now)) + (set-tm:mday now month-days)) (set-tm:isdst now -1) (gnc-mktime now)))) @@ -699,10 +699,10 @@ (begin (set:tm-mon now (- (tm:mon now) 9)) (set:tm-year now (+ (tm:year now) 1)) - (set:tm-mon now (+ (tm:mon now) 3)))) + (set:tm-mon now (+ (tm:mon now) 3)))) (let ((month-days (gnc:days-in-month (+ (tm:mon now) 1) (+ (tm:year now) 1900)))) - (if (> month-days (tm:mday now)) + (if (< month-days (tm:mday now)) (set-tm:mday now month-days)) (set-tm:isdst now -1) (gnc-mktime now)))) @@ -713,10 +713,10 @@ (begin (set:tm-mon now (- (tm:mon now) 6)) (set:tm-year now (+ (tm:year now) 1)) - (set:tm-mon now (+ (tm:mon now) 6)))) + (set:tm-mon now (+ (tm:mon now) 6)))) (let ((month-days (gnc:days-in-month (+ (tm:mon now) 1) (+ (tm:year now) 1900)))) - (if (> month-days (tm:mday now)) + (if (< month-days (tm:mday now)) (set-tm:mday now month-days)) (set-tm:isdst now -1) (gnc-mktime now)))) @@ -725,8 +725,8 @@ (let ((now (gnc-localtime (current-time)))) (set:tm-year now (+ (tm:year now) 1)) (let ((month-days (gnc:days-in-month (+ (tm:mon now) 1) - (+ (tm:year now) 1900)))) - (if (> month-days (tm:mday now)) + (+ (tm:year now) 1900)))) + (if (< month-days (tm:mday now)) (set-tm:mday now month-days)) (set-tm:isdst now -1) (gnc-mktime now)))) diff --git a/libgnucash/app-utils/gnc-component-manager.c b/libgnucash/app-utils/gnc-component-manager.c index e788b48995..c32be015df 100644 --- a/libgnucash/app-utils/gnc-component-manager.c +++ b/libgnucash/app-utils/gnc-component-manager.c @@ -690,6 +690,8 @@ gnc_gui_refresh_internal (gboolean force) #endif list = find_component_ids_by_class (NULL); + // reverse the list so class GncPluginPageRegister is before register-single + list = g_list_reverse (list); for (node = list; node; node = node->next) {