[glom: 44/47] Merge from glom-1-16



commit 43c9c134f90e0aa4d058ae6cb415eda2659cf11e
Merge: 45d4dea 4a21848
Author: Murray Cumming <murrayc murrayc com>
Date:   Sun Jul 25 22:19:13 2010 +0200

    Merge from glom-1-16

 ChangeLog                                          |17774 +-------------------
 NEWS                                               |   31 +-
 configure.ac                                       |   12 +
 examples/example_smallbusiness.glom                |   28 +-
 glom/application.cc                                |  687 +-
 glom/application.h                                 |   21 +-
 glom/bakery/app_withdoc_gtk.h                      |    6 +-
 glom/bakery/dialog_offersave.cc                    |    2 +-
 glom/base_db.h                                     |    3 +-
 glom/dialog_progress_creating.cc                   |    2 +-
 glom/frame_glom.cc                                 |   22 +-
 glom/frame_glom.h                                  |    4 +-
 glom/glom_document.dtd                             |    5 +-
 glom/libglom/connectionpool.cc                     |   73 +-
 glom/libglom/connectionpool.h                      |   70 +-
 glom/libglom/connectionpool_backends/backend.cc    |   15 +-
 glom/libglom/connectionpool_backends/backend.h     |   54 +-
 glom/libglom/connectionpool_backends/postgres.cc   |  498 +-
 glom/libglom/connectionpool_backends/postgres.h    |   53 +-
 .../connectionpool_backends/postgres_central.cc    |   22 +-
 .../connectionpool_backends/postgres_central.h     |    3 -
 .../connectionpool_backends/postgres_self.cc       |  276 +-
 .../connectionpool_backends/postgres_self.h        |   21 +-
 glom/libglom/connectionpool_backends/sqlite.cc     |   29 +-
 glom/libglom/connectionpool_backends/sqlite.h      |    8 +-
 glom/libglom/db_utils.cc                           |   92 +
 glom/libglom/db_utils.h                            |    2 +
 glom/libglom/document/bakery/document.cc           |    3 +-
 glom/libglom/document/document.cc                  |  216 +-
 glom/libglom/document/document.h                   |    4 +
 glom/libglom/spawn_with_feedback.cc                |   43 +-
 glom/libglom/utils.cc                              |   92 +-
 glom/libglom/utils.h                               |   16 +
 glom/main.cc                                       |   61 +-
 glom/mode_data/notebook_data.cc                    |    4 +-
 glom/mode_design/box_db_table_relationships.cc     |    9 +-
 glom/mode_design/box_db_table_relationships.h      |    5 +-
 glom/mode_design/dialog_add_related_table.h        |    3 +-
 glom/mode_design/dialog_database_preferences.h     |    3 +-
 glom/mode_design/dialog_initial_password.h         |    3 +-
 glom/mode_design/fields/combo_fieldtype.cc         |   11 +-
 glom/mode_design/layout/treestore_layout.cc        |    4 +-
 .../print_layouts/print_layout_toolbar.cc          |   14 +-
 .../print_layouts/print_layout_toolbar.h           |    2 +-
 .../print_layouts/window_print_layout_edit.h       |    2 +-
 .../dialog_relationships_overview.cc               |   76 +-
 .../report_layout/treestore_report_layout.cc       |    1 +
 .../mode_design/script_library/dialog_new_script.h |    3 +-
 .../translation/dialog_change_language.cc          |    1 +
 .../translation/dialog_change_language.h           |    2 +-
 .../translation/dialog_copy_translation.h          |    3 +-
 .../translation/dialog_identify_original.h         |    3 +-
 .../mode_design/translation/window_translations.cc |    2 +
 glom/mode_design/users/dialog_choose_user.h        |    3 +-
 glom/mode_design/users/dialog_groups_list.cc       |    3 +-
 glom/mode_design/users/dialog_new_group.h          |    2 +-
 glom/mode_find/notebook_find.cc                    |   14 +-
 glom/print_layout/canvas_layout_item.cc            |   44 +-
 glom/utility_widgets/canvas/canvas_editable.cc     |    4 +-
 glom/utility_widgets/canvas/canvas_item_movable.h  |   12 +-
 .../cellrendererlist/cellrendererlist.h            |    7 +-
 glom/utility_widgets/db_adddel/glom_db_treemodel.h |    8 +-
 glom/utility_widgets/dialog_properties.cc          |    6 +-
 .../utility_widgets/filechooserdialog_saveextras.h |    2 +-
 glom/utility_widgets/layouttoolbar.h               |    3 +-
 glom/utility_widgets/layouttoolbarbutton.cc        |    7 +-
 glom/utility_widgets/layoutwidgetbase.h            |    8 +-
 glom/utility_widgets/sidebar.h                     |   10 +-
 glom/utils_ui.h                                    |   14 +-
 tests/test_selfhosting_new_empty.cc                |   62 +-
 70 files changed, 2345 insertions(+), 18263 deletions(-)
---
diff --cc ChangeLog
index f141f77,d43cd5f..d328f34
--- a/ChangeLog
+++ b/ChangeLog
@@@ -1,3 -1,230 +1,229 @@@
+ 2010-07-25  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Allow unique fields with same name in multiple tables.
+ 
+ 	* glom/libglom/connectionpool_backends/postgres.cc:
+ 	change_column(): Prefix the table name to the constraint name when
+ 	setting/removing the unique-key constraint, as libgda (or PostgreSQL)
+ 	seems to do when creating a field. This prevents a clash when two tables
+ 	have the same field name, and both should be unique.
+ 	This is nasty code anyway that I would rather have in libgda.
+ 	This fixes bug #625192 (fmyhr).
+ 
 -
+ 2010-07-22  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Added --restore command-line option.
+ 
+ 	* glom/application.[h|cc]: Added init() with a bool restore option,
+   calling do_backup_restore() if appropriate.
+ 	* glom/main.cc: Added a --restore command and pass the bool result to
+   Application::init().
+ 
+   This allows the user to restore from a backup without first loading an
+   existing file, though this is so far only possible via the terminal.
+ 
+ 2010-07-22  Murray Cumming  <murrayc murrayc com>
+ 
+   Added Developer/Restore Backup menu item.
+ 
+ 	* glom/application.[h.cc]: Added a Developer/Restore Backup menu item,
+   which lets the user choose a .tar.gz, untars it in /tmp/ and opens it.
+ 
+ 	* tests/test_selfhosting_new_empty.cc:
+ 	* glom/libglom/utils.[h|cc]: Move delete_directory() to Utils.
+   Added get_directory_child_with_suffix(), used to find the .glom file inside
+   an untarred directory.
+ 
+ 2010-07-22  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Saving from a backup: Now works.
+ 
+ 	* glom/application.[h|cc]: on_document_load(): Simplify the code to
+   create from a backup, modifying the from-example code to handle it too,
+   calling a new recreate_database_from_backup() method.
+   That now creates the database and then adds the groups before trying
+   to restore from the backup file.
+ 	* glom/libglom/connectionpool_backends/backend.h: convert_backup():
+ 	* glom/libglom/connectionpool_backends/postgres.[h|cc]: convert_backup():
+ 	* glom/libglom/connectionpool_backends/sqlite.[h|cc]: convert_backup():
+   Add a database_name_parameter. This now expects the database to exist
+   already, though it should be empty. It should also already have the
+   expected groups.
+ 	* glom/libglom/connectionpool.[h|cc]: convert_backup(): Supply the
+   database name. Also update the meta data so we know about the new tables.
+ 
+ 2010-07-21  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Small Business example: Add table privileges.
+ 
+ 	* examples/example_smallbusiness.glom: Give some privileges to the
+     accounts and personnel groups and resave-as-an-example. These were
+     probably lost some time.
+ 
+ 2010-07-21  Murray Cumming  <murrayc murrayc com>>
+ 
+ 	Saving as example: Fix this.
+ 
+ 	* glom/libglom/document/document.cc: set_modified(): Actually use
+     m_allow_auto_save so we don't just save every time, overwriting
+     previous saves. For instance, the examples were saved with is_example=false
+     after the document was changed back.
+ 
+ 2010-07-21  Murray Cumming  <murrayc murrayc com>>
+ 
+ 	Saving from examples: Set the table privileges mentioned in the document.
+ 
+ 	* glom/base_db.[h|cc]: Added set_table_privileges_groups_from_document().
+ 	* glom/application.cc: recreate_database_from_example(): call it.
+ 
+ 2010-07-21  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Saving from examples: Create the groups mentioned in the document.
+ 
+ 	* glom/base_db.[h|cc]: Added add_groups_from_document().
+ 	* glom/application.cc: recreate_database_from_example(): call it.
+ 
+ 2010-07-20  Murray Cumming  <murrayc murrayc com>>
+ 
+ 	Fixed warnings with latest gtkmm-2.24
+ 
+ 	* glom/mode_data/notebook_data.cc:
+ 	* glom/mode_find/notebook_find.cc: Use Gtk::Notebook::append_page()
+     instead of Gtk::Notebook::pages().push_back().
+ 
+ 2010-07-13  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Fixed warnings, even with the latest gtkmm-2.24.
+ 
+ 	Many files: Try to include box.h or dialog.h before other treemodel.h.
+     Sometimes just add a gtkmm.h to simplify things. This will not be necessary
+     with gtkmm-3.0 (in glom's master branch).
+ 
+ 2010-07-07  Murray Cumming  <murrayc murrayc-desktop>
+ 
+ 	PostgresQL backups: Suggest a dated name.
+ 
+ 	* glom/application.cc: on_menu_developer_export_backup(): Suggest
+     a directory name based on the current name and the date/time.
+     Also use the directory name for the .glom filename, as we usually would do,
+     instead of calling it just backup.glom.
+ 
+ 2010-07-07  Murray Cumming  <murrayc murrayc com>
+ 
+ 	PostgreSQL backups: Archive the directory in a .tar.gz..
+ 
+ 	* configure.ac: Check for the tar and gzip executables.
+ 	* glom/application.cc: on_menu_developer_export_backup(): Use tar
+     via the command line, to put it all in a .tar.gz, so it is self-contained.
+ 
+ 2010-07-07  Murray Cumming  <murrayc murrayc com>
+ 
+ 	PostgreSQL backups: Use .pgpass.
+ 
+ 	* glom/libglom/connectionpool_backends/postgres.[h|cc]:
+ 	* glom/libglom/connectionpool_backends/postgres_self.[h|cc]:
+     Move create_text_file() from PostgresSelf to Postgres and add an
+     only_for_current_user bool parameter, so we can use it in a
+     new save_password_to_pgpass() method.
+     save_backup(), convert_backup(): Temporarily store the password in
+     ~/.pgpass, so pg_dump and pg_restore actually work.
+ 
+ 2010-07-05  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Show progress in the UI during backup saving and restoring.
+ 
+ 	* glom/application.[h|cc]: on_document_load(),
+     on_menu_developer_export_backup(): Show a pulsing progress dialog while
+     waiting for backup exporting and restoring.
+     on_menu_developer_export_backup(): Close the file chooser dialog as soon
+     as we stop using it.
+ 
+ 2010-07-03  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Improve backup saving and add backup restoring.
+ 
+ 	* glom/libglom/document/document.[h|cc]: Added get/set_is_backup_file(),
+ 	saved in the XML document..
+   on_menu_developer_export_backup(): Mark the .glom file as a backup file.
+ 	Rename recreate_database() to recreate_database_from_example().
+ 	on_document_load(): Handle backup .glom files similarly to examples files,
+ 	but using the backup file instead of example data.
+ 	* glom/frame_glom.cc:
+ 	* glom/libglom/connection_pool.[h|cc]:
+ 	* glom/libglom/connectionpool_backends/backend.[h|cc]: startup(): Return a
+ 	StartupErrors enum, to provide more clues, for instance to say that backup
+ 	data was found.
+ 	Add get/set_database_directory_uri(), replacing the one in sqlite.[h|cc] and
+ 	replacing set_self_hosting_data_uri() in postgres_self.[hc|cc].
+ 	save_backup(): Don't take a filepath - use get_database_directory_uri()
+ 	instead.
+ 	Added convert_backup() to restore from a backup.
+ 	* glom/libglom/connectionpool_backends/sqlite.[h|cc]:
+ 	* glom/libglom/connectionpool_backends/postgres.[h|cc]:
+ 	get_path_to_postgres_executable(): Catch exceptions from Glib::build_filename().
+ 	save_backup(): Use --format=c with pg_dump, because the default one can't be
+ 	used with pg_restore.
+ 	Implement convert_backup(), using pg_restore.
+ 	Added get_self_hosting_config_path(), get_self_hosting_data_path() and
+ 	get_self_hosting_backup_path() to avoid copy/pasting magic paths.
+ 	* glom/libglom/connectionpool_backends/postgres_self.[h|cc]:
+ 	Adapted.
+ 	* glom/application.[h|cc]:
+ 	* tests/test_selfhosting_new_empty.cc: Adapted to check the enum result from
+ 	startup().
+ 
+ 2010-07-02  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Document: Avoid a crash when creating the parent directory.
+ 
+ 	* glom/libglom/docment/bakery/document.cc: write_to_disk(): Check the
+ 	result of Gio::File::get_parent() for null, because that happens if we
+ 	provide a path instead of a URI.
+ 
+ 2010-07-02  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Save as Example: Reset the old file URI and allow auto-saving again.
+ 
+ 	* glom/application.cc: on_menu_file_save_as_example(): reset the old file
+ 	URI and turn auto-saving back on again, because it makes no sense to leave
+ 	the user editing an example document. This is really an export anyway.
+ 	This allows the user to close the window again after saving as an example.
+ 
+ 2010-07-01  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Add Save Backup menu item.
+ 
+ 	* glom/libglom/connectionpool_backends/backend.[h|cc]:
+ 	* glom/libglom/connectionpool_backends/posgres.[h|cc]:
+ 	* glom/libglom/connectionpool_backends/sqlite.[h|cc]: Added save_backup()
+ 	virtual method, using pg_dump for PostgreSQL.
+ 	* glom/libglom/connectionpool.[h|cc]: Add save_backup() here, calling the
+ 	backend.
+ 	* glom/application.cc: Add a Developer/Export Backup menu item, to use
+ 	this feature. This also saves the .glom file.
+ 
+ 2010-07-01  Murray Cumming  <murrayc murrayc com>
+ 
+ 	Spawn functions: Catch some exceptions.
+ 
+ 	* glom/libglom/spawn_with_feedback.cc():
+ 	execute_command_line(), execute_command_line_and_wait(): Catch exceptions
+ 	so that these functions don't throw, simplifying caller code. For instance,
+ 	a command may be malformed and rejected by the shell.
+ 
+ 2010-06-29  Murray Cumming  <murrayc murrayc com>
+ 
+ 	* glom/application.[h|cc]: Developer menu: Added an Export Backup menu item.
+ 
+ 	* glom/libglom/connectionpool_backends/postgres_central.[h|cc]:
+ 	* glom/libglom/connectionpool_backends/postgres_self.[h|cc]: Moved
+     m_host and m_port into the base class:
+ 	* glom/libglom/connectionpool_backends/postgres.[h|cc]:
+     because they are used in both derived classes. Therefore remove port
+     parameter from attempt_connect().
+     Also move get_path_to_postgres_executable() and port_as_string() there
+     so they can be used in the base class.
+ 
  2010-06-29  Murray Cumming  <murrayc murrayc com>
  
  	Improve stderr message.
diff --cc glom/application.cc
index da14a8f,4116864..ae656d4
--- a/glom/application.cc
+++ b/glom/application.cc
@@@ -55,8 -56,8 +56,6 @@@
  #include <libsoup/soup-status.h>
  #endif // !G_OS_WIN32
  
- #include <gtk/gtk.h>
- 
 -//#include <gtk/gtk.h>
 -
  #ifndef G_OS_WIN32
  # include <netdb.h> //For gethostbyname().
  #endif
diff --cc glom/libglom/connectionpool.h
index 8d42fa5,b1577b7..cb14880
--- a/glom/libglom/connectionpool.h
+++ b/glom/libglom/connectionpool.h
@@@ -137,14 -137,50 +137,38 @@@ public
     *
     * @throws an ExceptionConnection when the connection fails.
     */
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
    sharedptr<SharedConnection> connect();
 -#else
 -  sharedptr<SharedConnection> connect(std::auto_ptr<ExceptionConnection>& error);
 -#endif
  
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
    static sharedptr<SharedConnection> get_and_connect();
 -#else
 -  static sharedptr<SharedConnection> get_and_connect(std::auto_ptr<ExceptionConnection>& error);
 -#endif
  
+   /** This callback should show UI to indicate that work is still happening.
+    * For instance, a pulsing ProgressBar.
+    */
+   typedef Backend::SlotProgress SlotProgress;
+ 
+  //TODO: Add SlotProgress?
    /** Creates a new database.
     */
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
    void create_database(const Glib::ustring& database_name);
 -#else
 -  void create_database(const Glib::ustring& database_name, std::auto_ptr<Glib::Error>& error);
 -#endif
  
+   /** Save a backup of the database in a tarball.
+    * This backup can later be used to recreate the database,
+    * for instance with a later version of PostgreSQL.
+    * See @convert_backup().
+    *
+    * @param path_dir The top-level directory for the backup file, using the normal directory structure.
+    *
+    */
+   bool save_backup(const SlotProgress& slot_progress, const std::string& path_dir);
+ 
+   /** Use a backup of the database in a tarball to create tables and data in an existing empty database.
+    * The database (server) should already have the necessary groups and users.
+    *
+    * @param path_dir The top-level directory for the backup file, using the normal directory structure.
+    * See save_backup().
+    */
+   bool convert_backup(const SlotProgress& slot_progress, const std::string& path_dir);
+ 
    void set_user(const Glib::ustring& value);
    void set_password(const Glib::ustring& value);
    void set_database(const Glib::ustring& value);
diff --cc glom/libglom/connectionpool_backends/backend.cc
index 5044391,c65449f..a90bcd5
--- a/glom/libglom/connectionpool_backends/backend.cc
+++ b/glom/libglom/connectionpool_backends/backend.cc
@@@ -65,32 -65,248 +65,43 @@@ bool Backend::set_network_shared(const 
    return true; //Success at doing nothing.
  }
  
 -bool Backend::set_server_operation_value(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, const Glib::ustring& path, const Glib::ustring& value, std::auto_ptr<Glib::Error>& error)
 -{
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -  try
 -  {
 -    operation->set_value_at(path, value);
 -    return true;
 -  }
 -  catch(const Glib::Error& ex)
 -  {
 -    error.reset(new Glib::Error(ex));
 -    return false;
 -  }
 -#else
 -  operation->set_value_at(path, value, error);
 -  if(error.get()) return false;
 -  return true;
 -#endif
 -}
 -
 -Glib::RefPtr<Gnome::Gda::ServerOperation> Backend::create_server_operation(const Glib::RefPtr<Gnome::Gda::ServerProvider>& provider, const Glib::RefPtr<Gnome::Gda::Connection>& connection, Gnome::Gda::ServerOperationType type, std::auto_ptr<Glib::Error>& error)
 -{
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -  try
 -  {
 -    return provider->create_operation(connection, type);
 -  }
 -  catch(const Glib::Error& ex)
 -  {
 -    error.reset(new Glib::Error(ex));
 -    return Glib::RefPtr<Gnome::Gda::ServerOperation>();
 -  }
 -#else
 -  return provider->create_operation(connection, type, error);
 -#endif
 -}
 -
 -bool Backend::perform_server_operation(const Glib::RefPtr<Gnome::Gda::ServerProvider>& provider, const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, std::auto_ptr<Glib::Error>& error)
 -{
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -  try
 -  {
 -    provider->perform_operation(connection, operation);
 -    return true;
 -  }
 -  catch(const Glib::Error& ex)
 -  {
 -    error.reset(new Glib::Error(ex));
 -    return false;
 -  }
 -#else
 -  provider->perform_operation(connection, operation, error);
 -  if(error.get()) return false;
 -  return true;
 -#endif
 -}
 -
 -bool Backend::begin_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, Gnome::Gda::TransactionIsolation level, std::auto_ptr<Glib::Error>& error)
 -{
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -  try
 -  {
 -    return connection->begin_transaction(name, level);
 -  }
 -  catch(const Glib::Error& ex)
 -  {
 -    error.reset(new Glib::Error(ex));
 -    return false;
 -  }
 -#else
 -  return connection->begin_transaction(name, level, error);
 -#endif
 -}
 -
 -bool Backend::commit_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, std::auto_ptr<Glib::Error>& error)
 -{
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -  try
 -  {
 -    return connection->commit_transaction(name);
 -  }
 -  catch(const Glib::Error& ex)
 -  {
 -    error.reset(new Glib::Error(ex));
 -    return false;
 -  }
 -#else
 -  return connection->commit_transaction(name, error);
 -#endif
 -}
 -
 -bool Backend::rollback_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, std::auto_ptr<Glib::Error>& error)
 -{
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -  try
 -  {
 -    return connection->rollback_transaction(name);
 -  }
 -  catch(const Glib::Error& ex)
 -  {
 -    error.reset(new Glib::Error(ex));
 -    return false;
 -  }
 -#else
 -  return connection->rollback_transaction(name, error);
 -#endif
 -}
 -
 -bool Backend::query_execute(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& sql_query, std::auto_ptr<Glib::Error>& error)
 -{
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -  try
 -  {
 -    return connection->statement_execute_non_select(sql_query) != -1;
 -  }
 -  catch(const Glib::Error& ex)
 -  {
 -    error.reset(new Glib::Error(ex));
 -    return false;
 -  }
 -#else
 -  return connection->statement_execute_non_select(sql_query, error) != -1;
 -#endif
 -}
 -
 -bool Backend::add_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const sharedptr<const Field>& field, std::auto_ptr<Glib::Error>& error)
 +void Backend::add_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const sharedptr<const Field>& field)
  {
    Glib::RefPtr<Gnome::Gda::ServerProvider> provider = connection->get_provider();
 -  Glib::RefPtr<Gnome::Gda::ServerOperation> operation = create_server_operation(provider, connection, Gnome::Gda::SERVER_OPERATION_ADD_COLUMN, error);
 -  if(!operation) return false;
 +  Glib::RefPtr<Gnome::Gda::ServerOperation> operation = provider->create_operation(connection, Gnome::Gda::SERVER_OPERATION_ADD_COLUMN);
  
    //TODO: Quote table_name and field_name?
 -  if(!set_server_operation_value(operation, "/COLUMN_DEF_P/TABLE_NAME", table_name, error))
 -    return false;
 +  operation->set_value_at("/COLUMN_DEF_P/TABLE_NAME", table_name);
 +  operation->set_value_at("/COLUMN_DEF_P/COLUMN_NAME", field->get_name());
 +  operation->set_value_at("/COLUMN_DEF_P/COLUMN_TYPE", field->get_sql_type());
 +  operation->set_value_at("/COLUMN_DEF_P/COLUMN_PKEY", field->get_primary_key());
 +  operation->set_value_at("/COLUMN_DEF_P/COLUMN_UNIQUE", field->get_unique_key());
  
 -  if(!set_server_operation_value(operation, "/COLUMN_DEF_P/COLUMN_NAME", field->get_name(), error))
 -    return false;
 -
 -  if(!set_server_operation_value(operation, "/COLUMN_DEF_P/COLUMN_TYPE", field->get_sql_type(), error))
 -    return false;
 -
 -  if(!set_server_operation_value(operation, "/COLUMN_DEF_P/COLUMN_PKEY", field->get_primary_key() ? "TRUE" : "FALSE", error))
 -    return false;
 -
 -  if(!set_server_operation_value(operation, "/COLUMN_DEF_P/COLUMN_UNIQUE", field->get_unique_key() ? "TRUE" : "FALSE", error))
 -    return false;
 -
 -  if(!perform_server_operation(provider, connection, operation, error))
 -    return false;
 -
 -  return true;
 +  provider->perform_operation(connection, operation);
  }
  
 -bool Backend::drop_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const Glib::ustring& field_name, std::auto_ptr<Glib::Error>& error)
 +void Backend::drop_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const Glib::ustring& field_name)
  {
    Glib::RefPtr<Gnome::Gda::ServerProvider> provider = connection->get_provider();
 -  Glib::RefPtr<Gnome::Gda::ServerOperation> operation = create_server_operation(provider, connection, Gnome::Gda::SERVER_OPERATION_DROP_COLUMN, error);
 -  if(!operation)
 -    return false;
 +  Glib::RefPtr<Gnome::Gda::ServerOperation> operation = provider->create_operation(connection, Gnome::Gda::SERVER_OPERATION_DROP_COLUMN);
  
    //TODO: Quote table name and column name?
 -  if(!set_server_operation_value(operation, "/COLUMN_DESC_P/TABLE_NAME", table_name, error))
 -    return false;
 -
 -  if(!set_server_operation_value(operation, "/COLUMN_DESC_P/COLUMN_NAME", field_name, error))
 -    return false;
 -  
 -  if(!perform_server_operation(provider, connection, operation, error))
 -    return false;
 -
 -  return true;
 -}
 -
 -//TODO: Why/When do we need to change multiple columns instead of a single one? murrayc.
 -//When changing a table's primary key, we unset the primary key for the old
 -//column and set it for the new column. Using a single call to the
 -//ConnectionPoolBackend for this, the backend can do all the required
 -//operations at once, maybe optimizing them. For example, for SQLite we need
 -//to recreate the whole table when changing columns, so we only need to do
 -//this once instead of twice when changing the primary key. armin.
 -bool Backend::change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields, std::auto_ptr<Glib::Error>& error)
 -{
 -  static const char* TRANSACTION_NAME = "glom_change_columns_transaction";
 -  static const gchar* TEMP_COLUMN_NAME = "glom_temp_column"; // TODO: Find a unique name.
 -
 -  if(!begin_transaction(connection, TRANSACTION_NAME, Gnome::Gda::TRANSACTION_ISOLATION_UNKNOWN, error)) return false; // TODO: What does the transaction isolation do?
 -
 -  for(unsigned int i = 0; i < old_fields.size(); ++ i)
 -  {
 -    // TODO: Don't create an intermediate column if the name of the column
 -    // changes anyway.
 -    sharedptr<Field> temp_field = glom_sharedptr_clone(new_fields[i]);
 -    temp_field->set_name(TEMP_COLUMN_NAME);
 -    // The temporary column must not be a primary key, otherwise
 -    // we might end up with two primary key columns temporarily, which most
 -    // database systems do not allow.
 -    temp_field->set_primary_key(false);
 -
 -    if(!add_column(connection, table_name, temp_field, error))
 -      break;
 -
 -    const Glib::ustring temp_move_query = "UPDATE " + table_name + " SET " + TEMP_COLUMN_NAME + " = CAST(" + old_fields[i]->get_name() + " AS " + new_fields[i]->get_sql_type() + ")";
 -    if(!query_execute(connection, temp_move_query, error))
 -      break;
 -    // TODO: If this CAST was not successful, then just go on,
 -    // dropping the data in the column?
 -
 -    if(!drop_column(connection, table_name, old_fields[i]->get_name(), error))
 -      return false;
 -
 -    if(!add_column(connection, table_name, new_fields[i], error))
 -      break;
 -
 -    const Glib::ustring final_move_query = "UPDATE " + table_name + " SET " + new_fields[i]->get_name() + " = " + TEMP_COLUMN_NAME; // TODO: Do we need a cast here, even though the type matches?
 -    if(!query_execute(connection, final_move_query, error))
 -      break;
 -
 -    if(!drop_column(connection, table_name, TEMP_COLUMN_NAME, error))
 -      break;
 -  }
 -
 -  if(error.get() || !commit_transaction(connection, TRANSACTION_NAME, error))
 -  {
 -    std::auto_ptr<Glib::Error> rollback_error;
 -    rollback_transaction(connection, TRANSACTION_NAME, rollback_error);
 -    return false;
 -  }
 -
 -  return true;
 +  operation->set_value_at("/COLUMN_DESC_P/TABLE_NAME", table_name);
 +  operation->set_value_at("/COLUMN_DESC_P/COLUMN_NAME", field_name);
 +  provider->perform_operation(connection, operation);
  }
  
+ void Backend::set_database_directory_uri(const std::string& directory_uri)
+ {
+   m_database_directory_uri = directory_uri;
+ }
+ 
+ std::string Backend::get_database_directory_uri() const
+ {
+   return m_database_directory_uri;
+ }
+ 
+ 
  } // namespace ConnectionPoolBackends
  
  } // namespace Glom
diff --cc glom/libglom/connectionpool_backends/backend.h
index 418b00a,c72cd99..8297a5b
--- a/glom/libglom/connectionpool_backends/backend.h
+++ b/glom/libglom/connectionpool_backends/backend.h
@@@ -76,8 -76,26 +76,16 @@@ public
       INITERROR_COULD_NOT_START_SERVER,
       INITERROR_OTHER
    };
-   
+ 
+   enum StartupErrors
+   {
+     STARTUPERROR_NONE, /*< The database is ready for use. */
+     STARTUPERROR_FAILED_NO_DATA, /*< There is no data for the database. */
+     STARTUPERROR_FAILED_NO_DATA_HAS_BACKUP_DATA, /*< There is no data for the database, but there is a backup file instead. */
+     STARTUPERROR_FAILED_UNKNOWN_REASON /*< Something else failed. */
+   };
+ 
  protected:
 -  /** Helper functions for backend implementations to use, so that these don't
 -   * need to worry whether glibmm was compiled with exceptions or not.
 -   */
 -  bool query_execute(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& sql_query, std::auto_ptr<Glib::Error>& error);
 -  bool set_server_operation_value(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, const Glib::ustring& path, const Glib::ustring& value, std::auto_ptr<Glib::Error>& error);
 -  Glib::RefPtr<Gnome::Gda::ServerOperation> create_server_operation(const Glib::RefPtr<Gnome::Gda::ServerProvider>& provider, const Glib::RefPtr<Gnome::Gda::Connection>& connection, Gnome::Gda::ServerOperationType type, std::auto_ptr<Glib::Error>& error);
 -  bool perform_server_operation(const Glib::RefPtr<Gnome::Gda::ServerProvider>& provider, const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, std::auto_ptr<Glib::Error>& error);
 -  bool begin_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, Gnome::Gda::TransactionIsolation level, std::auto_ptr<Glib::Error>& error);
 -  bool commit_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, std::auto_ptr<Glib::Error>& error);
 -  bool rollback_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, std::auto_ptr<Glib::Error>& error);
  
    /* TODO: Merge create_database() and initialize() into a single function?
     */
@@@ -173,7 -195,22 +189,22 @@@
  
    /** This method is called to create a new database on the
     * database server. */
 -  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error) = 0;
 +  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password) = 0;
+ 
+   /** Save a backup of the database in a tarball.
+    * This backup can later be used to recreate the database,
+    * for instance with a later version of PostgreSQL.
+    */
+   virtual bool save_backup(const SlotProgress& slot_progress, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name) = 0;
+ 
+   /** Use a backup of the database in a tarball to create the tables and data in an existing empty database.
+    * The database (server) should already have the necessary groups and users.
+    * See save_backup().
+    */
+   virtual bool convert_backup(const SlotProgress& slot_progress, const std::string& base_directory_uri, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name) = 0;
+ 
+ protected:
+   std::string m_database_directory_uri;
  };
  
  } // namespace ConnectionPoolBackends
diff --cc glom/libglom/connectionpool_backends/postgres.cc
index 4525896,d4f7b3e..3e52ce8
--- a/glom/libglom/connectionpool_backends/postgres.cc
+++ b/glom/libglom/connectionpool_backends/postgres.cc
@@@ -69,18 -73,19 +73,18 @@@ Glib::RefPtr<Gnome::Gda::Connection> Po
    Glib::RefPtr<Gnome::Gda::Connection> connection;
    Glib::RefPtr<Gnome::Gda::DataModel> data_model;
  
-   const Glib::ustring auth_string = create_auth_string(username, password);   
-  
- #ifdef GLOM_CONNECTION_DEBUG          
+   const Glib::ustring auth_string = create_auth_string(username, password);
+ 
+ #ifdef GLOM_CONNECTION_DEBUG
    std::cout << std::endl << "DEBUG: Glom: trying to connect on port=" << port << std::endl;
 -  std::cout << "DEBUG: ConnectionPoolBackends::Postgres::attempt_connect(): cnc_string=" << cnc_string << std::endl;
 +  std::cout << "debug: " << G_STRFUNC << ": cnc_string=" << cnc_string << std::endl;
    std::cout << "  DEBUG: auth_string=" << auth_string << std::endl;
  #endif
  
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
    try
    {
-     connection = Gnome::Gda::Connection::open_from_string("PostgreSQL", 
-       cnc_string, auth_string, 
+     connection = Gnome::Gda::Connection::open_from_string("PostgreSQL",
+       cnc_string, auth_string,
        Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE
        );
      connection->statement_execute_non_select("SET DATESTYLE = 'ISO'");
@@@ -88,19 -93,36 +92,18 @@@
    }
    catch(const Glib::Error& ex)
    {
- 
 -#else
 -  std::auto_ptr<Glib::Error> ex;
 -  connection = Gnome::Gda::Connection::open_from_string("PostgreSQL",
 -    cnc_string, auth_string,
 -    Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE,
 -    ex);
 -
 -  if(!ex.get())
 -    connection->statement_execute_non_select("SET DATESTYLE = 'ISO'", ex);
 -
 -  if(!ex.get())
 -    data_model = connection->statement_execute_select("SELECT version()", Gnome::Gda::STATEMENT_MODEL_RANDOM_ACCESS, ex);
 -
 -  if(!ex.get())
 -  {
 -#endif
 -
  #ifdef GLOM_CONNECTION_DEBUG
 -    std::cout << "ConnectionPoolBackends::Postgres::attempt_connect(): Attempt to connect to database failed on port=" << port << ", database=" << database << ": " << ex.what() << std::endl;
 -    std::cout << "ConnectionPoolBackends::Postgres::attempt_connect(): Attempting to connect without specifying the database." << std::endl;
 +    std::cout << "debug: " << G_STRFUNC << ": Attempt to connect to database failed on port=" << port << ", database=" << database << ": " << ex.what() << std::endl;
 +    std::cout << "debug: " << G_STRFUNC << ": Attempting to connect without specifying the database." << std::endl;
  #endif
  
 -    Glib::ustring cnc_string = cnc_string_main + ";DB_NAME=" + default_database;
 +    const Glib::ustring cnc_string = cnc_string_main + ";DB_NAME=" + default_database;
      Glib::RefPtr<Gnome::Gda::Connection> temp_conn;
      Glib::ustring auth_string = create_auth_string(username, password);
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
      try
      {
-       temp_conn = Gnome::Gda::Connection::open_from_string("PostgreSQL", 
-         cnc_string, auth_string, 
+       temp_conn = Gnome::Gda::Connection::open_from_string("PostgreSQL",
+         cnc_string, auth_string,
          Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE);
      }
      catch(const Glib::Error& ex)
diff --cc glom/libglom/connectionpool_backends/postgres.h
index 9faa899,8cb4fec..8dd32e5
--- a/glom/libglom/connectionpool_backends/postgres.h
+++ b/glom/libglom/connectionpool_backends/postgres.h
@@@ -58,16 -68,54 +68,54 @@@ private
    virtual Glib::ustring get_string_find_operator() const { return "ILIKE"; } // ILIKE is a postgres extension for locale-dependent case-insensitive matches.
    virtual const char* get_public_schema_name() const { return "public"; }
  
 -  virtual bool change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields, std::auto_ptr<Glib::Error>& error);
 +  virtual bool change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields) throw();
  
  protected:
 -  bool attempt_create_database(const Glib::ustring& database_name, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
 +  bool attempt_create_database(const Glib::ustring& database_name, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& username, const Glib::ustring& password);
  
    /** Attempt to connect to the database with the specified criteria.
 -   * @param error An error if the correction failed.
 -   */
 -  Glib::RefPtr<Gnome::Gda::Connection> attempt_connect(const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error) throw();
 +   * @throws An ExceptionConnection if the correction failed.
 +   */ 
 +  Glib::RefPtr<Gnome::Gda::Connection> attempt_connect(const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password);
  
+  std::string get_self_hosting_path(bool create = false, const std::string& child_directory = std::string());
+ 
+   /** Get the path to the config sub-directory, optionally creating it.
+    */
+   std::string get_self_hosting_config_path(bool create = false);
+ 
+   /** Get the path to the data sub-directory, optionally creating it.
+    */
+   std::string get_self_hosting_data_path(bool create = false);
+ 
+   /** Get the path to the backup file, regardless of whether it exists.
+    * @param base_directory Where to find the backup file, under a normal Glom directory structure.
+    * If @a base_directory is empty then it uses get_database_directory_uri().
+    */
+   std::string get_self_hosting_backup_path(const std::string& base_directory = std::string(), bool create_parent_dir = false);
+ 
+   bool create_directory_filepath(const std::string& filepath);
+   bool file_exists_filepath(const std::string& filepath);
+   bool file_exists_uri(const std::string& uri) const;
+ 
+   /**
+    * @param current_user_only If true then only the current user will be able to read or write the file.
+    */
+   static bool create_text_file(const std::string& file_uri, const std::string& contents, bool current_user_only = false);
+ 
+   /**
+    * @param filepath_previous The path to which the previous .pgpass, if any was moved.
+    * @param filepath_original The path to which filepath_previous should be moved back after the caller has finished.
+    * @param result whether it succeeded.
+    */
+   bool save_password_to_pgpass(const Glib::ustring username, const Glib::ustring& password, std::string& filepath_previous, std::string& filepath_original);
+ 
+ protected:
+   static Glib::ustring port_as_string(int port_num);
+ 
+   Glib::ustring m_host;
+   int m_port;
+ 
  private:
    float m_postgres_server_version;
  };
diff --cc glom/libglom/connectionpool_backends/postgres_central.cc
index ea5dc8f,2666f78..ca56275
--- a/glom/libglom/connectionpool_backends/postgres_central.cc
+++ b/glom/libglom/connectionpool_backends/postgres_central.cc
@@@ -135,10 -109,11 +117,10 @@@ Glib::RefPtr<Gnome::Gda::Connection> Po
      while(!connection && iter_port != m_list_ports.end())
      {
        port = *iter_port;
-       
 -      connection = attempt_connect(port, database, username, password, error);
+ 
 -      // Remember port if only the database was missing
 -      if(error.get() && error->get_failure_type() == ExceptionConnection::FAILURE_NO_DATABASE)
 +      try
        {
 +        connection = attempt_connect(m_host, port, database, username, password);
          connection_possible = true;
          m_port = atoi(port.c_str());
        }
diff --cc glom/libglom/connectionpool_backends/postgres_self.cc
index eb68609,35674ed..958414e
--- a/glom/libglom/connectionpool_backends/postgres_self.cc
+++ b/glom/libglom/connectionpool_backends/postgres_self.cc
@@@ -221,12 -167,12 +167,12 @@@ Backend::InitErrors PostgresSelfHosted:
  {
    m_network_shared = network_shared;
  
-   if(m_self_hosting_data_uri.empty())
+   if(m_database_directory_uri.empty())
    {
 -    std::cerr << "PostgresSelfHosted::initialize: m_database_directory_uri is empty." << std::endl;
 +    std::cerr << G_STRFUNC << ": initialize: m_self_hosting_data_uri is empty." << std::endl;
      return INITERROR_OTHER;
    }
-   
+ 
    if(initial_username.empty())
    {
      std::cerr << "PostgresSelfHosted::initialize(). Username was empty while attempting to create self-hosting database" << std::endl;
@@@ -320,9 -264,10 +264,9 @@@ Glib::ustring PostgresSelfHosted::get_p
    //Use a regex to get the version number:
    Glib::RefPtr<Glib::Regex> regex;
  
-   //We want the characters at the end:  
+   //We want the characters at the end:
    const gchar* VERSION_REGEX = "pg_ctl \\(PostgreSQL\\) (.*)";
  
 -  #ifdef GLIBMM_EXCEPTIONS_ENABLED
    try
    {
      regex = Glib::Regex::create(VERSION_REGEX);
@@@ -331,8 -276,17 +275,8 @@@
    {
      std::cerr << "Glom: Glib::Regex::create() failed: " << ex.what() << std::endl;
      return result;
 -  }
 -  #else
 -  std::auto_ptr<Glib::Error> ex;
 -  regex = Glib::Regex::create(VERSION_REGEX, static_cast<Glib::RegexCompileFlags>(0), static_cast<Glib::RegexMatchFlags>(0), ex);
 -  if(ex.get())
 -  {
 -    std::cerr << "Glom: Glib::Regex::create() failed: " << ex->what() << std::endl;
 -    return result;
 -  }
 -  #endif
 +  } 
-  
+ 
    if(!regex)
      return result;
  
@@@ -362,9 -316,10 +306,9 @@@ float PostgresSelfHosted::get_postgresq
  
    Glib::RefPtr<Glib::Regex> regex;
  
-   //We want the characters at the end:  
+   //We want the characters at the end:
    const gchar* VERSION_REGEX = "^(\\d*)\\.(\\d*)";
  
 -  #ifdef GLIBMM_EXCEPTIONS_ENABLED
    try
    {
      regex = Glib::Regex::create(VERSION_REGEX);
@@@ -373,8 -328,17 +317,8 @@@
    {
      std::cerr << "Glom: Glib::Regex::create() failed: " << ex.what() << std::endl;
      return result;
 -  }
 -  #else
 -  std::auto_ptr<Glib::Error> ex;
 -  regex = Glib::Regex::create(VERSION_REGEX, static_cast<Glib::RegexCompileFlags>(0), static_cast<Glib::RegexMatchFlags>(0), ex);
 -  if(ex.get())
 -  {
 -    std::cerr << "Glom: Glib::Regex::create() failed: " << ex->what() << std::endl;
 -    return result;
 -  }
 -  #endif
 +  } 
-  
+ 
    if(!regex)
      return result;
  
@@@ -420,40 -384,51 +364,53 @@@ Backend::StartupErrors PostgresSelfHost
    //g_assert(!get_self_hosting_active());
  
    if(get_self_hosting_active())
-     return true; //Just do it once.
+   {
+     std::cerr << G_STRFUNC << ": Already started." << std::endl;
+     return STARTUPERROR_NONE; //Just do it once.
+   }
  
-   const std::string dbdir_uri = m_self_hosting_data_uri;
+   const std::string dbdir_uri = m_database_directory_uri;
  
-   if(!(directory_exists_uri(dbdir_uri)))
+   if(!(file_exists_uri(dbdir_uri)))
    {
 -    std::cerr << "ConnectionPool::create_self_hosting(): The directory could not be found: " << dbdir_uri << std::endl;
 +    //TODO: Use a return enum or exception so we can tell the user about this:
 +    std::cerr << G_STRFUNC << ": The data directory could not be found: " << dbdir_uri << std::endl;
-     return false;
+     return STARTUPERROR_FAILED_UNKNOWN_REASON;
    }
  
    const std::string dbdir = Glib::filename_from_uri(dbdir_uri);
    g_assert(!dbdir.empty());
  
-   const std::string dbdir_data = Glib::build_filename(dbdir, "data");
-   const std::string dbdir_data_uri = Glib::filename_to_uri(dbdir_data);
-   if(!(directory_exists_uri(dbdir_data_uri)))
+   const std::string dbdir_data = Glib::build_filename(dbdir, FILENAME_DATA);
+   const Glib::ustring dbdir_data_uri = Glib::filename_to_uri(dbdir_data);
+   if(!(file_exists_uri(dbdir_data_uri)))
    {
-     //TODO: Use a return enum or exception so we can tell the user about this:
-     std::cerr << G_STRFUNC << ": The data sub-directory could not be found." << dbdir_data_uri << std::endl;
-     return false;
+     const std::string dbdir_backup = Glib::build_filename(dbdir, FILENAME_BACKUP);
+     const Glib::ustring dbdir_backup_uri = Glib::filename_to_uri(dbdir_backup);
+     if(file_exists_uri(dbdir_backup_uri))
+     {
+       std::cerr << G_STRFUNC << ": There is no data, but there is backup data." << std::endl;
+       //Let the caller convert the backup to real data and then try again:
+       return STARTUPERROR_FAILED_NO_DATA_HAS_BACKUP_DATA;
+     }
+     else
+     {
+       std::cerr << "ConnectionPool::create_self_hosting(): The data sub-directory could not be found." << dbdir_data_uri << std::endl;
+       return STARTUPERROR_FAILED_NO_DATA;
+     }
    }
  
+   //Attempt to ensure that the config files are correct:
+   set_network_shared(slot_progress, m_network_shared); //Creates pg_hba.conf and pg_ident.conf
+ 
  
    const int available_port = discover_first_free_port(PORT_POSTGRESQL_SELF_HOSTED_START, PORT_POSTGRESQL_SELF_HOSTED_END);
 -  //std::cout << "ConnectionPool::create_self_hosting():() : debug: Available port for self-hosting: " << available_port << std::endl;
 +  //std::cout << "debug: " << G_STRFUNC << ":() : debug: Available port for self-hosting: " << available_port << std::endl;
    if(available_port == 0)
    {
 -    std::cerr << "ConnectionPool::create_self_hosting(): No port was available between " << PORT_POSTGRESQL_SELF_HOSTED_START << " and " << PORT_POSTGRESQL_SELF_HOSTED_END << std::endl;
 +    //TODO: Use a return enum or exception so we can tell the user about this:
 +    std::cerr << G_STRFUNC << ": No port was available between " << PORT_POSTGRESQL_SELF_HOSTED_START << " and " << PORT_POSTGRESQL_SELF_HOSTED_END << std::endl;
-     return false;
+     return STARTUPERROR_FAILED_UNKNOWN_REASON;
    }
  
    //TODO: Performance:
@@@ -602,36 -575,31 +557,34 @@@ Glib::RefPtr<Gnome::Gda::Connection> Po
      return Glib::RefPtr<Gnome::Gda::Connection>();
    }
  
--  std::auto_ptr<ExceptionConnection> ex;
--
    Glib::RefPtr<Gnome::Gda::Connection> result;
    bool keep_trying = true;
    guint count_retries = 0;
    const guint MAX_RETRIES_KNOWN_PASSWORD = 30; /* seconds */
    const guint MAX_RETRIES_EVER = 60; /* seconds */
    while(keep_trying)
-   { 
+   {
 -    result = attempt_connect(port_as_string(m_port), database, username, password, ex);
 -    if(!result &&
 -      ex.get() && (ex->get_failure_type() == ExceptionConnection::FAILURE_NO_SERVER))
 +    try
 +    {
-       result = attempt_connect("localhost", port_as_string(m_port), database, username, password);
++      result = attempt_connect(m_host, port_as_string(m_port), database, username, password);
 +    }
-     catch(const ExceptionConnection& ex)
++    catch(const ExceptionConnection ex)
      {
 -      //It must be using a default password, so any failure would not be due to a wrong password.
 -      //However, pg_ctl sometimes reports success before it is really ready to let us connect,
 -      //so in this case we can just keep trying until it works, with a very long timeout.
 -      count_retries++;
 -      const guint max_retries = m_network_shared ? MAX_RETRIES_EVER : MAX_RETRIES_KNOWN_PASSWORD;
 -      if(count_retries > max_retries)
 +      if(ex.get_failure_type() == ExceptionConnection::FAILURE_NO_SERVER)
        {
 -        keep_trying = false;
 -        continue;
 +        //It must be using a default password, so any failure would not be due to a wrong password.
 +        //However, pg_ctl sometimes reports success before it is really ready to let us connect, 
 +        //so in this case we can just keep trying until it works, with a very long timeout.
 +        count_retries++;
 +        const guint max_retries = m_network_shared ? MAX_RETRIES_EVER : MAX_RETRIES_KNOWN_PASSWORD;
 +        if(count_retries > max_retries)
 +        {
 +          keep_trying = false;
 +          continue;
 +        }
        }
  
 -      std::cout << "DEBUG: Glom::PostgresSelfHosted::connect(): Waiting and retrying the connection due to suspected too-early success of pg_ctl." << std::endl;
 +      std::cout << "debug: " << G_STRFUNC << ": Waiting and retrying the connection due to suspected too-early success of pg_ctl." << std::endl; 
  
        //Wait:
        Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create(false);
diff --cc glom/libglom/connectionpool_backends/sqlite.cc
index 7ee4f97,a7bb785..99b13ea
--- a/glom/libglom/connectionpool_backends/sqlite.cc
+++ b/glom/libglom/connectionpool_backends/sqlite.cc
@@@ -34,17 -34,7 +34,7 @@@ Sqlite::Sqlite(
  {
  }
  
- void Sqlite::set_database_directory_uri(const std::string& directory_uri)
- {
-   m_database_directory_uri = directory_uri;
- }
- 
- const std::string& Sqlite::get_database_directory_uri() const
- {
-   return m_database_directory_uri;
- }
- 
 -Glib::RefPtr<Gnome::Gda::Connection> Sqlite::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error)
 +Glib::RefPtr<Gnome::Gda::Connection> Sqlite::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password)
  {
    Glib::RefPtr<Gnome::Gda::Connection> connection;
    if(m_database_directory_uri.empty())
@@@ -89,13 -95,30 +79,13 @@@ bool Sqlite::create_database(const Glib
      return false;
  
    Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(m_database_directory_uri);
-   const std::string database_directory = file->get_path(); 
+   const std::string database_directory = file->get_path();
    const Glib::ustring cnc_string = Glib::ustring::compose("DB_DIR=%1;DB_NAME=%2", database_directory, database_name);
  
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -  try
 -  {
 -    Glib::RefPtr<Gnome::Gda::Connection> cnc =
 -      Gnome::Gda::Connection::open_from_string("SQLite",
 -        cnc_string, "",
 -        Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE);
 -  }
 -  catch(const Glib::Error& ex)
 -  {
 -    error.reset(new Glib::Error(ex));
 -    return false;
 -  }
 -#else
 -  Glib::RefPtr<Gnome::Gda::Connection> cnc =
 -    Gnome::Gda::Connection::open_from_string("SQLite",
 +  Glib::RefPtr<Gnome::Gda::Connection> cnc = 
 +    Gnome::Gda::Connection::open_from_string("SQLite", 
        cnc_string, "",
 -      Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE, error);
 -  if(error.get() != 0)
 -    return false;
 -#endif
 +      Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE);
  
    return true;
  }
@@@ -118,9 -141,10 +108,9 @@@ bool Sqlite::add_column_to_server_opera
  
    if(column->default_value)
    {
 -    if(!set_server_operation_value(operation, default_path, column->default_value, error))
 -      return false;
 +    operation->set_value_at(default_path, column->default_value);
    }
-   
+ 
    return true;
  }
  
@@@ -148,9 -172,12 +138,8 @@@ bool Sqlite::recreate_table(const Glib:
  
    Glib::RefPtr<Gnome::Gda::MetaStore> store = connection->get_meta_store();
    Glib::RefPtr<Gnome::Gda::MetaStruct> metastruct = Gnome::Gda::MetaStruct::create(store, Gnome::Gda::META_STRUCT_FEATURE_NONE);
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
 -  GdaMetaDbObject* object = metastruct->complement(Gnome::Gda::META_DB_TABLE, Gnome::Gda::Value(), Gnome::Gda::Value(), Gnome::Gda::Value(table_name));
 -#else
 -  GdaMetaDbObject* object = metastruct->complement(Gnome::Gda::META_DB_TABLE, Gnome::Gda::Value(), Gnome::Gda::Value(), Gnome::Gda::Value(table_name), error);
 -#endif
  
 +  GdaMetaDbObject* object = metastruct->complement(Gnome::Gda::META_DB_TABLE, Gnome::Gda::Value(), Gnome::Gda::Value(), Gnome::Gda::Value(table_name));
-   
    if(!object)
      return false;
  
@@@ -369,9 -384,23 +358,23 @@@ bool Sqlite::change_columns(const Glib:
    for(type_vec_const_fields::size_type i = 0; i < old_fields.size(); ++ i)
      fields_changed[old_fields[i]->get_name()] = new_fields[i];
  
 -  return recreate_table(connection, table_name, type_vec_strings(), type_vec_const_fields(), fields_changed, error);
 +  return recreate_table(connection, table_name, type_vec_strings(), type_vec_const_fields(), fields_changed);
  }
  
+ bool Sqlite::save_backup(const SlotProgress& /* slot_progress */, const Glib::ustring& /* username */, const Glib::ustring& /* password */, const Glib::ustring& /* database_name */)
+ {
+   //TODO:
+   std::cerr << G_STRFUNC << ": Not implemented.";
+   return false;
+ }
+ 
+ bool Sqlite::convert_backup(const SlotProgress& /* slot_progress */, const std::string& /* base_directory */, const Glib::ustring& /* username */, const Glib::ustring& /* password */, const Glib::ustring& /* database_name */)
+ {
+   //TODO:
+   std::cerr << G_STRFUNC << ": Not implemented.";
+   return false;
+ }
+ 
  
  } // namespace ConnectionPoolBackends
  
diff --cc glom/libglom/connectionpool_backends/sqlite.h
index 3fbf6ea,d4ae24b..03b34a2
--- a/glom/libglom/connectionpool_backends/sqlite.h
+++ b/glom/libglom/connectionpool_backends/sqlite.h
@@@ -63,10 -60,10 +60,10 @@@ private
  
    /** Creates a new database.
     */
 -  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
 +  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password);
  
- private:
-   std::string m_database_directory_uri;
+   virtual bool save_backup(const SlotProgress& slot_progress, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name);
+   virtual bool convert_backup(const SlotProgress& slot_progress, const std::string& base_directory, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name);
  };
  
  } //namespace ConnectionPoolBackends
diff --cc glom/libglom/document/document.cc
index 26bba25,7cf2f31..dffb483
--- a/glom/libglom/document/document.cc
+++ b/glom/libglom/document/document.cc
@@@ -1523,9 -1530,9 +1530,9 @@@ Document::type_list_layout_groups Docum
  
    if(create_default)
    {
 -    std::cout << "DEBUG: Document::get_data_layout_groups_plus_new_fields(): Creating a default layout." << std::endl;
 +    std::cout << "debug: " << G_STRFUNC << ": Creating a default layout." << std::endl;
      result = get_data_layout_groups_default(layout_name, parent_table_name, layout_platform);
-     
+ 
      //Make the default layout suitable for the special platform:
      if(layout_platform == "maemo")
      {
@@@ -2013,9 -2025,9 +2025,9 @@@ void Document::load_after_layout_item_u
    {
      sharedptr<Relationship> related_relationship = get_relationship(relationship->get_to_table(), related_relationship_name);
      if(!related_relationship)
 -      std::cerr << "Document::load_after_layout_item_field(): related relationship not found in table=" << relationship->get_to_table() << ",  name=" << related_relationship_name << std::endl;
 +      std::cerr << G_STRFUNC << ": related relationship not found in table=" << relationship->get_to_table() << ",  name=" << related_relationship_name << std::endl;
  
-     item->set_related_relationship(related_relationship); 
+     item->set_related_relationship(related_relationship);
    }
  }
  
diff --cc glom/libglom/spawn_with_feedback.cc
index 6e5078f,475247d..ddc66e1
--- a/glom/libglom/spawn_with_feedback.cc
+++ b/glom/libglom/spawn_with_feedback.cc
@@@ -206,7 -242,8 +206,7 @@@ public
        if(redirect & REDIRECT_STDERR)
          redirect_to_string(child_stderr, stderr_text);
      }
-     catch(Glib::Exception& ex)
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
+     catch(const Glib::Exception& ex)
      {
        throw SpawnError(ex.what());
      }
@@@ -353,8 -391,18 +353,18 @@@ bool execute_command_line_and_wait(cons
  {
    //Show UI progress feedback while we wait for the command to finish:
  
-   std::auto_ptr<const Impl::SpawnInfo> info = Impl::spawn_async(command, 0);
+   std::auto_ptr<const Impl::SpawnInfo> info;
+   
+   try
+   {
+     info = Impl::spawn_async(command, 0);
+   }
+   catch(const Impl::SpawnError& ex)
+   {
+     std::cerr << G_STRFUNC << ": exception: " << ex.what() << std::endl;
+     return false;
+   }
 -  
 +
    Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create(false);
    info->signal_finished().connect(
      sigc::bind(sigc::ptr_fun(&on_spawn_info_finished), sigc::ref(mainloop) ) );
@@@ -386,8 -434,18 +396,19 @@@ bool execute_command_line_and_wait(cons
  
    //Show UI progress feedback while we wait for the command to finish:
  
-   std::auto_ptr<const Impl::SpawnInfo> info = Impl::spawn_async(command, Impl::REDIRECT_STDOUT | Impl::REDIRECT_STDERR);
+   std::auto_ptr<const Impl::SpawnInfo> info;
+   
+   try
+   {
+     info = Impl::spawn_async(command, Impl::REDIRECT_STDOUT | Impl::REDIRECT_STDERR);
+   }
+   catch(const Impl::SpawnError& ex)
+   {
+     std::cerr << G_STRFUNC << ": exception: " << ex.what() << std::endl;
+     return false;
+   }
+   
 +
    Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create(false);
    info->signal_finished().connect(
      sigc::bind(sigc::ptr_fun(&on_spawn_info_finished), sigc::ref(mainloop) ) );
diff --cc glom/main.cc
index 7011d2a,aaae0c6..81f1e44
--- a/glom/main.cc
+++ b/glom/main.cc
@@@ -458,14 -469,39 +466,14 @@@ main(int argc, char* argv[]
    {
      std::cerr << "Glom: Error while initializing gtkmm: " << ex.what() << std::endl;
      return 0;
-   }    
+   }
 -#else
 -  if (!mainInstance.get())
 -  {
 -    std::cerr << "Glom: Error while initializing gtkmm" << std::endl;
 -    return 0;
 -  }
 -#endif
  
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
    try
 -#else
 -  std::auto_ptr<Glib::Error> error;
 -#endif // GLIBMM_EXCEPTIONS_ENABLED
    {
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
      context.parse(argc, argv);
 -#else
 -    context.parse(argc, argv, error);
 -#endif // GLIBMM_EXCEPTIONS_ENABLED
    }
 -#ifdef GLIBMM_EXCEPTIONS_ENABLED
    catch(const Glib::OptionError& ex)
 -#else
 -  if(error.get())
 -#endif
    {
 -#ifndef GLIBMM_EXCEPTIONS_ENABLED
 -    const Glib::OptionError* exptr = dynamic_cast<Glib::OptionError*>(error.get());
 -    if(exptr)
 -    {
 -      const Glib::OptionError& ex = *exptr;
 -#endif // !GLIBMM_EXCEPTIONS_ENABLED
        std::cout << _("Error while parsing command-line options: ") << std::endl << ex.what() << std::endl;
        std::cout << _("Use --help to see a list of available command-line options.") << std::endl;
        return 0;
diff --cc glom/mode_design/relationships_overview/dialog_relationships_overview.cc
index 2cedd08,53ab212..20ed690
--- a/glom/mode_design/relationships_overview/dialog_relationships_overview.cc
+++ b/glom/mode_design/relationships_overview/dialog_relationships_overview.cc
@@@ -99,9 -103,17 +100,9 @@@ Dialog_RelationshipsOverview::Dialog_Re
    {
      std::cerr << "building menus failed: " <<  ex.what();
    }
 -  #else
 -  std::auto_ptr<Glib::Error> error;
 -  m_refUIManager->add_ui_from_string(ui_info, error);
 -  if(error.get())
 -  {
 -    std::cerr << "building menus failed: " << error->what();
 -  }
 -  #endif
  
    //Get the menu:
-   m_menu = dynamic_cast<Gtk::MenuBar*>( m_refUIManager->get_widget("/Overview_MainMenu") ); 
+   m_menu = dynamic_cast<Gtk::MenuBar*>( m_refUIManager->get_widget("/Overview_MainMenu") );
    if(!m_menu)
      g_warning("menu not found");
  
@@@ -486,9 -498,11 +487,9 @@@ void Dialog_RelationshipsOverview::setu
    m_context_menu_uimanager = Gtk::UIManager::create();
    m_context_menu_uimanager->insert_action_group(m_context_menu_action_group);
  
 -  #ifdef GLIBMM_EXCEPTIONS_ENABLED
    try
    {
-     Glib::ustring ui_info = 
 -  #endif
+     Glib::ustring ui_info =
      "<ui>"
      "  <popup name='ContextMenu'>"
      "  <menuitem action='ContextEditFields'/>"
@@@ -502,9 -517,17 +503,9 @@@
    {
      std::cerr << "building menus failed: " <<  ex.what();
    }
 -  #else
 -  std::auto_ptr<Glib::Error> error;
 -  m_context_menu_uimanager->add_ui_from_string(ui_info, error);
 -  if(error.get())
 -  {
 -    std::cerr << "building menus failed: " << error->what();
 -  }
 -  #endif
  
    //Get the menu:
-   m_context_menu = dynamic_cast<Gtk::Menu*>( m_context_menu_uimanager->get_widget("/ContextMenu") ); 
+   m_context_menu = dynamic_cast<Gtk::Menu*>( m_context_menu_uimanager->get_widget("/ContextMenu") );
  }
  
  void Dialog_RelationshipsOverview::on_context_menu_edit_fields(Glib::RefPtr<CanvasGroupDbTable> table)
diff --cc glom/print_layout/canvas_layout_item.cc
index ecc4dbc,0d9e3c1..d60eb1f
--- a/glom/print_layout/canvas_layout_item.cc
+++ b/glom/print_layout/canvas_layout_item.cc
@@@ -232,10 -252,15 +232,10 @@@ Glib::RefPtr<CanvasItemMovable> CanvasL
          double end_x  = 0;
          double end_y = 0;
          line->get_coordinates(start_x, start_y, end_x, end_y);
-         
+ 
          Glib::RefPtr<CanvasLineMovable> canvas_item = CanvasLineMovable::create();
 -        #ifdef GLIBMM_PROPERTIES_ENABLED
          canvas_item->property_line_width() = 1;
          canvas_item->property_stroke_color() = "black";
 -        #else
 -        canvas_item->set_property("line-width", 1);
 -        canvas_item->set_property("stroke-color", Glib::ustring("black"));
 -        #endif
  
          Goocanvas::Points points(2);
          points.set_coordinate(0, start_x, start_y);
@@@ -261,8 -290,12 +261,7 @@@
            else //text, numbers, date, time, boolean:
            {
              Glib::RefPtr<CanvasTextMovable> canvas_item = CanvasTextMovable::create();
 -            #ifdef GLIBMM_PROPERTIES_ENABLED
              canvas_item->property_line_width() = 0;
-          
 -            #else
 -            canvas_item->set_property("line-width", 0);
 -            #endif
 -
              apply_formatting(canvas_item, field);
  
              Glib::ustring name = field->get_name();
@@@ -427,9 -466,9 +426,9 @@@ void CanvasLayoutItem::set_db_data(cons
        break;
      }
      default:
 -      std::cerr << "CanvasLayoutItem::set_db_data(): unhandled field type." << std::endl;
 +      std::cerr << G_STRFUNC << ": unhandled field type." << std::endl;
    }
-         
+ 
  }
  
  void CanvasLayoutItem::remove_empty_indicators()



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