[glom/feature_choices_show_all] List: 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] List: Choices with !show_all: Update the list when the from_field changes.
- Date: Thu, 5 Aug 2010 22:55:54 +0000 (UTC)
commit 8d38f199264fd836a41251a34cc86ec85d2608de
Author: Murray Cumming <murrayc murrayc com>
Date: Fri Aug 6 00:55:22 2010 +0200
List: Choices with !show_all: Update the list when the from_field changes.
* glom/libglom/utils.[h|cc]: Added a get_choice_values() overload that
takes the foreign_key.
* glom/utility_widgets/db_adddel/db_adddel.[h|cc]: Added get_choice_index()
to get the affected choice lists when a field value changes.
Added refresh_cell_choices_data_from_database_with_foreign_key() to update
these lists.
set_value(): Use these methods to update choice lists when appropriate,
as already happens in the Details view.
ChangeLog | 15 +++-
glom/libglom/utils.cc | 127 +++++++++++++++++++++-
glom/libglom/utils.h | 2 +
glom/mode_data/datawidget/combochoices.cc | 6 +-
glom/mode_data/flowtablewithfields.cc | 2 +-
glom/utility_widgets/db_adddel/db_adddel.cc | 158 ++++++++++++++++++++++-----
glom/utility_widgets/db_adddel/db_adddel.h | 8 +-
7 files changed, 282 insertions(+), 36 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index e0237bc..5063778 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2010-08-06 Murray Cumming <murrayc murrayc com>
+
+ List: Choices with !show_all: Update the list when the from_field changes.
+
+ * glom/libglom/utils.[h|cc]: Added a get_choice_values() overload that
+ takes the foreign_key.
+ * glom/utility_widgets/db_adddel/db_adddel.[h|cc]: Added get_choice_index()
+ to get the affected choice lists when a field value changes.
+ Added refresh_cell_choices_data_from_database_with_foreign_key() to update
+ these lists.
+ set_value(): Use these methods to update choice lists when appropriate,
+ as already happens in the Details view.
+
2010-08-05 Murray Cumming <murrayc murrayc com>
List view: When a value is edited, update other instances of the same field.
@@ -19,7 +32,7 @@
2010-08-04 Murray Cumming <murrayc murrayc com>
- Choices with !show_all: Update the list when the from_field changes.
+ Details: 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().
diff --git a/glom/libglom/utils.cc b/glom/libglom/utils.cc
index e6df8a8..f8f6829 100644
--- a/glom/libglom/utils.cc
+++ b/glom/libglom/utils.cc
@@ -485,7 +485,7 @@ Utils::type_list_values_with_second Utils::get_choice_values(const sharedptr<con
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;
+ std::cout <<" debug: field has no choices: " << field->get_name() << std::endl;
return list_values;
}
@@ -520,8 +520,11 @@ Utils::type_list_values_with_second Utils::get_choice_values(const sharedptr<con
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;
@@ -552,6 +555,126 @@ Utils::type_list_values_with_second Utils::get_choice_values(const sharedptr<con
return list_values;
}
+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)
+{
+ //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;
+
+ 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;
+ return result;
+ }
+
+ const Glib::ustring to_table = choice_relationship->get_to_table();
+ sharedptr<const Field> field_details = document->get_field(to_table, choice_field);
+ if(!field_details)
+ {
+ 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);
+ if(!field_details)
+ {
+ std::cerr << G_STRFUNC << ": !field_details (second)." << std::endl;
+ return result;
+ }
+
+ 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;
+ }
+
+ //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);
+
+ if(!builder)
+ {
+ std::cerr << G_STRFUNC << ": builder is null." << std::endl;
+ return result;
+ }
+
+ //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 result;
+ }
+
+ const std::string sql_query =
+ Utils::sqlbuilder_get_full_query(builder);
+ //std::cout << "debug: sql_query=" << 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();
+ const guint cols_count = datamodel->get_n_columns();
+ 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(layout_choice_second && (cols_count > 1))
+ itempair.second = datamodel->get_value_at(1, row);
+
+ result.push_back(itempair);
+ }
+ }
+ else
+ {
+ std::cerr << G_STRFUNC << ": Error while executing SQL" << std::endl <<
+ " " << sql_query << std::endl;
+ return result;
+ }
+
+ return result;
+}
Glib::ustring Utils::create_name_from_title(const Glib::ustring& title)
{
diff --git a/glom/libglom/utils.h b/glom/libglom/utils.h
index 72429c5..493cbcf 100644
--- a/glom/libglom/utils.h
+++ b/glom/libglom/utils.h
@@ -110,6 +110,8 @@ Gnome::Gda::SqlExpr get_find_where_clause_quick(Document* document, const Glib::
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(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(
const Glib::RefPtr<Gnome::Gda::Connection>& connection,
diff --git a/glom/mode_data/datawidget/combochoices.cc b/glom/mode_data/datawidget/combochoices.cc
index f010410..8b1f5ee 100644
--- a/glom/mode_data/datawidget/combochoices.cc
+++ b/glom/mode_data/datawidget/combochoices.cc
@@ -61,8 +61,10 @@ bool ComboChoices::refresh_data_from_database_with_foreign_key(const Gnome::Gda:
if(Conversions::value_is_empty(foreign_key_value))
{
- std::cerr << G_STRFUNC << ": foreign_key_value is empty." << std::endl;
- return false;
+ //Clear the choices list:
+ type_list_values_with_second list_values;
+ set_choices_with_second(list_values);
+ return true;
}
if(m_related_show_all)
diff --git a/glom/mode_data/flowtablewithfields.cc b/glom/mode_data/flowtablewithfields.cc
index e26f0f3..e1612f3 100644
--- a/glom/mode_data/flowtablewithfields.cc
+++ b/glom/mode_data/flowtablewithfields.cc
@@ -947,7 +947,7 @@ FlowTableWithFields::type_choice_widgets FlowTableWithFields::get_choice_widgets
FlowTableWithFields* subtable = *iter;
if(subtable)
{
- type_choice_widgets sub_list = subtable->get_choice_widgets(from_key);
+ const type_choice_widgets sub_list = subtable->get_choice_widgets(from_key);
if(!sub_list.empty())
{
//Add to the main result:
diff --git a/glom/utility_widgets/db_adddel/db_adddel.cc b/glom/utility_widgets/db_adddel/db_adddel.cc
index e1cb37e..d2fe609 100644
--- a/glom/utility_widgets/db_adddel/db_adddel.cc
+++ b/glom/utility_widgets/db_adddel/db_adddel.cc
@@ -833,7 +833,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.
+ bool 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())
@@ -857,16 +857,19 @@ 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)
+ if(choice_show_all) //Otherwise it must change whenever the relationships's ID value changes.
{
- const Glib::ustring first = Conversions::get_text_for_gda_value(item_field->get_glom_type(), iter->first, item_field->get_formatting_used().m_numeric_format);
+ 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)
+ {
+ const Glib::ustring first = Conversions::get_text_for_gda_value(item_field->get_glom_type(), iter->first, item_field->get_formatting_used().m_numeric_format);
- Glib::ustring second;
- if(use_second)
- second = Conversions::get_text_for_gda_value(layout_field_second->get_glom_type(), iter->second, layout_field_second->get_formatting_used().m_numeric_format);
+ Glib::ustring second;
+ if(use_second)
+ second = Conversions::get_text_for_gda_value(layout_field_second->get_glom_type(), iter->second, layout_field_second->get_formatting_used().m_numeric_format);
- pCellRendererCombo->append_list_item(first, second);
+ pCellRendererCombo->append_list_item(first, second);
+ }
}
}
}
@@ -1216,31 +1219,35 @@ void DbAddDel::set_value(const Gtk::TreeModel::iterator& iter, const sharedptr<c
InnerIgnore innerIgnore(this);
if(!m_refListStore)
- g_warning("DbAddDel::set_value: No model.");
- else
{
- Gtk::TreeModel::Row treerow = *iter;
- if(treerow)
- {
- const type_list_indexes list_indexes = get_data_model_column_index(layout_item, set_specified_field_layout);
- for(type_list_indexes::const_iterator iter = list_indexes.begin(); iter != list_indexes.end(); ++iter)
- {
- const guint treemodel_col = *iter + get_count_hidden_system_columns();
- treerow.set_value(treemodel_col, value);
+ std::cerr << G_STRFUNC << ": No model." << std::endl;
+ return;
+ }
- //Mark this row as not a placeholder because it has real data now.
- if(!(Conversions::value_is_empty(value)))
- {
- //treerow.set_value(m_col_key, Glib::ustring("placeholder debug value setted"));
- //treerow.set_value(m_col_placeholder, false);
- }
- }
+ //Show the value in any columns:
+ Gtk::TreeModel::Row treerow = *iter;
+ if(treerow)
+ {
+ const type_list_indexes list_indexes = get_data_model_column_index(layout_item, set_specified_field_layout);
+ for(type_list_indexes::const_iterator iter = list_indexes.begin(); iter != list_indexes.end(); ++iter)
+ {
+ const guint treemodel_col = *iter + get_count_hidden_system_columns();
+ treerow.set_value(treemodel_col, value);
}
-
- //Add extra blank if necessary:
- //add_blank();
}
-
+
+ /// Get indexes of any columns with choices with !show_all relationships that have @a from_key as the from_key.
+ type_list_indexes list_choice_cells = get_choice_index(layout_item /* from_key field name */);
+ std::cout << "debug: list_choice_cells.size() == " << list_choice_cells.size() << std::endl;
+ for(type_list_indexes::iterator iter = list_choice_cells.begin(); iter != list_choice_cells.end(); ++iter)
+ {
+ const guint model_index = *iter;
+ refresh_cell_choices_data_from_database_with_foreign_key(model_index, value /* foreign key value */);
+ }
+
+ //Add extra blank if necessary:
+ //add_blank();
+
//g_warning("DbAddDel::set_value end");
}
@@ -1249,6 +1256,64 @@ void DbAddDel::set_value_selected(const sharedptr<const LayoutItem_Field>& layou
set_value(get_item_selected(), layout_item, value);
}
+void DbAddDel::refresh_cell_choices_data_from_database_with_foreign_key(guint model_index, const Gnome::Gda::Value& foreign_key_value)
+{
+ if(m_ColumnTypes.size() <= model_index)
+ {
+ std::cerr << G_STRFUNC << ": model_index is out of range: model_index=" << model_index << ", size=" << m_ColumnTypes.size() << std::endl;
+ return;
+ }
+
+ sharedptr<const LayoutItem> item = m_ColumnTypes[model_index].m_item;
+ sharedptr<const LayoutItem_Field> layout_field = sharedptr<const LayoutItem_Field>::cast_dynamic(item);
+ if(!layout_field)
+ {
+ std::cerr << G_STRFUNC << ": The layout item was not a LayoutItem_Field." << std::endl;
+ return;
+ }
+
+ guint view_column_index = 0;
+ const bool test = get_view_column_index(model_index, view_column_index);
+ if(!test)
+ {
+ std::cerr << G_STRFUNC << ": view column not found for model_column=" << model_index << std::endl;
+ return;
+ }
+
+ CellRendererList* cell =
+ dynamic_cast<CellRendererList*>( m_TreeView.get_column_cell_renderer(view_column_index) );
+ if(!cell)
+ {
+ std::cerr << G_STRFUNC << ": cell renderer not found for model_column=" << model_index << std::endl;
+ return;
+ }
+
+ //Set the choices:
+ cell->remove_all_list_items();
+
+ sharedptr<LayoutItem_Field> layout_choice_first;
+ sharedptr<LayoutItem_Field> layout_choice_second;
+ Utils::type_list_values_with_second list_values =
+ Utils::get_choice_values(get_document(), layout_field, foreign_key_value,
+ layout_choice_first, layout_choice_second);
+
+ for(Utils::type_list_values_with_second::const_iterator iter = list_values.begin(); iter != list_values.end(); ++iter)
+ {
+ const Glib::ustring first =
+ Conversions::get_text_for_gda_value(
+ layout_choice_first->get_glom_type(), iter->first, layout_choice_first->get_formatting_used().m_numeric_format);
+
+ Glib::ustring second;
+ if(layout_choice_second)
+ {
+ second = Conversions::get_text_for_gda_value(
+ layout_choice_second->get_glom_type(), iter->second, layout_choice_second->get_formatting_used().m_numeric_format);
+ }
+
+ cell->append_list_item(first, second);
+ }
+}
+
void DbAddDel::remove_all_columns()
{
m_ColumnTypes.clear();
@@ -1370,6 +1435,41 @@ DbAddDel::type_list_indexes DbAddDel::get_column_index(const sharedptr<const Lay
return list_indexes;
}
+DbAddDel::type_list_indexes DbAddDel::get_choice_index(const sharedptr<const LayoutItem_Field>& from_key)
+{
+ type_list_indexes result;
+
+ if(!from_key)
+ return result;
+
+ const Glib::ustring from_key_name = from_key->get_name();
+
+ guint index = 0;
+ for(type_ColumnTypes::const_iterator iter = m_ColumnTypes.begin(); iter != m_ColumnTypes.end(); ++iter)
+ {
+ sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(iter->m_item);
+ if(!field)
+ continue;
+
+ 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 && !choice_show_all) //"Show All" choices don't use the ID field values.
+ {
+ if(choice_relationship->get_from_field() == from_key_name)
+ result.push_back(index);
+ }
+
+ index++;
+ }
+
+ return result;
+}
+
+
sharedptr<const LayoutItem_Field> DbAddDel::get_column_field(guint column_index) const
{
if(column_index < m_ColumnTypes.size())
diff --git a/glom/utility_widgets/db_adddel/db_adddel.h b/glom/utility_widgets/db_adddel/db_adddel.h
index ef99b1b..388a2fc 100644
--- a/glom/utility_widgets/db_adddel/db_adddel.h
+++ b/glom/utility_widgets/db_adddel/db_adddel.h
@@ -61,6 +61,7 @@ public:
};
class DbTreeViewColumnGlom;
+class CellRendererList;
/** For adding/deleting/selecting record rows.
*/
@@ -286,7 +287,10 @@ private:
typedef std::list<guint> type_list_indexes;
///Return the column indexes of any columns that display this field.
- virtual type_list_indexes get_column_index(const sharedptr<const LayoutItem>& layout_item) const;
+ type_list_indexes get_column_index(const sharedptr<const LayoutItem>& layout_item) const;
+
+ /// Get indexes of any columns with choices with !show_all relationships that have @a from_key as the from_key.
+ type_list_indexes get_choice_index(const sharedptr<const LayoutItem_Field>& from_key);
/** Return the query column index of any columns that display this field:
* @param including_specified_field_layout If false, then don't return the actual layout item itself.
@@ -385,6 +389,8 @@ private:
//TODO: Remove this and use AppGlom::get_application() instead?
Application* get_application();
+
+ void refresh_cell_choices_data_from_database_with_foreign_key(guint model_index, const Gnome::Gda::Value& foreign_key_value);
static void apply_formatting(Gtk::CellRenderer* renderer, const sharedptr<const LayoutItem_WithFormatting>& layout_item);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]