[glom/feature_choices_show_all] Choices with !show_all: Update the list when the from_field changes.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom/feature_choices_show_all] Choices with !show_all: Update the list when the from_field changes.
- Date: Wed, 4 Aug 2010 03:23:28 +0000 (UTC)
commit ca1a71cac3b9965cde7c1b728365a3d401f2be84
Author: Murray Cumming <murrayc murrayc com>
Date: Wed Aug 4 03:22:01 2010 +0200
Choices with !show_all: Update the list when the from_field changes.
* glom/libglom/data_structure/layout/fieldformatting.[h|cc]: Renamed
set/get_choices() to set/get_choices_related().
* glom/libglom/utils.cc:
* glom/libglom/document/document.cc:
* glom/mode_design/layout/layout_item_dialogs/box_formatting.cc:
* glom/utility_widgets/db_adddel/db_adddel.cc: Adapted.
* glom/mode_data/datawidget/combochoices.[h|cc]: Remove the non-default
constructor that took a second field.
Move set_choices_with_second() to private.
Add set_choices_related() and matching member variables.
Add refresh_data_from_database_with_foreign_key(), like the one in
Box_Data_RelatedRecords, which gets the related values and calls
set_choices_with_second().
* glom/mode_data/datawidget/combo.[h|cc]:
* glom/mode_data/datawidget/combo_as_radio_buttons.[h|cc]:
* glom/mode_data/datawidget/combochoiceswithtreemodel.[h|cc]:
* glom/mode_data/datawidget/comboentry.[h|cc]: Adapt to the changed
ComboChoices base API.
* glom/mode_data/datawidget/datawidget.cc:
create_combo_widget_for_field(): Do not take the second field as a parameter,
because that is now specified later.
Constructor: Simplify the code now that ComboChoices does more of the work.
* glom/mode_data/flowtablewithfields.cc: set_field_value(): Call
refresh_data_from_database_with_foreign_key() on the choice widgets as it
already does on the portals, to refresh the list of possible values.
ChangeLog | 32 ++++
.../data_structure/layout/fieldformatting.cc | 4 +-
.../data_structure/layout/fieldformatting.h | 4 +-
glom/libglom/document/document.cc | 4 +-
glom/libglom/utils.cc | 102 ++++++++------
glom/mode_data/box_data_portal.h | 1 -
glom/mode_data/datawidget/combo.cc | 44 +++---
glom/mode_data/datawidget/combo.h | 7 +-
.../mode_data/datawidget/combo_as_radio_buttons.cc | 16 +--
glom/mode_data/datawidget/combo_as_radio_buttons.h | 6 +-
glom/mode_data/datawidget/combochoices.cc | 152 ++++++++++++++++++-
glom/mode_data/datawidget/combochoices.h | 26 +++-
.../datawidget/combochoiceswithtreemodel.cc | 10 +-
.../datawidget/combochoiceswithtreemodel.h | 6 +-
glom/mode_data/datawidget/comboentry.cc | 34 ++---
glom/mode_data/datawidget/comboentry.h | 7 +-
glom/mode_data/datawidget/datawidget.cc | 45 ++-----
glom/mode_data/flowtablewithfields.cc | 40 +++++-
.../layout/layout_item_dialogs/box_formatting.cc | 4 +-
glom/utility_widgets/db_adddel/db_adddel.cc | 3 +-
20 files changed, 364 insertions(+), 183 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a5fc035..3c96ca9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2010-08-04 Murray Cumming <murrayc murrayc com>
+
+ Choices with !show_all: Update the list when the from_field changes.
+
+ * glom/libglom/data_structure/layout/fieldformatting.[h|cc]: Renamed
+ set/get_choices() to set/get_choices_related().
+ * glom/libglom/utils.cc:
+ * glom/libglom/document/document.cc:
+ * glom/mode_design/layout/layout_item_dialogs/box_formatting.cc:
+ * glom/utility_widgets/db_adddel/db_adddel.cc: Adapted.
+
+ * glom/mode_data/datawidget/combochoices.[h|cc]: Remove the non-default
+ constructor that took a second field.
+ Move set_choices_with_second() to private.
+ Add set_choices_related() and matching member variables.
+ Add refresh_data_from_database_with_foreign_key(), like the one in
+ Box_Data_RelatedRecords, which gets the related values and calls
+ set_choices_with_second().
+ * glom/mode_data/datawidget/combo.[h|cc]:
+ * glom/mode_data/datawidget/combo_as_radio_buttons.[h|cc]:
+ * glom/mode_data/datawidget/combochoiceswithtreemodel.[h|cc]:
+ * glom/mode_data/datawidget/comboentry.[h|cc]: Adapt to the changed
+ ComboChoices base API.
+ * glom/mode_data/datawidget/datawidget.cc:
+ create_combo_widget_for_field(): Do not take the second field as a parameter,
+ because that is now specified later.
+ Constructor: Simplify the code now that ComboChoices does more of the work.
+ * glom/mode_data/flowtablewithfields.cc: set_field_value(),
+ set_other_field_value(): Call refresh_data_from_database_with_foreign_key() on
+ the choice widgets as they already does on the portals, to refresh the list of
+ possible values.
+
2010-08-02 Murray Cumming <murrayc murrayc com>
FlowTableWithFields: Added get_choices_widgets(from_field).
diff --git a/glom/libglom/data_structure/layout/fieldformatting.cc b/glom/libglom/data_structure/layout/fieldformatting.cc
index cbb9201..5de8380 100644
--- a/glom/libglom/data_structure/layout/fieldformatting.cc
+++ b/glom/libglom/data_structure/layout/fieldformatting.cc
@@ -235,7 +235,7 @@ void FieldFormatting::set_has_related_choices(bool val)
m_choices_related = val;
}
-void FieldFormatting::get_choices(sharedptr<const Relationship>& relationship, Glib::ustring& field, Glib::ustring& field_second, bool& show_all) const
+void FieldFormatting::get_choices_related(sharedptr<const Relationship>& relationship, Glib::ustring& field, Glib::ustring& field_second, bool& show_all) const
{
relationship = get_relationship();
@@ -246,7 +246,7 @@ void FieldFormatting::get_choices(sharedptr<const Relationship>& relationship, G
//g_warning("FieldFormatting::get_choices, %s, %s, %s", m_choices_related_relationship->c_str(), m_choices_related_field.c_str(), m_choices_related_field_second.c_str());
}
-void FieldFormatting::set_choices(const sharedptr<const Relationship>& relationship, const Glib::ustring& field, const Glib::ustring& field_second, bool show_all)
+void FieldFormatting::set_choices_related(const sharedptr<const Relationship>& relationship, const Glib::ustring& field, const Glib::ustring& field_second, bool show_all)
{
set_relationship(relationship);
diff --git a/glom/libglom/data_structure/layout/fieldformatting.h b/glom/libglom/data_structure/layout/fieldformatting.h
index c9aa272..cb19b0d 100644
--- a/glom/libglom/data_structure/layout/fieldformatting.h
+++ b/glom/libglom/data_structure/layout/fieldformatting.h
@@ -65,8 +65,8 @@ public:
*/
void set_choices_restricted(bool val = true, bool as_radio_buttons = false);
- void get_choices(sharedptr<const Relationship>& relationship_name, Glib::ustring& field, Glib::ustring& field_second, bool& show_all) const;
- void set_choices(const sharedptr<const Relationship>& relationship_name, const Glib::ustring& field, const Glib::ustring& field_second, bool show_all);
+ void get_choices_related(sharedptr<const Relationship>& relationship_name, Glib::ustring& field, Glib::ustring& field_second, bool& show_all) const;
+ void set_choices_related(const sharedptr<const Relationship>& relationship_name, const Glib::ustring& field, const Glib::ustring& field_second, bool show_all);
/** Get whether the text should be displayed with multiple lines in the
* details view. Text is displayed with a single line in the list view.
diff --git a/glom/libglom/document/document.cc b/glom/libglom/document/document.cc
index 1c97b8f..112fbb2 100644
--- a/glom/libglom/document/document.cc
+++ b/glom/libglom/document/document.cc
@@ -2000,7 +2000,7 @@ void Document::load_after_layout_item_formatting(const xmlpp::Element* element,
}
sharedptr<Relationship> relationship = get_relationship(table_name, relationship_name);
- format.set_choices(relationship,
+ format.set_choices_related(relationship,
get_node_attribute_value(element, GLOM_ATTRIBUTE_FORMAT_CHOICES_RELATED_FIELD),
get_node_attribute_value(element, GLOM_ATTRIBUTE_FORMAT_CHOICES_RELATED_SECOND),
show_all);
@@ -3003,7 +3003,7 @@ void Document::save_before_layout_item_formatting(xmlpp::Element* nodeItem, cons
sharedptr<const Relationship> choice_relationship;
Glib::ustring choice_field, choice_second;
bool choice_show_all = false;
- format.get_choices(choice_relationship, choice_field, choice_second, choice_show_all);
+ format.get_choices_related(choice_relationship, choice_field, choice_second, choice_show_all);
set_node_attribute_value(nodeItem, GLOM_ATTRIBUTE_FORMAT_CHOICES_RELATED_RELATIONSHIP, glom_get_sharedptr_name(choice_relationship));
set_node_attribute_value(nodeItem, GLOM_ATTRIBUTE_FORMAT_CHOICES_RELATED_FIELD, choice_field);
diff --git a/glom/libglom/utils.cc b/glom/libglom/utils.cc
index e2fcb11..e6df8a8 100644
--- a/glom/libglom/utils.cc
+++ b/glom/libglom/utils.cc
@@ -342,11 +342,15 @@ void Utils::build_sql_select_add_fields_to_get(const Glib::RefPtr<Gnome::Gda::Sq
}
else
{
- const Gnome::Gda::SqlBuilder::Id id = builder->select_add_field(layout_item->get_name(), parent);
+ const Glib::ustring field_name = layout_item->get_name();
+ if(!field_name.empty())
+ {
+ const Gnome::Gda::SqlBuilder::Id id = builder->select_add_field(field_name, parent);
- //Avoid duplicate records with doubly-related fields:
- if(extra_join)
- builder->select_group_by(id);
+ //Avoid duplicate records with doubly-related fields:
+ if(extra_join)
+ builder->select_group_by(id);
+ }
}
@@ -363,51 +367,60 @@ void Utils::build_sql_select_add_fields_to_get(const Glib::RefPtr<Gnome::Gda::Sq
Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_where_clause(const Glib::ustring& table_name, const type_vecConstLayoutFields& fieldsToGet, const Gnome::Gda::SqlExpr& where_clause, const sharedptr<const Relationship>& extra_join, const type_sort_clause& sort_clause, guint limit)
{
+ Glib::RefPtr<Gnome::Gda::SqlBuilder> builder;
+
//Build the whole SQL statement:
- Glib::RefPtr<Gnome::Gda::SqlBuilder> builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
- builder->select_add_target(table_name);
+ try
+ {
+ builder = Gnome::Gda::SqlBuilder::create(Gnome::Gda::SQL_STATEMENT_SELECT);
+ builder->select_add_target(table_name);
- //Add the fields to SELECT, plus the tables that they are selected FROM.
- //We tell it whether extra_join is empty, so it can do an extra GROUP BY if necessary.
- //TODO: Try to use DISTINCT instead, with a proper test case.
- Utils::build_sql_select_add_fields_to_get(builder, table_name, fieldsToGet, sort_clause, extra_join /* bool */);
+ //Add the fields to SELECT, plus the tables that they are selected FROM.
+ //We tell it whether extra_join is empty, so it can do an extra GROUP BY if necessary.
+ //TODO: Try to use DISTINCT instead, with a proper test case.
+ Utils::build_sql_select_add_fields_to_get(builder, table_name, fieldsToGet, sort_clause, extra_join /* bool */);
- if(extra_join)
- {
- sharedptr<UsesRelationship> uses_relationship = sharedptr<UsesRelationship>::create();
- uses_relationship->set_relationship(extra_join);
- builder_add_join(builder, uses_relationship);
- }
+ if(extra_join)
+ {
+ sharedptr<UsesRelationship> uses_relationship = sharedptr<UsesRelationship>::create();
+ uses_relationship->set_relationship(extra_join);
+ builder_add_join(builder, uses_relationship);
+ }
- //Add the WHERE clause:
- if(!where_clause.empty())
- {
- const int id = builder->import_expression(where_clause);
- builder->set_where(id);
- }
+ //Add the WHERE clause:
+ if(!where_clause.empty())
+ {
+ const int id = builder->import_expression(where_clause);
+ builder->set_where(id);
+ }
- //Sort clause:
- if(!sort_clause.empty())
- {
- for(type_sort_clause::const_iterator iter = sort_clause.begin(); iter != sort_clause.end(); ++iter)
+ //Sort clause:
+ if(!sort_clause.empty())
{
- sharedptr<const LayoutItem_Field> layout_item = iter->first;
- if(layout_item)
+ for(type_sort_clause::const_iterator iter = sort_clause.begin(); iter != sort_clause.end(); ++iter)
{
- const bool ascending = iter->second;
+ sharedptr<const LayoutItem_Field> layout_item = iter->first;
+ if(layout_item)
+ {
+ const bool ascending = iter->second;
- //TODO: Avoid the need for the "."
- builder->select_order_by(
- builder->add_field_id(layout_item->get_name(), layout_item->get_sql_table_or_join_alias_name(table_name)),
- ascending);
+ //TODO: Avoid the need for the "."
+ builder->select_order_by(
+ builder->add_field_id(layout_item->get_name(), layout_item->get_sql_table_or_join_alias_name(table_name)),
+ ascending);
+ }
}
}
- }
- //LIMIT clause:
- if(limit > 0)
+ //LIMIT clause:
+ if(limit > 0)
+ {
+ builder->select_set_limit(limit);
+ }
+ }
+ catch(const Glib::Error& ex)
{
- builder->select_set_limit(limit);
+ std::cerr << G_STRFUNC << ": Exception: " << ex.what() << std::endl;
}
return builder;
@@ -468,16 +481,17 @@ Utils::type_list_values_with_second Utils::get_choice_values(const sharedptr<con
sharedptr<const Relationship> choice_relationship;
Glib::ustring choice_field, choice_second;
- bool choice_show_all = false; //TODO: Use this.
- if(!choice_show_all)
+ 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::cerr << G_STRFUNC << ": Not fully implemented. TODO: Restrict values to related records." << std::endl;
+ //std::cout <<" debug: field has no choices: " << field->get_name() << std::endl;
+ return list_values;
}
- field->get_formatting_used().get_choices(choice_relationship, choice_field, choice_second, choice_show_all);
- if(!choice_relationship)
+ if(!choice_show_all)
{
- //std::cout <<" debug: field has no choices: " << field->get_name() << std::endl;
+ std::cerr << G_STRFUNC << ": This should not be called for !show_all choices." << std::endl;
return list_values;
}
diff --git a/glom/mode_data/box_data_portal.h b/glom/mode_data/box_data_portal.h
index ad4189d..13e0421 100644
--- a/glom/mode_data/box_data_portal.h
+++ b/glom/mode_data/box_data_portal.h
@@ -60,7 +60,6 @@ public:
/** Update a portal if a relevant value in its parent table has changed.
*
* @param foreign_key_value: The value that should be found in this table.
- * @param from_table_primary_key_value The primary key of the parent record's table, used to associate new related records.
*/
bool refresh_data_from_database_with_foreign_key(const Gnome::Gda::Value& foreign_key_value);
diff --git a/glom/mode_data/datawidget/combo.cc b/glom/mode_data/datawidget/combo.cc
index f3fe95e..9cfe294 100644
--- a/glom/mode_data/datawidget/combo.cc
+++ b/glom/mode_data/datawidget/combo.cc
@@ -38,17 +38,8 @@ namespace DataWidgetChildren
{
ComboGlom::ComboGlom()
-: ComboChoicesWithTreeModel()
-{
-#ifndef GLOM_ENABLE_CLIENT_ONLY
- setup_menu();
-#endif // !GLOM_ENABLE_CLIENT_ONLY
-
- init();
-}
-
-ComboGlom::ComboGlom(const sharedptr<LayoutItem_Field>& field_second)
-: ComboChoicesWithTreeModel(field_second)
+: ComboChoicesWithTreeModel(),
+ m_cell_second(0)
{
#ifndef GLOM_ENABLE_CLIENT_ONLY
setup_menu();
@@ -74,7 +65,18 @@ void ComboGlom::init()
column->pack_start(m_Columns.m_col_first, false);
#endif //GLOM_ENABLE_MAEMO
- if(m_with_second)
+ //if(m_glom_type == Field::TYPE_NUMERIC)
+ // get_entry()->set_alignment(1.0); //Align numbers to the right.
+}
+
+ComboGlom::~ComboGlom()
+{
+}
+
+void ComboGlom::set_choices_related(const Document* document, const sharedptr<const Relationship>& relationship, const Glib::ustring& field, const Glib::ustring& field_second, bool show_all)
+{
+ //Add the extra cell if necessary:
+ if(!m_cell_second && !field_second.empty())
{
#ifndef GLOM_ENABLE_MAEMO
//We don't use this convenience method, because we want more control over the renderer.
@@ -82,26 +84,22 @@ void ComboGlom::init()
//(well, maybe set_cell_data_func(), but that's a bit awkward.)
//pack_start(m_Columns.m_col_second);
- Gtk::CellRenderer* cell_second = Gtk::manage(new Gtk::CellRendererText);
- cell_second->set_property("xalign", 0.0);
+ m_cell_second = Gtk::manage(new Gtk::CellRendererText);
+ m_cell_second->set_property("xalign", 0.0);
//Use the renderer:
- pack_start(*cell_second);
+ pack_start(*m_cell_second);
//Make the renderer render the column:
- add_attribute(cell_second->_property_renderable(), m_Columns.m_col_second);
+ add_attribute(m_cell_second->_property_renderable(), m_Columns.m_col_second);
+ std::cout << "debug: Added second column." << std::endl;
#else
//Maemo:
column->pack_start(m_Columns.m_col_second);
#endif //GLOM_ENABLE_MAEMO
}
-
- //if(m_glom_type == Field::TYPE_NUMERIC)
- // get_entry()->set_alignment(1.0); //Align numbers to the right.
-}
-
-ComboGlom::~ComboGlom()
-{
+
+ ComboChoicesWithTreeModel::set_choices_related(document, relationship, field, field_second, show_all);
}
void ComboGlom::check_for_change()
diff --git a/glom/mode_data/datawidget/combo.h b/glom/mode_data/datawidget/combo.h
index 4620fb5..93450d4 100644
--- a/glom/mode_data/datawidget/combo.h
+++ b/glom/mode_data/datawidget/combo.h
@@ -55,9 +55,6 @@ public:
///You must call set_layout_item() to specify the field type and formatting of the main column.
ComboGlom();
- ///You must call set_layout_item() to specify the field type and formatting of the main column.
- explicit ComboGlom(const sharedptr<LayoutItem_Field>& field_second);
-
virtual ~ComboGlom();
virtual void set_read_only(bool read_only = true);
@@ -74,6 +71,8 @@ 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:
void init();
@@ -101,6 +100,8 @@ private:
#ifdef GLOM_ENABLE_MAEMO
Hildon::TouchSelector m_maemo_selector;
#endif
+
+ Gtk::CellRenderer* m_cell_second;
};
} //namespace DataWidetChildren
diff --git a/glom/mode_data/datawidget/combo_as_radio_buttons.cc b/glom/mode_data/datawidget/combo_as_radio_buttons.cc
index 8598352..2a31a4b 100644
--- a/glom/mode_data/datawidget/combo_as_radio_buttons.cc
+++ b/glom/mode_data/datawidget/combo_as_radio_buttons.cc
@@ -45,19 +45,9 @@ ComboAsRadioButtons::ComboAsRadioButtons()
init();
}
-ComboAsRadioButtons::ComboAsRadioButtons(const sharedptr<LayoutItem_Field>& field_second)
-: ComboChoices(field_second)
-{
-#ifndef GLOM_ENABLE_CLIENT_ONLY
- setup_menu();
-#endif // !GLOM_ENABLE_CLIENT_ONLY
-
- init();
-}
-
void ComboAsRadioButtons::init()
{
- if(m_with_second)
+ if(m_related_field_second)
{
//TODO
}
@@ -86,9 +76,9 @@ void ComboAsRadioButtons::set_choices_with_second(const type_list_values_with_se
{
const Glib::ustring value_first = Conversions::get_text_for_gda_value(layout_item->get_glom_type(), iter->first, layout_item->get_formatting_used().m_numeric_format);
Glib::ustring title = value_first;
- if(m_with_second)
+ if(m_related_field_second)
{
- const Glib::ustring value_second = Conversions::get_text_for_gda_value(m_layoutitem_second->get_glom_type(), iter->second, m_layoutitem_second->get_formatting_used().m_numeric_format);
+ const Glib::ustring value_second = Conversions::get_text_for_gda_value(m_related_field_second->get_glom_type(), iter->second, m_related_field_second->get_formatting_used().m_numeric_format);
title += " - " + value_second; //TODO: Find a better way to join them?
}
diff --git a/glom/mode_data/datawidget/combo_as_radio_buttons.h b/glom/mode_data/datawidget/combo_as_radio_buttons.h
index 1f62689..c3a63dc 100644
--- a/glom/mode_data/datawidget/combo_as_radio_buttons.h
+++ b/glom/mode_data/datawidget/combo_as_radio_buttons.h
@@ -46,13 +46,9 @@ public:
///You must call set_layout_item() to specify the field type and formatting of the main column.
ComboAsRadioButtons();
- ///You must call set_layout_item() to specify the field type and formatting of the main column.
- explicit ComboAsRadioButtons(const sharedptr<LayoutItem_Field>& field_second);
-
virtual ~ComboAsRadioButtons();
virtual void set_choices(const FieldFormatting::type_list_values& list_values);
- virtual void set_choices_with_second(const type_list_values_with_second& list_values);
virtual void set_read_only(bool read_only = true);
@@ -72,6 +68,8 @@ public:
private:
void init();
+ virtual void set_choices_with_second(const type_list_values_with_second& list_values);
+
void on_radiobutton_toggled();
void check_for_change();
diff --git a/glom/mode_data/datawidget/combochoices.cc b/glom/mode_data/datawidget/combochoices.cc
index 55e3b58..f010410 100644
--- a/glom/mode_data/datawidget/combochoices.cc
+++ b/glom/mode_data/datawidget/combochoices.cc
@@ -20,6 +20,9 @@
#include "combochoices.h"
#include <libglom/data_structure/glomconversions.h>
+#include <libglom/document/document.h>
+#include <libglom/connectionpool.h>
+#include <libglom/utils.h>
#include <glibmm/i18n.h>
//#include <sstream> //For stringstream
@@ -35,25 +38,158 @@ namespace DataWidgetChildren
{
ComboChoices::ComboChoices()
-: m_with_second(false)
+: m_related_show_all(false)
{
init();
}
-ComboChoices::ComboChoices(const sharedptr<LayoutItem_Field>& field_second)
-: m_with_second(true),
- m_layoutitem_second(field_second)
+void ComboChoices::init()
{
- init();
}
-void ComboChoices::init()
+ComboChoices::~ComboChoices()
{
}
-ComboChoices::~ComboChoices()
+bool ComboChoices::refresh_data_from_database_with_foreign_key(const Gnome::Gda::Value& foreign_key_value)
+{
+ if(!m_related_relationship || !m_related_field)
+ {
+ std::cerr << G_STRFUNC << ": !m_related_relationship or !m_related_field." << std::endl;
+ return false;
+ }
+
+ if(Conversions::value_is_empty(foreign_key_value))
+ {
+ std::cerr << G_STRFUNC << ": foreign_key_value is empty." << std::endl;
+ return false;
+ }
+
+ 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;
+ return false;
+ }
+
+ //TODO: builder->select_order_by(choice_field_id);
+
+ //Connect to database and get the related values:
+ sharedptr<SharedConnection> connection = ConnectionPool::get_instance()->connect();
+
+ if(!connection)
+ {
+ std::cerr << G_STRFUNC << ": connection is null." << std::endl;
+ return false;
+ }
+
+ const std::string sql_query =
+ Utils::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)
+ {
+ 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;
+ 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(m_related_field_second && (cols_count > 1))
+ itempair.second = datamodel->get_value_at(1, row);
+
+ 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.
+ }
+ else
+ {
+ std::cerr << G_STRFUNC << ": Error while executing SQL" << std::endl <<
+ " " << sql_query << std::endl;
+ return false;
+ }
+
+ 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)
{
+ m_related_relationship = relationship;
+ m_related_show_all = show_all;
+
+ m_related_field_second.clear();
+ if(m_related_relationship && !field.empty())
+ {
+ 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);
+ }
+
+ 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.
}
-} //namespace DataWidetChildren
+} //namespace DataWidgetChildren
} //namespace Glom
diff --git a/glom/mode_data/datawidget/combochoices.h b/glom/mode_data/datawidget/combochoices.h
index a31054a..f039900 100644
--- a/glom/mode_data/datawidget/combochoices.h
+++ b/glom/mode_data/datawidget/combochoices.h
@@ -28,6 +28,8 @@
namespace Glom
{
+class Document;
+
namespace DataWidgetChildren
{
@@ -46,15 +48,31 @@ public:
virtual void set_choices(const FieldFormatting::type_list_values& list_values) = 0;
- 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;
+ /**
+ * See also refresh_data_from_database_with_foreign_key().
+ */
+ 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.
+ */
+ bool refresh_data_from_database_with_foreign_key(const Gnome::Gda::Value& foreign_key_value);
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;
- bool m_with_second;
- sharedptr<const LayoutItem_Field> m_layoutitem_second;
//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.
+ sharedptr<LayoutItem_Field> m_related_field;
+ sharedptr<LayoutItem_Field> m_related_field_second;
+ bool m_related_show_all;
};
} //namespace DataWidetChildren
diff --git a/glom/mode_data/datawidget/combochoiceswithtreemodel.cc b/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
index 09cba5f..6cf8ac6 100644
--- a/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
+++ b/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
@@ -39,12 +39,6 @@ ComboChoicesWithTreeModel::ComboChoicesWithTreeModel()
init();
}
-ComboChoicesWithTreeModel::ComboChoicesWithTreeModel(const sharedptr<LayoutItem_Field>& field_second)
-: ComboChoices(field_second)
-{
- init();
-}
-
void ComboChoicesWithTreeModel::init()
{
ComboChoices::init();
@@ -69,9 +63,9 @@ void ComboChoicesWithTreeModel::set_choices_with_second(const type_list_values_w
{
row[m_Columns.m_col_first] = Conversions::get_text_for_gda_value(layout_item->get_glom_type(), iter->first, layout_item->get_formatting_used().m_numeric_format);
- if(m_with_second && m_layoutitem_second)
+ if(m_related_field_second)
{
- row[m_Columns.m_col_second] = Conversions::get_text_for_gda_value(m_layoutitem_second->get_glom_type(), iter->second, m_layoutitem_second->get_formatting_used().m_numeric_format);
+ row[m_Columns.m_col_second] = Conversions::get_text_for_gda_value(m_related_field_second->get_glom_type(), iter->second, m_related_field_second->get_formatting_used().m_numeric_format);
}
}
}
diff --git a/glom/mode_data/datawidget/combochoiceswithtreemodel.h b/glom/mode_data/datawidget/combochoiceswithtreemodel.h
index 4fc23cf..8cad4e8 100644
--- a/glom/mode_data/datawidget/combochoiceswithtreemodel.h
+++ b/glom/mode_data/datawidget/combochoiceswithtreemodel.h
@@ -35,17 +35,15 @@ public:
///You must call set_layout_item() to specify the field type and formatting of the main column.
explicit ComboChoicesWithTreeModel();
- ///You must call set_layout_item() to specify the field type and formatting of the main column.
- explicit ComboChoicesWithTreeModel(const sharedptr<LayoutItem_Field>& field_second);
-
virtual ~ComboChoicesWithTreeModel();
virtual void set_choices(const FieldFormatting::type_list_values& list_values);
- virtual void set_choices_with_second(const type_list_values_with_second& list_values);
protected:
void init();
+ virtual void set_choices_with_second(const type_list_values_with_second& list_values);
+
//Tree model columns:
class ModelColumns : public Gtk::TreeModel::ColumnRecord
{
diff --git a/glom/mode_data/datawidget/comboentry.cc b/glom/mode_data/datawidget/comboentry.cc
index d062264..8d89417 100644
--- a/glom/mode_data/datawidget/comboentry.cc
+++ b/glom/mode_data/datawidget/comboentry.cc
@@ -42,17 +42,8 @@ namespace DataWidgetChildren
{
ComboEntry::ComboEntry()
-: ComboChoicesWithTreeModel()
-{
-#ifndef GLOM_ENABLE_CLIENT_ONLY
- setup_menu();
-#endif // !GLOM_ENABLE_CLIENT_ONLY
-
- init();
-}
-
-ComboEntry::ComboEntry(const sharedptr<LayoutItem_Field>& field_second)
-: ComboChoicesWithTreeModel(field_second)
+: ComboChoicesWithTreeModel(),
+ m_cell_second(0)
{
#ifndef GLOM_ENABLE_CLIENT_ONLY
setup_menu();
@@ -115,8 +106,15 @@ void ComboEntry::init()
get_entry()->signal_focus_out_event().connect(sigc::mem_fun(*this, &ComboEntry::on_entry_focus_out_event), false);
get_entry()->signal_activate().connect(sigc::mem_fun(*this, &ComboEntry::on_entry_activate));
+}
- if(m_with_second)
+ComboEntry::~ComboEntry()
+{
+}
+
+void ComboEntry::set_choices_related(const Document* document, const sharedptr<const Relationship>& relationship, const Glib::ustring& field, const Glib::ustring& field_second, bool show_all)
+{
+ if(!m_cell_second && !field_second.empty())
{
#ifndef GLOM_ENABLE_MAEMO
//We don't use this convenience method, because we want more control over the renderer.
@@ -124,22 +122,20 @@ void ComboEntry::init()
//(well, maybe set_cell_data_func(), but that's a bit awkward.)
//pack_start(m_Columns.m_col_second);
- Gtk::CellRenderer* cell_second = Gtk::manage(new Gtk::CellRendererText);
- cell_second->set_property("xalign", 0.0);
+ m_cell_second = Gtk::manage(new Gtk::CellRendererText);
+ m_cell_second->set_property("xalign", 0.0);
//Use the renderer:
- pack_start(*cell_second);
+ pack_start(*m_cell_second);
//Make the renderer render the column:
- add_attribute(cell_second->_property_renderable(), m_Columns.m_col_second);
+ add_attribute(m_cell_second->_property_renderable(), m_Columns.m_col_second);
#else //GLOM_ENABLE_MAEMO
column->pack_start(m_Columns.m_col_second, false);
#endif //GLOM_ENABLE_MAEMO
}
-}
-ComboEntry::~ComboEntry()
-{
+ ComboChoicesWithTreeModel::set_choices_related(document, relationship, field, field_second, show_all);
}
void ComboEntry::set_layout_item(const sharedptr<LayoutItem>& layout_item, const Glib::ustring& table_name)
diff --git a/glom/mode_data/datawidget/comboentry.h b/glom/mode_data/datawidget/comboentry.h
index 8f7bff7..9941644 100644
--- a/glom/mode_data/datawidget/comboentry.h
+++ b/glom/mode_data/datawidget/comboentry.h
@@ -55,9 +55,6 @@ public:
///You must call set_layout_item() to specify the field type and formatting of the main column.
ComboEntry();
- ///You must call set_layout_item() to specify the field type and formatting of the main column.
- explicit ComboEntry(const sharedptr<LayoutItem_Field>& field_second);
-
virtual ~ComboEntry();
//Override this so we can store the text to compare later.
@@ -73,6 +70,8 @@ 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:
void init();
@@ -111,6 +110,8 @@ private:
#ifdef GLOM_ENABLE_MAEMO
Hildon::TouchSelectorEntry m_maemo_selector;
#endif
+
+ Gtk::CellRenderer* m_cell_second;
};
} //namespace DataWidetChildren
diff --git a/glom/mode_data/datawidget/datawidget.cc b/glom/mode_data/datawidget/datawidget.cc
index 7e2540d..1af2791 100644
--- a/glom/mode_data/datawidget/datawidget.cc
+++ b/glom/mode_data/datawidget/datawidget.cc
@@ -46,7 +46,7 @@
namespace Glom
{
-static DataWidgetChildren::ComboChoices* create_combo_widget_for_field(const sharedptr<LayoutItem_Field>& field, const sharedptr<LayoutItem_Field>& layout_item_second = sharedptr<LayoutItem_Field>())
+static DataWidgetChildren::ComboChoices* create_combo_widget_for_field(const sharedptr<LayoutItem_Field>& field)
{
DataWidgetChildren::ComboChoices* result = 0;
bool as_radio_buttons = false; //TODO: Use this.
@@ -54,12 +54,12 @@ static DataWidgetChildren::ComboChoices* create_combo_widget_for_field(const sha
if(restricted)
{
if(as_radio_buttons)
- result = Gtk::manage(new DataWidgetChildren::ComboAsRadioButtons(layout_item_second));
+ result = Gtk::manage(new DataWidgetChildren::ComboAsRadioButtons());
else
- result = Gtk::manage(new DataWidgetChildren::ComboGlom(layout_item_second));
+ result = Gtk::manage(new DataWidgetChildren::ComboGlom());
}
else
- result = Gtk::manage(new DataWidgetChildren::ComboEntry(layout_item_second));
+ result = Gtk::manage(new DataWidgetChildren::ComboEntry());
return result;
}
@@ -127,38 +127,15 @@ DataWidget::DataWidget(const sharedptr<LayoutItem_Field>& field, const Glib::ust
}
else if(field->get_formatting_used().get_has_related_choices())
{
+ 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 show_all = false; //TODO: Use this.
- field->get_formatting_used().get_choices(choice_relationship, choice_field, choice_second, show_all);
- if(choice_relationship && !choice_field.empty())
- {
- const Glib::ustring to_table = choice_relationship->get_to_table();
-
- const bool with_second = !choice_second.empty();
- if(with_second && document)
- {
- const sharedptr<const Field> field_second = document->get_field(to_table, choice_second);
-
- const sharedptr<LayoutItem_Field> layout_field_second = sharedptr<LayoutItem_Field>::create();
- layout_field_second->set_full_field_details(field_second);
- //We use the default formatting for this field->
-
- combo = create_combo_widget_for_field(field, layout_field_second);
- }
- else
- {
- combo = create_combo_widget_for_field(field);
- }
-
- //set_choices() needs this, for the numeric layout:
- combo->set_layout_item( get_layout_item(), table_name);
-
- //If !show_all then the list must be set every time we show the data,
- //because it depends on another ID value:
- if(show_all)
- combo->set_choices_with_second( Utils::get_choice_values(field) );
- }
+ bool choice_show_all = false;
+ field->get_formatting_used().get_choices_related(choice_relationship, choice_field, choice_second, choice_show_all);
+
+ combo->set_choices_related(document, choice_relationship, choice_field, choice_second, choice_show_all);
}
else
{
diff --git a/glom/mode_data/flowtablewithfields.cc b/glom/mode_data/flowtablewithfields.cc
index 10430ca..5251604 100644
--- a/glom/mode_data/flowtablewithfields.cc
+++ b/glom/mode_data/flowtablewithfields.cc
@@ -794,7 +794,7 @@ void FlowTableWithFields::set_field_value(const sharedptr<const LayoutItem_Field
}
}
- //Refresh widgets which should show the related records for relationships that use this field:
+ //Refresh portal widgets which should show the related records for relationships that use this field:
type_portals list_portals = get_portals(field /* from_key field name */);
for(type_portals::iterator iter = list_portals.begin(); iter != list_portals.end(); ++iter)
{
@@ -805,6 +805,18 @@ void FlowTableWithFields::set_field_value(const sharedptr<const LayoutItem_Field
portal->refresh_data_from_database_with_foreign_key(value /* foreign key value */);
}
}
+
+ //Refresh choices widgets which should show the related records for relationships that use this field:
+ type_choice_widgets list_choice_widgets = get_choice_widgets(field /* from_key field name */);
+ for(type_choice_widgets::iterator iter = list_choice_widgets.begin(); iter != list_choice_widgets.end(); ++iter)
+ {
+ DataWidgetChildren::ComboChoices* widget = *iter;
+ if(widget)
+ {
+ //g_warning("FlowTableWithFields::set_field_value: foreign_key_value=%s", value.to_string().c_str());
+ widget->refresh_data_from_database_with_foreign_key(value /* foreign key value */);
+ }
+ }
}
void FlowTableWithFields::set_other_field_value(const sharedptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& value)
@@ -831,6 +843,18 @@ void FlowTableWithFields::set_other_field_value(const sharedptr<const LayoutItem
portal->refresh_data_from_database_with_foreign_key(value /* foreign key value */);
}
}
+
+ //Refresh choices widgets which should show the related records for relationships that use this field:
+ type_choice_widgets list_choice_widgets = get_choice_widgets(field /* from_key field name */);
+ for(type_choice_widgets::iterator iter = list_choice_widgets.begin(); iter != list_choice_widgets.end(); ++iter)
+ {
+ DataWidgetChildren::ComboChoices* widget = *iter;
+ if(widget)
+ {
+ //g_warning("FlowTableWithFields::set_field_value: foreign_key_value=%s", value.to_string().c_str());
+ widget->refresh_data_from_database_with_foreign_key(value /* foreign key value */);
+ }
+ }
}
Gnome::Gda::Value FlowTableWithFields::get_field_value(const sharedptr<const LayoutItem_Field>& field) const
@@ -908,7 +932,7 @@ FlowTableWithFields::type_portals FlowTableWithFields::get_portals(const sharedp
}
FlowTableWithFields::type_choice_widgets FlowTableWithFields::get_choice_widgets(const sharedptr<const LayoutItem_Field>& from_key)
-{
+{
type_choice_widgets result;
if(!from_key)
return result;
@@ -919,10 +943,14 @@ FlowTableWithFields::type_choice_widgets FlowTableWithFields::get_choice_widgets
for(type_listFields::iterator iter = m_listFields.begin(); iter != m_listFields.end(); ++iter)
{
DataWidget* widget = iter->m_second;
- DataWidgetChildren::ComboChoices* combochoices = dynamic_cast<DataWidgetChildren::ComboChoices*>(widget);
- if(!combochoices)
+ if(!widget)
continue;
+ Gtk::Widget* child_widget = widget->get_data_child_widget();
+ DataWidgetChildren::ComboChoices* combochoices = dynamic_cast<DataWidgetChildren::ComboChoices*>(child_widget);
+ if(!combochoices)
+ continue;
+
const sharedptr<const LayoutItem> layout_item =
combochoices->get_layout_item();
const sharedptr<const LayoutItem_Field> field =
@@ -935,10 +963,10 @@ FlowTableWithFields::type_choice_widgets FlowTableWithFields::get_choice_widgets
sharedptr<const Relationship> choice_relationship;
Glib::ustring choice_field, choice_second;
bool choice_show_all = false;
- format.get_choices(choice_relationship, choice_field, choice_second, choice_show_all);
+ format.get_choices_related(choice_relationship, choice_field, choice_second, choice_show_all);
if(choice_show_all)
continue; //"Show All" choices don't use the ID field values.
-
+
if(choice_relationship->get_from_field() == from_key_name)
result.push_back(combochoices);
}
diff --git a/glom/mode_design/layout/layout_item_dialogs/box_formatting.cc b/glom/mode_design/layout/layout_item_dialogs/box_formatting.cc
index 974e7e8..4133781 100644
--- a/glom/mode_design/layout/layout_item_dialogs/box_formatting.cc
+++ b/glom/mode_design/layout/layout_item_dialogs/box_formatting.cc
@@ -239,7 +239,7 @@ void Box_Formatting::set_formatting(const FieldFormatting& format, bool show_num
sharedptr<const Relationship> choices_relationship;
Glib::ustring choices_field, choices_field_second;
bool choices_show_all = false;
- format.get_choices(choices_relationship, choices_field, choices_field_second, choices_show_all);
+ format.get_choices_related(choices_relationship, choices_field, choices_field_second, choices_show_all);
m_combo_choices_relationship->set_selected_relationship(choices_relationship);
on_combo_choices_relationship_changed(); //Fill the combos so we can set their active items.
@@ -313,7 +313,7 @@ bool Box_Formatting::get_formatting(FieldFormatting& format) const
m_checkbutton_choices_restricted_as_radio_buttons->get_active());
sharedptr<Relationship> choices_relationship = m_combo_choices_relationship->get_selected_relationship();
- m_format.set_choices(choices_relationship,
+ m_format.set_choices_related(choices_relationship,
m_combo_choices_field->get_selected_field_name(),
m_combo_choices_field_second->get_selected_field_name(),
m_checkbutton_choices_related_show_all->get_active());
diff --git a/glom/utility_widgets/db_adddel/db_adddel.cc b/glom/utility_widgets/db_adddel/db_adddel.cc
index 2465aca..66dca4c 100644
--- a/glom/utility_widgets/db_adddel/db_adddel.cc
+++ b/glom/utility_widgets/db_adddel/db_adddel.cc
@@ -834,7 +834,7 @@ Gtk::CellRenderer* DbAddDel::construct_specified_columns_cellrenderer(const shar
sharedptr<const Relationship> choice_relationship;
Glib::ustring choice_field, choice_second;
bool choice_show_all; //TODO: Use this.
- item_field->get_formatting_used().get_choices(choice_relationship, choice_field, choice_second, choice_show_all);
+ item_field->get_formatting_used().get_choices_related(choice_relationship, choice_field, choice_second, choice_show_all);
if(choice_relationship && !choice_field.empty())
{
@@ -856,6 +856,7 @@ Gtk::CellRenderer* DbAddDel::construct_specified_columns_cellrenderer(const shar
}
}
+ //TODO: Update this when the relationship's field value changes:
Utils::type_list_values_with_second list_values = Utils::get_choice_values(item_field);
for(Utils::type_list_values_with_second::const_iterator iter = list_values.begin(); iter != list_values.end(); ++iter)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]