[glom] Show a specific error message when the flie format is too new.



commit ad518bba83f87a9423a1c151770eecbfd65b4826
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Jun 4 22:50:10 2009 +0200

    Show a specific error message when the flie format is too new.
    
    * glom/libglom/document/bakery/document.[h|cc]:
    * glom/libglom/document/bakery/document_xml.[h|cc]: load(),
    load_after(): Take a int& failure_code output parameter to allow
    derived document classes to report a custom failure code.
    * glom/libglom/document/document.[h|cc]: load_after(): Return a
    custom failure_code for a too-new file version.
    * glom/bakery/app_withdoc.[h|cc]:
    Add a virtual ui_warning_load_failed(int failure_code) method that
    derived classes can override to respond to their own failure codes,
    with a generic default error message.
    open_document(), open_document_from_data(): Use the new method instead
    of hard-coding the error message.
    
    * glom/application.[h|cc]:
    open_browsed_document(), on_menu_developer_changelanguage(): Adapt.
    Add an override of ui_warning_load_failed() to show
    our custom error dialog in response to our custom failure code.
    * glom/libglom/test_document.cc: Apapted.
    
    Exceptions might be purer and need less code changes, but they would
    just be a container for an int failure code and it would be easier to
    not catch the error.
    This fixed bug #567102.
---
 ChangeLog                                    |   28 ++++++++++++++++++++++++++
 glom/application.cc                          |   22 ++++++++++++++++---
 glom/application.h                           |    3 ++
 glom/bakery/app_withdoc.cc                   |   15 ++++++++++---
 glom/bakery/app_withdoc.h                    |    7 ++++++
 glom/libglom/document/bakery/document.cc     |   17 +++++++++++----
 glom/libglom/document/bakery/document.h      |   12 ++++++----
 glom/libglom/document/bakery/document_xml.cc |    7 ++++-
 glom/libglom/document/bakery/document_xml.h  |    2 +-
 glom/libglom/document/document.cc            |   14 ++++++++----
 glom/libglom/document/document.h             |   10 +++++++-
 glom/libglom/test_document.cc                |    3 +-
 12 files changed, 111 insertions(+), 29 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 32ae54a..897a26d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,33 @@
 2009-06-04  Murray Cumming  <murrayc murrayc com>
 
+	Show a specific error message when the flie format is too new.
+
+	* glom/libglom/document/bakery/document.[h|cc]: 
+	* glom/libglom/document/bakery/document_xml.[h|cc]: load(), 
+	load_after(): Take a int& failure_code output parameter to allow 
+	derived document classes to report a custom failure code.
+	* glom/libglom/document/document.[h|cc]: load_after(): Return a 
+	custom failure_code for a too-new file version.
+	* glom/bakery/app_withdoc.[h|cc]:
+	Add a virtual ui_warning_load_failed(int failure_code) method that 
+	derived classes can override to respond to their own failure codes, 
+	with a generic default error message.
+	open_document(), open_document_from_data(): Use the new method instead 
+	of hard-coding the error message.
+
+	* glom/application.[h|cc]:
+	open_browsed_document(), on_menu_developer_changelanguage(): Adapt.
+	Add an override of ui_warning_load_failed() to show 
+	our custom error dialog in response to our custom failure code.
+	* glom/libglom/test_document.cc: Apapted.
+
+	Exceptions might be purer and need less code changes, but they would 
+	just be a container for an int failure code and it would be easier to 
+	not catch the error.
+	This fixed bug #567102.
+
+2009-06-04  Murray Cumming  <murrayc murrayc com>
+
 	* glom/libglom/data_structure/layout/layoutitem_portal.cc:
 	get_navigation_relationship_specific(): Remove unnecessary this-> to 
 	be consistent with the rest of the code.
diff --git a/glom/application.cc b/glom/application.cc
index fee7798..096835a 100644
--- a/glom/application.cc
+++ b/glom/application.cc
@@ -670,6 +670,18 @@ static bool hostname_is_localhost(const Glib::ustring& hostname)
   return true;
 }
 
+void App_Glom::ui_warning_load_failed(int failure_code)
+{
+  if(failure_code == Document::LOAD_FAILURE_CODE_FILE_VERSION_TOO_NEW)
+  {
+    ui_warning(_("Open Failed."), 
+      _("The document could not be opened because it was created or modified by a newer version of Glom."));
+  }
+  else
+    GlomBakery::App_WithDoc_Gtk::ui_warning_load_failed();
+}
+
+
 #ifndef G_OS_WIN32
 void App_Glom::open_browsed_document(const EpcServiceInfo* server, const Glib::ustring& service_name)
 {
@@ -738,7 +750,8 @@ void App_Glom::open_browsed_document(const EpcServiceInfo* server, const Glib::u
   {
     //Create a temporary Document instance, so we can manipulate the data:
     Document document_temp;
-    const bool loaded = document_temp.load_from_data((const guchar*)document_contents, length);
+    int failure_code = 0;
+    const bool loaded = document_temp.load_from_data((const guchar*)document_contents, length, failure_code);
     if(loaded)
     {
       // Connection is always remote-hosted in client only mode:
@@ -758,13 +771,13 @@ void App_Glom::open_browsed_document(const EpcServiceInfo* server, const Glib::u
       if(hostname_is_localhost(host))
         document_temp.set_connection_server( epc_service_info_get_host(server) );
 
-      //Make sure that we only use the specified port instead of connectin to some other postgres instance 
+      //Make sure that we only use the specified port instead of connecting to some other postgres instance 
       //on the same server:
       document_temp.set_connection_try_other_ports(false);
     }
     else
     {
-      std::cerr << "Could not parse the document that was retrieved over the network." << std::endl;
+      std::cerr << "Could not parse the document that was retrieved over the network: failure_code=" << failure_code << std::endl;
     }
 
     g_free(document_contents);
@@ -2393,7 +2406,8 @@ void App_Glom::on_menu_developer_changelanguage()
 
        //Get the translations from the document (in Operator mode, we only load the necessary translations.)
        //This also updates the UI, so we show all the translated titles:
-       get_document()->load();
+       int failure_code = 0;
+       get_document()->load(failure_code);
 
        m_pFrame->show_table_refresh(); //load() doesn't seem to refresh the view.
       }
diff --git a/glom/application.h b/glom/application.h
index 22fa3f7..56a8f51 100644
--- a/glom/application.h
+++ b/glom/application.h
@@ -89,6 +89,9 @@ public:
 
   static App_Glom* get_application();
 
+protected:
+  virtual void ui_warning_load_failed(int failure_code = 0); //Override.
+
 private:
   virtual void init_layout(); //override.
   virtual void init_menus_file(); //override.
diff --git a/glom/bakery/app_withdoc.cc b/glom/bakery/app_withdoc.cc
index 39ad0f9..867cc6d 100644
--- a/glom/bakery/app_withdoc.cc
+++ b/glom/bakery/app_withdoc.cc
@@ -70,7 +70,8 @@ void App_WithDoc::on_menu_file_close()
 
 bool App_WithDoc::open_document_from_data(const guchar* data, std::size_t length)
 {
-  const bool bTest = m_pDocument->load_from_data(data, length);
+  int failure_code = 0;
+  const bool bTest = m_pDocument->load_from_data(data, length, failure_code);
 
   bool bOpenFailed = false;
   if(!bTest) //if open failed.
@@ -92,7 +93,7 @@ bool App_WithDoc::open_document_from_data(const guchar* data, std::size_t length
 
   if(bOpenFailed)
   {
-    ui_warning(_("Open failed."), _("The document could not be opened."));
+    ui_warning_load_failed(failure_code);
 
     return false; //failed.
   }
@@ -117,7 +118,8 @@ bool App_WithDoc::open_document(const Glib::ustring& file_uri)
 
     //Open it.
     pApp->m_pDocument->set_file_uri(file_uri);
-    bool bTest = pApp->m_pDocument->load();
+    int failure_code = 0;
+    const bool bTest = pApp->m_pDocument->load(failure_code);
 
     bool bOpenFailed = false;
     if(!bTest) //if open failed.
@@ -145,7 +147,7 @@ bool App_WithDoc::open_document(const Glib::ustring& file_uri)
 
     if(bOpenFailed)
     {
-      ui_warning(_("Open failed."), _("The document could not be opened."));
+      ui_warning_load_failed(failure_code);
 
       //re-initialize document.
       delete pApp->m_pDocument;
@@ -488,5 +490,10 @@ void App_WithDoc::document_history_remove(const Glib::ustring& /* file_uri */)
   //Override this.
 }
 
+void App_WithDoc::ui_warning_load_failed(int failure_code)
+{
+  ui_warning(_("Open Failed."), _("The document could not be opened."));
+}
+
 } //namespace
 
diff --git a/glom/bakery/app_withdoc.h b/glom/bakery/app_withdoc.h
index 1450f65..71cdbbc 100644
--- a/glom/bakery/app_withdoc.h
+++ b/glom/bakery/app_withdoc.h
@@ -148,6 +148,13 @@ protected:
   virtual void after_successful_save(); //e.g. disable File|Save.
 
   virtual void ui_warning(const Glib::ustring& text, const Glib::ustring& secondary_text) = 0;
+
+  /** Warn the user about a failure while loading a document.
+   * Override this to show a specific message in response to your application's 
+   * custom @a failure_code.
+   */
+  virtual void ui_warning_load_failed(int failure_code = 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.
diff --git a/glom/libglom/document/bakery/document.cc b/glom/libglom/document/bakery/document.cc
index 706df84..3a467b5 100644
--- a/glom/libglom/document/bakery/document.cc
+++ b/glom/libglom/document/bakery/document.cc
@@ -117,12 +117,15 @@ bool Document::get_modified() const
   return m_bModified;
 }
 
-bool Document::load()
+bool Document::load(int& failure_code)
 {
+  //Initialize the output parameter:
+  failure_code = 0;
+
   bool bTest = read_from_disk();
   if(bTest)
   {
-    bTest = load_after(); //may be overridden.
+    bTest = load_after(failure_code); //may be overridden.
     if(bTest)
     {
       //Tell the View to show the new data:
@@ -134,14 +137,17 @@ bool Document::load()
   return bTest;
 }
 
-bool Document::load_from_data(const guchar* data, std::size_t length)
+bool Document::load_from_data(const guchar* data, std::size_t length, int& failure_code)
 {
   if(!data || !length)
     return false;
 
+  //Initialize the output parameter:
+  failure_code = 0;
+
   m_strContents = Glib::ustring((char*)data, length);
  
-  const bool bTest = load_after(); //may be overridden.
+  const bool bTest = load_after(failure_code); //may be overridden.
   if(bTest)
   {
     //Tell the View to show the new data:
@@ -154,13 +160,14 @@ bool Document::load_from_data(const guchar* data, std::size_t length)
 
 
 
-bool Document::load_after()
+bool Document::load_after(int& failure_code)
 {
   //Called after text is read from disk, but before updating view.
 
   //Override this if necessary.
   //For instance, Document_XML parses the XML.
 
+  failure_code = 0;
   return true;
 }
 
diff --git a/glom/libglom/document/bakery/document.h b/glom/libglom/document/bakery/document.h
index a50ddeb..5ca2b40 100644
--- a/glom/libglom/document/bakery/document.h
+++ b/glom/libglom/document/bakery/document.h
@@ -47,15 +47,15 @@ public:
 
   /* Loads data from disk, using the URI (set with set_file_uri()) then asks the View to update itself.
    * bool indicates success.
+   * @param failure_code Used to return a custom error code that is understood by your application.
    */
-  bool load();
+  bool load(int& failure_code);
 
-  //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.
+   * @param failure_code Used to return a custom error code that is understood by your application.
    */
-  bool load_from_data(const guchar* data, std::size_t length);
+  bool load_from_data(const guchar* data, std::size_t length, int& failure_code);
 
 
   bool get_modified() const;
@@ -108,10 +108,12 @@ public:
   ///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.
+   * @param failure_code Used to return a custom error code that is understood by your application.
    */
-  virtual bool load_after();
+  virtual bool load_after(int& failure_code);
 
   /** overrideable.
    * Does anything which should be done before the view has saved its data, before writing to disk..
diff --git a/glom/libglom/document/bakery/document_xml.cc b/glom/libglom/document/bakery/document_xml.cc
index 8d8a21f..7ccef28 100644
--- a/glom/libglom/document/bakery/document_xml.cc
+++ b/glom/libglom/document/bakery/document_xml.cc
@@ -34,9 +34,12 @@ Document_XML::~Document_XML()
   //m_pDOM_Document is owned by m_DOM_Document;
 }
 
-bool Document_XML::load_after()
+bool Document_XML::load_after(int& failure_code)
 {
-  bool bTest = type_base::load_after();
+  //Initialize the output parameter:
+  failure_code = 0;
+
+  const bool bTest = type_base::load_after(failure_code);
   if(!bTest)
     return false; //Failed.
 
diff --git a/glom/libglom/document/bakery/document_xml.h b/glom/libglom/document/bakery/document_xml.h
index 44eed4a..5ca2149 100644
--- a/glom/libglom/document/bakery/document_xml.h
+++ b/glom/libglom/document/bakery/document_xml.h
@@ -38,7 +38,7 @@ public:
   virtual ~Document_XML();
 
   //overrides:
-  virtual bool load_after();
+  virtual bool load_after(int& failure_code);
   virtual bool save_before();
 
   void set_dtd_name(const std::string& strVal); //e.g. "glom.dtd"
diff --git a/glom/libglom/document/document.cc b/glom/libglom/document/document.cc
index 57298a9..85ba111 100644
--- a/glom/libglom/document/document.cc
+++ b/glom/libglom/document/document.cc
@@ -2328,8 +2328,11 @@ void Document::load_after_print_layout_position(const xmlpp::Element* nodeItem,
   }
 }
 
-bool Document::load_after()
+bool Document::load_after(int& failure_code)
 {
+  //Initialize the output variable:
+  failure_code = 0;
+
   //TODO: Use some callback UI to show a busy cursor?
   /*
   //Use a std::auto_ptr<> to avoid even unncessarily instantiating a BusyCursor,
@@ -2341,7 +2344,7 @@ bool Document::load_after()
   
   m_block_modified_set = true; //Prevent the set_ functions from trigerring a save.
 
-  bool result = GlomBakery::Document_XML::load_after();  
+  bool result = GlomBakery::Document_XML::load_after(failure_code);  
 
   m_block_cache_update = true; //Don't waste time repeatedly updating this until we have finished.
 
@@ -2355,7 +2358,8 @@ bool Document::load_after()
       if(m_document_format_version > get_latest_known_document_format_version())
       {
         std::cerr << "Document::load_after(): Loading failed because format_version=" << m_document_format_version << ", but latest known format version is " << get_latest_known_document_format_version() << std::endl;
-        return false; //TODO: Provide more information so the application (or Bakery) can say exactly why loading failed.
+        failure_code = LOAD_FAILURE_CODE_FILE_VERSION_TOO_NEW;
+        return false;
       }
       
       m_is_example = get_node_attribute_value_as_bool(nodeRoot, GLOM_ATTRIBUTE_IS_EXAMPLE);
@@ -4151,9 +4155,9 @@ bool Document::get_opened_from_browse() const
   return m_opened_from_browse;
 }
 
-bool Document::load()
+bool Document::load(int& failure_code)
 {
-  return GlomBakery::Document_XML::load();
+  return GlomBakery::Document_XML::load(failure_code);
 }
 
 
diff --git a/glom/libglom/document/document.h b/glom/libglom/document/document.h
index bf5669a..9d1dad8 100644
--- a/glom/libglom/document/document.h
+++ b/glom/libglom/document/document.h
@@ -66,7 +66,7 @@ public:
    * bool indicates success.
    * This is just here so the SWIG Java API generator does not need to wrap methods from the base classes.
    */
-  bool load();
+  bool load(int& failure_code);
   
   
   /** Whether the document was opened from another networked glom instance, 
@@ -436,6 +436,12 @@ public:
   static bool get_relationship_is_system_properties(const sharedptr<const Relationship>& relationship);
 #endif //SWIG
 
+  /// Failure codes that could be returned by load_after()
+  enum load_failure_codes
+  {
+    LOAD_FAILURE_CODE_FILE_VERSION_TOO_NEW
+  };
+
 private:
   //Overrides:
 
@@ -453,7 +459,7 @@ private:
   void save_changes();
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
-  virtual bool load_after();
+  virtual bool load_after(int& failure_code);
   void load_after_layout_group(const xmlpp::Element* node, const Glib::ustring& table_name, const sharedptr<LayoutGroup>& group, bool with_print_layout_positions = false);
   void load_after_sort_by(const xmlpp::Element* node, const Glib::ustring& table_name, LayoutItem_GroupBy::type_list_sort_fields& list_fields);
   void load_after_layout_item_usesrelationship(const xmlpp::Element* element, const Glib::ustring& table_name, const sharedptr<UsesRelationship>& item);
diff --git a/glom/libglom/test_document.cc b/glom/libglom/test_document.cc
index 5c0bfa1..c4a03e1 100644
--- a/glom/libglom/test_document.cc
+++ b/glom/libglom/test_document.cc
@@ -92,7 +92,8 @@ int main()
   // Load the document:
   Glom::Document document;
   document.set_file_uri(uri);
-  bool test = document.load();
+  int failure_code = 0;
+  const bool test = document.load(failure_code);
   std::cout << "Document load result=" << test << std::endl;
 
   if(!test)



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