[glom] Fix crashes when using choices with fixed lists.



commit 7093469abe8dd414e1cf5e8a87bdeb5ee197f46d
Author: Murray Cumming <murrayc murrayc com>
Date:   Sat Mar 12 16:22:20 2011 +0100

    Fix crashes when using choices with fixed lists.
    
    * glom/mode_data/datawidget/combochoiceswithtreemodel.[h|cc]:
    create_model_non_db(): Instead of creating just a text-based treemodel,
    create a Value-based one with an extra text column at the end. That is what
    the related-records model has, though it uses a custom TreeModel.
    The text column is needed for GtkComboBox when it has has-entry=true:
    (See https://bugzilla.gnome.org/show_bug.cgi?id=631167 )
    Add get_fixed_model_text_column() so that other code knows which column that
    is.
    * glom/mode_data/datawidget/cellrenderer_dblist.cc: set_choices_fixed(),
    repack_cells_fixed():
    * glom/mode_data/datawidget/combo.cc:set_choices_fixed():
    Adapt to use the special column instead of assuming that column 0 is a text
    column.
    Previously Glom::Combo::set_value() crashed because we tried to get a
    Value<Gnome::Gda::Value> where there was a Value<ustring>.

 ChangeLog                                          |   20 ++++++++
 glom/mode_data/datawidget/cellrenderer_dblist.cc   |    8 ++--
 glom/mode_data/datawidget/combo.cc                 |    9 +++-
 .../datawidget/combochoiceswithtreemodel.cc        |   51 ++++++++++++++++---
 .../datawidget/combochoiceswithtreemodel.h         |   18 ++++++-
 5 files changed, 89 insertions(+), 17 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index c4f332a..a52d047 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2011-03-12  Murray Cumming  <murrayc murrayc com>
+
+	Fix crashes when using choices with fixed lists.
+
+	* glom/mode_data/datawidget/combochoiceswithtreemodel.[h|cc]: 
+	create_model_non_db(): Instead of creating just a text-based treemodel, 
+	create a Value-based one with an extra text column at the end. That is what 
+	the related-records model has, though it uses a custom TreeModel.
+	The text column is needed for GtkComboBox when it has has-entry=true:
+	(See https://bugzilla.gnome.org/show_bug.cgi?id=631167 )
+	Add get_fixed_model_text_column() so that other code knows which column that 
+	is.
+	* glom/mode_data/datawidget/cellrenderer_dblist.cc: set_choices_fixed(),
+	repack_cells_fixed():
+	* glom/mode_data/datawidget/combo.cc:	set_choices_fixed():
+	Adapt to use the special column instead of assuming that column 0 is a text 
+	column.
+	Previously Glom::Combo::set_value() crashed because we tried to get a 
+	Value<Gnome::Gda::Value> where there was a Value<ustring>.
+
 2011-03-08  Murray Cumming  <murrayc murrayc com>
 
 	Remove some unnecessary padding/borders around the main window.
diff --git a/glom/mode_data/datawidget/cellrenderer_dblist.cc b/glom/mode_data/datawidget/cellrenderer_dblist.cc
index fcc391d..a080bb0 100644
--- a/glom/mode_data/datawidget/cellrenderer_dblist.cc
+++ b/glom/mode_data/datawidget/cellrenderer_dblist.cc
@@ -48,7 +48,7 @@ void CellRendererDbList::set_choices_fixed(const FieldFormatting::type_list_valu
 
   //Show model in the view:
   property_model() = model;
-  property_text_column() = 0; //This must be a text column, in m_refModel.
+  property_text_column() = get_fixed_model_text_column(); //This must be a text column, in m_refModel.
   property_editable() = true; //It would be useless if we couldn't edit it.
 
   //The other cells are added in on_editing_started().
@@ -112,7 +112,7 @@ void CellRendererDbList::repack_cells_fixed(Gtk::CellLayout* combobox)
     cell->unreference();
 
     //Make the renderer render the column:
-    combobox->add_attribute(*cell, "text", 0);
+    combobox->add_attribute(*cell, "text", get_fixed_model_text_column());
 
     cell->property_xalign() = 0.0f;
 
@@ -121,9 +121,9 @@ void CellRendererDbList::repack_cells_fixed(Gtk::CellLayout* combobox)
 
   //Add extra cells:
   Glib::ListHandle<Gtk::CellRenderer*> cells = combobox->get_cells();
-  if(cells.size() < m_vec_model_columns_fixed.size())
+  if(cells.size() < m_vec_model_columns_value_fixed.size())
   {
-    for(guint col = cells.size(); col != m_vec_model_columns_fixed.size(); ++col)
+    for(guint col = cells.size(); col != m_vec_model_columns_value_fixed.size(); ++col)
     {
       Gtk::CellRenderer* cell = 0;
       if(m_db_layout_items.empty())
diff --git a/glom/mode_data/datawidget/combo.cc b/glom/mode_data/datawidget/combo.cc
index 670f360..17fca4d 100644
--- a/glom/mode_data/datawidget/combo.cc
+++ b/glom/mode_data/datawidget/combo.cc
@@ -88,7 +88,7 @@ void ComboGlom::set_choices_fixed(const FieldFormatting::type_list_values& list_
 
   if(get_has_entry())
   {
-    set_entry_text_column(0);
+    set_entry_text_column( get_fixed_model_text_column() );
   }
   else
   {
@@ -103,11 +103,16 @@ void ComboGlom::set_choices_fixed(const FieldFormatting::type_list_values& list_
     return;
   }
   
-  const guint columns_count = model->get_n_columns();
+  guint columns_count = model->get_n_columns();
+  if(columns_count)
+    columns_count -= 1; //The last one is the just the extra text-equivalent of the first one, for GtkComboBox wth has-entry=true.
+
   for(guint i = 0; i < columns_count; ++i)
   {
     //set_entry_text_column() adds its own CellRenderer,
     //which we cannot replace without confusing (and crashing) GtkComboBox.
+    //We used the special get_fixed_model_text_column() column for that,
+    //so we don't need to add another cell renderer for the value-equivalent of that column:
     if(i == 0 && get_has_entry())
       continue;
 
diff --git a/glom/mode_data/datawidget/combochoiceswithtreemodel.cc b/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
index 2fcf74e..445b7aa 100644
--- a/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
+++ b/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
@@ -52,6 +52,15 @@ void ComboChoicesWithTreeModel::init()
   ComboChoices::init();
 }
 
+int ComboChoicesWithTreeModel::get_fixed_model_text_column() const
+{
+  const int count = m_refModel->get_n_columns();
+  if(count > 0)
+    return count -1;
+  else
+   return 0; //An error, but better than a negative number.
+}
+
 void ComboChoicesWithTreeModel::create_model_non_db(guint columns_count)
 {
   delete_model();
@@ -59,13 +68,29 @@ void ComboChoicesWithTreeModel::create_model_non_db(guint columns_count)
   Gtk::TreeModel::ColumnRecord record;
 
   //Create the TreeModelColumns, adding them to the ColumnRecord:
-  m_vec_model_columns_fixed.resize(columns_count, 0);
+    
+  m_vec_model_columns_value_fixed.resize(columns_count, 0);
   for(guint i = 0; i < columns_count; ++i)
-  {
-    type_model_column_fixed* model_column = new type_model_column_fixed();
+  {    
+    //Create a value column for all columns
+    //for instance for later value comparison.
+    type_model_column_value_fixed* model_column = new type_model_column_value_fixed();
+   
+    //Store it so we can use it and delete it later:
+    m_vec_model_columns_value_fixed[i] = model_column;
 
+    record.add(*model_column);
+  }
+  
+  //Create a text column, for use by a GtkComboBox with has-entry, which allows no other column type:
+  //Note that get_fixed_model_text_column() assumes that this is the last column:
+  m_vec_model_columns_string_fixed.resize(1, 0);
+  if(columns_count > 0)
+  {
+    type_model_column_string_fixed* model_column = new type_model_column_string_fixed();
+   
     //Store it so we can use it and delete it later:
-    m_vec_model_columns_fixed[i] = model_column;
+    m_vec_model_columns_string_fixed.push_back(model_column);
 
     record.add(*model_column);
   }
@@ -77,12 +102,20 @@ void ComboChoicesWithTreeModel::create_model_non_db(guint columns_count)
 void ComboChoicesWithTreeModel::delete_model()
 {
   //Delete the vector's items:
-  for(type_vec_model_columns_fixed::iterator iter = m_vec_model_columns_fixed.begin(); iter != m_vec_model_columns_fixed.end(); ++iter)
+  for(type_vec_model_columns_string_fixed::iterator iter = m_vec_model_columns_string_fixed.begin(); iter != m_vec_model_columns_string_fixed.end(); ++iter)
+  {
+    type_model_column_string_fixed* model_column = *iter;
+    delete model_column;
+  }
+  m_vec_model_columns_string_fixed.clear();
+  
+  //Delete the vector's items:
+  for(type_vec_model_columns_value_fixed::iterator iter = m_vec_model_columns_value_fixed.begin(); iter != m_vec_model_columns_value_fixed.end(); ++iter)
   {
-    type_model_column_fixed* model_column = *iter;
+    type_model_column_value_fixed* model_column = *iter;
     delete model_column;
   }
-  m_vec_model_columns_fixed.clear();
+  m_vec_model_columns_value_fixed.clear();
 
   m_refModel.reset();
 }
@@ -189,8 +222,10 @@ void ComboChoicesWithTreeModel::set_choices_fixed(const FieldFormatting::type_li
     if(layout_item)
     {
       const Gnome::Gda::Value value = *iter;
+      row.set_value(0, value);
+      
       const Glib::ustring text = Conversions::get_text_for_gda_value(layout_item->get_glom_type(), value, layout_item->get_formatting_used().m_numeric_format);
-      row.set_value(0, text);
+      row.set_value(1, text);
     }
   }
 
diff --git a/glom/mode_data/datawidget/combochoiceswithtreemodel.h b/glom/mode_data/datawidget/combochoiceswithtreemodel.h
index 4a185a2..65f3be0 100644
--- a/glom/mode_data/datawidget/combochoiceswithtreemodel.h
+++ b/glom/mode_data/datawidget/combochoiceswithtreemodel.h
@@ -56,9 +56,21 @@ protected:
    */
   int get_fixed_cell_height(Gtk::Widget& widget);
   
-  typedef Gtk::TreeModelColumn<Glib::ustring> type_model_column_fixed;
-  typedef std::vector< type_model_column_fixed* > type_vec_model_columns_fixed;
-  type_vec_model_columns_fixed m_vec_model_columns_fixed; //If set_choices_fixed() was used.
+
+  typedef Gtk::TreeModelColumn<Glib::ustring> type_model_column_string_fixed;
+  typedef std::vector< type_model_column_string_fixed* > type_vec_model_columns_string_fixed;
+  type_vec_model_columns_string_fixed m_vec_model_columns_string_fixed; //If set_choices_fixed() was used.
+
+  typedef Gtk::TreeModelColumn<Gnome::Gda::Value> type_model_column_value_fixed;
+  typedef std::vector< type_model_column_value_fixed* > type_vec_model_columns_value_fixed;
+  type_vec_model_columns_value_fixed m_vec_model_columns_value_fixed; //If set_choices_fixed() was used.
+
+  /** Get the index of the extra column, at the end, that is just a 
+   * text representation of the first column, for use by GtkCombo with has-entry=true,
+   * which accepts only a text column.
+   */
+  int get_fixed_model_text_column() const;
+
 
   typedef std::vector< sharedptr<const LayoutItem_Field> > type_vec_const_layout_items;
   type_vec_const_layout_items m_db_layout_items; //If set_choices_related() was used.



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