glom r2033 - in trunk: . glom glom/bakery glom/libglom glom/libglom/connectionpool_backends glom/libglom/document



Author: murrayc
Date: Fri Mar 27 16:54:06 2009
New Revision: 2033
URL: http://svn.gnome.org/viewvc/glom?rev=2033&view=rev

Log:
2009-03-27  Murray Cumming  <murrayc murrayc com>

* glom/bakery/app_withdoc.[h|cc]: Added on_document_close() virtual method 
now that we can break this ABI.
* glom/application.[h|cc]: Override on_document_close().
* glom/libglom/document/document_glom.cc: Destructor: Don't shutdown the 
database here. Do in App_Glom::on_document_close() instead.

* glom/libglom/Makefile.am:
* glom/libglom/spawn_with_feedback.[h|cc]: execute_command_line_and_wait(),
  execute_command_line_and_wait_until_second_command_returns_success():
  Take a SlotProgress callback instead of a parent window, and don't take 
  a human-readable message string to show, allowing the caller to show UI if 
  it wants, removing UI code from this part of libglom.
  Use a Glib::MainLoop to block instead of using the Gtk::Main in 
  Gtk::Dialog::run().
* glom/libglom/connectionpool.[h|cc]: initialize(), startup, cleanup():
* glom/libglom/connectionpool_backends/backend.[h|cc]: initialize(),
  startup(), cleanup():
* glom/libglom/connectionpool_backends/postgres_self.cc: initialize(), 
startup, cleanup(): Take a SlotProgress callback instead of a parent window, 
allowing the caller to show UI if it wants, removing UI code from this part of 
libglom.

glom/Makefile.am:
* glom/libglom/dialog_progress_creating.[h|cc]: moved to 
* glom/glom/glade_utils.[h|cc]: Moved get_and_show_pulse_dialog() here.

* glom/dialog_new_self_hosted_connection.[h|cc]:
* glom/frame_glom.[h|cc]: 
connection_request_password_and_choose_new_database_name(), 
connection_request_password_and_attempt(): Adapted.

Added:
   trunk/glom/dialog_progress_creating.cc   (contents, props changed)
      - copied, changed from r2030, /trunk/glom/libglom/dialog_progress_creating.cc
   trunk/glom/dialog_progress_creating.h   (props changed)
      - copied unchanged from r2030, /trunk/glom/libglom/dialog_progress_creating.h
Removed:
   trunk/glom/libglom/dialog_progress_creating.cc
   trunk/glom/libglom/dialog_progress_creating.h
Modified:
   trunk/ChangeLog
   trunk/glom/Makefile.am
   trunk/glom/application.cc
   trunk/glom/application.h
   trunk/glom/bakery/app_withdoc.cc
   trunk/glom/bakery/app_withdoc.h
   trunk/glom/dialog_new_self_hosted_connection.cc
   trunk/glom/dialog_new_self_hosted_connection.h
   trunk/glom/frame_glom.cc
   trunk/glom/frame_glom.h
   trunk/glom/glade_utils.h
   trunk/glom/libglom/Makefile.am
   trunk/glom/libglom/connectionpool.cc
   trunk/glom/libglom/connectionpool.h
   trunk/glom/libglom/connectionpool_backends/backend.cc
   trunk/glom/libglom/connectionpool_backends/backend.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/spawn_with_feedback.cc
   trunk/glom/libglom/spawn_with_feedback.h

Modified: trunk/glom/Makefile.am
==============================================================================
--- trunk/glom/Makefile.am	(original)
+++ trunk/glom/Makefile.am	Fri Mar 27 16:54:06 2009
@@ -48,10 +48,11 @@
 	             dialog_existing_or_new.h dialog_existing_or_new.cc \
                dialog_invalid_data.h dialog_invalid_data.cc \
                filechooser_export.h filechooser_export.cc \
+               dialog_progress_creating.h dialog_progress_creating.cc \
                box_reports.h box_reports.cc \
                xsl_utils.h xsl_utils.cc \
                variablesmap.h variablesmap.cc \
-               signal_reemitter.h glade_utils.h
+               signal_reemitter.h glade_utils.h glade_utils.cc
 
 if !GLOM_ENABLE_CLIENT_ONLY
 glom_SOURCES += dialog_new_self_hosted_connection.h \

Modified: trunk/glom/application.cc
==============================================================================
--- trunk/glom/application.cc	(original)
+++ trunk/glom/application.cc	Fri Mar 27 16:54:06 2009
@@ -23,7 +23,7 @@
 #include "application.h"
 #include "dialog_existing_or_new.h"
 
-#include <libglom/dialog_progress_creating.h>
+#include <glom/dialog_progress_creating.h>
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 #include <glom/translation/dialog_change_language.h>
@@ -1048,7 +1048,7 @@
           {
             // TODO: Do we need to call connection_pool->cleanup() here, for
             // stopping self-hosted databases? armin.
-            connection_pool->cleanup(this);
+            connection_pool->cleanup( sigc::mem_fun(*this, &App_Glom::on_connection_close_progress) );
             //If the database was not successfully recreated:
             if(!user_cancelled)
             {
@@ -1093,6 +1093,24 @@
   }
 }
 
+void App_Glom::on_connection_close_progress()
+{
+  //TODO_murrayc
+}
+
+void App_Glom::on_document_close()
+{
+#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:
+  ConnectionPool* connection_pool = ConnectionPool::get_instance();
+  if(!connection_pool)
+    return;
+
+  connection_pool->cleanup( sigc::mem_fun(*this, &App_Glom::on_connection_close_progress) );
+#endif // !GLOM_ENABLE_CLIENT_ONLY
+}
+
 /*
 void App_Glom::statusbar_set_text(const Glib::ustring& strText)
 {
@@ -2267,7 +2285,7 @@
     if(!connection_pool)
       return;
 
-    connection_pool->cleanup(this);
+    connection_pool->cleanup( sigc::mem_fun(*this, &App_Glom::on_connection_close_progress ));
   }
 }
 
@@ -2396,6 +2414,7 @@
 }
 #endif
 
+
 } //namespace Glom
 
 

Modified: trunk/glom/application.h
==============================================================================
--- trunk/glom/application.h	(original)
+++ trunk/glom/application.h	Fri Mar 27 16:54:06 2009
@@ -91,6 +91,7 @@
   virtual void init_toolbars(); //override
   virtual void init_create_document(); //override
   virtual bool on_document_load(); //override.
+  virtual void on_document_close(); //override.
 
   bool offer_new_or_existing();
 
@@ -131,6 +132,8 @@
   virtual void document_history_add(const Glib::ustring& file_uri); //overridden.
 
   virtual void new_instance(const Glib::ustring& uri = Glib::ustring()); //Override
+  
+  void on_connection_close_progress();
 
 #ifndef G_OS_WIN32
   void open_browsed_document(const EpcServiceInfo* server, const Glib::ustring& service_name);

Modified: trunk/glom/bakery/app_withdoc.cc
==============================================================================
--- trunk/glom/bakery/app_withdoc.cc	(original)
+++ trunk/glom/bakery/app_withdoc.cc	Fri Mar 27 16:54:06 2009
@@ -47,7 +47,7 @@
 }
 
 //static
-void  App_WithDoc::add_mime_type(const Glib::ustring& mime_type)
+void App_WithDoc::add_mime_type(const Glib::ustring& mime_type)
 {
   if( std::find(m_mime_types.begin(), m_mime_types.end(), mime_type) == m_mime_types.end() )
     m_mime_types.push_back(mime_type);
@@ -64,6 +64,8 @@
 
   if(!get_operation_cancelled())
     ui_hide();
+    
+  on_document_close();
 }
 
 bool App_WithDoc::open_document_from_data(const guchar* data, std::size_t length)
@@ -123,7 +125,7 @@
     else
     {
       //if open succeeded then let the App respond:
-      bool test = pApp->on_document_load();
+      const bool test = pApp->on_document_load();
       if(!test)
         bOpenFailed = true; //The application didn't like something about the just-loaded document.
       else
@@ -412,6 +414,10 @@
   //If you are not using Views, then override this to fill your various windows with stuff according to the contents of the document.
 }
 
+void App_WithDoc::on_document_close()
+{
+}
+
 void App_WithDoc::update_window_title()
 {
 

Modified: trunk/glom/bakery/app_withdoc.h
==============================================================================
--- trunk/glom/bakery/app_withdoc.h	(original)
+++ trunk/glom/bakery/app_withdoc.h	Fri Mar 27 16:54:06 2009
@@ -131,6 +131,9 @@
 
   ///override this to show document contents.
   virtual bool on_document_load();
+  
+  ///override this to do extra cleanup.
+  virtual void on_document_close();
 
   virtual void offer_to_save_changes();
 

Modified: trunk/glom/dialog_new_self_hosted_connection.cc
==============================================================================
--- trunk/glom/dialog_new_self_hosted_connection.cc	(original)
+++ trunk/glom/dialog_new_self_hosted_connection.cc	Fri Mar 27 16:54:06 2009
@@ -21,6 +21,7 @@
 #include "dialog_new_self_hosted_connection.h"
 #include "box_withbuttons.h" //For Box_WithButtons::connect_to_server().
 #include <glom/frame_glom.h> //For Frame_Glom::show_ok_dialog
+#include <glom/glade_utils.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -30,7 +31,8 @@
 : Gtk::Dialog(cobject),
   Base_DB(),
   m_entry_user(0),
-  m_entry_password(0)
+  m_entry_password(0),
+  m_dialog_progess_connection_initialize(0)
 {
   builder->get_widget("entry_user", m_entry_user);
   builder->get_widget("entry_password", m_entry_password);
@@ -39,6 +41,19 @@
 
 Dialog_NewSelfHostedConnection::~Dialog_NewSelfHostedConnection()
 {
+  if(m_dialog_progess_connection_initialize)
+  {
+    delete m_dialog_progess_connection_initialize;
+    m_dialog_progess_connection_initialize = 0;
+  }
+}
+
+void Dialog_NewSelfHostedConnection::on_connection_initialization_progress()
+{
+  if(!m_dialog_progess_connection_initialize)
+    m_dialog_progess_connection_initialize = Utils::get_and_show_pulse_dialog(_("Creating Database Data"), this);
+        
+  m_dialog_progess_connection_initialize->pulse();
 }
 
 bool Dialog_NewSelfHostedConnection::create_self_hosted()
@@ -62,7 +77,8 @@
       connection_pool->set_user(m_entry_user->get_text());
       connection_pool->set_password(m_entry_password->get_text());
       //std::cout << "debug: Dialog_NewSelfHostedConnection::create_self_hosted() user=" << m_entry_user->get_text() << ", password=" << m_entry_password->get_text() << std::endl;
-      const bool created = connection_pool->initialize(this /* parent_window for errors */);
+      const bool created = connection_pool->initialize(
+        sigc::mem_fun(*this, &Dialog_NewSelfHostedConnection::on_connection_initialization_progress) );
       if(!created)
       {
         return false;

Modified: trunk/glom/dialog_new_self_hosted_connection.h
==============================================================================
--- trunk/glom/dialog_new_self_hosted_connection.h	(original)
+++ trunk/glom/dialog_new_self_hosted_connection.h	Fri Mar 27 16:54:06 2009
@@ -31,6 +31,8 @@
 namespace Glom
 {
 
+class Dialog_ProgressCreating;
+
 class Dialog_NewSelfHostedConnection
   : public Gtk::Dialog,
     public Base_DB
@@ -47,9 +49,13 @@
 
 
 private:
+  void on_connection_initialization_progress();
+  
   Gtk::Entry* m_entry_user;
   Gtk::Entry* m_entry_password;
   Gtk::Entry* m_entry_password_confirm;
+  
+  Dialog_ProgressCreating* m_dialog_progess_connection_initialize;
 };
 
 } //namespace Glom

Copied: trunk/glom/dialog_progress_creating.cc (from r2030, /trunk/glom/libglom/dialog_progress_creating.cc)
==============================================================================
--- /trunk/glom/libglom/dialog_progress_creating.cc	(original)
+++ trunk/glom/dialog_progress_creating.cc	Fri Mar 27 16:54:06 2009
@@ -18,7 +18,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include "dialog_progress_creating.h"
+#include <glom/dialog_progress_creating.h>
 #include <gtkmm/main.h>
 #include <gtkmm/dialog.h>
 #include <glibmm/i18n.h>

Modified: trunk/glom/frame_glom.cc
==============================================================================
--- trunk/glom/frame_glom.cc	(original)
+++ trunk/glom/frame_glom.cc	Fri Mar 27 16:54:06 2009
@@ -102,7 +102,9 @@
   m_dialog_addrelatedtable(0),
   m_dialog_relationships_overview(0),
 #endif // !GLOM_ENABLE_CLIENT_ONLY
-  m_pDialogConnection(0)
+  m_pDialogConnection(0),
+  m_dialog_progess_connection_startup(0),
+  m_dialog_progess_connection_cleanup(0)
 {
   //Load widgets from glade file:
   builder->get_widget("label_table_name", m_pLabel_Table);
@@ -177,6 +179,18 @@
     delete m_pDialogConnection;
     m_pDialogConnection = 0;
   }
+  
+  if(m_dialog_progess_connection_startup)
+  {
+    delete m_dialog_progess_connection_startup;
+    m_dialog_progess_connection_startup = 0;
+  }
+  
+  if(m_dialog_progess_connection_cleanup)
+  {
+    delete m_dialog_progess_connection_cleanup;
+    m_dialog_progess_connection_cleanup = 0;
+  }
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   if(m_pBox_Reports)
@@ -1692,6 +1706,22 @@
   }
 }
 
+void Frame_Glom::on_connection_startup_progress()
+{
+  if(!m_dialog_progess_connection_startup)
+    m_dialog_progess_connection_startup = Utils::get_and_show_pulse_dialog(_("Starting Database Server"), get_app_window());
+        
+  m_dialog_progess_connection_startup->pulse();
+}
+
+void Frame_Glom::on_connection_cleanup_progress()
+{
+  if(!m_dialog_progess_connection_cleanup)
+    m_dialog_progess_connection_cleanup = Utils::get_and_show_pulse_dialog(_("Stopping Database Server"), get_app_window());
+        
+  m_dialog_progess_connection_cleanup->pulse();
+}
+
 bool Frame_Glom::connection_request_password_and_choose_new_database_name()
 {
   Document_Glom* document = dynamic_cast<Document_Glom*>(get_document());
@@ -1797,14 +1827,15 @@
       //Ask for connection details:
       m_pDialogConnection->load_from_document(); //Get good defaults.
       m_pDialogConnection->set_transient_for(*get_app_window());
-      int response = Glom::Utils::dialog_run_with_help(m_pDialogConnection, "dialog_connection");
+      const int response = Glom::Utils::dialog_run_with_help(m_pDialogConnection, "dialog_connection");
       m_pDialogConnection->hide();
 
       if(response == Gtk::RESPONSE_OK)
       {
         // We are not self-hosting, but we also call initialize() for
         // consistency (the backend will ignore it anyway).
-        if(!connection_pool->initialize(get_app_window()))
+        ConnectionPool::SlotProgress slot_ignored;
+        if(!connection_pool->initialize(slot_ignored))
           return false;
       }
       else
@@ -1835,8 +1866,14 @@
   }
 
   // Do startup, such as starting the self-hosting database server
-  if(!connection_pool->startup(get_app_window()))
+  if(!connection_pool->startup( sigc::mem_fun(*this, &Frame_Glom::on_connection_startup_progress) ))
     return false;
+    
+  if(m_dialog_progess_connection_startup)
+  {
+    delete m_dialog_progess_connection_startup;
+    m_dialog_progess_connection_startup = 0;
+  }
 
   const Glib::ustring database_name = document->get_connection_database();
 
@@ -1929,10 +1966,23 @@
     }
   }
 
-  connection_pool->cleanup(get_app_window());
+  cleanup_connection();
+  
   return false;
 }
 
+void Frame_Glom::cleanup_connection()
+{
+  ConnectionPool* connection_pool = ConnectionPool::get_instance(); 
+  connection_pool->cleanup( sigc::mem_fun(*this, &Frame_Glom::on_connection_cleanup_progress) );
+
+  if(m_dialog_progess_connection_cleanup)
+  {
+    delete m_dialog_progess_connection_cleanup;
+    m_dialog_progess_connection_cleanup = 0;
+  }
+}
+
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
 bool Frame_Glom::connection_request_password_and_attempt(const Glib::ustring known_username, const Glib::ustring& known_password)
 #else
@@ -1951,8 +2001,14 @@
 
   ConnectionPool* connection_pool = ConnectionPool::get_instance();
   setup_connection_pool_from_document(document);
-  if(!connection_pool->startup(get_app_window()))
+  if(!connection_pool->startup( sigc::mem_fun(*this, &Frame_Glom::on_connection_startup_progress) ))
     return false;
+    
+  if(m_dialog_progess_connection_startup)
+  {
+    delete m_dialog_progess_connection_startup;
+    m_dialog_progess_connection_startup = 0;
+  }
 
   while(true) //Loop until a return
   {
@@ -2015,7 +2071,7 @@
           m_pDialogConnection->hide();
           if(response != Gtk::RESPONSE_OK)
           {
-            connection_pool->cleanup(get_app_window());
+            cleanup_connection();
             return false; //The user cancelled.
           }
         }
@@ -2023,7 +2079,7 @@
         {
           g_warning("Frame_Glom::connection_request_password_and_attempt(): rethrowing exception.");
 
-          connection_pool->cleanup(get_app_window());
+          cleanup_connection();
 
           //The connection to the server is OK, but the specified database does not exist:
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
@@ -2039,7 +2095,7 @@
     }
     else
     {
-      connection_pool->cleanup(get_app_window());
+      cleanup_connection();
       return false; //The user cancelled.
     }
   }

Modified: trunk/glom/frame_glom.h
==============================================================================
--- trunk/glom/frame_glom.h	(original)
+++ trunk/glom/frame_glom.h	Fri Mar 27 16:54:06 2009
@@ -52,6 +52,7 @@
 class Window_PrintLayout_Edit;
 class Dialog_AddRelatedTable;
 class Dialog_RelationshipsOverview;
+class Dialog_ProgressCreating;
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
 class Frame_Glom :
@@ -217,6 +218,10 @@
   void on_dialog_add_related_table_response(int response);
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
+  void on_connection_startup_progress();
+  void on_connection_cleanup_progress();
+  void cleanup_connection();
+  
   //Member data:
   Glib::ustring m_table_name;
 
@@ -259,10 +264,12 @@
   Dialog_Relationships* m_pDialog_Relationships;
   Dialog_AddRelatedTable* m_dialog_addrelatedtable;
   Dialog_RelationshipsOverview* m_dialog_relationships_overview;
-  
+    
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
   Dialog_Connection* m_pDialogConnection;
+  Dialog_ProgressCreating* m_dialog_progess_connection_startup;
+  Dialog_ProgressCreating* m_dialog_progess_connection_cleanup;
 };
 
 } //namespace Glom

Modified: trunk/glom/glade_utils.h
==============================================================================
--- trunk/glom/glade_utils.h	(original)
+++ trunk/glom/glade_utils.h	Fri Mar 27 16:54:06 2009
@@ -23,7 +23,7 @@
 
 #include <iostream> // For std::cerr
 #include <gtkmm/builder.h>
-#include <gtkmm/builder.h>
+#include <glom/dialog_progress_creating.h>
 
 namespace Glom
 {
@@ -123,6 +123,8 @@
   }
 }
 
+Dialog_ProgressCreating* get_and_show_pulse_dialog(const Glib::ustring& message, Gtk::Window* parent_window);
+
 } //namespace Utils
 
 } //namespace Glom

Modified: trunk/glom/libglom/Makefile.am
==============================================================================
--- trunk/glom/libglom/Makefile.am	(original)
+++ trunk/glom/libglom/Makefile.am	Fri Mar 27 16:54:06 2009
@@ -29,7 +29,6 @@
                      busy_cursor.h \
                      calcinprogress.h \
                      connectionpool.h \
-                     dialog_progress_creating.h \
                      spawn_with_feedback.h \
                      utils.h \
                      gst-package.h
@@ -38,7 +37,6 @@
                      busy_cursor.cc \
                      calcinprogress.cc \
                      connectionpool.cc \
-                     dialog_progress_creating.cc \
                      spawn_with_feedback.cc \
                      utils.cc \
                      gst-package.c

Modified: trunk/glom/libglom/connectionpool.cc
==============================================================================
--- trunk/glom/libglom/connectionpool.cc	(original)
+++ trunk/glom/libglom/connectionpool.cc	Fri Mar 27 16:54:06 2009
@@ -602,9 +602,8 @@
 
   if(signum == SIGSEGV)
   {
-    //TODO: Make this dialog transient for the parent window, 
-    //though this is obviously an unusual case.
-    connection_pool->cleanup(0 /* parent_window */);
+    ConnectionPool::SlotProgress slot_ignored;
+    connection_pool->cleanup(slot_ignored);
 
     //Let GNOME/Ubuntu's crash handler still handle this?
     if(previous_sig_handler)
@@ -614,12 +613,12 @@
   }
 }
 
-bool ConnectionPool::startup(Gtk::Window* parent_window)
+bool ConnectionPool::startup(const SlotProgress& slot_progress)
 {
   if(!m_backend.get())
     return false;
 
-  if(!m_backend->startup(parent_window))
+  if(!m_backend->startup(slot_progress))
     return false;
 
 #ifndef G_OS_WIN32
@@ -634,10 +633,10 @@
   return true;
 }
 
-void ConnectionPool::cleanup(Gtk::Window* parent_window)
+void ConnectionPool::cleanup(const SlotProgress& slot_progress)
 {
   if(m_backend.get())
-    m_backend->cleanup(parent_window);
+    m_backend->cleanup(slot_progress);
 
   //Make sure that connect() makes a new connection:
   connection_cached.clear();
@@ -781,10 +780,10 @@
 }
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
-bool ConnectionPool::initialize(Gtk::Window* parent_window)
+bool ConnectionPool::initialize(const SlotProgress& slot_progress)
 {
   if(m_backend.get())
-    return m_backend->initialize(parent_window, get_user(), get_password());
+    return m_backend->initialize(slot_progress, get_user(), get_password());
   else
     return false;
 }

Modified: trunk/glom/libglom/connectionpool.h
==============================================================================
--- trunk/glom/libglom/connectionpool.h	(original)
+++ trunk/glom/libglom/connectionpool.h	Fri Mar 27 16:54:06 2009
@@ -41,7 +41,6 @@
 
 namespace Gtk
 {
-  class Window;
   class Dialog;
 }
 
@@ -150,22 +149,27 @@
   const FieldTypes* get_field_types() const;
   Glib::ustring get_string_find_operator() const;
 
+  /** This callback should show UI to indicate that work is still happening.
+   * For instance, a pulsing ProgressBar.
+   */
+  typedef sigc::slot<void> SlotProgress;
+  
   /** Do one-time initialization, such as  creating required database
    * files on disk for later use by their own  database server instance.
    * @param parent_window A parent window to use as the transient window when displaying errors.
    */
-  bool initialize(Gtk::Window* parent_window);
+  bool initialize(const SlotProgress& slot_progress);
 
   /** Start a database server instance for the exisiting database files.
    * @param parent_window The parent window (transient for) of any dialogs shown during this operation.
    * @result Whether the operation was successful.
    */
-  bool startup(Gtk::Window* parent_window);
+  bool startup(const SlotProgress& slot_progress);
 
   /** Stop the database server instance for the database files.
    * @param parent_window The parent window (transient for) of any dialogs shown during this operation.
    */
-  void cleanup(Gtk::Window* parent_window);
+  void cleanup(const SlotProgress& slot_progress);
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 #ifdef GLIBMM_EXCEPTIONS_ENABLED

Modified: trunk/glom/libglom/connectionpool_backends/backend.cc
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/backend.cc	(original)
+++ trunk/glom/libglom/connectionpool_backends/backend.cc	Fri Mar 27 16:54:06 2009
@@ -45,18 +45,19 @@
 namespace ConnectionPoolBackends
 {
 
-bool Backend::initialize(Gtk::Window* /* parent_window */, const Glib::ustring& /* initial_username */, const Glib::ustring& /* password */)
+bool Backend::initialize(const SlotProgress& /* slot_progress */, const Glib::ustring& /* initial_username */, const Glib::ustring& /* password */)
 {
   return true;
 }
 
-bool Backend::startup(Gtk::Window* /* parent_window */)
+bool Backend::startup(const SlotProgress& /* slot_progress */)
 {
   return true;
 }
 
-void Backend::cleanup(Gtk::Window* /* parent_window */)
-{}
+void Backend::cleanup(const SlotProgress& /* slot_progress */)
+{
+}
 
 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)
 {

Modified: trunk/glom/libglom/connectionpool_backends/backend.h
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/backend.h	(original)
+++ trunk/glom/libglom/connectionpool_backends/backend.h	Fri Mar 27 16:54:06 2009
@@ -101,23 +101,34 @@
    */
   virtual Glib::ustring get_string_find_operator() const = 0;
 
+  /** This callback should show UI to indicate that work is still happening.
+   * For instance, a pulsing ProgressBar.
+   */
+  typedef sigc::slot<void> SlotProgress;
+
   /** This method is called for one-time initialization of the database
    * storage. No need to implement this function if the data is centrally
    * hosted, not managed by Glom.
+   *
+   * @slot_progress A callback to call while the work is still happening.
    */
-  virtual bool initialize(Gtk::Window* parent_window, const Glib::ustring& initial_username, const Glib::ustring& password);
+  virtual bool initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username, const Glib::ustring& password);
 
   /** This method is called before the backend is used otherwise. This can
    * be used to start a self-hosted database server. There is no need to implement
    * this function if there is no need for extra startup code.
+   *
+   * @slot_progress A callback to call while the work is still happening.
    */
-  virtual bool startup(Gtk::Window* parent_window);
+  virtual bool startup(const SlotProgress& slot_progress);
 
   /** This method is called when the backend is no longer used. This can be
    * used to shut down a self-hosted database server. There is no need to
    * implement this function if there is no need for extra cleanup code.
+   *
+   * @slot_progress A callback to call while the work is still happening.
    */
-  virtual void cleanup(Gtk::Window* parent_window);
+  virtual void cleanup(const SlotProgress& slot_progress);
 
   /** This method is called to create a connection to the database server.
    * There exists only the variant with an error variable as last parameter

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 Mar 27 16:54:06 2009
@@ -194,7 +194,7 @@
 /** Try to install postgres on the distro, though this will require a
  * distro-specific patch to the implementation.
  */
-bool PostgresSelfHosted::install_postgres(Gtk::Window* /* parent_window */)
+bool PostgresSelfHosted::install_postgres(const SlotProgress& /* slot_progress */)
 {
 #if 0
   // This  is example code for Ubuntu, and possibly Debian,
@@ -229,8 +229,10 @@
 #endif // #if 0
 }
 
-bool PostgresSelfHosted::initialize(Gtk::Window* parent_window, const Glib::ustring& initial_username, const Glib::ustring& password)
+bool PostgresSelfHosted::initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username, const Glib::ustring& password)
 {
+  Gtk::Window* parent_window = 0; //TODO: Replace the dialog with some callback or exception?
+  
   if(m_self_hosting_data_uri.empty())
   {
     std::cerr << "PostgresSelfHosted::initialize: m_self_hosting_data_uri is empty." << std::endl;
@@ -322,7 +324,7 @@
                                         " -U " + initial_username + " --pwfile=\"" + temp_pwfile + "\"";
 
   //Note that --pwfile takes the password from the first line of a file. It's an alternative to supplying it when prompted on stdin.
-  const bool result = Glom::Spawn::execute_command_line_and_wait(command_initdb, _("Creating Database Data"), parent_window);
+  const bool result = Glom::Spawn::execute_command_line_and_wait(command_initdb, slot_progress);
   if(!result)
   {
     std::cerr << "Error while attempting to create self-hosting database." << std::endl;
@@ -334,7 +336,7 @@
   return result;
 }
 
-bool PostgresSelfHosted::startup(Gtk::Window* parent_window)
+bool PostgresSelfHosted::startup(const SlotProgress& slot_progress)
 {
   // Don't risk random crashes, although this really shouldn't be called
   // twice of course.
@@ -405,7 +407,7 @@
   const std::string second_command_success_text = "is running"; //TODO: This is not a stable API. Also, watch out for localisation.
 
   //The first command does not return, but the second command can check whether it succeeded:
-  const bool result = Glom::Spawn::execute_command_line_and_wait_until_second_command_returns_success(command_postgres_start, command_check_postgres_has_started, _("Starting Database Server"), parent_window, second_command_success_text);
+  const bool result = Glom::Spawn::execute_command_line_and_wait_until_second_command_returns_success(command_postgres_start, command_check_postgres_has_started, slot_progress, second_command_success_text);
   if(!result)
   {
     std::cerr << "Error while attempting to self-host a database." << std::endl;
@@ -417,7 +419,7 @@
   return true;
 }
 
-void PostgresSelfHosted::cleanup(Gtk::Window* parent_window)
+void PostgresSelfHosted::cleanup(const SlotProgress& slot_progress)
 {
   // This seems to be called twice sometimes, so we don't assert here until
   // this is fixed.
@@ -445,14 +447,14 @@
   // Make sure to use double quotes for the executable path, because the
   // CreateProcess() API used on Windows does not support single quotes.
   const std::string command_postgres_stop = "\"" + get_path_to_postgres_executable("pg_ctl") + "\" -D \"" + dbdir_data + "\" stop -m fast";
-  const bool result = Glom::Spawn::execute_command_line_and_wait(command_postgres_stop, _("Stopping Database Server"), parent_window);
+  const bool result = Glom::Spawn::execute_command_line_and_wait(command_postgres_stop, slot_progress);
   if(!result)
   {
     std::cerr << "Error while attempting to stop self-hosting of the database. Trying again."  << std::endl;
 
     //I've seen it fail when running under valgrind, and there are reports of failures in bug #420962.
     //Maybe it will help to try again:
-    const bool result = Glom::Spawn::execute_command_line_and_wait(command_postgres_stop, _("Stopping Database Server (retrying)"), parent_window);
+    const bool result = Glom::Spawn::execute_command_line_and_wait(command_postgres_stop, slot_progress);
     if(!result)
     {
       std::cerr << "Error while attempting (for a second time) to stop self-hosting of the database."  << std::endl;

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 Mar 27 16:54:06 2009
@@ -64,13 +64,13 @@
   /** Try to install postgres on the distro, though this will require a
    * distro-specific patch to the implementation.
    */
-  static bool install_postgres(Gtk::Window* parent_window);
+  static bool install_postgres(const SlotProgress& slot_progress);
 
 private:
-  virtual bool initialize(Gtk::Window* parent_window, const Glib::ustring& initial_username, const Glib::ustring& password);
+  virtual bool initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username, const Glib::ustring& password);
 
-  virtual bool startup(Gtk::Window* parent_window);
-  virtual void cleanup(Gtk::Window* parent_window);
+  virtual bool startup(const SlotProgress& slot_progress);
+  virtual void cleanup(const SlotProgress& slot_progress);
 
   virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
 

Modified: trunk/glom/libglom/document/document_glom.cc
==============================================================================
--- trunk/glom/libglom/document/document_glom.cc	(original)
+++ trunk/glom/libglom/document/document_glom.cc	Fri Mar 27 16:54:06 2009
@@ -271,15 +271,6 @@
 
 Document_Glom::~Document_Glom()
 {
-#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:
-  ConnectionPool* connection_pool = ConnectionPool::get_instance();
-  if(!connection_pool)
-    return;
-
-  connection_pool->cleanup(m_parent_window);
-#endif // !GLOM_ENABLE_CLIENT_ONLY
 }
 
 Document_Glom::HostingMode Document_Glom::get_hosting_mode() const

Modified: trunk/glom/libglom/spawn_with_feedback.cc
==============================================================================
--- trunk/glom/libglom/spawn_with_feedback.cc	(original)
+++ trunk/glom/libglom/spawn_with_feedback.cc	Fri Mar 27 16:54:06 2009
@@ -19,12 +19,15 @@
  */
 
 #include <libglom/spawn_with_feedback.h>
-#include <libglom/dialog_progress_creating.h>
-#include <glom/glade_utils.h>
-#include <gtkmm/main.h>
-#include <gtkmm/messagedialog.h>
+#include <glibmm/main.h>
+#include <glibmm/spawn.h>
+#include <glibmm/thread.h>
+#include <glibmm/iochannel.h>
+#include <glibmm/shell.h>
+#include <glibmm/miscutils.h>
 #include <glibmm/i18n.h>
 #include <memory> //For auto_ptr.
+#include <stdexcept>
 #include <iostream>
 
 #ifdef G_OS_WIN32
@@ -50,9 +53,17 @@
   bool* m_result;
 };
 
-// This is a simple process launching API wrapping g_spawn_async on linux and
-// CreateProcess() on Windows. We need to use CreateProcess on Windows to be
+static void on_spawn_info_finished(const Glib::RefPtr<Glib::MainLoop>& mainloop)
+{
+  //Allow our mainloop.run() to return:
+  if(mainloop)
+    mainloop->quit();
+}
+
+// This is a simple-process launching API wrapping g_spawn_async on linux and
+// CreateProcess() on Windows. We need to use CreateProcess() on Windows to be
 // able to suppress the console window.
+// TODO: File a bug about the console window on Windows.
 namespace Impl
 {
 
@@ -120,7 +131,7 @@
       char buffer[1024 + 1];
       gsize bytes_read;
 
-      Glib::IOStatus status;
+      Glib::IOStatus status = Glib::IO_STATUS_NORMAL;
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
       try
       {
@@ -341,11 +352,14 @@
   if(stderr_text)
     redirect_flags |= REDIRECT_STDERR;
 
+  Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create(false);
+     
   std::auto_ptr<const SpawnInfo> info = spawn_async(command_line, redirect_flags);
-  info->signal_finished().connect(sigc::ptr_fun(&Gtk::Main::quit));
-
-  // Wait for termination
-  Gtk::Main::run();
+  info->signal_finished().connect(
+    sigc::bind(sigc::ptr_fun(&on_spawn_info_finished), sigc::ref(mainloop) ) );
+ 
+  // Block until signal_finished is emitted:
+  mainloop->run();
 
   int return_status = 0;
   bool returned = spawn_async_end(info, stdout_text, stderr_text, &return_status);
@@ -355,69 +369,30 @@
 
 } // namespace Impl
 
-static Dialog_ProgressCreating* get_and_show_pulse_dialog(const Glib::ustring& message, Gtk::Window* parent_window)
-{
-  if(!parent_window)
-    std::cerr << "debug: Glom: get_and_show_pulse_dialog(): parent_window is NULL" << std::endl;
-
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  Glib::RefPtr<Gtk::Builder> refXml = Gtk::Builder::create_from_file(Utils::get_glade_file_path("glom.glade"), "window_progress");
-#else
-  std::auto_ptr<Glib::Error> error;
-  Glib::RefPtr<Gtk::Builder> refXml = Gtk::Builder::create_from_file(Utils::get_glade_file_path("glom.glade"), "window_progress", "", error);
-  if(error.get())
-    return 0;
-#endif
-
-  if(refXml)
-  {
-    Dialog_ProgressCreating* dialog_progress = 0;
-    refXml->get_widget_derived("window_progress", dialog_progress);
-    if(dialog_progress)
-    {
-      dialog_progress->set_message(_("Processing"), message);
-      dialog_progress->set_modal();
-
-      if(parent_window)
-        dialog_progress->set_transient_for(*parent_window);
 
-      dialog_progress->show();
-
-      return dialog_progress;
-    }
-  }
-
-  return NULL;
-}
-
-
-
-bool execute_command_line_and_wait(const std::string& command, const Glib::ustring& message, Gtk::Window* parent_window)
+bool execute_command_line_and_wait(const std::string& command, const SlotProgress& slot_progress)
 {
-  if(!parent_window)
-    std::cerr << "debug: Glom: execute_command_line_and_wait(): parent_window is NULL" << std::endl;
-
-  //Show a dialog with a pulsing progress bar and a human-readable message, while we wait for the command to finish:
-  //
-  //Put the dialog in an auto_ptr so that it will be deleted (and hidden) when the current function returns.
-  Dialog_ProgressCreating* dialog_temp = get_and_show_pulse_dialog(message, parent_window);
-  std::auto_ptr<Dialog_ProgressCreating> dialog_progress;
-  dialog_progress.reset(dialog_temp);
-
+  //Show UI progress feedback while we wait for the command to finish:
+  
   std::auto_ptr<const Impl::SpawnInfo> info = Impl::spawn_async(command, 0);
+  
+  Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create(false);
   info->signal_finished().connect(
-    sigc::bind(sigc::mem_fun(*dialog_progress, &Dialog_ProgressCreating::response), Gtk::RESPONSE_ACCEPT));
+    sigc::bind(sigc::ptr_fun(&on_spawn_info_finished), sigc::ref(mainloop) ) );
 
-  // Pulse two times a second
+  // Pulse two times a second:
   Glib::signal_timeout().connect(
-    sigc::bind_return(sigc::mem_fun(*dialog_progress, &Dialog_ProgressCreating::pulse), true),
+    sigc::bind_return( slot_progress, true),
     500);
+  slot_progress(); //Make sure it is called at least once.
 
-  dialog_progress->run();
+  //Block until signal_finished is called.
+  mainloop->run();
 
-  int return_status;
-  bool returned = Impl::spawn_async_end(info, NULL, NULL, &return_status);
-  if(!returned) return false; // User closed the dialog prematurely?
+  int return_status = false;
+  const bool returned = Impl::spawn_async_end(info, NULL, NULL, &return_status);
+  if(!returned)
+    return false; // User closed the dialog prematurely?
 
   return (return_status == 0);
 }
@@ -426,7 +401,7 @@
 namespace
 {
 
-  bool on_timeout(const std::string& second_command, const std::string& success_text, Dialog_ProgressCreating* dialog_progress)
+  bool second_command_on_timeout(const std::string& second_command, const std::string& success_text, const SlotProgress& slot_progress, const Glib::RefPtr<Glib::MainLoop>& mainloop)
   {
     Glib::ustring stored_env_lang;
     Glib::ustring stored_env_language;
@@ -485,9 +460,9 @@
 
       if(success)
       {
-        std::cout << "Success, do response" << std::endl;
+        std::cout << "debug: Success, do response" << std::endl;
         // Exit from run() in execute_command_line_and_wait_until_second_command_returns_success().
-        dialog_progress->response(Gtk::RESPONSE_OK);
+        mainloop->quit();
         // Cancel timeout. Actually, we also could return true here since
         // the signal is disconnect explicetely after run() anyway.
         return false;
@@ -498,22 +473,24 @@
        std::cout << " debug: second command failed. output=" << stdout_output << std::endl;
     }
 
-    dialog_progress->pulse();
+    slot_progress(); //Show UI progress feedback.
     return true;
   }
 
 } //Anonymous namespace
 
-bool execute_command_line_and_wait_until_second_command_returns_success(const std::string& command, const std::string& second_command, const Glib::ustring& message, Gtk::Window* parent_window, const std::string& success_text)
+static bool on_timeout_delay(const Glib::RefPtr<Glib::MainLoop>& mainloop)
 {
-  if(!parent_window)
-    std::cerr << "debug: Glom: execute_command_line_and_wait_until_second_command_returns_success(): parent_window is NULL" << std::endl;
-
-  Dialog_ProgressCreating* dialog_temp = get_and_show_pulse_dialog(message, parent_window);
-  std::auto_ptr<Dialog_ProgressCreating> dialog_progress;
-  dialog_progress.reset(dialog_temp);
+  //Allow our mainloop.run() to return:
+  if(mainloop)
+    mainloop->quit();
+    
+  return false;
+}
 
-  std::cout << "Command: " << command << std::endl;
+bool execute_command_line_and_wait_until_second_command_returns_success(const std::string& command, const std::string& second_command, const SlotProgress& slot_progress, const std::string& success_text)
+{
+  std::cout << "debug: Command: " << command << std::endl;
 
   std::auto_ptr<const Impl::SpawnInfo> info = Impl::spawn_async(command, Impl::REDIRECT_STDERR);
 
@@ -523,35 +500,41 @@
   // b) Get stderr data, to display an error message in case the command
   // fails:
 
-  // Hide dialog when the first command finished for some reason
-  sigc::connection watch_conn = info->signal_finished().connect(sigc::bind(sigc::mem_fun(*dialog_temp, &Dialog_ProgressCreating::response), Gtk::RESPONSE_REJECT));
+  Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create(false);
+  sigc::connection watch_conn = info->signal_finished().connect(
+    sigc::bind(sigc::ptr_fun(&on_spawn_info_finished), sigc::ref(mainloop) ) );
 
   // Call the second command once every second
-  sigc::connection timeout_conn = Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&on_timeout), sigc::ref(second_command), sigc::ref(success_text), dialog_temp), 1000);
+  sigc::connection timeout_conn = Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&second_command_on_timeout), sigc::ref(second_command), sigc::ref(success_text), slot_progress, sigc::ref(mainloop)), 1000);
+  slot_progress(); //Make sure it is called at least once.
 
-  // Enter the main loop
-  int response = dialog_temp->run();
+  // Block until signal_finished is emitted:
+  mainloop->run();
 
   timeout_conn.disconnect();
   watch_conn.disconnect();
 
   std::string stderr_text;
 
-  Impl::spawn_async_end(info, NULL, &stderr_text, NULL);
+  const bool success = Impl::spawn_async_end(info, NULL, &stderr_text, NULL);
 
-  if(response == Gtk::RESPONSE_OK)
+  if(success) //response == Gtk::RESPONSE_OK)
   {
     //Sleep for a bit more, because I think that pg_ctl sometimes reports success too early.
-    Glib::signal_timeout().connect(sigc::bind_return(sigc::ptr_fun(&Gtk::Main::quit), false), 3000);
-    Gtk::Main::run();
+    Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create(false);
+    Glib::signal_timeout().connect(
+     sigc::bind(sigc::ptr_fun(&on_timeout_delay), sigc::ref(mainloop)), 
+     3000);
+    mainloop->run();
 
     return true;
   }
   else
   {
     // The user either cancelled, or the first command failed, or exited prematurely
-    if(response == Gtk::RESPONSE_REJECT)
+    if(true) //response == Gtk::RESPONSE_REJECT)
     {
+      /* TODO: Allow the caller to show a dialog?
       // Command failed
       std::auto_ptr<Gtk::MessageDialog> error_dialog;
       if(parent_window)
@@ -562,6 +545,9 @@
       // TODO: i18n
       error_dialog->set_secondary_text("The command was:\n\n" + Glib::Markup::escape_text(command) + (stderr_text.empty() ? Glib::ustring("") : ("\n\n<small>" + Glib::Markup::escape_text(stderr_text) + "</small>")), true);
       error_dialog->run();
+      */
+      
+      std::cerr << "Glom:  execute_command_line_and_wait_until_second_command_returns_success(): Child command failed. The command was: " << std::endl << stderr_text << std::endl;
     }
     else
     {

Modified: trunk/glom/libglom/spawn_with_feedback.h
==============================================================================
--- trunk/glom/libglom/spawn_with_feedback.h	(original)
+++ trunk/glom/libglom/spawn_with_feedback.h	Fri Mar 27 16:54:06 2009
@@ -21,7 +21,8 @@
 #ifndef GLOM_SPAWN_WITH_FEEDBACK_H
 #define GLOM_SPAWN_WITH_FEEDBACK_H
 
-#include <gtkmm/window.h>
+#include <glibmm/ustring.h>
+#include <sigc++/sigc++.h>
 
 namespace Glom
 {
@@ -29,23 +30,25 @@
 namespace Spawn
 {
 
+/** This callback should show UI to indicate that work is still happening.
+ * For instance, a pulsing ProgressBar.
+ */
+typedef sigc::slot<void> SlotProgress;
 
 /** Execute a command-line command, and wait for it to return.
  * @param command The command-line command.
  * @param message A human-readable message to be shown, for instance in a dialog, while waiting.
- * @parent_window Make the dialog transient to this window.
+ * @slot_progress A callback to call while the work is still happening.
  */
-bool execute_command_line_and_wait(const std::string& command, const Glib::ustring& message, Gtk::Window* parent_window);
+bool execute_command_line_and_wait(const std::string& command, const SlotProgress& slot_progress);
 
 /** Execute a command-line command, and repeatedly call a second command that tests whether the first command has finished.
  * @param command The command-line command.
  * @param message A human-readable message to be shown, for instance in a dialog, while waiting. 
- * @parent_window Make the dialog transient to this window.
+ * @slot_progress A callback to call while the work is still happening.
  * @success_text If this is not empty, then the second command will only be considered to have succeeded when this text is found in its stdout output.
  */
-bool execute_command_line_and_wait_until_second_command_returns_success(const std::string& command, const std::string& second_command, const Glib::ustring& message, Gtk::Window* parent_window, const std::string& success_text = std::string());
-
-//bool execute_command_line_and_wait_fixed_seconds(const std::string& command, unsigned int seconds, const Glib::ustring& message, Gtk::Window* parent_window);
+bool execute_command_line_and_wait_until_second_command_returns_success(const std::string& command, const std::string& second_command, const SlotProgress& slot_progress, const std::string& success_text = std::string());
 
 
 } //Spawn



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