[glom] Add a startup script feature.



commit 08015441d6cc1570ba295be754f35a2539cadc34
Author: Murray Cumming <murrayc murrayc com>
Date:   Sun Mar 14 14:32:59 2010 +0100

    Add a startup script feature.
    
      * libglom/document/document.cc: Added get/set_startup_script().
      load_after(), save_before(): Load and save the startup script.
    
      * glom_developer.glade:
      * glom/mode_design/dialog_database_preferences.[h|cc]: Add a startup script tab.
    
      * libglom/python_embed/py_glom_ui.h: Move PythonUICallbacks into its own
      py_glom_ui_callbacks.h header.
      * glom/python_embed/python_ui_callbacks.[h|cc]: Add this derived callbacks
      class that has handlers that call methods in the application.
      * glom/mode_data/box_data.cc: execute_button_script(): Use the new callbacks
      class instead of using member methods here.
      * glom/application.cc: on_document_load(): Run the startup script, if any,
      after loading the document, using the new derived callbacks class.
    
      * Makefile_glom.am, Makefile_libglom.am: Mention the new files.

 ChangeLog                                          |   21 ++++
 Makefile_glom.am                                   |    2 +
 Makefile_libglom.am                                |    1 +
 glom/application.cc                                |   19 ++++-
 glom/frame_glom.cc                                 |    2 +-
 glom/glom_developer.glade                          |  105 +++++++++++++++++++-
 glom/libglom/data_structure/system_prefs.h         |    3 +-
 glom/libglom/document/document.cc                  |   21 ++++-
 glom/libglom/document/document.h                   |   10 ++
 glom/libglom/python_embed/py_glom_ui.h             |   36 +-------
 glom/libglom/python_embed/py_glom_ui_callbacks.h   |   68 +++++++++++++
 glom/mode_data/box_data.cc                         |   51 +---------
 glom/mode_design/dialog_database_preferences.cc    |   70 +++++++++++++-
 glom/mode_design/dialog_database_preferences.h     |    5 +
 .../layout_item_dialogs/dialog_buttonscript.cc     |   28 +++---
 .../layout_item_dialogs/dialog_buttonscript.h      |    6 +-
 glom/python_embed/python_ui_callbacks.cc           |   76 ++++++++++++++
 glom/python_embed/python_ui_callbacks.h            |   47 +++++++++
 18 files changed, 464 insertions(+), 107 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 9d6baea..31a3e96 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2010-03-16  Murray Cumming  <murrayc murrayc com>
+
+  Add a startup script feature.
+  
+  * libglom/document/document.cc: Added get/set_startup_script().
+  load_after(), save_before(): Load and save the startup script.
+  
+  * glom_developer.glade:
+  * glom/mode_design/dialog_database_preferences.[h|cc]: Add a startup script tab.
+  
+  * libglom/python_embed/py_glom_ui.h: Move PythonUICallbacks into its own 
+  py_glom_ui_callbacks.h header.
+  * glom/python_embed/python_ui_callbacks.[h|cc]: Add this derived callbacks 
+  class that has handlers that call methods in the application.
+  * glom/mode_data/box_data.cc: execute_button_script(): Use the new callbacks
+  class instead of using member methods here.
+  * glom/application.cc: on_document_load(): Run the startup script, if any, 
+  after loading the document, using the new derived callbacks class.
+  
+  * Makefile_glom.am, Makefile_libglom.am: Mention the new files.
+  
 2010-03-13  David King  <davidk openismus com>
 
 	Depend on gtkmm >= 2.19.2, fixing GNOME bug #612796
diff --git a/Makefile_glom.am b/Makefile_glom.am
index aea4a43..b223b07 100644
--- a/Makefile_glom.am
+++ b/Makefile_glom.am
@@ -112,6 +112,8 @@ glom_glom_SOURCES =							\
 	glom/print_layout/canvas_print_layout.h				\
 	glom/python_embed/glom_python.cc				\
 	glom/python_embed/glom_python.h					\
+	glom/python_embed/python_ui_callbacks.cc				\
+	glom/python_embed/python_ui_callbacks.h					\
 	glom/utility_widgets/alignment_justified.cc			\
 	glom/utility_widgets/alignment_justified.h			\
 	glom/utility_widgets/buttonglom.cc				\
diff --git a/Makefile_libglom.am b/Makefile_libglom.am
index 63fdc75..f00c65b 100644
--- a/Makefile_libglom.am
+++ b/Makefile_libglom.am
@@ -150,6 +150,7 @@ glom_libglom_libglom_1_14_la_SOURCES =					\
 	glom/libglom/python_embed/py_glom_relatedrecord.h		\
 	glom/libglom/python_embed/py_glom_ui.cc		\
 	glom/libglom/python_embed/py_glom_ui.h		\
+	glom/libglom/python_embed/py_glom_ui_callbacks.h		\
 	glom/libglom/python_embed/pygdavalue_conversions.cc		\
 	glom/libglom/python_embed/pygdavalue_conversions.h
 
diff --git a/glom/application.cc b/glom/application.cc
index df75cda..d43d2b2 100644
--- a/glom/application.cc
+++ b/glom/application.cc
@@ -34,6 +34,8 @@
 #include <glom/utils_ui.h>
 #include <glom/glade_utils.h>
 #include <glom/glom_privs.h>
+#include <glom/python_embed/python_ui_callbacks.h>
+#include <glom/python_embed/glom_python.h>
 
 #include <cstdio>
 #include <memory> //For std::auto_ptr<>
@@ -1188,8 +1190,23 @@ bool Application::on_document_load()
 
   update_network_shared_ui();
 
-#ifndef GLOM_ENABLE_CLIENT_ONLY
+  //Run any startup script:
+  const Glib::ustring script = pDocument->get_startup_script();
+  if(!script.empty())
+  {
+    ConnectionPool* connection_pool = ConnectionPool::get_instance();
+    sharedptr<SharedConnection> sharedconnection = connection_pool->connect();
+    AppPythonUICallbacks callbacks;
+    glom_execute_python_function_implementation(script,
+      type_map_fields(), //only used when there is a current table and record.
+      pDocument,
+      Glib::ustring() /* table_name */,
+      sharedptr<Field>(), Gnome::Gda::Value(), // primary key - only used when there is a current table and record.
+      sharedconnection->get_gda_connection(),
+      callbacks);
+  }
 
+#ifndef GLOM_ENABLE_CLIENT_ONLY
   pDocument->set_allow_autosave(true);
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
diff --git a/glom/frame_glom.cc b/glom/frame_glom.cc
index 2c483c9..c72b9bd 100644
--- a/glom/frame_glom.cc
+++ b/glom/frame_glom.cc
@@ -1708,7 +1708,7 @@ void Frame_Glom::on_menu_developer_database_preferences()
       add_view(dialog);
       dialog->load_from_document();
 
-     Glom::Utils::dialog_run_with_help(dialog, "dialog_database_preferences");
+      Glom::Utils::dialog_run_with_help(dialog, "dialog_database_preferences");
 
       remove_view(dialog);
       delete dialog;
diff --git a/glom/glom_developer.glade b/glom/glom_developer.glade
index 4f78e6a..7dbc2c0 100644
--- a/glom/glom_developer.glade
+++ b/glom/glom_developer.glade
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <interface>
-  <requires lib="gtk+" version="2.14"/>
   <!-- interface-requires gtksourceview 0.0 -->
+  <requires lib="gtk+" version="2.14"/>
   <!-- interface-naming-policy toplevel-contextual -->
   <object class="GtkWindow" id="window_data_layout_export">
     <property name="border_width">12</property>
@@ -4556,6 +4556,109 @@ Which user should be added to this group?</property>
                     <property name="tab_fill">False</property>
                   </packing>
                 </child>
+                <child>
+                  <object class="GtkVBox" id="vbox21">
+                    <property name="visible">True</property>
+                    <property name="border_width">6</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <object class="GtkLabel" id="label54">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">When the database is opened the python function implemented here will run.</property>
+                        <property name="wrap">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label55">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label">import glom
+
+        &lt;b&gt;def on_startup(ui):&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkAlignment" id="alignment16">
+                        <property name="visible">True</property>
+                        <property name="left_padding">20</property>
+                        <child>
+                          <object class="GtkScrolledWindow" id="scrolledwindow7">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="hscrollbar_policy">automatic</property>
+                            <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">in</property>
+                            <child>
+                              <object class="GtkViewport" id="viewport1">
+                                <property name="visible">True</property>
+                                <child>
+                                  <object class="GtkSourceView" id="textview_calculation">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkHButtonBox" id="hbuttonbox43">
+                        <property name="visible">True</property>
+                        <property name="layout_style">end</property>
+                        <child>
+                          <object class="GtkButton" id="button_test">
+                            <property name="label" translatable="yes">Test</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="can_default">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">4</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel" id="label_startupscript">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Startup Script</property>
+                  </object>
+                  <packing>
+                    <property name="position">3</property>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
               </object>
               <packing>
                 <property name="position">1</property>
diff --git a/glom/libglom/data_structure/system_prefs.h b/glom/libglom/data_structure/system_prefs.h
index 31f1aa0..3fa0226 100644
--- a/glom/libglom/data_structure/system_prefs.h
+++ b/glom/libglom/data_structure/system_prefs.h
@@ -31,7 +31,8 @@ class SystemPrefs
 {
 public:
  Glib::ustring m_name, m_org_name,
-    m_org_address_street, m_org_address_street2, m_org_address_town, m_org_address_county, m_org_address_country, m_org_address_postcode;
+    m_org_address_street, m_org_address_street2, m_org_address_town, 
+    m_org_address_county, m_org_address_country, m_org_address_postcode;
  Gnome::Gda::Value m_org_logo; //TYPE_IMAGE.
 };
 
diff --git a/glom/libglom/document/document.cc b/glom/libglom/document/document.cc
index c5d0e27..12922c0 100644
--- a/glom/libglom/document/document.cc
+++ b/glom/libglom/document/document.cc
@@ -138,6 +138,7 @@ namespace Glom
 #define GLOM_ATTRIBUTE_FORMAT_VERSION "format_version"
 #define GLOM_ATTRIBUTE_IS_EXAMPLE "is_example"
 #define GLOM_ATTRIBUTE_CONNECTION_DATABASE_TITLE "database_title"
+#define GLOM_NODE_STARTUP_SCRIPT "startup_script"
 #define GLOM_ATTRIBUTE_TRANSLATION_ORIGINAL_LOCALE "translation_original_locale"
 #define GLOM_ATTRIBUTE_NAME "name"
 #define GLOM_ATTRIBUTE_TITLE "title"
@@ -2422,6 +2423,8 @@ bool Document::load_after(int& failure_code)
       
       m_is_example = get_node_attribute_value_as_bool(nodeRoot, GLOM_ATTRIBUTE_IS_EXAMPLE);
       m_database_title = get_node_attribute_value(nodeRoot, GLOM_ATTRIBUTE_CONNECTION_DATABASE_TITLE);
+      
+      m_startup_script = get_child_text_node(nodeRoot, GLOM_NODE_STARTUP_SCRIPT);
 
       m_translation_original_locale = get_node_attribute_value(nodeRoot, GLOM_ATTRIBUTE_TRANSLATION_ORIGINAL_LOCALE);
       TranslatableItem::set_original_locale(m_translation_original_locale);
@@ -3361,6 +3364,8 @@ bool Document::save_before()
 
     set_node_attribute_value_as_bool(nodeRoot, GLOM_ATTRIBUTE_IS_EXAMPLE, m_is_example);
     set_node_attribute_value(nodeRoot, GLOM_ATTRIBUTE_CONNECTION_DATABASE_TITLE, m_database_title);
+    
+    set_child_text_node(nodeRoot, GLOM_NODE_STARTUP_SCRIPT, m_startup_script);
 
     //Assume that the first language used is the original locale.
     //It can be identified as a translation later.
@@ -4150,7 +4155,7 @@ guint Document::get_latest_known_document_format_version()
   // Version 2: hosting_mode="postgres-central|postgres-self|sqlite" instead of self_hosted="true|false". Can open Version 1 documents, by falling back to the self_hosted attribute if hosting_mode is not set.
   // Version 3: (Glom 1.10). Support for the old one-big-string example_rows format was removed, and we now use (unquoted) non-postgres libgda escaping. 
   // Version 4: (Glom 1.12). Portal navigation options were simplified, with a "none" option. network_sharing was added, defaulting to off.
-  // Version 5: (Glom 1.14). Extra layout item formatting options were added.
+  // Version 5: (Glom 1.14). Extra layout item formatting options were added, plus a startup script.
 
   return 5;
 }
@@ -4210,6 +4215,20 @@ void Document::remove_library_module(const Glib::ustring& name)
   }
 }
 
+Glib::ustring Document::get_startup_script() const
+{
+  return m_startup_script;
+}
+
+void Document::set_startup_script(const Glib::ustring& script)
+{
+  if(m_startup_script == script)
+    return;
+    
+  m_startup_script = script;
+  set_modified();
+}
+
 Glib::ustring Document::build_and_get_contents() const
 {
   //save_before() probably should be const because it doesn't change much of the external behaviour:
diff --git a/glom/libglom/document/document.h b/glom/libglom/document/document.h
index 0cfd574..b78a9fd 100644
--- a/glom/libglom/document/document.h
+++ b/glom/libglom/document/document.h
@@ -296,6 +296,14 @@ public:
   void set_library_module(const Glib::ustring& name, const Glib::ustring& script);
   Glib::ustring get_library_module(const Glib::ustring& name) const;
   void remove_library_module(const Glib::ustring& name);
+  
+  /** Get a Python script that should be run when the document is opened.
+   */
+  Glib::ustring get_startup_script() const;
+  
+  /** See get_startup_script().
+   */
+  void set_startup_script(const Glib::ustring& script);
 
   /// These are only used when recreating a database from an example file. The actualy access-control is on the server, of course.
   typedef std::list<GroupInfo> type_list_groups;
@@ -604,6 +612,8 @@ private:
 
   typedef std::map<Glib::ustring, Glib::ustring> type_map_library_scripts;
   type_map_library_scripts m_map_library_scripts;
+  
+  Glib::ustring m_startup_script;
 
   bool m_block_cache_update; //For efficiency.
   bool m_block_modified_set;
diff --git a/glom/libglom/python_embed/py_glom_ui.h b/glom/libglom/python_embed/py_glom_ui.h
index 22a7384..fc80ed7 100644
--- a/glom/libglom/python_embed/py_glom_ui.h
+++ b/glom/libglom/python_embed/py_glom_ui.h
@@ -1,6 +1,6 @@
 /* Glom
  *
- * Copyright (C) 2001-2005 Murray Cumming
+ * Copyright (C) 2001-2010 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
@@ -25,44 +25,12 @@
 
 #include <libglom/document/document.h>
 #include <libglom/data_structure/field.h>
+#include <libglom/python_embed/py_glom_ui_callbacks.h>
 #include <glibmm/ustring.h>
 
 namespace Glom
 {
 
-/** UI code should connect to the signals to respond when Python code
- * request a change in the UI.
- */
-class PythonUICallbacks
-{
-public:
-  /** For example,
-   * void on_show_details(const Glib::ustring& table_name, const Gnome::Gda::Value& primary_key_value);
-   */
-  sigc::slot<void, const Glib::ustring&, const Gnome::Gda::Value&> m_slot_show_table_details;
-
-   /** For example,
-   * void on_show_list(const Glib::ustring& table_name);
-   */
-  sigc::slot<void, const Glib::ustring&> m_slot_show_table_list;
-
-   /** For example,
-   * void on_print_report(const Glib::ustring& table_name);
-   */
-  sigc::slot<void, const Glib::ustring&> m_slot_print_report;
-
-   /** For example,
-   * void on_print_layout();
-   */
-  sigc::slot<void> m_slot_print_layout;
-
-  /** For example,
-   * void on_start_new_record(const Gnome::Gda::Value& new_primary_key_value);
-   * Use an empty Value for auto-created fields.
-   */
-  sigc::slot<void> m_slot_start_new_record;
-};
-
 class PyGlomUI
 {
 public:
diff --git a/glom/libglom/python_embed/py_glom_ui_callbacks.h b/glom/libglom/python_embed/py_glom_ui_callbacks.h
new file mode 100644
index 0000000..1b978b2
--- /dev/null
+++ b/glom/libglom/python_embed/py_glom_ui_callbacks.h
@@ -0,0 +1,68 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2010 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GLOM_PYTHON_GLOM_UI_CALLBACKS_H
+#define GLOM_PYTHON_GLOM_UI_CALLBACKS_H
+
+#include <boost/python.hpp>
+
+#include <libglom/document/document.h>
+#include <libglom/data_structure/field.h>
+#include <glibmm/ustring.h>
+
+namespace Glom
+{
+
+/** UI code should connect to the signals to respond when Python code
+ * request a change in the UI.
+ */
+class PythonUICallbacks
+{
+public:
+  /** For example,
+   * void on_show_table_details(const Glib::ustring& table_name, const Gnome::Gda::Value& primary_key_value);
+   */
+  sigc::slot<void, const Glib::ustring&, const Gnome::Gda::Value&> m_slot_show_table_details;
+
+   /** For example,
+   * void on_show_table_list(const Glib::ustring& table_name);
+   */
+  sigc::slot<void, const Glib::ustring&> m_slot_show_table_list;
+
+   /** For example,
+   * void on_print_report(const Glib::ustring& report_name);
+   */
+  sigc::slot<void, const Glib::ustring&> m_slot_print_report;
+
+   /** For example,
+   * void on_print_layout();
+   */
+  sigc::slot<void> m_slot_print_layout;
+
+  /** For example,
+   * void on_start_new_record();
+   * Use an empty Value for auto-created fields.
+   */
+  sigc::slot<void> m_slot_start_new_record;
+};
+
+} //namespace Glom
+
+#endif //GLOM_PYTHON_GLOM_CALLBACKS_UI_H
diff --git a/glom/mode_data/box_data.cc b/glom/mode_data/box_data.cc
index 224cdea..dc611c3 100644
--- a/glom/mode_data/box_data.cc
+++ b/glom/mode_data/box_data.cc
@@ -26,6 +26,7 @@
 #include <libglom/data_structure/layout/layoutitem_field.h>
 #include <glom/glom_privs.h>
 #include <glom/python_embed/glom_python.h>
+#include <glom/python_embed/python_ui_callbacks.h>
 #include <glom/application.h>
 #include <algorithm> //For std::find()
 #include <libglom/libglom_config.h>
@@ -351,44 +352,6 @@ Glib::ustring Box_Data::get_layout_name() const
   return m_layout_name;
 }
 
-void Box_Data::on_python_requested_show_table_details(const Glib::ustring& table_name, const Gnome::Gda::Value& primary_key_value)
-{
-  //std::cout << "debug: on_python_requested_show_table_details(): " << table_name << ", pk value: " << primary_key_value.to_string() << std::endl;
-
-  Application* app = Application::get_application();
-  if(app)
-    app->show_table_details(table_name, primary_key_value);
-}
-
-void Box_Data::on_python_requested_show_table_list(const Glib::ustring& table_name)
-{
-  Application* app = Application::get_application();
-  if(app)
-    app->show_table_list(table_name);
-}
-
-void Box_Data::on_python_requested_print_report(const Glib::ustring& report_name)
-{
-  Application* app = Application::get_application();
-  if(app)
-    app->print_report(report_name);
-}
-
-void Box_Data::on_python_requested_print_layout()
-{
-  Application* app = Application::get_application();
-  if(app)
-    app->print_layout();
-}
-
-void Box_Data::on_python_requested_start_new_record()
-{
-  Application* app = Application::get_application();
-  if(app)
-    app->start_new_record();
-}
-
-
 void Box_Data::execute_button_script(const sharedptr<const LayoutItem_Button>& layout_item, const Gnome::Gda::Value& primary_key_value)
 {
   const sharedptr<Field> field_primary_key = get_field_primary_key();
@@ -405,17 +368,7 @@ void Box_Data::execute_button_script(const sharedptr<const LayoutItem_Button>& l
 #endif // GLIBMM_EXCEPTIONS_ENABLED
 
     //Allow this UI to respond to UI change requests from the Python code:
-    PythonUICallbacks callbacks;
-    callbacks.m_slot_show_table_details =
-      sigc::mem_fun(*this, &Box_Data::on_python_requested_show_table_details);
-    callbacks.m_slot_show_table_list =
-      sigc::mem_fun(*this, &Box_Data::on_python_requested_show_table_list);
-    callbacks.m_slot_print_layout =
-      sigc::mem_fun(*this, &Box_Data::on_python_requested_print_layout);
-    callbacks.m_slot_print_report =
-      sigc::mem_fun(*this, &Box_Data::on_python_requested_print_report);
-    callbacks.m_slot_start_new_record =
-      sigc::mem_fun(*this, &Box_Data::on_python_requested_start_new_record);
+    AppPythonUICallbacks callbacks;
 
     glom_execute_python_function_implementation(layout_item->get_script(),
       field_values, //TODO: Maybe use the field's type here.
diff --git a/glom/mode_design/dialog_database_preferences.cc b/glom/mode_design/dialog_database_preferences.cc
index b515147..e54d978 100644
--- a/glom/mode_design/dialog_database_preferences.cc
+++ b/glom/mode_design/dialog_database_preferences.cc
@@ -19,9 +19,11 @@
  */
  
 #include "dialog_database_preferences.h"
+#include <glom/python_embed/glom_python.h>
 #include <libglom/standard_table_prefs_fields.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <glom/bakery/busy_cursor.h>
+#include <gtksourceviewmm/sourcelanguagemanager.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
@@ -52,7 +54,7 @@ Dialog_Database_Preferences::Dialog_Database_Preferences(BaseObjectType* cobject
 
   m_treeview_autoincrements->append_column(_("Table"), m_columns.m_col_table);
   m_treeview_autoincrements->append_column(_("Field"), m_columns.m_col_field);
-  int view_cols_count = m_treeview_autoincrements->append_column(_("Next Value"), m_columns.m_col_next_value);
+  const int view_cols_count = m_treeview_autoincrements->append_column(_("Next Value"), m_columns.m_col_next_value);
 
   Gtk::CellRendererText* pCellRenderer = dynamic_cast<Gtk::CellRendererText*>(m_treeview_autoincrements->get_column_cell_renderer(view_cols_count-1));
   if(pCellRenderer)
@@ -65,6 +67,32 @@ Dialog_Database_Preferences::Dialog_Database_Preferences(BaseObjectType* cobject
     pCellRenderer->signal_edited().connect(
       sigc::mem_fun(*this, &Dialog_Database_Preferences::on_treeview_cell_edited_next_value) );
   }
+
+  //Startup script widgets:
+  builder->get_widget("textview_calculation",  m_text_view_script);
+  builder->get_widget("button_test",  m_button_test_script);
+
+  m_button_test_script->signal_clicked().connect( 
+    sigc::mem_fun(*this, &Dialog_Database_Preferences::on_button_test_script) );
+
+  // Set a monospace font
+  m_text_view_script->modify_font(Pango::FontDescription("Monospace"));
+
+  //Dialog_Properties::set_modified(false);
+
+  //Tell the SourceView to do syntax highlighting for Python:
+  Glib::RefPtr<gtksourceview::SourceLanguageManager> languages_manager = 
+    gtksourceview::SourceLanguageManager::get_default();
+
+  Glib::RefPtr<gtksourceview::SourceLanguage> language = 
+    languages_manager->get_language("python"); //This is the GtkSourceView language ID.
+  if(language)
+  {
+     //Create a new buffer and set it, instead of getting the default buffer, in case libglade has tried to set it, using the wrong buffer type:
+     Glib::RefPtr<gtksourceview::SourceBuffer> buffer = gtksourceview::SourceBuffer::create(language);
+     buffer->set_highlight_syntax();
+     m_text_view_script->set_buffer(buffer);
+  }
 }
 
 Dialog_Database_Preferences::~Dialog_Database_Preferences()
@@ -116,7 +144,7 @@ void Dialog_Database_Preferences::load_from_document()
 
 
   //Make sure that all auto-increment values are setup:
-  Document* document = get_document();
+  const Document* document = get_document();
   const Document::type_listTableInfo tables = document->get_tables();
   for(Document::type_listTableInfo::const_iterator iter = tables.begin(); iter != tables.end(); ++iter)
   {
@@ -147,7 +175,7 @@ void Dialog_Database_Preferences::load_from_document()
     return;
   }
 
-  guint count = datamodel->get_n_rows();
+  const guint count = datamodel->get_n_rows();
   for(guint i = 0; i < count; ++i)
   {
     Gtk::TreeModel::iterator iter = m_model_autoincrements->append();
@@ -160,6 +188,9 @@ void Dialog_Database_Preferences::load_from_document()
   }
 
   m_model_autoincrements->set_default_sort_func( sigc::mem_fun(*this, &Dialog_Database_Preferences::on_autoincrements_sort) );
+
+  const Glib::ustring script = document->get_startup_script();
+  m_text_view_script->get_buffer()->set_text(script);
 }
 
 int Dialog_Database_Preferences::on_autoincrements_sort(const Gtk::TreeModel::iterator& a, const Gtk::TreeModel::iterator& b)
@@ -183,6 +214,14 @@ void Dialog_Database_Preferences::save_to_document()
   m_system_prefs.m_org_logo = m_image->get_value();
 
   set_database_preferences(m_system_prefs);
+
+  //The script is not part of "database preferencs" in the database data,
+  //because it does not seem to be part of simple personalisation.
+  Document* document = get_document();
+  if(!document)
+     return;
+  const Glib::ustring script = m_text_view_script->get_buffer()->get_text();
+  document->set_startup_script(script);
 }
 
 void Dialog_Database_Preferences::on_response(int response_id)
@@ -196,4 +235,29 @@ void Dialog_Database_Preferences::on_button_choose_image()
    m_image->do_choose_image();
 }
 
+
+void Dialog_Database_Preferences::on_button_test_script()
+{
+  const Glib::ustring calculation = m_text_view_script->get_buffer()->get_text();
+
+  type_map_fields field_values;
+
+  Document* document = get_document();
+  if(!document)
+    return;
+
+  //We need the connection when we run the script, so that the script may use it.
+  sharedptr<SharedConnection> sharedconnection = connect_to_server(this /* parent window */);
+
+  PythonUICallbacks callbacks;
+  glom_execute_python_function_implementation(calculation,
+     type_map_fields(),
+    document,
+    Glib::ustring() /* table_name */,
+    sharedptr<Field>(), Gnome::Gda::Value(), // primary key - only used when setting values in the DB, which we would not encourage in a test.
+    sharedconnection->get_gda_connection(),
+    callbacks);
+}
+
+
 } //namespace Glom
diff --git a/glom/mode_design/dialog_database_preferences.h b/glom/mode_design/dialog_database_preferences.h
index db5f409..47ae549 100644
--- a/glom/mode_design/dialog_database_preferences.h
+++ b/glom/mode_design/dialog_database_preferences.h
@@ -26,6 +26,7 @@
 #include <gtkmm/dialog.h>
 #include <gtkmm/entry.h>
 #include <gtkmm/label.h>
+#include <gtksourceviewmm/sourceview.h>
 #include <glom/base_db.h>
 #include <libglom/data_structure/system_prefs.h>
 #include <libglom/connectionpool.h>
@@ -51,6 +52,7 @@ private:
   void on_response(int response_id);
 
   void on_button_choose_image();
+  void on_button_test_script();
   void on_treeview_cell_edited_next_value(const Glib::ustring& path_string, const Glib::ustring& new_text);
   int on_autoincrements_sort(const Gtk::TreeModel::iterator& a, const Gtk::TreeModel::iterator& b);
 
@@ -78,6 +80,9 @@ private:
   ImageGlom* m_image;
   Gtk::Button* m_button_choose_image;
 
+  gtksourceview::SourceView* m_text_view_script;
+  Gtk::Button* m_button_test_script;
+
   SystemPrefs m_system_prefs;
 };
 
diff --git a/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.cc b/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.cc
index ecce872..cf23948 100644
--- a/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.cc
+++ b/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.cc
@@ -34,28 +34,30 @@ namespace Glom
 Dialog_ButtonScript::Dialog_ButtonScript(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder)
 : Gtk::Dialog(cobject)
 {
-  builder->get_widget("textview_calculation",  m_text_view);
-  builder->get_widget("button_test",  m_button_test);
+  builder->get_widget("textview_calculation",  m_text_view_script);
+  builder->get_widget("button_test",  m_button_test_script);
   builder->get_widget("entry_title",  m_entry_title);
 
-  m_button_test->signal_clicked().connect( sigc::mem_fun(*this, &Dialog_ButtonScript::on_button_test) );
+  m_button_test_script->signal_clicked().connect( sigc::mem_fun(*this, &Dialog_ButtonScript::on_button_test_script) );
 
   // Set a monospace font
-  m_text_view->modify_font(Pango::FontDescription("Monospace"));
+  m_text_view_script->modify_font(Pango::FontDescription("Monospace"));
   //on_foreach_connect(*this);
 
   //Dialog_Properties::set_modified(false);
 
-  //Set the SourceView to do syntax highlighting for Python:
-  Glib::RefPtr<gtksourceview::SourceLanguageManager> languages_manager = gtksourceview::SourceLanguageManager::get_default();
+  //Tell the SourceView to do syntax highlighting for Python:
+  Glib::RefPtr<gtksourceview::SourceLanguageManager> languages_manager = 
+    gtksourceview::SourceLanguageManager::get_default();
 
-  Glib::RefPtr<gtksourceview::SourceLanguage> language = languages_manager->get_language("python"); //This is the GtkSourceView language ID.
+  Glib::RefPtr<gtksourceview::SourceLanguage> language = 
+    languages_manager->get_language("python"); //This is the GtkSourceView language ID.
   if(language)
   {
      //Create a new buffer and set it, instead of getting the default buffer, in case libglade has tried to set it, using the wrong buffer type:
      Glib::RefPtr<gtksourceview::SourceBuffer> buffer = gtksourceview::SourceBuffer::create(language);
      buffer->set_highlight_syntax();
-     m_text_view->set_buffer(buffer);
+     m_text_view_script->set_buffer(buffer);
   }
 
   show_all_children();
@@ -72,7 +74,7 @@ void Dialog_ButtonScript::set_script(const sharedptr<const LayoutItem_Button>& s
   m_script = glom_sharedptr_clone(script); //Remember it so we save any details that are not in our UI.
   m_table_name = table_name;  //Used for lookup combo boxes.
 
-  m_text_view->get_buffer()->set_text( script->get_script() );
+  m_text_view_script->get_buffer()->set_text( script->get_script() );
 
   m_entry_title->set_text(script->get_title());
   //set_blocked(false);
@@ -84,20 +86,20 @@ sharedptr<LayoutItem_Button> Dialog_ButtonScript::get_script() const
 {
   sharedptr<LayoutItem_Button> result = glom_sharedptr_clone(m_script); //Start with the old details, to preserve anything that is not in our UI.
 
-  get_script (result);
+  get_script(result);
 
   return result;
 }
 
 void Dialog_ButtonScript::get_script(const sharedptr<LayoutItem_Button>& script) const
 {
-  script->set_script(m_text_view->get_buffer()->get_text() );
+  script->set_script(m_text_view_script->get_buffer()->get_text() );
   script->set_title(m_entry_title->get_text());
 }
 
-void Dialog_ButtonScript::on_button_test()
+void Dialog_ButtonScript::on_button_test_script()
 {
-  const Glib::ustring calculation = m_text_view->get_buffer()->get_text();
+  const Glib::ustring calculation = m_text_view_script->get_buffer()->get_text();
 
   type_map_fields field_values;
 
diff --git a/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.h b/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.h
index 3bb32dc..c960099 100644
--- a/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.h
+++ b/glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.h
@@ -45,11 +45,11 @@ public:
   void get_script (const sharedptr<LayoutItem_Button>& script) const;
 
 private:
-  void on_button_test();
+  void on_button_test_script();
 
   Gtk::Entry* m_entry_title;
-  gtksourceview::SourceView* m_text_view;
-  Gtk::Button* m_button_test;
+  gtksourceview::SourceView* m_text_view_script;
+  Gtk::Button* m_button_test_script;
 
   sharedptr<LayoutItem_Button> m_script;
   Glib::ustring m_table_name;
diff --git a/glom/python_embed/python_ui_callbacks.cc b/glom/python_embed/python_ui_callbacks.cc
new file mode 100644
index 0000000..d77b7cc
--- /dev/null
+++ b/glom/python_embed/python_ui_callbacks.cc
@@ -0,0 +1,76 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2010 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glom/python_embed/python_ui_callbacks.h>
+#include <glom/application.h>
+
+namespace Glom
+{
+
+AppPythonUICallbacks::AppPythonUICallbacks()
+{
+  m_slot_show_table_details =
+    sigc::mem_fun(*this, &AppPythonUICallbacks::on_show_table_details);
+  m_slot_show_table_list =
+    sigc::mem_fun(*this, &AppPythonUICallbacks::on_show_table_list);
+  m_slot_print_report =
+    sigc::mem_fun(*this, &AppPythonUICallbacks::on_print_report);
+  m_slot_print_layout =
+    sigc::mem_fun(*this, &AppPythonUICallbacks::on_print_layout);
+  m_slot_start_new_record =
+    sigc::mem_fun(*this, &AppPythonUICallbacks::on_start_new_record);
+}
+
+void AppPythonUICallbacks::on_show_table_details(const Glib::ustring& table_name, const Gnome::Gda::Value& primary_key_value)
+{
+  Application* app = Application::get_application();
+  if(app)
+    app->show_table_details(table_name, primary_key_value);
+}
+
+void AppPythonUICallbacks::on_show_table_list(const Glib::ustring& table_name)
+{
+  Application* app = Application::get_application();
+  if(app)
+    app->show_table_list(table_name);
+}
+
+void AppPythonUICallbacks::on_print_report(const Glib::ustring& report_name)
+{
+  Application* app = Application::get_application();
+  if(app)
+    app->print_report(report_name);
+}
+
+void AppPythonUICallbacks::on_print_layout()
+{
+  Application* app = Application::get_application();
+  if(app)
+    app->print_layout();
+}
+
+void AppPythonUICallbacks::on_start_new_record()
+{
+  Application* app = Application::get_application();
+  if(app)
+    app->start_new_record();
+}
+
+} //namespace Glom
diff --git a/glom/python_embed/python_ui_callbacks.h b/glom/python_embed/python_ui_callbacks.h
new file mode 100644
index 0000000..4b973a4
--- /dev/null
+++ b/glom/python_embed/python_ui_callbacks.h
@@ -0,0 +1,47 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2010 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GLOM_PYTHON_EMBED_UI_CALLBACKS_H
+#define GLOM_PYTHON_EMBED_UI_CALLBACKS_H
+
+#include <libglom/python_embed/py_glom_ui_callbacks.h>
+
+namespace Glom
+{
+
+/** UI code should connect to the signals to respond when Python code
+ * request a change in the UI.
+ */
+class AppPythonUICallbacks : public PythonUICallbacks
+{
+public:
+  AppPythonUICallbacks();
+
+private:
+  void on_show_table_details(const Glib::ustring& table_name, const Gnome::Gda::Value& primary_key_value);
+  void on_show_table_list(const Glib::ustring& table_name);
+  void on_print_report(const Glib::ustring& report_name);
+  void on_print_layout();
+  void on_start_new_record();
+};
+
+} //namespace Glom
+
+#endif //GLOM_PYTHON_GLOM_UI_H



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