[glom/sqlbuilder2: 66/67] Merge branch 'master' into sqlbuilder2



commit c3a3e3b40dc4311b28dfab89c7acf583f8de7c29
Merge: 27fea35 bc782ab
Author: Murray Cumming <murrayc murrayc com>
Date:   Mon Mar 29 18:10:39 2010 +0200

    Merge branch 'master' into sqlbuilder2
    
    Conflicts:
    	ChangeLog
    	glom/libglom/python_embed/py_glom_relatedrecord.cc

 ChangeLog                                          |  488 +++
 Makefile_glom.am                                   |   10 +-
 Makefile_libglom.am                                |    3 +
 Makefile_tests.am                                  |   15 +-
 NEWS                                               |   48 +
 configure.ac                                       |    8 +-
 docs/user-guide/de/de.po                           |  793 +++--
 examples/example_smallbusiness.glom                |   75 +-
 glom/application.cc                                |  371 ++-
 glom/application.h                                 |   37 +-
 glom/bakery/app_withdoc.cc                         |   51 +-
 glom/base_db.cc                                    |   40 +-
 glom/base_db_table_data.cc                         |   16 +-
 glom/box_withbuttons.cc                            |    2 +-
 glom/dialog_connection.cc                          |   12 +-
 glom/dialog_existing_or_new.cc                     |    3 +-
 glom/filechooser_export.cc                         |    7 +-
 glom/frame_glom.cc                                 |  180 +-
 glom/frame_glom.h                                  |   38 +-
 glom/glom.glade                                    |  691 ++--
 glom/glom_developer.glade                          |  699 +++--
 glom/glom_privs.cc                                 |    4 +-
 glom/libglom/connectionpool.h                      |    2 +-
 .../connectionpool_backends/postgres_self.cc       |    8 +-
 glom/libglom/connectionpool_backends/sqlite.cc     |    9 +-
 .../data_structure/layout/fieldformatting.cc       |   10 +-
 .../data_structure/layout/fieldformatting.h        |   13 +-
 glom/libglom/data_structure/system_prefs.h         |    3 +-
 glom/libglom/document/bakery/document.cc           |   38 +-
 glom/libglom/document/bakery/document.h            |   16 +-
 glom/libglom/document/bakery/document_xml.cc       |   12 +-
 glom/libglom/document/document.cc                  |   31 +-
 glom/libglom/document/document.h                   |   69 +-
 glom/libglom/python_embed/py_glom_record.cc        |   15 +-
 glom/libglom/python_embed/py_glom_record.h         |   10 +
 glom/libglom/python_embed/py_glom_relatedrecord.cc |    5 +-
 glom/libglom/python_embed/py_glom_ui.cc            |   83 +
 glom/libglom/python_embed/py_glom_ui.h             |   68 +
 glom/libglom/python_embed/py_glom_ui_callbacks.h   |   68 +
 glom/libglom/utils.cc                              |   28 +-
 glom/libglom/utils.h                               |   12 +-
 glom/main.cc                                       |   20 +-
 glom/mode_data/box_data.cc                         |    8 +-
 glom/mode_data/box_data.h                          |   11 +-
 glom/mode_data/box_data_calendar_related.cc        |    4 +-
 glom/mode_data/box_data_details.cc                 |   67 +-
 glom/mode_data/box_data_details.h                  |   16 +-
 glom/mode_data/box_data_list.cc                    |   32 +-
 glom/mode_data/box_data_list.h                     |    2 +-
 glom/mode_data/box_data_list_related.cc            |   31 +-
 glom/mode_data/box_data_list_related.h             |    2 +-
 glom/mode_data/box_data_portal.cc                  |    4 +-
 glom/mode_data/flowtablewithfields.cc              |  119 +-
 glom/mode_data/flowtablewithfields.h               |   29 +-
 glom/mode_data/notebook_data.cc                    |   56 +-
 glom/mode_data/notebook_data.h                     |   24 +-
 glom/mode_design/dialog_database_preferences.cc    |   70 +-
 glom/mode_design/dialog_database_preferences.h     |    5 +
 glom/mode_design/fields/box_db_table_definition.cc |   14 +-
 glom/mode_design/fields/dialog_fielddefinition.cc  |   10 +-
 glom/mode_design/iso_codes.cc                      |    2 +-
 glom/mode_design/layout/dialog_layout_export.cc    |    2 +-
 .../layout/layout_item_dialogs/box_formatting.cc   |   17 +-
 .../layout/layout_item_dialogs/box_formatting.h    |    1 +
 .../layout_item_dialogs/dialog_buttonscript.cc     |   32 +-
 .../layout_item_dialogs/dialog_buttonscript.h      |    6 +-
 .../layout_item_dialogs/dialog_field_layout.cc     |   10 +-
 .../layout_item_dialogs/dialog_formatting.cc       |   10 +-
 .../print_layouts/dialog_text_formatting.cc        |   10 +-
 .../dialog_relationships_overview.cc               |    4 +-
 glom/navigation/box_tables.cc                      |   19 +-
 glom/navigation/box_tables.h                       |    1 -
 glom/notebook_glom.cc                              |    2 +-
 glom/print_layout/canvas_print_layout.cc           |   11 +-
 glom/python_embed/glom_python.cc                   |  330 +-
 glom/python_embed/glom_python.h                    |   12 +-
 glom/python_embed/python_module/py_glom_module.cc  |    9 +
 glom/python_embed/python_ui_callbacks.cc           |   76 +
 glom/python_embed/python_ui_callbacks.h            |   47 +
 glom/report_builder.cc                             |   22 +-
 glom/utility_widgets/buttonglom.cc                 |    6 +-
 glom/utility_widgets/buttonglom.h                  |    4 +-
 .../utility_widgets/canvas/canvas_image_movable.cc |    2 +-
 glom/utility_widgets/checkglom.cc                  |    6 +-
 glom/utility_widgets/checkglom.h                   |    4 +-
 glom/utility_widgets/combo_as_radio_buttons.cc     |  302 ++
 glom/utility_widgets/combo_as_radio_buttons.h      |   95 +
 glom/utility_widgets/combochoices.cc               |   56 +
 .../{comboglomchoicesbase.h => combochoices.h}     |   36 +-
 ...choicesbase.cc => combochoiceswithtreemodel.cc} |   19 +-
 ...omchoicesbase.h => combochoiceswithtreemodel.h} |   28 +-
 glom/utility_widgets/comboentryglom.cc             |   14 +-
 glom/utility_widgets/comboentryglom.h              |   10 +-
 glom/utility_widgets/comboglom.cc                  |   10 +-
 glom/utility_widgets/comboglom.h                   |   10 +-
 glom/utility_widgets/datawidget.cc                 |   48 +-
 glom/utility_widgets/datawidget.h                  |    6 +-
 glom/utility_widgets/db_adddel/db_adddel.cc        |   16 +-
 glom/utility_widgets/db_adddel/db_adddel.h         |    4 +-
 .../utility_widgets/db_adddel/glom_db_treemodel.cc |    2 +-
 glom/utility_widgets/entryglom.cc                  |    6 +-
 glom/utility_widgets/entryglom.h                   |    4 +-
 .../filechooserdialog_saveextras.cc                |    4 +-
 glom/utility_widgets/flowtable.cc                  |   87 +-
 glom/utility_widgets/flowtable.h                   |   25 +-
 glom/utility_widgets/flowtable_dnd.cc              |   68 +-
 glom/utility_widgets/imageglom.cc                  |    8 +-
 glom/utility_widgets/imageglom.h                   |    4 +-
 glom/utility_widgets/labelglom.cc                  |    6 +-
 glom/utility_widgets/labelglom.h                   |    4 +-
 glom/utility_widgets/layoutwidgetbase.cc           |    2 +-
 glom/utility_widgets/layoutwidgetbase.h            |    4 +-
 glom/utility_widgets/layoutwidgetmenu.cc           |    2 +-
 glom/utility_widgets/notebookglom.cc               |    4 +-
 glom/utility_widgets/notebookglom.h                |    4 +-
 glom/utility_widgets/notebooklabelglom.cc          |    6 +-
 glom/utility_widgets/notebooklabelglom.h           |    4 +-
 glom/utility_widgets/placeholder-glom.cc           |   28 +-
 glom/utility_widgets/placeholder-glom.h            |    2 +-
 glom/utility_widgets/textviewglom.cc               |    6 +-
 glom/utility_widgets/textviewglom.h                |    4 +-
 glom/utils_ui.cc                                   |    4 +-
 glom/window_boxholder.cc                           |    6 +
 glom/xsl_utils.cc                                  |    3 +-
 po/LINGUAS                                         |    1 +
 po/cs.po                                           |  856 +++--
 po/de.po                                           | 1231 ++++---
 po/es.po                                           |  450 ++--
 po/fr.po                                           | 2029 ++++++-----
 po/pt.po                                           | 3971 +++++++++++++++++++-
 po/ru.po                                           | 3545 +++++++++++++++++
 po/sl.po                                           |  906 +++---
 ...e_validation.sh => test_dtd_file_validation.sh} |    0
 tests/test_glade_file_validation.sh                |    9 +
 tests/test_python_execute_script.cc                |  103 +
 135 files changed, 14479 insertions(+), 4833 deletions(-)
---
diff --cc ChangeLog
index 02dad9d,e37f9d0..6eae219
--- a/ChangeLog
+++ b/ChangeLog
@@@ -1,40 -1,459 +1,528 @@@
++<<<<<<<
++2010-02-27  Murray Cumming  <murrayc murrayc com>
++
++  Increase required version of libgdamm.
++  
++	* configure.ac: Increase libgdamm dependency to the last one that doesn't 
++	need libgda 4.1/4.2. We actually need some API that was not in the older one.
++
++2010-02-27  Murray Cumming  <murrayc murrayc com>
++
++  Revert use of SqlBuilder because it requires libgda 4.1,
++  which will not be packaged by the upcoming Ubuntu Lucid, which is an 
++  important version of an important distro.
++   
++2010-02-27  Murray Cumming  <murrayc murrayc com>
++
++	More uses of SqlBuilder for SELECT statements.
++
++2010-02-27  Murray Cumming  <murrayc murrayc com>
++
++  Fix runtime problems with the use of SqlBuilder.
++  
++	* glom/base_db.[h|cc]: query_execute_select(), query_execute(): Catch more 
++  errors and output better debug and error text.
++	get_database_preferences(): Don't bother catching exceptions already caught 
++	by query_execute*().
++	add_standard_tables(): Fix a typo in the SQL query.
++	insert_example_data(): Work around an inability in GdaSqlBuilder to INSERT 
++	a NULL value. I have asked about it on the mailing list.
++
++=======
+ 2010-03-29  Murray Cumming  <murrayc murrayc com>
+ 
+     Avoid Operation Not Supported warnings at startup.
+ 
+ 	* glom/application.cc:
+ 	* glom/bakery/app_withdoc.cc:
+ 	* glom/libglom/connectionpool_backends/postgres_self.cc:
+ 	* glom/libglom/connectionpool_backends/sqlite.cc:
+ 	* glom/libglom/document/bakery/document.cc:
+ 	* glom/libglom/utils.cc:
+ 	* glom/xsl_utils.cc: Avoid creating a Gio::File() from an empty URI,
+     avoiding useless stdout warnings at startup.
+ 
+ 2010-03-29  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Edit Field Definition Dialog adjustments.
+ 
+ 	* glom/glom_developer.glade: Update alignment and spacings, add mnemonics.
+ 	* glom/mode_design/fields/box_db_table_definition.cc: Set window icon.
+ 
+ 2010-03-29  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Export Format dialog adjustments.
+ 
+ 	* glom/filechooser_export.cc: Set icon name for export format dialog.
+ 	* glom/glom_developer.glade: (Export Format) Remove frame, move Add
+ 	button to the start.
+ 	* glom/mode_design/layout/dialog_layout_export.cc: Rename treeview
+ 	header to "Fields" to replace the label.
+ 
+ 2010-03-29  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Print Layouts dialog adjustments.
+ 
+ 	* glom/frame_glom.cc: Set title and transient for Print Layouts dialog.
+ 	* glom/glom_developer.glade: Remove the frame from Print Layouts dialog.
+ 
+ 2010-03-26  Murray Cumming  <murrayc murraycs com>
+ 
+ 	Say when a chosen file doen't exist, and remove it from the history.
+ 
+ 	* glom/libglom/document/bakery/document.[h|cc]: Add an enum for
+     standard failure_codes, including a last enum values that custom codes
+     should start after.
+     read_from_disk(): Set a failure_code output variable here too, so we
+     can detect non-existant files.
+ 	* glom/libglom/document/document.h: Start the custom code after the last
+     standard one.
+ 	* glom/bakery/app_withdoc.cc: open_document(): Remove non-existant
+     files from the recent files history.
+ 	* glom/application.cc: ui_warning_load_failed(): Say if the file could not
+     be found, instead of being mysterious. This happens for me often for
+     recent files that I have deleted.
+ 
+ 2010-03-26  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Adjust file chooser dialogs.
+ 
+ 	* glom/dialog_existing_or_new.cc: Adjust title of file open dialog,
+ 	set glom icon.
+ 	* glom/utility_widgets/filechooserdialog_saveextras.cc: Set glom icon.
+ 
+ 2010-03-26  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Fix filechooser title label.
+ 
+ 	* glom/utility_widgets/filechooserdialog_saveextras.cc: Add colon and
+ 	mnemonic to "Title" label.
+ 
+ 2010-03-26  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Fix column spacing in connection dialog.
+ 
+ 	* glom/glom.glade: Set column spacing in connection dialog to 12px.
+ 
+ 2010-03-26  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Connection dialog adjustments.
+ 
+ 	* glom/dialog_connection.cc: Add glom icon and remove maemo title hack
+ 	as primary text does not exist anymore.
+ 	* glom/glom.glade: Remove double title from connection dialog
+ 	and make it HIG/GNOME conform.
+ 
+ 2010-03-26  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Export dialog adjustments.
+ 
+ 	* glom/filechooser_export.cc: Add glom icon and set mnemonic for Export
+ 	button.
+ 
+ 2010-03-26  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Adjustments for Import dialog.
+ 
+ 	* glom/frame_glom.cc: Set window icon and update title text.
+ 
+ 2010-03-26  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Adjustments for Tables dialog.
+ 
+ 	* glom/application.cc: Use gtkmm API to set document icon.
+ 	* glom/frame_glom.cc: Change Tables dialog title to "Edit Tables" to
+ 	match the command name.
+ 	* glom/glom.glade: Remove the frame.
+ 	* glom/navigation/box_tables.cc: Change column name from Tables to Table.
+ 	* glom/navigation/box_tables.h: Remove frame member.
+ 	* glom/window_boxholder.cc: Set icon and default position to center on
+ 	parent.
+ 
+ 2010-03-25  Murray Cumming  <murrayc murrayc com>
+ 
+     Glade files: Remove adjustment objects, simplifying window instantiation.
+ 
+ 	* glom/glom_developer.glade: Remove useless (default, empty) adjustment
+     objects, so we can load the windows with GtkBuilder without specifying
+     them. Recent versions of Glade no longer seem to create these when they
+     would just have default values.
+ 	* glom/base_db.cc:
+ 	* glom/frame_glom.cc:
+ 	* glom/glom.glade:
+ 	* glom/mode_design/fields/dialog_fielddefinition.cc:
+ 	* glom/mode_design/layout/layout_item_dialogs/dialog_field_layout.c
+ 	c:
+ 	* glom/mode_design/layout/layout_item_dialogs/dialog_formatting.cc:
+ 	* glom/mode_design/print_layouts/dialog_text_formatting.cc:
+     Don't provide the id of the adjustment, removing the silly workaround.
+ 
+ 2010-03-24  Daniel Borgmann  <danielb openismus com>
+ 
+ 	Don't show error dialog when user cancels template creation.
+ 
+ 	* glom/application.cc: Display error message when trying to create
+ 	a document from template in client-only-mode.
+ 	* glom/bakery/app_withdoc.cc: Don't display error message if the
+ 	document is rejected, let the application decide about it.
+ 
+ 1.13.9:
+ 
+ 2010-03-23  Murray Cumming  <murrayc murrayc com>
+ 
+     Refactored combo classes.
+ 
+ 	* glom/utility_widgets/comboglomchoicesbase.[h|cc]:
+     Split into combochoices.[h|cc] and combochoiceswithtreemodel.[h|cc] so
+     that combo_as_radio_buttons.[h|cc] doesn't need to have an unused treemodel.
+ 
+ 2010-03-23  Murray Cumming  <murrayc murrayc com>
+ 
+     Formatting: Choices: Add a Display as radio buttons option.
+ 
+ 	* glom/glom_developer.glade: formatting: choices: Add a Show As Radio
+     Buttons checkbox.
+ 	* glom/libglom/data_structure/layout/fieldformatting.[h|cc]:
+     set/get_choices_restricted(): Add a show_as_radio_buttons output parameter.
+ 	* glom/libglom/document/document.cc:
+     load_after_layout_item_formatting(), save_after_layout_item_formatting():
+     load and save the new formatting detail.
+ 	* glom/mode_design/layout/layout_item_dialogs/box_formatting.[h|cc]:
+     Handle the new checkbox and make sure that it is only sensitive when
+     the choices are restricted, because radio buttons provide no way to enter
+     freeform data.
+ 	* glom/utility_widgets/comboglomchoicesbase.h: Make set_choices() and
+     set_choices_with_second() virtual.
+     * glom/utility_widgets/combo_as_radio_buttons.[h|cc]: A new widget that is
+     a vbbox of radio buttons, with a combo-like API.
+ 	* Makefile_glom.am: Mention the new files.
+ 	* glom/utility_widgets/datawidget.cc: Refactor some repeated code into
+     create_combo_widget_for_field() and create the radiobuttons widget when
+     necessary.
+ 
+ 2010-03-22  Murray Cumming  <murrayc murrayc com>
+ 
+     Fix the distcheck. Don't use deprecated gtkmm API.
+ 
+ 	* glom/utility_widgets/flowtable.cc:
+ 	* glom/utility_widgets/flowtable_dnd.cc:
+ 	* glom/utility_widgets/placeholder-glom.cc: Adapt to deprecated gtkmm API.
+     Use get_has_window() and set_has_window() instead of get_flags(),
+     unset_flags() and set_flags().
+ 
+ 2010-03-21  Murray Cumming  <murrayc murrayc com>
+ 
+     Small fixes to glade file.
+ 
+ 	* glom/glom_developer.glade: Add some still-missing vbox orientation=vertical
+ 	lines.
+ 
+ 2010-03-19  Daniel Borgmann <danielb openismus com>
+ 
+ 	* configure.ac: Make Glom build with autoconf 2.65.
+ 	Patch from Fryderyk Dziarmagowski in GNOME bug #613179.
+ 
+ 2010-03-16  David King  <davidk openismus com>
+ 
+ 	Fix GtkVBox orientation in GtkBuilder files
+ 
+ 	* glom/glom.glade:
+ 	* glom/glom_developer.glade: Manually set the orientation of GtkVBox
+ 	objects specified in the GtkBuilder files to â??verticalâ??. See GNOME bug
+ 	#587256 for details of the issue with Glade.
+ 
+ 2010-03-16  Murray Cumming  <murrayc murrayc com>
+ 
+   Tests: Check that the .glade files are valid XML.
+ 
+   * Makefile_tests.am:
+ 	* tests/test_glade_file_validation.sh: Add this text that the .glade files
+ 	are basically valid XML. It would be nice to have a Glade DTD to validate
+ 	them against too.
+ 	We should also check that each top-level widget can be instantiated by
+ 	GtkBuilder.
+ 
+ 2010-03-16  Murray Cumming  <murrayc murrayc com>
+ 
+   Add a startup script feature.
+ 
+   * libglom/document/document.cc: Added get/set_startup_script().
+   load_after(), save_before(): Load and save the startup script.
+ 
+   * glom_developer.glade:
+   * glom/mode_design/dialog_database_preferences.[h|cc]: Add a startup script tab.
+ 
+   * libglom/python_embed/py_glom_ui.h: Move PythonUICallbacks into its own
+   py_glom_ui_callbacks.h header.
+   * glom/python_embed/python_ui_callbacks.[h|cc]: Add this derived callbacks
+   class that has handlers that call methods in the application.
+   * glom/mode_data/box_data.cc: execute_button_script(): Use the new callbacks
+   class instead of using member methods here.
+   * glom/application.cc: on_document_load(): Run the startup script, if any,
+   after loading the document, using the new derived callbacks class.
+ 
+   * Makefile_glom.am, Makefile_libglom.am: Mention the new files.
+ 
+ 2010-03-13  David King  <davidk openismus com>
+ 
+ 	Depend on gtkmm >= 2.19.2, fixing GNOME bug #612796
+ 
+ 	* configure.ac: Bump glom gtkmm version requirement to >= 2.19.2 for
+ 	Gtk::ToolPalette. Fixes GNOME bug #612796.
+ 
+ 2010-03-13  David King  <davidk openismus com>
+ 
+ 	Depend on libxml++ >= 2.23.1, fixing GNOME bug#612794
+ 
+ 	* configure.ac: Bump libglom libxml++ version requirement to >= 2.23.1
+ 	for xmlpp::Element::add_child_text_before(). Fixes GNOME bug #612794.
+ 
+ 2010-03-09  Murray Cumming  <murrayc murrayc com>
+ 
+     Initial Dialog: Do not crash sometimes if cancelling the file chooser.
+ 
+ 	* glom/application.cc: offer_new_or_existing(): Show the dialog again if
+     we get a 0 response, because we cannot (yet) prevent the dialog from
+     doing this when the child file chooser dialog is cancelled. Fixes a crash
+     if pressing the Select button instead of double-clicking on an item.
+     Bug #612303 (David King)
+ 
+ 1.13.8:
+ 
+ 2010-03-08  Murray Cumming  <murrayc murrayc com>
+ 
+     Slight update of Small Business example.
+ 
+ 	* examples/example_smallbusiness.glom: Resave, with a new record with
+     a picture of a polar bear for use on the www.glom.org website.
+     The picture is from http://www.flickr.com/photos/mape_s/350700095/
+     (Creative-Commons licensed, by Marieke IJsendoorn-Kuijpers)
+ 
+ 2010-03-08  Murray Cumming  <murrayc murrayc com>
+ 
+     Python button scripts: Rename print() to print_layout() and add start_new_record().
+ 
+ 	* glom/application.[h|cc]
+ 	* glom/frame_glom.[h|cc]
+ 	* glom/libglom/python_embed/py_glom_ui.[h|cc]
+ 	* glom/mode_data/box_data.[h|cc]
+ 	* glom/mode_data/box_data_details.[h|cc]
+ 	* glom/mode_data/notebook_data.[h|cc]
+ 	* glom/python_embed/python_module/py_glom_module.cc:
+ 	* tests/test_python_execute_script.cc:
+     Add a ui.start_new_record() python method, and rename ui.print() to
+     ui.print_layout() because print seems to be a python keyword that can't
+     be used as a method name, seen when trying to use it in the unit test.
+ 
+ 2010-03-08  Peter Penz  <ppenz openismus com>
+ 
+ 	Fix the build with exceptions disabled.
+ 
+ 	* glom/libglom/document/bakery/document_xml.cc:
+ 	* glom/mode_design/iso_codes.cc: The exception handling is enabled by the
+     define LIBXMLPP_EXCEPTIONS_ENABLED. But this is a typo, as libxml++ defines
+     LIBXMLCPP_EXCEPTIONS_ENABLED.
+ 
+ 2010-03-05  Murray Cumming  <murrayc murrayc com>
+ 
+     Python button scripts: Add ui.print() and ui.print_reports(report_name).
+ 
+ 	* glom/application.[h|cc]: Add print() and print_report(), calling
+     methods in the frame widget.
+ 	* glom/libglom/python_embed/py_glom_ui.[h|cc]: Add new print() and
+     print_report() methods, adding callback slots for use by Glom.
+ 	* glom/python_embed/python_module/py_glom_module.cc: Register the new
+     Python methods.
+ 	* glom/mode_data/box_data.[h|cc]: execute_button_script(): Handle the
+     new signals, calling the new methods in Application.
+ 
+ 2010-03-07  Murray Cumming  <murrayc murrayc com>
+ 
+     Details: Align widgets in other columns too.
+ 
+ 	* glom/utility_widgets/flowtable.[h|cc]: Added get_columns_count().
+ 	* glom/mode_data/flowtablewithfields.[h|cc]: apply_size_group_to_label():
+ 	Change this to apply_size_groups_to_label().
+ 	align_child_group_labels(): Create a size group for each possible column,
+ 	and call apply_size_groups_to_label() with them.
+ 
+ 2010-03-06  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Details: Align widgets in the first columns of neighbouring layout groups.
+ 
+ 	* glom/utility_widgets/flowtable.[h|cc]: Added get_column_for_first_widget(),
+ 	to discover what column a widget is in, and whether it has even been assigned
+ 	to a column yet (if the size has been allocated already.)
+ 	FlowTableItem: Remember whether the item has a column number and what it is.
+ 	on_size_allocate(): Remember the column numbers of items for later retrieval.
+ 	* glom/mode_data/flowtablewithfields.[h|cc]: Info, add_field_at_position():
+ 	Store the pointer to eventbox too, so we can later discover its column from
+ 	the base FlowTable.
+ 	Add align_child_group_labels(), to make all first-level labels in child
+ 	flowtables share a single Gtk::SizeGroup, making them align.
+ 	Add apply_size_group_to_labels() to actually add the labels to the size group.
+ 	add_layout_group_at_position(): Call align_child_group_labels() on new
+ 	sub-flowtables.
+ 	on_size_allocate(): After the base class has allocated the spaces for the
+ 	child widgets, after it therefore knows the column positions for the widgets,
+ 	call apply_size_group_to_labels() to make them align.
+ 	* glom/mode_data/box_data_details.cc: create_layout(): Call
+ 	align_child_group_labels() to align items in top-level groups.
+ 
+ 2010-03-06  Murray Cumming  <murrayc murrayc com>
+ 
+   Details: Do not make field widgets too wide, so this fits on a laptop screen.
+ 
+ 	* glom/utils_ui.cc: get_suitable_field_width_for_widget(): Do not add 150
+ 	to all calculated widths. I don't know why this code ever did that.
+ 
+ 1.13.7:
+ 
+ 2010-02-28  Murray Cumming  <murrayc murrayc com>
+ 
+     Python button scripts: Avoid a crash with buttons in lists.
+ 
+ 	* glom/mode_data/box_data_list.[h|cc]: on_adddel_script_button_clicked():
+ 	Run the script in the (existing) on_script_button_idle() idle handler because
+ 	the script can cause the cell (that is emitting the signal) to be destroyed,
+ 	by navigating to a different table. This fixes that crash.
+ 	* glom/mode_data/box_data_list_related.cc: Do the same here.
+ 	* glom/mode_data/notebook_data.cc: on_list_user_requested_details(): Use
+ 	the same idle handler trick here, just in case.
+ 
+ 2010-02-28  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Added unit test for the new button script ui python API.
+ 
+ 	* Makefile_tests.am:
+ 	* tests/test_python_execute_script.cc: Added unit test for the new button
+ 	script ui python API.
+ 
+ 2010-02-28  Murray Cumming  <murrayc murrayc com>
+ 
+     PyGlomUI: Simplify the callbacks object.
+ 
+ 	* glom/libglom/python_embed/py_glom_ui.[h|cc]: Use public sigc::slots instead
+ 	  of signals, to simplify this.
+ 	* glom/mode_data/box_data.cc
+ 	  Box_Data::execute_button_script(): Adapt.
+ 
+ 1.13.6:
+ 
+ 2010-02-28  Murray Cumming  <murrayc murrayc com>
+ 
+   Fix the python function tests.
+ 
+ 	* glom/python_embed/glom_python.cc
+ 	glom_execute_python_function_implementation,
+ 	glom_evaluate_python_function_implementation: Import the glom python module
+ 	before trying to create a boost::python::object(new PyGlomRecord), to avoid
+ 	an exception in the tests.
+ 
+ 2010-02-28  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Many files: Rename App_Glom to Application (in namespace Glom).
+ 
+ 2010-02-28  Murray Cumming  <murrayc murrayc com>
+ 
+   Python button scripts: Add show_table_details() and show_table_list().
+ 
+ 	* Makefile_libglom.am:
+ 	* glom/python_embed/python_module/py_glom_module.cc:
+ 	* glom/libglom/python_embed/py_glom_ui.[h|cc]: Added a PyGlomUI object
+ 	that can be passed to python functions in addition to the record object,
+ 	with methods to navigate in the UI. So far there is just
+ 	show_table_details() and show_table_list().
+ 	* glom/glom_developer.glade: Script editor window: Mention the extra ui
+ 	parameter.
+ 	* glom/python_embed/glom_python.[h|cc]: Add a callback object parameter so
+ 	scripts can tell the caller to change things in the UI.
+   * glom/frame_glom.h: Made show_table() public so that the Application can
+ 	call it.
+ 	* glom/application.[h|cc]: Add show_table_details() and add_show_list()
+ 	methods for the callbacks to call.
+ 	* glom/mode_data/box_data.[h|cc]: Handle the callback signals, to actually do
+ 	the navigation when a python script requests it.
+ 	* glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.cc: Adapted.
+ 
+ 2010-02-27  Murray Cumming  <murrayc murrayc com>
+ 
+   Python: Prevent field calculations from changing the data in other fields.
+ 
+ 	* glom/libglom/python_embed/py_glom_record.[h|cc]: Added set_read_only().
+ 	* glom/python_embed/glom_python.[h|cc]:
+ 	glom_evaluate_python_function_implementation(): Add a bool read_only
+ 	parameter that defaults to true.
+ 	glom_execute_python_function_implementation(): Pass read_only=false so
+ 	scripts can write data to the database via the record object.
+ 
+ 2010-02-27  Murray Cumming  <murrayc murrayc com>
+ 
+   Increase required version of libgdamm.
+ 
+ 	* configure.ac: Increase libgdamm dependency to the last one that doesn't
+ 	need libgda 4.1/4.2. We actually need some API that was not in the older one.
+ 
+ 2010-02-27  Murray Cumming  <murrayc murrayc com>
+ 
+   Revert use of SqlBuilder because it requires libgda 4.1,
+   which will not be packaged by the upcoming Ubuntu Lucid, which is an
+   important version of an important distro.
+ 
+ 2010-02-27  Murray Cumming  <murrayc murrayc com>
+ 
+ 	More uses of SqlBuilder for SELECT statements.
+ 
+ 2010-02-27  Murray Cumming  <murrayc murrayc com>
+ 
+   Fix runtime problems with the use of SqlBuilder.
+ 
+ 	* glom/base_db.[h|cc]: query_execute_select(), query_execute(): Catch more
+   errors and output better debug and error text.
+ 	get_database_preferences(): Don't bother catching exceptions already caught
+ 	by query_execute*().
+ 	add_standard_tables(): Fix a typo in the SQL query.
+ 	insert_example_data(): Work around an inability in GdaSqlBuilder to INSERT
+ 	a NULL value. I have asked about it on the mailing list.
+ 
++>>>>>>>
 +2010-02-27  Murray Cumming  <murrayc murrayc com>
 +
 +	Use Gnome::Gda::SqlBuilder
 +
 +	* several files: Use Gnome::Gda::SqlBuilder to simplify query building and to 
 +	make it safer.
 +	Much of this work was actually by Johannes Schmid for Openismus.
 +	
 +2010-02-27  Murray Cumming  <murrayc murrayc com>
 +
 +  Increase required version of libgdamm.
 +  
 +	* configure.ac: Increase libgdamm dependency to the last one that doesn't 
 +	need libgda 4.1/4.2. We actually need some API that was not in the older one.
 +
 +2010-02-27  Murray Cumming  <murrayc murrayc com>
 +
 +  Revert use of SqlBuilder because it requires libgda 4.1,
 +  which will not be packaged by the upcoming Ubuntu Lucid, which is an 
 +  important version of an important distro.
 +   
 +2010-02-27  Murray Cumming  <murrayc murrayc com>
 +
 +	More uses of SqlBuilder for SELECT statements.
 +
 +2010-02-27  Murray Cumming  <murrayc murrayc com>
 +
 +  Fix runtime problems with the use of SqlBuilder.
 +  
 +	* glom/base_db.[h|cc]: query_execute_select(), query_execute(): Catch more 
 +  errors and output better debug and error text.
 +	get_database_preferences(): Don't bother catching exceptions already caught 
 +	by query_execute*().
 +	add_standard_tables(): Fix a typo in the SQL query.
 +	insert_example_data(): Work around an inability in GdaSqlBuilder to INSERT 
 +	a NULL value. I have asked about it on the mailing list.
 +
  2010-02-26  Murray Cumming  <murrayc murrayc-desktop>
  
  	Use Gnome::Gda::SqlBuilder
diff --cc glom/base_db.cc
index 7e7d421,fffd102..dfb9fb5
--- a/glom/base_db.cc
+++ b/glom/base_db.cc
@@@ -209,82 -209,29 +209,82 @@@ Glib::RefPtr<Gnome::Gda::DataModel> Bas
  
  
    //Debug output:
-   const App_Glom* app = App_Glom::get_application();
+   const Application* app = Application::get_application();
    if(stmt && app && app->get_show_sql_debug())
    {
 +    const std::string full_query = sqlbuilder_get_full_query(gda_connection, strQuery, params);
 +    std::cout << "Debug: Base_DB::query_execute_select():  " << full_query << std::endl;
 +  }
 +
  #ifdef GLIBMM_EXCEPTIONS_ENABLED
 -    try
 -    {
 -      const Glib::ustring full_query = stmt->to_sql(params);
 -      std::cout << "Debug: Base_DB::query_execute_select():  " << full_query << std::endl;
 -    }
 -    catch(const Glib::Exception& ex)
 -    {
 -      std::cout << "Debug: query string could not be converted to std::cout: " << ex.what() << std::endl;
 -    }
 +  try
 +  {
 +    result = gda_connection->statement_execute_select(stmt, params);
 +  }
 +  catch(const Gnome::Gda::ConnectionError& ex)
 +  {
 +    std::cout << "debug: Base_DB::query_execute_select(): ConnectionError: exception from statement_execute_select(): " << ex.what() << std::endl;
 +  }
 +  catch(const Gnome::Gda::ServerProviderError& ex)
 +  {
 +    std::cout << "debug: Base_DB::query_execute_select(): ServerProviderError exception from statement_execute_select(): code=" << ex.code() << ", message=" << ex.what() << std::endl;
 +  }
 +  catch(const Glib::Error& ex)
 +  {
 +    std::cout << "debug: Base_DB::query_execute_select(): Error exception from statement_execute_select(): " << ex.what() << std::endl;
 +  }
  #else
 -      const Glib::ustring full_query = stmt->to_sql(params, ex);
 -      std::cout << "Debug: Base_DB::query_execute_select():  " << full_query << std::endl;
 -      if (ex.get())
 -        std::cout << "Debug: query string could not be converted to std::cout: " << ex->what() << std::endl;
 +  result = gda_connection->statement_execute_select(stmt, params, ex);
 +  if(ex.get())
 +    std::cout << "debug: Base_DB::query_execute_select(): Glib::Error from statement_execute_select(): " << ex->what() << std::endl;
 +#endif //GLIBMM_EXCEPTIONS_ENABLED
  
 +  if(!result)
 +  {
 +    const std::string full_query = sqlbuilder_get_full_query(gda_connection, strQuery, params);
 +    std::cerr << "Glom  Base_DB::query_execute_select(): Error while executing SQL" << std::endl <<
 +      "  " <<  full_query << std::endl;
 +    handle_error();
 +  }
 +
 +  return result;
 +}
 +
 +//static:
 +Glib::RefPtr<Gnome::Gda::DataModel> Base_DB::query_execute_select(const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder,
 +                                                                  const Glib::RefPtr<const Gnome::Gda::Set>& params)
 +{
 +  Glib::RefPtr<Gnome::Gda::DataModel> result;
 +
 +  //TODO: BusyCursor busy_cursor(get_app_window());
 +
 +#ifdef GLIBMM_EXCEPTIONS_ENABLED
 +  sharedptr<SharedConnection> sharedconnection = connect_to_server();
 +#else
 +  std::auto_ptr<ExceptionConnection> error;
 +  sharedptr<SharedConnection> sharedconnection = connect_to_server(0, error);
 +  if(error.get())
 +  {
 +    g_warning("Base_DB::query_execute_select() failed (query was: %s): %s", strQuery.c_str(), error->what());
 +    // TODO: Rethrow?
 +  }
  #endif
 +  if(!sharedconnection)
 +  {
 +    std::cerr << "Base_DB::query_execute_select(): No connection yet." << std::endl;
 +    return result;
    }
  
 +  Glib::RefPtr<Gnome::Gda::Connection> gda_connection = sharedconnection->get_gda_connection();
  
 +  //Debug output:
-   const App_Glom* app = App_Glom::get_application();
++  const Application* app = Application::get_application();
 +  if(app && app->get_show_sql_debug())
 +  {
 +    const std::string full_query = sqlbuilder_get_full_query(builder, params);
 +    std::cout << "Debug: Base_DB::query_execute_select():  " << full_query << std::endl;
 +  }
 +  
  #ifdef GLIBMM_EXCEPTIONS_ENABLED
    try
    {
@@@ -366,11 -312,27 +366,11 @@@ bool Base_DB::query_execute(const Glib:
  
  
    //Debug output:
-   const App_Glom* app = App_Glom::get_application();
+   const Application* app = Application::get_application();
    if(stmt && app && app->get_show_sql_debug())
    {
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -    try
 -    {
 -      //TODO: full_query still seems to contain ## parameter names,
 -      //though it works for our SELECT queries in query_execute_select():
 -      const Glib::ustring full_query = stmt->to_sql(params);
 -      std::cerr << "Debug: Base_DB::query_execute(): " << full_query << std::endl;
 -    }
 -    catch(const Glib::Exception& ex)
 -    {
 -      std::cerr << "Debug: query string could not be converted to std::cout: " << ex.what() << std::endl;
 -    }
 -#else
 -    const Glib::ustring full_query = stmt->to_sql(params, sql_error);
 +    const std::string full_query = sqlbuilder_get_full_query(gda_connection, strQuery, params);
      std::cerr << "Debug: Base_DB::query_execute(): " << full_query << std::endl;
 -    if (sql_error.get())
 -      std::cerr << "Debug: query string could not be converted to std::cout: " << sql_error->what() << std::endl;
 -#endif
    }
  
  
@@@ -393,66 -355,7 +393,66 @@@
    if(exec_error.get())
    {
      std::cerr << "BaseDB::query_execute: ConnectionError: " << exec_error->what() << std::endl;
 -    const Glib::ustring full_query = stmt->to_sql(params, exec_error);
 +    const std::string full_query = sqlbuilder_get_full_query(gda_connection, stmt, params);
 +    std::cerr << "  full_query: " << full_query << std::endl;
 +    return false;
 +  }
 +#endif
 +  return (exec_retval >= 0);
 +}
 +
 +//static:
 +bool Base_DB::query_execute(const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder,
 +                            const Glib::RefPtr<const Gnome::Gda::Set>& params)
 +{
 +  #ifdef GLIBMM_EXCEPTIONS_ENABLED
 +  sharedptr<SharedConnection> sharedconnection = connect_to_server();
 +#else
 +  std::auto_ptr<ExceptionConnection> error;
 +  sharedptr<SharedConnection> sharedconnection = connect_to_server(0, error);
 +  if(error.get())
 +  {
 +    g_warning("Base_DB::query_execute() failed (query was: %s): %s", strQuery.c_str(), error->what());
 +    // TODO: Rethrow?
 +  }
 +#endif
 +  if(!sharedconnection)
 +  {
 +    std::cerr << "Base_DB::query_execute(): No connection yet." << std::endl;
 +    return false;
 +  }
 +
 +  Glib::RefPtr<Gnome::Gda::Connection> gda_connection = sharedconnection->get_gda_connection();
 +  
 +  //Debug output:
-   const App_Glom* app = App_Glom::get_application();
++  const Application* app = Application::get_application();
 +  if(app && app->get_show_sql_debug())
 +  {
 +    const std::string full_query = sqlbuilder_get_full_query(builder, params);
 +    std::cerr << "Debug: Base_DB::query_execute(): " << full_query << std::endl;
 +  }
 +
 +
 +  int exec_retval = -1;
 +#ifdef GLIBMM_EXCEPTIONS_ENABLED
 +  try
 +  {
 +    exec_retval = gda_connection->statement_execute_non_select_builder(builder, params);
 +  }
 +  catch(const Glib::Error& error)
 +  {
 +    std::cerr << "BaseDB::query_execute: ConnectionError: " << error.what() << std::endl;
 +    const std::string full_query = sqlbuilder_get_full_query(builder, params);
 +    std::cerr << "  full_query: " << full_query << std::endl;
 +    return false;
 +  }
 +#else
 +  std::auto_ptr<Glib::Error> exec_error;
 +  exec_retval = gda_connection->statement_execute_non_select_builder(builder, params, exec_error);
 +  if(exec_error.get())
 +  {
 +    std::cerr << "BaseDB::query_execute: ConnectionError: " << exec_error->what() << std::endl;
 +    const std::string full_query = sqlbuilder_get_full_query(builder, params);
      std::cerr << "  full_query: " << full_query << std::endl;
      return false;
    }
@@@ -2927,10 -2815,10 +2919,7 @@@ Gnome::Gda::Value Base_DB::get_field_va
    sharedptr<const LayoutItem_Field> layout_item = field_in_record.m_field;
    list_fields.push_back(layout_item);
    Glib::ustring sql_query = Utils::build_sql_select_with_key(field_in_record.m_table_name,
--      list_fields, field_in_record.m_key, field_in_record.m_key_value);
--
--  if(!sql_query.empty())
--    sql_query += " LIMIT 1";
++      list_fields, field_in_record.m_key, field_in_record.m_key_value, 1);
  
    Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(sql_query);
    if(data_model)
@@@ -2974,12 -2862,12 +2963,11 @@@ Gnome::Gda::Value Base_DB::get_field_va
    sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::create();
    layout_item->set_full_field_details(field);
    list_fields.push_back(layout_item);
--  Glib::ustring sql_query = Utils::build_sql_select_with_where_clause(found_set.m_table_name,
++  const Glib::ustring sql_query = Utils::build_sql_select_with_where_clause(found_set.m_table_name,
      list_fields,
--    found_set.m_where_clause);
--
--  if(!sql_query.empty())
--    sql_query += " LIMIT 1";
++    found_set.m_where_clause,
++    Glib::ustring(), type_sort_clause(), Glib::ustring(),
++    1 /* limit */);
  
    Glib::RefPtr<Gnome::Gda::DataModel> data_model = query_execute_select(sql_query);
    if(data_model)
@@@ -3514,15 -3401,8 +3502,15 @@@ int Base_DB::count_rows_returned_by(con
    //Note that the alias is just because the SQL syntax requires it - we get an error if we don't use it.
    //Be careful not to include ORDER BY clauses in this, because that would make it unnecessarily slow:
    const Glib::ustring query_count = "SELECT COUNT (*) FROM (" + sql_query + ") AS glomarbitraryalias";
 +  
 +  /* TODO: Use SqlBuilder when we discover how to use a sub-query, or when this function can take a Sqlbuilder.
 +  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
 +    Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
 +  builder->add_function("count", builder->add_id("*")); //TODO: Is * allowed here?
 +  builder->select_add_target(m_found_set.m_table_name);
 +  */
  
-   const App_Glom* app = App_Glom::get_application();
+   const Application* app = Application::get_application();
    if(app && app->get_show_sql_debug())
    {
      try
diff --cc glom/base_db_table_data.cc
index c72a1ce,271799d..caf37d2
--- a/glom/base_db_table_data.cc
+++ b/glom/base_db_table_data.cc
@@@ -262,9 -262,9 +262,9 @@@ bool Base_DB_Table_Data::record_new(boo
  }
  
  
 -bool Base_DB_Table_Data::get_related_record_exists(const sharedptr<const Relationship>& relationship, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value)
 +bool Base_DB_Table_Data::get_related_record_exists(const sharedptr<const Relationship>& relationship, const Gnome::Gda::Value& key_value)
  {
-   BusyCursor cursor(App_Glom::get_application());
+   BusyCursor cursor(Application::get_application());
  
    bool result = false;
  
diff --cc glom/libglom/python_embed/py_glom_relatedrecord.cc
index 396a6d9,7d7c23f..4e7e111
--- a/glom/libglom/python_embed/py_glom_relatedrecord.cc
+++ b/glom/libglom/python_embed/py_glom_relatedrecord.cc
@@@ -62,90 -61,86 +62,91 @@@ boost::python::object PyGlomRelatedReco
      //If the value has already been stored, then just return it again:
      return glom_pygda_value_as_boost_pyobject(iterFind->second);
    }
 +  
 +  const Glib::ustring related_table = m_relationship->get_to_table();
 +
 +  //Check whether the field exists in the table.
 +  //TODO_Performance: Do this without the useless Field information?
 +  sharedptr<const Field> field = m_document->get_field(m_relationship->get_to_table(), field_name);
 +  if(!field)
 +  {
 +    g_warning("PyGlomRelatedRecord::setitem(): field %s not found in table %s", field_name.c_str(), m_relationship->get_to_table().c_str());
 +    PyErr_SetString(PyExc_IndexError, "field not found");
 +    return boost::python::object();
 +  }
    else
    {
 -    const Glib::ustring related_table = m_relationship->get_to_table();
 -
 -    //Check whether the field exists in the table.
 -    //TODO_Performance: Do this without the useless Field information?
 -    sharedptr<const Field> field = m_document->get_field(m_relationship->get_to_table(), field_name);
 -    if(!field)
 -      g_warning("RelatedRecord_tp_as_mapping_getitem: field %s not found in table %s", field_name.c_str(), m_relationship->get_to_table().c_str());
 -    else
 -    {
 -      //Try to get the value from the database:
 -      //const Glib::ustring parent_key_name;
 +    //Try to get the value from the database:
 +    //const Glib::ustring parent_key_name;
  #ifdef GLIBMM_EXCEPTIONS_ENABLED
 -      sharedptr<SharedConnection> sharedconnection = ConnectionPool::get_instance()->connect();
 +    sharedptr<SharedConnection> sharedconnection = ConnectionPool::get_instance()->connect();
  #else
 -      std::auto_ptr<ExceptionConnection> conn_error;
 -      sharedptr<SharedConnection> sharedconnection = ConnectionPool::get_instance()->connect(conn_error);
 -      // Ignore error, sharedconnection presence is checked below
 +    std::auto_ptr<ExceptionConnection> conn_error;
 +    sharedptr<SharedConnection> sharedconnection = ConnectionPool::get_instance()->connect(conn_error);
 +    // Ignore error, sharedconnection presence is checked below
  #endif
 -      if(sharedconnection)
 -      {
 -        Glib::RefPtr<Gnome::Gda::Connection> gda_connection = sharedconnection->get_gda_connection();
 -
 -        const Glib::ustring related_key_name = m_relationship->get_to_field();
 -
 -        //Do not try to get a value based on a null key value:
 -        if(m_from_key_value_sqlized.empty())
 -          return boost::python::object();
 -
 -        //Get the single value from the related records:
 -        const Glib::ustring sql_query = "SELECT \"" + related_table + "\".\"" + field_name + "\" FROM \"" + related_table + "\""
 -          + " WHERE \"" + related_table + "\".\"" + related_key_name + "\" = " + m_from_key_value_sqlized;
 -
 -        /* TODO: Fix linking problems
 -        const Application* app = Application::get_application();
 -        if(app && app->get_show_sql_debug())
 -        {
 -          try
 -          {
 -            std::cout << "Debug: RelatedRecord_tp_as_mapping_getitem():  " << sql_query << std::endl;
 -          }
 -          catch(const Glib::Exception& ex)
 -          {
 -            std::cout << "Debug: query string could not be converted to std::cout: " << ex.what() << std::endl;
 -          }
 -        }*/
+ 
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -        // TODO: Does this behave well if this throws an exception?
 -        Glib::RefPtr<Gnome::Gda::DataModel> datamodel = gda_connection->statement_execute_select(sql_query);
 -#else
 -        std::auto_ptr<Glib::Error> error;
 -        Glib::RefPtr<Gnome::Gda::DataModel> datamodel =  gda_connection->statement_execute_select(sql_query, Gnome::Gda::STATEMENT_MODEL_RANDOM_ACCESS, error);
 -        // Ignore error, datamodel return value is checked below
 -#endif
 -        if(datamodel && datamodel->get_n_rows())
 -        {
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -          Gnome::Gda::Value value = datamodel->get_value_at(0, 0);
 -#else
 -          Gnome::Gda::Value value = datamodel->get_value_at(0, 0, error);
 -#endif
 -          //g_warning("RelatedRecord_tp_as_mapping_getitem(): value from datamodel = %s", value.to_string().c_str());
 -
 -          //Cache it, in case it's asked-for again.
 -          m_map_field_values[field_name] = value;
 -          return glom_pygda_value_as_boost_pyobject(value);
 -        }
 -        else if(!datamodel)
 -        {
 -          g_warning("RelatedRecord_tp_as_mapping_getitem(): The datamodel was null.");
 -          ConnectionPool::handle_error_cerr_only();
 -          RelatedRecord_HandlePythonError();
 -        }
 -        else
 -        {
 -          g_warning("RelatedRecord_tp_as_mapping_getitem(): No related records exist yet for relationship %s.",  m_relationship->get_name().c_str());
 -        }
 +    if(!sharedconnection)
 +    {
-       PyErr_SetString(PyExc_IndexError, "connection not found");
++      PyErr_SetString(PyExc_IndexError, "no database connection");
 +      return boost::python::object();
 +    }
-   
++
 +    Glib::RefPtr<Gnome::Gda::Connection> gda_connection = sharedconnection->get_gda_connection();
 +
 +    const Glib::ustring related_key_name = m_relationship->get_to_field();
 +
 +    //Do not try to get a value based on a null key value:
 +    if(Conversions::value_is_empty(m_from_key_value))
 +    {
 +      PyErr_SetString(PyExc_IndexError, "connection not found");
 +      return boost::python::object();
 +    }
 +
 +    //Get the single value from the related records:
 +    Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
 +      Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
 +    builder->select_add_field(field_name, related_table);
 +    builder->select_add_target(related_table);
 +    builder->set_where(
 +      builder->add_cond(Gnome::Gda::SQL_OPERATOR_TYPE_EQ,
 +        builder->add_id(related_key_name), //TODO: It would nice to specify the table name here too.
 +        builder->add_expr(m_from_key_value)));
 +        
 +    /* TODO: Fix linking problems
 +    const App_Glom* app = App_Glom::get_application();
 +    if(app && app->get_show_sql_debug())
 +    {
 +      try
 +      {
 +        std::cout << "Debug: PyGlomRelatedRecord::setitem()():  " << sql_query << std::endl;
        }
 +      catch(const Glib::Exception& ex)
 +      {
 +        std::cout << "Debug: query string could not be converted to std::cout: " << ex.what() << std::endl;
 +      }
 +    }*/
 +    
 +    // TODO: Does this behave well if this throws an exception?
 +    Glib::RefPtr<Gnome::Gda::DataModel> datamodel = gda_connection->statement_execute_select_builder(builder);
 +    if(datamodel && datamodel->get_n_rows())
 +    {
 +      const Gnome::Gda::Value value = datamodel->get_value_at(0, 0);
 +      //g_warning("PyGlomRelatedRecord::setitem()(): value from datamodel = %s", value.to_string().c_str());
 +
 +      //Cache it, in case it's asked-for again.
 +      m_map_field_values[field_name] = value;
 +      return glom_pygda_value_as_boost_pyobject(value);
 +    }
 +    else if(!datamodel)
 +    {
 +      g_warning("PyGlomRelatedRecord::setitem()(): The datamodel was null.");
 +      ConnectionPool::handle_error_cerr_only();
 +      RelatedRecord_HandlePythonError();
 +    }
 +    else
 +    {
 +      g_warning("PyGlomRelatedRecord::setitem()(): No related records exist yet for relationship %s.",  m_relationship->get_name().c_str());
      }
    }
  
diff --cc glom/libglom/utils.cc
index 4f4fdd2,0eb629b..ffa9bc9
--- a/glom/libglom/utils.cc
+++ b/glom/libglom/utils.cc
@@@ -195,7 -195,7 +195,7 @@@ Glib::ustring Utils::string_replace(con
  }
  
  
--Glib::ustring Utils::build_sql_select_with_where_clause(const Glib::ustring& table_name, const type_vecLayoutFields& fieldsToGet, const Glib::ustring& where_clause, const Glib::ustring& extra_join, const type_sort_clause& sort_clause, const Glib::ustring& extra_group_by)
++Glib::ustring Utils::build_sql_select_with_where_clause(const Glib::ustring& table_name, const type_vecLayoutFields& fieldsToGet, const Glib::ustring& where_clause, const Glib::ustring& extra_join, const type_sort_clause& sort_clause, const Glib::ustring& extra_group_by, guint limit)
  {
    //TODO_Performance:
    type_vecConstLayoutFields constFieldsToGet;
@@@ -204,7 -204,7 +204,7 @@@
      constFieldsToGet.push_back(*iter);
    }
  
--  return build_sql_select_with_where_clause(table_name, constFieldsToGet, where_clause, extra_join, sort_clause, extra_group_by);
++  return build_sql_select_with_where_clause(table_name, constFieldsToGet, where_clause, extra_join, sort_clause, extra_group_by, limit);
  }
  
  
@@@ -331,7 -331,7 +331,7 @@@ Glib::ustring Utils::build_sql_select_f
  }
  
  
--Glib::ustring Utils::build_sql_select_with_where_clause(const Glib::ustring& table_name, const type_vecConstLayoutFields& fieldsToGet, const Glib::ustring& where_clause, const Glib::ustring& extra_join, const type_sort_clause& sort_clause, const Glib::ustring& extra_group_by)
++Glib::ustring Utils::build_sql_select_with_where_clause(const Glib::ustring& table_name, const type_vecConstLayoutFields& fieldsToGet, const Glib::ustring& where_clause, const Glib::ustring& extra_join, const type_sort_clause& sort_clause, const Glib::ustring& extra_group_by, guint limit)
  {
    //Get the list of fields to SELECT, plus the tables that they are selected FROM.
    Glib::ustring sql_part_from;
@@@ -386,11 -386,11 +386,19 @@@
        result += " ORDER BY " + str_sort_clause;
    }
  
++  //LIMIT clause:
++  if(!result.empty() && limit > 0)
++  {
++    char pchLimit[10];
++    sprintf(pchLimit, "%d", limit);
++    result += " LIMIT " + Glib::ustring(pchLimit);
++  }
++
    return result;
  }
  
  
--Glib::ustring Utils::build_sql_select_with_key(const Glib::ustring& table_name, const type_vecLayoutFields& fieldsToGet, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value)
++Glib::ustring Utils::build_sql_select_with_key(const Glib::ustring& table_name, const type_vecLayoutFields& fieldsToGet, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value, guint limit)
  {
    //TODO_Performance:
    type_vecConstLayoutFields constFieldsToGet;
@@@ -399,18 -399,18 +407,17 @@@
      constFieldsToGet.push_back(*iter);
    }
  
--  return build_sql_select_with_key(table_name, constFieldsToGet, key_field, key_value);
--
--
++  return build_sql_select_with_key(table_name, constFieldsToGet, key_field, key_value, limit);
  }
  
--Glib::ustring Utils::build_sql_select_with_key(const Glib::ustring& table_name, const type_vecConstLayoutFields& fieldsToGet, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value)
++Glib::ustring Utils::build_sql_select_with_key(const Glib::ustring& table_name, const type_vecConstLayoutFields& fieldsToGet, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value, guint limit)
  {
    if(!Conversions::value_is_empty(key_value)) //If there is a record to show:
    {
      //TODO: Use a SQL parameter instead of using sql():
      const Glib::ustring where_clause = '\"' + table_name + "\".\"" + key_field->get_name() + "\" = " + key_field->sql(key_value);
--    return Utils::build_sql_select_with_where_clause(table_name, fieldsToGet, where_clause);
++    return Utils::build_sql_select_with_where_clause(table_name, fieldsToGet, where_clause,
++      Glib::ustring(), type_sort_clause(),  Glib::ustring(), limit);
    }
  
    return Glib::ustring();
diff --cc glom/libglom/utils.h
index a20e369,a20e369..e95bb60
--- a/glom/libglom/utils.h
+++ b/glom/libglom/utils.h
@@@ -66,7 -66,7 +66,8 @@@ Glib::ustring build_sql_select_with_whe
    const Glib::ustring& where_clause = Glib::ustring(),
    const Glib::ustring& extra_join = Glib::ustring(),
    const type_sort_clause& sort_clause = type_sort_clause(),
--  const Glib::ustring& extra_group_by = Glib::ustring());
++  const Glib::ustring& extra_group_by = Glib::ustring(),
++  guint limit = 0);
  
  /** Just a version of build_sql_select_with_where_clause() that takes a list of const fields.
   */
@@@ -76,13 -76,13 +77,15 @@@ Glib::ustring build_sql_select_with_whe
    const Glib::ustring& where_clause = Glib::ustring(),
    const Glib::ustring& extra_join = Glib::ustring(),
    const type_sort_clause& sort_clause = type_sort_clause(),
--  const Glib::ustring& extra_group_by = Glib::ustring());
++  const Glib::ustring& extra_group_by = Glib::ustring(),
++  guint limit = 0);
  
  Glib::ustring build_sql_select_with_key(
    const Glib::ustring& table_name,
    const type_vecLayoutFields& fieldsToGet,
    const sharedptr<const Field>& key_field,
--  const Gnome::Gda::Value& key_value);
++  const Gnome::Gda::Value& key_value,
++  guint limit = 0);
  
  /** Just a version of build_sql_select_with_key() that takes a list of const fields.
   */
@@@ -90,7 -90,7 +93,8 @@@ Glib::ustring build_sql_select_with_key
    const Glib::ustring& table_name,
    const type_vecConstLayoutFields& fieldsToGet,
    const sharedptr<const Field>& key_field,
--  const Gnome::Gda::Value& key_value);
++  const Gnome::Gda::Value& key_value,
++  guint limit = 0);
  
  typedef std::list< std::pair<Gnome::Gda::Value, Gnome::Gda::Value> > type_list_values_with_second;
  type_list_values_with_second get_choice_values(const sharedptr<const LayoutItem_Field>& field);
diff --cc glom/mode_design/fields/box_db_table_definition.cc
index df7cc93,78cec56..2f057b9
--- a/glom/mode_design/fields/box_db_table_definition.cc
+++ b/glom/mode_design/fields/box_db_table_definition.cc
@@@ -656,11 -654,10 +658,13 @@@ bool Box_DB_Table_Definition::field_has
    long count_distinct = 0;
    long count_all = 0;
  
-   //TODO: Use SqlBuilder. I asked on the mailing list about how to use DISTINCT with it. murrayc.
-   //Count the distinct rows:
-   const Glib::ustring sql_query_distinct = "SELECT DISTINCT \"" + field->get_name() + "\" FROM \"" + m_table_name + "\"";
-   
-   Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query_distinct);
 -  //Count the distint rows:
 -  const Glib::ustring sql_query_distinct = "SELECT DISTINCT \"" + field->get_name() + "\" FROM \"" + m_table_name + "\"";
 -  
 -  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query_distinct);
++  //Count the distinct rows:  
++  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder_query_distinct = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
++  builder_query_distinct->select_set_distinct();
++  builder_query_distinct->set_table(m_table_name);
++  builder_query_distinct->select_add_field(field->get_name(), m_table_name);
++
++  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(builder_query_distinct);
    if(datamodel)
    {
      count_distinct = datamodel->get_n_rows();
diff --cc glom/print_layout/canvas_print_layout.cc
index f5353cd,f5353cd..de5014a
--- a/glom/print_layout/canvas_print_layout.cc
+++ b/glom/print_layout/canvas_print_layout.cc
@@@ -645,14 -645,14 +645,11 @@@ void Canvas_PrintLayout::fill_with_data
    if(fieldsToGet.empty())
      return;
  
--  Glib::ustring sql_query = Utils::build_sql_select_with_where_clause(found_set.m_table_name,
++  const Glib::ustring sql_query = Utils::build_sql_select_with_where_clause(found_set.m_table_name,
      fieldsToGet,
--    found_set.m_where_clause, Glib::ustring() /* extra_join */, found_set.m_sort_clause);
--
--  if(!sql_query.empty())
--    sql_query += " LIMIT 1";
--  else
--    return;
++    found_set.m_where_clause, Glib::ustring() /* extra_join */, found_set.m_sort_clause, 
++    Glib::ustring(),
++    1);
    
    bool records_found = false;
    Glib::RefPtr<Gnome::Gda::DataModel> datamodel;
diff --cc glom/report_builder.cc
index 0052d98,d1257fb..2e59143
--- a/glom/report_builder.cc
+++ b/glom/report_builder.cc
@@@ -306,13 -305,13 +306,16 @@@ void ReportBuilder::report_build_record
        }
      }
  
--   Glib::ustring sql_query = Utils::build_sql_select_with_where_clause(found_set.m_table_name,
--      fieldsToGet,
--      found_set.m_where_clause, Glib::ustring() /* extra_join */, found_set.m_sort_clause);
--
      //For instance, when we just want to get a name corresponding to a contact ID, and want to ignore duplicates.
++    guint limit = 0; //no limit.
      if(one_record_only)
--      sql_query += " LIMIT 1";
++      limit = 1;
++
++    const Glib::ustring sql_query = Utils::build_sql_select_with_where_clause(found_set.m_table_name,
++      fieldsToGet,
++      found_set.m_where_clause, Glib::ustring() /* extra_join */, found_set.m_sort_clause,
++      Glib::ustring(),
++      limit);
  
      bool records_found = false;
      Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(sql_query);
@@@ -385,10 -384,9 +388,11 @@@ void ReportBuilder::report_build_record
    {
      //In this case it can only be a system preferences field.
      //So let's get that data here:
-     //TODO: Use SqlBuilder when we know how to use LIMIT with it. I asked on the libgda mailing list. murrayc.
--    const Glib::ustring table_used = field->get_table_used(found_set.m_table_name);
--    const Glib::ustring query = "SELECT \"" + table_used + "\".\"" + field->get_name() + "\" FROM \""+ table_used + "\" LIMIT 1";
--    Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(query);
++    Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_UPDATE);
++    builder->set_table(field->get_table_used(found_set.m_table_name));
++    builder->select_add_field(field->get_name(), found_set.m_table_name);
++    builder->select_set_limit(1);
++    Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute_select(builder);
  
      if(!datamodel)
        return;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]