glom r1582 - trunk/glom/mode_data



Author: murrayc
Date: Tue Apr 22 10:02:46 2008
New Revision: 1582
URL: http://svn.gnome.org/viewvc/glom?rev=1582&view=rev

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

* examples/example_lesson_planner.glom:
* examples/Makefile.am: Added a new example, which uses a calendar.

* glom/mode_data/box_data_calendar_related.h
* glom/mode_data/box_data_calendar_related.cc:
fill_from_database(): Do one SQL query for the whole month and store 
the values.
on_calendar_details(): Show the stored values.
* glom/mode_data/box_data_list_related.cc:
* glom/mode_data/box_data_list_related.h: Removed get_fields_to_show() 
because it is in the base class.

Modified:
   trunk/glom/mode_data/box_data_calendar_related.cc
   trunk/glom/mode_data/box_data_calendar_related.h
   trunk/glom/mode_data/box_data_list_related.cc
   trunk/glom/mode_data/box_data_list_related.h

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 Apr 22 10:02:46 2008
@@ -30,7 +30,8 @@
 {
 
 Box_Data_Calendar_Related::Box_Data_Calendar_Related()
-: m_pMenuPopup(0)
+: m_pMenuPopup(0),
+  m_query_column_date_field(-1)
 {
   set_size_request(400, -1); //An arbitrary default.
 
@@ -38,6 +39,10 @@
   m_Alignment.add(m_calendar);
   m_calendar.show();
   
+  //m_calendar.set_show_details();
+  m_calendar.set_detail_width_chars(7);
+  m_calendar.set_detail_height_rows(2); 
+  
   //Tell the calendar how to get the record details to show:
   m_calendar.set_detail_func( sigc::mem_fun(*this, &Box_Data_Calendar_Related::on_calendar_details) );
   
@@ -48,6 +53,11 @@
   m_layout_name = "list_related_calendar"; //TODO: We need a unique name when 2 portals use the same table.
 }
 
+Box_Data_Calendar_Related::~Box_Data_Calendar_Related()
+{
+  clear_cached_database_values();
+}
+
 void Box_Data_Calendar_Related::enable_buttons()
 {
   //const bool view_details_possible = get_has_suitable_record_to_view_details();
@@ -89,8 +99,10 @@
 
 bool Box_Data_Calendar_Related::fill_from_database()
 {
+  if(!m_portal)
+    return false;
+  
   bool result = false;
-  bool allow_add = true;
 
   if(m_key_field && m_found_set.m_where_clause.empty()) //There's a key field, but no value.
   {
@@ -104,31 +116,102 @@
   }
   else
   {
-    result = Box_Data_List::fill_from_database();
-
+    if(m_query_column_date_field == -1)
+      return false; //This is useless without the date in the result.
+       
+    //Create a date range from the beginning to end of the selected month:
+    Glib::Date calendar_date;
+    m_calendar.get_date(calendar_date);
+    const Glib::Date date_start(1, calendar_date.get_month(), calendar_date.get_year());
+    Glib::Date date_end = date_start;
+    date_end.add_months(1);
+    
+    Gnome::Gda::Value date_start_value(date_start);
+    Gnome::Gda::Value date_end_value(date_end);
 
-    //Is there already one record here?
-    if(m_has_one_or_more_records) //This was set by Box_Data_List::fill_from_database().
+    //Add a WHERE clause for this date range:
+    sharedptr<Relationship> relationship = m_portal->get_relationship();
+    Glib::ustring where_clause_to_table_name = relationship->get_to_table();
+  
+    sharedptr<LayoutItem_CalendarPortal> derived_portal = sharedptr<LayoutItem_CalendarPortal>::cast_dynamic(m_portal);
+    const Glib::ustring date_field_name = derived_portal->get_date_field()->get_name();
+    
+    sharedptr<const Relationship> relationship_related = m_portal->get_related_relationship();
+    if(relationship_related)
     {
-      //Is the to_field unique? If so, there can not be more than one.
-      if(m_key_field && m_key_field->get_unique_key()) //automatically true if it is a primary key
-        allow_add = false;
+      //Adjust the WHERE clause appropriately for the extra JOIN:
+      sharedptr<UsesRelationship> uses_rel_temp = sharedptr<UsesRelationship>::create();
+      uses_rel_temp->set_relationship(relationship);
+      where_clause_to_table_name = uses_rel_temp->get_sql_join_alias_name();
     }
 
-    //TODO: Disable add if the from_field already has a value and the to_field is auto-incrementing because
-    //- we cannot override the auto-increment in the to_field.
-    //- we cannot change the value in the from_field to the new auto_increment value in the to_field.
+    //Add an AND to the existing where clause, to get only records within these dates, if any:
+    sharedptr<const Field> date_field = derived_portal->get_date_field();
+    const Glib::ustring extra_where_clause = "\"" + where_clause_to_table_name + "\".\"" + date_field->get_name() + "\""
+      " BETWEEN DATE " + date_field->sql(date_start_value) + 
+      " AND DATE " + date_field->sql(date_end_value);
+    
+    Glib::ustring where_clause;
+    if(m_found_set.m_where_clause.empty())
+      where_clause = extra_where_clause;
+    else
+      where_clause = "( " + m_found_set.m_where_clause + " ) AND ( " + extra_where_clause + " )";
+    
+    
+    //Do one SQL query for the whole month and store the cached values here:
+    clear_cached_database_values();
+    
+    const Glib::ustring sql_query = Utils::build_sql_select_with_where_clause(m_found_set.m_table_name, m_FieldsShown, where_clause, m_found_set.m_extra_join, m_found_set.m_sort_clause, m_found_set.m_extra_group_by);
+    //std::cout << "DEBUG: sql_query=" << sql_query << std::endl;
+    Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute(sql_query, get_app_window());
+    if(!(datamodel))
+      return true;
+    
+    const int rows_count = datamodel->get_n_rows();
+    if(!(rows_count > 0))
+      return true;
+    
+    //Get the data:
+    for(int row_index = 0; row_index < rows_count; ++row_index)
+    {
+      const int columns_count = datamodel->get_n_columns();
+      if(m_query_column_date_field > columns_count)
+       continue;
+       
+      //Get the date value for this row:
+      Gnome::Gda::Value value_date = datamodel->get_value_at(m_query_column_date_field, row_index);     
+      const Glib::Date date = value_date.get_date();
+      
+      //Get all the values for this row:
+      type_vector_values* pVector = new type_vector_values(m_FieldsShown.size());
+      for(int column_index = 0; column_index < columns_count; ++column_index)
+      {
+        (*pVector)[column_index] = datamodel->get_value_at(column_index, row_index);
+      }
+      
+      m_map_values[date].push_back(pVector);
+    }
   }
 
-  //Prevent addition of new records if that is what the relationship specifies:
-  if(allow_add && m_portal->get_relationship())
-    allow_add = m_portal->get_relationship()->get_auto_create();
-
-  //TODO: m_calendar.set_allow_add(allow_add);
-
+ 
   return result;
 }
 
+void Box_Data_Calendar_Related::clear_cached_database_values()
+{
+  for(type_map_values::iterator iter = m_map_values.begin(); iter != m_map_values.end(); ++iter)
+  {
+    type_list_vectors vec = iter->second;
+    for(type_list_vectors::iterator iter = vec.begin(); iter != vec.end(); ++iter)
+    {
+      type_vector_values* pValues = *iter;
+      if(pValues)
+        delete pValues;
+    }
+  }
+  
+  m_map_values.clear(); 
+}
 void Box_Data_Calendar_Related::on_record_added(const Gnome::Gda::Value& primary_key_value, const Gtk::TreeModel::iterator& row)
 {
   //primary_key_value is a new autogenerated or human-entered key for the row.
@@ -194,33 +277,22 @@
 
 Box_Data_Calendar_Related::type_vecLayoutFields Box_Data_Calendar_Related::get_fields_to_show() const
 {
-  const Document_Glom* document = get_document();
-  if(document)
-  {
-    Document_Glom::type_list_layout_groups mapGroups;
-    mapGroups.push_back(m_portal);
-
-    sharedptr<const Relationship> relationship = m_portal->get_relationship();
-    if(relationship)
-    {
-      type_vecLayoutFields result = get_table_fields_to_show_for_sequence(m_portal->get_table_used(Glib::ustring() /* not relevant */), mapGroups);
-
-      //If the relationship does not allow editing, then mark all these fields as non-editable:
-      if(!(m_portal->get_relationship_used_allows_edit()))
-      {
-        for(type_vecLayoutFields::iterator iter = result.begin(); iter != result.end(); ++iter)
-        {
-          sharedptr<LayoutItem_Field> item = *iter;
-          if(item)
-            item->set_editable(false);
-        }
-      }
-
-      return result;
-    }
-  }
-
-  return type_vecLayoutFields();
+  type_vecLayoutFields layout_fields = Box_Data_Portal::get_fields_to_show();
+  
+  sharedptr<LayoutItem_CalendarPortal> derived_portal = sharedptr<LayoutItem_CalendarPortal>::cast_dynamic(m_portal);
+  if(!derived_portal)
+    return layout_fields;
+  
+  sharedptr<const Field> date_field = derived_portal->get_date_field();
+  if(!date_field)
+    return layout_fields;
+  
+  //Add it to the list to ensure that we request the date (though it will not really be shown in the calendar):
+  sharedptr<LayoutItem_Field> layout_item_date_field = sharedptr<LayoutItem_Field>::create();
+  layout_item_date_field->set_full_field_details(date_field);
+  layout_fields.push_back(layout_item_date_field);
+  m_query_column_date_field = layout_fields.size() - 1;
+  return layout_fields;
 }
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
@@ -276,79 +348,82 @@
 Glib::ustring Box_Data_Calendar_Related::on_calendar_details(guint year, guint month, guint day)
 {
   sharedptr<LayoutItem_CalendarPortal> derived_portal = sharedptr<LayoutItem_CalendarPortal>::cast_dynamic(m_portal);
-    
-  
-  if(!derived_portal || !derived_portal->get_date_field())
+  if(!derived_portal)
   {
     std::cout << "DEBUG: Box_Data_Calendar_Related::on_calendar_details(): date_field is NULL" << std::endl;
     return Glib::ustring();
   }
   
+  sharedptr<const Field> date_field = derived_portal->get_date_field();
+  if(!date_field)
+    return Glib::ustring();
+  
   Glib::Date date(day, Glib::Date::Month(month+1), year);
-  Gnome::Gda::Value date_value(date);
-
-  sharedptr<Relationship> relationship = m_portal->get_relationship();
-  Glib::ustring where_clause_to_table_name = relationship->get_to_table();
   
-  const Glib::ustring date_field_name = derived_portal->get_date_field()->get_name();
-    
-  sharedptr<const Relationship> relationship_related = m_portal->get_related_relationship();
-  if(relationship_related)
-  {
-    //Adjust the WHERE clause appropriately for the extra JOIN:
-    sharedptr<UsesRelationship> uses_rel_temp = sharedptr<UsesRelationship>::create();
-    uses_rel_temp->set_relationship(relationship);
-    where_clause_to_table_name = uses_rel_temp->get_sql_join_alias_name();
-  }
-
-  //Add an AND to the existing where clause, to get only records with this date, if any:
-  const Glib::ustring extra_where_clause = "\"" + where_clause_to_table_name + "\".\"" + derived_portal->get_date_field()->get_name() + "\" = " + derived_portal->get_date_field()->sql(date_value);
-  Glib::ustring where_clause;
-  if(m_found_set.m_where_clause.empty())
-    where_clause = extra_where_clause;
-  else
-    where_clause = "( " + m_found_set.m_where_clause + " ) AND ( " + extra_where_clause + " )";
+  //Examine the cached data:
+  type_map_values::const_iterator iter_find = m_map_values.find(date);
+  if(iter_find == m_map_values.end())
+    return Glib::ustring(); //No data was found for this date.
+  
   
-  //TODO: Do one SQL query for the whole month and just read the cached values here, responding to month_changed to update the cache.
-  const Glib::ustring sql_query = Utils::build_sql_select_with_where_clause(m_found_set.m_table_name, m_FieldsShown, where_clause, m_found_set.m_extra_join, m_found_set.m_sort_clause, m_found_set.m_extra_group_by);
-  //std::cout << "DEBUG: sql_query=" << sql_query << std::endl;
-  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = query_execute(sql_query, get_app_window());
-  if(!(datamodel && datamodel->get_n_rows()))
-    return Glib::ustring();
- 
-  //Execute the query to get the data:
   Glib::ustring result;
-  const int row_index = 0;
-  int column_index = 0;
-  for(type_vecLayoutFields::const_iterator iter = m_FieldsShown.begin(); iter != m_FieldsShown.end(); ++iter)
-  {
-    sharedptr<LayoutItem> layout_item = *iter;
-    
-    Glib::ustring text;
-    
-    //Text for a text item:
-    sharedptr<LayoutItem_Text> layout_item_text = sharedptr<LayoutItem_Text>::cast_dynamic(layout_item);
-    if(layout_item_text)
-      text = layout_item_text->get_text();
-    else
-    {  
-      //Text for a field:
-      sharedptr<LayoutItem_Field> layout_item_field = sharedptr<LayoutItem_Field>::cast_dynamic(layout_item);
-      if(layout_item_field)
+  
+  //Look at each row for this date:
+  const type_list_vectors& rows = iter_find->second;
+  for(type_list_vectors::const_iterator iter = rows.begin(); iter != rows.end(); ++iter)
+  {
+    type_vector_values* pRow = *iter;
+    if(!pRow)
+      continue;
+    
+    //Get the data for each column in the row:
+    Glib::ustring row_text;
+    int column_index = 0;
+    
+    //We iterate over the original list of items from the portal,
+    //instead of the ones used by the query (m_FieldsShown),
+    //because we really don't want to show the extra fields (at the end) to the user:
+    LayoutGroup::type_list_items items = m_portal->get_items();
+    for(LayoutGroup::type_list_items::const_iterator iter = items.begin(); iter != items.end(); ++iter)
+    {   
+      sharedptr<const LayoutItem> layout_item = *iter;
+      if(!layout_item)
+        continue;
+            
+      Glib::ustring text;
+      
+      //Text for a text item:
+      sharedptr<const LayoutItem_Text> layout_item_text = sharedptr<const LayoutItem_Text>::cast_dynamic(layout_item);
+      if(layout_item_text)
+        text = layout_item_text->get_text();
+      else
       {
-        const Gnome::Gda::Value value = datamodel->get_value_at(row_index, column_index);
+        //Text for a field:
+        sharedptr<const LayoutItem_Field> layout_item_field = sharedptr<const LayoutItem_Field>::cast_dynamic(layout_item);
+        
+        const Gnome::Gda::Value value = (*pRow)[column_index];
         text = Conversions::get_text_for_gda_value(layout_item_field->get_glom_type(), value, layout_item_field->get_formatting_used().m_numeric_format);
-        //std::cout << "  DEBUG: text=" << text << std::endl;
+        
         ++column_index;
       }
+      
+      //Add the field text to the row:
+      if(!text.empty())
+      {
+        if(!row_text.empty())
+          row_text += ", "; //TODO: Internationalization?
+      
+        row_text += text;
+      }
     }
     
-    if(!text.empty())
+    //Add the row text to the result:
+    if(!row_text.empty())
     {
       if(!result.empty())
-          result += ", "; //TODO: Internationalization?
+        result += "\n";
       
-      result += text;
+      result += row_text;
     }
   }
   

Modified: trunk/glom/mode_data/box_data_calendar_related.h
==============================================================================
--- trunk/glom/mode_data/box_data_calendar_related.h	(original)
+++ trunk/glom/mode_data/box_data_calendar_related.h	Tue Apr 22 10:02:46 2008
@@ -37,6 +37,7 @@
 {
 public: 
   Box_Data_Calendar_Related();
+  virtual ~Box_Data_Calendar_Related();
 
   /**
    * @param portal: The full portal details
@@ -73,6 +74,8 @@
   #ifndef GLOM_ENABLE_CLIENT_ONLY
   void on_MenuPopup_activate_layout();
   #endif
+  
+  void clear_cached_database_values();
     
 protected:
   GlomGtk::Calendar m_calendar;
@@ -86,8 +89,14 @@
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   Glib::RefPtr<Gtk::Action> m_refContextLayout;
 #endif
-
-  type_signal_record_changed m_signal_record_changed;
+    
+  //The cached data for the month:
+  //For each date we have a list of rows (vectors):
+  typedef std::vector<Gnome::Gda::Value> type_vector_values;
+  typedef std::list<type_vector_values*> type_list_vectors;
+  typedef std::map<Glib::Date, type_list_vectors> type_map_values;
+  type_map_values m_map_values;
+  mutable int m_query_column_date_field;
 };
 
 } //namespace Glom

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 Apr 22 10:02:46 2008
@@ -238,37 +238,6 @@
   }
 }
 
-Box_Data_List_Related::type_vecLayoutFields Box_Data_List_Related::get_fields_to_show() const
-{
-  const Document_Glom* document = get_document();
-  if(document)
-  {
-    Document_Glom::type_list_layout_groups mapGroups;
-    mapGroups.push_back(m_portal);
-
-    sharedptr<const Relationship> relationship = m_portal->get_relationship();
-    if(relationship)
-    {
-      type_vecLayoutFields result = get_table_fields_to_show_for_sequence(m_portal->get_table_used(Glib::ustring() /* not relevant */), mapGroups);
-
-      //If the relationship does not allow editing, then mark all these fields as non-editable:
-      if(!(m_portal->get_relationship_used_allows_edit()))
-      {
-        for(type_vecLayoutFields::iterator iter = result.begin(); iter != result.end(); ++iter)
-        {
-          sharedptr<LayoutItem_Field> item = *iter;
-          if(item)
-            item->set_editable(false);
-        }
-      }
-
-      return result;
-    }
-  }
-
-  return type_vecLayoutFields();
-}
-
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 void Box_Data_List_Related::on_dialog_layout_hide()
 {

Modified: trunk/glom/mode_data/box_data_list_related.h
==============================================================================
--- trunk/glom/mode_data/box_data_list_related.h	(original)
+++ trunk/glom/mode_data/box_data_list_related.h	Tue Apr 22 10:02:46 2008
@@ -42,7 +42,6 @@
 
 protected:
   virtual bool fill_from_database(); //Override.
-  virtual type_vecLayoutFields get_fields_to_show() const; //override
 
   virtual void on_adddel_user_requested_add();
   virtual void on_adddel_user_changed(const Gtk::TreeModel::iterator& row, guint col);



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