glom r1726 - in trunk: . glom glom/libglom glom/libglom/connectionpool_backends glom/libglom/document glom/utility_widgets



Author: arminb
Date: Fri Nov 21 13:04:29 2008
New Revision: 1726
URL: http://svn.gnome.org/viewvc/glom?rev=1726&view=rev

Log:
2008-11-21  Armin Burgmeier  <armin openismus com>

	* glom/libglom/connectionpool.h: Changed connect() and
	create_database() functions of Backend to always take an error
	parameter as last argument, to save ugly #ifdefs. The ConnectionPool
	is the only one accessing these functions anyway, so this is not part
	of "public" API.

	* glom/libglom/connectionpool_backends/postgres_self.h:
	* glom/libglom/connectionpool_backends/postgres_self.cc:
	* glom/libglom/connectionpool_backends/postgres_central.h:
	* glom/libglom/connectionpool_backends/postgres_central.cc: Adapt.

	* glom/libglom/connectionpool_backends/sqlite.h:
	* glom/libglom/connectionpool_backends/sqlite.cc:
	* glom/libglom/connectionpool_backends/Makefile.am: Added a sqlite for
	creating and connecting to SQlite databases.

	* glom/libglom/document/document_glom.h:
	* glom/libglom/document/document_glom.cc: Replace self_hosted
	attribute by a hosting_mode one in the document XML, which can be
	either "postgres_central", "postgres_self" or "sqlite".

	* glom/utility_widgets/filechooserdialog_saveextras.h:
	* glom/utility_widgets/filechooserdialog_saveextras.cc: Offer to store
	the data in a SQlite database.

	* glom/application.h:
	* glom/application.cc:
	* glom/dialog_connection.cc:
	* glom/frame_glom.cc: Handle the SQlite case, create corresponding
	ConnectionPool backend. It is possible to create a SQlite database
	this way, but some initial queries still fail yet because they are
	specific to postgres.


Added:
   trunk/glom/libglom/connectionpool_backends/sqlite.cc
   trunk/glom/libglom/connectionpool_backends/sqlite.h
Modified:
   trunk/ChangeLog
   trunk/glom/application.cc
   trunk/glom/application.h
   trunk/glom/dialog_connection.cc
   trunk/glom/frame_glom.cc
   trunk/glom/libglom/connectionpool.cc
   trunk/glom/libglom/connectionpool.h
   trunk/glom/libglom/connectionpool_backends/Makefile.am
   trunk/glom/libglom/connectionpool_backends/postgres_central.cc
   trunk/glom/libglom/connectionpool_backends/postgres_central.h
   trunk/glom/libglom/connectionpool_backends/postgres_self.cc
   trunk/glom/libglom/connectionpool_backends/postgres_self.h
   trunk/glom/libglom/document/document_glom.cc
   trunk/glom/libglom/document/document_glom.h
   trunk/glom/utility_widgets/filechooserdialog_saveextras.cc
   trunk/glom/utility_widgets/filechooserdialog_saveextras.h

Modified: trunk/glom/application.cc
==============================================================================
--- trunk/glom/application.cc	(original)
+++ trunk/glom/application.cc	Fri Nov 21 13:04:29 2008
@@ -113,7 +113,7 @@
   m_menu_print_layouts_ui_merge_id(0),
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   m_ui_save_extra_showextras(false),
-  m_ui_save_extra_newdb_selfhosted(false),
+  m_ui_save_extra_newdb_hosting_mode(Document_Glom::POSTGRES_CENTRAL_HOSTED),
 #endif // !GLOM_ENABLE_CLIENT_ONLY
   m_show_sql_debug(false)
 {
@@ -708,9 +708,11 @@
       // Connection is always remote-hosted in client only mode:
 #ifndef GLOM_ENABLE_CLIENT_ONLY
       //Stop the document from being self-hosted (it's already hosted by the other networked Glom instance):
-      document_temp.set_connection_is_self_hosted(false);
-      // TODO: Set port from epc info(?)
+      if(document_temp.get_hosting_mode() == Document_Glom::POSTGRES_SELF_HOSTED)
+        document_temp.set_hosting_mode(Document_Glom::POSTGRES_CENTRAL_HOSTED);
 #endif // !GLOM_ENABLE_CLIENT_ONLY
+      // TODO: Error out in case this is a sqlite database, since we probably
+      // can't access it from this host?
 
       //If the publisher thinks that it's using a postgres database on localhost, 
       //then we need to use a host name that means the same thing from the client's PC:
@@ -934,7 +936,7 @@
         m_ui_save_extra_title = _("Creating From Example File");
         m_ui_save_extra_message = _("To use this example file you must save an editable copy of the file. A new database will also be created on the server.");
         m_ui_save_extra_newdb_title = "TODO";
-        m_ui_save_extra_newdb_selfhosted = true;
+        m_ui_save_extra_newdb_hosting_mode = Document_Glom::POSTGRES_SELF_HOSTED;
         offer_saveas();
         // Note that bakery will try to add the example file itself to the
         // recently used documents, which is not what we want.
@@ -943,8 +945,8 @@
 
         //Get the results from the extended save dialog:
         pDocument->set_database_title(m_ui_save_extra_newdb_title);
-        pDocument->set_connection_is_self_hosted(m_ui_save_extra_newdb_selfhosted);
-        m_ui_save_extra_newdb_selfhosted = false;
+        pDocument->set_hosting_mode(m_ui_save_extra_newdb_hosting_mode);
+        m_ui_save_extra_newdb_hosting_mode = Document_Glom::POSTGRES_CENTRAL_HOSTED;
 
         m_ui_save_extra_newdb_title.clear();
         m_ui_save_extra_showextras = false;
@@ -1232,7 +1234,7 @@
   Glib::ustring db_title;
 
   m_ui_save_extra_showextras = true; //Offer self-hosting or central hosting, and offer the database title.
-  m_ui_save_extra_newdb_selfhosted = true; /* Default to self-hosting */
+  m_ui_save_extra_newdb_hosting_mode = Document_Glom::POSTGRES_SELF_HOSTED; /* Default to self-hosting */
   m_ui_save_extra_newdb_title.clear();
   offer_saveas();
 
@@ -1242,15 +1244,15 @@
   {
     //Get details from the extended save dialog:
     const Glib::ustring db_title = m_ui_save_extra_newdb_title;
-    const bool self_hosted = m_ui_save_extra_newdb_selfhosted;
+    Document_Glom::HostingMode hosting_mode = m_ui_save_extra_newdb_hosting_mode;
     m_ui_save_extra_newdb_title.clear();
-    m_ui_save_extra_newdb_selfhosted = false;
+    m_ui_save_extra_newdb_hosting_mode = Document_Glom::POSTGRES_CENTRAL_HOSTED;
 
     //Make sure that the user can do something with his new document:
     document->set_userlevel(AppState::USERLEVEL_DEVELOPER);
     // Try various ports if connecting to an existing database server instead
     // of self-hosting one:
-    document->set_connection_try_other_ports(!m_ui_save_extra_newdb_selfhosted);
+    document->set_connection_try_other_ports(m_ui_save_extra_newdb_hosting_mode == Document_Glom::POSTGRES_CENTRAL_HOSTED);
 
     //Each new document must have an associated new database,
     //so choose a name
@@ -1266,7 +1268,7 @@
 
     //Connect to the server and choose a variation of this db_name that does not exist yet:
     document->set_connection_database(db_name);
-    document->set_connection_is_self_hosted(self_hosted);
+    document->set_hosting_mode(hosting_mode);
          
    //Tell the connection pool about the document:
    ConnectionPool* connection_pool = ConnectionPool::get_instance();
@@ -1877,7 +1879,7 @@
   m_ui_save_extra_title.clear();
   m_ui_save_extra_message.clear();
   m_ui_save_extra_newdb_title.clear();
-  m_ui_save_extra_newdb_selfhosted = false;
+  m_ui_save_extra_newdb_hosting_mode = Document_Glom::POSTGRES_CENTRAL_HOSTED;
 
   Glib::ustring file_uri = ui_file_select_save(file_uriOld); //Also asks for overwrite confirmation.
   if(!file_uri.empty())
@@ -2094,7 +2096,7 @@
     fileChooser_SaveExtras->set_extra_newdb_title(m_ui_save_extra_newdb_title); 
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-    fileChooser_SaveExtras->set_extra_newdb_self_hosted(m_ui_save_extra_newdb_selfhosted);
+    fileChooser_SaveExtras->set_extra_newdb_hosting_mode(m_ui_save_extra_newdb_hosting_mode);
 #endif // !GLOM_ENABLE_CLIENT_ONLY
   }
 
@@ -2184,7 +2186,7 @@
         m_ui_save_extra_newdb_title = fileChooser_SaveExtras->get_extra_newdb_title();
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-        m_ui_save_extra_newdb_selfhosted = fileChooser_SaveExtras->get_extra_newdb_self_hosted();
+        m_ui_save_extra_newdb_hosting_mode = fileChooser_SaveExtras->get_extra_newdb_hosting_mode();
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
         if(m_ui_save_extra_newdb_title.empty())
@@ -2196,8 +2198,11 @@
         }
       }
  
-#ifndef GLOM_ENABLE_CLIENT_ONLY
-      if(!try_again && fileChooser_SaveExtras && m_ui_save_extra_newdb_selfhosted)
+      // Create a directory for self-hosted databases (sqlite or self-hosted
+      // postgresql).
+      if(!try_again && fileChooser_SaveExtras &&
+         (m_ui_save_extra_newdb_hosting_mode == Document_Glom::POSTGRES_SELF_HOSTED ||
+          m_ui_save_extra_newdb_hosting_mode == Document_Glom::SQLITE_HOSTED))
       {
         //Check that the directory does not exist already.
         //The GtkFileChooser could not check for that because it could not know that we would create a directory based on the filename:
@@ -2231,7 +2236,6 @@
         Glib::RefPtr<Gio::File> file_whole = dir->get_child(filename_part);
         return file_whole->get_uri();
       }
-#endif // !GLOM_ENABLE_CLIENT_ONLY
 
       if(!try_again)
       {

Modified: trunk/glom/application.h
==============================================================================
--- trunk/glom/application.h	(original)
+++ trunk/glom/application.h	Fri Nov 21 13:04:29 2008
@@ -175,7 +175,7 @@
 
   Glib::ustring m_ui_save_extra_newdb_title;
 
-  bool m_ui_save_extra_newdb_selfhosted;
+  Document_Glom::HostingMode m_ui_save_extra_newdb_hosting_mode;
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
   // This is set to the URI of an example file that is loaded to be able to

Modified: trunk/glom/dialog_connection.cc
==============================================================================
--- trunk/glom/dialog_connection.cc	(original)
+++ trunk/glom/dialog_connection.cc	Fri Nov 21 13:04:29 2008
@@ -90,7 +90,7 @@
       //std::cout << "debug: Dialog_Connection::connect_to_server_with_connection_settings(): m_database_name=" << m_database_name << std::endl;
       connection_pool->set_database(m_database_name);
 
-      if(!document->get_connection_is_self_hosted())
+      if(document->get_hosting_mode() == Document_Glom::POSTGRES_CENTRAL_HOSTED)
       {
         ConnectionPoolBackend* backend = connection_pool->get_backend();
         ConnectionPoolBackends::PostgresCentralHosted* central = dynamic_cast<ConnectionPoolBackends::PostgresCentralHosted*>(backend);
@@ -121,7 +121,7 @@
       //to make opening faster next time,
       //and so we can tell connecting clients (using browse network) what port to use:
       Document_Glom* unconst = const_cast<Document_Glom*>(document);
-      if(!document->get_connection_is_self_hosted())
+      if(document->get_hosting_mode() == Document_Glom::POSTGRES_CENTRAL_HOSTED)
       {
         ConnectionPoolBackend* backend = connection_pool->get_backend();
         ConnectionPoolBackends::PostgresCentralHosted* central = dynamic_cast<ConnectionPoolBackends::PostgresCentralHosted*>(backend);
@@ -129,7 +129,7 @@
 
         unconst->set_connection_port(central->get_port() );
       }
-      else
+      else if(document->get_hosting_mode() == Document_Glom::POSTGRES_SELF_HOSTED)
       {
         ConnectionPoolBackend* backend = connection_pool->get_backend();
         ConnectionPoolBackends::PostgresSelfHosted* self = dynamic_cast<ConnectionPoolBackends::PostgresSelfHosted*>(backend);
@@ -160,7 +160,7 @@
   {
 #ifndef GLOM_ENABLE_CLIENT_ONLY
     //Load server and user:
-    if(document->get_connection_is_self_hosted())
+    if(document->get_hosting_mode() != Document_Glom::POSTGRES_CENTRAL_HOSTED)
     {
        m_entry_host->set_text("(self hosted)");
        m_entry_host->set_sensitive(false);

Modified: trunk/glom/frame_glom.cc
==============================================================================
--- trunk/glom/frame_glom.cc	(original)
+++ trunk/glom/frame_glom.cc	Fri Nov 21 13:04:29 2008
@@ -29,6 +29,7 @@
 #include <glom/libglom/connectionpool.h>
 #include <glom/libglom/connectionpool_backends/postgres_central.h>
 #include <glom/libglom/connectionpool_backends/postgres_self.h>
+#include <glom/libglom/connectionpool_backends/sqlite.h>
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 #include "mode_design/users/dialog_groups_list.h"
@@ -1519,19 +1520,35 @@
   void setup_connection_pool_from_document(Document_Glom* document)
   {
     ConnectionPool* connection_pool = ConnectionPool::get_instance();
-    if(document->get_connection_is_self_hosted())
+    switch(document->get_hosting_mode())
     {
-      ConnectionPoolBackends::PostgresSelfHosted* backend = new ConnectionPoolBackends::PostgresSelfHosted;
-      backend->set_self_hosting_data_uri(document->get_connection_self_hosted_directory_uri());
-      connection_pool->set_backend(std::auto_ptr<ConnectionPoolBackend>(backend));
-    }
-    else
-    {
-      ConnectionPoolBackends::PostgresCentralHosted* backend = new ConnectionPoolBackends::PostgresCentralHosted;
-      backend->set_host(document->get_connection_server());
-      backend->set_port(document->get_connection_port());
-      backend->set_try_other_ports(document->get_connection_try_other_ports());
-      connection_pool->set_backend(std::auto_ptr<ConnectionPoolBackend>(backend));
+    case Document_Glom::POSTGRES_SELF_HOSTED:
+      {
+        ConnectionPoolBackends::PostgresSelfHosted* backend = new ConnectionPoolBackends::PostgresSelfHosted;
+        backend->set_self_hosting_data_uri(document->get_connection_self_hosted_directory_uri());
+        connection_pool->set_backend(std::auto_ptr<ConnectionPoolBackend>(backend));
+      }
+      break;
+    case Document_Glom::POSTGRES_CENTRAL_HOSTED:
+      {
+        ConnectionPoolBackends::PostgresCentralHosted* backend = new ConnectionPoolBackends::PostgresCentralHosted;
+        backend->set_host(document->get_connection_server());
+        backend->set_port(document->get_connection_port());
+        backend->set_try_other_ports(document->get_connection_try_other_ports());
+        connection_pool->set_backend(std::auto_ptr<ConnectionPoolBackend>(backend));
+      }
+
+      break;
+    case Document_Glom::SQLITE_HOSTED:
+      {
+        ConnectionPoolBackends::Sqlite* backend = new ConnectionPoolBackends::Sqlite;
+        backend->set_database_directory_uri(document->get_connection_self_hosted_directory_uri());
+        connection_pool->set_backend(std::auto_ptr<ConnectionPoolBackend>(backend));
+      }
+      break;
+    default:
+      g_assert_not_reached();
+      break;
     }
 
     // Might be overwritten later when actually attempting a connection:
@@ -1560,9 +1577,9 @@
   //Ask either for the existing username and password to use an existing database server,
   //or ask for a new username and password to specify when creating a new self-hosted database.
   int response = 0;
-#ifndef GLOM_ENABLE_CLIENT_ONLY
-  if(document->get_connection_is_self_hosted())
+  if(document->get_hosting_mode() == Document_Glom::POSTGRES_SELF_HOSTED)
   {
+#ifndef GLOM_ENABLE_CLIENT_ONLY
     Dialog_NewSelfHostedConnection* dialog = 0;
     Glib::RefPtr<Gnome::Glade::Xml> refXml;
 
@@ -1633,9 +1650,12 @@
 
     if(!created)
       return false; // The user cancelled
-  }
-  else
+#else
+    // Self-hosted postgres not supported in client only mode
+    g_assert_not_reached();
 #endif // !GLOM_ENABLE_CLIENT_ONLY
+  }
+  else if(document->get_hosting_mode() == Document_Glom::POSTGRES_CENTRAL_HOSTED)
   {
     //Ask for connection details:
     m_pDialogConnection->load_from_document(); //Get good defaults.
@@ -1656,6 +1676,15 @@
       return false;
     }
   }
+  else
+  {
+    // sqlite
+    if(!connection_pool->initialize(get_app_window()))
+      return false;
+
+    m_pDialogConnection->load_from_document(); //Get good defaults.
+    // No authentication required
+  }
 
   // Do startup, such as starting the self-hosting database server
   if(!connection_pool->startup(get_app_window()))
@@ -1719,7 +1748,7 @@
         document->set_connection_database(database_name_possible);
 
         // Remember host if the document is not self hosted
-        if(!document->get_connection_is_self_hosted())
+        if(document->get_hosting_mode() == Document_Glom::POSTGRES_CENTRAL_HOSTED)
         {
           ConnectionPoolBackend* backend = connection_pool->get_backend();
           ConnectionPoolBackends::PostgresCentralHosted* central = dynamic_cast<ConnectionPoolBackends::PostgresCentralHosted*>(backend);

Modified: trunk/glom/libglom/connectionpool.cc
==============================================================================
--- trunk/glom/libglom/connectionpool.cc	(original)
+++ trunk/glom/libglom/connectionpool.cc	Fri Nov 21 13:04:29 2008
@@ -336,23 +336,14 @@
     }
     else
     {
-      m_refGdaConnection = m_backend->connect(m_database, get_user(), get_password());
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+      std::auto_ptr<ExceptionConnection> error;
+#endif
+      m_refGdaConnection = m_backend->connect(m_database, get_user(), get_password(), error);
       if(!m_refGdaConnection)
       {
-        Glib::RefPtr<Gnome::Gda::Connection> temp_conn = m_backend->connect("", get_user(), get_password());
-#ifdef GLOM_CONNECTION_DEBUG
-        std::cout << "  ConnectionPool::connect() Attempting to connect without specifying the database." << std::endl;
-        if(temp_conn)
-          std::cout << "  (Connection succeeds, but not to the specific database,  database=" << m_database << std::endl;
-        else
-          std::cerr << "  (Could not connect even to the default database, database=" << m_database  << std::endl;
-#endif
-
-        g_warning("ConnectionPool::connect() throwing exception.");
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
-        throw ExceptionConnection(temp_conn ? ExceptionConnection::FAILURE_NO_DATABASE : ExceptionConnection::FAILURE_NO_SERVER);
-#else
-        error.reset(new ExceptionConnection(temp_conn ? ExceptionConnection::FAILURE_NO_DATABASE : ExceptionConnection::FAILURE_NO_SERVER));
+        throw *error;
 #endif
         return sharedptr<SharedConnection>(0);
       }
@@ -398,9 +389,11 @@
 #endif
 {
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
-  m_backend->create_database(database_name, get_user(), get_password());
-#else
+  std::auto_ptr<Glib::Error> error;
+#endif
   m_backend->create_database(database_name, get_user(), get_password(), error);
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  if(error.get()) throw *error;
 #endif
 }
 #endif // !GLOM_ENABLE_CLIENT_ONLY
@@ -694,7 +687,8 @@
 
  
   //Attempt a connection with this username/password:
-  Glib::RefPtr<Gnome::Gda::Connection> connection = connection_pool->m_backend->connect(connection_pool->get_database(), user_name, password);
+  std::auto_ptr<ExceptionConnection> error;
+  Glib::RefPtr<Gnome::Gda::Connection> connection = connection_pool->m_backend->connect(connection_pool->get_database(), user_name, password, error);
 
   if(connection)
   {

Modified: trunk/glom/libglom/connectionpool.h
==============================================================================
--- trunk/glom/libglom/connectionpool.h	(original)
+++ trunk/glom/libglom/connectionpool.h	Fri Nov 21 13:04:29 2008
@@ -126,18 +126,18 @@
    * implement this function  if there is no need for extra cleanup code. */
   virtual void cleanup(Gtk::Window* parent_window) {}
 
-  /* This method is called to create a connection to the database server. */
-  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password) = 0;
+  /* This method is called to create a connection to the database server.
+   * There exists only the variant with an error variable as last parameter
+   * so we don't need #ifdefs all over the code. This part of the API is only
+   * used by the ConnectionPool which will translate the error back into
+   * an exception in case exceptions are enabled. */
+  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error) = 0;
 
   /* This method is called to create a new database on the
    * database server. */
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password) = 0;
-#else
   virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error) = 0;
 #endif
-#endif
 };
 
 /** This is a singleton.

Modified: trunk/glom/libglom/connectionpool_backends/Makefile.am
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/Makefile.am	(original)
+++ trunk/glom/libglom/connectionpool_backends/Makefile.am	Fri Nov 21 13:04:29 2008
@@ -5,4 +5,9 @@
 noinst_LTLIBRARIES = libconnectionpool_backends.la
 libconnectionpool_backends_la_SOURCES = \
 	postgres_central.h postgres_central.cc \
+	sqlite.h sqlite.cc
+
+if !GLOM_ENABLE_CLIENT_ONLY
+libconnectionpool_backends_la_SOURCES += \
 	postgres_self.h postgres_self.cc
+endif

Modified: trunk/glom/libglom/connectionpool_backends/postgres_central.cc
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/postgres_central.cc	(original)
+++ trunk/glom/libglom/connectionpool_backends/postgres_central.cc	Fri Nov 21 13:04:29 2008
@@ -110,13 +110,14 @@
   return m_postgres_server_version;
 }
 
-Glib::RefPtr<Gnome::Gda::Connection> PostgresCentralHosted::attempt_connect(const Glib::RefPtr<Gnome::Gda::Client>& client, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, float& postgres_server_version)
+Glib::RefPtr<Gnome::Gda::Connection> PostgresCentralHosted::attempt_connect(const Glib::RefPtr<Gnome::Gda::Client>& client, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, float& postgres_server_version, std::auto_ptr<ExceptionConnection>& error)
 {
   //We must specify _some_ database even when we just want to create a database.
   //This _might_ be different on some systems. I hope not. murrayc
   const Glib::ustring default_database = "template1";
-  const Glib::ustring& actual_database = (!database.empty()) ? database : default_database;;
-  const Glib::ustring cnc_string = "HOST=" + host + ";PORT=" + port + ";DB_NAME=" + actual_database;
+  //const Glib::ustring& actual_database = (!database.empty()) ? database : default_database;;
+  const Glib::ustring cnc_string_main = "HOST=" + host + ";PORT=" + port;
+  Glib::ustring cnc_string = cnc_string_main + ";DB_NAME=" + database;
 
   //std::cout << "debug: connecting: cnc string: " << cnc_string << std::endl;
 #ifdef GLOM_CONNECTION_DEBUG          
@@ -136,21 +137,42 @@
   catch(const Glib::Error& ex)
   {
 #else
-  std::auto_ptr<Glib::Error> error;
-  connection = m_GdaClient->open_connection_from_string("PostgreSQL", cnc_string, m_user, m_password, error);
-  if(!error)
+  std::auto_ptr<Glib::Error> glib_error;
+  connection = m_GdaClient->open_connection_from_string("PostgreSQL", cnc_string, m_user, m_password, glib_error);
+  if(!glib_error)
     connection->execute_non_select_command("SET DATESTYLE = 'ISO'", error);
-  if(!error)
+  if(!glib_error)
     data_model = connection->execute_select_command("SELECT version()", error);
 
-  if(error.get())
+  if(glib_error.get())
   {
     const Glib::Error& ex = *glib_error;
 #endif
 
 #ifdef GLOM_CONNECTION_DEBUG
     std::cout << "ConnectionPoolBackends::PostgresCentralHosted::attempt_connect(): Attempt to connect to database failed on port=" << port << ", database=" << actual_database << ": " << ex.what() << std::endl;
+    std::cout << "ConnectionPoolBackends::PostgresCentralHosted::attempt_connect(): Attempting to connect without specifying the database." << std::endl;
 #endif
+
+    Glib::ustring cnc_string = cnc_string_main + ";DB_NAME=" + default_database;
+    Glib::RefPtr<Gnome::Gda::Connection> temp_conn;
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+    try
+    {
+      temp_conn = client->open_connection_from_string("PostgreSQL", cnc_string, username, password);
+    } catch(const Glib::Error& ex) {}
+#else
+    temp_conn = client->open_connection_from_string("PostgreSQL", cnc_string, username, password, glib_error);
+#endif
+
+#ifdef GLOM_CONNECTION_DEBUG
+    if(temp_conn)
+      std::cout << "  (Connection succeeds, but not to the specific database,  database=" << m_database << std::endl;
+    else
+      std::cerr << "  (Could not connect even to the default database, database=" << m_database  << std::endl;
+#endif
+
+    error.reset(new ExceptionConnection(temp_conn ? ExceptionConnection::FAILURE_NO_DATABASE : ExceptionConnection::FAILURE_NO_SERVER));
     return Glib::RefPtr<Gnome::Gda::Connection>();
   }
 
@@ -178,7 +200,7 @@
   return connection;
 }
 
-Glib::RefPtr<Gnome::Gda::Connection> PostgresCentralHosted::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password)
+Glib::RefPtr<Gnome::Gda::Connection> PostgresCentralHosted::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error)
 {
   if(!m_refGdaClient)
   {
@@ -197,7 +219,15 @@
   if(port == 0)
     port = *iter_port ++;
 
-  connection = attempt_connect(m_refGdaClient, m_host, port, database, username, password, m_postgres_server_version);
+  connection = attempt_connect(m_refGdaClient, m_host, port, database, username, password, m_postgres_server_version, error);
+
+  // Remember port if only the database was missing
+  bool connection_possible = false;
+  if(error.get() && error->get_failure_type() == ExceptionConnection::FAILURE_NO_DATABASE)
+  {
+    connection_possible = true;
+    m_port = atoi(port.c_str());
+  }
 
   // Try more ports if so desired, and we don't have a connection yet
   if(m_try_other_ports && !connection)
@@ -205,7 +235,14 @@
     while(!connection && iter_port != m_list_ports.end())
     {
       port = *iter_port;
-      connection = attempt_connect(m_refGdaClient, m_host, port, database, username, password, m_postgres_server_version);
+      connection = attempt_connect(m_refGdaClient, m_host, port, database, username, password, m_postgres_server_version, error);
+
+      // Remember port if only the database was missing
+      if(error.get() && error->get_failure_type() == ExceptionConnection::FAILURE_NO_DATABASE)
+      {
+        connection_possible = true;
+        m_port = atoi(port.c_str());
+      }
 
       // Skip if we already tried this port
       if(iter_port != m_list_ports.end() && *iter_port == port)
@@ -218,16 +255,19 @@
     //Remember working port:
     m_port = atoi(port.c_str());
   }
+  else
+  {
+    if(connection_possible)
+      error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_DATABASE));
+    else
+      error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_SERVER));
+  }
 
   return connection;
 }
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-bool PostgresCentralHosted::create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password)
-#else
 bool PostgresCentralHosted::create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error)
-#endif
 {
   if(!m_refGdaClient)
   {
@@ -239,11 +279,19 @@
   Glib::RefPtr<Gnome::Gda::ServerOperation> op = m_refGdaClient->prepare_create_database(database_name, "PostgreSQL");
   g_assert(op);
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
-  op->set_value_at("/SERVER_CNX_P/HOST", get_host());
-  op->set_value_at("/SERVER_CNX_P/PORT", port_as_string(m_port));
-  op->set_value_at("/SERVER_CNX_P/ADM_LOGIN", username);
-  op->set_value_at("/SERVER_CNX_P/ADM_PASSWORD", password);
-  m_refGdaClient->perform_create_database(op);
+  try
+  {
+    op->set_value_at("/SERVER_CNX_P/HOST", get_host());
+    op->set_value_at("/SERVER_CNX_P/PORT", port_as_string(m_port));
+    op->set_value_at("/SERVER_CNX_P/ADM_LOGIN", username);
+    op->set_value_at("/SERVER_CNX_P/ADM_PASSWORD", password);
+    m_refGdaClient->perform_create_database(op);
+  }
+  catch(const Glib::Error& ex)
+  {
+    error.reset(new Glib::Error(ex));
+    return false;
+  }
 #else
   op->set_value_at("/SERVER_CNX_P/HOST", get_host(), error);
   op->set_value_at("/SERVER_CNX_P/PORT", port_as_string(m_port), error);

Modified: trunk/glom/libglom/connectionpool_backends/postgres_central.h
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/postgres_central.h	(original)
+++ trunk/glom/libglom/connectionpool_backends/postgres_central.h	Fri Nov 21 13:04:29 2008
@@ -63,20 +63,16 @@
    */
   static bool check_postgres_gda_client_is_available_with_warning();
 
-  static Glib::RefPtr<Gnome::Gda::Connection> attempt_connect(const Glib::RefPtr<Gnome::Gda::Client>& client, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, float& postgres_server_version);
+  static Glib::RefPtr<Gnome::Gda::Connection> attempt_connect(const Glib::RefPtr<Gnome::Gda::Client>& client, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, float& postgres_server_version, std::auto_ptr<ExceptionConnection>& error);
 
 protected:
-  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password);
+  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
 
   /** Creates a new database.
    */
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password);
-#else
   virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
 #endif
-#endif
 
 private:
   typedef std::list<Glib::ustring> type_list_ports;

Modified: trunk/glom/libglom/connectionpool_backends/postgres_self.cc
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/postgres_self.cc	(original)
+++ trunk/glom/libglom/connectionpool_backends/postgres_self.cc	Fri Nov 21 13:04:29 2008
@@ -469,7 +469,7 @@
   m_port = 0;
 }
 
-Glib::RefPtr<Gnome::Gda::Connection> PostgresSelfHosted::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password)
+Glib::RefPtr<Gnome::Gda::Connection> PostgresSelfHosted::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error)
 {
   if(!m_refGdaClient)
   {
@@ -481,15 +481,11 @@
   if(!get_self_hosting_active())
     return Glib::RefPtr<Gnome::Gda::Connection>();
 
-  return PostgresCentralHosted::attempt_connect(m_refGdaClient, "localhost", port_as_string(m_port), database, username, password, m_postgres_server_version);
+  return PostgresCentralHosted::attempt_connect(m_refGdaClient, "localhost", port_as_string(m_port), database, username, password, m_postgres_server_version, error);
 }
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-bool PostgresSelfHosted::create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password)
-#else
 bool PostgresSelfHosted::create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error)
-#endif
 {
   if(!m_refGdaClient)
   {
@@ -501,11 +497,19 @@
   Glib::RefPtr<Gnome::Gda::ServerOperation> op = m_refGdaClient->prepare_create_database(database_name, "PostgreSQL");
   g_assert(op);
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
-  op->set_value_at("/SERVER_CNX_P/HOST", "localhost");
-  op->set_value_at("/SERVER_CNX_P/PORT", port_as_string(m_port));
-  op->set_value_at("/SERVER_CNX_P/ADM_LOGIN", username);
-  op->set_value_at("/SERVER_CNX_P/ADM_PASSWORD", password);
-  m_refGdaClient->perform_create_database(op);
+  try
+  {
+    op->set_value_at("/SERVER_CNX_P/HOST", "localhost");
+    op->set_value_at("/SERVER_CNX_P/PORT", port_as_string(m_port));
+    op->set_value_at("/SERVER_CNX_P/ADM_LOGIN", username);
+    op->set_value_at("/SERVER_CNX_P/ADM_PASSWORD", password);
+    m_refGdaClient->perform_create_database(op);
+  }
+  catch(const Glib::Error& ex)
+  {
+    error.reset(new Glib::Error(ex));
+    return false;
+  }
 #else
   op->set_value_at("/SERVER_CNX_P/HOST", get_host(), error);
   op->set_value_at("/SERVER_CNX_P/PORT", port_as_string(m_port), error);

Modified: trunk/glom/libglom/connectionpool_backends/postgres_self.h
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/postgres_self.h	(original)
+++ trunk/glom/libglom/connectionpool_backends/postgres_self.h	Fri Nov 21 13:04:29 2008
@@ -79,13 +79,9 @@
   virtual bool startup(Gtk::Window* parent_window);
   virtual void cleanup(Gtk::Window* parent_window);
 
-  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password);
+  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password);
-#else
   virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
-#endif
 
 private:
   /** Examine ports one by one, starting at @a starting_port, in increasing

Added: trunk/glom/libglom/connectionpool_backends/sqlite.cc
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/connectionpool_backends/sqlite.cc	Fri Nov 21 13:04:29 2008
@@ -0,0 +1,142 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glom/libglom/connectionpool_backends/sqlite.h>
+
+#include <giomm/file.h>
+
+namespace Glom
+{
+
+namespace ConnectionPoolBackends
+{
+
+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)
+{
+  if(!m_refGdaClient)
+  {
+    m_refGdaClient = Gnome::Gda::Client::create();
+    if(!m_refGdaClient)
+      return Glib::RefPtr<Gnome::Gda::Connection>();
+  }
+
+  // Check if the database file exists. If it does not, then we don't try to
+  // connect. libgda would create the database file if necessary, but we need
+  // to ensure slightly different semantics.
+  Glib::RefPtr<Gio::File> db_dir = Gio::File::create_for_uri(m_database_directory_uri);
+  Glib::RefPtr<Gio::File> db_file = db_dir->get_child(database + ".db");
+
+  Glib::RefPtr<Gnome::Gda::Connection> connection;
+  if(db_file->query_file_type() == Gio::FILE_TYPE_REGULAR)
+  {
+    // Convert URI to path, for GDA connection string
+    std::string database_directory = db_dir->get_path();
+
+    const Glib::ustring cnc_string = "DB_DIR=" + database_directory + ";DB_NAME=" + database;
+
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+    try
+    {
+      connection = m_refGdaClient->open_connection_from_string("SQLite", cnc_string, username, password);
+    }
+    catch(const Glib::Error& ex)
+    {
+#else
+    std::auto_ptr<Glib::Error> error;
+    connection = m_refGdaClient->open_connection_from_string("SQLite", cnc_string, username, password, error);
+    if(error.get())
+    {
+      const Glib::Error& ex = *error.get();
+#endif
+    }
+  }
+
+  if(!connection)
+  {
+    // If the database directory is valid, then only the database (file) is
+    // missing, otherwise we pretend the "server" is not running.
+    if(db_dir->query_file_type() == Gio::FILE_TYPE_DIRECTORY)
+      error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_DATABASE));
+    else
+      error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_SERVER));
+  }
+
+  return connection;
+}
+
+#ifndef GLOM_ENABLE_CLIENT_ONLY
+bool Sqlite::create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error)
+{
+  if(!m_refGdaClient)
+  {
+    m_refGdaClient = Gnome::Gda::Client::create();
+    if(!m_refGdaClient)
+      return false;
+  }
+
+  Glib::RefPtr<Gnome::Gda::ServerOperation> op = m_refGdaClient->prepare_create_database(database_name, "SQLite");
+  g_assert(op);
+
+  // Convert URI to path, for DB_DIR in server operation
+  Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(m_database_directory_uri);
+  std::string database_directory = file->get_path();
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  try
+  {
+    op->set_value_at("/DB_DEF_P/DB_DIR", database_directory);
+    m_refGdaClient->perform_create_database(op);
+  }
+  catch(const Glib::Error& ex)
+  {
+    error.reset(new Glib::Error(ex));
+    return false;
+  }
+#else
+  op->set_value_at("/DB_DEF_P/DB_DIR", database_directory);
+
+  if(error.get() != NULL)
+    m_refGdaClient->perform_create_database(op);
+  else
+    return false;
+#endif
+
+  return true;
+}
+#endif
+
+} // namespace ConnectionPoolBackends
+
+} // namespace Glom

Added: trunk/glom/libglom/connectionpool_backends/sqlite.h
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/connectionpool_backends/sqlite.h	Fri Nov 21 13:04:29 2008
@@ -0,0 +1,62 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GLOM_BACKEND_SQLITE_H
+#define GLOM_BACKEND_SQLITE_H
+
+#include <libgdamm.h>
+#include <glom/libglom/connectionpool.h>
+
+#include "config.h" // For GLOM_ENABLE_CLIENT_ONLY
+
+namespace Glom
+{
+
+namespace ConnectionPoolBackends
+{
+
+class Sqlite : public ConnectionPoolBackend
+{
+public:
+  Sqlite();
+
+  void set_database_directory_uri(const std::string& directory_uri);
+  const std::string& get_database_directory_uri() const;
+
+protected:
+  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
+
+  /** Creates a new database.
+   */
+#ifndef GLOM_ENABLE_CLIENT_ONLY
+  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
+#endif
+
+private:
+  Glib::RefPtr<Gnome::Gda::Client> m_refGdaClient;
+  std::string m_database_directory_uri;
+};
+
+} //namespace ConnectionPoolBackends
+
+} //namespace Glom
+
+#endif //GLOM_BACKEND_SQLITE_H
+

Modified: trunk/glom/libglom/document/document_glom.cc
==============================================================================
--- trunk/glom/libglom/document/document_glom.cc	(original)
+++ trunk/glom/libglom/document/document_glom.cc	Fri Nov 21 13:04:29 2008
@@ -49,6 +49,10 @@
 
 #define GLOM_NODE_CONNECTION "connection"
 #define GLOM_ATTRIBUTE_CONNECTION_SELF_HOSTED "self_hosted"
+#define GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE "hosting_mode"
+#define GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_CENTRAL "postgres_central"
+#define GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_SELF "postgres_self"
+#define GLOM_ATTRIBUTE_CONNECTION_HOSTING_SQLITE "sqlite"
 #define GLOM_ATTRIBUTE_CONNECTION_SERVER "server"
 #define GLOM_ATTRIBUTE_CONNECTION_PORT "port"
 #define GLOM_ATTRIBUTE_CONNECTION_TRY_OTHER_PORTS "try_other_ports"
@@ -205,9 +209,7 @@
 
 Document_Glom::Document_Glom()
 :
-#ifndef GLOM_ENABLE_CLIENT_ONLY
-  m_connection_is_self_hosted(false),
-#endif // !GLOM_ENABLE_CLIENT_ONLY
+  m_hosting_mode(POSTGRES_CENTRAL_HOSTED),
   m_connection_port(0),
   m_connection_try_other_ports(false),
   m_block_cache_update(false),
@@ -248,21 +250,17 @@
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   //TODO: It would be better to do this in a Application::on_document_closed() virtual method,
   //but that would need an ABI break in Bakery:
-  if(get_connection_is_self_hosted())
-  {
-    ConnectionPool* connection_pool = ConnectionPool::get_instance();
-    if(!connection_pool)
-      return;
+  ConnectionPool* connection_pool = ConnectionPool::get_instance();
+  if(!connection_pool)
+    return;
 
-    connection_pool->cleanup(m_parent_window);
-  }
+  connection_pool->cleanup(m_parent_window);
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 }
 
-#ifndef GLOM_ENABLE_CLIENT_ONLY
-bool Document_Glom::get_connection_is_self_hosted() const
+Document_Glom::HostingMode Document_Glom::get_hosting_mode() const
 {
-  return m_connection_is_self_hosted;
+  return m_hosting_mode;
 }
 
 std::string Document_Glom::get_connection_self_hosted_directory_uri() const
@@ -279,9 +277,26 @@
     Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(uri_file);
 
     Glib::RefPtr<Gio::File> parent = file->get_parent();
+    Glib::RefPtr<Gio::File> datadir;
+
     if(parent)
     {
-      Glib::RefPtr<Gio::File> datadir = parent->get_child("glom_postgres_data");
+      switch(m_hosting_mode)
+      {
+      case POSTGRES_SELF_HOSTED:
+        datadir = parent->get_child("glom_postgres_data");
+        break;
+      case POSTGRES_CENTRAL_HOSTED:
+        datadir = parent;
+        break;
+      case SQLITE_HOSTED:
+        datadir = parent;
+        break;
+      default:
+        g_assert_not_reached();
+        break;
+      }
+
       if(datadir)
         return datadir->get_uri();
     }
@@ -290,7 +305,6 @@
   g_warning("Document_Glom::get_connection_self_hosted_directory_uri(): returning empty string.");
   return std::string();
 }
-#endif // !GLOM_ENABLE_CLIENT_ONLY
 
 Glib::ustring Document_Glom::get_connection_user() const
 {
@@ -326,16 +340,14 @@
   }
 }
 
-#ifndef GLOM_ENABLE_CLIENT_ONLY
-void Document_Glom::set_connection_is_self_hosted(bool self_hosted)
+void Document_Glom::set_hosting_mode(HostingMode mode)
 {
-  if(self_hosted != m_connection_is_self_hosted)
+  if(mode != m_hosting_mode)
   {
-    m_connection_is_self_hosted = self_hosted;
+    m_hosting_mode = mode;
     set_modified();
   }
 }
-#endif // !GLOM_ENABLE_CLIENT_ONLY
 
 void Document_Glom::set_connection_server(const Glib::ustring& strVal)
 {
@@ -2267,21 +2279,42 @@
       if(nodeConnection)
       {
         //Connection information:
-        bool self_hosted = get_node_attribute_value_as_bool(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_SELF_HOSTED);
         m_connection_server = get_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_SERVER);
         m_connection_port = get_node_attribute_value_as_decimal(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_PORT);
         m_connection_try_other_ports = get_node_attribute_value_as_bool(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_TRY_OTHER_PORTS, true /* default */);
         m_connection_user = get_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_USER);
         m_connection_database = get_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_DATABASE);
 
+        Glib::ustring attr_mode = get_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE);
+        HostingMode mode;
+
+        if(attr_mode.empty())
+        {
+          // If no hosting mode is set, then try the self_hosted flag which
+          // was used before sqlite support has been implemented.
+          bool self_hosted = get_node_attribute_value_as_bool(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_SELF_HOSTED);
+          mode = self_hosted ? POSTGRES_SELF_HOSTED : POSTGRES_CENTRAL_HOSTED;
+        }
+        else
+        {
+          if(attr_mode == GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_CENTRAL)
+            mode = POSTGRES_CENTRAL_HOSTED;
+          else if(attr_mode == GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_SELF)
+            mode = POSTGRES_SELF_HOSTED;
+          else if(attr_mode == GLOM_ATTRIBUTE_CONNECTION_HOSTING_SQLITE)
+            mode = SQLITE_HOSTED;
+          else
+            mode = POSTGRES_CENTRAL_HOSTED; // Default
+        }
+
 #ifdef GLOM_ENABLE_CLIENT_ONLY
-        if(self_hosted)
+        if(mode == POSTGRES_SELF_HOSTED)
         {
           std::cerr << "Document_Glom::load_after(): Loading failed because the document needs to be self-hosted, but self-hosting is not supported in client only mode" << std::endl;
           return false; //TODO: Provide more information so the application (or Bakery) can say exactly why loading failed.
         }
 #else
-        m_connection_is_self_hosted = self_hosted;
+        m_hosting_mode = mode;
 #endif
       }
 
@@ -3125,11 +3158,22 @@
     set_node_attribute_value(nodeRoot, GLOM_ATTRIBUTE_TRANSLATION_ORIGINAL_LOCALE, m_translation_original_locale);
 
     xmlpp::Element* nodeConnection = get_node_child_named_with_add(nodeRoot, GLOM_NODE_CONNECTION);
-#ifdef GLOM_ENABLE_CLIENT_ONLY
-    set_node_attribute_value_as_bool(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_SELF_HOSTED, false);
-#else // GLOM_ENABLE_CLIENT_ONLY
-    set_node_attribute_value_as_bool(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_SELF_HOSTED, m_connection_is_self_hosted);
-#endif // !GLOM_ENABLE_CLIENT_ONLY
+
+    switch(m_hosting_mode)
+    {
+    case POSTGRES_CENTRAL_HOSTED:
+      set_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_CENTRAL);
+      break;
+    case POSTGRES_SELF_HOSTED:
+      set_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_SELF);
+      break;
+    case SQLITE_HOSTED:
+      set_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_SQLITE);
+      break;
+    default:
+      g_assert_not_reached();
+      break;
+    }
 
     set_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_SERVER, m_connection_server);
     set_node_attribute_value_as_decimal(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_PORT, m_connection_port);
@@ -3852,8 +3896,9 @@
   // History:
   // Version 0: The first document format. (And the default version number when no version number was saved in the .XML)
   // Version 1: Saved scripts and other multiline text in text nodes instead of attributes. Can open Version 1 documents.
+  // Version 2: hosting_mode="postgres-central|postgres-self|sqlite" instead of self_hosted="true|false". Can open Version 1 documents, by falling back to the self_hosted attribute if hosting_mode is not set.
 
-  return 1;
+  return 2;
 }
 
 std::vector<Glib::ustring> Document_Glom::get_library_module_names() const

Modified: trunk/glom/libglom/document/document_glom.h
==============================================================================
--- trunk/glom/libglom/document/document_glom.h	(original)
+++ trunk/glom/libglom/document/document_glom.h	Fri Nov 21 13:04:29 2008
@@ -109,12 +109,18 @@
 
   static guint get_latest_known_document_format_version();
 
-#ifndef GLOM_ENABLE_CLIENT_ONLY
-  /** When this is set, the postgres database is hosted by the local client,
-   *  instead of connecting to an external database server.
+  enum HostingMode {
+    /* The database is hosted on an external postgresql server */
+    POSTGRES_CENTRAL_HOSTED,
+    /* A new postgres database process is spawned that hosts the data */
+    POSTGRES_SELF_HOSTED,
+    /* A sqlite database file is used */
+    SQLITE_HOSTED
+  };
+
+  /** Set the hosting mode of the database.
    */
-  void set_connection_is_self_hosted(bool self_hosted = true);
-#endif // !GLOM_ENABLE_CLIENT_ONLY
+  void set_hosting_mode(HostingMode mode);
 
   void set_connection_server(const Glib::ustring& strVal);
   void set_connection_user(const Glib::ustring& strVal);
@@ -122,18 +128,17 @@
   void set_connection_port(int port_number);
   void set_connection_try_other_ports(bool val);
 
-#ifndef GLOM_ENABLE_CLIENT_ONLY
-  /** When this returns true, the postgres database should be hosted by the local client,
-   *  instead of connecting to an external database server.
+  /** This returns how the hosting mode of the database.
    */
-  bool get_connection_is_self_hosted() const;
+  HostingMode get_hosting_mode() const;
 
   /** If the database should be hosted, this provides the 
     * path to the directory that contains all the files needed to do that.
     * This is usually a specifically-named directory at the same level as the .glom file. 
+    * If the database is a sqlite database, this specifies the directory in
+    * which the database file is in.
     */   
   std::string get_connection_self_hosted_directory_uri() const;
-#endif // !GLOM_ENABLE_CLIENT_ONLY
 
   Glib::ustring get_connection_server() const;
   Glib::ustring get_connection_user() const;
@@ -440,9 +445,7 @@
   AppState m_app_state;
   type_signal_userlevel_changed m_signal_userlevel_changed;
 
-#ifndef GLOM_ENABLE_CLIENT_ONLY
-  bool m_connection_is_self_hosted;
-#endif // !GLOM_ENABLE_CLIENT_ONLY
+  HostingMode m_hosting_mode;
 
   Glib::ustring m_connection_server, m_connection_user, m_connection_database;
   int m_connection_port; //0 means any port. Ignored when self-hosting (which may use a different port each time).

Modified: trunk/glom/utility_widgets/filechooserdialog_saveextras.cc
==============================================================================
--- trunk/glom/utility_widgets/filechooserdialog_saveextras.cc	(original)
+++ trunk/glom/utility_widgets/filechooserdialog_saveextras.cc	Fri Nov 21 13:04:29 2008
@@ -100,15 +100,20 @@
   vbox->pack_start(*box_label);
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-  m_radiobutton_server_selfhosted.set_label(_("Create database in its own folder, to be hosted by this computer."));
-  vbox->pack_start(m_radiobutton_server_selfhosted);
-  m_radiobutton_server_selfhosted.show();
-
-  m_radiobutton_server_central.set_label(_("Create database on an external database server, to be specified in the next step."));
-  Gtk::RadioButton::Group group = m_radiobutton_server_selfhosted.get_group();
-  m_radiobutton_server_central.set_group(group);
-  vbox->pack_start(m_radiobutton_server_central);
-  m_radiobutton_server_central.show();
+  m_radiobutton_server_postgres_selfhosted.set_label(_("Create postgresql database in its own folder, to be hosted by this computer."));
+  vbox->pack_start(m_radiobutton_server_postgres_selfhosted);
+  m_radiobutton_server_postgres_selfhosted.show();
+
+  m_radiobutton_server_postgres_central.set_label(_("Create database on an external postgresql database server, to be specified in the next step."));
+  Gtk::RadioButton::Group group = m_radiobutton_server_postgres_selfhosted.get_group();
+  m_radiobutton_server_postgres_central.set_group(group);
+  vbox->pack_start(m_radiobutton_server_postgres_central);
+  m_radiobutton_server_postgres_central.show();
+
+  m_radiobutton_server_sqlite.set_label(_("Create sqlite database in its own folder, to be hosted by this computer."));
+  m_radiobutton_server_sqlite.set_group(group);
+  vbox->pack_start(m_radiobutton_server_sqlite);
+  m_radiobutton_server_sqlite.show();
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
 
@@ -123,23 +128,38 @@
   m_entry_title.set_text(title);
 }
 
-#ifndef GLOM_ENABLE_CLIENT_ONLY
-void FileChooserDialog_SaveExtras::set_extra_newdb_self_hosted(bool self_hosted)
+void FileChooserDialog_SaveExtras::set_extra_newdb_hosting_mode(Document_Glom::HostingMode mode)
 {
-  m_radiobutton_server_selfhosted.set_active(self_hosted);
+  switch(mode)
+  {
+  case Document_Glom::POSTGRES_CENTRAL_HOSTED:
+    m_radiobutton_server_postgres_selfhosted.set_active();
+    break;
+  case Document_Glom::POSTGRES_SELF_HOSTED:
+    m_radiobutton_server_postgres_central.set_active();
+    break;
+  case Document_Glom::SQLITE_HOSTED:
+    m_radiobutton_server_sqlite.set_active();
+    break;
+  default:
+    g_assert_not_reached();
+    break;
+  }
 }
-#endif // !GLOM_ENABLE_CLIENT_ONLY
 
 Glib::ustring FileChooserDialog_SaveExtras::get_extra_newdb_title() const
 {
   return m_entry_title.get_text();
 }
 
-#ifndef GLOM_ENABLE_CLIENT_ONLY
-bool FileChooserDialog_SaveExtras::get_extra_newdb_self_hosted() const
+Document_Glom::HostingMode FileChooserDialog_SaveExtras::get_extra_newdb_hosting_mode() const
 {
-  return m_radiobutton_server_selfhosted.get_active();
+  if(m_radiobutton_server_postgres_central.get_active())
+    return Document_Glom::POSTGRES_CENTRAL_HOSTED;
+  else if(m_radiobutton_server_postgres_selfhosted.get_active())
+    return Document_Glom::POSTGRES_SELF_HOSTED;
+  else
+    return Document_Glom::SQLITE_HOSTED;
 }
-#endif // !GLOM_ENABLE_CLIENT_ONLY
 
 } //namespace Glom

Modified: trunk/glom/utility_widgets/filechooserdialog_saveextras.h
==============================================================================
--- trunk/glom/utility_widgets/filechooserdialog_saveextras.h	(original)
+++ trunk/glom/utility_widgets/filechooserdialog_saveextras.h	Fri Nov 21 13:04:29 2008
@@ -21,6 +21,8 @@
 #ifndef GLOM_UTILITY_WIDGETS_FILECHOOSERDIALOG_SAVEEXTRAS_H
 #define GLOM_UTILITY_WIDGETS_FILECHOOSERDIALOG_SAVEEXTRAS_H
 
+#include <glom/libglom/document/document_glom.h>
+
 #include <gtkmm/filechooserdialog.h>
 #include <gtkmm/label.h>
 #include <gtkmm/box.h>
@@ -45,13 +47,14 @@
   void set_extra_message(const Glib::ustring& message);
   void set_extra_newdb_title(const Glib::ustring& title);
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-  void set_extra_newdb_self_hosted(bool self_hosted = true);
+  void set_extra_newdb_hosting_mode(Document_Glom::HostingMode mode);
+  //void set_extra_newdb_self_hosted(bool self_hosted = true);
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
   Glib::ustring get_extra_newdb_title() const;
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-  bool get_extra_newdb_self_hosted() const;
+  Document_Glom::HostingMode get_extra_newdb_hosting_mode() const;
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
 protected:
@@ -63,8 +66,9 @@
   /* New database details: */
   Gtk::Entry m_entry_title;
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-  Gtk::RadioButton m_radiobutton_server_central;
-  Gtk::RadioButton m_radiobutton_server_selfhosted;
+  Gtk::RadioButton m_radiobutton_server_postgres_central;
+  Gtk::RadioButton m_radiobutton_server_postgres_selfhosted;
+  Gtk::RadioButton m_radiobutton_server_sqlite;
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 };
 



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