glom r1774 - in trunk: . glom glom/libglom/data_structure glom/libglom/document glom/mode_data glom/utility_widgets/db_adddel



Author: murrayc
Date: Thu Dec  4 21:26:30 2008
New Revision: 1774
URL: http://svn.gnome.org/viewvc/glom?rev=1774&view=rev

Log:
2008-12-04  Murray Cumming  <murrayc murrayc com>

* glom/libglom/data_structure/foundset.[h|cc]: Added has_no_criteria() 
to check if it has a sort order or where clause.
* glom/libglom/document/document_glom.[h|cc]: Added 
set_criteria_current(), like set_layout_current(), so we can 
temporarily remember the sort (and find) for a table while navigating.
DocumentTableInfo: Hand-wrote copy constructor and operator=() rather 
than depend on generated ones.
* glom/utility_widgets/db_adddel/db_adddel.[h|cc]: 
Added signal_sort_clause_changed, emitted when the user clicks on 
the column header, which already caused a refresh with that sort.
* glom/mode_data/box_data_list.[h|cc]: Respond to a sort change in the 
DbAddDel widget, saving it temporarily in the document.
* glom/mode_data/frame_glom.cc: show_table(): Use the remembered 
criteria, from the document, where there is one.

Ubuntu bug https://bugs.launchpad.net/ubuntu/+source/glom/+bug/303422
(elmergato)

Modified:
   trunk/ChangeLog
   trunk/glom/frame_glom.cc
   trunk/glom/libglom/data_structure/foundset.cc
   trunk/glom/libglom/data_structure/foundset.h
   trunk/glom/libglom/document/document_glom.cc
   trunk/glom/libglom/document/document_glom.h
   trunk/glom/mode_data/box_data_list.cc
   trunk/glom/mode_data/box_data_list.h
   trunk/glom/mode_data/notebook_data.cc
   trunk/glom/utility_widgets/db_adddel/db_adddel.cc
   trunk/glom/utility_widgets/db_adddel/db_adddel.h

Modified: trunk/glom/frame_glom.cc
==============================================================================
--- trunk/glom/frame_glom.cc	(original)
+++ trunk/glom/frame_glom.cc	Thu Dec  4 21:26:30 2008
@@ -236,8 +236,8 @@
 
 void Frame_Glom::on_box_tables_selected(const Glib::ustring& strName)
 {
-  if (m_pDialog_Tables)
-    m_pDialog_Tables->hide(); //cause_close();
+  if(m_pDialog_Tables)
+    m_pDialog_Tables->hide();
 
   show_table(strName);
 }
@@ -365,29 +365,42 @@
       {
         strMode = _("Data");
         FoundSet found_set;
+
+        //Start with the last-used found set (sort order and where clause)
+        //for this layout:
+        //(This would be ignored anyway if a details primary key is specified.)
+        Document_Glom* document = get_document(); 
+        if(document)
+          found_set = document->get_criteria_current(m_table_name);
+
+        //Make sure that this is set:
         found_set.m_table_name = m_table_name;
 
-        //Sort by the ID, just so we sort by something, so that the order is predictable:
-        sharedptr<Field> field_primary_key = get_field_primary_key_for_table(m_table_name);
-        if(field_primary_key)
+        //If there is no saved sort clause, 
+        //then sort by the ID, just so we sort by something, so that the order is predictable:
+        if(found_set.m_sort_clause.empty())
         {
-          sharedptr<LayoutItem_Field> layout_item_sort = sharedptr<LayoutItem_Field>::create();
-          layout_item_sort->set_full_field_details(field_primary_key);
+          sharedptr<Field> field_primary_key = get_field_primary_key_for_table(m_table_name);
+          if(field_primary_key)
+          {
+            sharedptr<LayoutItem_Field> layout_item_sort = sharedptr<LayoutItem_Field>::create();
+            layout_item_sort->set_full_field_details(field_primary_key);
 
-          found_set.m_sort_clause.clear();
+            found_set.m_sort_clause.clear();
 
-          //Avoid the sort clause if the found set will include too many records, 
-          //because that would be too slow.
-          //The user can explicitly request a sort later, by clicking on a column header.
-          //TODO_Performance: This causes an almost-duplicate COUNT query (we do it in the treemodel too), but it's not that slow. 
-          sharedptr<LayoutItem_Field> layout_item_temp = sharedptr<LayoutItem_Field>::create();
-          layout_item_temp->set_full_field_details(field_primary_key);
-          type_vecLayoutFields layout_fields;
-          layout_fields.push_back(layout_item_temp);
-          const Glib::ustring sql_query_without_sort = Utils::build_sql_select_with_where_clause(found_set.m_table_name, layout_fields, found_set.m_where_clause, found_set.m_extra_join, type_sort_clause(), found_set.m_extra_group_by);
-          const int count = Base_DB::count_rows_returned_by(sql_query_without_sort);
-          if(count < 10000) //Arbitrary large number.
-            found_set.m_sort_clause.push_back( type_pair_sort_field(layout_item_sort, true /* ascending */) );
+            //Avoid the sort clause if the found set will include too many records, 
+            //because that would be too slow.
+            //The user can explicitly request a sort later, by clicking on a column header.
+            //TODO_Performance: This causes an almost-duplicate COUNT query (we do it in the treemodel too), but it's not that slow. 
+            sharedptr<LayoutItem_Field> layout_item_temp = sharedptr<LayoutItem_Field>::create();
+            layout_item_temp->set_full_field_details(field_primary_key);
+            type_vecLayoutFields layout_fields;
+            layout_fields.push_back(layout_item_temp);
+            const Glib::ustring sql_query_without_sort = Utils::build_sql_select_with_where_clause(found_set.m_table_name, layout_fields, found_set.m_where_clause, found_set.m_extra_join, type_sort_clause(), found_set.m_extra_group_by);
+            const int count = Base_DB::count_rows_returned_by(sql_query_without_sort);
+            if(count < 10000) //Arbitrary large number.
+              found_set.m_sort_clause.push_back( type_pair_sort_field(layout_item_sort, true /* ascending */) );
+          }
         }
 
         //Show the wanted records in the notebook, showing details for a particular record if wanted:

Modified: trunk/glom/libglom/data_structure/foundset.cc
==============================================================================
--- trunk/glom/libglom/data_structure/foundset.cc	(original)
+++ trunk/glom/libglom/data_structure/foundset.cc	Thu Dec  4 21:26:30 2008
@@ -56,6 +56,12 @@
       && (m_sort_clause == src.m_sort_clause);
 }
 
+bool FoundSet::has_no_criteria() const
+{
+  return m_where_clause.empty() &&
+    m_sort_clause.empty();
+}
+
 } //namespace Glom
 
 

Modified: trunk/glom/libglom/data_structure/foundset.h
==============================================================================
--- trunk/glom/libglom/data_structure/foundset.h	(original)
+++ trunk/glom/libglom/data_structure/foundset.h	Thu Dec  4 21:26:30 2008
@@ -30,6 +30,10 @@
 namespace Glom
 {
 
+/** A grouping of information about a view of a table, 
+ * including what records are viewed (the where clause),
+ * how the are  sorted (the sort clause).
+ */
 class FoundSet
 {
 public:
@@ -39,6 +43,10 @@
 
   bool operator==(const FoundSet& src) const;
 
+  /** Whether this specifies any where clause or sort order.
+   */
+  bool has_no_criteria() const;
+
   Glib::ustring m_table_name;
   Glib::ustring m_extra_join; // Only used for doubly-related related records (portals), in which case the WHERE clause is also slightly different.
   Glib::ustring m_where_clause;

Modified: trunk/glom/libglom/document/document_glom.cc
==============================================================================
--- trunk/glom/libglom/document/document_glom.cc	(original)
+++ trunk/glom/libglom/document/document_glom.cc	Thu Dec  4 21:26:30 2008
@@ -3733,7 +3733,18 @@
   type_tables::iterator iterFind = m_tables.find(table_name);
   if(iterFind != m_tables.end())
   {
-    iterFind->second.m_layout_current = layout_name;
+    DocumentTableInfo& table_info = iterFind->second; 
+    table_info.m_layout_current = layout_name;
+  }
+}
+
+void Document_Glom::set_criteria_current(const Glib::ustring& table_name, const FoundSet& found_set)
+{
+  type_tables::iterator iterFind = m_tables.find(table_name);
+  if(iterFind != m_tables.end())
+  {
+    DocumentTableInfo& table_info = iterFind->second; 
+    table_info.m_foundset_current = found_set; 
   }
 }
 
@@ -3742,12 +3753,26 @@
   type_tables::const_iterator iterFind = m_tables.find(table_name);
   if(iterFind != m_tables.end())
   {
-    return iterFind->second.m_layout_current;
+    const DocumentTableInfo& table_info = iterFind->second; 
+    return table_info.m_layout_current;
   }
 
   return Glib::ustring(); //not found.
 }
 
+FoundSet Document_Glom::get_criteria_current(const Glib::ustring& table_name) const
+{
+  type_tables::const_iterator iterFind = m_tables.find(table_name);
+  if(iterFind != m_tables.end())
+  {
+    const DocumentTableInfo& table_info = iterFind->second; 
+    return table_info.m_foundset_current;
+  }
+
+  return FoundSet();
+}
+
+
 bool Document_Glom::get_is_example_file() const
 {
   return m_is_example;

Modified: trunk/glom/libglom/document/document_glom.h
==============================================================================
--- trunk/glom/libglom/document/document_glom.h	(original)
+++ trunk/glom/libglom/document/document_glom.h	Thu Dec  4 21:26:30 2008
@@ -37,6 +37,7 @@
 #include <glom/libglom/data_structure/groupinfo.h>
 #include <glom/libglom/data_structure/report.h>
 #include <glom/libglom/data_structure/print_layout.h>
+#include <glom/libglom/data_structure/foundset.h>
 #include "../appstate.h"
 #include <gtkmm/window.h>
 #include <vector>
@@ -315,9 +316,29 @@
   void forget_layout_record_viewed(const Glib::ustring& table_name);
   Gnome::Gda::Value get_layout_record_viewed(const Glib::ustring& table_name, const Glib::ustring& layout_name) const;
 
+  //TODO: Rename set_layout_current() and set_criteria_current().
+
+  /** Temporarily save (but not in the document) the last-viewed layout for the table,
+   * so we can show the same layout when navigating back to this table later.
+   * 
+   * @param table_name The table.
+   * @param layout_name The layout name, such as "list" or "details".
+   */
   void set_layout_current(const Glib::ustring& table_name, const Glib::ustring& layout_name);
+
+  /** Temporarily save (but not in the document) the last-viewed criteria for the table,
+   * so we can show the same criteria (sort order, where clause) when navigating back to this table later.
+   * 
+   * @param table_name The table.
+   * @param found_set Additional information about the last use of that layout, such as the sort order or where clause.
+   */
+  void set_criteria_current(const Glib::ustring& table_name,const FoundSet& found_set);
+
   Glib::ustring get_layout_current(const Glib::ustring& table_name) const;
 
+  FoundSet get_criteria_current(const Glib::ustring& table_name) const;
+
+
   // Used by Relationship Overview dialog to preserve table locations accross instantiations:
     
   /** Retrieve the x and y coordinates for the given table position.
@@ -465,12 +486,46 @@
   {
   public:
     DocumentTableInfo()
-        : m_overviewx ( std::numeric_limits<float>::infinity () ),
-          m_overviewy ( std::numeric_limits<float>::infinity () )
+      : m_overviewx ( std::numeric_limits<float>::infinity () ),
+        m_overviewy ( std::numeric_limits<float>::infinity () )
     {
       m_info = sharedptr<TableInfo>(new TableInfo()); //Avoid a null sharedptr.
     }
 
+    //TODO: Avoid the use of this:
+    DocumentTableInfo(const DocumentTableInfo& src)
+      : m_fields(src.m_fields),
+        m_relationships(src.m_relationships),
+        m_layouts(src.m_layouts),
+        m_reports(src.m_reports),
+        m_print_layouts(src.m_print_layouts),
+        m_example_rows(src.m_example_rows),
+        m_map_current_record(src.m_map_current_record),
+        m_layout_current(src.m_layout_current),
+        m_foundset_current(src.m_foundset_current),
+        m_overviewx(src.m_overviewx),
+        m_overviewy(src.m_overviewy)
+    {
+    }
+
+    //TODO: Avoid the use of this:
+    DocumentTableInfo& operator=(const DocumentTableInfo& src)
+    {
+      m_fields = src.m_fields;
+      m_relationships = src.m_relationships;
+      m_layouts = src.m_layouts;
+      m_reports = src.m_reports;
+      m_print_layouts = src.m_print_layouts;
+      m_example_rows = src.m_example_rows;
+      m_map_current_record = src.m_map_current_record;
+      m_layout_current = src.m_layout_current;
+      m_foundset_current = src.m_foundset_current;
+      m_overviewx = src.m_overviewx;
+      m_overviewy = src.m_overviewy;
+
+      return *this;
+    }
+
     sharedptr<TableInfo> m_info;
 
     type_vecFields m_fields;
@@ -490,8 +545,8 @@
     //Per-session, not saved in document:
     typedef std::map<Glib::ustring, Gnome::Gda::Value> type_map_layout_primarykeys;
     type_map_layout_primarykeys m_map_current_record; //The record last viewed in each layout.
-
     Glib::ustring m_layout_current;
+    FoundSet m_foundset_current;
     
     float m_overviewx, m_overviewy;
   };

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	Thu Dec  4 21:26:30 2008
@@ -48,6 +48,7 @@
   //The Add and Delete buttons are handled by the DbAddDel widget itself.
   m_AddDel.signal_user_requested_edit().connect(sigc::mem_fun(*this, &Box_Data_List::on_adddel_user_requested_edit));
   m_AddDel.signal_script_button_clicked().connect(sigc::mem_fun(*this, &Box_Data_List::on_adddel_script_button_clicked));
+  m_AddDel.signal_sort_clause_changed().connect(sigc::mem_fun(*this, &Box_Data_List::on_adddel_user_sort_clause_changed));
   
   //TODO: Re-add this signal if this is really wanted, but make it part of a complete drag-and-drop feature for list views:
   //m_AddDel.signal_user_reordered_columns().connect(sigc::mem_fun(*this, &Box_Data_List::on_adddel_user_reordered_columns));
@@ -580,6 +581,19 @@
     refModelDerived->get_record_counts(total, found);
 }
 
+void Box_Data_List::on_adddel_user_sort_clause_changed()
+{
+  //Remember details about the previously viewed table, 
+  //so we don't forget the sort order and where clause when 
+  //navigating back, which would annoy the user:
+
+  m_found_set = m_AddDel.get_found_set();
+
+  Document_Glom* document = get_document(); 
+  if(document)
+    document->set_criteria_current(m_table_name, m_found_set);
+}
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 //overridden, so we can change the column widths, so they are all visible:
 void Box_Data_List::on_dialog_layout_hide()

Modified: trunk/glom/mode_data/box_data_list.h
==============================================================================
--- trunk/glom/mode_data/box_data_list.h	(original)
+++ trunk/glom/mode_data/box_data_list.h	Thu Dec  4 21:26:30 2008
@@ -91,6 +91,7 @@
   void on_adddel_user_requested_edit(const Gtk::TreeModel::iterator& row);
   void on_adddel_user_requested_delete(const Gtk::TreeModel::iterator& rowStart, const Gtk::TreeModel::iterator& rowEnd);
   void on_adddel_user_reordered_columns();
+  void on_adddel_user_sort_clause_changed();
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   void on_adddel_user_requested_layout();

Modified: trunk/glom/mode_data/notebook_data.cc
==============================================================================
--- trunk/glom/mode_data/notebook_data.cc	(original)
+++ trunk/glom/mode_data/notebook_data.cc	Thu Dec  4 21:26:30 2008
@@ -91,67 +91,52 @@
     // Ignore error, sharedconnection is not used directly within this function
 #endif
 
-    //const FoundSet old_found_set = m_Box_List.get_found_set();
-    //std::cout << "  old_where_clause=" << old_where_clause << std::endl;
-    //std::cout << "  where_clause=" << where_clause << std::endl;
-    //const bool new_find_set = !(found_set == old_found_set);
-
-    //if(get_current_view() == DATA_VIEW_List)
-    //{
-      result = m_Box_List.init_db_details(found_set, get_document()->get_active_layout_platform()); //TODO: Select the last selected record.
-      //m_Box_List.load_from_document();
-    //}
-    //else //DATA_VIEW_Details
-    //{
-      //Show the previously-shown record, if there is one, if this is not a new found-set (via a new where_clause)
-      //so that returning to this table will return the user to the same record:
-      Document_Glom* document = get_document();
-      if(document)
-      {
-        Gnome::Gda::Value primary_key_for_details;
+    result = m_Box_List.init_db_details(found_set, get_document()->get_active_layout_platform()); //TODO: Select the last selected record.
 
-        if(!details_record_specified)
-        {
-          //std::cout << "debug: no new_found_set" << std::endl;
-          primary_key_for_details = document->get_layout_record_viewed(m_table_name, m_Box_Details.get_layout_name());
-        }
-        else if(details_record_specified)
-        {
-          primary_key_for_details = primary_key_value_for_details;
-        }
-        else
-        {
-          //std::cout << "debug: new_found_set" << std::endl;
-        }
+    //Show the previously-shown record, if there is one, if this is not a new found-set (via a new where_clause)
+    //so that returning to this table will return the user to the same record:
+    Document_Glom* document = get_document();
+    if(document)
+    {
+      Gnome::Gda::Value primary_key_for_details;
 
+      if(!details_record_specified)
+      {
+        //std::cout << "debug: no new_found_set" << std::endl;
+        primary_key_for_details = document->get_layout_record_viewed(m_table_name, m_Box_Details.get_layout_name());
+      }
+      else if(details_record_specified)
+      {
+        primary_key_for_details = primary_key_value_for_details;
+      }
 
-        //If the specified (or remembered) primary key value is not in the found set, 
-        //then ignore it:
-        if(!found_set.m_where_clause.empty() && !get_primary_key_is_in_foundset(found_set, primary_key_for_details))
-        {
-          primary_key_for_details = Gnome::Gda::Value(); //TODO: We set it to empty just so we can test if for empty.
-        }
+      //If the specified (or remembered) primary key value is not in the found set, 
+      //then ignore it:
+      if(!found_set.m_where_clause.empty() && !get_primary_key_is_in_foundset(found_set, primary_key_for_details))
+      {
+        primary_key_for_details = Gnome::Gda::Value(); //TODO: We set it to empty just so we can test if for empty.
+      }
 
+      if(Conversions::value_is_empty(primary_key_for_details))
+      {
+        //Make sure that the details view is not empty, if there are any records to show:
+        primary_key_for_details = m_Box_List.get_primary_key_value_selected();
+        //std::cout << "debug:  m_Box_List.get_primary_key_value_selected()=" << primary_key_for_details.to_string() << std::endl;
         if(Conversions::value_is_empty(primary_key_for_details))
         {
-          //Make sure that the details view is not empty, if there are any records to show:
-          primary_key_for_details = m_Box_List.get_primary_key_value_selected();
-          //std::cout << "debug:  m_Box_List.get_primary_key_value_selected()=" << primary_key_for_details.to_string() << std::endl;
-          if(Conversions::value_is_empty(primary_key_for_details))
-          {
-            //std::cout << "debug: calling list.get_primary_key_value_first()" << std::endl;
-            primary_key_for_details = m_Box_List.get_primary_key_value_first();
-            //std::cout << "  debug:  result=" <<  primary_key_for_details.to_string() << std::endl;
-          }
+          //std::cout << "debug: calling list.get_primary_key_value_first()" << std::endl;
+          primary_key_for_details = m_Box_List.get_primary_key_value_first();
+          //std::cout << "  debug:  result=" <<  primary_key_for_details.to_string() << std::endl;
         }
-
-        m_Box_Details.init_db_details(found_set, get_document()->get_active_layout_platform(), primary_key_for_details);
       }
-      else
-        std::cerr << "Notebook_Data::init_db_details(): document is NULL" << std::endl;
-    //}
+
+      m_Box_Details.init_db_details(found_set, get_document()->get_active_layout_platform(), primary_key_for_details);
+    }
+    else
+      std::cerr << "Notebook_Data::init_db_details(): document is NULL" << std::endl;
   }
 
+
   //Block this handler temporarily because we don't need another refresh from the database:
   if(m_connection_switch_page)
     m_connection_switch_page.block();
@@ -166,17 +151,20 @@
   }
   else
   {
-    //Select the last-viewed layout:
-    Document_Glom* document = get_document();
-    
-    if(document)
+    //Get information abvout the the last-viewed layout:
+    Glib::ustring current_layout;
+    if(!details_record_specified)
     {
-      const Glib::ustring current_layout = get_document()->get_layout_current(m_table_name);
-      if( (current_layout.empty() || (current_layout == "list")) && (current_view != DATA_VIEW_List) )
-        set_current_view(DATA_VIEW_List);
-      else if( (current_layout == "details") && (current_view != DATA_VIEW_Details) )
-        set_current_view(DATA_VIEW_Details);
+      Document_Glom* document = get_document(); 
+      if(document)
+        current_layout = document->get_layout_current(m_table_name);
     }
+
+    //Set the layout:
+    if( (current_layout.empty() || (current_layout == "list")) && (current_view != DATA_VIEW_List) )
+      set_current_view(DATA_VIEW_List);
+    else if( (current_layout == "details") && (current_view != DATA_VIEW_Details) )
+      set_current_view(DATA_VIEW_Details);
   }
 
   //Re-enable this handler, so we can respond to notebook page changes:

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	Thu Dec  4 21:26:30 2008
@@ -1641,6 +1641,11 @@
   return m_signal_record_added;
 }
 
+DbAddDel::type_signal_sort_clause_changed DbAddDel::signal_sort_clause_changed()
+{
+  return m_signal_sort_clause_changed;
+}
+
 void DbAddDel::on_treeview_button_press_event(GdkEventButton* event)
 {
   on_button_press_event_Popup(event);
@@ -1761,6 +1766,8 @@
   }
 
   refresh_from_database();
+
+  m_signal_sort_clause_changed.emit();
 }
 
 void DbAddDel::on_treeview_columns_changed()

Modified: trunk/glom/utility_widgets/db_adddel/db_adddel.h
==============================================================================
--- trunk/glom/utility_widgets/db_adddel/db_adddel.h	(original)
+++ trunk/glom/utility_widgets/db_adddel/db_adddel.h	Thu Dec  4 21:26:30 2008
@@ -246,6 +246,13 @@
   typedef sigc::signal<void, const Gtk::TreeModel::iterator&, const Gnome::Gda::Value&> type_signal_record_added;
   type_signal_record_added signal_record_added();
     
+
+  /** Emitted when the user changed the sort order, 
+   * for instance by clicking on a column header.
+   */
+  typedef sigc::signal<void> type_signal_sort_clause_changed;
+  type_signal_sort_clause_changed signal_sort_clause_changed();
+
  
   virtual Gtk::TreeModel::iterator get_last_row();
   virtual Gtk::TreeModel::iterator get_last_row() const;
@@ -399,13 +406,15 @@
   bool m_allow_view_details;
   Gtk::TreeViewColumn* m_treeviewcolumn_button;
 
-  //signals:
+  //Signals:
   type_signal_user_requested_edit m_signal_user_requested_edit;
+  type_signal_script_button_clicked m_signal_script_button_clicked;
+  type_signal_record_added m_signal_record_added;
+  type_signal_sort_clause_changed m_signal_sort_clause_changed;
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   type_signal_user_requested_layout m_signal_user_requested_layout;
 #endif // !GLOM_ENABLE_CLIENT_ONLY
-  type_signal_script_button_clicked m_signal_script_button_clicked;
-  type_signal_record_added m_signal_record_added;
     
   //TODO: Do this properly:
   //type_signal_user_added m_signal_record_count_changed;



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