[glom] DbAddDel: Replace add_columns() with set_columns(), simplifying the code.



commit 5c2058e752948697fffee8fbda7ff7099bcf709b
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Sep 23 15:14:42 2010 +0200

    DbAddDel: Replace add_columns() with set_columns(), simplifying the code.
    
    * glom/libglom/data_structure/layout/layoutgroup.[h|cc]: Added non-const
      version of get_items_recursive().
    * glom/mode_data/db_adddel/db_adddel.[h|cc]: Remove add_columns() and
      set_columns_ready(), replacing them with set_columsn() which takes a list
      of layout items. Remove DbAddDelColumnInfo because we do not use its other
      member variables, replacing it with the simple list of layout items.
    * glom/mode_data/db_adddel/treemodel_db.[h|cc]: Improve debug out.
    * glom/mode_find/box_data_list_find.cc:
    * glom/mode_data/box_data_list.[h|cc]:
    * glom/mode_data/box_data_list_related.[h|cc]: Adapted.

 ChangeLog                                         |   15 ++
 glom/libglom/data_structure/layout/layoutgroup.cc |   20 ++
 glom/libglom/data_structure/layout/layoutgroup.h  |    4 +
 glom/mode_data/box_data_list.cc                   |  137 ++++++--------
 glom/mode_data/box_data_list.h                    |    5 +-
 glom/mode_data/box_data_list_related.cc           |  164 +++++++---------
 glom/mode_data/box_data_list_related.h            |   21 +-
 glom/mode_data/db_adddel/db_adddel.cc             |  207 +++++++--------------
 glom/mode_data/db_adddel/db_adddel.h              |   32 +---
 glom/mode_data/db_adddel/treemodel_db.cc          |    3 +-
 glom/mode_data/db_adddel/treemodel_db.h           |    2 +-
 glom/mode_find/box_data_list_find.cc              |    3 -
 12 files changed, 258 insertions(+), 355 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b8cb056..3c49768 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
 2010-09-23  Murray Cumming  <murrayc murrayc com>
 
+	DbAddDel: Replace add_columns() with set_columns(), simplifying the code.
+
+	* glom/libglom/data_structure/layout/layoutgroup.[h|cc]: Added non-const
+  version of get_items_recursive().
+	* glom/mode_data/db_adddel/db_adddel.[h|cc]: Remove add_columns() and
+  set_columns_ready(), replacing them with set_columsn() which takes a list
+  of layout items. Remove DbAddDelColumnInfo because we do not use its other
+  member variables, replacing it with the simple list of layout items.
+	* glom/mode_data/db_adddel/treemodel_db.[h|cc]: Improve debug out.
+	* glom/mode_find/box_data_list_find.cc:
+	* glom/mode_data/box_data_list.[h|cc]:
+	* glom/mode_data/box_data_list_related.[h|cc]: Adapted.
+
+2010-09-23  Murray Cumming  <murrayc murrayc com>
+
 	Move code into a create_cell() utility function.
 
   * glom/mode_data/db_adddel/cellrenderer*.[h|cc]: Move to
diff --git a/glom/libglom/data_structure/layout/layoutgroup.cc b/glom/libglom/data_structure/layout/layoutgroup.cc
index 2220877..b98c5a0 100644
--- a/glom/libglom/data_structure/layout/layoutgroup.cc
+++ b/glom/libglom/data_structure/layout/layoutgroup.cc
@@ -199,6 +199,26 @@ LayoutGroup::type_list_const_items LayoutGroup::get_items_recursive() const
   return result;
 }
 
+LayoutGroup::type_list_items LayoutGroup::get_items_recursive()
+{
+  type_list_items result;
+
+  for(type_list_items::const_iterator iter = m_list_items.begin(); iter != m_list_items.end(); ++iter)
+  {
+    const sharedptr<LayoutItem> item = *iter;
+    sharedptr<LayoutGroup> group = sharedptr<LayoutGroup>::cast_dynamic(item);
+    if(group)
+    {
+      const type_list_items sub_result = group->get_items_recursive();
+      result.insert(result.end(), sub_result.begin(), sub_result.end());
+    }
+    else
+      result.push_back(item);
+  }
+
+  return result;
+}
+
 void LayoutGroup::remove_relationship(const sharedptr<const Relationship>& relationship)
 {
   LayoutGroup::type_list_items::iterator iterItem = m_list_items.begin();
diff --git a/glom/libglom/data_structure/layout/layoutgroup.h b/glom/libglom/data_structure/layout/layoutgroup.h
index f95395c..75b9e7e 100644
--- a/glom/libglom/data_structure/layout/layoutgroup.h
+++ b/glom/libglom/data_structure/layout/layoutgroup.h
@@ -105,6 +105,10 @@ public:
    */
   type_list_const_items get_items_recursive() const;
 
+  /** Get the items recursively, depth-first, not returning any groups.
+   */
+  type_list_items get_items_recursive();
+
   virtual Glib::ustring get_part_type_name() const;
   virtual Glib::ustring get_report_part_id() const;
 
diff --git a/glom/mode_data/box_data_list.cc b/glom/mode_data/box_data_list.cc
index c3c88e9..2b5babc 100644
--- a/glom/mode_data/box_data_list.cc
+++ b/glom/mode_data/box_data_list.cc
@@ -394,47 +394,6 @@ bool Box_Data_List::get_showing_multiple_records() const
   return m_AddDel.get_count() > 1;
 }
 
-void Box_Data_List::create_layout_add_group(const sharedptr<LayoutGroup>& layout_group)
-{
-  if(!layout_group)
-    return;
-
-  LayoutGroup::type_list_items child_items = layout_group->get_items();
-  for(LayoutGroup::type_list_items::const_iterator iter = child_items.begin(); iter != child_items.end(); ++iter)
-  {
-    sharedptr<LayoutItem> child_item = *iter;
-
-    sharedptr<LayoutGroup> child_group = sharedptr<LayoutGroup>::cast_dynamic(child_item);
-    if(child_group)
-    {
-      //std::cout << "debug: Start Adding child group." << std::endl;
-      create_layout_add_group(child_group);
-      //std::cout << "debug: End Adding child group." << std::endl;
-    }
-    else
-    {
-      if(m_read_only)
-        child_item->set_editable(false);
-
-      //std::cout << "debug: adding column: " << child_item->get_name() << std::endl;
-
-      sharedptr<LayoutItem_Field> child_field = sharedptr<LayoutItem_Field>::cast_dynamic(child_item);
-      if(child_field)
-      {
-        //Check that the field really exists, to avoid SQL errors.
-        //This could probably only happen if we have failed to rename something everywhere, when the user has renamed something.
-        if(!DbUtils::get_field_exists_in_database(child_field->get_table_used(m_table_name), child_field->get_name()))
-        {
-          std::cerr << G_STRFUNC << ": Field does not exist in database: table_name=" << child_field->get_table_used(m_table_name) << ", field_name=" << child_field->get_name() << std::endl;
-          continue;
-        }
-      }
-
-      m_AddDel.add_column(child_item);
-    }
-  }
-}
-
 Document::type_list_layout_groups Box_Data_List::create_layout_get_layout()
 {
   //This method is overriden in Box_Data_List_Related.
@@ -447,62 +406,80 @@ void Box_Data_List::create_layout()
   Box_Data::create_layout(); //Fills m_TableFields.
 
   const Document* pDoc = dynamic_cast<const Document*>(get_document());
-  if(pDoc)
-  {
-    //Field Names:
-    m_AddDel.remove_all_columns();
-    //m_AddDel.set_columns_count(m_Fields.size());
+  if(!pDoc)
+    return;
 
-    m_AddDel.set_table_name(m_table_name);
 
+  //Field Names:
+  m_AddDel.remove_all_columns();
+  //m_AddDel.set_columns_count(m_Fields.size());
 
-    sharedptr<Field> field_primary_key = get_field_primary_key_for_table(m_table_name);
-    if(!field_primary_key)
-    {
-      std::cerr << G_STRFUNC << ": primary key not found." << std::endl;
-    }
-    else
-    {
-      //std::cout << "debug: " << G_STRFUNC << ": primary_key=" << field_primary_key->get_name() << std::endl;
+  m_AddDel.set_table_name(m_table_name);
 
-      m_AddDel.set_key_field(field_primary_key);
 
-      //This map of layout groups will also contain the field information from the database:
-      Document::type_list_layout_groups layout_groups = create_layout_get_layout();
+  sharedptr<Field> field_primary_key = get_field_primary_key_for_table(m_table_name);
+  if(!field_primary_key)
+  {
+    std::cerr << G_STRFUNC << ": primary key not found." << std::endl;
+    return;
+  }
 
-      //int debug_count = 0;
-      for(Document::type_list_layout_groups::const_iterator iter = layout_groups.begin(); iter != layout_groups.end(); ++iter)
-      {
-        //std::cout << "Box_Data_List::create_layout() group number=" << debug_count;
-        //debug_count++;
-        //iter->second->debug();
+   m_AddDel.set_key_field(field_primary_key);
 
-        create_layout_add_group(*iter);
-      }
-    }
 
 
-    m_FieldsShown = get_fields_to_show();
+  LayoutGroup::type_list_items items_to_use;
+
+  //This map of layout groups will also contain the field information from the database:
+  Document::type_list_layout_groups layout_groups = create_layout_get_layout();
+  for(Document::type_list_layout_groups::const_iterator iter = layout_groups.begin(); iter != layout_groups.end(); ++iter)
+  {
+    const sharedptr<LayoutGroup> layout_group = *iter;
+    if(!layout_group)
+      continue;
 
-    //Add extra possibly-non-visible columns that we need:
-    //TODO: Only add it if it is not already there.
-    if(field_primary_key)
+    const LayoutGroup::type_list_items child_items = layout_group->get_items_recursive();
+    for(LayoutGroup::type_list_items::const_iterator iterItems = child_items.begin(); iterItems != child_items.end(); ++iterItems)
     {
-      sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::create();
-      layout_item->set_hidden();
-      layout_item->set_full_field_details(m_AddDel.get_key_field());
-      m_FieldsShown.push_back(layout_item);
+      sharedptr<LayoutItem> child_item = *iterItems;
+
+      //TODO: Set the whole thing as read-only instead:
+      if(m_read_only)
+        child_item->set_editable(false);
 
-      m_AddDel.add_column(layout_item);
+      sharedptr<const LayoutItem_Field> child_field = sharedptr<const LayoutItem_Field>::cast_dynamic(child_item);
+      if(child_field)
+      {
+        //Check that the field really exists, to avoid SQL errors.
+        //This could probably only happen if we have failed to rename something everywhere, when the user has renamed something.
+        if(!DbUtils::get_field_exists_in_database(child_field->get_table_used(m_table_name), child_field->get_name()))
+        {
+          std::cerr << G_STRFUNC << ": Field does not exist in database: table_name=" << child_field->get_table_used(m_table_name) << ", field_name=" << child_field->get_name() << std::endl;
+          continue;
+        }
+      }
+
+      items_to_use.push_back(child_item);
     }
+  }
 
-    m_AddDel.set_found_set(m_found_set);
 
-    //Column-creation happens in fill_database() instead:
-    //otherwise the treeview will be filled twice.
-    //m_AddDel.set_columns_ready();
+  //Add extra possibly-non-visible columns that we need:
+  //TODO: Only add it if it is not already there.
+  if(field_primary_key)
+  {
+    sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::create();
+    layout_item->set_hidden();
+    layout_item->set_full_field_details(m_AddDel.get_key_field());
+    m_FieldsShown.push_back(layout_item);
+
+    items_to_use.push_back(layout_item);
   }
 
+  m_AddDel.set_columns(items_to_use);
+  m_AddDel.set_found_set(m_found_set);
+
+  m_FieldsShown = get_fields_to_show();
 }
 
 sharedptr<Field> Box_Data_List::get_field_primary_key() const
diff --git a/glom/mode_data/box_data_list.h b/glom/mode_data/box_data_list.h
index f8dd398..25f8885 100644
--- a/glom/mode_data/box_data_list.h
+++ b/glom/mode_data/box_data_list.h
@@ -31,7 +31,7 @@ namespace Glom
 
 class Box_Data_List : public Box_Data_ManyRecords
 {
-public: 
+public:
   Box_Data_List();
   virtual ~Box_Data_List();
 
@@ -83,8 +83,7 @@ protected:
   //Overrides of functions from Box_Data:
   virtual void create_layout(); //override
   virtual Document::type_list_layout_groups create_layout_get_layout();
-  void create_layout_add_group(const sharedptr<LayoutGroup>& layout_group);
-    
+
   virtual bool fill_from_database(); //override.
   virtual void enable_buttons();
 
diff --git a/glom/mode_data/box_data_list_related.cc b/glom/mode_data/box_data_list_related.cc
index 7390014..6dd7013 100644
--- a/glom/mode_data/box_data_list_related.cc
+++ b/glom/mode_data/box_data_list_related.cc
@@ -38,33 +38,33 @@ Box_Data_List_Related::Box_Data_List_Related()
   add_view(&m_AddDel); //Give it access to the document.
   m_AddDel.show();
   m_Alignment.show();
-  
-  //Connect signals:  
+
+  //Connect signals:
   m_AddDel.signal_user_requested_edit().connect(sigc::mem_fun(*this, &Box_Data_List_Related::on_adddel_user_requested_edit));
   m_AddDel.signal_record_changed().connect(sigc::mem_fun(*this, &Box_Data_List_Related::on_adddel_record_changed));
 
   m_AddDel.signal_script_button_clicked().connect(sigc::mem_fun(*this, &Box_Data_List_Related::on_adddel_script_button_clicked));
   m_AddDel.signal_record_added().connect(sigc::mem_fun(*this, &Box_Data_List_Related::on_adddel_record_added));
-  
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   m_AddDel.signal_user_requested_layout().connect(sigc::mem_fun(*this, &Box_Data_List_Related::on_adddel_user_requested_layout));
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 
-  //We do not actually use this, 
+  //We do not actually use this,
   //so it is a bug if this appears in the .glom file:
   m_layout_name = "list_related";
 }
 
 void Box_Data_List_Related::enable_buttons()
 {
-  const bool view_details_possible = 
-    get_has_suitable_record_to_view_details() && 
+  const bool view_details_possible =
+    get_has_suitable_record_to_view_details() &&
     (m_portal->get_navigation_type() != LayoutItem_Portal::NAVIGATION_NONE);
 
   #ifndef GLOM_ENABLE_MAEMO
   // Don't allow the user to go to a record in a hidden table.
   // Unless we are on Maemo - then we want to allow editing in a separate window only.
-  m_AddDel.set_allow_view_details(view_details_possible); 
+  m_AddDel.set_allow_view_details(view_details_possible);
   #endif //GLOM_ENABLE_MAEMO
 }
 
@@ -79,7 +79,7 @@ bool Box_Data_List_Related::init_db_details(const Glib::ustring& parent_table, b
   m_parent_table = parent_table;
 
   if(m_portal)
-    LayoutWidgetBase::m_table_name = m_portal->get_table_used(Glib::ustring() /* parent table_name, not used. */); 
+    LayoutWidgetBase::m_table_name = m_portal->get_table_used(Glib::ustring() /* parent table_name, not used. */);
   else
     LayoutWidgetBase::m_table_name = Glib::ustring();
 
@@ -95,7 +95,7 @@ bool Box_Data_List_Related::init_db_details(const Glib::ustring& parent_table, b
       //Note to translators: This text is shown instead of a table title, when the table has not yet been chosen.
       relationship_title = _("Undefined Table");
     }
-  
+
     m_Label.set_markup(Utils::bold_message(relationship_title));
     m_Label.show();
 
@@ -118,7 +118,7 @@ bool Box_Data_List_Related::init_db_details(const Glib::ustring& parent_table, b
   //Prevent impossible multiple related records:
   const bool single_related = (m_key_field && (m_key_field->get_unique_key() || m_key_field->get_primary_key()));
   m_AddDel.set_allow_only_one_related_record(single_related);
-  
+
   enable_buttons();
 
   FoundSet found_set;
@@ -162,7 +162,7 @@ bool Box_Data_List_Related::fill_from_database()
     allow_add = m_portal->get_relationship()->get_auto_create();
 
   m_AddDel.set_allow_add(allow_add);
-  
+
   m_AddDel.set_found_set(m_found_set);
   result = m_AddDel.refresh_from_database();
 
@@ -183,7 +183,7 @@ void Box_Data_List_Related::on_adddel_user_requested_edit(const Gtk::TreeModel::
   }
 
   //Call base class:
-  
+
   const Gnome::Gda::Value primary_key_value = m_AddDel.get_value_key(row); //The primary key is in the key.
   //std::cout << "debug: " << G_STRFUNC << ": Requesting edit for primary_key=" << primary_key_value.to_string() << std::endl;
   signal_user_requested_details().emit(primary_key_value);
@@ -207,10 +207,10 @@ void Box_Data_List_Related::on_adddel_script_button_clicked(const sharedptr<cons
 {
   if(!layout_item)
     return;
-  
+
   const Gnome::Gda::Value primary_key_value = get_primary_key_value(row);
 
-  // TODO: Calling refresh_data_from_database(), 
+  // TODO: Calling refresh_data_from_database(),
   // or navigating to a different table from inside the Python script,
   // causes a crash somewhere down in GTK+, so it is done in an idle handler here.
   // We are currently in a callback from the CellRendererButton_Text cell
@@ -218,7 +218,7 @@ void Box_Data_List_Related::on_adddel_script_button_clicked(const sharedptr<cons
   // Probably this causes issues somewhere.
   Glib::signal_idle().connect(
     sigc::bind(
-      sigc::mem_fun(*this, &Box_Data_List_Related::on_script_button_idle), 
+      sigc::mem_fun(*this, &Box_Data_List_Related::on_script_button_idle),
       layout_item,
       primary_key_value));
 }
@@ -245,9 +245,9 @@ bool Box_Data_List_Related::on_script_button_idle(const sharedptr<const LayoutIt
 
 void Box_Data_List_Related::on_adddel_record_added(const Gtk::TreeModel::iterator& row, const Gnome::Gda::Value& primary_key_value)
 {
-  //Note that on_record_added() would only be called on the AddDel itself, 
+  //Note that on_record_added() would only be called on the AddDel itself,
   //so we need to handle this AddDel signal.
-  
+
   //primary_key_value is a new autogenerated or human-entered key for the row.
   //It has already been added to the database.
   //Gnome::Gda::Value primary_key_value = m_AddDel.get_value_key(row);
@@ -266,7 +266,7 @@ void Box_Data_List_Related::on_adddel_record_added(const Gtk::TreeModel::iterato
     layout_item->set_full_field_details(m_key_field);
     key_value = m_AddDel.get_value(row, layout_item);
   }
-  
+
 
   //Make sure that the new related record is related,
   //by setting the foreign key:
@@ -288,22 +288,22 @@ void Box_Data_List_Related::on_adddel_record_added(const Gtk::TreeModel::iterato
     if(m_key_field && m_portal)
     {
       make_record_related(primary_key_value);
-      
+
       //Show it on the view, if it's visible:
       sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::create();
       layout_item->set_full_field_details(m_key_field);
 
-      //TODO: Although the to-field value is visible on the new related record, get_value() returns NULL so you can't immediately navigate to the new record: 
-      //std::cout << "debug: " << G_STRFUNC << ": setting field=" << layout_item->get_name() << "m_key_value=" << m_key_value.to_string() << std::endl; 
+      //TODO: Although the to-field value is visible on the new related record, get_value() returns NULL so you can't immediately navigate to the new record:
+      //std::cout << "debug: " << G_STRFUNC << ": setting field=" << layout_item->get_name() << "m_key_value=" << m_key_value.to_string() << std::endl;
       m_AddDel.set_value(row, layout_item, m_key_value);
     }
     else
       std::cerr << G_STRFUNC << ": m_key_field is NULL" << std::endl;
-  
+
 
     //on_adddel_user_changed(row, iKey); //Update the database.
   }
-  
+
   on_record_added(key_value, row);
 }
 
@@ -316,7 +316,7 @@ void Box_Data_List_Related::on_dialog_layout_hide()
 
 
   //Update the UI:
-  init_db_details(m_portal); 
+  init_db_details(m_portal);
 
   Box_Data::on_dialog_layout_hide();
 
@@ -370,98 +370,60 @@ Document::type_list_layout_groups Box_Data_List_Related::create_layout_get_layou
   //instead do this:
   if(m_portal)
     result.push_back(m_portal);
-  
+
   return result;
 }
 
-//These create_layout*() methods are actually copy/pasted from Box_Data_List().
+//These create_layout*() methods are actually copy/pasted from Box_Data_List(),
+//because we do not derived from Box_Data_List.
 //TODO: Reduce the copy/pasting of these?
 void Box_Data_List_Related::create_layout()
 {
   Box_Data::create_layout(); //Fills m_TableFields.
 
   const Document* pDoc = dynamic_cast<const Document*>(get_document());
-  if(pDoc)
-  {
-    //Field Names:
-    m_AddDel.remove_all_columns();
-    //m_AddDel.set_columns_count(m_Fields.size());
-
-    m_AddDel.set_table_name(Base_DB_Table::m_table_name);
-
+  if(!pDoc)
+    return;
 
-    sharedptr<Field> field_primary_key = get_field_primary_key_for_table(Base_DB_Table::m_table_name);
-    if(!field_primary_key)
-    {
-      //g_warning("%s: primary key not found.", __FUNCTION__);
-    }
-    else
-    {
-      m_AddDel.set_key_field(field_primary_key);
- 
-      //This map of layout groups will also contain the field information from the database:
-      Document::type_list_layout_groups layout_groups = create_layout_get_layout();
-      
-      //int debug_count = 0;
-      for(Document::type_list_layout_groups::const_iterator iter = layout_groups.begin(); iter != layout_groups.end(); ++iter)
-      {
-        //std::cout << "Box_Data_List::create_layout() group number=" << debug_count;
-        //debug_count++;
-        //iter->second->debug();
 
-        create_layout_add_group(*iter);
-      }
-    }
+  //Field Names:
+  m_AddDel.remove_all_columns();
+  //m_AddDel.set_columns_count(m_Fields.size());
 
+  m_AddDel.set_table_name(Base_DB_Table::m_table_name);
 
-    m_FieldsShown = get_fields_to_show();
 
-    //Add extra possibly-non-visible columns that we need:
-    //TODO: Only add it if it is not already there.
-    if(field_primary_key)
-    {
-      sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::create();
-      layout_item->set_hidden();
-      layout_item->set_full_field_details(m_AddDel.get_key_field());
-      m_FieldsShown.push_back(layout_item);
-
-      m_AddDel.add_column(layout_item);
-    }
+  sharedptr<Field> field_primary_key = get_field_primary_key_for_table(Base_DB_Table::m_table_name);
+  if(!field_primary_key)
+  {
+    std::cerr << G_STRFUNC << ": primary key not found." << std::endl;
+    return;
+  }
 
-    m_AddDel.set_found_set(m_found_set);
+   m_AddDel.set_key_field(field_primary_key);
 
-    //Column-creation happens in fill_database() instead:
-    //otherwise the treeview will be filled twice.
-    //m_AddDel.set_columns_ready();
-  }
 
-}
 
-void Box_Data_List_Related::create_layout_add_group(const sharedptr<LayoutGroup>& layout_group)
-{
-  if(!layout_group)
-    return;
+  LayoutGroup::type_list_items items_to_use;
 
-  LayoutGroup::type_list_items child_items = layout_group->get_items();
-  for(LayoutGroup::type_list_items::const_iterator iter = child_items.begin(); iter != child_items.end(); ++iter)
+  //This map of layout groups will also contain the field information from the database:
+  Document::type_list_layout_groups layout_groups = create_layout_get_layout();
+  for(Document::type_list_layout_groups::const_iterator iter = layout_groups.begin(); iter != layout_groups.end(); ++iter)
   {
-    sharedptr<LayoutItem> child_item = *iter;
+    const sharedptr<LayoutGroup> layout_group = *iter;
+    if(!layout_group)
+      continue;
 
-    sharedptr<LayoutGroup> child_group = sharedptr<LayoutGroup>::cast_dynamic(child_item);
-    if(child_group)
-    {
-      //std::cout << "debug: Start Adding child group." << std::endl;
-      create_layout_add_group(child_group);
-      //std::cout << "debug: End Adding child group." << std::endl;
-    }
-    else
+    const LayoutGroup::type_list_items child_items = layout_group->get_items_recursive();
+    for(LayoutGroup::type_list_items::const_iterator iterItems = child_items.begin(); iterItems != child_items.end(); ++iterItems)
     {
+      sharedptr<LayoutItem> child_item = *iterItems;
+
+      //TODO: Set the whole thing as read-only instead:
       if(m_read_only)
         child_item->set_editable(false);
 
-      //std::cout << "debug: adding column: " << child_item->get_name() << std::endl;
-
-      sharedptr<LayoutItem_Field> child_field = sharedptr<LayoutItem_Field>::cast_dynamic(child_item);
+      sharedptr<const LayoutItem_Field> child_field = sharedptr<const LayoutItem_Field>::cast_dynamic(child_item);
       if(child_field)
       {
         //Check that the field really exists, to avoid SQL errors.
@@ -473,9 +435,27 @@ void Box_Data_List_Related::create_layout_add_group(const sharedptr<LayoutGroup>
         }
       }
 
-      m_AddDel.add_column(child_item);
+      items_to_use.push_back(child_item);
     }
   }
+
+
+  //Add extra possibly-non-visible columns that we need:
+  //TODO: Only add it if it is not already there.
+  if(field_primary_key)
+  {
+    sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::create();
+    layout_item->set_hidden();
+    layout_item->set_full_field_details(m_AddDel.get_key_field());
+    m_FieldsShown.push_back(layout_item);
+
+    items_to_use.push_back(layout_item);
+  }
+
+  m_AddDel.set_columns(items_to_use);
+  m_AddDel.set_found_set(m_found_set);
+
+  m_FieldsShown = get_fields_to_show();
 }
 
 } //namespace Glom
diff --git a/glom/mode_data/box_data_list_related.h b/glom/mode_data/box_data_list_related.h
index 8fbb21a..8a111f8 100644
--- a/glom/mode_data/box_data_list_related.h
+++ b/glom/mode_data/box_data_list_related.h
@@ -30,7 +30,7 @@ namespace Glom
 
 class Box_Data_List_Related : public Box_Data_Portal
 {
-public: 
+public:
   Box_Data_List_Related();
 
   /**
@@ -55,34 +55,33 @@ protected:
   bool on_script_button_idle(const sharedptr<const LayoutItem_Button>& layout_item, const Gnome::Gda::Value& primary_key);
 
   void on_adddel_record_added(const Gtk::TreeModel::iterator& row, const Gnome::Gda::Value& primary_key_value);
-    
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   void on_adddel_user_requested_layout();
 #endif // !GLOM_ENABLE_CLIENT_ONLY
-    
+
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   virtual void on_dialog_layout_hide(); //override.
-#endif // !GLOM_ENABLE_CLIENT_ONLY 
-  
+#endif // !GLOM_ENABLE_CLIENT_ONLY
+
   //Implementations of pure virtual methods from Base_DB_Table_Data:
   virtual sharedptr<Field> get_field_primary_key() const; //TODO: Already in base class?
   virtual Gnome::Gda::Value get_primary_key_value_selected() const;
   virtual void set_primary_key_value(const Gtk::TreeModel::iterator& row, const Gnome::Gda::Value& value);
   virtual Gnome::Gda::Value get_primary_key_value(const Gtk::TreeModel::iterator& row) const;
- 
+
   //Overrides of functions from Box_Data:
-  virtual void create_layout(); //override
   virtual Document::type_list_layout_groups create_layout_get_layout();
-  void create_layout_add_group(const sharedptr<LayoutGroup>& layout_group);
-    
+  virtual void create_layout();
+
   virtual void enable_buttons(); //override
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
   virtual Dialog_Layout* create_layout_dialog() const; // override.
   virtual void prepare_layout_dialog(Dialog_Layout* dialog); // override.
 #endif // !GLOM_ENABLE_CLIENT_ONLY
-    
-    
+
+
   //Member widgets:
   mutable DbAddDel_WithButtons m_AddDel; //mutable because its get_ methods aren't const.
 };
diff --git a/glom/mode_data/db_adddel/db_adddel.cc b/glom/mode_data/db_adddel/db_adddel.cc
index 3e9da0b..4f21478 100644
--- a/glom/mode_data/db_adddel/db_adddel.cc
+++ b/glom/mode_data/db_adddel/db_adddel.cc
@@ -1,6 +1,6 @@
 /* Glom
  *
- * Copyright (C) 2001-2004 Murray Cumming
+ * Copyright (C) 2001-2010 Murray Cumming
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -43,31 +43,6 @@
 namespace Glom
 {
 
-DbAddDelColumnInfo::DbAddDelColumnInfo()
-:
-  m_editable(true),
-  m_visible(true)
-{
-}
-
-DbAddDelColumnInfo::DbAddDelColumnInfo(const DbAddDelColumnInfo& src)
-: m_item(src.m_item),
-  m_choices(src.m_choices),
-  m_editable(src.m_editable),
-  m_visible(src.m_visible)
-{
-}
-
-DbAddDelColumnInfo& DbAddDelColumnInfo::operator=(const DbAddDelColumnInfo& src)
-{
-  m_item = src.m_item;
-  m_choices = src.m_choices;
-  m_editable = src.m_editable;
-  m_visible = src.m_visible;
-
-  return *this;
-}
-
 DbAddDel::DbAddDel()
 : m_column_is_sorted(false),
   m_column_sorted_direction(false),
@@ -82,7 +57,6 @@ DbAddDel::DbAddDel()
   m_allow_delete(true),
   m_find_mode(false),
   m_allow_only_one_related_record(false),
-  m_columns_ready(false),
   m_allow_view(true),
   m_allow_view_details(false),
 #ifndef GLOM_ENABLE_MAEMO
@@ -491,14 +465,11 @@ bool DbAddDel::select_item(const Gtk::TreeModel::iterator& iter, bool start_edit
 {
   //Find the first column with a layout_item:
   sharedptr<const LayoutItem> layout_item;
-  for(type_ColumnTypes::iterator iter_columns = m_ColumnTypes.begin(); iter_columns != m_ColumnTypes.end(); ++iter_columns)
+  for(type_column_items::const_iterator iter_columns = m_column_items.begin(); iter_columns != m_column_items.end(); ++iter_columns)
   {
-    const DbAddDelColumnInfo& column_info = *iter_columns;
-    if(column_info.m_item)
-    {
-      layout_item = column_info.m_item;
+    layout_item = *iter_columns;
+    if(layout_item)
       break;
-    }
   }
 
   return select_item(iter, layout_item, start_editing);
@@ -614,29 +585,6 @@ guint DbAddDel::get_columns_count() const
   #endif //GLOM_ENABLE_MAEMO
 }
 
-/*
-void DbAddDel::set_columns_count(guint count)
-{
-  m_ColumnTypes.resize(count, STYLE_Text);
-  m_vecColumnNames.resize(count);
-}
-*/
-
-/*
-void DbAddDel::set_column_title(guint col, const Glib::ustring& strText)
-{
-  bool bPreventUserSignals = get_prevent_user_signals();
-  set_prevent_user_signals(true);
-
-  Gtk::TreeViewColumn* pColumn = m_TreeView.get_column(col);
-  if(pColumn)
-    pColumn->set_title(strText);
-
-
-  set_prevent_user_signals(bPreventUserSignals);
-}
-*/
-
 int DbAddDel::get_fixed_cell_height()
 {
   if(m_fixed_cell_height <= 0)
@@ -654,11 +602,11 @@ int DbAddDel::get_fixed_cell_height()
     m_fixed_cell_height = height;
 
     //Look at each column:
-    for(type_ColumnTypes::iterator iter = m_ColumnTypes.begin(); iter != m_ColumnTypes.end(); ++iter)
+    for(type_column_items::iterator iter = m_column_items.begin(); iter != m_column_items.end(); ++iter)
     {
       Glib::ustring font_name;
 
-      sharedptr<LayoutItem_WithFormatting> item_withformatting = sharedptr<LayoutItem_WithFormatting>::cast_dynamic(iter->m_item);
+      sharedptr<const LayoutItem_WithFormatting> item_withformatting = sharedptr<const LayoutItem_WithFormatting>::cast_dynamic(*iter);
       if(item_withformatting)
       {
          const FieldFormatting& formatting = item_withformatting->get_formatting_used();
@@ -762,7 +710,7 @@ void DbAddDel::construct_specified_columns()
 
   //Delay actual use of set_column_*() stuff until this method is called.
 
-  if(m_ColumnTypes.empty())
+  if(m_column_items.empty())
   {
     //std::cout << "debug: " << G_STRFUNC << ": showing hint model: m_find_mode=" << m_find_mode << std::endl;
 
@@ -784,7 +732,7 @@ void DbAddDel::construct_specified_columns()
 
   typedef Gtk::TreeModelColumn<Gnome::Gda::Value> type_modelcolumn_value;
   typedef std::vector< type_modelcolumn_value* > type_vecModelColumns;
-  type_vecModelColumns vecModelColumns(m_ColumnTypes.size(), 0);
+  type_vecModelColumns vecModelColumns(m_column_items.size(), 0);
 
   //Create the Gtk ColumnRecord:
 
@@ -794,9 +742,9 @@ void DbAddDel::construct_specified_columns()
   type_model_store::type_vec_fields fields;
   {
     type_vecModelColumns::size_type i = 0;
-    for(type_ColumnTypes::iterator iter = m_ColumnTypes.begin(); iter != m_ColumnTypes.end(); ++iter)
+    for(type_column_items::iterator iter = m_column_items.begin(); iter != m_column_items.end(); ++iter)
     {
-      sharedptr<LayoutItem_Field> item_field = sharedptr<LayoutItem_Field>::cast_dynamic(iter->m_item);
+      sharedptr<LayoutItem_Field> item_field = sharedptr<LayoutItem_Field>::cast_dynamic(*iter);
       if(item_field)
       {
         type_modelcolumn_value* pModelColumn = new type_modelcolumn_value;
@@ -806,9 +754,6 @@ void DbAddDel::construct_specified_columns()
 
         record.add( *pModelColumn );
 
-        //if(iter->m_item->get_has_relationship_name())
-        //  std::cout << "  DEBUG: relationship=" << iter->m_item->get_relationship()->get_name() << std::endl;
-
         fields.push_back(item_field);
 
         i++;
@@ -916,18 +861,17 @@ void DbAddDel::construct_specified_columns()
 
   for(type_vecModelColumns::iterator iter = vecModelColumns.begin(); iter != vecModelColumns.end(); ++iter)
   {
-    const DbAddDelColumnInfo& column_info = m_ColumnTypes[model_column_index];
-    if(column_info.m_visible)
+    const sharedptr<LayoutItem> layout_item = m_column_items[model_column_index];
+    if(layout_item) //column_info.m_visible)
     {
       no_columns_used = false;
 
-      const Glib::ustring column_name = column_info.m_item->get_title_or_name();
-      const Glib::ustring column_id = column_info.m_item->get_name();
+      const Glib::ustring column_name = layout_item->get_title_or_name();
+      const Glib::ustring column_id = layout_item->get_name();
 
       // Whenever we are dealing with real database fields,
       // we need to know the index of the field in the query:
       int item_data_model_column_index = -1;
-      sharedptr<const LayoutItem> layout_item = m_ColumnTypes[model_column_index].m_item;
       sharedptr<const LayoutItem_Field> item_field = sharedptr<const LayoutItem_Field>::cast_dynamic(layout_item);
       if(item_field)
       {
@@ -936,7 +880,7 @@ void DbAddDel::construct_specified_columns()
       }
 
       //Add the ViewColumn
-      Gtk::CellRenderer* pCellRenderer = construct_specified_columns_cellrenderer(column_info.m_item, model_column_index, item_data_model_column_index);
+      Gtk::CellRenderer* pCellRenderer = construct_specified_columns_cellrenderer(layout_item, model_column_index, item_data_model_column_index);
       if(pCellRenderer)
       {
         //Get the index of the field in the query, if it is a field:
@@ -947,10 +891,12 @@ void DbAddDel::construct_specified_columns()
           model_column_index, item_data_model_column_index,
           expand);
 
+        /* TODO:
         if(column_info.m_editable)
         {
 
         }
+        */
 
         ++view_column_index;
       }
@@ -1076,13 +1022,13 @@ void DbAddDel::set_value_selected(const sharedptr<const LayoutItem_Field>& layou
 
 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)
+  if(m_column_items.size() <= model_index)
   {
-    std::cerr << G_STRFUNC << ": model_index is out of range: model_index=" << model_index << ", size=" << m_ColumnTypes.size() << std::endl;
+    std::cerr << G_STRFUNC << ": model_index is out of range: model_index=" << model_index << ", size=" << m_column_items.size() << std::endl;
     return;
   }
 
-  sharedptr<const LayoutItem> item = m_ColumnTypes[model_index].m_item;
+  sharedptr<const LayoutItem> item = m_column_items[model_index];
   sharedptr<const LayoutItem_Field> layout_field = sharedptr<const LayoutItem_Field>::cast_dynamic(item);
   if(!layout_field)
   {
@@ -1113,10 +1059,9 @@ void DbAddDel::refresh_cell_choices_data_from_database_with_foreign_key(guint mo
 
 void DbAddDel::remove_all_columns()
 {
-  m_ColumnTypes.clear();
+  m_column_items.clear();
 
   m_fixed_cell_height = 0; //Force it to be recalculated.
-  m_columns_ready = false;
 }
 
 void DbAddDel::set_table_name(const Glib::ustring& table_name)
@@ -1125,40 +1070,36 @@ void DbAddDel::set_table_name(const Glib::ustring& table_name)
   Base_DB_Table::m_table_name = table_name;
 }
 
-guint DbAddDel::add_column(const sharedptr<LayoutItem>& layout_item)
+void DbAddDel::set_columns(const LayoutGroup::type_list_items& layout_items)
 {
-  if(!layout_item)
-    return 0; //TODO: Do something more sensible.
-
   InnerIgnore innerIgnore(this); //Stop on_treeview_columns_changed() from doing anything when it is called just because we add a new column.
 
-  DbAddDelColumnInfo column_info;
-  column_info.m_item = layout_item;
-  //column_info.m_editable = editable;
-  //column_info.m_visible = visible;
-
-  //Make it non-editable if it is auto-generated:
-
-  sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic(layout_item);
-  if(field)
+  for(LayoutGroup::type_list_items::const_iterator iter = layout_items.begin(); iter != layout_items.end(); ++iter)
   {
-    sharedptr<const Field> field_full = field->get_full_field_details();
-    if(field_full && field_full->get_auto_increment())
-      column_info.m_editable = false;
-    else
-      column_info.m_editable = field->get_editable_and_allowed();
-  }
+    sharedptr<LayoutItem> layout_item = *iter;
 
-  m_ColumnTypes.push_back(column_info);
+    if(!layout_item)
+      continue; //TODO: Do something more sensible.
 
-  //Generate appropriate model columns:
-  if(m_columns_ready)
-    construct_specified_columns();
+    //Make it non-editable if it is auto-generated:
+    //TODO: Actually use this bool:
+    /*
+    sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(layout_item);
+    if(field)
+    {
+      sharedptr<const Field> field_full = field->get_full_field_details();
+      if(field_full && field_full->get_auto_increment())
+        column_info.m_editable = false;
+      else
+        column_info.m_editable = field->get_editable_and_allowed();
+    }
+    */
 
-  //Tell the View to use the model:
-  //m_TreeView.set_model(m_refListStore);
+    m_column_items.push_back(layout_item);
+  }
 
-  return m_ColumnTypes.size() - 1;
+  //Generate appropriate model columns:
+  construct_specified_columns();
 }
 
 void DbAddDel::set_found_set(const FoundSet& found_set)
@@ -1171,12 +1112,6 @@ FoundSet DbAddDel::get_found_set() const
   return m_found_set;
 }
 
-void DbAddDel::set_columns_ready()
-{
-  m_columns_ready = true;
-  construct_specified_columns();
-}
-
 DbAddDel::type_list_indexes DbAddDel::get_data_model_column_index(const sharedptr<const LayoutItem_Field>& layout_item_field, bool including_specified_field_layout) const
 {
   //TODO_Performance: Replace all this looping by a cache/map:
@@ -1187,9 +1122,9 @@ DbAddDel::type_list_indexes DbAddDel::get_data_model_column_index(const sharedpt
     return list_indexes;
 
   guint data_model_column_index = 0;
-  for(type_ColumnTypes::const_iterator iter = m_ColumnTypes.begin(); iter != m_ColumnTypes.end(); ++iter)
+  for(type_column_items::const_iterator iter = m_column_items.begin(); iter != m_column_items.end(); ++iter)
   {
-    sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(iter->m_item); //TODO_Performance: This would be unnecessary if !layout_item_field
+    sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(*iter); //TODO_Performance: This would be unnecessary if !layout_item_field
     if(field)
     {
       if(field->is_same_field(layout_item_field)
@@ -1214,14 +1149,15 @@ DbAddDel::type_list_indexes DbAddDel::get_column_index(const sharedptr<const Lay
   sharedptr<const LayoutItem_Field> layout_item_field = sharedptr<const LayoutItem_Field>::cast_dynamic(layout_item);
 
   guint i = 0;
-  for(type_ColumnTypes::const_iterator iter = m_ColumnTypes.begin(); iter != m_ColumnTypes.end(); ++iter)
+  for(type_column_items::const_iterator iter = m_column_items.begin(); iter != m_column_items.end(); ++iter)
   {
-    sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(iter->m_item); //TODO_Performance: This would be unnecessary if !layout_item_field
+    const sharedptr<const LayoutItem> item = *iter;
+    const sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(item); //TODO_Performance: This would be unnecessary if !layout_item_field
     if(field && layout_item_field && field->is_same_field(layout_item_field))
     {
       list_indexes.push_back(i);
     }
-    else if(*(iter->m_item) == *(layout_item))
+    else if(*(item) == *(layout_item))
     {
       list_indexes.push_back(i);
     }
@@ -1242,9 +1178,9 @@ DbAddDel::type_list_indexes DbAddDel::get_choice_index(const sharedptr<const Lay
   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)
+  for(type_column_items::const_iterator iter = m_column_items.begin(); iter != m_column_items.end(); ++iter)
   {
-    sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(iter->m_item);
+    sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(*iter);
     if(!field)
        continue;
 
@@ -1268,9 +1204,9 @@ DbAddDel::type_list_indexes DbAddDel::get_choice_index(const sharedptr<const Lay
 
 sharedptr<const LayoutItem_Field> DbAddDel::get_column_field(guint column_index) const
 {
-  if(column_index < m_ColumnTypes.size())
+  if(column_index < m_column_items.size())
   {
-    sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic( m_ColumnTypes[column_index].m_item );
+    sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic( m_column_items[column_index] );
     if(field)
       return field;
   }
@@ -1294,7 +1230,7 @@ void DbAddDel::set_column_choices(guint col, const type_vec_strings& vecStrings)
 {
   InnerIgnore innerIgnore(this); //Stop on_treeview_columns_changed() from doing anything when it is called just because we add new columns.
 
-  m_ColumnTypes[col].m_choices = vecStrings;
+  m_column_items[col].m_choices = vecStrings;
 
   guint view_column_index = 0;
   const bool test = get_view_column_index(col, view_column_index);
@@ -1497,7 +1433,7 @@ void DbAddDel::on_cell_layout_button_clicked(const Gtk::TreeModel::Path& path, i
   Gtk::TreeModel::iterator iter = m_refListStore->get_iter(path);
   if(iter)
   {
-    sharedptr<const LayoutItem> layout_item = m_ColumnTypes[model_column_index].m_item;
+    sharedptr<const LayoutItem> layout_item = m_column_items[model_column_index];
     sharedptr<const LayoutItem_Button> item_button = sharedptr<const LayoutItem_Button>::cast_dynamic(layout_item);
     if(item_button)
     {
@@ -1643,7 +1579,7 @@ void DbAddDel::on_treeview_cell_edited(const Glib::ustring& path_string, const G
     }
 
 
-    sharedptr<LayoutItem_Field> item_field = sharedptr<LayoutItem_Field>::cast_dynamic(m_ColumnTypes[model_column_index].m_item);
+    sharedptr<LayoutItem_Field> item_field = sharedptr<LayoutItem_Field>::cast_dynamic(m_column_items[model_column_index]);
     if(!item_field)
       return;
 
@@ -1779,7 +1715,7 @@ void DbAddDel::on_treeview_column_resized(int model_column_index, DbTreeViewColu
   if(n_view_columns && (view_column == m_TreeView.get_column(n_view_columns -1)))
     return;
 
-  DbAddDelColumnInfo& column_info = m_ColumnTypes[model_column_index];
+  const sharedptr<LayoutItem>& layout_item = m_column_items[model_column_index];
 
   const int width = view_column->get_width();
   //std::cout << "debug: " << G_STRFUNC << ": width=" << width << std::endl;
@@ -1787,18 +1723,18 @@ void DbAddDel::on_treeview_column_resized(int model_column_index, DbTreeViewColu
   if(width == -1) //Means automatic.
     return;
 
-  if(column_info.m_item)
-      column_info.m_item->set_display_width(width);
+  if(layout_item)
+    layout_item->set_display_width(width);
 }
 
 void DbAddDel::on_treeview_column_clicked(int model_column_index)
 {
   BusyCursor busy_cursor(get_application());
 
-  if(model_column_index >= (int)m_ColumnTypes.size())
+  if(model_column_index >= (int)m_column_items.size())
     return;
 
-  sharedptr<const LayoutItem_Field> layout_item = sharedptr<const LayoutItem_Field>::cast_dynamic(m_ColumnTypes[model_column_index].m_item); //We can only sort on fields, not on other layout item.
+  sharedptr<const LayoutItem_Field> layout_item = sharedptr<const LayoutItem_Field>::cast_dynamic(m_column_items[model_column_index]); //We can only sort on fields, not on other layout item.
   if(layout_item && layout_item->get_name_not_empty())
   {
     bool ascending = true;
@@ -1858,9 +1794,9 @@ bool DbAddDel::get_column_to_expand(guint& column_to_expand) const
 
   //Discover the right-most text column:
   guint i = 0;
-  for(type_ColumnTypes::const_iterator iter = m_ColumnTypes.begin(); iter != m_ColumnTypes.end(); ++iter)
+  for(type_column_items::const_iterator iter = m_column_items.begin(); iter != m_column_items.end(); ++iter)
   {
-    sharedptr<LayoutItem> layout_item = iter->m_item;
+    sharedptr<LayoutItem> layout_item = *iter;
 
     sharedptr<LayoutItem_Field> layout_item_field = sharedptr<LayoutItem_Field>::cast_dynamic(layout_item);
     if(layout_item_field)
@@ -1910,7 +1846,7 @@ guint DbAddDel::treeview_append_column(const Glib::ustring& title, Gtk::CellRend
   guint cols_count = get_columns_count();
   #endif //GLOM_ENABLE_MAEMO
 
-  sharedptr<const LayoutItem> layout_item = m_ColumnTypes[model_column_index].m_item;
+  sharedptr<const LayoutItem> layout_item = m_column_items[model_column_index];
   sharedptr<const LayoutItem_Field> layout_item_field = sharedptr<const LayoutItem_Field>::cast_dynamic(layout_item);
 
   //Tell the Treeview.how to render the Gnome::Gda::Values:
@@ -1963,7 +1899,7 @@ guint DbAddDel::treeview_append_column(const Glib::ustring& title, Gtk::CellRend
   //This property is read only: pViewColumn->property_width() = column_width;
 
   //Save the extra ID, using the title if the column_id is empty:
-  const Glib::ustring column_id = m_ColumnTypes[model_column_index].m_item->get_name();
+  const Glib::ustring column_id = m_column_items[model_column_index]->get_name();
   pViewColumn->set_column_id( (column_id.empty() ? title : column_id) );
 
   //TODO pViewColumn->signal_button_press_event().connect( sigc::mem_fun(*this, &DbAddDel::on_treeview_columnheader_button_press_event) );
@@ -2091,10 +2027,7 @@ bool DbAddDel::get_view_column_index(guint model_column_index, guint& view_colum
   //Initialize output parameter:
   view_column_index = 0;
 
-  if(model_column_index >=  m_ColumnTypes.size())
-    return false;
-
-  if( !(m_ColumnTypes[model_column_index].m_visible) )
+  if(model_column_index >=  m_column_items.size())
     return false;
 
   view_column_index = model_column_index;
@@ -2145,9 +2078,9 @@ void DbAddDel::treeviewcolumn_on_cell_data(Gtk::CellRenderer* renderer, const Gt
 
   if(iter)
   {
-    const DbAddDelColumnInfo& column_info = m_ColumnTypes[model_column_index];
+    const sharedptr<LayoutItem>& layout_item = m_column_items[model_column_index];
 
-    sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic(column_info.m_item);
+    sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic(layout_item);
     if(field)
     {
       const guint col_real = data_model_column_index + get_count_hidden_system_columns();
@@ -2312,9 +2245,9 @@ bool DbAddDel::start_new_record()
   if(fieldPrimaryKey && fieldPrimaryKey->get_auto_increment())
   {
     //Start editing in the first cell that is not auto_increment:
-    for(type_ColumnTypes::iterator iter = m_ColumnTypes.begin(); iter != m_ColumnTypes.end(); ++iter)
+    for(type_column_items::iterator iter = m_column_items.begin(); iter != m_column_items.end(); ++iter)
     {
-      sharedptr<LayoutItem> layout_item = iter->m_item;
+      sharedptr<LayoutItem> layout_item = *iter;
       sharedptr<LayoutItem_Field> layout_item_field = sharedptr<LayoutItem_Field>::cast_dynamic(layout_item);
       if(!(layout_item_field->get_full_field_details()->get_auto_increment()))
       {
diff --git a/glom/mode_data/db_adddel/db_adddel.h b/glom/mode_data/db_adddel/db_adddel.h
index faeebee..1a5c977 100644
--- a/glom/mode_data/db_adddel/db_adddel.h
+++ b/glom/mode_data/db_adddel/db_adddel.h
@@ -43,23 +43,6 @@ namespace Glom
 
 class Application;
 
-class DbAddDelColumnInfo
-{
-public:
-  DbAddDelColumnInfo();
-  DbAddDelColumnInfo(const DbAddDelColumnInfo& src);
-  DbAddDelColumnInfo& operator=(const DbAddDelColumnInfo& src);
-
-  sharedptr<LayoutItem> m_item;
-
-  //For fields with choices:
-  typedef std::vector<Glib::ustring> type_vec_strings;
-  type_vec_strings m_choices;
-
-  bool m_editable;
-  bool m_visible;
-};
-
 class DbTreeViewColumnGlom;
 
 /** For adding/deleting/selecting record rows.
@@ -167,23 +150,19 @@ public:
   bool get_allow_view_details() const;
 
 
-  /** @result The index of the new column.
-   */
-  guint add_column(const sharedptr<LayoutItem>& layout_item);
+  //The items are not const, so that their display widths can be changed in the UI.
+  void set_columns(const LayoutGroup::type_list_items& layout_items);
 
   /// Specify which records to show:
   void set_found_set(const FoundSet& found_set);
 
   FoundSet get_found_set() const;
 
-  /// Start using the added columns.
-  void set_columns_ready();
-
   guint get_columns_count() const;
 
   sharedptr<const LayoutItem_Field> get_column_field(guint column_index) const;
 
-  typedef DbAddDelColumnInfo::type_vec_strings type_vec_strings;
+  typedef std::vector<Glib::ustring> type_vec_strings;
 
   /** Retrieves the column order, even after they have been reordered by the user.
    * @result a vector of column_id. These column_ids were provided in the call to add_column().
@@ -408,8 +387,8 @@ private:
   Glib::RefPtr<type_model_store> m_refListStore;
 
   //Columns, not including the hidden internal columns:
-  typedef std::vector<DbAddDelColumnInfo> type_ColumnTypes;
-  type_ColumnTypes m_ColumnTypes;
+  typedef LayoutGroup::type_list_items type_column_items;
+  type_column_items m_column_items;
   FoundSet m_found_set; //table, where_clause, sort_clause.
 
   bool m_column_is_sorted; //If empty, then m_column_sorted and m_column_sorted_direction should not be used.
@@ -451,7 +430,6 @@ private:
   /// The primary key for the table:
   sharedptr<Field> m_key_field;
 
-  bool m_columns_ready;
   bool m_allow_view;
   bool m_allow_view_details;
 
diff --git a/glom/mode_data/db_adddel/treemodel_db.cc b/glom/mode_data/db_adddel/treemodel_db.cc
index 14806bf..1901fad 100644
--- a/glom/mode_data/db_adddel/treemodel_db.cc
+++ b/glom/mode_data/db_adddel/treemodel_db.cc
@@ -270,7 +270,8 @@ bool DbTreeModel::refresh_from_database(const FoundSet& found_set)
       m_data_model_rows_count = 0;
       m_data_model_columns_count = m_columns_count;
 
-      std::cerr << G_STRFUNC << ": error executing SQL." << std::endl;
+      std::cerr << G_STRFUNC << ": error executing SQL. SQL query: " << std::endl;
+      std::cerr << "  " << Utils::sqlbuilder_get_full_query(sql_query) << std::endl;
       ConnectionPool::handle_error_cerr_only();
       return false; //No records were found.
     }
diff --git a/glom/mode_data/db_adddel/treemodel_db.h b/glom/mode_data/db_adddel/treemodel_db.h
index 08bf5ff..bc7c67f 100644
--- a/glom/mode_data/db_adddel/treemodel_db.h
+++ b/glom/mode_data/db_adddel/treemodel_db.h
@@ -69,7 +69,7 @@ public:
   typedef unsigned int size_type;
 
   //typedef std::vector<LayoutItem_Field> type_vec_fields;
-  typedef Base_DB::type_vecLayoutFields type_vec_fields;
+  typedef Base_DB::type_vecLayoutFields type_vec_fields; //TODO: Use const items instead?
 
   friend class DbTreeModelRow;
 
diff --git a/glom/mode_find/box_data_list_find.cc b/glom/mode_find/box_data_list_find.cc
index 99f3582..f0c81ae 100644
--- a/glom/mode_find/box_data_list_find.cc
+++ b/glom/mode_find/box_data_list_find.cc
@@ -63,9 +63,6 @@ bool Box_Data_List_Find::fill_from_database()
 
   m_FieldsShown = get_fields_to_show();
 
-  m_AddDel.set_columns_ready(); //Actually create the columns.
-  //m_AddDel.add_item(Glib::ValueBase("find"));
-
   return result;
 }
 



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