[glom/feature_choices_show_all] Utils::get_choice_values(): Reduce copy/pasted code.



commit 734687d2a6854f7085461a3d783600b32a7244b3
Author: Murray Cumming <murrayc murrayc com>
Date:   Fri Aug 6 14:54:22 2010 +0200

    Utils::get_choice_values(): Reduce copy/pasted code.
    
    * glom/libglom/utils.[h|cc]: build_sql_select_with_key(): Add a sort_clause
      parameter.
      get_choice_values(field): Rename this to get_choice_values_all() and change
      the implementation to just call the other get_choice_values(). Add
      a Document* parameter so we can do that.
      get_choice_values(document, field, ...): Sort the list by the first field.
      This should probably be an option in the developer-mode UI.
    * glom/mode_data/datawidget/combo.h:
    * glom/mode_data/datawidget/combochoices.[h|cc]:
    * glom/mode_data/datawidget/comboentry.h:
    * glom/utility_widgets/db_adddel/db_adddel.cc:
      get_choice_values(): Adapt to the change, by adding a Document* parameter.
    * glom/base_db.cc: Adapt.

 ChangeLog                                   |   18 ++++
 glom/base_db.cc                             |    2 +-
 glom/libglom/utils.cc                       |  148 ++++++++-------------------
 glom/libglom/utils.h                        |   11 ++-
 glom/mode_data/datawidget/combo.cc          |   14 ++--
 glom/mode_data/datawidget/combo.h           |    9 +-
 glom/mode_data/datawidget/combochoices.cc   |   53 ++++------
 glom/mode_data/datawidget/combochoices.h    |   10 +-
 glom/mode_data/datawidget/comboentry.cc     |   24 ++--
 glom/mode_data/datawidget/comboentry.h      |   15 ++--
 glom/mode_data/datawidget/datawidget.cc     |   30 +++---
 glom/utility_widgets/db_adddel/db_adddel.cc |   20 +---
 12 files changed, 146 insertions(+), 208 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index ba29e03..04cf9f3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 2010-08-06  Murray Cumming  <murrayc murrayc com>
 
+	Utils::get_choice_values(): Reduce copy/pasted code.
+
+	* glom/libglom/utils.[h|cc]: build_sql_select_with_key(): Add a sort_clause
+  parameter.
+  get_choice_values(field): Rename this to get_choice_values_all() and change
+  the implementation to just call the other get_choice_values(). Add
+  a Document* parameter so we can do that.
+  get_choice_values(document, field, ...): Sort the list by the first field.
+  This should probably be an option in the developer-mode UI.
+	* glom/mode_data/datawidget/combo.h:
+	* glom/mode_data/datawidget/combochoices.[h|cc]:
+	* glom/mode_data/datawidget/comboentry.h:
+	* glom/utility_widgets/db_adddel/db_adddel.cc:
+  get_choice_values(): Adapt to the change, by adding a Document* parameter.
+	* glom/base_db.cc: Adapt.
+
+2010-08-06  Murray Cumming  <murrayc murrayc com>
+
 	DbAddDel: Avoid some copy/pasting of code to append items to choices cells.
 
 	* glom/utility_widgets/db_adddel/db_adddel.[h|cc]: Added set_cell_choices(),
diff --git a/glom/base_db.cc b/glom/base_db.cc
index 8401dde..c89b726 100644
--- a/glom/base_db.cc
+++ b/glom/base_db.cc
@@ -1233,7 +1233,7 @@ Gnome::Gda::Value Base_DB::get_field_value_in_database(const LayoutFieldInRecord
   sharedptr<const LayoutItem_Field> layout_item = field_in_record.m_field;
   list_fields.push_back(layout_item);
   Glib::RefPtr<Gnome::Gda::SqlBuilder> sql_query = Utils::build_sql_select_with_key(field_in_record.m_table_name,
-      list_fields, field_in_record.m_key, field_in_record.m_key_value, 1);
+    list_fields, field_in_record.m_key, field_in_record.m_key_value, type_sort_clause(), 1);
 
   Glib::RefPtr<const Gnome::Gda::DataModel> data_model = DbUtils::query_execute_select(sql_query);
   if(data_model)
diff --git a/glom/libglom/utils.cc b/glom/libglom/utils.cc
index f8f6829..8e73617 100644
--- a/glom/libglom/utils.cc
+++ b/glom/libglom/utils.cc
@@ -427,7 +427,7 @@ Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_where_clause(c
 }
 
 
-Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_key(const Glib::ustring& table_name, const type_vecLayoutFields& fieldsToGet, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value, guint limit)
+Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_key(const Glib::ustring& table_name, const type_vecLayoutFields& fieldsToGet, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value, const type_sort_clause& sort_clause, guint limit)
 {
   //TODO_Performance:
   type_vecConstLayoutFields constFieldsToGet;
@@ -436,7 +436,7 @@ Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_key(const Glib
     constFieldsToGet.push_back(*iter);
   }
 
-  return build_sql_select_with_key(table_name, constFieldsToGet, key_field, key_value, limit);
+  return build_sql_select_with_key(table_name, constFieldsToGet, key_field, key_value, sort_clause, limit);
 }
 
 Gnome::Gda::SqlExpr Utils::build_simple_where_expression(const Glib::ustring& table_name, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value)
@@ -463,120 +463,55 @@ Gnome::Gda::SqlExpr Utils::build_combined_where_expression(const Gnome::Gda::Sql
   return builder->export_expression(id);
 }
 
-Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_key(const Glib::ustring& table_name, const type_vecConstLayoutFields& fieldsToGet, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value, guint limit)
+Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_key(const Glib::ustring& table_name, const type_vecConstLayoutFields& fieldsToGet, const sharedptr<const Field>& key_field, const Gnome::Gda::Value& key_value, const type_sort_clause& sort_clause, guint limit)
 {
-  if(!Conversions::value_is_empty(key_value)) //If there is a record to show:
+  //We choose instead to have no where clause in this case,
+  //because that is useful to some callers:
+  //if(Conversions::value_is_empty(key_value)) //If there is a record to show:
+  //  return Glib::RefPtr<Gnome::Gda::SqlBuilder>();
+
+  Gnome::Gda::SqlExpr where_clause;
+  if(!Conversions::value_is_empty(key_value) && key_field)
   {
-    const Gnome::Gda::SqlExpr where_clause = build_simple_where_expression(table_name, key_field, key_value);
-    return Utils::build_sql_select_with_where_clause(table_name, fieldsToGet, where_clause,
-      sharedptr<const Relationship>(), type_sort_clause(), limit);
+    where_clause = build_simple_where_expression(table_name, key_field, key_value);
   }
 
-  return Glib::RefPtr<Gnome::Gda::SqlBuilder>();
+  return Utils::build_sql_select_with_where_clause(table_name, fieldsToGet, where_clause,
+    sharedptr<const Relationship>(), sort_clause, limit);
 }
 
-Utils::type_list_values_with_second Utils::get_choice_values(const sharedptr<const LayoutItem_Field>& field)
+Utils::type_list_values_with_second Utils::get_choice_values_all(const Document* document, const sharedptr<const LayoutItem_Field>& field, sharedptr<LayoutItem_Field>& layout_choice_first, sharedptr<LayoutItem_Field>& layout_choice_second)
 {
-  type_list_values_with_second list_values;
-
-  sharedptr<const Relationship> choice_relationship;
-  Glib::ustring choice_field, choice_second;
-  bool choice_show_all = false;
-  field->get_formatting_used().get_choices_related(choice_relationship, choice_field, choice_second, choice_show_all);
-  if(!choice_relationship || choice_field.empty())
-  {
-    std::cout <<" debug: field has no choices: " << field->get_name() << std::endl;
-    return list_values;
-  }
-  
-  if(!choice_show_all)
-  {
-    std::cerr << G_STRFUNC << ": This should not be called for !show_all choices." << std::endl;
-    return list_values;
-  }
-
-  const Glib::ustring to_table = choice_relationship->get_to_table();
-  if(to_table.empty())
-  {
-    g_warning("get_choice_values(): table_name is null. relationship name = %s", glom_get_sharedptr_name(choice_relationship).c_str());
-    return list_values;
-  }
-
-  const bool with_second = !choice_second.empty();
-
-  //Get possible values from database, sorted by the first column.
-  Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
-      Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
-  const guint choice_field_id = builder->select_add_field(choice_field, to_table);
-  builder->select_add_target(to_table);
-
-  if(with_second)
-    builder->select_add_field(choice_second, to_table);
-
-  builder->select_order_by(choice_field_id);
-
-  //std::cout << "debug: " << G_STRFUNC << ": query: " << sql_query << std::endl;
-  //Connect to database:
-  sharedptr<SharedConnection> connection = ConnectionPool::get_instance()->connect();
-
-  if(!connection)
-  {
-    std::cerr << G_STRFUNC << ": No connection." << std::endl;
-    return list_values;
-  }
-  
-  const std::string sql_query =
-    sqlbuilder_get_full_query(builder);
-  //std::cout << "get_choice_values: Executing SQL: " << sql_query << std::endl;
-  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = connection->get_gda_connection()->statement_execute_select(sql_query);
-
-  if(datamodel)
-  {
-    const guint count = datamodel->get_n_rows();
-    //std::cout << "  result: count=" << count << std::endl;
-    for(guint row = 0; row < count; ++row)
-    {
-
-      std::pair<Gnome::Gda::Value, Gnome::Gda::Value> itempair;
-      itempair.first = datamodel->get_value_at(0, row);
-
-      if(with_second)
-        itempair.second = datamodel->get_value_at(1, row);
-
-      list_values.push_back(itempair);
-    }
-  }
-  else
-  {
-      std::cerr << G_STRFUNC << ": Error while executing SQL" << std::endl <<
-                   "  " <<  sql_query << std::endl;
-  }
-
-  return list_values;
+  return get_choice_values(document, field,
+    Gnome::Gda::Value() /* means get all with no WHERE clause */,
+    layout_choice_first, layout_choice_second);
 }
 
-Utils::type_list_values_with_second Utils::get_choice_values(Document* document, const sharedptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& foreign_key_value, sharedptr<LayoutItem_Field>& layout_choice_first, sharedptr<LayoutItem_Field>& layout_choice_second)
+Utils::type_list_values_with_second Utils::get_choice_values(const Document* document, const sharedptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& foreign_key_value, sharedptr<LayoutItem_Field>& layout_choice_first, sharedptr<LayoutItem_Field>& layout_choice_second)
 {
   //Initialize output parameters:
   layout_choice_first = sharedptr<LayoutItem_Field>();
   layout_choice_second = sharedptr<LayoutItem_Field>();
-    
+
   //TODO: Reduce duplication between this and get_choice_values(field).
-  
+
   type_list_values_with_second result;
-  
+
+  //We allows this, so this method can be used to get all records in a related table:
+  /*
   if(Conversions::value_is_empty(foreign_key_value))
   {
     std::cout << G_STRFUNC << "debug: foreign_key_value is empty." << std::endl;
     return result;
   }
-  
+  */
+
   const FieldFormatting& format = field->get_formatting_used();
   sharedptr<const Relationship> choice_relationship;
   Glib::ustring choice_field, choice_second;
   bool choice_show_all = false;
   format.get_choices_related(choice_relationship, choice_field, choice_second, choice_show_all);
-  
+
   if(!choice_relationship)
   {
     std::cerr << G_STRFUNC << ": !choice_relationship." << std::endl;
@@ -590,11 +525,11 @@ Utils::type_list_values_with_second Utils::get_choice_values(Document* document,
     std::cerr << G_STRFUNC << ": !field_details." << std::endl;
     return result;
   }
-  
+
   layout_choice_first = sharedptr<LayoutItem_Field>::create();
   layout_choice_first->set_full_field_details(field_details);
-  
-  
+
+
   if(!choice_second.empty())
   {
     sharedptr<const Field> field_details = document->get_field(to_table, choice_second);
@@ -603,31 +538,36 @@ Utils::type_list_values_with_second Utils::get_choice_values(Document* document,
       std::cerr << G_STRFUNC << ": !field_details (second)." << std::endl;
       return result;
     }
-    
+
+    layout_choice_second = sharedptr<LayoutItem_Field>::create();
     layout_choice_second->set_full_field_details(field_details);
   }
- 
-  
-  
+
+
+
   Utils::type_vecLayoutFields fields;
   fields.push_back(layout_choice_first);
   if(layout_choice_second)
     fields.push_back(layout_choice_second);
-    
+
   sharedptr<Field> to_field = document->get_field(to_table, choice_relationship->get_to_field());
-    
+
   if(!to_field)
   {
     std::cerr << G_STRFUNC << ": to_field is null." << std::endl;
   }
-    
+
+  type_sort_clause sort_clause;
+  sort_clause.push_back( type_pair_sort_field(layout_choice_first, true /* ascending */));
+
   //TODO: Support related relationships (in the UI too):
   Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Utils::build_sql_select_with_key(
     to_table,
     fields,
     to_field,
-    foreign_key_value);
-    
+    foreign_key_value,
+    sort_clause);
+
   if(!builder)
   {
     std::cerr << G_STRFUNC << ": builder is null." << std::endl;
@@ -1080,7 +1020,7 @@ std::string Utils::sqlbuilder_get_full_query(
   return std::string(buf.get());
 }
 
-Gnome::Gda::SqlExpr Utils::get_find_where_clause_quick(Document* document, const Glib::ustring& table_name, const Gnome::Gda::Value& quick_search)
+Gnome::Gda::SqlExpr Utils::get_find_where_clause_quick(const Document* document, const Glib::ustring& table_name, const Gnome::Gda::Value& quick_search)
 {
   Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
     Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
diff --git a/glom/libglom/utils.h b/glom/libglom/utils.h
index 493cbcf..f24ed11 100644
--- a/glom/libglom/utils.h
+++ b/glom/libglom/utils.h
@@ -88,11 +88,15 @@ Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_where_clause(
   const type_sort_clause& sort_clause = type_sort_clause(),
   guint limit = 0);
 
+/**
+ * @param key_value If this is empty then all records in the tables will be retrieved.
+ */
 Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_key(
   const Glib::ustring& table_name,
   const type_vecLayoutFields& fieldsToGet,
   const sharedptr<const Field>& key_field,
   const Gnome::Gda::Value& key_value,
+  const type_sort_clause& sort_clause = type_sort_clause(),
   guint limit = 0);
 
 /** Just a version of build_sql_select_with_key() that takes a list of const fields.
@@ -102,15 +106,16 @@ Glib::RefPtr<Gnome::Gda::SqlBuilder> build_sql_select_with_key(
   const type_vecConstLayoutFields& fieldsToGet,
   const sharedptr<const Field>& key_field,
   const Gnome::Gda::Value& key_value,
+  const type_sort_clause& sort_clause = type_sort_clause(),
   guint limit = 0);
 
-Gnome::Gda::SqlExpr get_find_where_clause_quick(Document* document, const Glib::ustring& table_name, const Gnome::Gda::Value& quick_search);
+Gnome::Gda::SqlExpr get_find_where_clause_quick(const Document* document, const Glib::ustring& table_name, const Gnome::Gda::Value& quick_search);
 
 
 typedef std::list< std::pair<Gnome::Gda::Value, Gnome::Gda::Value> > type_list_values_with_second;
-type_list_values_with_second get_choice_values(const sharedptr<const LayoutItem_Field>& field);
+type_list_values_with_second get_choice_values_all(const Document* document, const sharedptr<const LayoutItem_Field>& field, sharedptr<LayoutItem_Field>& layout_choice_first, sharedptr<LayoutItem_Field>& layout_choice_second);
 
-type_list_values_with_second get_choice_values(Document* document, const sharedptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& foreign_key_value, sharedptr<LayoutItem_Field>& layout_choice_first, sharedptr<LayoutItem_Field>& layout_choice_second);
+type_list_values_with_second get_choice_values(const Document* document, const sharedptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& foreign_key_value, sharedptr<LayoutItem_Field>& layout_choice_first, sharedptr<LayoutItem_Field>& layout_choice_second);
 
 /// Get the full query string suitable for use with std::cout.
 std::string sqlbuilder_get_full_query(
diff --git a/glom/mode_data/datawidget/combo.cc b/glom/mode_data/datawidget/combo.cc
index 9cfe294..6283ece 100644
--- a/glom/mode_data/datawidget/combo.cc
+++ b/glom/mode_data/datawidget/combo.cc
@@ -57,7 +57,7 @@ void ComboGlom::init()
   //Maemo:
   set_selector(m_maemo_selector);
   m_maemo_selector.set_model(0, m_refModel);
-  
+
   Glib::RefPtr<Hildon::TouchSelectorColumn> column =
     m_maemo_selector.append_text_column(m_refModel);
   column->set_property("text-column", 0); // TODO: Add a TextSelectorColumn::set_text_column() method?
@@ -98,7 +98,7 @@ void ComboGlom::set_choices_related(const Document* document, const sharedptr<co
     column->pack_start(m_Columns.m_col_second);
     #endif //GLOM_ENABLE_MAEMO
   }
-  
+
   ComboChoicesWithTreeModel::set_choices_related(document, relationship, field, field_second, show_all);
 }
 
@@ -152,7 +152,7 @@ void ComboGlom::set_value(const Gnome::Gda::Value& value)
     if(!cell)
       return;
 
-    const Glib::ustring fg_color = 
+    const Glib::ustring fg_color =
     layout_item->get_formatting_used().get_text_format_color_foreground_to_use(value);
     if(fg_color.empty())
     {
@@ -188,7 +188,7 @@ void ComboGlom::set_text(const Glib::ustring& text)
   {
     g_warning("ComboGlom::set_text(): no item found for: %s", text.c_str());
   }
-  
+
   //Not found, so mark it as blank:
   #ifndef GLOM_ENABLE_MAEMO
   unset_active();
@@ -215,7 +215,7 @@ Glib::ustring ComboGlom::get_text() const
   ComboGlom* unconst = const_cast<ComboGlom*>(this);
   Gtk::TreeModel::iterator iter = unconst->get_selected();
   #endif //GLOM_ENABLE_MAEMO
-  
+
   if(iter)
   {
     Gtk::TreeModel::Row row = *iter;
@@ -275,7 +275,7 @@ Application* ComboGlom::get_application()
 void ComboGlom::on_changed()
 #else
 void ComboGlom::on_changed(int /* column */)
-#endif 
+#endif
 {
   //Call base class:
   Gtk::ComboBox::on_changed();
@@ -287,7 +287,7 @@ void ComboGlom::on_changed(int /* column */)
   #else
   Gtk::TreeModel::iterator iter = get_selected();
   #endif //GLOM_ENABLE_MAEMO
-  
+
   if(iter)
   {
     //This is either a choice from the dropdown menu, or someone has typed in something that is in the drop-down menu.
diff --git a/glom/mode_data/datawidget/combo.h b/glom/mode_data/datawidget/combo.h
index 93450d4..c48c96c 100644
--- a/glom/mode_data/datawidget/combo.h
+++ b/glom/mode_data/datawidget/combo.h
@@ -42,7 +42,7 @@ namespace DataWidgetChildren
  * Use this when the user should only be allowed to enter values that are in the choices.
  */
 class ComboGlom
-: 
+:
 #ifndef GLOM_ENABLE_MAEMO
   public Gtk::ComboBox,
 #else
@@ -71,7 +71,7 @@ public:
   virtual void set_value(const Gnome::Gda::Value& value);
 
   virtual Gnome::Gda::Value get_value() const;
-  
+
   virtual void set_choices_related(const Document* document, const sharedptr<const Relationship>& relationship, const Glib::ustring& field, const Glib::ustring& field_second, bool show_all);
 
 private:
@@ -96,11 +96,11 @@ private:
 
   Glib::ustring m_old_text;
   //Gnome::Gda::Value m_value; //The last-stored value. We have this because the displayed value might be unparseable.
-  
+
   #ifdef GLOM_ENABLE_MAEMO
   Hildon::TouchSelector m_maemo_selector;
   #endif
-  
+
   Gtk::CellRenderer* m_cell_second;
 };
 
@@ -108,4 +108,3 @@ private:
 } //namespace Glom
 
 #endif //GLOM_UTILITY_WIDGETS_COMBOENTRY_GLOM_H
-
diff --git a/glom/mode_data/datawidget/combochoices.cc b/glom/mode_data/datawidget/combochoices.cc
index 8b1f5ee..cce338a 100644
--- a/glom/mode_data/datawidget/combochoices.cc
+++ b/glom/mode_data/datawidget/combochoices.cc
@@ -66,33 +66,33 @@ bool ComboChoices::refresh_data_from_database_with_foreign_key(const Gnome::Gda:
     set_choices_with_second(list_values);
     return true;
   }
-   
+
   if(m_related_show_all)
   {
     //The list should be set in set_choices_related() instead.
     std::cerr << G_STRFUNC << ": Called with m_related_show_all=true." << std::endl;
     return false;
   }
-  
+
   Utils::type_vecLayoutFields fields;
   fields.push_back(m_related_field);
   if(m_related_field_second)
     fields.push_back(m_related_field_second);
 
   //std::cout << G_STRFUNC << "debug: m_related_field=" << m_related_field->get_name() << ", m_related_field_second" << m_related_field_second->get_name() << std::endl;
-    
+
   if(!m_related_to_field)
   {
     std::cerr << G_STRFUNC << ": m_related_to_field is null." << std::endl;
   }
-    
+
   //TODO: Support related relationships (in the UI too):
   Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Utils::build_sql_select_with_key(
     m_related_relationship->get_to_table(),
     fields,
     m_related_to_field,
     foreign_key_value);
-    
+
   if(!builder)
   {
     std::cerr << G_STRFUNC << ": builder is null." << std::endl;
@@ -118,7 +118,7 @@ bool ComboChoices::refresh_data_from_database_with_foreign_key(const Gnome::Gda:
   if(datamodel)
   {
     type_list_values_with_second list_values;
-    
+
     const guint count = datamodel->get_n_rows();
     const guint cols_count = datamodel->get_n_columns();
     //std::cout << "  result: count=" << count << std::endl;
@@ -133,10 +133,10 @@ bool ComboChoices::refresh_data_from_database_with_foreign_key(const Gnome::Gda:
 
       list_values.push_back(itempair);
     }
-    
+
     const Gnome::Gda::Value old_value = get_value();
     set_choices_with_second(list_values);
-    set_value(old_value); //Try to preserve the value, even in iter-based ComboBoxes. 
+    set_value(old_value); //Try to preserve the value, even in iter-based ComboBoxes.
   }
   else
   {
@@ -148,49 +148,34 @@ bool ComboChoices::refresh_data_from_database_with_foreign_key(const Gnome::Gda:
   return true;
 }
 
-void ComboChoices::set_choices_related(const Document* document, const sharedptr<const Relationship>& relationship, const Glib::ustring& field, const Glib::ustring& field_second, bool show_all)
+void ComboChoices::set_choices_related(const Document* document, const sharedptr<const Relationship>& relationship, const Glib::ustring& /* field */, const Glib::ustring& /* field_second */, bool show_all)
 {
+  //Note that field_second is used in derived classes.
+
   m_related_relationship = relationship;
   m_related_show_all = show_all;
-  
+
+  m_related_field.clear();
   m_related_field_second.clear();
-  if(m_related_relationship && !field.empty())
+  if(m_related_relationship)
   {
     const Glib::ustring to_table = m_related_relationship->get_to_table();
     m_related_to_field = document->get_field(to_table, m_related_relationship->get_to_field());
-    
-    if(!document)
-    {
-      std::cerr << G_STRFUNC << ": document is null." << std::endl;
-      return;
-    }
-    
-    //TODO: Avoid this lookup every time a value changes:
-    sharedptr<const Field> field_details = document->get_field(to_table, field);
-    m_related_field = sharedptr<LayoutItem_Field>::create();
-    m_related_field->set_full_field_details(field_details);
-    
-    if(!field_second.empty())
-    {
-      field_details = document->get_field(to_table, field_second);
-      m_related_field_second = sharedptr<LayoutItem_Field>::create();
-      m_related_field_second->set_full_field_details(field_details);
-    }
   }
-  
+
   type_list_values_with_second list_values;
-  
+
   //Set the values now because if it will be the same regardless of the foreign key value.
   //Otherwise show them when refresh_data_from_database_with_foreign_key() is called.
   if(relationship && show_all)
   {
     sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::cast_dynamic(get_layout_item());
-    list_values = Utils::get_choice_values(layout_item);
+    list_values = Utils::get_choice_values_all(document, layout_item, m_related_field, m_related_field_second);
   }
-  
+
   const Gnome::Gda::Value old_value = get_value();
   set_choices_with_second(list_values);
-  set_value(old_value); //Try to preserve the value, even in iter-based ComboBoxes. 
+  set_value(old_value); //Try to preserve the value, even in iter-based ComboBoxes.
 }
 
 } //namespace DataWidgetChildren
diff --git a/glom/mode_data/datawidget/combochoices.h b/glom/mode_data/datawidget/combochoices.h
index f039900..c9f8010 100644
--- a/glom/mode_data/datawidget/combochoices.h
+++ b/glom/mode_data/datawidget/combochoices.h
@@ -50,9 +50,12 @@ public:
 
   /**
    * See also refresh_data_from_database_with_foreign_key().
+   * @param relationship Just to save some extra lookup in the format, from get_layout_item().
+   * @param field Just to save some extra lookup in the format, from get_layout_item().
+   * @param field_second Just to save some extra lookup in the format, from get_layout_item().
    */
   virtual void set_choices_related(const Document* document, const sharedptr<const Relationship>& relationship, const Glib::ustring& field, const Glib::ustring& field_second, bool show_all);
-  
+
   /** Update a choices widget's list of related choices if a relevant value in its parent table has changed.
    *
    * @param foreign_key_value: The value that should be found in this table.
@@ -61,12 +64,12 @@ public:
 
 protected:
   void init();
-  
+
   typedef std::list< std::pair<Gnome::Gda::Value, Gnome::Gda::Value> > type_list_values_with_second;
   virtual void set_choices_with_second(const type_list_values_with_second& list_values) = 0;
 
   //Gnome::Gda::Value m_value; //The last-stored value. We have this because the displayed value might be unparseable.
-  
+
   //These are used if it is related choices:
   sharedptr<const Relationship> m_related_relationship;
   sharedptr<const Field> m_related_to_field; //To avoid retrieving it each time.
@@ -79,4 +82,3 @@ protected:
 } //namespace Glom
 
 #endif //GLOM_UTILITY_WIDGETS_COMBO_CHOICES_H
-
diff --git a/glom/mode_data/datawidget/comboentry.cc b/glom/mode_data/datawidget/comboentry.cc
index 8d89417..051fc65 100644
--- a/glom/mode_data/datawidget/comboentry.cc
+++ b/glom/mode_data/datawidget/comboentry.cc
@@ -78,7 +78,7 @@ void ComboEntry::init()
 #else
   //Maemo:
   set_selector(m_maemo_selector);
- 
+
   //We don't use append_text_column(), because we want to specify no expand.
   //Glib::RefPtr<Hildon::TouchSelectorColumn> column =
   //  m_maemo_selector.append_text_column(m_refModel);
@@ -86,15 +86,15 @@ void ComboEntry::init()
   //  m_maemo_selector.append_column(m_refModel);
   Glib::RefPtr<Hildon::TouchSelectorColumn> column = Glib::wrap(hildon_touch_selector_append_column(
     HILDON_TOUCH_SELECTOR(m_maemo_selector.gobj()), GTK_TREE_MODEL(Glib::unwrap(m_refModel)), 0, static_cast<char*>(0)), true);
-      
+
   column->pack_start(m_Columns.m_col_first, false);
   //Only in the latest hildonmm: column->set_text_column(m_Columns.m_col_first);
   column->set_property("text_column", 0);
-  
+
   //Only in the latest hildonmm: m_maemo_selector->set_text_column(m_Columns.m_col_first);
   m_maemo_selector.set_text_column(0);
 
-  
+
   //m_maemo_selector.set_model(0, m_refModel);
   //m_maemo_selector.set_text_column(0);
 #endif
@@ -147,7 +147,7 @@ void ComboEntry::set_layout_item(const sharedptr<LayoutItem>& layout_item, const
     return;
 
   //Horizontal Alignment:
-  FieldFormatting::HorizontalAlignment alignment = 
+  FieldFormatting::HorizontalAlignment alignment =
     FieldFormatting::HORIZONTAL_ALIGNMENT_LEFT;
   sharedptr<LayoutItem_Field> layout_field =
     sharedptr<LayoutItem_Field>::cast_dynamic(layout_item);
@@ -155,7 +155,7 @@ void ComboEntry::set_layout_item(const sharedptr<LayoutItem>& layout_item, const
     alignment = layout_field->get_formatting_used_horizontal_alignment();
 
   const float x_align = (alignment == FieldFormatting::HORIZONTAL_ALIGNMENT_LEFT ? 0.0 : 1.0);
-  get_entry()->set_alignment(x_align); 
+  get_entry()->set_alignment(x_align);
 }
 
 void ComboEntry::check_for_change()
@@ -165,7 +165,7 @@ void ComboEntry::check_for_change()
     //Don't allow editing via the menu either, if the Entry is non-editable.
 
     //Give the user some kind of warning.
-    //We could just remove the menu (by using a normal Entry for read-only fields with choices), 
+    //We could just remove the menu (by using a normal Entry for read-only fields with choices),
     //but I think that the choice is a useful recognisable visual hint about the field,
     //which shouldn't change sometimes just because the field is read-only.
     Gtk::Window* top_level_window = get_application();
@@ -217,7 +217,7 @@ bool ComboEntry::on_entry_focus_out_event(GdkEventFocus* /* event */)
 }
 
 void ComboEntry::on_entry_activate()
-{ 
+{
   //Call base class:
   //get_entry()->on_activate();
 
@@ -249,7 +249,7 @@ void ComboEntry::set_value(const Gnome::Gda::Value& value)
     if(!entry)
       return;
 
-    const Glib::ustring fg_color = 
+    const Glib::ustring fg_color =
     layout_item->get_formatting_used().get_text_format_color_foreground_to_use(value);
     if(!fg_color.empty())
       entry->modify_text(Gtk::STATE_NORMAL, Gdk::Color(fg_color));
@@ -261,7 +261,7 @@ void ComboEntry::set_value(const Gnome::Gda::Value& value)
 void ComboEntry::set_text(const Glib::ustring& text)
 {
   m_old_text = text;
-  
+
   #if GLOM_ENABLE_MAEMO
   for(Gtk::TreeModel::iterator iter = m_refModel->children().begin(); iter != m_refModel->children().end(); ++iter)
   {
@@ -333,7 +333,7 @@ Application* ComboEntry::get_application()
 void ComboEntry::on_changed()
 #else
 void ComboEntry::on_changed(int /* column */)
-#endif 
+#endif
 {
   //Call base class:
   Gtk::ComboBoxEntry::on_changed();
@@ -345,7 +345,7 @@ void ComboEntry::on_changed(int /* column */)
   #else
   Gtk::TreeModel::iterator iter = get_selected();
   #endif //GLOM_ENABLE_MAEMO
-  
+
   if(iter)
   {
     //This is either a choice from the dropdown menu, or someone has typed in something that is in the drop-down menu.
diff --git a/glom/mode_data/datawidget/comboentry.h b/glom/mode_data/datawidget/comboentry.h
index 9941644..bbff22f 100644
--- a/glom/mode_data/datawidget/comboentry.h
+++ b/glom/mode_data/datawidget/comboentry.h
@@ -43,7 +43,7 @@ namespace DataWidgetChildren
  * including values that are not in the choices.
  */
 class ComboEntry
-: 
+:
 #ifndef GLOM_ENABLE_MAEMO
   public Gtk::ComboBoxEntry,
 #else
@@ -70,7 +70,7 @@ public:
   virtual void set_layout_item(const sharedptr<LayoutItem>& layout_item, const Glib::ustring& table_name);
 
   virtual void set_read_only(bool read_only = true);
-  
+
   virtual void set_choices_related(const Document* document, const sharedptr<const Relationship>& relationship, const Glib::ustring& field, const Glib::ustring& field_second, bool show_all);
 
 private:
@@ -83,7 +83,7 @@ private:
   virtual void on_entry_activate(); //From Gtk::Entry.
   virtual bool on_entry_focus_out_event(GdkEventFocus* event); //From Gtk::Widget
 
-  
+
   #ifndef GLOM_ENABLE_MAEMO
   // Note that this is a normal signal handler when glibmm was complied
   // without default signal handlers
@@ -91,7 +91,7 @@ private:
   #else
   void on_changed(int column);
   #endif //GLOM_ENABLE_MAEMO
-  
+
 
   virtual void check_for_change();
 
@@ -100,17 +100,17 @@ private:
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
   virtual Application* get_application();
-  
+
   Gtk::Entry* get_entry();
   const Gtk::Entry* get_entry() const;
 
   Glib::ustring m_old_text;
   //Gnome::Gda::Value m_value; //The last-stored value. We have this because the displayed value might be unparseable.
-   
+
   #ifdef GLOM_ENABLE_MAEMO
   Hildon::TouchSelectorEntry m_maemo_selector;
   #endif
-  
+
   Gtk::CellRenderer* m_cell_second;
 };
 
@@ -118,4 +118,3 @@ private:
 } //namespace Glom
 
 #endif //GLOM_UTILITY_WIDGETS_COMBOENTRY_GLOM_H
-
diff --git a/glom/mode_data/datawidget/datawidget.cc b/glom/mode_data/datawidget/datawidget.cc
index 1af2791..a5051f3 100644
--- a/glom/mode_data/datawidget/datawidget.cc
+++ b/glom/mode_data/datawidget/datawidget.cc
@@ -129,7 +129,7 @@ DataWidget::DataWidget(const sharedptr<LayoutItem_Field>& field, const Glib::ust
       {
         combo = create_combo_widget_for_field(field);
         combo->set_layout_item( get_layout_item(), table_name);
-        
+
         sharedptr<const Relationship> choice_relationship;
         Glib::ustring choice_field, choice_second;
         bool choice_show_all = false;
@@ -183,7 +183,7 @@ DataWidget::DataWidget(const sharedptr<LayoutItem_Field>& field, const Glib::ust
   {
     //Use the text formatting:
     apply_formatting(*m_child, field);
-    
+
     bool child_added = false; //Don't use an extra container unless necessary.
 
     //Check whether the field controls a relationship,
@@ -191,14 +191,14 @@ DataWidget::DataWidget(const sharedptr<LayoutItem_Field>& field, const Glib::ust
     const bool field_used_in_relationship_to_one = document->get_field_used_in_relationship_to_one(table_name, field);
     //std::cout << "DEBUG: table_name=" << table_name << ", table_used=" << field->get_table_used(table_name) << ", field=" << field->get_name() << ", field_used_in_relationship_to_one=" << field_used_in_relationship_to_one << std::endl;
 
-    //Check whether the field identifies a record in another table 
+    //Check whether the field identifies a record in another table
     //just because it is a primary key in that table:
     bool field_is_related_primary_key = false;
     if(document)
       field->set_full_field_details( document->get_field(field->get_table_used(table_name), field->get_name()) ); //Otherwise get_primary_key() returns false always.
     sharedptr<const Field> field_info = field->get_full_field_details();
-    field_is_related_primary_key = 
-      field->get_has_relationship_name() && 
+    field_is_related_primary_key =
+      field->get_has_relationship_name() &&
       field_info && field_info->get_primary_key();
     //std::cout <<   "DEBUG: field->get_has_relationship_name()=" << field->get_has_relationship_name() << ", field_info->get_primary_key()=" <<  field_info->get_primary_key() << ", field_is_related_primary_key=" << field_is_related_primary_key << std::endl;
 
@@ -226,7 +226,7 @@ DataWidget::DataWidget(const sharedptr<LayoutItem_Field>& field, const Glib::ust
       #else
       Gtk::Button* button_date = Gtk::manage(new Hildon::Button(Gtk::Hildon::SIZE_FINGER_HEIGHT, Hildon::BUTTON_ARRANGEMENT_HORIZONTAL, _("..."), ""));
       #endif
-      button_date->set_tooltip_text(_("Choose a date from an on-screen calendar.")); 
+      button_date->set_tooltip_text(_("Choose a date from an on-screen calendar."));
       button_date->show();
       hbox_parent->pack_start(*button_date);
       button_date->signal_clicked().connect(sigc::mem_fun(*this, &DataWidget::on_button_choose_date));
@@ -245,14 +245,14 @@ DataWidget::DataWidget(const sharedptr<LayoutItem_Field>& field, const Glib::ust
       m_button_go_to_details->signal_clicked().connect(sigc::mem_fun(*this, &DataWidget::on_button_open_details));
 
       //Add a button to make it easier to choose an ID for this field.
-      //Don't add this for simple related primary key fields, because they 
+      //Don't add this for simple related primary key fields, because they
       //can generally not be edited via another table's layout.
       if(field_used_in_relationship_to_one)
       {
         #ifndef GLOM_ENABLE_MAEMO
         Gtk::Button* button_select = Gtk::manage(new Gtk::Button(Gtk::Stock::FIND));
         #else
-        Gtk::Button* button_select = Gtk::manage(new Hildon::Button(Gtk::Hildon::SIZE_FINGER_HEIGHT, 
+        Gtk::Button* button_select = Gtk::manage(new Hildon::Button(Gtk::Hildon::SIZE_FINGER_HEIGHT,
            Hildon::BUTTON_ARRANGEMENT_HORIZONTAL, _("Find"), ""));
         #endif
         button_select->set_tooltip_text(_("Enter search criteria to identify records in the other table, to choose an ID for this field."));
@@ -318,7 +318,7 @@ void DataWidget::set_value(const Gnome::Gda::Value& value)
 
 void DataWidget::update_go_to_details_button_sensitivity()
 {
-  //If there is a Go-To-Details "Open" button, only enable it if there is 
+  //If there is a Go-To-Details "Open" button, only enable it if there is
   //an ID:
   if(m_button_go_to_details)
   {
@@ -368,12 +368,12 @@ void DataWidget::set_child_size_by_field(const sharedptr<const LayoutItem_Field>
     int height = -1; //auto.
     if((glom_type == Field::TYPE_TEXT) && (field->get_formatting_used().get_text_format_multiline()))
     {
-      #ifndef GLOM_ENABLE_MAEMO 
+      #ifndef GLOM_ENABLE_MAEMO
       int example_width = 0;
       int example_height = 0;
       Glib::RefPtr<Pango::Layout> refLayout = create_pango_layout("example"); //TODO: Use different text, according to the current locale, or allow the user to choose an example?
       refLayout->get_pixel_size(example_width, example_height);
-      
+
       if(example_height > 0)
         height = example_height * field->get_formatting_used().get_text_format_multiline_height_lines();
       #else
@@ -381,7 +381,7 @@ void DataWidget::set_child_size_by_field(const sharedptr<const LayoutItem_Field>
       //TODO: Expansion only happens if both are -1, and vertical expansion never happens.
       //See bug https://bugs.maemo.org/show_bug.cgi?id=5515
       width = -1;
-      height = -1; 
+      height = -1;
       #endif //GLOM_ENABLE_MAEMO
     }
 
@@ -443,7 +443,7 @@ bool DataWidget::on_button_press_event(GdkEventButton *event)
     pApp->add_developer_action(m_refContextAddRelatedRecords);
     pApp->add_developer_action(m_refContextAddGroup);
 
-    pApp->update_userlevel_ui(); //Update our action's sensitivity. 
+    pApp->update_userlevel_ui(); //Update our action's sensitivity.
 
     //Only show this popup in developer mode, so operators still see the default GtkEntry context menu.
     //TODO: It would be better to add it somehow to the standard context menu.
@@ -476,7 +476,7 @@ sharedptr<LayoutItem_Field> DataWidget::offer_field_list(const Glib::ustring& ta
 sharedptr<LayoutItem_Field> DataWidget::offer_field_list(const Glib::ustring& table_name, const sharedptr<const LayoutItem_Field>& start_field, Document* document, Application* app)
 {
   sharedptr<LayoutItem_Field> result;
-  
+
   Dialog_ChooseField* dialog = 0;
   Utils::get_glade_widget_derived_with_warning(dialog);
 
@@ -598,7 +598,7 @@ const Gtk::Widget* DataWidget::get_data_child_widget() const
 {
   return m_child;
 }
- 
+
  DataWidget::type_signal_open_details_requested DataWidget::signal_open_details_requested()
  {
    return m_signal_open_details_requested;
diff --git a/glom/utility_widgets/db_adddel/db_adddel.cc b/glom/utility_widgets/db_adddel/db_adddel.cc
index d7818e0..bb5a644 100644
--- a/glom/utility_widgets/db_adddel/db_adddel.cc
+++ b/glom/utility_widgets/db_adddel/db_adddel.cc
@@ -843,24 +843,14 @@ Gtk::CellRenderer* DbAddDel::construct_specified_columns_cellrenderer(const shar
           const bool use_second = !choice_second.empty();
           pCellRendererCombo->set_use_second(use_second);
 
-          const sharedptr<LayoutItem_Field> layout_field_second = sharedptr<LayoutItem_Field>::create();
-          if(use_second)
-          {
-            Document* document = get_document();
-            if(document)
-            {
-              sharedptr<Field> field_second = document->get_field(to_table, choice_second); //TODO: Actually show this in the combo:
-              layout_field_second->set_full_field_details(field_second);
-
-              //We use the default formatting for this field->
-            }
-          }
-
           //TODO: Update this when the relationship's field value changes:
           if(choice_show_all) //Otherwise it must change whenever the relationships's ID value changes.
           {
-            Utils::type_list_values_with_second list_values = Utils::get_choice_values(item_field);
-            set_cell_choices(pCellRendererCombo, item_field /* TODO: We shoulds really use a layout_field_first instead */, layout_field_second, list_values);
+            Document* document = get_document();
+            sharedptr<LayoutItem_Field> layout_field_first;
+            sharedptr<LayoutItem_Field> layout_field_second;
+            Utils::type_list_values_with_second list_values = Utils::get_choice_values_all(document, item_field, layout_field_first, layout_field_second);
+            set_cell_choices(pCellRendererCombo,  layout_field_first, layout_field_second, list_values);
           }
         }
       }



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