glom r1997 - in trunk: . glom glom/bakery glom/layout_item_dialogs glom/libglom glom/libglom/connectionpool_backends glom/libglom/document glom/libglom/document/bakery glom/libglom/document/bakery/view glom/mode_data glom/mode_design glom/mode_design/fields glom/mode_design/print_layouts glom/mode_design/script_library glom/mode_design/users glom/mode_find glom/navigation glom/reports glom/translation glom/utility_widgets glom/utility_widgets/adddel glom/utility_widgets/db_adddel



Author: murrayc
Date: Tue Mar 17 10:46:53 2009
New Revision: 1997
URL: http://svn.gnome.org/viewvc/glom?rev=1997&view=rev

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

* configure.ac: Remove bakery dependency.
* glom/Makefile.am:
* glom/bakery/: Added copies of the Bakery/App files.
* glom/libglom/document/bakery/: Added copies of the Bakery Document 
and View files.
This allows us to change the Bakery ABI when we need to. We already 
do unusually hacky things with Bakery so this is reasonable.

Added:
   trunk/glom/bakery/
   trunk/glom/bakery/App.cc
   trunk/glom/bakery/App.h
   trunk/glom/bakery/AppInstanceManager.cc
   trunk/glom/bakery/AppInstanceManager.h
   trunk/glom/bakery/App_Gtk.cc
   trunk/glom/bakery/App_Gtk.h
   trunk/glom/bakery/App_WithDoc.cc
   trunk/glom/bakery/App_WithDoc.h
   trunk/glom/bakery/App_WithDoc_Gtk.cc
   trunk/glom/bakery/App_WithDoc_Gtk.h
   trunk/glom/bakery/Dialog_OfferSave.cc
   trunk/glom/bakery/Dialog_OfferSave.h
   trunk/glom/bakery/GtkDialogs.cc
   trunk/glom/bakery/GtkDialogs.h
   trunk/glom/bakery/Makefile.am
   trunk/glom/libglom/busy_cursor.cc
   trunk/glom/libglom/busy_cursor.h
   trunk/glom/libglom/document/bakery/
   trunk/glom/libglom/document/bakery/Document.cc
   trunk/glom/libglom/document/bakery/Document.h
   trunk/glom/libglom/document/bakery/Document_XML.cc
   trunk/glom/libglom/document/bakery/Document_XML.h
   trunk/glom/libglom/document/bakery/Makefile.am
   trunk/glom/libglom/document/bakery/view/
   trunk/glom/libglom/document/bakery/view/Makefile.am
   trunk/glom/libglom/document/bakery/view/View.cc
   trunk/glom/libglom/document/bakery/view/View.h
   trunk/glom/libglom/document/bakery/view/ViewBase.cc
   trunk/glom/libglom/document/bakery/view/ViewBase.h
   trunk/glom/libglom/document/bakery/view/View_Composite.cc
   trunk/glom/libglom/document/bakery/view/View_Composite.h
   trunk/glom/libglom/document/view.h   (contents, props changed)
Modified:
   trunk/ChangeLog
   trunk/configure.ac
   trunk/glom/Makefile.am
   trunk/glom/application.cc
   trunk/glom/application.h
   trunk/glom/base_db.cc
   trunk/glom/base_db.h
   trunk/glom/base_db_table_data.cc
   trunk/glom/box_reports.cc
   trunk/glom/box_withbuttons.h
   trunk/glom/dialog_connection.cc
   trunk/glom/dialog_database_preferences.cc
   trunk/glom/dialog_new_self_hosted_connection.cc
   trunk/glom/frame_glom.cc
   trunk/glom/frame_glom.h
   trunk/glom/glom_privs.cc
   trunk/glom/layout_item_dialogs/dialog_groupby_secondaryfields.cc
   trunk/glom/layout_item_dialogs/dialog_groupby_sortfields.cc
   trunk/glom/layout_item_dialogs/dialog_notebook.cc
   trunk/glom/libglom/Makefile.am
   trunk/glom/libglom/connectionpool.cc
   trunk/glom/libglom/connectionpool_backends/postgres.cc
   trunk/glom/libglom/connectionpool_backends/postgres_central.cc
   trunk/glom/libglom/connectionpool_backends/postgres_self.cc
   trunk/glom/libglom/document/Makefile.am
   trunk/glom/libglom/document/document_glom.cc
   trunk/glom/libglom/document/document_glom.h
   trunk/glom/libglom/spawn_with_feedback.cc
   trunk/glom/libglom/utils.cc
   trunk/glom/libglom/utils.h
   trunk/glom/main.cc
   trunk/glom/mode_data/box_data.cc
   trunk/glom/mode_data/box_data_calendar_related.cc
   trunk/glom/mode_data/box_data_details.cc
   trunk/glom/mode_data/box_data_list.cc
   trunk/glom/mode_data/box_data_list_related.cc
   trunk/glom/mode_data/box_data_manyrecords.cc
   trunk/glom/mode_data/box_data_portal.cc
   trunk/glom/mode_data/dialog_layout_calendar_related.cc
   trunk/glom/mode_data/dialog_layout_details.cc
   trunk/glom/mode_data/dialog_layout_export.cc
   trunk/glom/mode_data/dialog_layout_list.cc
   trunk/glom/mode_data/dialog_layout_list_related.cc
   trunk/glom/mode_data/flowtablewithfields.cc
   trunk/glom/mode_design/box_db_table_relationships.cc
   trunk/glom/mode_design/dialog_fields.cc
   trunk/glom/mode_design/dialog_relationships.cc
   trunk/glom/mode_design/fields/box_db_table_definition.cc
   trunk/glom/mode_design/print_layouts/box_print_layouts.cc
   trunk/glom/mode_design/print_layouts/canvas_print_layout.cc
   trunk/glom/mode_design/print_layouts/window_print_layout_edit.cc
   trunk/glom/mode_design/script_library/dialog_script_library.cc
   trunk/glom/mode_design/users/dialog_groups_list.cc
   trunk/glom/mode_design/users/dialog_users_list.cc
   trunk/glom/mode_find/box_data_details_find.cc
   trunk/glom/mode_find/box_data_list_find.cc
   trunk/glom/navigation/box_tables.cc
   trunk/glom/reports/dialog_layout_report.cc
   trunk/glom/translation/dialog_copy_translation.cc
   trunk/glom/translation/dialog_identify_original.cc
   trunk/glom/translation/window_translations.cc
   trunk/glom/utility_widgets/adddel/adddel.cc
   trunk/glom/utility_widgets/db_adddel/db_adddel.cc
   trunk/glom/utility_widgets/dialog_choose_date.cc
   trunk/glom/utility_widgets/dialog_choose_id.cc
   trunk/glom/utility_widgets/filechooserdialog_saveextras.cc

Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac	(original)
+++ trunk/configure.ac	Tue Mar 17 10:46:53 2009
@@ -106,12 +106,11 @@
 
 
 # Do not require, goocanvas and gtksourceviewmm in client only mode
-REQUIRED_LIBS="bakery-2.6 >= 2.6.0 gtkmm-2.4 >= 2.14 gthread-2.0 libxslt >= 1.1.10 pygda-4.0 >= 2.25.3 pygtk-2.0 >= 2.6.0 libgdamm-4.0 >= 3.99.12 libgda-4.0 >= 3.99.13 libgda-postgres-4.0 goocanvasmm-1.0 >= 0.13.0"
+REQUIRED_LIBS="gtkmm-2.4 >= 2.14 gthread-2.0 libglademm-2.4 gconfmm-2.6 libxml++-2.6 libxslt >= 1.1.10 pygda-4.0 >= 2.25.3 pygtk-2.0 >= 2.6.0 libgdamm-4.0 >= 3.99.12 libgda-4.0 >= 3.99.13 libgda-postgres-4.0 goocanvasmm-1.0 >= 0.13.0"
 if test $enable_client_only != yes; then
 	REQUIRED_LIBS="$REQUIRED_LIBS gtksourceviewmm-2.0"
 fi
 
-# TODO_maemo: Make sure bakery was also compiled with (or without, respectively) maemo support
 if test "$enable_maemo" = "yes"; then
 	REQUIRED_LIBS="$REQUIRED_LIBS hildonmm libepc-1.0 >= 0.3.1 avahi-ui";
 elif test "$win32" = "true"; then
@@ -133,7 +132,7 @@
 
 # Temporary egg CFLAGS
 PKG_CHECK_MODULES(EGG, gtk+-2.0 >= 2.5.0)
-GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`  
+GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
 AC_SUBST(GLIB_GENMARSHAL)
 
 #Get the location of the ISO-Codes (currencies, languages) files:
@@ -222,14 +221,39 @@
   glom/Makefile \
     docs/Makefile \
       docs/user-guide/Makefile \
+  icons/Makefile \
+    icons/16x16/Makefile \
+    icons/22x22/Makefile \
+    icons/24x24/Makefile \
+    icons/32x32/Makefile \
+    icons/48x48/Makefile \
+    icons/scalable/Makefile \
+    icons/win32/Makefile \
+  xslt/Makefile \
+  po/Makefile.in \
+  macros/Makefile \
+  examples/Makefile \
+  regression_tests/Makefile \
+  glom.desktop.in \
+  win32/Makefile \
+  win32/glom.iss
+])
+
+AC_CONFIG_FILES([
     glom/libglom/glom-1.0.pc \
     glom/libglom/Makefile \
       glom/libglom/data_structure/Makefile \
         glom/libglom/data_structure/layout/Makefile \
           glom/libglom/data_structure/layout/report_parts/Makefile \
       glom/libglom/document/Makefile \
+        glom/libglom/document/bakery/Makefile \
+          glom/libglom/document/bakery/view/Makefile \
       glom/libglom/connectionpool_backends/Makefile \
       glom/libglom/python_embed/Makefile \
+])
+
+AC_CONFIG_FILES([
+    glom/bakery/Makefile \
     glom/layout_item_dialogs/Makefile \
     glom/mode_data/Makefile \
     glom/mode_design/Makefile \
@@ -253,22 +277,6 @@
     glom/relationships_overview/Makefile \
     glom/reports/Makefile \
     glom/translation/Makefile \
-    icons/Makefile \
-      icons/16x16/Makefile \
-      icons/22x22/Makefile \
-      icons/24x24/Makefile \
-      icons/32x32/Makefile \
-      icons/48x48/Makefile \
-      icons/scalable/Makefile \
-      icons/win32/Makefile \
-    xslt/Makefile \
-    po/Makefile.in \
-  macros/Makefile \
-  examples/Makefile \
-  regression_tests/Makefile \
-  glom.desktop.in \
-  win32/Makefile \
-  win32/glom.iss
 ])
 AC_OUTPUT
 

Modified: trunk/glom/Makefile.am
==============================================================================
--- trunk/glom/Makefile.am	(original)
+++ trunk/glom/Makefile.am	Tue Mar 17 10:46:53 2009
@@ -1,4 +1,4 @@
-SUBDIRS = libglom mode_data mode_find navigation utility_widgets python_embed reports
+SUBDIRS = libglom bakery mode_data mode_find navigation utility_widgets python_embed reports
 
 if !GLOM_ENABLE_CLIENT_ONLY
 SUBDIRS += layout_item_dialogs mode_design translation relationships_overview
@@ -77,7 +77,8 @@
               relationships_overview/librelationshipsoverview.a
 endif
 
-glom_LDADD += navigation/libnavigation.a \
+glom_LDADD += bakery/libbakery_app.a \
+              navigation/libnavigation.a \
               utility_widgets/libutility_widgets.a \
               utility_widgets/adddel/libutility_widgets_adddel.a \
               utility_widgets/adddel/eggcolumnchooser/libutility_widgets_adddel_eggcolumnchooserdialog.a \

Modified: trunk/glom/application.cc
==============================================================================
--- trunk/glom/application.cc	(original)
+++ trunk/glom/application.cc	Tue Mar 17 10:46:53 2009
@@ -260,7 +260,7 @@
 }
 
 //We could put this in Bakery instead, but it's hard enough just getting updates 
-//into Ubuntu, so we override this Bakery::App method here.
+//into Ubuntu, so we override this GlomBakery::App method here.
 void App_Glom::add_ui_from_string(const Glib::ustring& ui_description)
 {
   try
@@ -788,7 +788,7 @@
 void App_Glom::on_menu_file_close() //override
 {
   // Call the base class implementation:
-  Bakery::App_WithDoc_Gtk::on_menu_file_close();
+  GlomBakery::App_WithDoc_Gtk::on_menu_file_close();
 }
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
@@ -848,7 +848,7 @@
   }
 }
 
-Bakery::App* App_Glom::new_instance() //Override
+GlomBakery::App* App_Glom::new_instance() //Override
 {
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
   Glib::RefPtr<Gnome::Glade::Xml> refXml = Gnome::Glade::Xml::create(Utils::get_glade_file_path("glom.glade"), "window_main");
@@ -983,7 +983,7 @@
       const AppState::userlevels userlevel = pDocument->get_userlevel(reason);
       if( (userlevel == AppState::USERLEVEL_OPERATOR) && (reason == Document_Glom::USER_LEVEL_REASON_FILE_READ_ONLY) )
       {
-        Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Opening Read-Only File.")), true,  Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE);
+        Gtk::MessageDialog dialog(Utils::bold_message(_("Opening Read-Only File.")), true,  Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE);
         dialog.set_secondary_text(_("This file is read only, so you will not be able to enter Developer mode to make design changes."));
         dialog.set_transient_for(*this);
         dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
@@ -1476,7 +1476,7 @@
     connection_pool->set_database(db_name); //Specify the new database when connecting from now on.
 
   dialog_progress->pulse();
-  Bakery::BusyCursor busy_cursor(this);
+  BusyCursor busy_cursor(this);
 
   sharedptr<SharedConnection> sharedconnection;
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
@@ -1887,7 +1887,7 @@
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 void App_Glom::on_menu_file_save_as_example()
 {
-  //Based on the implementation of Bakery::App_WithDoc::on_menu_file_saveas()
+  //Based on the implementation of GlomBakery::App_WithDoc::on_menu_file_saveas()
 
   //Display File Save dialog and respond to choice:
 
@@ -2399,7 +2399,7 @@
       return;
   }
 
-  Bakery::App_WithDoc_Gtk::document_history_add(file_uri);
+  GlomBakery::App_WithDoc_Gtk::document_history_add(file_uri);
 }
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY

Modified: trunk/glom/application.h
==============================================================================
--- trunk/glom/application.h	(original)
+++ trunk/glom/application.h	Tue Mar 17 10:46:53 2009
@@ -21,7 +21,7 @@
 #ifndef HEADER_APP_GLOM
 #define HEADER_APP_GLOM
 
-#include "bakery/bakery.h"
+#include <glom/bakery/App_WithDoc_Gtk.h>
 #include "frame_glom.h"
 
 #include <libglom/libglom_config.h> // For GLOM_ENABLE_CLIENT_ONLY
@@ -40,7 +40,7 @@
 
 class Window_Translations;
 
-class App_Glom : public Bakery::App_WithDoc_Gtk
+class App_Glom : public GlomBakery::App_WithDoc_Gtk
 {
 public:
   App_Glom(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& refGlade);
@@ -132,7 +132,7 @@
   virtual void on_menu_file_close(); //override.
   virtual void document_history_add(const Glib::ustring& file_uri); //overridden.
 
-  virtual Bakery::App* new_instance(); //Override
+  virtual GlomBakery::App* new_instance(); //Override
 
 #ifndef G_OS_WIN32
   void open_browsed_document(const EpcServiceInfo* server, const Glib::ustring& service_name);
@@ -140,7 +140,7 @@
 
   static Glib::ustring get_file_uri_without_extension(const Glib::ustring& uri);
 
-  typedef Bakery::App_WithDoc_Gtk type_base;
+  typedef GlomBakery::App_WithDoc_Gtk type_base;
 
   //Widgets:
 

Added: trunk/glom/bakery/App.cc
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/App.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glom/bakery/App.h>
+#include <algorithm>
+
+
+namespace GlomBakery
+{
+
+//Initialize static member data:
+AppInstanceManager App::m_AppInstanceManager;
+HelpInfo App::m_HelpInfo;
+
+bool App::m_bAboutShown = false;
+bool App::m_bOperationCancelled = false;
+Glib::ustring App::m_strCommandLine_0;
+Glib::ustring App::m_strAppName;
+
+App::App(const Glib::ustring& appname)
+{
+  init_app_name(appname);
+  
+  //Register an instance of this app:
+  m_AppInstanceManager.add_app(this);
+}
+
+App::~App()
+{
+  //If this was the last instance:
+  if(m_AppInstanceManager.get_app_count() == 0)
+  {
+    
+  }
+}
+
+void App::init_app_name(const Glib::ustring& appname) //static
+{
+  m_strAppName = appname;
+}
+
+void App::init()
+{
+  //set_wmclass(m_strAppName, m_strTitle); //The docs say "Don't use this".
+
+  //TODO: set_statusbar(m_Status);
+
+  init_ui_manager();
+  init_menus();
+  init_toolbars();
+
+  //on_document_load(); //Show the document (even if it is empty).
+}
+
+void App::init_ui_manager()
+{
+  
+}
+
+void App::init_menus()
+{
+  init_menus_file();
+  init_menus_edit();
+  init_menus_help();
+
+  //create_menus(m_menu_UI_Infos);
+  //install_menu_hints();
+
+  //Override this to add more menus.
+}
+
+void App::init_toolbars()
+{
+  
+}
+
+
+
+void App::on_menu_file_new()
+{
+  App* pApp = new_instance();
+  pApp->init(); 
+}
+
+void App::on_menu_file_close()
+{
+  ui_hide(); //AppInstanceManager will delete this when the hide signal is emitted..
+}
+
+void App::on_menu_file_exit()
+{
+  // we don't want to quit directly as we should save our work
+  // therefore we need to send close to each window.
+
+  //Close each instance:
+  m_AppInstanceManager.close_all();
+}
+
+void App::on_menu_edit_cut()
+{
+  on_menu_edit_copy();
+  on_menu_edit_clear();
+}
+
+
+void App::on_menu_edit_copy()
+{
+  
+}
+
+void App::on_menu_edit_paste()
+{
+  
+}
+
+void App::on_menu_edit_clear()
+{
+  
+}
+
+/*
+void App::on_menu_help_about()
+{
+  
+}
+*/
+
+void App::on_about_close()
+{
+  m_bAboutShown = false;
+}
+
+void App::set_about_information(const Glib::ustring& strVersion, const type_vecStrings& vecAuthors, const Glib::ustring& strCopyright, const Glib::ustring& strDescription)
+{
+  m_HelpInfo.m_strVersion = strVersion;
+  m_HelpInfo.m_vecAuthors = vecAuthors;
+  m_HelpInfo.m_strCopyright = strCopyright;
+  m_HelpInfo.m_strDescription = strDescription;
+}
+
+void App::set_about_information(const Glib::ustring& strVersion, const type_vecStrings& vecAuthors, const Glib::ustring& strCopyright, const Glib::ustring& strDescription, const type_vecStrings& vecDocumenters, const Glib::ustring& strTranslatorCredits)
+{
+  m_HelpInfo.m_strVersion = strVersion;
+  m_HelpInfo.m_vecAuthors = vecAuthors;
+  m_HelpInfo.m_strCopyright = strCopyright;
+  m_HelpInfo.m_strDescription = strDescription;
+  m_HelpInfo.m_vecDocumenters = vecDocumenters;
+  m_HelpInfo.m_strTranslatorCredits = strTranslatorCredits;
+}
+
+Glib::ustring App::get_version() const
+{
+  return m_HelpInfo.m_strVersion;
+}
+
+
+
+void App::set_operation_cancelled(bool bVal /* = true */)
+{
+  m_bOperationCancelled = bVal;
+}
+
+bool App::get_operation_cancelled()
+{
+  return m_bOperationCancelled;
+}
+
+void App::set_command_line_args(int argc, char **&argv)
+{
+  if( (argc > 0) && argv[0])
+    m_strCommandLine_0 = (char*)argv[0];
+}
+
+App::type_signal_hide App::ui_signal_hide()
+{
+  return m_signal_hide;
+}
+
+
+
+} //namespace

Added: trunk/glom/bakery/App.h
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/App.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_APP_H
+#define BAKERY_APP_H
+
+#include <glom/bakery/AppInstanceManager.h>
+#include <glibmm/object.h>
+
+#include <vector>
+#include <list>
+#include <map>
+
+namespace GlomBakery
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+class HelpInfo
+{
+public:
+  typedef std::vector<Glib::ustring> type_vecStrings;	
+  Glib::ustring m_strVersion, m_strCopyright, m_strDescription, m_strTranslatorCredits;
+
+  type_vecStrings m_vecAuthors, m_vecDocumenters;
+};
+#endif //DOXYGEN_SHOULD_SKIP_THIS
+
+/** Bakery's Main Window.
+ * This is an abstract class. You must use a class such as App_Gtk, which implements
+ * the ui_* methods for a particular GUI toolkit.
+ *
+ * Features:
+ * - Override methods to add/change menus/toolbars/statusbar.
+ *   - Default is basic File, Edit, Help menus and toolbar icons.
+ * - Configurable about box via set_about_information().
+ *
+ 
+ *
+ * TODO:
+ * - Command-line args - wrap popt?
+ * - Session Management - need Command-line args.
+ *
+ */
+
+class App : virtual public Glib::ObjectBase
+{
+public:
+  friend class AppInstanceManager;
+
+  //The constructor has a default argument so that there is a default constructor,
+  //so that derived classes do not need to call a specific constructor. This is
+  //a virtual base class so they would otherwise need to do that.
+
+  ///Don't forget to call init() too.
+  App(const Glib::ustring& appname = Glib::ustring()); 
+
+  virtual ~App();
+
+  virtual void init(); //Sets it up and shows it.
+
+  //'About Box' information:
+  typedef std::vector<Glib::ustring> type_vecStrings;	
+  static void set_about_information(const Glib::ustring& strVersion, const type_vecStrings& vecAuthors, const Glib::ustring& strCopyright, const Glib::ustring& strDescription);
+  static void set_about_information(const Glib::ustring& strVersion, const type_vecStrings& vecAuthors, const Glib::ustring& strCopyright, const Glib::ustring& strDescription, const type_vecStrings& vecDocumenters, const Glib::ustring& strTranslatorCredits);
+  virtual Glib::ustring get_version() const;
+
+  static void set_command_line_args(int argc, char** &argv); //Needed for session management.
+
+  typedef sigc::signal<void> type_signal_hide;
+  type_signal_hide ui_signal_hide();
+
+protected:
+  static void init_app_name(const Glib::ustring& appname);
+
+  /** Builds the intial ui string, with placeholders.
+   * This allows us to merge in actual menus and toolbars in the other init_*() methods.
+   */
+  virtual void init_ui_manager();
+
+  /** Override this to add more menus or different menus.
+   */
+  virtual void init_menus();
+
+  /** Call this from init_menus() to add the standard file menu
+   */
+  virtual void init_menus_file() = 0;
+
+  /** Call this from init_menus() to add the standard edit menu
+   */ 
+  virtual void init_menus_edit() = 0;
+
+  /** Call this from init_menus() to add the standard help menu
+   */
+  virtual void init_menus_help() = 0;
+
+  virtual void init_toolbars();
+  
+  virtual App* new_instance() = 0; //Must override in order to new() the derived document class.
+
+//  virtual void close_window() = 0;
+//  virtual void bring_to_front() = 0;
+  //Signal handlers:
+
+public: // We can not take function pointers of these methods in a 
+        // derived class, if they are protected - for instance, with sigc::mem_fun() 
+  //Menus:
+  virtual void on_menu_file_new();
+  virtual void on_menu_file_close();
+  virtual void on_menu_file_exit();
+
+  //Edit menu handlers overriden in App_WithDoc:
+  virtual void on_menu_edit_cut();
+  virtual void on_menu_edit_copy();
+  virtual void on_menu_edit_paste();
+  virtual void on_menu_edit_clear();
+
+  virtual void on_menu_help_about() = 0;
+
+
+  virtual void on_about_close();
+
+protected:
+  //GUI abstractions:
+  virtual void ui_hide() = 0;
+  virtual void ui_bring_to_front() = 0;
+
+  //operation_cancelled:
+  //e.g. A File|Open tries to save existing data,
+  //but this needs to be cancelled if the save failed. 
+  static void set_operation_cancelled(bool bVal = true);
+  static bool get_operation_cancelled();
+
+  //Member data:
+  
+  //'About Box'/WM Class information:
+  static Glib::ustring m_strAppName;
+
+  //'About Box' information:
+  static HelpInfo m_HelpInfo;
+
+  //Instances
+  static AppInstanceManager m_AppInstanceManager;
+
+  static bool m_bOperationCancelled; //see set/get_operation_cancelled().
+
+  //All instances share 1 About box:
+  static bool m_bAboutShown;
+
+  //Command line args:
+  static Glib::ustring m_strCommandLine_0;
+
+  type_signal_hide m_signal_hide;
+
+
+  
+  //typedef std::vector<poptOption> type_vecPoptOptions;
+  //type_vecPoptOptions m_vecPoptOptions;
+};
+
+} //namespace
+
+#endif //BAKERY_APP_H

Added: trunk/glom/bakery/AppInstanceManager.cc
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/AppInstanceManager.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glom/bakery/AppInstanceManager.h>
+#include <glom/bakery/App.h>
+#include <gtkmm/main.h>
+
+namespace GlomBakery
+{
+
+AppInstanceManager::AppInstanceManager()
+{
+  m_bExiting = false;
+}
+
+AppInstanceManager::~AppInstanceManager()
+{
+}
+
+void AppInstanceManager::on_app_hide(App* pApp)
+{
+  //If pApp is one of the remembered instances (it always should be):
+  type_listAppInstances::iterator iterFind = std::find(m_listAppInstances.begin(), m_listAppInstances.end(), pApp);
+  if(iterFind != m_listAppInstances.end())
+  {
+    m_listAppInstances.erase(iterFind);
+    delete pApp;
+    pApp = 0;
+  }
+
+  //When the last instance goes, the application closes.
+  if(m_listAppInstances.empty())
+  {
+    Gtk::Main::quit();
+  }
+}
+
+void AppInstanceManager::add_app(App* pApp)
+{
+  m_listAppInstances.push_back(pApp);
+
+  //Allow the AppInstanceManager to respond when the Application is hidden (hidden == closed):
+  pApp->ui_signal_hide().connect( sigc::bind<App*>(sigc::mem_fun(*this, &AppInstanceManager::on_app_hide), pApp) );
+}
+
+void AppInstanceManager::close_all()
+{
+  m_bExiting = true; //One of the instances could cancel this loop.
+
+  type_listAppInstances::iterator i = m_listAppInstances.begin();
+  while (m_bExiting && (i != m_listAppInstances.end()))
+  {
+    type_listAppInstances::iterator j = i;
+    i++;
+
+    App* pApp = (*j);
+    if(pApp)
+    {
+      type_listAppInstances::size_type count = m_listAppInstances.size();
+      pApp->on_menu_file_close();
+
+      //The iterator is invalid if an element has been removed:
+      if(count != m_listAppInstances.size())
+      {
+        i = m_listAppInstances.begin(); //There should not be a problem with asking again.
+      }
+    }
+  }
+}
+
+void AppInstanceManager::cancel_close_all()
+{
+  m_bExiting = false;
+}
+
+unsigned int AppInstanceManager::get_app_count() const
+{
+  return m_listAppInstances.size();
+}
+
+AppInstanceManager::type_listAppInstances AppInstanceManager::get_instances() const
+{
+  return m_listAppInstances;
+}
+
+
+
+} //namespace

Added: trunk/glom/bakery/AppInstanceManager.h
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/AppInstanceManager.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2002 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_APPINSTANCEMANAGER_H
+#define BAKERY_APPINSTANCEMANAGER_H
+
+#include <sigc++/sigc++.h>
+#include <list>
+
+namespace GlomBakery
+{
+
+class App;
+
+/** Contains a list of App instances.
+ * Each App registers itself with the one AppInstanceManager,
+ * and the AppInstanceManager will then delete the App when
+ * it has been closed, by catching the "hide" signal.
+ * You should not need to use this class directly.
+ */
+class AppInstanceManager : public sigc::trackable
+{
+public:
+  AppInstanceManager();
+  virtual ~AppInstanceManager();
+
+  virtual void add_app(App* pApp);
+  virtual void close_all();
+  virtual void cancel_close_all();
+
+  virtual unsigned int get_app_count() const;
+
+  typedef std::list<App*> type_listAppInstances;
+  virtual type_listAppInstances get_instances() const; //Used by App_WithDoc to get associated Documents.
+
+protected:
+  //Signal handler:
+  virtual void on_app_hide(App* pApp);
+
+  //Instances:
+  type_listAppInstances m_listAppInstances;
+
+  bool m_bExiting;
+};
+
+} //namespace
+
+#endif //BAKERY_APPINSTANCEMANAGER_H

Added: trunk/glom/bakery/App_Gtk.cc
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/App_Gtk.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,416 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+
+#include <glom/bakery/App_Gtk.h>
+#include <gtkmm/stock.h>
+#include <gtkmm/aboutdialog.h>
+#include <gtkmm/messagedialog.h>
+#include <gtkmm/toolbutton.h>
+#include <glibmm/i18n-lib.h>
+#include <algorithm>
+#include <iostream>
+
+namespace GlomBakery
+{
+
+//Initialize static member data:
+
+
+Gtk::Window* App_Gtk::m_pAbout = 0;
+
+App_Gtk::App_Gtk(const Glib::ustring& appname)
+: m_pVBox(0)
+{
+  init_app_name(appname);
+
+#ifndef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED
+  signal_hide().connect(sigc::mem_fun(*this, &App_Gtk::on_hide));
+  signal_delete_event().connect(sigc::mem_fun(*this, &App_Gtk::on_delete_event));
+#endif
+}
+
+/// This constructor can be used with Gnome::Glade::Xml::get_derived_widget().
+App_Gtk::App_Gtk(BaseObjectType* cobject, const Glib::ustring& appname)
+: ParentWindow(cobject),
+  m_pVBox(0)
+{
+  init_app_name(appname);  
+
+#ifndef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED
+  signal_hide().connect(sigc::mem_fun(*this, &App_Gtk::on_hide));
+  signal_delete_event().connect(sigc::mem_fun(*this, &App_Gtk::on_delete_event));
+#endif
+}
+  
+
+App_Gtk::~App_Gtk()
+{
+  if(m_pVBox)
+  {
+    delete m_pVBox;
+    m_pVBox = 0;
+  }
+  
+  //If this was the last instance:
+  if(m_AppInstanceManager.get_app_count() == 0)
+  {
+    //Delete shared static widgets if this was the last instance:
+    if(m_pAbout)
+    {
+      delete m_pAbout;
+      m_pAbout = 0;
+    }
+  }
+}
+
+void App_Gtk::on_hide()
+{
+  ui_signal_hide().emit();
+}
+
+void App_Gtk::ui_hide()
+{
+  hide();  
+}
+
+void App_Gtk::ui_bring_to_front()
+{
+  get_window()->raise();
+}
+  
+void App_Gtk::init_layout()
+{
+  set_resizable(); //resizable
+  set_default_size(640, 400); //A sensible default.
+
+  //This might have been instantiated by Gnome::Glade::Xml::get_widget() instead.
+  //If not, then we create a default one and add it to the window.
+  if(!m_pVBox)
+  {
+    m_pVBox = new Gtk::VBox();
+    Gtk::Window::add(*m_pVBox);
+  }
+
+  //Add menu bar at the top:
+  //These were defined in init_uimanager().
+#ifdef BAKERY_MAEMO_ENABLED
+  Gtk::Menu* pMenu = static_cast<Gtk::Menu*>(m_refUIManager->get_widget("/Bakery_MainMenu"));
+  set_menu(*pMenu);
+#else
+  Gtk::MenuBar* pMenuBar = static_cast<Gtk::MenuBar*>(m_refUIManager->get_widget("/Bakery_MainMenu"));
+  m_pVBox->pack_start(*pMenuBar, Gtk::PACK_SHRINK);
+#endif
+
+  Gtk::Toolbar* pToolBar = static_cast<Gtk::Toolbar*>(m_refUIManager->get_widget("/Bakery_ToolBar"));
+  if(pToolBar)
+  {
+#ifdef BAKERY_MAEMO_ENABLED
+    add_toolbar(*pToolBar);
+#else
+    m_HandleBox_Toolbar.add(*pToolBar);
+    m_HandleBox_Toolbar.show();
+    m_pVBox->pack_start(m_HandleBox_Toolbar, Gtk::PACK_SHRINK);
+#endif
+  }
+
+  add_accel_group(m_refUIManager->get_accel_group());
+
+
+  //Add placeholder, to be used by add():
+  m_pVBox->pack_start(m_VBox_PlaceHolder);
+  m_VBox_PlaceHolder.show();
+  
+  m_pVBox->show(); //Show it last so the child widgets all show at once.
+}
+
+void App_Gtk::add_ui_from_string(const Glib::ustring& ui_description)
+{
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  try
+  {
+    m_refUIManager->add_ui_from_string(ui_description);
+  }
+  catch(const Glib::Error& ex)
+  {
+    std::cerr << "building menus failed: " <<  ex.what();
+  }
+#else
+  std::auto_ptr<Glib::Error> error;
+  m_refUIManager->add_ui_from_string(ui_description, error);
+  if(error.get() != NULL) std::cerr << "building menus failed: " << error->what();
+#endif
+}
+
+void App_Gtk::init()
+{
+  App::init();
+  init_layout(); // start setting up layout after we've gotten all widgets from UIManager
+  show();
+}
+
+void App_Gtk::init_ui_manager()
+{
+  using namespace Gtk;
+
+  m_refUIManager = UIManager::create();
+
+  //This is just a skeleton structure.
+  //The placeholders allow us to merge the menus and toolbars in later,
+  //by adding a us string with one of the placeholders, but with menu items underneath it.
+  static const Glib::ustring ui_description =
+    "<ui>"
+#ifdef BAKERY_MAEMO_ENABLED
+    "  <popup name='Bakery_MainMenu'>"
+#else
+    "  <menubar name='Bakery_MainMenu'>"
+#endif
+    "    <placeholder name='Bakery_MenuPH_File' />"
+    "    <placeholder name='Bakery_MenuPH_Edit' />"
+    "    <placeholder name='Bakery_MenuPH_Others' />" //Note that extra menus should be inserted before the Help menu, which should always be at the end.
+    "    <placeholder name='Bakery_MenuPH_Help' />"
+#ifdef BAKERY_MAEMO_ENABLED
+    "  </popup>"
+#else
+    "  </menubar>"
+#endif
+    "  <toolbar name='Bakery_ToolBar'>"
+    "    <placeholder name='Bakery_ToolBarItemsPH' />"
+    "  </toolbar>"
+    "</ui>";
+  
+  add_ui_from_string(ui_description);
+}
+
+void App_Gtk::init_menus()
+{
+  //Override this to add more menus
+  init_menus_file();
+  init_menus_edit();
+  init_menus_help();
+
+}
+
+void App_Gtk::add(Gtk::Widget& child)
+{
+  m_VBox_PlaceHolder.pack_start(child);
+}
+
+
+void App_Gtk::init_toolbars()
+{
+  //Build part of the toolbar structure, to be merged in by using the "PH" placeholders:
+  static const Glib::ustring ui_description =
+    "<ui>"
+    "  <toolbar name='Bakery_ToolBar'>"
+    "    <placeholder name='Bakery_ToolBarItemsPH'>"
+    "      <toolitem action='BakeryAction_File_New' />"
+    "    </placeholder>"
+    "  </toolbar>"
+    "</ui>";
+
+  add_ui_from_string(ui_description);
+}
+
+
+bool App_Gtk::on_delete_event(GdkEventAny* /* event */)
+{
+  //Clicking on the [x] in the title bar should be like choosing File|New
+  on_menu_file_close();
+
+  return true; // true = don't hide, don't destroy
+}
+
+void App_Gtk::init_menus_file()
+{
+  using namespace Gtk;
+  // File menu
+
+  //Build actions:
+  m_refFileActionGroup = ActionGroup::create("BakeryFileActions");
+  m_refFileActionGroup->add(Action::create("BakeryAction_Menu_File", _("File")));
+
+  m_refFileActionGroup->add(Action::create("BakeryAction_File_New", Gtk::Stock::NEW),
+                        sigc::mem_fun((GlomBakery::App&)*this, &App_Gtk::on_menu_file_new));
+  m_refFileActionGroup->add(Action::create("BakeryAction_File_Close", Gtk::Stock::CLOSE),
+                        sigc::mem_fun((GlomBakery::App&)*this, &App_Gtk::on_menu_file_close));
+  m_refFileActionGroup->add(Action::create("BakeryAction_File_Exit", Gtk::Stock::QUIT),
+                        sigc::mem_fun((GlomBakery::App&)*this, &App_Gtk::on_menu_file_exit));
+  m_refUIManager->insert_action_group(m_refFileActionGroup);
+
+  //Build part of the menu structure, to be merged in by using the "PH" placeholders:
+  static const Glib::ustring ui_description =
+    "<ui>"
+#ifdef BAKERY_MAEMO_ENABLED
+    "  <popup name='Bakery_MainMenu'>"
+#else
+    "  <menubar name='Bakery_MainMenu'>"
+#endif
+    "    <placeholder name='Bakery_MenuPH_File'>" //this has to have the same name as the placeholder above
+    "      <menu action='BakeryAction_Menu_File'>" 
+    "        <menuitem action='BakeryAction_File_New' />"
+    "        <menuitem action='BakeryAction_File_Close' />"
+    "        <menuitem action='BakeryAction_File_Exit' />"
+    "      </menu>"
+    "    </placeholder>"
+#ifdef BAKERY_MAEMO_ENABLED
+    "  </popup>"
+#else
+    "  </menubar>"
+#endif
+    "</ui>";
+  
+  //Add menu:
+  add_ui_from_string(ui_description);
+}
+
+void App_Gtk::init_menus_edit()
+{
+  using namespace Gtk;
+  //Edit menu
+  
+  //Build actions:
+  m_refEditActionGroup = ActionGroup::create("BakeryEditActions");
+  m_refEditActionGroup->add(Action::create("BakeryAction_Menu_Edit", _("_Edit")));
+  
+  m_refEditActionGroup->add(Action::create("BakeryAction_Edit_Cut", Gtk::Stock::CUT));
+  m_refEditActionGroup->add(Action::create("BakeryAction_Edit_Copy", Gtk::Stock::COPY));
+  m_refEditActionGroup->add(Action::create("BakeryAction_Edit_Paste", Gtk::Stock::PASTE));
+  m_refEditActionGroup->add(Action::create("BakeryAction_Edit_Clear", Gtk::Stock::CLEAR));
+
+  m_refUIManager->insert_action_group(m_refEditActionGroup);
+  
+  //Build part of the menu structure, to be merged in by using the "PH" placeholders:
+  static const Glib::ustring ui_description =
+    "<ui>"
+#ifdef BAKERY_MAEMO_ENABLED
+    "  <popup name='Bakery_MainMenu'>"
+#else
+    "  <menubar name='Bakery_MainMenu'>"
+#endif
+    "    <placeholder name='Bakery_MenuPH_Edit'>"
+    "      <menu action='BakeryAction_Menu_Edit'>"
+    "        <menuitem action='BakeryAction_Edit_Cut' />"
+    "        <menuitem action='BakeryAction_Edit_Copy' />"
+    "        <menuitem action='BakeryAction_Edit_Paste' />"
+    "        <menuitem action='BakeryAction_Edit_Clear' />"
+    "      </menu>"
+    "    </placeholder>"
+#ifdef BAKERY_MAEMO_ENABLED
+    "  </popup>"
+#else
+    "  </menubar>"
+#endif
+    "</ui>";
+
+  //Add menu:
+  add_ui_from_string(ui_description);
+}
+
+void App_Gtk::init_menus_help()
+{
+  using namespace Gtk;
+  //Help menu
+
+  //Build actions:
+  m_refHelpActionGroup = ActionGroup::create("BakeryHelpActions");
+  m_refHelpActionGroup->add(Action::create("BakeryAction_Menu_Help", _("_Help")));
+
+  //TODO: Use stock?
+  m_refHelpActionGroup->add(Action::create("BakeryAction_Help_About",
+                        _("_About"), _("About the application")),
+                        sigc::mem_fun((GlomBakery::App&)*this, &App::on_menu_help_about));
+
+  m_refUIManager->insert_action_group(m_refHelpActionGroup);
+
+  //Build part of the menu structure, to be merged in by using the "PH" plaeholders:
+  static const Glib::ustring ui_description =
+    "<ui>"
+#ifdef BAKERY_MAEMO_ENABLED
+    "  <popup name='Bakery_MainMenu'>"
+#else
+    "  <menubar name='Bakery_MainMenu'>"
+#endif
+    "    <placeholder name='Bakery_MenuPH_Help'>"
+    "      <menu action='BakeryAction_Menu_Help'>"
+    "        <menuitem action='BakeryAction_Help_About' />"
+    "      </menu>"
+    "    </placeholder>"
+#ifdef BAKERY_MAEMO_ENABLED
+    "  </popup>"
+#else
+    "  </menubar>"
+#endif
+    "</ui>";
+
+  //Add menu:
+  add_ui_from_string(ui_description);
+}
+
+
+void App_Gtk::on_menu_help_about()
+{
+  if(m_pAbout && m_bAboutShown) // "About" box hasn't been closed, so just raise it
+  {
+    m_pAbout->set_transient_for(*this);
+
+    Glib::RefPtr<Gdk::Window> about_win = m_pAbout->get_window();
+    about_win->show();
+    about_win->raise();
+  }
+  else
+  {
+    //Re-create About box:
+    if(m_pAbout)
+    {
+      delete m_pAbout;
+      m_pAbout = 0;
+    }
+
+    Gtk::AboutDialog* pDerived = new Gtk::AboutDialog;
+    m_pAbout = pDerived;
+
+    pDerived->set_name(m_strAppName);
+    pDerived->set_version(m_HelpInfo.m_strVersion);
+    pDerived->set_copyright(m_HelpInfo.m_strCopyright);
+    pDerived->set_authors(m_HelpInfo.m_vecAuthors);
+    pDerived->set_documenters(m_HelpInfo.m_vecDocumenters);
+    pDerived->set_translator_credits(m_HelpInfo.m_strTranslatorCredits);
+
+    m_pAbout->signal_hide().connect(sigc::mem_fun((App&)*this, &App::on_about_close));
+    m_bAboutShown = true;
+    static_cast<Gtk::Dialog*>(m_pAbout)->run(); //show() would be better. see below:
+    m_pAbout->hide();
+    //m_pAbout->show(); //TODO: respond to the OK button.
+  }
+}
+
+void App_Gtk::on_about_close()
+{
+  m_bAboutShown = false;
+}
+
+Glib::ustring App_Gtk::util_bold_message(const Glib::ustring& message)
+{
+  return "<b>" + message + "</b>";
+}
+
+
+
+} //namespace

Added: trunk/glom/bakery/App_Gtk.h
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/App_Gtk.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_APP_GTK_H
+#define BAKERY_APP_GTK_H
+
+#include <config.h> // For BAKERY_MAEMO_ENABLED
+#include <glom/bakery/App.h>
+
+#ifdef BAKERY_MAEMO_ENABLED
+#include <hildonmm/window.h>
+#endif
+
+#include <gtkmm/menubar.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/toolbar.h>
+#include <gtkmm/handlebox.h>
+#include <gtkmm/dialog.h>
+#include <gtkmm/uimanager.h>
+#include <libglademm.h>
+
+namespace GlomBakery
+{
+
+/** This class implements GlomBakery::App using gtkmm.
+ *
+ * Features:
+ * - Override methods to add/change menus/toolbars/statusbar.
+ *   - Default is basic File, Edit, Help menus and toolbar icons.
+ */
+class App_Gtk
+  : virtual public App, //virtual because App_WithDoc_Gtk will inherit it via App_Gtk and via App_With_Doc
+#ifdef BAKERY_MAEMO_ENABLED
+    virtual public Hildon::Window //inherit virtually to share sigc::trackable.
+#else
+    virtual public Gtk::Window //inherit virtually to share sigc::trackable.
+#endif
+{
+public:
+#ifdef BAKERY_MAEMO_ENABLED
+  typedef Hildon::Window ParentWindow;
+#else
+  typedef Gtk::Window ParentWindow;
+#endif
+  friend class AppInstanceManager;
+
+  ///Don't forget to call init() too.
+  App_Gtk(const Glib::ustring& appname);
+
+  /// This constructor can be used to implement derived classes for use with Gnome::Glade::Xml::get_derived_widget().
+  App_Gtk(BaseObjectType* cobject, const Glib::ustring& appname);
+
+  virtual ~App_Gtk();
+
+  /// Overidden to add a widget in the middle, under the menu, instead of replacing the whole contents.
+  virtual void add(Gtk::Widget& child);
+
+  /// For instance, to create bold primary text for a dialog box, without marking the markup for translation.
+  static Glib::ustring util_bold_message(const Glib::ustring& message);
+
+protected:
+
+  virtual void init(); //Override to show().
+  virtual void init_ui_manager(); //Override this to add more UI placeholders
+  virtual void init_menus(); //Override this to add more or different menus.
+  virtual void init_menus_file(); //Call this from init_menus() to add the standard file menu.
+  virtual void init_menus_edit(); //Call this from init_menus() to add the standard edit menu
+  virtual void init_menus_help(); //Call this from init_menus() to add the standard help menu.	
+  virtual void init_toolbars();
+
+  virtual void init_layout(); //Arranges the menu, toolbar, etc.
+
+  virtual void add_ui_from_string(const Glib::ustring& ui_description); //Convenience function
+
+  virtual void on_hide(); //override.
+
+  //Signal handlers:
+
+  //Menus:
+  virtual void on_menu_help_about();
+
+  virtual void on_about_close();
+
+
+  virtual void ui_hide();
+  virtual void ui_bring_to_front();
+
+  virtual bool on_delete_event(GdkEventAny* event); //override
+
+  //virtual void destroy_and_remove_from_list();
+
+  //Member data:
+
+  //UIManager and Actions
+  Glib::RefPtr<Gtk::UIManager> m_refUIManager;
+  Glib::RefPtr<Gtk::ActionGroup> m_refFileActionGroup;
+  Glib::RefPtr<Gtk::ActionGroup> m_refEditActionGroup;
+  Glib::RefPtr<Gtk::ActionGroup> m_refHelpActionGroup;
+
+  //Member widgets:
+  Gtk::VBox* m_pVBox;
+  Gtk::VBox m_VBox_PlaceHolder;
+
+  //Gtk::MenuBar m_MenuBar;
+  //Gtk::Menu m_Menu_File, m_Menu_Edit, m_Menu_Help;
+
+  Gtk::HandleBox m_HandleBox_Toolbar;
+  //Gtk::Toolbar m_Toolbar;
+
+  //All instances share 1 About box:
+  static Gtk::Window* m_pAbout; //About box.
+
+
+  //typedef std::vector<poptOption> type_vecPoptOptions;
+  //type_vecPoptOptions m_vecPoptOptions;
+};
+
+} //namespace
+
+#endif //BAKERY_APP_GTK_H

Added: trunk/glom/bakery/App_WithDoc.cc
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/App_WithDoc.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,539 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+#include <glom/bakery/App_WithDoc.h>
+#include <glom/bakery/Dialog_OfferSave.h>
+#include <gconfmm.h>
+#include <giomm.h>
+#include <algorithm>
+#include <glibmm/i18n-lib.h>
+
+//#include <gtk/gtkfilesel.h>
+
+#define BAKERY_GCONF_DIRECTORY_RECENTFILES "recent_files"
+
+namespace GlomBakery
+{
+
+App_WithDoc::type_list_strings App_WithDoc::m_mime_types;
+
+App_WithDoc::App_WithDoc(const Glib::ustring& appname)
+: App(appname),
+  m_pDocument(0),
+  m_bCloseAfterSave(false)
+{  
+}
+
+App_WithDoc::~App_WithDoc()
+{
+  //Delete the document:
+  if(m_pDocument)
+  {
+    delete m_pDocument; //This will cause Document::signal_forget to be emitted, so the Views will then null their pointers as well. A smartpointer might be a better way to do this.
+    m_pDocument = 0;
+  }
+}
+
+//static
+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);
+}
+
+void App_WithDoc::on_menu_file_close()
+{
+  if(m_pDocument->get_modified())
+  {
+    //Offer to save changes:
+    m_bCloseAfterSave = true; //Checked in FileChooser signal handler.
+    offer_to_save_changes(); //If a File|Exit is in progress, this could cancel it.
+  }
+
+  if(!get_operation_cancelled())
+    ui_hide(); //The AppInstanceManager will delete it.
+}
+
+bool App_WithDoc::open_document_from_data(const guchar* data, std::size_t length)
+{
+  const bool bTest = m_pDocument->load_from_data(data, length);
+
+  bool bOpenFailed = false;
+  if(!bTest) //if open failed.
+    bOpenFailed = true;
+  else
+  {
+    //if open succeeded then let the App respond:
+    const bool test = on_document_load();
+    if(!test)
+      bOpenFailed = true; //The application didn't like something about the just-loaded document.
+    else
+    {
+      update_window_title();
+      set_document_modified(false); //disables menu and toolbar Save items.
+
+      return true; //success.
+    }
+  }
+
+  if(bOpenFailed)
+  {
+    ui_warning(_("Open failed."), _("The document could not be opened."));
+
+    return false; //failed.
+  }
+  else
+    return true;
+}
+
+bool App_WithDoc::open_document(const Glib::ustring& file_uri)
+{
+  //Check whether it's already open:
+  //It could even be open in this instance.
+  bool bAlreadyOpen = false;
+  App_WithDoc* pAppAlreadyOpen = 0;
+
+  AppInstanceManager::type_listAppInstances apps =  m_AppInstanceManager.get_instances();
+  for(AppInstanceManager::type_listAppInstances::iterator iter = apps.begin(); iter != apps.end(); iter++)
+  {
+    App_WithDoc* pApp = dynamic_cast<App_WithDoc*>(*iter);
+    if(pApp)
+    {
+      Document* pDoc = pApp->get_document();
+      if(pDoc->get_file_uri() == file_uri)
+      {
+        bAlreadyOpen = true;
+        pAppAlreadyOpen = pApp;
+      }
+    }
+  }
+
+  if(bAlreadyOpen)
+  {
+    //Bring it to the front:
+    if(pAppAlreadyOpen)
+    {
+      pAppAlreadyOpen->ui_bring_to_front();
+    }
+
+    //Tell user that it's already open:
+    ui_warning(_("Document already open"), _("This document is already open."));
+
+    return true; //success.
+  }
+  else
+  {
+    //Open it:
+        
+    //Load it into a new instance unless the current document is just a default new.
+    App_WithDoc* pApp = 0;
+    bool bUsingNewInstance = false;
+    if(!(get_document()->get_is_new())) //if it's not new.
+    {
+      //New instance:
+      pApp = dynamic_cast<App_WithDoc*>(new_instance());
+      pApp->init(); //It's shown too.
+      bUsingNewInstance = true;
+    }
+    else
+    {
+      pApp = this; //Replace the default new document in this instance.
+    }
+
+    //Open it.
+    pApp->m_pDocument->set_file_uri(file_uri);
+    bool bTest = pApp->m_pDocument->load();
+
+    bool bOpenFailed = false;
+    if(!bTest) //if open failed.
+      bOpenFailed = true;
+    else
+    {
+      //if open succeeded then let the App respond:
+      bool test = pApp->on_document_load();
+      if(!test)
+        bOpenFailed = true; //The application didn't like something about the just-loaded document.
+      else
+      {
+        pApp->update_window_title();
+        set_document_modified(false); //disables menu and toolbar Save items.
+
+        //Update document history list:
+        //(Getting the file URI again, in case it has changed while being opened, 
+        //for instance if it was a template file that was saved as a real file.)
+        if(pApp->m_pDocument)
+          document_history_add(pApp->m_pDocument->get_file_uri());
+
+        return true; //success.
+      }
+    }
+
+    if(bOpenFailed)
+    {
+      ui_warning(_("Open failed."), _("The document could not be opened."));
+
+      if(bUsingNewInstance)
+      {
+        //Remove new instance:
+        pApp->get_document()->set_modified(false); //avoid 'do you want to save?' dialog.
+        pApp->on_menu_file_close();
+      }
+      else
+      {
+        //re-initialize document.
+        delete pApp->m_pDocument;
+        pApp->m_pDocument = 0;
+        pApp->init_create_document();
+      }
+
+      return false; //failed.
+    }
+      
+  } //if already open.
+
+  return false; //failed.
+}
+
+void App_WithDoc::on_menu_file_open()
+{
+  //Display File Open dialog and respond to choice:
+
+  //Bring document window to front, to make it clear which document is being changed:
+  ui_bring_to_front();
+
+  //Ask user to choose file to open:
+  Glib::ustring file_uri = ui_file_select_open();
+  if(!file_uri.empty())
+    open_document(file_uri);
+}
+
+//This is for calling directly, use the other override for the signal handler:
+void App_WithDoc::offer_saveas()
+{
+  on_menu_file_saveas();
+}
+
+bool App_WithDoc::file_exists(const Glib::ustring& uri)
+{
+  //Check whether file exists already:
+  {
+    // Try to examine the input file.
+    Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(uri);
+
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+    try
+    {
+      return file->query_exists();
+    }
+    catch(const Gio::Error& /* ex */)
+    {
+      return false; //Something went wrong. It does not exist.
+    }
+#else
+      std::auto_ptr<Gio::Error> error;
+      retrun file->query_exists(error);
+#endif
+  }
+}
+
+void App_WithDoc::on_menu_file_saveas()
+{
+  //Display File Save dialog and respond to choice:
+
+  //Bring document window to front, to make it clear which document is being saved:
+  //This doesn't work: TODO.
+  ui_bring_to_front();
+
+  //Show the save dialog:  
+  const Glib::ustring& file_uriOld = m_pDocument->get_file_uri();
+
+  Glib::ustring file_uri = ui_file_select_save(file_uriOld); //Also asks for overwrite confirmation.
+  if(!file_uri.empty())
+  {
+    //Enforce the file extension:
+    file_uri = m_pDocument->get_file_uri_with_extension(file_uri);
+
+    bool bUseThisFileUri = true;
+
+    //Save to this filepath:
+    if(bUseThisFileUri)
+    {
+      m_pDocument->set_file_uri(file_uri, true); //true = enforce file extension
+      const bool bTest = m_pDocument->save();
+
+      if(!bTest)
+      {
+        ui_warning(_("Save failed."), _("There was an error while saving the file. Your changes have not been saved."));
+      }
+      else
+      {
+        //Disable Save and SaveAs menu items:
+        after_successful_save();
+      }
+
+      update_window_title();
+
+
+      //Close if this save was a result of a File|Close or File|Exit:.
+      //if(bTest && m_bCloseAfterSave) //Don't close if the save failed.
+      //{
+      //  on_menu_file_close(); //This could be the second time, but now there are no unsaved changes.
+      //}
+    }
+    else
+    {
+      //Let the user choose a different file path,
+      //because he decided not to overwrite the 1st one.
+      offer_saveas(); //recursive.
+    }
+  }
+  else
+  {
+    cancel_close_or_exit();
+  }
+}
+
+void App_WithDoc::on_menu_file_save()
+{
+  if(m_pDocument)
+  {
+    //If there is already a filepath, then save to that location:
+    if(!(m_pDocument->get_file_uri().empty()))
+    {
+      bool bTest = m_pDocument->save();
+
+      if(bTest)
+      {
+        //Disable Save and SaveAs menu items:
+        after_successful_save();
+
+        //Close the document if this save was in response to a 'Do you want to save before closing?':
+        //if(m_bCloseAfterSave) // || m_bExiting
+        //  close_mark_or_destroy();
+      }
+      else
+      {
+        //The save failed. Tell the user and don't do anything else:
+        ui_warning(_("Save failed."), _("There was an error while saving the file. Your changes have not been saved."));
+
+        cancel_close_or_exit();
+      }
+    }
+    else
+    {
+      //If there is no filepath, then ask for one and save to that location:
+      offer_saveas();
+    }
+  }
+
+  if(!m_bCloseAfterSave) //Don't try to do anything after closing - this instance would not exist anymore.
+  {
+    update_window_title();
+  }
+
+}
+
+void App_WithDoc::init()
+{  
+  init_create_document();
+
+  //Call base method:
+  App::init();
+
+  on_document_load(); //Show default empty document in the View.
+
+  set_document_modified(false); //Disable Save menu item.
+}
+
+void App_WithDoc::init_create_document()
+{
+  //Overrides should call this base method at the end.
+
+  if(!m_pDocument)
+  {
+    m_pDocument = new Document();
+  }
+
+  m_pDocument->set_is_new(true); //Can't be modified if it's just been created.
+  
+  m_pDocument->signal_modified().connect(sigc::mem_fun(*this, &App_WithDoc::on_document_modified));
+
+  update_window_title();
+}
+
+Document* App_WithDoc::get_document()
+{
+  return m_pDocument;
+}
+
+const Document* App_WithDoc::get_document() const
+{
+  return m_pDocument;
+}
+
+void App_WithDoc::offer_to_save_changes()
+{
+  if(m_pDocument)
+  {
+    if(m_pDocument->get_modified())
+    {
+      set_operation_cancelled(false); //Initialize it again. It might be set later in this method by cancel_close_or_exit().
+      
+      //The document has unsaved changes,
+      //so ask the user whether the document should be saved:
+      enumSaveChanges buttonClicked = ui_offer_to_save_changes();
+
+      //Respond to button that was clicked:
+      switch(buttonClicked)
+      {
+        case(SAVECHANGES_Save):
+        {
+          on_menu_file_save(); //If File|Exit is in progress, this could cancel it.
+          break;
+        }
+        
+        case(SAVECHANGES_Discard):
+        {
+          //Close if this save offer was a result of a FileClose (It probably always is):
+          //close_mark_or_destroy();
+          //Do nothing - the caller will probably hide() the window to have it deleted.
+          break;
+        }
+        
+        case(SAVECHANGES_Cancel): //Cancel.
+        {
+          cancel_close_or_exit();
+          break;
+        }
+        
+        default:
+        {
+          break;
+        }
+      }   
+    }
+  }
+}
+
+void App_WithDoc::close_mark_or_destroy()
+{
+  ui_hide();
+}
+
+void App_WithDoc::cancel_close_or_exit()
+{
+  set_operation_cancelled();
+  m_bCloseAfterSave = false;
+  m_AppInstanceManager.cancel_close_all();
+
+  //exit_destroy_marked_instances(); //Clean up after an exit.
+}
+
+bool App_WithDoc::on_document_load()
+{
+  //Show document contents:
+  if(m_pDocument)
+  {
+    GlomBakery::ViewBase* pView = m_pDocument->get_view();
+    if(pView)
+      pView->load_from_document();
+
+    //Set document as unmodified (this could have been wrongly set during the load):
+    set_document_modified(false);
+
+    return true;
+  }
+  else
+    return false; //I can't think of any reason why this would happen.
+  
+  //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::update_window_title()
+{
+
+}
+
+void App_WithDoc::on_document_modified(bool modified)
+{
+  //Change the displayed 'modified' status.
+  //This method could be overridden to e.g. enable a Save icon or enable the Save menu item.
+  //TODO: enable/disable the Save menu item.
+
+  ui_show_modification_status();
+
+  //Change title bar:
+  update_window_title();
+}
+
+void App_WithDoc::set_document_modified(bool bModified /* = true */)
+{
+  m_pDocument->set_modified(bModified);
+
+  //Enable/Disable Save menu item and toolbar item:
+  ui_show_modification_status();
+}
+
+void App_WithDoc::on_menu_edit_copy()
+{
+  GlomBakery::ViewBase* pView = m_pDocument->get_view();
+  if(pView)
+    pView->clipboard_copy();
+}
+
+void App_WithDoc::on_menu_edit_paste()
+{
+  GlomBakery::ViewBase* pView = m_pDocument->get_view();
+  if(pView)
+    pView->clipboard_paste();
+}
+
+void App_WithDoc::on_menu_edit_clear()
+{
+  GlomBakery::ViewBase* pView = m_pDocument->get_view();
+  if(pView)
+    pView->clipboard_clear();
+}
+
+void App_WithDoc::after_successful_save()
+{
+  set_document_modified(false); //enables/disables menu and toolbar widgets.
+    
+  //Update document history list:
+  document_history_add(m_pDocument->get_file_uri());     
+}
+
+Glib::ustring App_WithDoc::get_conf_fullkey(const Glib::ustring& key)
+{
+  return "/apps/" + m_strAppName + "/" + key;
+}
+
+
+void App_WithDoc::document_history_add(const Glib::ustring& file_uri)
+{
+  //Override this.
+}
+
+void App_WithDoc::document_history_remove(const Glib::ustring& file_uri)
+{
+  //Override this.
+}
+
+} //namespace
+

Added: trunk/glom/bakery/App_WithDoc.h
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/App_WithDoc.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_APP_WITHDOC_H
+#define BAKERY_APP_WITHDOC_H
+
+#include <glom/bakery/App.h>
+#include <libglom/document/bakery/Document.h>
+
+namespace GlomBakery
+{
+
+/** Main Window which supports documents.
+ *
+ * This is an abstract class. You must use a class such as App_WithDoc_Gtk, which implements
+ * the ui_* methods for a particular GUI toolkit.
+ 
+ * Features:
+ * - 1 document per application instance. Uses Document-derived class polymorphically.
+ * - Override init_create_document() to create new blank document.
+ * - Appropriate Default handling of document open, save, save as.
+ * - Appropriate checking of document 'modified' status - asks user about unsaved changes.
+ * - Asks user about overwriting existing documents.
+ * - Override methods to add/change menus/toolbars/statusbar.
+ *   - Default is basic File, Edit, Help menus and toolbar icons.
+ * - Shows document name (or 'untitled') in window title.
+ * - Shows * in title bar for unsaved docs. Overridable to e.g. shade a Save icon.
+ * - Enforces a file extension.
+ * - Recent Documents menu item - if you use add_mime_type().
+ *
+ *
+ * TODO:
+ * - Printing -?
+ *  - Print Setup
+ *  - Print Preview
+ *  - Multiple document-types:
+ *  - File/New sub menu
+ *  - Some way to associate a view with a document type: class factory.
+ */
+class App_WithDoc : virtual public App //virtual because App_WithDoc_Gtk will inherit it via App_With_Doc and via App_Gtk.
+{
+public: 
+  ///Don't forget to call init() too.
+  App_WithDoc(const Glib::ustring& appname = ""); //TODO: appname when using get_derived_widget()
+
+  virtual ~App_WithDoc();
+
+  virtual void init(); //overridden to create document.
+
+  enum enumSaveChanges
+  {
+    SAVECHANGES_Save,
+    SAVECHANGES_Cancel,
+    SAVECHANGES_Discard
+  };
+
+  static bool file_exists(const Glib::ustring& uri);
+
+protected:
+  virtual void init_create_document(); //override this to new() the specific document type.
+
+  /** Add a MIME-type that this application can support.
+   * You should also register the MIME-type when the application is installed:
+   * See http://freedesktop.org/Standards/AddingMIMETutor
+   */
+  static void add_mime_type(const Glib::ustring& mime_type);
+
+  ///static_cast<> or dynamic_cast<> this pointer to the correct type.
+  virtual Document* get_document();
+
+  ///static_cast<> or dynamic_cast<> this pointer to the correct type.
+  virtual const Document* get_document() const ;
+
+  virtual void set_document_modified(bool bModified = true);
+
+  /** Open the document from a file at a URI.
+   * This will check whether the document is already open.
+   * @result true indicates success.
+   */
+  virtual bool open_document(const Glib::ustring& file_uri);
+
+  //This cannot be virtual, because that would break our ABI.
+  //Hopefully that is not necessary.
+  /** Open the document using the supplied document contents.
+   * Unlike open_document(), this has no way to know whether the document is already open.
+   * @param data A pointer to the bytes of the document contents.
+   * @param length The number of bytes in the data.
+   * @result true indicates success.
+   */
+  bool open_document_from_data(const guchar* data, std::size_t length);
+
+  virtual void document_history_add(const Glib::ustring& file_uri);
+  virtual void document_history_remove(const Glib::ustring& file_uri);
+
+public:
+  // We can not take function pointers of these methods in 
+  // a derived class if they are protected - for instance, with sigc::mem_fun()
+  //Signal handlers:
+
+  //Menu items:
+  virtual void on_menu_file_open();
+  virtual void on_menu_file_saveas(); //signal handler.
+  virtual void offer_saveas(); //For direct use.
+  virtual void on_menu_file_save(); //signal handler.
+  virtual void on_menu_file_close();
+
+  virtual void on_menu_edit_copy();
+  virtual void on_menu_edit_paste();
+  virtual void on_menu_edit_clear();
+
+protected:
+  //Document:
+
+  ///Update visual status.
+  virtual void on_document_modified(bool modified);
+
+  ///override this to show document contents.
+  virtual bool on_document_load();
+
+  virtual void offer_to_save_changes();
+
+  ///Stop the File|Close or the File|Exit.
+  virtual void cancel_close_or_exit();
+
+  ///destroy it or mark it for destruction.
+  virtual void close_mark_or_destroy();
+
+  virtual void update_window_title();
+
+  virtual void after_successful_save(); //e.g. disable File|Save.
+
+  virtual void ui_warning(const Glib::ustring& text, const Glib::ustring& secondary_text) = 0;
+  virtual Glib::ustring ui_file_select_open(const Glib::ustring& ui_file_select_open = Glib::ustring()) = 0;
+
+  /** Present a user interface that allows the user to select a location to save the file.
+   * @param old_file_uri The existing URI of the file, if any.
+   * @result The URI of the file chosen by the user.
+   */
+  virtual Glib::ustring ui_file_select_save(const Glib::ustring& old_file_uri) = 0;
+
+  virtual void ui_show_modification_status() = 0;
+
+  virtual enumSaveChanges ui_offer_to_save_changes() = 0;
+
+  static Glib::ustring get_conf_fullkey(const Glib::ustring& key);
+
+  //Document:
+  Document* m_pDocument; //An instance of a derived type.
+  bool m_bCloseAfterSave;
+
+  //Mime types which this application can load and save:
+  typedef std::list<Glib::ustring> type_list_strings;
+  static type_list_strings m_mime_types;
+};
+
+} //namespace
+
+#endif //BAKERY_APP_WITHDOC_H

Added: trunk/glom/bakery/App_WithDoc_Gtk.cc
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/App_WithDoc_Gtk.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+
+#include <glom/bakery/App_WithDoc_Gtk.h>
+#include <glom/bakery/GtkDialogs.h>
+//#include <libgnomevfsmm/utils.h> //For escape_path_string()
+//#include <libgnomevfsmm/mime-handlers.h> //For type_is_known(). 
+#include <gtkmm/toolbutton.h>
+#include <gtkmm/stock.h>
+#ifdef GTKMM_GEQ_2_10
+#include <gtkmm/recentchoosermenu.h>
+#endif // GTKMM_GEQ_2_10
+#include <algorithm>
+#include <glibmm/i18n-lib.h>
+
+//#include <gtk/gtkfilesel.h>
+
+
+namespace GlomBakery
+{
+
+
+//Initialize static member data:
+
+App_WithDoc_Gtk::App_WithDoc_Gtk(const Glib::ustring& appname)
+: App_WithDoc(appname),
+  App_Gtk(appname)
+{
+}
+
+/// This constructor can be used with Gnome::Glade::Xml::get_derived_widget().
+App_WithDoc_Gtk::App_WithDoc_Gtk(BaseObjectType* cobject, const Glib::ustring& appname)
+: App_WithDoc(appname),
+  App_Gtk(cobject, appname),
+  ParentWindow(cobject) //This is a virtual base class (not a direct base), so we must specify a constructor or the default constructor will be called, regardless of what the App_Gtk(cobject) constructor does. Derived classes must do this as well.
+{
+  //TODO: appname.
+}
+
+  
+App_WithDoc_Gtk::~App_WithDoc_Gtk()
+{
+}
+
+
+void App_WithDoc_Gtk::init()
+{  
+  App_WithDoc::init(); //Create document and ask to show it in the UI.
+  
+  init_layout();
+    
+  show();
+}
+
+void App_WithDoc_Gtk::init_toolbars()
+{
+  //Build part of the menu structure, to be merged in by using the "PH" placeholders:
+  static const Glib::ustring ui_description =
+    "<ui>"
+    "  <toolbar name='Bakery_ToolBar'>"
+    "    <placeholder name='Bakery_ToolBarItemsPH'>"
+    "      <toolitem action='BakeryAction_File_New' />"
+    "      <toolitem action='BakeryAction_File_Open' />"
+    "      <toolitem action='BakeryAction_File_Save' />"
+    "    </placeholder>"
+    "  </toolbar>"
+    "</ui>";
+
+  add_ui_from_string(ui_description);
+}
+
+void App_WithDoc_Gtk::init_menus_file_recentfiles(const Glib::ustring& path)
+{
+  if(!m_mime_types.empty()) //"Recent-files" is useless unless it knows what documents (which MIME-types) to show.
+  {
+    //Add recent-files submenu:
+    Gtk::MenuItem* pMenuItem = dynamic_cast<Gtk::MenuItem*>(m_refUIManager->get_widget(path));
+    if(pMenuItem)
+    {
+#ifdef GTKMM_GEQ_2_10
+      Gtk::RecentFilter filter;
+
+      //Add the mime-types, so that it only shows those documents:
+      for(type_list_strings::iterator iter = m_mime_types.begin(); iter != m_mime_types.end(); ++iter)
+      {
+        const Glib::ustring mime_type = *iter;
+
+        //TODO: Find a gio equivalent for gnome_vfs_mime_type_is_known(). murrayc.
+//#ifndef G_OS_WIN32
+//        if( Gnome::Vfs::Mime::type_is_known(mime_type) )
+//#endif // !G_OS_WIN32
+//        {
+          filter.add_mime_type(mime_type);
+//        }
+//#ifndef G_OS_WIN32
+//        else
+//        {
+//          g_warning("App_WithDoc_Gtk::init_menus_file_recentfiles(): MIME-type %s is not known to gnome-vfs", mime_type.c_str());
+//        }
+//#endif // !G_OS_WIN32
+      }
+
+      Gtk::RecentChooserMenu* menu = Gtk::manage(new Gtk::RecentChooserMenu);
+      menu->set_filter(filter);
+      menu->set_limit(10 /* this should be a global GNOME preference, I think. */);
+      menu->set_show_numbers(false);
+      menu->set_sort_type(Gtk::RECENT_SORT_MRU);
+      menu->signal_item_activated().connect(sigc::bind(sigc::mem_fun(*this, static_cast<void(App_WithDoc_Gtk::*)(Gtk::RecentChooser&)>(&App_WithDoc_Gtk::on_recent_files_activate)), sigc::ref(*menu)));
+
+      pMenuItem->set_submenu(*menu);
+#else
+      // TODO: Resurrect libegg? Ignore?
+#endif // GTKMM_GEQ_2_10
+    }
+    else
+    {
+      std::cout << "debug: recent files menu not found" << std::endl;
+    }
+  }
+  else
+  {
+    //std::cout << "debug: GlomBakery::App_WithDoc_Gtk::init_menus_file_recentfiles(): No recent files sub-menu added, because no MIME types are specified." << std::endl;
+  }
+}
+
+void App_WithDoc_Gtk::init_menus_file()
+{
+  // File menu
+
+  //Build actions:
+  m_refFileActionGroup = Gtk::ActionGroup::create("BakeryFileActions");
+
+  m_refFileActionGroup->add(Gtk::Action::create("BakeryAction_Menu_File", _("_File")));
+  m_refFileActionGroup->add(Gtk::Action::create("BakeryAction_Menu_File_RecentFiles", _("_Recent Files")));
+
+  //File actions
+  m_refFileActionGroup->add(Gtk::Action::create("BakeryAction_File_New", Gtk::Stock::NEW),
+                        sigc::mem_fun((App&)*this, &App::on_menu_file_new));
+  m_refFileActionGroup->add(Gtk::Action::create("BakeryAction_File_Open", Gtk::Stock::OPEN),
+                        sigc::mem_fun((App_WithDoc&)*this, &App_WithDoc::on_menu_file_open));
+
+  //Remember thes ones for later, so we can disable Save menu and toolbar items:
+  m_action_save = Gtk::Action::create("BakeryAction_File_Save", Gtk::Stock::SAVE);
+  m_refFileActionGroup->add(m_action_save,
+                        sigc::mem_fun((App_WithDoc&)*this, &App_WithDoc::on_menu_file_save));
+
+  m_action_saveas = Gtk::Action::create("BakeryAction_File_SaveAs", Gtk::Stock::SAVE_AS);                   
+  m_refFileActionGroup->add(m_action_saveas,
+                        sigc::mem_fun((App_WithDoc&)*this, &App_WithDoc::on_menu_file_saveas));
+                        
+  m_refFileActionGroup->add(Gtk::Action::create("BakeryAction_File_Close", Gtk::Stock::CLOSE),
+                        sigc::mem_fun((App_WithDoc&)*this, &App_WithDoc::on_menu_file_close));
+  m_refFileActionGroup->add(Gtk::Action::create("BakeryAction_File_Exit", Gtk::Stock::QUIT),
+                        sigc::mem_fun((App&)*this, &App::on_menu_file_exit));
+                        
+  m_refUIManager->insert_action_group(m_refFileActionGroup);
+
+  //Build part of the menu structure, to be merged in by using the "PH" placeholders:
+  static const Glib::ustring ui_description =
+    "<ui>"
+#ifdef BAKERY_MAEMO_ENABLED
+    "  <popup name='Bakery_MainMenu'>"
+#else
+    "  <menubar name='Bakery_MainMenu'>"
+#endif
+    "    <placeholder name='Bakery_MenuPH_File'>"
+    "      <menu action='BakeryAction_Menu_File'>"
+    "        <menuitem action='BakeryAction_File_New' />"
+    "        <menuitem action='BakeryAction_File_Open' />"
+    "        <menu action='BakeryAction_Menu_File_RecentFiles'>"
+    "        </menu>"
+    "        <menuitem action='BakeryAction_File_Save' />"
+    "        <menuitem action='BakeryAction_File_SaveAs' />"
+    "        <separator/>"
+    "        <menuitem action='BakeryAction_File_Close' />"
+    "        <menuitem action='BakeryAction_File_Exit' />"
+    "      </menu>"
+    "    </placeholder>"
+#ifdef BAKERY_MAEMO_ENABLED
+    "  </popup>"
+#else
+    "  </menubar>"
+#endif
+    "</ui>";
+  
+  //Add menu:
+  add_ui_from_string(ui_description);
+ 
+  //Add recent-files submenu:
+  init_menus_file_recentfiles("/Bakery_MainMenu/Bakery_MenuPH_File/BakeryAction_Menu_File/BakeryAction_Menu_File_RecentFiles");
+}
+
+
+void App_WithDoc_Gtk::update_window_title()
+{
+  //Set application's main window title:
+
+  Glib::ustring strTitle = m_strAppName;
+  Document* pDoc = get_document();
+  if(pDoc)
+  {
+    strTitle += " - " + pDoc->get_name();
+
+    //Indicate unsaved changes:
+    if(pDoc->get_modified())
+      strTitle += " *";
+
+    //Indicate read-only files:
+    if(pDoc->get_read_only())
+      strTitle += _(" (read-only)");
+
+    set_title(strTitle);
+  }
+}
+
+void App_WithDoc_Gtk::ui_warning(const Glib::ustring& text, const Glib::ustring& secondary_text)
+{
+  GtkDialogs::ui_warning(*this, text, secondary_text);
+}
+
+Glib::ustring App_WithDoc_Gtk::ui_file_select_open(const Glib::ustring& starting_folder_uri)
+{
+  return GtkDialogs::ui_file_select_open(*this, starting_folder_uri);
+}
+
+Glib::ustring App_WithDoc_Gtk::ui_file_select_save(const Glib::ustring& old_file_uri)
+{
+  return GtkDialogs::ui_file_select_save(*this, old_file_uri);
+}
+
+void App_WithDoc_Gtk::ui_show_modification_status()
+{
+  bool modified = m_pDocument->get_modified();
+
+  //Enable Save and SaveAs menu items:
+  if(m_action_save)
+    g_object_set(G_OBJECT(m_action_save->gobj()), "sensitive", modified, NULL); // TODO: Use a set_sensitive(modified)?
+
+  if(m_action_saveas)
+    g_object_set(G_OBJECT(m_action_saveas->gobj()), "sensitive", modified, NULL); // TODO: Use a set_sensitive(modified)?
+
+}
+
+App_WithDoc_Gtk::enumSaveChanges App_WithDoc_Gtk::ui_offer_to_save_changes()
+{
+  return GtkDialogs::ui_offer_to_save_changes(*this, m_pDocument->get_file_uri());
+}
+
+void App_WithDoc_Gtk::document_history_add(const Glib::ustring& file_uri)
+{
+  if(file_uri.empty())
+    return;
+
+  //This can sometimes be called for a file that does not yet exist on disk.
+  //Avoid warning in RecentManager if that is the case.
+  //For instance, Glom does this when the user chooses a new filename, 
+  //but before Glom has enough information to save a useful file.
+  if(!file_exists(file_uri))
+    return;
+
+#ifdef GTKMM_GEQ_2_10
+  {
+    //TODO: Wrap gnome_vfs_escape_path_string() in gnome-vfsmm.
+    //Glib::ustring filename_e = Gnome::Vfs::escape_path_string(file_uri);
+    Glib::ustring uri = file_uri; // "file://" + filename_e;
+
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+    Gtk::RecentManager::get_default()->add_item(uri);
+#else
+    std::auto_ptr<Glib::Error> error;
+    Gtk::RecentManager::get_default()->add_item(uri, error);
+    // Ignore error
+#endif
+  }
+#endif // GTKMM_GEQ_2_10
+}
+
+void App_WithDoc_Gtk::document_history_remove(const Glib::ustring& file_uri)
+{
+#ifdef GTKMM_GEQ_2_10
+  if(!file_uri.empty())
+  {
+    //Glib::ustring filename_e = Gnome::Vfs::escape_path_string(file_uri.c_str());
+    Glib::ustring uri = file_uri; //"file://" + filename_e;
+
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+    Gtk::RecentManager::get_default()->remove_item(uri);
+#else
+    std::auto_ptr<Glib::Error> error;
+    Gtk::RecentManager::get_default()->remove_item(uri, error);
+    // Ignore error
+#endif
+  }
+#endif // GTKMM_GEQ_2_10
+}
+
+void App_WithDoc_Gtk::on_recent_files_activate(Gtk::RecentChooser& chooser)
+{
+#ifdef GTKMM_GEQ_2_10
+  Glib::ustring uri = chooser.get_current_uri();
+  bool bTest = open_document(uri);
+  if(!bTest)
+    document_history_remove(uri);
+#endif // GTKMM_GEQ_2_10
+}
+
+} //namespace

Added: trunk/glom/bakery/App_WithDoc_Gtk.h
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/App_WithDoc_Gtk.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_APP_WITHDOC_GTK_H
+#define BAKERY_APP_WITHDOC_GTK_H
+
+#include <glom/bakery/App_WithDoc.h>
+#include <glom/bakery/App_Gtk.h>
+#include <libglom/document/bakery/Document.h>
+#include <gtkmm/toolbutton.h>
+#include <gtkmm/recentmanager.h>
+#include <gtkmm/recentchooser.h>
+
+namespace GlomBakery
+{
+
+/** This class implements GlomBakery::App_WithDoc using gtkmm.
+ *
+ * Your application's installation should register your document's MIME-type in GNOME's (freedesktop's) MIME-type system,
+ * and register your application as capable of opening documents of that MIME-type.
+ * 
+ *
+ */
+class App_WithDoc_Gtk
+    //These are virtual base classes, with shared shared App and sigc::trackable base classes:
+  : public App_WithDoc, 
+    public App_Gtk
+{
+public:
+  ///Don't forget to call init() too.
+  App_WithDoc_Gtk(const Glib::ustring& appname);
+
+  /// This constructor can be used to implement derived classes for use with Gnome::Glade::Xml::get_derived_widget().
+  App_WithDoc_Gtk(BaseObjectType* cobject, const Glib::ustring& appname);
+
+  virtual ~App_WithDoc_Gtk();
+
+  virtual void init(); //Unique final overrider.
+
+protected:
+  virtual void init_menus_file(); //overridden to add open/save/save as.
+  virtual void init_menus_file_recentfiles(const Glib::ustring& path); // call this in init_menus_file()
+  virtual void init_toolbars(); //overridden to add open/save
+
+  virtual void document_history_add(const Glib::ustring& file_uri); //overridden.
+  virtual void document_history_remove(const Glib::ustring& file_uri); //overridden.
+
+  virtual void update_window_title();
+
+  virtual void ui_warning(const Glib::ustring& text, const Glib::ustring& secondary_text);
+  virtual Glib::ustring ui_file_select_open(const Glib::ustring& starting_folder_uri = Glib::ustring());
+  virtual Glib::ustring ui_file_select_save(const Glib::ustring& old_file_uri);
+  virtual void ui_show_modification_status();
+  virtual enumSaveChanges ui_offer_to_save_changes();
+
+  void on_recent_files_activate(Gtk::RecentChooser& recent_chooser);
+
+  //Menu stuff:
+  Glib::RefPtr<Gtk::Action> m_action_save, m_action_saveas;
+};
+
+} //namespace
+
+#endif //BAKERY_APP_WITHDOC_GTK_H

Added: trunk/glom/bakery/Dialog_OfferSave.cc
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/Dialog_OfferSave.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+#include <glom/bakery/Dialog_OfferSave.h>
+#include <glom/bakery/App_Gtk.h>
+#include <gtkmm/box.h>
+#include <gtkmm/stock.h>
+#include <glibmm/i18n-lib.h>
+
+namespace
+{
+  Glib::ustring get_confirmation_message(const Glib::ustring& file_uri)
+  {
+    Glib::ustring message = _("This document has unsaved changes. Would you like to save the document?");
+    if(!file_uri.empty())
+      message += _("\n\nDocument:\n") + Glib::filename_display_basename(file_uri); //TODO: Can we use filename_display_basename() with a URI?
+    return message;
+  }
+}
+
+namespace GlomBakery
+{
+
+
+Dialog_OfferSave::Dialog_OfferSave(const Glib::ustring& file_uri)
+#ifdef BAKERY_MAEMO_ENABLED
+: Hildon::Note(Hildon::NOTE_TYPE_CONFIRMATION_BUTTON, get_confirmation_message(file_uri))
+#else
+: Gtk::MessageDialog( App_Gtk::util_bold_message(_("Close without Saving")), true /* use markup */, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE)
+#endif
+{
+  set_title(""); //The HIG says that alert dialogs should not have titles. The default comes from the message type.
+
+#ifndef BAKERY_MAEMO_ENABLED
+  set_secondary_text(get_confirmation_message(file_uri));
+#endif
+
+  add_button(_("Discard"), BUTTON_Discard);
+  Gtk::Button* cancel_button = add_button(Gtk::Stock::CANCEL, BUTTON_Cancel);
+  add_button(Gtk::Stock::SAVE, BUTTON_Save);
+
+  // Otherwise Discard has focus initially which seems inconvenient:
+  cancel_button->grab_focus();
+}
+
+Dialog_OfferSave::~Dialog_OfferSave()
+{
+
+}
+
+
+} //namespace

Added: trunk/glom/bakery/Dialog_OfferSave.h
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/Dialog_OfferSave.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef DIALOG_OFFERSAVE_H
+#define DIALOG_OFFERSAVE_H
+
+#include <config.h>
+
+#ifdef BAKERY_MAEMO_ENABLED
+#include <hildonmm/note.h>
+#else
+#include <gtkmm/messagedialog.h>
+#endif
+
+namespace GlomBakery
+{
+
+#ifdef BAKERY_MAEMO_ENABLED
+class Dialog_OfferSave : public Hildon::Note
+#else
+class Dialog_OfferSave : public Gtk::MessageDialog
+#endif
+{
+public:
+  Dialog_OfferSave(const Glib::ustring& file_uri);
+  virtual ~Dialog_OfferSave();
+
+  ///Return values:
+  enum enumButtons
+  {
+    BUTTON_Save,
+    BUTTON_Discard,
+    BUTTON_Cancel
+  };
+
+};
+
+} //namespace
+
+#endif //DIALOG_OFFERSAVE_H

Added: trunk/glom/bakery/GtkDialogs.cc
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/GtkDialogs.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+
+#ifdef BAKERY_MAEMO_ENABLED
+#include <hildon-fmmm/file-chooser-dialog.h>
+#include <hildonmm/note.h>
+#endif // BAKERY_MAEMO_ENABLED
+
+#include <glom/bakery/GtkDialogs.h>
+#include <glom/bakery/Dialog_OfferSave.h>
+#include <glom/bakery/App_Gtk.h>
+#include <gtkmm/stock.h>
+#include <gtkmm/messagedialog.h>
+#include <gtkmm/filechooserdialog.h>
+#include <giomm.h>
+#include <glibmm/i18n-lib.h>
+
+
+namespace GlomBakery
+{
+
+void GtkDialogs::ui_warning(App& app, const Glib::ustring& text, const Glib::ustring& secondary_text)
+{
+  Gtk::Window* pWindow = dynamic_cast<Gtk::Window*>(&app);
+
+#ifdef BAKERY_MAEMO_ENABLED
+  Hildon::Note dialog(Hildon::NOTE_TYPE_INFORMATION, text, Gtk::Stock::DIALOG_WARNING);
+#else
+  Gtk::MessageDialog dialog(App_Gtk::util_bold_message(text), true /* use markup */, Gtk::MESSAGE_WARNING);
+  dialog.set_secondary_text(secondary_text);
+
+  dialog.set_title(""); //The HIG says that alert dialogs should not have titles. The default comes from the message type.
+#endif
+
+  if(pWindow)
+    dialog.set_transient_for(*pWindow);
+
+  dialog.run();
+}
+
+Glib::ustring GtkDialogs::ui_file_select_open(App& app, const Glib::ustring& starting_folder_uri)
+{
+  Gtk::Window* pWindow = dynamic_cast<Gtk::Window*>(&app);
+
+#ifdef BAKERY_MAEMO_ENABLED
+  Hildon::FileChooserDialog fileChooser_Open(Gtk::FILE_CHOOSER_ACTION_OPEN);
+#else
+  Gtk::FileChooserDialog fileChooser_Open(_("Open Document"), Gtk::FILE_CHOOSER_ACTION_OPEN);
+  fileChooser_Open.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+  fileChooser_Open.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
+  fileChooser_Open.set_default_response(Gtk::RESPONSE_OK);
+#endif // BAKERY_MAEMO_ENABLED
+
+  if(pWindow)
+    fileChooser_Open.set_transient_for(*pWindow);
+
+  if(!starting_folder_uri.empty())
+    fileChooser_Open.set_current_folder_uri(starting_folder_uri);
+
+  const int response_id = fileChooser_Open.run();
+  fileChooser_Open.hide();
+  if(response_id != Gtk::RESPONSE_CANCEL)
+  {
+    return fileChooser_Open.get_uri();
+  }
+  else
+    return Glib::ustring();
+}
+
+static bool uri_is_writable(const Glib::RefPtr<const Gio::File>& uri)
+{
+  if(!uri)
+    return false;
+
+  Glib::RefPtr<const Gio::FileInfo> file_info;
+
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  try
+  {
+    file_info = uri->query_info(G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+  }
+  catch(const Glib::Error& /* ex */)
+  {
+    return false;
+  }
+#else
+  std::auto_ptr<Gio::Error> error;
+  file_info = uri->query_info(G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, Gio::FILE_QUERY_INFO_NONE, error);
+  if(error.get())
+    return false;
+#endif
+
+  if(file_info)
+  {
+    return file_info->get_attribute_boolean(G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+  }
+  else
+    return true; //Not every URI protocol supports access rights, so assume that it's writable and complain later.
+}
+
+Glib::ustring GtkDialogs::ui_file_select_save(App& app, const Glib::ustring& old_file_uri)
+{
+  Gtk::Window* pWindow = dynamic_cast<Gtk::Window*>(&app);
+
+#ifdef BAKERY_MAEMO_ENABLED
+  Hildon::FileChooserDialog fileChooser_Save(Gtk::FILE_CHOOSER_ACTION_SAVE);
+#else
+  Gtk::FileChooserDialog fileChooser_Save(_("Save Document"), Gtk::FILE_CHOOSER_ACTION_SAVE);
+  fileChooser_Save.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+  fileChooser_Save.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
+  fileChooser_Save.set_default_response(Gtk::RESPONSE_OK);
+#endif // BAKERY_MAEMO_ENABLED
+
+ if(pWindow)
+    fileChooser_Save.set_transient_for(*pWindow);
+
+  fileChooser_Save.set_do_overwrite_confirmation(); //Ask the user if the file already exists.
+
+  //Make the save dialog show the existing filename, if any:
+  if(!old_file_uri.empty())
+  {
+    //Just start with the parent folder,
+    //instead of the whole name, to avoid overwriting:
+    Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_uri(old_file_uri);
+    if(gio_file)
+    {
+      Glib::RefPtr<Gio::File> parent = gio_file->get_parent();
+      if(parent)
+      {
+        const Glib::ustring uri_parent = parent->get_uri();
+        fileChooser_Save.set_uri(uri_parent);
+      }
+    }
+  }
+
+
+  //bool tried_once_already = false;
+
+  bool try_again = true;
+  while(try_again)
+  {
+    try_again = false;
+
+    //Work around bug #330680 "GtkFileChooserDialog is too small when shown a second time.":
+    //(Commented-out because the workaround doesn't work)
+    /*
+    if(tried_once_already)
+    {
+      fileChooser_Save.set_default_size(-1, 600); 
+    }
+    else
+      tried_once_already = true;
+    */
+
+    const int response_id = fileChooser_Save.run();
+    fileChooser_Save.hide();
+    if(response_id != Gtk::RESPONSE_CANCEL)
+    {
+      const Glib::ustring uri = fileChooser_Save.get_uri();
+
+      Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_uri(uri);
+
+      //If the file exists (the FileChooser offers a "replace?" dialog, so this is possible.):
+      if(App_WithDoc::file_exists(uri))
+      {
+        //Check whether we have rights to the file to change it:
+        //Really, GtkFileChooser should do this for us.
+        if(!uri_is_writable(gio_file))
+        {
+           //Warn the user:
+           ui_warning(app, _("Read-only File."), _("You may not overwrite the existing file, because you do not have sufficient access rights."));
+           try_again = true; //Try again.
+           continue;
+        }
+      }
+
+      //Check whether we have rights to the directory, to create a new file in it:
+      //Really, GtkFileChooser should do this for us.
+      Glib::RefPtr<const Gio::File> gio_file_parent = gio_file->get_parent();
+      if(gio_file_parent)
+      {
+        if(!uri_is_writable(gio_file_parent))
+        {
+          //Warn the user:
+           ui_warning(app, _("Read-only Directory."), _("You may not create a file in this directory, because you do not have sufficient access rights."));
+           try_again = true; //Try again.
+           continue;
+        }
+      }
+
+      if(!try_again)
+        return uri;
+    }
+    else
+      return Glib::ustring(); //The user cancelled.
+  }
+}
+
+App_WithDoc::enumSaveChanges GtkDialogs::ui_offer_to_save_changes(App& app, const Glib::ustring& file_uri)
+{
+  App_WithDoc::enumSaveChanges result = App_WithDoc::SAVECHANGES_Cancel;
+
+  GlomBakery::Dialog_OfferSave* pDialogQuestion = new GlomBakery::Dialog_OfferSave(file_uri);
+
+  Gtk::Window* pWindow = dynamic_cast<Gtk::Window*>(&app);
+  if(pWindow)
+    pDialogQuestion->set_transient_for(*pWindow);
+
+  GlomBakery::Dialog_OfferSave::enumButtons buttonClicked = (GlomBakery::Dialog_OfferSave::enumButtons)pDialogQuestion->run();
+  delete pDialogQuestion;
+  pDialogQuestion = 0;
+
+  if(buttonClicked == GlomBakery::Dialog_OfferSave::BUTTON_Save)
+     result = App_WithDoc::SAVECHANGES_Save;
+  else if(buttonClicked == GlomBakery::Dialog_OfferSave::BUTTON_Discard)
+     result = App_WithDoc::SAVECHANGES_Discard;
+  else
+     result = App_WithDoc::SAVECHANGES_Cancel;
+
+  return result;
+}
+
+} //namespace

Added: trunk/glom/bakery/GtkDialogs.h
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/GtkDialogs.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_APP_GTKDIALOGS_H
+#define BAKERY_APP_GTKDIALOGS_H
+
+#include <glom/bakery/App_WithDoc.h>
+
+namespace GlomBakery
+{
+
+/** This class implements some gtkmm UI abstractions.
+ */
+class GtkDialogs
+{
+public:
+  static void ui_warning(App& app, const Glib::ustring& text, const Glib::ustring& secondary_text);
+  static Glib::ustring ui_file_select_open(App& app, const Glib::ustring& starting_folder_uri = Glib::ustring());
+
+  ///Ask the user for a filename, and ask for confirmation if the file exists already.
+  static Glib::ustring ui_file_select_save(App& app, const Glib::ustring& old_file_uri);
+
+  static void ui_show_modification_status();
+  static App_WithDoc::enumSaveChanges ui_offer_to_save_changes(App& app, const Glib::ustring& file_uri);
+};
+
+} //namespace
+
+#endif //BAKERY_APP_GTKDIALOGS_H

Added: trunk/glom/bakery/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/glom/bakery/Makefile.am	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,10 @@
+AM_CPPFLAGS = -I top_srcdir@/ -I top_srcdir@/glom $(GLOM_CFLAGS)
+
+h_sources = App_Gtk.h AppInstanceManager.h App_WithDoc.h GtkDialogs.h App.h App_WithDoc_Gtk.h Dialog_OfferSave.h
+cc_sources = App_Gtk.cc AppInstanceManager.cc App_WithDoc.cc GtkDialogs.cc App.cc App_WithDoc_Gtk.cc Dialog_OfferSave.cc
+
+noinst_LIBRARIES = libbakery_app.a
+libbakery_app_a_SOURCES = $(h_sources) $(cc_sources)
+
+ 
+

Modified: trunk/glom/base_db.cc
==============================================================================
--- trunk/glom/base_db.cc	(original)
+++ trunk/glom/base_db.cc	Tue Mar 17 10:46:53 2009
@@ -120,7 +120,7 @@
 sharedptr<SharedConnection> Base_DB::connect_to_server(Gtk::Window* parent_window, std::auto_ptr<ExceptionConnection>& error)
 #endif
 {
-  Bakery::BusyCursor busy_cursor(parent_window);
+  BusyCursor busy_cursor(parent_window);
 
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
   return ConnectionPool::get_and_connect();
@@ -133,7 +133,7 @@
 {
   std::cerr << "Internal Error (Base_DB::handle_error()): exception type=" << typeid(ex).name() << ", ex.what()=" << ex.what() << std::endl;
 
-  Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Internal error")), true, Gtk::MESSAGE_WARNING );
+  Gtk::MessageDialog dialog(Utils::bold_message(_("Internal error")), true, Gtk::MESSAGE_WARNING );
   dialog.set_secondary_text(ex.what());
   //TODO: dialog.set_transient_for(*get_application());
   dialog.run();
@@ -146,7 +146,7 @@
 #ifdef GLOM_ENABLE_MAEMO
   Hildon::Note dialog(Hildon::NOTE_TYPE_INFORMATION, ex.what());
 #else
-  Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Internal error")), true, Gtk::MESSAGE_WARNING );
+  Gtk::MessageDialog dialog(Utils::bold_message(_("Internal error")), true, Gtk::MESSAGE_WARNING );
   dialog.set_secondary_text(ex.what());
   //TODO: dialog.set_transient_for(*get_application());
 #endif
@@ -164,7 +164,7 @@
 {
   Glib::RefPtr<Gnome::Gda::DataModel> result;
 
-  //TODO: Bakery::BusyCursor busy_cursor(get_app_window());
+  //TODO: BusyCursor busy_cursor(get_app_window());
 
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
   sharedptr<SharedConnection> sharedconnection = connect_to_server();
@@ -540,7 +540,7 @@
     DATAMODEL_FIELDS_COL_EXTRA = 6 // Could be auto-increment
   };
 
-  //TODO: Bakery::BusyCursor busy_cursor(get_application());
+  //TODO: BusyCursor busy_cursor(get_application());
 
 #ifdef GLIBMM_EXCEPTIONS_ENABLED
   sharedptr<SharedConnection> sharedconnection = connect_to_server();
@@ -1348,7 +1348,7 @@
     const Glib::Error& ex = *error;
 #endif
     handle_error(ex);
-//    Gtk::MessageDialog window(*parent_window, Bakery::App_Gtk::util_bold_message(ex.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
+//    Gtk::MessageDialog window(*parent_window, Utils::bold_message(ex.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
 //    window.run();
     return false;
   }
@@ -1375,7 +1375,7 @@
     const Glib::Error& ex = *error;
 #endif
     handle_error(ex);
-//    Gtk::MessageDialog window(*parent_window, Bakery::App_Gtk::util_bold_message(ex.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
+//    Gtk::MessageDialog window(*parent_window, Utils::bold_message(ex.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
 //    window.run();
     return false;
   }
@@ -1444,7 +1444,7 @@
     const Glib::Error& ex = *error;
 #endif
     handle_error(ex);
-//    Gtk::MessageDialog window(*parent_window, Bakery::App_Gtk::util_bold_message(ex.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
+//    Gtk::MessageDialog window(*parent_window, Utils::bold_message(ex.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
 //    window.run();
     return sharedptr<Field>();
   }
@@ -1480,7 +1480,7 @@
     const Glib::Error& ex = *error;
 #endif
     handle_error(ex);
-//    Gtk::MessageDialog window(*parent_window, Bakery::App_Gtk::util_bold_message(ex.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
+//    Gtk::MessageDialog window(*parent_window, Utils::bold_message(ex.what()), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
 //    window.run();
     return false;
   }
@@ -1851,7 +1851,7 @@
 #ifdef GLOM_ENABLE_MAEMO
   Hildon::Note dialog(Hildon::NOTE_TYPE_CONFIRMATION_BUTTON, transient_for, message);
 #else
-  Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("No Records Found")), true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
+  Gtk::MessageDialog dialog(Utils::bold_message(_("No Records Found")), true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
   dialog.set_secondary_text(message);
   dialog.set_transient_for(transient_for);
 #endif

Modified: trunk/glom/base_db.h
==============================================================================
--- trunk/glom/base_db.h	(original)
+++ trunk/glom/base_db.h	Tue Mar 17 10:46:53 2009
@@ -33,8 +33,8 @@
 #include <libglom/data_structure/system_prefs.h>
 #include <libglom/utils.h>
 #include <libglom/calcinprogress.h>
-#include "bakery/View/View.h"
-#include <bakery/Utilities/BusyCursor.h>
+#include <libglom/document/bakery/view/View.h>
+#include <libglom/busy_cursor.h>
 
 namespace Glom
 {

Modified: trunk/glom/base_db_table_data.cc
==============================================================================
--- trunk/glom/base_db_table_data.cc	(original)
+++ trunk/glom/base_db_table_data.cc	Tue Mar 17 10:46:53 2009
@@ -254,7 +254,7 @@
 
 bool Base_DB_Table_Data::get_related_record_exists(const sharedptr<const Relationship>& relationship, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value)
 {
-  Bakery::BusyCursor cursor(App_Glom::get_application());
+  BusyCursor cursor(App_Glom::get_application());
 
   bool result = false;
 
@@ -308,7 +308,7 @@
 #ifdef GLOM_ENABLE_MAEMO
     Hildon::Note dialog(Hildon::NOTE_TYPE_INFORMATION, *App_Glom::get_application(), message);
 #else
-    Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Related Record Does Not Exist")), true);
+    Gtk::MessageDialog dialog(Utils::bold_message(_("Related Record Does Not Exist")), true);
     dialog.set_secondary_text(message);
     dialog.set_transient_for(*App_Glom::get_application());
 #endif
@@ -333,7 +333,7 @@
 #ifdef GLOM_ENABLE_MAEMO
       Hildon::Note dialog(Hildon::NOTE_TYPE_INFORMATION, *App_Glom::get_application(), message);
 #else
-      Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Related Record Cannot Be Created")), true);
+      Gtk::MessageDialog dialog(Utils::bold_message(_("Related Record Cannot Be Created")), true);
       //TODO: This is a very complex error message:
       dialog.set_secondary_text(message);
       dialog.set_transient_for(*App_Glom::get_application());
@@ -439,7 +439,7 @@
 #ifdef GLOM_ENABLE_MAEMO
   Hildon::Note dialog(Hildon::NOTE_TYPE_CONFIRMATION_BUTTON, *get_app_window(), message);
 #else
-  Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Delete record")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE);
+  Gtk::MessageDialog dialog(Utils::bold_message(_("Delete record")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE);
   dialog.set_secondary_text(message);
   dialog.set_transient_for(*App_Glom::get_application());
 #endif

Modified: trunk/glom/box_reports.cc
==============================================================================
--- trunk/glom/box_reports.cc	(original)
+++ trunk/glom/box_reports.cc	Tue Mar 17 10:46:53 2009
@@ -19,7 +19,7 @@
  */
 
 #include "box_reports.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -67,7 +67,7 @@
 
 bool Box_Reports::fill_from_database()
 {
-  Bakery::BusyCursor busy_cursor(get_app_window());
+  BusyCursor busy_cursor(get_app_window());
 
   bool result = Box_DB_Table::fill_from_database();
 

Modified: trunk/glom/box_withbuttons.h
==============================================================================
--- trunk/glom/box_withbuttons.h	(original)
+++ trunk/glom/box_withbuttons.h	Tue Mar 17 10:46:53 2009
@@ -28,7 +28,7 @@
 #include <libglom/connectionpool.h>
 #include <libglom/appstate.h>
 #include "base_db.h"
-#include <bakery/Utilities/BusyCursor.h>
+#include <libglom/busy_cursor.h>
 #include <libglademm.h>
 
 namespace Glom

Modified: trunk/glom/dialog_connection.cc
==============================================================================
--- trunk/glom/dialog_connection.cc	(original)
+++ trunk/glom/dialog_connection.cc	Tue Mar 17 10:46:53 2009
@@ -77,7 +77,7 @@
 {
   //std::cout << "debug: Dialog_Connection::connect_to_server_with_connection_settings()" << std::endl;
 
-  //TODO: Bakery::BusyCursor busy_cursor(get_app_window());
+  //TODO: BusyCursor busy_cursor(get_app_window());
 
   sharedptr<SharedConnection> result(0);
 

Modified: trunk/glom/dialog_database_preferences.cc
==============================================================================
--- trunk/glom/dialog_database_preferences.cc	(original)
+++ trunk/glom/dialog_database_preferences.cc	Tue Mar 17 10:46:53 2009
@@ -22,7 +22,7 @@
 #include "box_withbuttons.h" //For Box_WithButtons::connect_to_server().
 #include <libglom/standard_table_prefs_fields.h>
 #include <libglom/data_structure/glomconversions.h>
-#include <bakery/Utilities/BusyCursor.h>
+#include <libglom/busy_cursor.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -178,7 +178,7 @@
 
 void Dialog_Database_Preferences::save_to_document()
 {
-  Bakery::BusyCursor busy_cursor(this);
+  BusyCursor busy_cursor(this);
 
   m_glade_variables_map.transfer_widgets_to_variables();
   m_system_prefs.m_org_logo = m_image->get_value();

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	Tue Mar 17 10:46:53 2009
@@ -45,7 +45,7 @@
 {
   //std::cout << "debug: Dialog_NewSelfHostedConnection::connect_to_server_with_connection_settings()" << std::endl;
 
-  //TODO: Bakery::BusyCursor busy_cursor(get_app_window());
+  //TODO: BusyCursor busy_cursor(get_app_window());
 
  
   ConnectionPool* connection_pool = ConnectionPool::get_instance();

Modified: trunk/glom/frame_glom.cc
==============================================================================
--- trunk/glom/frame_glom.cc	(original)
+++ trunk/glom/frame_glom.cc	Tue Mar 17 10:46:53 2009
@@ -340,7 +340,7 @@
   App_Glom* pApp = dynamic_cast<App_Glom*>(get_app_window());
 
   //This can take quite a long time, so we show the busy cursor while it's working:
-  Bakery::BusyCursor busy_cursor(pApp);
+  BusyCursor busy_cursor(pApp);
 
   //Choose a default mode, if necessary:
   if(m_Mode == MODE_None)
@@ -494,14 +494,14 @@
         if(document->get_opened_from_browse())
         {
           //TODO: Obviously this could be possible but it would require a network protocol and some work:
-          Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Developer Mode Not Available.")), true, Gtk::MESSAGE_WARNING);
+          Gtk::MessageDialog dialog(Utils::bold_message(_("Developer Mode Not Available.")), true, Gtk::MESSAGE_WARNING);
           dialog.set_secondary_text(_("Developer mode is not available because the file was opened over the network from a running Glom. Only the original file may be edited."));
           dialog.set_transient_for(*get_app_window());
           dialog.run();
         }
         else
         {
-          Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Developer Mode Not Available")), true, Gtk::MESSAGE_WARNING);
+          Gtk::MessageDialog dialog(Utils::bold_message(_("Developer Mode Not Available")), true, Gtk::MESSAGE_WARNING);
           dialog.set_secondary_text(_("Developer mode is not available. Check that you have sufficient database access rights and that the glom file is not read-only."));
           dialog.set_transient_for(*get_app_window());
           dialog.run();
@@ -509,7 +509,7 @@
       }
       else if(document->get_document_format_version() < Document_Glom::get_latest_known_document_format_version())
       {
-        Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Saving in New Document Format")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE);
+        Gtk::MessageDialog dialog(Utils::bold_message(_("Saving in New Document Format")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE);
         dialog.set_secondary_text(_("The document was created by an earlier version of the application. Making changes to the document will mean that the document cannot be opened by some earlier versions of the application."));
         dialog.set_transient_for(*get_app_window());
         dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
@@ -848,7 +848,7 @@
 {
   //This can take quite a long time, flicking between 1 or 2 intermediate screens. 
   //It shouldn't, but until we fix that, let's show the busy cursor while it's working:
-  Bakery::BusyCursor busy_cursor(get_app_window());
+  BusyCursor busy_cursor(get_app_window());
 
   const bool previously_in_data_mode = (m_Mode == MODE_Data);
 
@@ -1060,7 +1060,7 @@
   }
 
   {
-    Bakery::BusyCursor busy_cursor(get_app_window());
+    BusyCursor busy_cursor(get_app_window());
     m_pBox_Tables->init_db_details();
   }
 
@@ -1122,7 +1122,7 @@
     Hildon::Note note(Hildon::NOTE_TYPE_INFORMATION, *get_app_window(), message);
     note.run();
 #else
-    Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("No Find Criteria")), true, Gtk::MESSAGE_WARNING );
+    Gtk::MessageDialog dialog(Utils::bold_message(_("No Find Criteria")), true, Gtk::MESSAGE_WARNING );
     dialog.set_secondary_text(message);
     dialog.set_transient_for(*get_app_window());
     dialog.run();
@@ -1147,7 +1147,7 @@
     bool records_found = false;
 
     { //Extra scope, to control the lifetime of the busy cursor. 
-      Bakery::BusyCursor busy_cursor(pApp);
+      BusyCursor busy_cursor(pApp);
 
       pApp->set_mode_data();
 
@@ -2059,7 +2059,7 @@
   Gtk::Window* pWindowApp = get_app_window();
   g_assert(pWindowApp);
 
-  Bakery::BusyCursor busycursor(*pWindowApp);
+  BusyCursor busycursor(*pWindowApp);
 
   try
   {

Modified: trunk/glom/frame_glom.h
==============================================================================
--- trunk/glom/frame_glom.h	(original)
+++ trunk/glom/frame_glom.h	Tue Mar 17 10:46:53 2009
@@ -24,7 +24,7 @@
 #include <libglom/libglom_config.h> // For GLOM_ENABLE_CLIENT_ONLY
 
 #include <gtkmm/frame.h>
-#include "bakery/View/View_Composite.h"
+#include <libglom/document/bakery/view/View_Composite.h>
 #include <libglom/document/document_glom.h>
 
 #include "dialog_glom.h"
@@ -56,7 +56,7 @@
 
 class Frame_Glom :
   public PlaceHolder,
-  //public Bakery::View_Composite<Document_Glom>,
+  //public GlomBakery::View_Composite<Document_Glom>,
   public Base_DB //Inherits from View_Composite.
 {
 public: 

Modified: trunk/glom/glom_privs.cc
==============================================================================
--- trunk/glom/glom_privs.cc	(original)
+++ trunk/glom/glom_privs.cc	Tue Mar 17 10:46:53 2009
@@ -51,7 +51,7 @@
 
 Privs::type_vecStrings Privs::get_database_users(const Glib::ustring& group_name)
 {
-  Bakery::BusyCursor cursor(App_Glom::get_application());
+  BusyCursor cursor(App_Glom::get_application());
 
   type_vecStrings result;
 
@@ -341,7 +341,7 @@
   //TODO_Performance: There's lots of database access here.
   //We could maybe replace some with the postgres has_table_* function().
 
-  Bakery::BusyCursor cursor(App_Glom::get_application());
+  BusyCursor cursor(App_Glom::get_application());
 
   //Return a cached value if possible.
   //(If it is in the cache then it's fairly recent)

Modified: trunk/glom/layout_item_dialogs/dialog_groupby_secondaryfields.cc
==============================================================================
--- trunk/glom/layout_item_dialogs/dialog_groupby_secondaryfields.cc	(original)
+++ trunk/glom/layout_item_dialogs/dialog_groupby_secondaryfields.cc	Tue Mar 17 10:46:53 2009
@@ -20,7 +20,6 @@
 
 #include "dialog_groupby_secondaryfields.h"
 #include "dialog_field_layout.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
 
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>

Modified: trunk/glom/layout_item_dialogs/dialog_groupby_sortfields.cc
==============================================================================
--- trunk/glom/layout_item_dialogs/dialog_groupby_sortfields.cc	(original)
+++ trunk/glom/layout_item_dialogs/dialog_groupby_sortfields.cc	Tue Mar 17 10:46:53 2009
@@ -20,7 +20,6 @@
 
 #include "dialog_groupby_sortfields.h"
 #include "dialog_field_layout.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
 
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>

Modified: trunk/glom/layout_item_dialogs/dialog_notebook.cc
==============================================================================
--- trunk/glom/layout_item_dialogs/dialog_notebook.cc	(original)
+++ trunk/glom/layout_item_dialogs/dialog_notebook.cc	Tue Mar 17 10:46:53 2009
@@ -20,7 +20,6 @@
 
 #include "dialog_notebook.h"
 #include "../mode_data/dialog_layout.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
 
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>

Modified: trunk/glom/libglom/Makefile.am
==============================================================================
--- trunk/glom/libglom/Makefile.am	(original)
+++ trunk/glom/libglom/Makefile.am	Tue Mar 17 10:46:53 2009
@@ -26,6 +26,7 @@
                      appstate.h
                      
 h_sources = $(h_sources_public) \
+                     busy_cursor.h \
                      calcinprogress.h \
                      connectionpool.h \
                      dialog_progress_creating.h \
@@ -34,6 +35,7 @@
                      gst-package.h
 
 cc_sources = appstate.cc \
+                     busy_cursor.cc \
                      calcinprogress.cc \
                      connectionpool.cc \
                      dialog_progress_creating.cc \
@@ -55,6 +57,8 @@
 endif
 
 libglom_1_0_la_LIBADD  = document/libdocument.la \
+                     document/bakery/libdocument_bakery.la \
+                     document/bakery/view/libdocument_bakery_view.la \
                      connectionpool_backends/libconnectionpool_backends.la \
                      data_structure/libdata_structure.la \
                      data_structure/layout/libdata_structure_layout.la \

Added: trunk/glom/libglom/busy_cursor.cc
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/busy_cursor.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,88 @@
+#include <libglom/busy_cursor.h>
+#include <gtkmm/main.h>
+#include <gtk/gtk.h>
+
+namespace Glom
+{
+
+//Intialize static member variable:
+BusyCursor::type_map_cursors BusyCursor::m_map_cursors;
+
+BusyCursor::BusyCursor(Gtk::Window& window, Gdk::CursorType cursor_type)
+: m_Cursor(cursor_type),
+  m_old_cursor_valid(false)
+{
+  //If this is a nested cursor then remember the previously-set cursor, so we can restore it:
+  m_pWindow = &window;
+  init();
+}
+
+BusyCursor::BusyCursor(Gtk::Window* window, Gdk::CursorType cursor_type)
+: m_Cursor(cursor_type),
+  m_old_cursor_valid(false)
+{
+  m_pWindow = window;
+  if(m_pWindow)
+    init();
+}
+
+void BusyCursor::init()
+{
+  if(!m_pWindow)
+    return;
+
+  m_refWindow = m_pWindow->get_window();
+  if(!m_refWindow)
+    return;
+
+  type_map_cursors::iterator iter = m_map_cursors.find(m_pWindow);
+  if(iter != m_map_cursors.end())
+  {
+    m_old_cursor = iter->second; //Remember the existing cursor.
+    m_old_cursor_valid = true;
+  }
+
+  m_map_cursors[m_pWindow] = m_Cursor; //Let a further nested cursor know about the new cursor in use.
+
+
+  //Change the cursor:
+  if(m_refWindow)
+    m_refWindow->set_cursor(m_Cursor);
+
+  force_gui_update();
+}
+
+BusyCursor::~BusyCursor()
+{
+  //Restore the old cursor:
+  if(m_old_cursor_valid)
+  {
+    if(m_refWindow)
+      m_refWindow->set_cursor(m_old_cursor);
+  }
+  else
+  {
+    if(m_refWindow)
+      m_refWindow->set_cursor();
+
+    type_map_cursors::iterator iter = m_map_cursors.find(m_pWindow);
+    if(iter != m_map_cursors.end())
+      m_map_cursors.erase(iter);
+  }
+
+  force_gui_update();
+}
+
+
+void BusyCursor::force_gui_update()
+{
+  if(m_refWindow)
+  {
+    //Force the GUI to update:
+    while(Gtk::Main::events_pending())
+      Gtk::Main::iteration();
+  }
+}
+
+
+} //namespace Glom

Added: trunk/glom/libglom/busy_cursor.h
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/busy_cursor.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_UTILITIES_BUSYCURSOR_H
+#define BAKERY_UTILITIES_BUSYCURSOR_H
+
+#include <gtkmm/window.h>
+#include <gdkmm/cursor.h>
+#include <map>
+
+namespace Glom
+{
+
+/** Changes the cursor for as long as this instance lives.
+ * For instance, put it at the start of code in a { and } block.
+ */ 
+class BusyCursor
+{
+public:
+  /** Associate a busy cursor with the window, for the lifetime of this object.
+   */
+  BusyCursor(Gtk::Window& window, Gdk::CursorType cursor_type = Gdk::WATCH);
+
+  /**  Associate a busy cursor with the window, for the lifetime of this object, if window is not 0.
+   */
+  BusyCursor(Gtk::Window* window, Gdk::CursorType cursor_type = Gdk::WATCH);
+
+  virtual ~BusyCursor();
+
+protected:
+
+  void init();
+  void force_gui_update();
+
+  Gdk::Cursor m_Cursor;
+  Gtk::Window* m_pWindow;
+  Glib::RefPtr<Gdk::Window> m_refWindow;
+
+  typedef std::map<Gtk::Window*, Gdk::Cursor> type_map_cursors;
+  static type_map_cursors m_map_cursors;
+  Gdk::Cursor m_old_cursor;
+  bool m_old_cursor_valid;
+};
+
+} //namespace Glom
+
+#endif //BAKERY_UTILITIES_BUSYCURSOR_H

Modified: trunk/glom/libglom/connectionpool.cc
==============================================================================
--- trunk/glom/libglom/connectionpool.cc	(original)
+++ trunk/glom/libglom/connectionpool.cc	Tue Mar 17 10:46:53 2009
@@ -22,8 +22,10 @@
  
 #include <libglom/connectionpool.h>
 #include <libglom/document/document_glom.h>
-#include <bakery/bakery.h>
+#include <libglom/utils.h>
 //#include <libgdamm/connectionevent.h>
+#include <gtkmm/main.h>
+#include <gtkmm/messagedialog.h>
 #include <glibmm/i18n.h>
 
 #ifndef G_OS_WIN32
@@ -564,7 +566,7 @@
 #ifdef GLOM_ENABLE_MAEMO
         Hildon::Note dialog(Hildon::NOTE_TYPE_INFORMATION, error_details);
 #else
-        Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Internal error")), true, Gtk::MESSAGE_WARNING );
+        Gtk::MessageDialog dialog(Utils::bold_message(_("Internal error")), true, Gtk::MESSAGE_WARNING );
         dialog.set_secondary_text(error_details);
 #endif
         //TODO: dialog.set_transient_for(*get_application());
@@ -816,7 +818,7 @@
   if(!message.empty())
   {
 #ifndef GLOM_ENABLE_MAEMO
-    Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Running As Root")), true /* use_markup */, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true /* modal */);
+    Gtk::MessageDialog dialog(Utils::bold_message(_("Running As Root")), true /* use_markup */, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true /* modal */);
     dialog.set_secondary_text(message);
     dialog.run();
 #else
@@ -911,7 +913,7 @@
     connection_pool->m_dialog_epc_progress = 0;
   }
 
-  Gtk::MessageDialog* message_dialog = new Gtk::MessageDialog(Bakery::App_Gtk::util_bold_message(_("Glom: Generating Encryption Certificates")), true, Gtk::MESSAGE_INFO);
+  Gtk::MessageDialog* message_dialog = new Gtk::MessageDialog(Utils::bold_message(_("Glom: Generating Encryption Certificates")), true, Gtk::MESSAGE_INFO);
   message_dialog->set_secondary_text(_("Please wait while Glom prepares your system for publishing over the network."));
   message_dialog->show();
 

Modified: trunk/glom/libglom/connectionpool_backends/postgres.cc
==============================================================================
--- trunk/glom/libglom/connectionpool_backends/postgres.cc	(original)
+++ trunk/glom/libglom/connectionpool_backends/postgres.cc	Tue Mar 17 10:46:53 2009
@@ -22,7 +22,6 @@
 
 #include <libglom/connectionpool_backends/postgres.h>
 #include <glibmm/i18n.h>
-#include <bakery/bakery.h>
 
 #ifdef GLOM_ENABLE_MAEMO
 # include <hildonmm/note.h>
@@ -449,7 +448,7 @@
   const Glib::ustring message = _("Your installation of Glom is not complete, because the PostgreSQL libgda provider is not available on your system. This provider is needed to access Postgres database servers.\n\nPlease report this bug to your vendor, or your system administrator so it can be corrected.");
 #ifndef GLOM_ENABLE_MAEMO
   /* The Postgres provider was not found, so warn the user: */
-  Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Incomplete Glom Installation")), true /* use_markup */, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true /* modal */);
+  Gtk::MessageDialog dialog(Utils::bold_message(_("Incomplete Glom Installation")), true /* use_markup */, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true /* modal */);
   dialog.set_secondary_text(message);
   dialog.run();
 #else

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	Tue Mar 17 10:46:53 2009
@@ -22,7 +22,6 @@
 
 #include <libglom/connectionpool_backends/postgres_central.h>
 #include <glibmm/i18n.h>
-#include <bakery/bakery.h>
 
 // Uncomment to see debug messages
 //#define GLOM_CONNECTION_DEBUG

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	Tue Mar 17 10:46:53 2009
@@ -23,9 +23,9 @@
 #include <libglom/connectionpool_backends/postgres_self.h>
 #include <libglom/utils.h>
 #include <libglom/spawn_with_feedback.h>
+#include <giomm.h>
 #include <glib/gstdio.h> // For g_remove
 
-#include <bakery/bakery.h>
 #include <glibmm/i18n.h>
 
 #include "../gst-package.h"
@@ -162,7 +162,7 @@
   if(!binpath.empty())
   {
     const Glib::ustring uri_binpath = Glib::filename_to_uri(binpath);
-    if(Bakery::App_WithDoc::file_exists(uri_binpath))
+    if(Utils::file_exists(uri_binpath))
       return true;
   }
 
@@ -170,7 +170,7 @@
 
   //Show message to the user about the broken installation:
   //This is a packaging bug, but it would probably annoy packagers to mention that in the dialog:
-  Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Incomplete Glom Installation")), true /* use_markup */, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_NONE, true /* modal */);
+  Gtk::MessageDialog dialog(Utils::bold_message(_("Incomplete Glom Installation")), true /* use_markup */, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_NONE, true /* modal */);
   dialog.set_secondary_text(_("Your installation of Glom is not complete, because PostgreSQL is not available on your system. PostgreSQL is needed for self-hosting of Glom databases.\n\nYou may now install PostgreSQL to complete the Glom installation."));
   dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
   dialog.add_button(_("Install PostgreSQL"), Gtk::RESPONSE_OK);
@@ -183,7 +183,7 @@
   #else  //DISTRO_SPECIFIC_POSTGRES_INSTALL_IMPLEMENTED
 
   //Show message to the user about the broken installation:
-  Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Incomplete Glom Installation")), true /* use_markup */, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true /* modal */);
+  Gtk::MessageDialog dialog(Utils::bold_message(_("Incomplete Glom Installation")), true /* use_markup */, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true /* modal */);
   dialog.set_secondary_text(_("Your installation of Glom is not complete, because PostgreSQL is not available on your system. PostgreSQL is needed for self-hosting of Glom databases.\n\nPlease report this bug to your vendor, or your system administrator so it can be corrected."));
   dialog.run();
   return false;

Modified: trunk/glom/libglom/document/Makefile.am
==============================================================================
--- trunk/glom/libglom/document/Makefile.am	(original)
+++ trunk/glom/libglom/document/Makefile.am	Tue Mar 17 10:46:53 2009
@@ -1,3 +1,5 @@
+SUBDIRS = bakery
+
 AM_CPPFLAGS = -I top_srcdir@/ -I top_srcdir@/glom $(GLOM_CFLAGS)
 
 h_sources = document_glom.h view.h

Added: trunk/glom/libglom/document/bakery/Document.cc
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/Document.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,458 @@
+/*
+ * Copyright 2002 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+#include <libglom/document/bakery/Document.h>
+#include <giomm.h>
+//#include <fstream>
+#include <glibmm/i18n-lib.h>
+
+namespace GlomBakery
+{
+
+const guint BYTES_TO_PROCESS = 256;
+
+Document::Document()
+{
+  m_bIsNew = true;
+  m_bModified = false;
+  m_bReadOnly = false;
+  m_pView = 0;
+}
+
+Document::~Document()
+{
+  //Tell views to forget the document -  to null their pointers to it. We should maybe use the Document via a sharing smartpointer instead.
+  signal_forget_.emit();
+}
+
+Glib::ustring Document::get_file_uri() const
+{
+  return m_file_uri;
+}
+
+Glib::ustring Document::get_file_uri_with_extension(const Glib::ustring& uri)
+{
+  Glib::ustring result = uri;
+
+  //Enforce file extension:
+  if(!m_file_extension.empty())  //If there is an extension to enforce.
+  {
+    bool bAddExt = false;
+    Glib::ustring strExt = "." + get_file_extension();
+
+    if(result.size() < strExt.size()) //It can't have the ext already if it's not long enough.
+    {
+      bAddExt = true; //It isn't there already.
+    }
+    else
+    {
+      Glib::ustring strEnd = result.substr(result.size() - strExt.size());
+      if(strEnd != strExt) //If it doesn't already have the extension
+        bAddExt = true;
+    }
+
+    //Add extension if necessay.
+    if(bAddExt)
+      result += strExt;
+
+    //Note that this does not replace existing extensions, so it could be e.g. 'something.blah.theext'
+  }
+
+  return result;
+}
+
+void Document::set_file_uri(const Glib::ustring& file_uri, bool bEnforceFileExtension /* = false */)
+{
+  if(file_uri != m_file_uri)
+    set_modified(); //Ready to save() for a Save As.
+
+  m_file_uri = file_uri;
+
+  //Enforce file extension:
+  if(bEnforceFileExtension)
+    m_file_uri = get_file_uri_with_extension(m_file_uri);
+}
+
+void Document::set_contents(const Glib::ustring& strVal)
+{
+  m_strContents = strVal;
+}
+
+Glib::ustring Document::get_contents() const
+{
+  return m_strContents;
+}
+
+void Document::set_modified(bool bVal /* = true */)
+{
+  m_bModified = bVal;
+
+  if(m_bModified)
+  {
+    m_bIsNew = false; //Can't be new if it's been modified.
+  }
+
+  //Allow the application or view to update it's UI accordingly:
+  signal_modified().emit(m_bModified);
+}
+
+bool Document::get_modified() const
+{
+  return m_bModified;
+}
+
+bool Document::load()
+{
+  bool bTest = read_from_disk();
+  if(bTest)
+  {
+    bTest = load_after(); //may be overridden.
+    if(bTest)
+    {
+      //Tell the View to show the new data:
+      if(m_pView)
+        m_pView->load_from_document();
+    }
+  }
+
+  return bTest;
+}
+
+bool Document::load_from_data(const guchar* data, std::size_t length)
+{
+  if(!data || !length)
+    return false;
+
+  m_strContents = Glib::ustring((char*)data, length);
+ 
+  const bool bTest = load_after(); //may be overridden.
+  if(bTest)
+  {
+    //Tell the View to show the new data:
+    if(m_pView)
+      m_pView->load_from_document();
+  }
+
+  return bTest;
+}
+
+
+
+bool Document::load_after()
+{
+  //Called after text is read from disk, but before updating view.
+
+  //Override this if necessary.
+  //For instance, Document_XML parses the XML.
+
+  return true;
+}
+
+bool Document::save()
+{
+  //Tell the view to update the data in this document.
+  if(m_pView)
+    m_pView->save_to_document();
+
+  const bool bTest = save_before(); //This could be overridden.
+  if(bTest)
+    return write_to_disk();
+
+  return bTest;
+}
+
+bool Document::save_before()
+{
+  //Called after view saves itself to document, but before writing to disk.
+
+  //Override this if necessary.
+  //For instance, Document_XML serializes its XML to text.
+
+  return true;
+}
+
+bool Document::read_from_disk()
+{
+  m_strContents.erase();
+
+  // Open the input file for read access:
+  Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(m_file_uri);
+  Glib::RefPtr<Gio::FileInputStream> stream;
+
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  try
+  {
+    stream = file->read();
+  }
+  catch(const Gio::Error& ex)
+  {
+    // If the operation was not successful, print the error and abort
+    return false; //print_error(ex, input_uri_string);
+  }
+#else
+  std::auto_ptr<Gio::Error> error;
+  Glib::RefPtr<FileInputStream> stream = file.read(error);
+  if(error.get() != NULL)
+    return false; //print_error(ex, input_uri_string);
+#endif
+
+  // Read data from the input uri:
+  guint buffer[BYTES_TO_PROCESS] = {0, }; // For each chunk.
+  gsize bytes_read = 0;
+  std::string data; //We use a std::string because we might not get whole UTF8 characters at a time. This might not be necessary.
+
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  try
+#endif
+  {
+    bool bContinue = true;
+    while(bContinue)
+    {
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+      bytes_read = stream->read(buffer, BYTES_TO_PROCESS);
+#else
+      bytes_read = stream->read(buffer, BYTES_TO_PROCESS, error);
+      if(error.get() != NULL) break;
+#endif
+
+      if(bytes_read == 0)
+        bContinue = false; //stop because we reached the end.
+      else
+      {
+        // Add the text to the string:
+        data += std::string((char*)buffer, bytes_read);
+      }
+    }
+  }
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  catch(const Gio::Error& ex)
+  {
+#else
+  if(error.get() != NULL)
+  {
+    Gio::Error& ex = *error.get();
+#endif
+    // If the operation was not successful, print the error and abort
+    return false; //print_error(ex, input_uri_string);
+  }
+
+  m_strContents = data;
+
+  set_modified(false);
+
+  return true; //Success.
+}
+
+bool Document::write_to_disk()
+{
+  //Write the changed data to disk:
+  if(get_modified())
+  {
+    Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(m_file_uri);
+    Glib::RefPtr<Gio::FileOutputStream> stream;
+
+    //Create the file if it does not already exist:
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+    try
+    {
+      if(file->query_exists())
+      {
+        stream = file->replace(); //Instead of append_to().
+      }
+      else
+      {
+        //By default files created are generally readable by everyone, but if we pass FILE_CREATE_PRIVATE in flags the file will be made readable only to the current user, to the level that is supported on the target filesystem.
+        //TODO: Do we want to specify 0660 exactly? (means "this user and his group can read and write this non-executable file".)
+        stream = file->create_file();
+      }
+    }
+    catch(const Gio::Error& ex)
+    {
+#else
+    std::auto_ptr<Gio::Error> error;
+    stream.create(error);
+    if(error.get() != NULL)
+    {
+      const Gio::Error& ex = *error.get();
+#endif
+     // If the operation was not successful, print the error and abort
+     return false; // print_error(ex, output_uri_string);
+    }
+
+
+    if(!stream)
+      return false;
+
+
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+    try
+    {
+      //Write the data to the output uri
+      const gsize bytes_written = stream->write(m_strContents.data(), m_strContents.bytes());
+
+      //Close the stream to make sure that the write really happens 
+      //even with glibmm 2.16.0 which had a refcount leak that stopped it.
+      stream->close();
+      stream.reset();
+    }
+    catch(const Gio::Error& ex)
+    {
+#else
+    const gsize bytes_written = stream->write(m_strContents.data(), m_strContents.bytes(), error);
+    if(error.get() != NULL)
+    {
+      Gio::Error& ex = *error.get();
+#endif
+      // If the operation was not successful, print the error and abort
+      return false; //print_error(ex, output_uri_string);
+    }
+
+    return true; //Success. (At doing nothing, because nothing needed to be done.)
+  }
+  else
+    return true; //Success. (At doing nothing, because nothing needed to be done.)
+}
+
+Glib::ustring Document::get_name() const
+{
+  return util_file_uri_get_name(m_file_uri, m_file_extension);
+}
+
+Glib::ustring Document::util_file_uri_get_name(const Glib::ustring& file_uri, const Glib::ustring& file_extension)
+{
+  Glib::ustring strResult = Glib::filename_display_basename(file_uri);
+
+  //Remove the file extension:
+  //TODO: Maybe filename_display_basename() should do this.
+  if(!strResult.empty() && !file_extension.empty())
+  {
+    const Glib::ustring strExt = "." + file_extension;
+
+    if(strResult.size() >= file_extension.size()) //It can't have the ext already if it's not long enough.
+    {
+      Glib::ustring strEnd = strResult.substr(strResult.size() - strExt.size());
+      if(strEnd == strExt) //If it has the extension
+      {
+        strResult = strResult.substr(0, strResult.size() - strExt.size());
+      }
+    }
+  }
+
+  //Show untitled explicitly:
+  //Also happens for file_uris with path but no name. e.g. /sub/sub/, which shouldn't happen.
+  if(strResult.empty())
+    strResult = _("Untitled");
+
+  return strResult;
+}
+
+void Document::set_view(ViewBase* pView)
+{
+  m_pView = pView;
+}
+
+ViewBase* Document::get_view()
+{
+  return m_pView;
+}
+
+bool Document::get_read_only() const
+{
+  if(m_bReadOnly)
+  {
+    //An application might have used set_read_only() to make this document explicitly read_only, regardless of the positions of the storage location.
+    return true;
+  }
+  else
+  {
+    if(m_file_uri.empty())
+      return false; //It must be a default empty document, not yet saved, so it is not read-only.
+    else
+    {
+      Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(m_file_uri);
+      Glib::RefPtr<Gio::FileInfo> info;
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+      try
+      {
+        Glib::RefPtr<Gio::FileInfo> info = file->query_info(G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+      }
+      catch(const Gio::Error& ex)
+      {
+        return false; //We should at least be able to read the permissions, so maybe the location is invalid. I'm not sure what the best return result here is.
+      }
+#else
+      std::auto_ptr<Gio::Error> error;
+      info = file.query_info(G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, Gio::FILE_QUERY_INFO_NONE, error);
+      if(error.get() != NULL)
+        return false;
+#endif
+
+      if(!info)
+        return false;
+
+      const bool read_only = info->get_attribute_boolean(G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+      return read_only;
+    }
+  }
+
+  return m_bReadOnly;
+}
+
+void Document::set_read_only(bool bVal)
+{
+  m_bReadOnly = bVal;
+}
+
+bool Document::get_is_new() const
+{
+  return m_bIsNew;
+}
+
+void Document::set_is_new(bool bVal)
+{
+  if(bVal)
+    set_modified(false); //can't be modified if it is new.
+
+  m_bIsNew = bVal;
+}
+
+void Document::set_file_extension(const Glib::ustring& strVal)
+{
+  m_file_extension = strVal;
+}
+
+Glib::ustring Document::get_file_extension() const
+{
+  return m_file_extension; //TODO: get it from the mime-type system?
+}
+
+Document::type_signal_modified& Document::signal_modified()
+{
+  return signal_modified_;
+}
+
+Document::type_signal_forget& Document::signal_forget()
+{
+  return signal_forget_;
+}
+
+
+
+
+} //namespace

Added: trunk/glom/libglom/document/bakery/Document.h
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/Document.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_DOCUMENT_H
+#define BAKERY_DOCUMENT_H
+
+#include <glibmm.h>
+#include <libglom/document/bakery/view/ViewBase.h>
+#include <iostream>
+
+namespace GlomBakery
+{
+
+/** The Document is like the 'Model' in the Model-View-Controller framework.
+ * Each App should have a Document.
+ * Each View gets and sets data in its document.
+ */
+class Document
+{
+public: 
+  Document();
+  virtual ~Document();
+
+  /* Saves the data to disk.
+   * Asks the View to update this document before saving to disk,
+   * but you should probably ensure that the document is updated more regularly than this,
+   * so that different parts of the GUI are synchronized.
+   * Only saves if the document has been modified.
+   * bool indicates success.
+   */
+  bool save();
+
+  /* Loads data from disk, using the URI (set with set_file_uri()) then asks the View to update itself.
+   * bool indicates success.
+   */
+  bool load();
+
+  //This can't be virtual because that would break ABI.
+  //Hopefully it doesn't need to be.
+  /* Loads data from disk, using the URI (set with set_file_uri()) then asks the View to update itself.
+   * bool indicates success.
+   */
+  bool load_from_data(const guchar* data, std::size_t length);
+
+
+  virtual bool get_modified() const;
+  virtual void set_modified(bool bVal = true);
+
+  ///Whether this just a default document.
+  virtual bool get_is_new() const;
+  ///Called by App_WithDoc::init_create_document().
+  void set_is_new(bool bVal);
+
+  virtual Glib::ustring get_contents() const;
+  virtual void set_contents(const Glib::ustring& strVal);
+
+  virtual Glib::ustring get_file_uri_with_extension(const Glib::ustring& uri);
+
+  virtual Glib::ustring get_file_uri() const;
+  virtual void set_file_uri(const Glib::ustring& file_uri, bool bEnforceFileExtension = false);
+
+  ///Gets filename part of file_uri, or 'untitled'.
+  virtual Glib::ustring get_name() const;
+  static Glib::ustring util_file_uri_get_name(const Glib::ustring& file_uri, const Glib::ustring& file_extension);
+
+  virtual bool get_read_only() const;
+  virtual void set_read_only(bool bVal);
+
+  ///If you don't want to use a View, then don't use set_view().
+  virtual void set_view(ViewBase* pView);
+  virtual ViewBase* get_view();
+
+  virtual void set_file_extension(const Glib::ustring& strVal);
+  virtual Glib::ustring get_file_extension() const;
+
+  //Signals
+  /** For instance, void on_document_modified(bool modified);
+   */
+  typedef sigc::signal<void, bool> type_signal_modified;
+
+  /** This signal is emitted when the document has been modified.
+   * It allows the view to update itself to show the new information.
+   */
+  type_signal_modified& signal_modified();
+
+  typedef sigc::signal<void> type_signal_forget;
+
+  /** This signal is emitted when the view should forget the document.
+   * This is used internally, and you should not need to use it yourself.
+   */
+  type_signal_forget& signal_forget();
+
+  ///Allow app to update icons/title bar.
+
+protected:
+  /** overrideable.
+   * Does anything which should be done after the data has been loaded from disk, but before updating the View.
+   */
+  virtual bool load_after();
+
+  /** overrideable.
+   * Does anything which should be done before the view has saved its data, before writing to disk..
+   */
+  virtual bool save_before();
+
+  virtual bool read_from_disk();
+  virtual bool write_to_disk();
+
+  Glib::ustring m_strContents;
+  Glib::ustring m_file_uri;
+  Glib::ustring m_file_extension;
+
+  ViewBase* m_pView;
+
+  type_signal_modified signal_modified_;
+  type_signal_forget signal_forget_;
+  
+  bool m_bModified;
+  bool m_bIsNew; //see get_is_new().
+  bool m_bReadOnly;
+};
+
+} //namespace
+
+#endif //GNOME_APPWITHDOCS_DOCUMENT_H

Added: trunk/glom/libglom/document/bakery/Document_XML.cc
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/Document_XML.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2000-2002 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <libglom/document/bakery/Document_XML.h>
+
+
+namespace GlomBakery
+{
+
+
+Document_XML::Document_XML()
+: m_pDOM_Document(0),
+  m_write_formatted(false)
+{
+}
+
+Document_XML::~Document_XML()
+{
+  //m_pDOM_Document is owned by m_DOM_Document;
+}
+
+bool Document_XML::load_after()
+{
+  bool bTest = type_base::load_after();
+  if(!bTest)
+    return false; //Failed.
+
+#ifdef LIBXMLPP_EXCEPTIONS_ENABLED
+  try
+#endif
+  {
+    //Link the parser to the XML text that was loaded:
+    //m_DOM_Parser.setDoValidation(true);
+
+    if(m_strContents.empty())
+      g_warning("Document_XML::load_after(): parsing empty document.");
+
+    m_DOM_Parser.parse_memory(m_strContents);
+    m_pDOM_Document = m_DOM_Parser.get_document();
+    if(!m_pDOM_Document) return false;
+
+    return true; //Success.
+  }
+#ifdef LIBXMLPP_EXCEPTIONS_ENABLED
+  catch(const std::exception& ex)
+  {
+    std::cerr << "XML Parser error: \n" << ex.what() << std::endl;
+
+    return false; //Failed.
+  }
+#endif
+}
+
+
+bool Document_XML::save_before()
+{
+  if(get_modified())
+  {
+    //Write XML to string:
+    m_strContents.erase();
+
+    Util_DOM_Write(m_strContents);
+
+    //Save the XML string:
+    return type_base::save_before();
+  }
+  else
+  {
+    return true; //Success. (At doing nothing, because nothing needed to be done.)
+  }
+}
+
+bool Document_XML::set_xml(const Glib::ustring& strXML)
+{ 
+#ifdef LIBXMLPP_EXCEPTIONS_ENABLED
+  try
+#endif
+  {
+    if(m_strContents.empty())
+      g_warning("Document_XML::set_xml(): parsing empty document.");
+
+    m_DOM_Parser.parse_memory(m_strContents);
+    m_pDOM_Document = m_DOM_Parser.get_document();
+    if(!m_pDOM_Document) return false;
+
+    return true;	
+  }
+#ifdef LIBXMLPP_EXCEPTIONS_ENABLED
+  catch(const std::exception& ex)
+  {
+    std::cerr << "XML Parser error: \n" << ex.what() << std::endl;
+    return false; //Failed.
+  }
+#endif
+} 
+
+
+Glib::ustring Document_XML::get_xml() const
+{
+  //Write XML to string:
+  Glib::ustring strXML;
+  Util_DOM_Write(strXML);
+  return strXML;
+}
+
+void Document_XML::Util_DOM_Write(Glib::ustring& refstrXML) const
+{
+#ifdef LIBXMLPP_EXCEPTIONS_ENABLED
+  try
+#endif
+  {
+    if(m_write_formatted)
+      refstrXML = m_pDOM_Document->write_to_string_formatted();
+    else
+      refstrXML = m_pDOM_Document->write_to_string();
+  }
+#ifdef LIBXMLPP_EXCEPTIONS_ENABLED
+  catch(xmlpp::exception& ex)
+  {
+    std::cerr << "Document_XML::Util_DOM_Write(): exception caught: " << ex.what() << std::endl;
+  }
+#endif
+}
+
+Glib::ustring Document_XML::get_node_attribute_value(const xmlpp::Element* node, const Glib::ustring& strAttributeName)
+{
+  if(node)
+  {
+    const xmlpp::Attribute* attribute = node->get_attribute(strAttributeName);
+    if(attribute)
+    {
+      Glib::ustring value = attribute->get_value(); //Success.
+      return value;
+    }
+  }
+
+  return ""; //Failed.
+}
+
+void Document_XML::set_node_attribute_value(xmlpp::Element* node, const Glib::ustring& strAttributeName, const Glib::ustring& strValue)
+{
+  if(node)
+  {
+    xmlpp::Attribute* attribute = node->get_attribute(strAttributeName);
+    if(attribute)
+      attribute->set_value(strValue);
+    else
+    {
+      if(!strValue.empty()) //Don't add an attribute if the value is empty, to keep the document smaller.
+        node->set_attribute(strAttributeName, strValue);
+    }
+  }
+}
+
+xmlpp::Element* Document_XML::get_node_child_named(const xmlpp::Element* node, const Glib::ustring& strName)
+{
+  xmlpp::Element* nodeResult = 0;
+
+  if(node)
+  { 
+    xmlpp::Node::NodeList list = node->get_children(strName);
+
+    //We check all of them, instead of just the first, until we find one,
+    //because get_children() returns, for instance, TextNodes (which are not Elements) for "text", 
+    //as well as Elements with the name "text".
+    for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
+    {
+      nodeResult = dynamic_cast<xmlpp::Element*>(*iter);  
+      if(nodeResult)
+        return nodeResult;
+    }                       
+  }
+
+  return nodeResult;
+}
+
+xmlpp::Element* Document_XML::get_node_child_named_with_add(xmlpp::Element* node, const Glib::ustring& strName)
+{
+  xmlpp::Element* nodeResult = get_node_child_named(node, strName);
+
+  if(!nodeResult)
+    nodeResult = node->add_child(strName);
+
+  return nodeResult;
+}
+
+void Document_XML::set_dtd_name(const std::string& strVal)
+{
+  m_strDTD_Name = strVal;
+}
+
+std::string Document_XML::get_dtd_name() const
+{
+  return m_strDTD_Name;
+}
+
+void Document_XML::set_dtd_root_node_name(const Glib::ustring& strVal)
+{
+  m_strRootNodeName = strVal;
+}
+
+Glib::ustring Document_XML::get_dtd_root_node_name() const
+{
+  return m_strRootNodeName;
+}
+
+
+const xmlpp::Element* Document_XML::get_node_document() const
+{
+  //Call the non-const overload:
+  return const_cast<Document_XML*>(this)->get_node_document();
+}
+
+xmlpp::Element* Document_XML::get_node_document()
+{
+  if(!m_pDOM_Document)
+    m_pDOM_Document = m_DOM_Parser.get_document();
+  
+  xmlpp::Element* nodeRoot = m_pDOM_Document->get_root_node();
+  if(!nodeRoot)
+  {
+    //Add it if it isn't there already:
+    return m_pDOM_Document->create_root_node(m_strRootNodeName);
+  }
+  else
+    return nodeRoot;
+}
+
+void Document_XML::set_write_formatted(bool formatted)
+{
+  m_write_formatted = formatted;
+}
+
+
+void Document_XML::add_indenting_white_space_to_node(xmlpp::Node* node, const Glib::ustring& start_indent)
+{
+  if(!node)
+    node = get_node_document();
+
+  //Remove any previous indenting:
+  {
+  xmlpp::Node::NodeList list = node->get_children();
+  for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
+  {
+    xmlpp::Node* child = *iter;
+    if(!child)
+      continue;
+
+    xmlpp::ContentNode* text = dynamic_cast<xmlpp::ContentNode*>(child);
+    if(text)
+    {
+      if(text->is_white_space())
+        node->remove_child(text);
+    }
+  }
+  }
+
+  //All indents have a newline, 
+  //and we add spaces each time we recurse:
+  Glib::ustring indent = start_indent;
+  if(indent.empty())
+    indent = "\n  ";
+  else
+    indent += "  ";
+
+  //Add indenting text items:
+  bool had_children = false;
+  xmlpp::Element* node_as_element = dynamic_cast<xmlpp::Element*>(node);
+  xmlpp::Node::NodeList list = node_as_element->get_children();
+  for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
+  {
+    xmlpp::Node* child = *iter;
+    if(!child)
+      continue;
+
+    xmlpp::ContentNode* text = dynamic_cast<xmlpp::ContentNode*>(child);
+    if(text)
+    {
+      if(!text->is_white_space())
+        continue; //Don't change content items.
+    }
+
+    //Add a text item for the indenting, before the child:
+    //std::cout << "  Adding indent after node=" << child->get_name() << ": START" << indent << "END" << std::endl;
+    node_as_element->add_child_text_before(child, indent);
+    had_children = true;
+
+    //Recurse into the children:
+    add_indenting_white_space_to_node(child, indent);
+  }
+
+  //If it has children then add an indent before the closing tag:
+  if(had_children)
+    node_as_element->add_child_text(start_indent);
+}
+
+
+} //namespace GlomBakery.

Added: trunk/glom/libglom/document/bakery/Document_XML.h
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/Document_XML.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2002 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_DOCUMENT_XML_H
+#define BAKERY_DOCUMENT_XML_H
+
+#include <libglom/document/bakery/Document.h>
+#include <libxml++/libxml++.h>
+
+//Features:
+//- Read/Write to the Document in terms of XML DOM.
+
+//Future features:
+//- Parse the document from disk instad of memory - This *might* allow for very large documents.
+
+namespace GlomBakery
+{
+
+class Document_XML : public GlomBakery::Document
+{
+public: 
+  Document_XML();
+  virtual ~Document_XML();
+
+  //overrides:
+  virtual bool load_after();
+  virtual bool save_before();
+
+  virtual void set_dtd_name(const std::string& strVal); //e.g. "glom.dtd"
+  virtual std::string get_dtd_name() const;
+
+  virtual void set_dtd_root_node_name(const Glib::ustring& strVal);
+  virtual Glib::ustring get_dtd_root_node_name() const;
+
+  /** Whether to add extra whitespace when writing the XML to disk.
+   * Do not use this if whitespace is significant in your XML format.
+   * See also add_indenting_white_space().
+   */
+  void set_write_formatted(bool formatted = true);
+
+  /** Put each node on its own line and add white space for indenting,
+   * even if there are child text nodes.
+   * set_write_formatted() does not cause nodes to be indented if there are child text nodes,
+   * because it assumes that the white space is then significant.
+   */
+  void add_indenting_white_space();
+  
+  virtual bool set_xml(const Glib::ustring& strXML); //Parse the XML from the text.
+  virtual Glib::ustring get_xml() const; //Get the text for the XML.
+
+protected:
+  static Glib::ustring get_node_attribute_value(const xmlpp::Element* node, const Glib::ustring& strAttributeName);
+  static void set_node_attribute_value(xmlpp::Element* node, const Glib::ustring& strAttributeName, const Glib::ustring& strValue);
+
+  static xmlpp::Element* get_node_child_named(const xmlpp::Element* node, const Glib::ustring& strName);
+  static xmlpp::Element* get_node_child_named_with_add(xmlpp::Element* node, const Glib::ustring& strName);
+
+  virtual const xmlpp::Element* get_node_document() const; //e.g. <glom_document> (root name)
+  virtual xmlpp::Element* get_node_document(); //e.g. <glom_document> (root name)
+
+  virtual void Util_DOM_Write(Glib::ustring& refstrXML) const;
+
+  void add_indenting_white_space_to_node(xmlpp::Node* node = 0, const Glib::ustring& start_indent = Glib::ustring());
+
+  typedef GlomBakery::Document type_base;
+
+  //XML Parsing bits:
+  xmlpp::DomParser m_DOM_Parser; //Could be mutable to allow us to guarantee a root node.
+  xmlpp::Document* m_pDOM_Document; //1-to-1 with the m_DOM_Parser.
+  
+  std::string m_strDTD_Name;
+  Glib::ustring m_strRootNodeName;
+  bool m_write_formatted;
+};
+
+} //namespace GlomBakery.
+
+#endif // BAKERY_DOCUMENT_XML_H

Added: trunk/glom/libglom/document/bakery/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/Makefile.am	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,15 @@
+SUBDIRS = view
+
+AM_CPPFLAGS = -I top_srcdir@/ -I top_srcdir@/glom $(GLOM_CFLAGS)
+
+h_sources = Document.h Document_XML.h
+cc_sources = Document.cc Document_XML.cc
+
+noinst_LTLIBRARIES = libdocument_bakery.la
+libdocument_bakery_la_SOURCES = $(h_sources) $(cc_sources)
+
+ 
+
+
+
+

Added: trunk/glom/libglom/document/bakery/view/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/view/Makefile.am	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,16 @@
+SUBDIRS = 
+
+gladedir = $(datadir)/glom/glade/
+
+# We define GLOM_GLADEDIR so that we can get the installed .glade file at runtime.
+# We define PREFIX, SYSCONFDIR, LIBDIR, and DATADIR for the GNOME_PROGRAM_STANDARD_PROPERTIES macro.
+AM_CPPFLAGS = -I top_srcdir@/ -I top_srcdir@/glom $(GLOM_CFLAGS) $(PYTHON_INCLUDES) \
+           -DGLOM_GLADEDIR=\""$(gladedir)/"\"
+
+
+h_sources = View.h ViewBase.h View_Composite.h 
+cc_sources = View.cc ViewBase.cc View_Composite.cc 
+
+noinst_LTLIBRARIES = libdocument_bakery_view.la
+libdocument_bakery_view_la_SOURCES = $(h_sources) $(cc_sources)
+

Added: trunk/glom/libglom/document/bakery/view/View.cc
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/view/View.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <libglom/document/bakery/view/View.h>
+
+namespace GlomBakery
+{
+
+
+} //namespace

Added: trunk/glom/libglom/document/bakery/view/View.h
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/view/View.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_VIEW_H
+#define BAKERY_VIEW_H
+
+#include "ViewBase.h"
+#include <libglom/document/bakery/Document.h>
+#include <sigc++/sigc++.h>
+
+namespace GlomBakery
+{
+
+/** This is a base class which should be multiple-inherited with gtkmm widgets.
+  * You should override save_to_document() and load_from_document().
+  */
+template< class T_Document >
+class View : public ViewBase
+{
+public: 
+  View()
+  : m_pDocument(0)
+  {
+  }
+
+  virtual ~View()
+  {
+  }
+
+  typedef View<T_Document> type_self;
+
+  //typedef typename T_Document type_document;
+
+  virtual T_Document* get_document()
+  {
+    return m_pDocument;
+  }
+
+  virtual const T_Document* get_document() const
+  {
+    return m_pDocument;
+  }
+
+  virtual void set_document(T_Document* pDocument)
+  {
+    m_pDocument = pDocument;
+    if(m_pDocument)
+      m_pDocument->signal_forget().connect( sigc::mem_fun(*this, &type_self::on_document_forget) );
+  }
+
+  ///Just a convenience, instead of get_docuement()->set_modified().
+  virtual void set_modified(bool val = true)
+  {
+    if(m_pDocument)
+      m_pDocument->set_modified(val);
+  }
+
+protected:
+
+  void on_document_forget()
+  {
+    //This should prevent some segfaults:
+    m_pDocument = 0;
+  }
+  
+  T_Document* m_pDocument;
+};
+
+} //namespace
+
+#endif //BAKERY_VIEW_H
+

Added: trunk/glom/libglom/document/bakery/view/ViewBase.cc
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/view/ViewBase.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <libglom/document/bakery/view/ViewBase.h>
+
+namespace GlomBakery
+{
+
+ViewBase::ViewBase()
+{
+}
+
+ViewBase::~ViewBase()
+{
+}
+
+void ViewBase::load_from_document()
+{
+}
+
+void ViewBase::save_to_document()
+{
+}
+
+void ViewBase::clipboard_copy()
+{
+}
+
+void ViewBase::clipboard_paste()
+{
+}
+
+void ViewBase::clipboard_clear()
+{
+}
+
+} //namespace

Added: trunk/glom/libglom/document/bakery/view/ViewBase.h
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/view/ViewBase.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_VIEWBASE_H
+#define BAKERY_VIEWBASE_H
+
+#include <sigc++/trackable.h>
+
+namespace GlomBakery
+{
+
+/** This is a base class for View.
+ * This allows the App to call load_from_document() and save_to_document(),
+ * without knowing exactly what type of document the view uses.
+ */
+class ViewBase : virtual public sigc::trackable
+{
+public: 
+  ViewBase();
+  virtual ~ViewBase();
+  
+  virtual void load_from_document();
+  virtual void save_to_document();
+
+  //Override these:
+  virtual void clipboard_copy();
+  virtual void clipboard_paste();
+  virtual void clipboard_clear();
+};
+
+} //namespace
+
+#endif

Added: trunk/glom/libglom/document/bakery/view/View_Composite.cc
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/view/View_Composite.cc	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <libglom/document/bakery/view/View_Composite.h>
+
+namespace GlomBakery
+{
+
+
+
+} //namespace

Added: trunk/glom/libglom/document/bakery/view/View_Composite.h
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/bakery/view/View_Composite.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000 Murray Cumming
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef BAKERY_VIEW_COMPOSITE_H
+#define BAKERY_VIEW_COMPOSITE_H
+
+#include <libglom/document/bakery/view/View.h>
+#include <vector>
+#include <algorithm> //For std::find
+
+namespace GlomBakery
+{
+
+/** This View delegates to sub-views.
+ * It is very simplistic - maybe your View should be more intelligent.
+ */
+template< class T_Document >
+class View_Composite : public View<T_Document>
+{
+public: 
+  View_Composite()
+  {
+  }
+
+  virtual ~View_Composite()
+  {
+  }
+
+  typedef View<T_Document> type_view;
+
+  virtual void add_view(type_view* pView)
+  {
+    //Ensure that the view has the same document:
+    //This should be unnecessary.
+    if(pView)
+    {
+      pView->set_document(View<T_Document>::get_document());
+
+      //Add it to the list of child views:
+      m_vecViews.push_back(pView);
+    }
+  }
+
+  virtual void remove_view(type_view* pView)
+  {
+    typename type_vecViews::iterator iter = std::find(m_vecViews.begin(), m_vecViews.end(), pView);
+    if(iter != m_vecViews.end())
+      m_vecViews.erase(iter);
+  }
+
+  virtual void set_document(T_Document* pDocument)
+  {
+    //Call base class:
+    View<T_Document>::set_document(pDocument);
+
+    //Change the document in the child views.
+    for(typename type_vecViews::iterator iter = m_vecViews.begin(); iter != m_vecViews.end(); iter++)
+    {
+      type_view* pView = *iter;
+      if(pView)
+        pView->set_document(pDocument);
+    }
+  }
+
+  virtual void load_from_document()
+  {
+    //Delegate to the child views:
+    for(typename type_vecViews::iterator iter = m_vecViews.begin(); iter != m_vecViews.end(); iter++)
+    {
+      type_view* pView = *iter;
+      if(pView)
+        pView->load_from_document();
+    }
+  }
+
+  virtual void save_to_document()
+  {
+    //Delegate to the child views:
+    for(typename type_vecViews::iterator iter = m_vecViews.begin(); iter != m_vecViews.end(); iter++)
+    {
+      type_view* pView = *iter;
+      if(pView)
+        pView->save_to_document();
+    }
+  }
+
+protected:
+  typedef std::vector<type_view*> type_vecViews;
+  type_vecViews m_vecViews;    
+};
+
+} //namespace
+
+#endif

Modified: trunk/glom/libglom/document/document_glom.cc
==============================================================================
--- trunk/glom/libglom/document/document_glom.cc	(original)
+++ trunk/glom/libglom/document/document_glom.cc	Tue Mar 17 10:46:53 2009
@@ -33,7 +33,7 @@
 #include <libglom/data_structure/layout/layoutitem_line.h>
 #include <libglom/standard_table_prefs_fields.h>
 #include <giomm.h>
-#include <bakery/Utilities/BusyCursor.h>
+#include <libglom/busy_cursor.h>
 
 #include <libglom/connectionpool.h>
 
@@ -1838,7 +1838,7 @@
 
   //if(value != get_modified()) //Prevent endless loops
   //{
-    Bakery::Document_XML::set_modified(value);
+    GlomBakery::Document_XML::set_modified(value);
 
     if(value)
     {
@@ -2306,13 +2306,13 @@
 {
   //Use a std::auto_ptr<> to avoid even unncessarily instantiating a BusyCursor,
   //which would require GTK+ to be initialized:
-  std::auto_ptr<Bakery::BusyCursor> auto_cursor;
+  std::auto_ptr<BusyCursor> auto_cursor;
   if(m_parent_window)
-    auto_cursor = std::auto_ptr<Bakery::BusyCursor>( new Bakery::BusyCursor(m_parent_window) );
+    auto_cursor = std::auto_ptr<BusyCursor>( new BusyCursor(m_parent_window) );
 
   m_block_modified_set = true; //Prevent the set_ functions from trigerring a save.
 
-  bool result = Bakery::Document_XML::load_after();  
+  bool result = GlomBakery::Document_XML::load_after();  
 
   m_block_cache_update = true; //Don't waste time repeatedly updating this until we have finished.
 
@@ -3199,9 +3199,9 @@
 {
   //Use a std::auto_ptr<> to avoid even unncessarily instantiating a BusyCursor,
   //which would require GTK+ to be initialized:
-  std::auto_ptr<Bakery::BusyCursor> auto_cursor;
+  std::auto_ptr<BusyCursor> auto_cursor;
   if(m_parent_window)
-    auto_cursor = std::auto_ptr<Bakery::BusyCursor>( new Bakery::BusyCursor(m_parent_window) );
+    auto_cursor = std::auto_ptr<BusyCursor>( new BusyCursor(m_parent_window) );
 
   xmlpp::Element* nodeRoot = get_node_document();
 
@@ -3507,7 +3507,7 @@
   //We don't use set_write_formatted() because it doesn't handle text nodes well.
   add_indenting_white_space_to_node();
 
-  return Bakery::Document_XML::save_before();  
+  return GlomBakery::Document_XML::save_before();  
 }
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
@@ -3529,7 +3529,7 @@
 {
   //Show the database title in the window title bar:
   if(m_database_title.empty())
-    return Bakery::Document_XML::get_name();
+    return GlomBakery::Document_XML::get_name();
   else
     return m_database_title;
 }

Modified: trunk/glom/libglom/document/document_glom.h
==============================================================================
--- trunk/glom/libglom/document/document_glom.h	(original)
+++ trunk/glom/libglom/document/document_glom.h	Tue Mar 17 10:46:53 2009
@@ -23,8 +23,7 @@
 
 #include <libglom/libglom_config.h> // For GLOM_ENABLE_CLIENT_ONLY, GLOM_ENABLE_SQLITE
 
-#include <bakery/Document/Document_XML.h>
-#include <bakery/View/View_Composite.h>
+#include <libglom/document/bakery/Document_XML.h>
 #include <libglom/data_structure/relationship.h>
 #include <libglom/data_structure/field.h>
 #include <libglom/data_structure/layout/layoutgroup.h>
@@ -67,7 +66,7 @@
 namespace Glom
 {
 
-class Document_Glom : public Bakery::Document_XML
+class Document_Glom : public GlomBakery::Document_XML
 {
 public: 
   Document_Glom();

Added: trunk/glom/libglom/document/view.h
==============================================================================
--- (empty file)
+++ trunk/glom/libglom/document/view.h	Tue Mar 17 10:46:53 2009
@@ -0,0 +1,37 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2009 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 DOCUMENT_GLOM_VIEW_H
+#define DOCUMENT_GLOM_VIEW_H
+
+#include <libglom/document/document_glom.h>
+#include <libglom/document/bakery/view/View_Composite.h>
+
+namespace Glom
+{
+
+///The base View for the document.
+typedef GlomBakery::View<Document_Glom> View_Glom;
+
+typedef GlomBakery::View_Composite<Document_Glom> View_Composite_Glom;
+
+} //namespace Glom
+
+#endif //DOCUMENT_GLOM_VIEW_H

Modified: trunk/glom/libglom/spawn_with_feedback.cc
==============================================================================
--- trunk/glom/libglom/spawn_with_feedback.cc	(original)
+++ trunk/glom/libglom/spawn_with_feedback.cc	Tue Mar 17 10:46:53 2009
@@ -21,8 +21,10 @@
 #include <libglom/spawn_with_feedback.h>
 #include <libglom/dialog_progress_creating.h>
 #include <libglom/glade_utils.h>
-#include <bakery/bakery.h>
+#include <gtkmm/main.h>
+#include <gtkmm/messagedialog.h>
 #include <glibmm/i18n.h>
+#include <memory> //For auto_ptr.
 #include <iostream>
 
 #ifdef G_OS_WIN32
@@ -560,7 +562,7 @@
 #if 0
 bool execute_command_line_and_wait_fixed_seconds(const std::string& command, unsigned int seconds, const Glib::ustring& message, Gtk::Window* parent_window)
 {
-  Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(message), true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE, true /* modal */); 
+  Gtk::MessageDialog dialog(Utils::bold_message(message), true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE, true /* modal */); 
   if(parent_window)
     dialog.set_transient_for(*parent_window);
 

Modified: trunk/glom/libglom/utils.cc
==============================================================================
--- trunk/glom/libglom/utils.cc	(original)
+++ trunk/glom/libglom/utils.cc	Tue Mar 17 10:46:53 2009
@@ -28,7 +28,7 @@
 #include <glibmm/i18n.h>
 #include <gtkmm/messagedialog.h>
 
-#include <gio/gio.h> // For g_app_info_launch_default_for_uri
+#include <giomm.h>
 
 #ifdef GLOM_ENABLE_MAEMO
 #include <hildonmm/note.h>
@@ -936,5 +936,34 @@
   main_loop->run(); //Run and block until it is stopped by the hide signal handler.
 }
 
+Glib::ustring Utils::bold_message(const Glib::ustring& message)
+{
+  return "<b>" + message + "</b>";
+}
+
+
+bool Utils::file_exists(const Glib::ustring& uri)
+{
+  //Check whether file exists already:
+  {
+    // Try to examine the input file.
+    Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(uri);
+
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+    try
+    {
+      return file->query_exists();
+    }
+    catch(const Gio::Error& /* ex */)
+    {
+      return false; //Something went wrong. It does not exist.
+    }
+#else
+      std::auto_ptr<Gio::Error> error;
+      retrun file->query_exists(error);
+#endif
+  }
+}
+
 
 } //namespace Glom

Modified: trunk/glom/libglom/utils.h
==============================================================================
--- trunk/glom/libglom/utils.h	(original)
+++ trunk/glom/libglom/utils.h	Tue Mar 17 10:46:53 2009
@@ -110,6 +110,11 @@
 
 void show_window_until_hide(Gtk::Window* window);
 
+/// For instance, to create bold primary text for a dialog box, without marking the markup for translation.
+Glib::ustring bold_message(const Glib::ustring& message);
+
+bool file_exists(const Glib::ustring& uri);
+
 } //namespace Utils
 
 } //namespace Glom

Modified: trunk/glom/main.cc
==============================================================================
--- trunk/glom/main.cc	(original)
+++ trunk/glom/main.cc	Tue Mar 17 10:46:53 2009
@@ -226,8 +226,6 @@
   try
 #endif
   {
-    Bakery::init();
-
 #ifndef GLOM_ENABLE_CLIENT_ONLY
     gtksourceview::init();
     Goocanvas::init(PACKAGE, VERSION, argc, argv ) ;

Modified: trunk/glom/mode_data/box_data.cc
==============================================================================
--- trunk/glom/mode_data/box_data.cc	(original)
+++ trunk/glom/mode_data/box_data.cc	Tue Mar 17 10:46:53 2009
@@ -25,8 +25,7 @@
 #include <libglom/utils.h>
 #include <libglom/data_structure/layout/layoutitem_field.h>
 #include <glom/glom_privs.h>
-#include "../python_embed/glom_python.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include "../python_embed/glom_python.h".
 #include <algorithm> //For std::find()
 #include <libglom/libglom_config.h>
 #include <glibmm/i18n.h>
@@ -140,7 +139,7 @@
 #ifdef GLOM_ENABLE_MAEMO
     Hildon::Note dialog(Hildon::NOTE_TYPE_INFORMATION, *get_app_window(), message);
 #else
-    Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("No Find Criteria")), true, Gtk::MESSAGE_WARNING );
+    Gtk::MessageDialog dialog(Utils::bold_message(_("No Find Criteria")), true, Gtk::MESSAGE_WARNING );
     dialog.set_secondary_text(message);
     dialog.set_transient_for(*get_app_window());
 #endif
@@ -185,7 +184,7 @@
     //Hildon::Note dialog(Hildon::NOTE_TYPE_CONFIRMATION, *get_app_window(), message);
     Hildon::Note dialog(Hildon::NOTE_TYPE_CONFIRMATION, message);
 #else
-    Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("No primary key value")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL );
+    Gtk::MessageDialog dialog(Utils::bold_message(_("No primary key value")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL );
     dialog.set_secondary_text(message);
 #endif
     //TODO: It needs a const. I wonder if it should. murrayc. dialog.set_transient_for(*get_app_window());

Modified: trunk/glom/mode_data/box_data_calendar_related.cc
==============================================================================
--- trunk/glom/mode_data/box_data_calendar_related.cc	(original)
+++ trunk/glom/mode_data/box_data_calendar_related.cc	Tue Mar 17 10:46:53 2009
@@ -23,7 +23,6 @@
 #include <glom/application.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <glom/frame_glom.h> //For show_ok_dialog()
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -96,7 +95,7 @@
       relationship_title = _("Undefined Table");
     }
 
-    m_Label.set_markup(Bakery::App_Gtk::util_bold_message(relationship_title));
+    m_Label.set_markup(Utils::bold_message(relationship_title));
     m_Label.show();
 
     m_Alignment.set_padding(Utils::DEFAULT_SPACING_SMALL /* top */, 0, Utils::DEFAULT_SPACING_LARGE /* left */, 0);

Modified: trunk/glom/mode_data/box_data_details.cc
==============================================================================
--- trunk/glom/mode_data/box_data_details.cc	(original)
+++ trunk/glom/mode_data/box_data_details.cc	Tue Mar 17 10:46:53 2009
@@ -27,8 +27,7 @@
 #include <libglom/glade_utils.h>
 #include <libglom/utils.h>
 #include <glom/glom_privs.h>
-#include "../xsl_utils.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include "../xsl_utils.h".
 #include "../python_embed/glom_python.h"
 #include <sstream> //For stringstream
 #include <glibmm/i18n.h>
@@ -193,7 +192,7 @@
 
 void Box_Data_Details::create_layout()
 {
-  Bakery::BusyCursor busy_cursor(get_app_window());
+  BusyCursor busy_cursor(get_app_window());
 
   Box_Data::create_layout(); //Fills m_TableFields.
 
@@ -230,7 +229,7 @@
 
   bool bResult = false;
 
-  Bakery::BusyCursor busy_cursor(get_app_window());
+  BusyCursor busy_cursor(get_app_window());
 
   const bool primary_key_is_empty = Conversions::value_is_empty(m_primary_key_value);
   if(!primary_key_is_empty)
@@ -436,7 +435,7 @@
   if( Conversions::value_is_empty(get_primary_key_value_selected()) )
   {
     //Tell user that a primary key is needed to delete a record:
-    Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("No primary key value.")), true);
+    Gtk::MessageDialog dialog(Utils::bold_message(_("No primary key value.")), true);
     dialog.set_secondary_text(_("This record cannot be deleted because there is no primary key."));
     dialog.set_transient_for(*get_app_window());
     dialog.run();
@@ -840,7 +839,7 @@
       if(strFieldName == m_field_primary_key->get_name()) //If edited field is the primary key.
       {
         //Warn user that they can't choose their own primary key:
-        Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Primary key auto increments")), true);
+        Gtk::MessageDialog dialog(Utils::bold_message(_("Primary key auto increments")), true);
         dialog.set_secondary_text(_("The primary key is auto-incremented.\n You may not enter your own primary key value."));
         dialog.set_transient_for(*get_app_window());
         dialog.run();

Modified: trunk/glom/mode_data/box_data_list.cc
==============================================================================
--- trunk/glom/mode_data/box_data_list.cc	(original)
+++ trunk/glom/mode_data/box_data_list.cc	Tue Mar 17 10:46:53 2009
@@ -24,7 +24,7 @@
 #include <glom/reports/report_builder.h>
 #include "dialog_layout_list.h"
 #include <glom/glom_privs.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 //#include <../utility_widgets/db_adddel/glom_db_treemodel.h> //For DbTreeModel.
 #include <sstream> //For stringstream
 #include <glibmm/i18n.h>
@@ -108,7 +108,7 @@
   if(!get_document())
     return false;
 
-  Bakery::BusyCursor busy_cursor(get_app_window());
+  BusyCursor busy_cursor(get_app_window());
 
   sharedptr<SharedConnection> sharedconnection;
 

Modified: trunk/glom/mode_data/box_data_list_related.cc
==============================================================================
--- trunk/glom/mode_data/box_data_list_related.cc	(original)
+++ trunk/glom/mode_data/box_data_list_related.cc	Tue Mar 17 10:46:53 2009
@@ -23,7 +23,7 @@
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/glade_utils.h>
 #include <glom/frame_glom.h> //For show_ok_dialog()
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -89,7 +89,7 @@
       relationship_title = _("Undefined Table");
     }
   
-    m_Label.set_markup(Bakery::App_Gtk::util_bold_message(relationship_title));
+    m_Label.set_markup(Utils::bold_message(relationship_title));
     m_Label.show();
 
     m_Alignment.set_padding(Utils::DEFAULT_SPACING_SMALL /* top */, 0, Utils::DEFAULT_SPACING_LARGE /* left */, 0);

Modified: trunk/glom/mode_data/box_data_manyrecords.cc
==============================================================================
--- trunk/glom/mode_data/box_data_manyrecords.cc	(original)
+++ trunk/glom/mode_data/box_data_manyrecords.cc	Tue Mar 17 10:46:53 2009
@@ -24,7 +24,7 @@
 #include <glom/reports/report_builder.h>
 #include "dialog_layout_list.h"
 #include <glom/glom_privs.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <sstream> //For stringstream
 #include <glibmm/i18n.h>
 

Modified: trunk/glom/mode_data/box_data_portal.cc
==============================================================================
--- trunk/glom/mode_data/box_data_portal.cc	(original)
+++ trunk/glom/mode_data/box_data_portal.cc	Tue Mar 17 10:46:53 2009
@@ -22,7 +22,7 @@
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/glade_utils.h>
 #include <glom/frame_glom.h> //For show_ok_dialog()
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -86,7 +86,7 @@
       relationship_title = _("Undefined Table");
     }
 
-    m_Label.set_markup(Bakery::App_Gtk::util_bold_message(relationship_title));
+    m_Label.set_markup(Utils::bold_message(relationship_title));
     m_Label.show();
 
     m_Alignment.set_padding(Utils::DEFAULT_SPACING_SMALL /* top */, 0, Utils::DEFAULT_SPACING_LARGE /* left */, 0);

Modified: trunk/glom/mode_data/dialog_layout_calendar_related.cc
==============================================================================
--- trunk/glom/mode_data/dialog_layout_calendar_related.cc	(original)
+++ trunk/glom/mode_data/dialog_layout_calendar_related.cc	Tue Mar 17 10:46:53 2009
@@ -21,7 +21,7 @@
 #include "dialog_layout_calendar_related.h"
 #include "dialog_choose_field.h"
 #include "../layout_item_dialogs/dialog_field_layout.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 
 //#include <libgnome/gnome-i18n.h>
 #include <gtkmm/togglebutton.h>

Modified: trunk/glom/mode_data/dialog_layout_details.cc
==============================================================================
--- trunk/glom/mode_data/dialog_layout_details.cc	(original)
+++ trunk/glom/mode_data/dialog_layout_details.cc	Tue Mar 17 10:46:53 2009
@@ -25,7 +25,7 @@
 #include <libglom/glade_utils.h>
 #include "../frame_glom.h" //For show_ok_dialog()
 //#include <libgnome/gnome-i18n.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 #include <sstream> //For stringstream
 
@@ -1162,7 +1162,7 @@
           is_group = true;
 
           //Make group names bold:
-          markup = Bakery::App_Gtk::util_bold_message( layout_item->get_name() );
+          markup = Utils::bold_message( layout_item->get_name() );
         }
         else
         {

Modified: trunk/glom/mode_data/dialog_layout_export.cc
==============================================================================
--- trunk/glom/mode_data/dialog_layout_export.cc	(original)
+++ trunk/glom/mode_data/dialog_layout_export.cc	Tue Mar 17 10:46:53 2009
@@ -21,7 +21,7 @@
 #include "dialog_layout_export.h"
 #include "dialog_choose_field.h"
 #include "../layout_item_dialogs/dialog_field_layout.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>

Modified: trunk/glom/mode_data/dialog_layout_list.cc
==============================================================================
--- trunk/glom/mode_data/dialog_layout_list.cc	(original)
+++ trunk/glom/mode_data/dialog_layout_list.cc	Tue Mar 17 10:46:53 2009
@@ -22,7 +22,7 @@
 #include "dialog_choose_field.h"
 #include "../layout_item_dialogs/dialog_field_layout.h"
 #include "../frame_glom.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>

Modified: trunk/glom/mode_data/dialog_layout_list_related.cc
==============================================================================
--- trunk/glom/mode_data/dialog_layout_list_related.cc	(original)
+++ trunk/glom/mode_data/dialog_layout_list_related.cc	Tue Mar 17 10:46:53 2009
@@ -21,7 +21,7 @@
 #include "dialog_layout_list_related.h"
 #include "dialog_choose_field.h"
 #include "../layout_item_dialogs/dialog_field_layout.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 
 //#include <libgnome/gnome-i18n.h>
 #include <gtkmm/togglebutton.h>

Modified: trunk/glom/mode_data/flowtablewithfields.cc
==============================================================================
--- trunk/glom/mode_data/flowtablewithfields.cc	(original)
+++ trunk/glom/mode_data/flowtablewithfields.cc	Tue Mar 17 10:46:53 2009
@@ -33,7 +33,7 @@
 #include <libglom/glade_utils.h>
 #include "box_data_list_related.h"
 #include "dialog_choose_relationship.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 #include <libglom/data_structure/layout/layoutitem_placeholder.h>
 #include <glom/signal_reemitter.h>
@@ -182,7 +182,7 @@
     if(!group->get_title().empty())
     {
       Gtk::Label* label = Gtk::manage( new Gtk::Label ); //TODO: This is maybe leaked, according to valgrind, though it should be managed by GtkFrame.
-      label->set_markup( Bakery::App_Gtk::util_bold_message(group->get_title()) );
+      label->set_markup( Utils::bold_message(group->get_title()) );
       label->show();
       frame->set_label_widget(*label);
     }
@@ -363,7 +363,7 @@
       if(portal)
       {
         const Glib::ustring tab_title = glom_get_sharedptr_title_or_name(portal->get_relationship());
-        //tab_label->set_markup(Bakery::App_Gtk::util_bold_message(tab_title));
+        //tab_label->set_markup(Utils::bold_message(tab_title));
         tab_label->set_label(tab_title);
 
         //Add a Related Records list for this portal:
@@ -377,7 +377,7 @@
       else
       {
         const Glib::ustring tab_title = group->get_title_or_name();
-        //tab_label->set_markup(Bakery::App_Gtk::util_bold_message(tab_title));
+        //tab_label->set_markup(Utils::bold_message(tab_title));
         tab_label->set_label(tab_title);
 
         //Add a FlowTable for this group:

Modified: trunk/glom/mode_design/box_db_table_relationships.cc
==============================================================================
--- trunk/glom/mode_design/box_db_table_relationships.cc	(original)
+++ trunk/glom/mode_design/box_db_table_relationships.cc	Tue Mar 17 10:46:53 2009
@@ -68,7 +68,7 @@
 
 bool Box_DB_Table_Relationships::fill_from_database()
 {
-  Bakery::BusyCursor busy_cursor(get_app_window());
+  BusyCursor busy_cursor(get_app_window());
 
   bool result = Box_DB_Table::fill_from_database();
 
@@ -224,7 +224,7 @@
 {
   if(col == m_colToField)
   {
-    Bakery::BusyCursor busy_cursor(get_app_window());
+    BusyCursor busy_cursor(get_app_window());
 
     const Glib::ustring old_to_field = m_AddDel.get_value(row, m_colToField);
 

Modified: trunk/glom/mode_design/dialog_fields.cc
==============================================================================
--- trunk/glom/mode_design/dialog_fields.cc	(original)
+++ trunk/glom/mode_design/dialog_fields.cc	Tue Mar 17 10:46:53 2009
@@ -21,7 +21,7 @@
 #include "dialog_fields.h"
 #include "../box_db_table.h"
 //#include <libgnome/gnome-i18n.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -33,7 +33,7 @@
 {
   refGlade->get_widget_derived("vbox_placeholder", m_box);
 
-  m_label_frame->set_markup( Bakery::App_Gtk::util_bold_message(_("Field Definitions")) );
+  m_label_frame->set_markup( Utils::bold_message(_("Field Definitions")) );
 
 
   //Fill composite view:

Modified: trunk/glom/mode_design/dialog_relationships.cc
==============================================================================
--- trunk/glom/mode_design/dialog_relationships.cc	(original)
+++ trunk/glom/mode_design/dialog_relationships.cc	Tue Mar 17 10:46:53 2009
@@ -21,7 +21,7 @@
 #include "dialog_relationships.h"
 #include "../box_db_table.h"
 //#include <libgnome/gnome-i18n.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -33,7 +33,7 @@
 {
   refGlade->get_widget_derived("vbox_placeholder", m_box);
 
-  m_label_frame->set_markup( Bakery::App_Gtk::util_bold_message(_("Relationships")) );
+  m_label_frame->set_markup( Utils::bold_message(_("Relationships")) );
 
   //Fill composite view:
   add_view(m_box);

Modified: trunk/glom/mode_design/fields/box_db_table_definition.cc
==============================================================================
--- trunk/glom/mode_design/fields/box_db_table_definition.cc	(original)
+++ trunk/glom/mode_design/fields/box_db_table_definition.cc	Tue Mar 17 10:46:53 2009
@@ -21,7 +21,7 @@
 #include "box_db_table_definition.h"
 #include <glom/frame_glom.h>
 #include <libglom/glade_utils.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <libglom/libglom_config.h>
 #include <glibmm/i18n.h>
 
@@ -260,7 +260,7 @@
     if(field_new->get_calculation() != field_old->get_calculation())
     {
       //TODO: Only show this when there are > 100 records?
-      Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Recalculation Required")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE);
+      Gtk::MessageDialog dialog(Utils::bold_message(_("Recalculation Required")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE);
       dialog.set_secondary_text(_("You have changed the calculation used by this field so Glom must recalculate the value in all records. If the table contains many records then this could take a long time."));
       if(parent_window)
         dialog.set_transient_for(*parent_window);
@@ -311,7 +311,7 @@
     }
 
     //Ask the user to confirm this major change:
-    Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Change primary key")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE);
+    Gtk::MessageDialog dialog(Utils::bold_message(_("Change primary key")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE);
     dialog.set_secondary_text(_("Are you sure that you wish to set this field as the primary key, instead of the existing primary key?"));
     if(parent_window)
       dialog.set_transient_for(*parent_window);
@@ -498,7 +498,7 @@
 
 sharedptr<Field> Box_DB_Table_Definition::change_definition(const sharedptr<const Field>& fieldOld, const sharedptr<const Field>& field)
 {
-  Bakery::BusyCursor busy_cursor(get_app_window());
+  BusyCursor busy_cursor(get_app_window());
 
   //DB field definition:
 

Modified: trunk/glom/mode_design/print_layouts/box_print_layouts.cc
==============================================================================
--- trunk/glom/mode_design/print_layouts/box_print_layouts.cc	(original)
+++ trunk/glom/mode_design/print_layouts/box_print_layouts.cc	Tue Mar 17 10:46:53 2009
@@ -19,7 +19,7 @@
  */
 
 #include "box_print_layouts.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -67,7 +67,7 @@
 
 bool Box_Print_Layouts::fill_from_database()
 {
-  Bakery::BusyCursor busy_cursor(get_app_window());
+  BusyCursor busy_cursor(get_app_window());
 
   bool result = Base_DB::fill_from_database();
 

Modified: trunk/glom/mode_design/print_layouts/canvas_print_layout.cc
==============================================================================
--- trunk/glom/mode_design/print_layouts/canvas_print_layout.cc	(original)
+++ trunk/glom/mode_design/print_layouts/canvas_print_layout.cc	Tue Mar 17 10:46:53 2009
@@ -20,7 +20,7 @@
  */
 
 #include "canvas_print_layout.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <gtkmm/stock.h>
 #include <glom/mode_design/print_layouts/dialog_text_formatting.h>
 #include <glom/mode_data/dialog_layout_list_related.h>

Modified: trunk/glom/mode_design/print_layouts/window_print_layout_edit.cc
==============================================================================
--- trunk/glom/mode_design/print_layouts/window_print_layout_edit.cc	(original)
+++ trunk/glom/mode_design/print_layouts/window_print_layout_edit.cc	Tue Mar 17 10:46:53 2009
@@ -25,7 +25,7 @@
 #include <libglom/data_structure/layout/layoutitem_line.h>
 #include <libglom/data_structure/layout/layoutitem_portal.h>
 //#include <libgnome/gnome-i18n.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <gtkmm/scrolledwindow.h>
 #include <glibmm/i18n.h>
 

Modified: trunk/glom/mode_design/script_library/dialog_script_library.cc
==============================================================================
--- trunk/glom/mode_design/script_library/dialog_script_library.cc	(original)
+++ trunk/glom/mode_design/script_library/dialog_script_library.cc	Tue Mar 17 10:46:53 2009
@@ -129,7 +129,7 @@
   if(!document)
     return;
 
-  Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Remove library script")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE );
+  Gtk::MessageDialog dialog(Utils::bold_message(_("Remove library script")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE );
   dialog.set_secondary_text(_("Do you really want to delete this script? This data can not be recovered"));
   dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
   dialog.add_button(Gtk::Stock::REMOVE, Gtk::RESPONSE_OK);

Modified: trunk/glom/mode_design/users/dialog_groups_list.cc
==============================================================================
--- trunk/glom/mode_design/users/dialog_groups_list.cc	(original)
+++ trunk/glom/mode_design/users/dialog_groups_list.cc	Tue Mar 17 10:46:53 2009
@@ -26,7 +26,7 @@
 #include <libglom/glade_utils.h>
 #include <glom/glom_privs.h>
 //#include <libgnome/gnome-i18n.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -209,7 +209,7 @@
       if(!group.empty())
       {
         //TODO: Prevent deletion of standard groups
-        Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Delete Group")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL);
+        Gtk::MessageDialog dialog(Utils::bold_message(_("Delete Group")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL);
         dialog.set_secondary_text(_("Are your sure that you wish to delete this group?"));
         dialog.set_transient_for(*this);
 

Modified: trunk/glom/mode_design/users/dialog_users_list.cc
==============================================================================
--- trunk/glom/mode_design/users/dialog_users_list.cc	(original)
+++ trunk/glom/mode_design/users/dialog_users_list.cc	Tue Mar 17 10:46:53 2009
@@ -23,7 +23,7 @@
 #include "dialog_choose_user.h"
 #include <glom/glom_privs.h>
 #include <libglom/glade_utils.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>
 
@@ -159,7 +159,7 @@
         const Glib::ustring user = row[m_model_columns_users.m_col_name];
         if(!user.empty())
         {
-          Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Delete User")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL);
+          Gtk::MessageDialog dialog(Utils::bold_message(_("Delete User")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL);
           dialog.set_secondary_text(_("Are your sure that you wish to delete this user?"));
           dialog.set_transient_for(*this);
 
@@ -441,7 +441,7 @@
   {
     if(m_model_users->children().size() == 1)
     {
-      Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Developer group may not be empty.")), true, Gtk::MESSAGE_WARNING);
+      Gtk::MessageDialog dialog(Utils::bold_message(_("Developer group may not be empty.")), true, Gtk::MESSAGE_WARNING);
       dialog.set_secondary_text(_("The developer group must contain at least one user."));
       dialog.set_transient_for(*this);
       dialog.run();

Modified: trunk/glom/mode_find/box_data_details_find.cc
==============================================================================
--- trunk/glom/mode_find/box_data_details_find.cc	(original)
+++ trunk/glom/mode_find/box_data_details_find.cc	Tue Mar 17 10:46:53 2009
@@ -57,7 +57,7 @@
 
 bool Box_Data_Details_Find::fill_from_database()
 {
-  Bakery::BusyCursor busy_cursor(get_app_window());
+  BusyCursor busy_cursor(get_app_window());
 
   const bool result = Base_DB_Table_Data::fill_from_database();
   if(!result)

Modified: trunk/glom/mode_find/box_data_list_find.cc
==============================================================================
--- trunk/glom/mode_find/box_data_list_find.cc	(original)
+++ trunk/glom/mode_find/box_data_list_find.cc	Tue Mar 17 10:46:53 2009
@@ -51,7 +51,7 @@
 
 bool Box_Data_List_Find::fill_from_database()
 {
-  Bakery::BusyCursor busy_cursor(get_app_window());
+  BusyCursor busy_cursor(get_app_window());
 
   const bool result = Base_DB_Table_Data::fill_from_database();
   if(!result)

Modified: trunk/glom/navigation/box_tables.cc
==============================================================================
--- trunk/glom/navigation/box_tables.cc	(original)
+++ trunk/glom/navigation/box_tables.cc	Tue Mar 17 10:46:53 2009
@@ -19,7 +19,7 @@
  */
 
 #include "box_tables.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glom/application.h>
 #include <glibmm/i18n.h>
 
@@ -96,7 +96,7 @@
 
 bool Box_Tables::fill_from_database()
 {
-  Bakery::BusyCursor busy_cursor(App_Glom::get_application());
+  BusyCursor busy_cursor(App_Glom::get_application());
 
   bool result = Base_DB::fill_from_database();
 
@@ -232,7 +232,7 @@
   if(exists_in_db)
   {
     //Ask the user if they want us to try to cope with this:
-    Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Table Already Exists")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL);
+    Gtk::MessageDialog dialog(Utils::bold_message(_("Table Already Exists")), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL);
     dialog.set_secondary_text(_("This table already exists on the database server, though it is not mentioned in the .glom file. This should not happen. Would you like Glom to attempt to use the existing table?"));
     dialog.set_transient_for(*App_Glom::get_application());
 
@@ -301,7 +301,7 @@
         {
           //Ask the user to confirm:
           Glib::ustring strMsg = _("Are you sure that you want to delete this table?\nTable name: ") + table_name;
-          Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Delete Table")), true);
+          Gtk::MessageDialog dialog(Utils::bold_message(_("Delete Table")), true);
           dialog.set_secondary_text(strMsg);
           dialog.set_transient_for(*App_Glom::get_application());
           int iButtonClicked = dialog.run();
@@ -411,7 +411,7 @@
     //This should never happen, because we never show them in the list:
     if(false) //Let's see if we can adapt.  (!document->get_table_is_known(table_name))
     {
-       Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Unknown Table")), true);
+       Gtk::MessageDialog dialog(Utils::bold_message(_("Unknown Table")), true);
        dialog.set_secondary_text(_("You cannot open this table, because there is no information about this table in the document."));
        dialog.set_transient_for(*App_Glom::get_application());
        dialog.run();

Modified: trunk/glom/reports/dialog_layout_report.cc
==============================================================================
--- trunk/glom/reports/dialog_layout_report.cc	(original)
+++ trunk/glom/reports/dialog_layout_report.cc	Tue Mar 17 10:46:53 2009
@@ -35,7 +35,7 @@
 #include "../layout_item_dialogs/dialog_field_summary.h"
 #include "../mode_data/dialog_choose_relationship.h"
 //#include <libgnome/gnome-i18n.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 #include <sstream> //For stringstream
 

Modified: trunk/glom/translation/dialog_copy_translation.cc
==============================================================================
--- trunk/glom/translation/dialog_copy_translation.cc	(original)
+++ trunk/glom/translation/dialog_copy_translation.cc	Tue Mar 17 10:46:53 2009
@@ -19,7 +19,7 @@
  */
 
 #include "dialog_copy_translation.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 
 namespace Glom

Modified: trunk/glom/translation/dialog_identify_original.cc
==============================================================================
--- trunk/glom/translation/dialog_identify_original.cc	(original)
+++ trunk/glom/translation/dialog_identify_original.cc	Tue Mar 17 10:46:53 2009
@@ -20,7 +20,7 @@
 
 #include "dialog_identify_original.h"
 #include <libglom/data_structure/iso_codes.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -46,7 +46,7 @@
   std::cout << "Dialog_IdentifyOriginal::load_from_document" << std::endl;
 
   if(m_label_original )
-    m_label_original->set_markup( Bakery::App_Gtk::util_bold_message( IsoCodes::get_locale_name( get_document()->get_translation_original_locale()) ) );
+    m_label_original->set_markup( Utils::bold_message( IsoCodes::get_locale_name( get_document()->get_translation_original_locale()) ) );
 
   m_combo_locale->set_selected_locale(TranslatableItem::get_current_locale());
 

Modified: trunk/glom/translation/window_translations.cc
==============================================================================
--- trunk/glom/translation/window_translations.cc	(original)
+++ trunk/glom/translation/window_translations.cc	Tue Mar 17 10:46:53 2009
@@ -22,7 +22,7 @@
 #include "combobox_locale.h"
 #include "dialog_identify_original.h"
 #include "dialog_copy_translation.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <libglom/utils.h>
 #include <libglom/glade_utils.h>
 

Modified: trunk/glom/utility_widgets/adddel/adddel.cc
==============================================================================
--- trunk/glom/utility_widgets/adddel/adddel.cc	(original)
+++ trunk/glom/utility_widgets/adddel/adddel.cc	Tue Mar 17 10:46:53 2009
@@ -28,7 +28,7 @@
 #include <libglom/data_structure/glomconversions.h>
 #include "../../dialog_invalid_data.h"
 #include <libglom/utils.h>
-#include "bakery/App/App_Gtk.h"
+#include <glom/bakery/App_Gtk.h>
 #include <iostream> //For debug output.
 
 #ifdef GLOM_ENABLE_MAEMO
@@ -157,7 +157,7 @@
 #ifdef GLOM_ENABLE_MAEMO
   Hildon::Note dialog(Hildon::NOTE_TYPE_INFORMATION, message);
 #else
-  Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Duplicate")), true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK);
+  Gtk::MessageDialog dialog(Utils::bold_message(_("Duplicate")), true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK);
   dialog.set_secondary_text(message);
 #endif
   //TODO: dialog.set_transient_for(get_parent_window());

Modified: trunk/glom/utility_widgets/db_adddel/db_adddel.cc
==============================================================================
--- trunk/glom/utility_widgets/db_adddel/db_adddel.cc	(original)
+++ trunk/glom/utility_widgets/db_adddel/db_adddel.cc	Tue Mar 17 10:46:53 2009
@@ -1757,7 +1757,7 @@
 
 void DbAddDel::on_treeview_column_clicked(int model_column_index)
 {
-  Bakery::BusyCursor busy_cursor(get_application());
+  BusyCursor busy_cursor(get_application());
 
   if(model_column_index >= (int)m_ColumnTypes.size())
     return;
@@ -2322,7 +2322,7 @@
   if(m_allow_only_one_related_record && (get_count() > 0))
   {
     //Tell user that they can't do that:
-    Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("Extra Related Records Not Possible")), true, Gtk::MESSAGE_WARNING);
+    Gtk::MessageDialog dialog(Utils::bold_message(_("Extra Related Records Not Possible")), true, Gtk::MESSAGE_WARNING);
     dialog.set_secondary_text(_("You attempted to add a new related record, but there can only be one related record, because the relationship uses a unique key.")),
     dialog.set_transient_for(*App_Glom::get_application());
     dialog.run();

Modified: trunk/glom/utility_widgets/dialog_choose_date.cc
==============================================================================
--- trunk/glom/utility_widgets/dialog_choose_date.cc	(original)
+++ trunk/glom/utility_widgets/dialog_choose_date.cc	Tue Mar 17 10:46:53 2009
@@ -19,7 +19,7 @@
  */
 
 #include "dialog_choose_date.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>
 

Modified: trunk/glom/utility_widgets/dialog_choose_id.cc
==============================================================================
--- trunk/glom/utility_widgets/dialog_choose_id.cc	(original)
+++ trunk/glom/utility_widgets/dialog_choose_id.cc	Tue Mar 17 10:46:53 2009
@@ -21,7 +21,7 @@
 #include <libglom/libglom_config.h> // For GLOM_ENABLE_MAEMO
 
 #include "dialog_choose_id.h"
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 //#include <libgnome/gnome-i18n.h>
 #include <glibmm/i18n.h>
 
@@ -106,7 +106,7 @@
 #ifdef GLOM_ENABLE_MAEMO
     Hildon::Note dialog(Hildon::NOTE_TYPE_INFORMATION, *this, message);
 #else
-    Gtk::MessageDialog dialog(Bakery::App_Gtk::util_bold_message(_("No Find Criteria")), true, Gtk::MESSAGE_WARNING );
+    Gtk::MessageDialog dialog(Utils::bold_message(_("No Find Criteria")), true, Gtk::MESSAGE_WARNING );
     dialog.set_secondary_text(message);
     dialog.set_transient_for(*this);
 #endif

Modified: trunk/glom/utility_widgets/filechooserdialog_saveextras.cc
==============================================================================
--- trunk/glom/utility_widgets/filechooserdialog_saveextras.cc	(original)
+++ trunk/glom/utility_widgets/filechooserdialog_saveextras.cc	Tue Mar 17 10:46:53 2009
@@ -21,7 +21,7 @@
 #include <glom/utility_widgets/filechooserdialog_saveextras.h>
 #include <libglom/utils.h>
 #include <gtkmm/alignment.h>
-#include <bakery/App/App_Gtk.h> //For util_bold_message().
+#include <libglom/utils.h> //For bold_message()).
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -69,7 +69,7 @@
 
   Gtk::Frame* frame = Gtk::manage(new Gtk::Frame());
   Gtk::Label* frame_label = Gtk::manage(new Gtk::Label());
-  frame_label->set_markup(Bakery::App_Gtk::util_bold_message(_("New Database")));
+  frame_label->set_markup(Utils::bold_message(_("New Database")));
   frame_label->show();
   frame->set_label_widget(*frame_label);
   frame->set_shadow_type(Gtk::SHADOW_NONE);



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