glom r1836 - in trunk: . glom/mode_data glom/mode_find glom/utility_widgets/db_adddel regression_tests



Author: murrayc
Date: Mon Jan 12 09:27:34 2009
New Revision: 1836
URL: http://svn.gnome.org/viewvc/glom?rev=1836&view=rev

Log:
2009-01-12  Murray Cumming  <murrayc murrayc com>

* glom/mode_find/box_data_list_find.cc: fill_from_database(): 
Call DbAddDel::set_columns_ready() so the treeview actually shows some 
columns.
* glom/utility_widgets/db_adddel/Makefile.am:
* glom/utility_widgets/db_adddel/treemodel_with_addrow.[h|cc]: A new 
common MI abstract base class for treemodels that have the extra empty 
row for adding rows.
* glom/utility_widgets/db_adddel/liststore_with_addrow.[h|cc]: A new 
treemodel derived from ListStore and the new base class, for use with 
find mode.
* glom/utility_widgets/db_adddel/glom_db_treemodel.h: Derive from 
the new base class.
* glom/utility_widgets/db_adddel/db_adddel.[h|cc]: 
construct_specified_columns(): Create the ListStore model for find mode.
Use the model via the base class where possible, so we can use the 
find mode model too.
Avoid changing the data in the database when in find mode.

This makes find mode work again in the list view, fixing bug #565579.

Added:
   trunk/glom/utility_widgets/db_adddel/liststore_with_addrow.cc
   trunk/glom/utility_widgets/db_adddel/liststore_with_addrow.h
   trunk/glom/utility_widgets/db_adddel/treemodel_with_addrow.cc
   trunk/glom/utility_widgets/db_adddel/treemodel_with_addrow.h
   trunk/regression_tests/test_treemodel_dynamic_cast.cc
Modified:
   trunk/ChangeLog
   trunk/glom/mode_data/box_data_list.cc
   trunk/glom/mode_find/box_data_list_find.cc
   trunk/glom/utility_widgets/db_adddel/Makefile.am
   trunk/glom/utility_widgets/db_adddel/db_adddel.cc
   trunk/glom/utility_widgets/db_adddel/db_adddel.h
   trunk/glom/utility_widgets/db_adddel/glom_db_treemodel.h
   trunk/regression_tests/Makefile.am

Modified: trunk/glom/mode_data/box_data_list.cc
==============================================================================
--- trunk/glom/mode_data/box_data_list.cc	(original)
+++ trunk/glom/mode_data/box_data_list.cc	Mon Jan 12 09:27:34 2009
@@ -22,6 +22,7 @@
 #include <glom/libglom/data_structure/glomconversions.h>
 #include <glom/libglom/glade_utils.h>
 #include <glom/reports/report_builder.h>
+#include <glom/utility_widgets/db_adddel/glom_db_treemodel.h>
 #include "dialog_layout_list.h"
 #include <glom/glom_privs.h>
 #include <bakery/App/App_Gtk.h> //For util_bold_message().
@@ -469,7 +470,7 @@
     }
     else
     {
-      std::cout << "DEBUG: Box_Data_List::create_layout(): primary_key=" << field_primary_key->get_name() << std::endl;
+      //std::cout << "DEBUG: Box_Data_List::create_layout(): primary_key=" << field_primary_key->get_name() << std::endl;
 
       m_AddDel.set_key_field(field_primary_key);
  
@@ -577,10 +578,20 @@
   found = 0;
 
   Glib::RefPtr<Gtk::TreeModel> refModel = m_AddDel.get_model();
+  //if(!refModel)
+  //  std::cerr << "Box_Data_List::get_record_counts(): (this=" << typeid(this).name() << ") The tree model was NULL." << std::endl;
+
   Glib::RefPtr<DbTreeModel> refModelDerived = Glib::RefPtr<DbTreeModel>::cast_dynamic(refModel);
   
   if(refModelDerived)
     refModelDerived->get_record_counts(total, found);
+
+  /*
+  else
+  {
+    std::cerr << "Box_Data_List::get_record_counts(): (this=" << typeid(this).name() << ") The tree model was not a DbTreeModel. It was a " << typeid(refModel.operator->()).name() << std::endl;
+  }
+  */
 }
 
 void Box_Data_List::on_adddel_user_sort_clause_changed()

Modified: trunk/glom/mode_find/box_data_list_find.cc
==============================================================================
--- trunk/glom/mode_find/box_data_list_find.cc	(original)
+++ trunk/glom/mode_find/box_data_list_find.cc	Mon Jan 12 09:27:34 2009
@@ -62,6 +62,7 @@
 
   m_FieldsShown = get_fields_to_show();
 
+  m_AddDel.set_columns_ready(); //Actually create the columns.
   //m_AddDel.add_item(Glib::ValueBase("find"));
 
   return result;

Modified: trunk/glom/utility_widgets/db_adddel/Makefile.am
==============================================================================
--- trunk/glom/utility_widgets/db_adddel/Makefile.am	(original)
+++ trunk/glom/utility_widgets/db_adddel/Makefile.am	Mon Jan 12 09:27:34 2009
@@ -7,6 +7,8 @@
                                       db_treeviewcolumn_glom.cc db_treeviewcolumn_glom.h \
                                       glom_db_treemodel.h glom_db_treemodel.cc \
                                       cellrenderer_buttonimage.h cellrenderer_buttonimage.cc \
-                                      cellrenderer_buttontext.h cellrenderer_buttontext.cc
+                                      cellrenderer_buttontext.h cellrenderer_buttontext.cc \
+                                      treemodel_with_addrow.h treemodel_with_addrow.cc \
+                                      liststore_with_addrow.h liststore_with_addrow.cc
                                       
  

Modified: trunk/glom/utility_widgets/db_adddel/db_adddel.cc
==============================================================================
--- trunk/glom/utility_widgets/db_adddel/db_adddel.cc	(original)
+++ trunk/glom/utility_widgets/db_adddel/db_adddel.cc	Mon Jan 12 09:27:34 2009
@@ -23,6 +23,8 @@
 #include <glibmm/i18n.h>
 #include "../cellrendererlist/cellrendererlist.h"
 #include "db_treeviewcolumn_glom.h"
+#include "glom_db_treemodel.h"
+#include "liststore_with_addrow.h"
 #include <glom/libglom/data_structure/glomconversions.h>
 #include "../../dialog_invalid_data.h"
 #include "../../application.h"
@@ -406,8 +408,8 @@
      return refTreeSelection->get_selected();
   }
 
-  if(m_refListStore)
-    return m_refListStore->children().end();
+  if(m_refListStore_as_model)
+    return m_refListStore_as_model->children().end();
   else
     return Gtk::TreeModel::iterator();
 }
@@ -421,8 +423,8 @@
      return unconst->get_selected();
   }
 
-  if(m_refListStore)
-    return m_refListStore->children().end();
+  if(m_refListStore_as_model)
+    return m_refListStore_as_model->children().end();
   else
     return Gtk::TreeModel::iterator();
 }
@@ -430,10 +432,10 @@
 
 Gtk::TreeModel::iterator DbAddDel::get_row(const Gnome::Gda::Value& key)
 {
-  if(!m_refListStore)
+  if(!m_refListStore_as_model)
     return Gtk::TreeModel::iterator();
 
-  for(Gtk::TreeModel::iterator iter = m_refListStore->children().begin(); iter != m_refListStore->children().end(); ++iter)
+  for(Gtk::TreeModel::iterator iter = m_refListStore_as_model->children().begin(); iter != m_refListStore_as_model->children().end(); ++iter)
   {
     //Gtk::TreeModel::Row row = *iter;
     const Gnome::Gda::Value& valTemp = get_value_key(iter);
@@ -443,7 +445,7 @@
     }
   }
 
-  return  m_refListStore->children().end();
+  return  m_refListStore_as_model->children().end();
 }
 
 bool DbAddDel::select_item(const Gtk::TreeModel::iterator& iter, bool start_editing)
@@ -489,7 +491,7 @@
     {
       refTreeSelection->select(iter);
 
-      Gtk::TreeModel::Path path = m_refListStore->get_path(iter);
+      Gtk::TreeModel::Path path = m_refListStore_as_model->get_path(iter);
 
       guint view_column_index = 0;
       const bool test = get_view_column_index(treemodel_col, view_column_index);
@@ -516,10 +518,10 @@
 
 guint DbAddDel::get_count() const
 {
-  if(!m_refListStore)
+  if(!m_refListStore_as_model)
     return 0;
 
-  guint iCount = m_refListStore->children().size();
+  guint iCount = m_refListStore_as_model->children().size();
 
   //Take account of the extra blank for new entries:
   if(get_allow_user_actions()) //If it has the extra row.
@@ -578,10 +580,10 @@
 
 void DbAddDel::on_cell_layout_button_clicked(const Gtk::TreeModel::Path& path, int model_column_index)
 {
-  if(!m_refListStore)
+  if(!m_refListStore_as_model)
     return;
 
-  Gtk::TreeModel::iterator iter = m_refListStore->get_iter(path);
+  Gtk::TreeModel::iterator iter = m_refListStore_as_model->get_iter(path);
   if(iter)
   {
     sharedptr<const LayoutItem> layout_item = m_ColumnTypes[model_column_index].m_item;
@@ -822,7 +824,7 @@
 
 void DbAddDel::construct_specified_columns()
 {
-  //std::cout << "debug: DbAddDel::construct_specified_columns" << std::endl;
+  //std::cout << "debug: DbAddDel::construct_specified_columns()" << std::endl;
 
   InnerIgnore innerIgnore(this);
 
@@ -832,6 +834,8 @@
 
   if(m_ColumnTypes.empty())
   {
+    //std::cout << "debug: DbAddDel::construct_specified_columns(): showing hint model: m_find_mode=" << m_find_mode << std::endl;
+
     show_hint_model();
     return;
   }
@@ -845,7 +849,7 @@
   Gtk::TreeModel::ColumnRecord record;
     
   //Database columns:
-  type_model_store::type_vec_fields fields;
+  DbTreeModel::type_vec_fields fields;
   {
     type_vecModelColumns::size_type i = 0;
     for(type_ColumnTypes::iterator iter = m_ColumnTypes.begin(); iter != m_ColumnTypes.end(); ++iter)
@@ -872,43 +876,59 @@
   
   m_FieldsShown = fields; //Needed by Base_DB_Table_Data::record_new().
 
-  //Find the primary key:
-  int column_index_key = 0;
-  bool key_found = false;
-  for(type_model_store::type_vec_fields::const_iterator iter = fields.begin(); iter != fields.end(); ++iter)
-  {
-    sharedptr<LayoutItem_Field> layout_item = *iter;
-    if( !(layout_item->get_has_relationship_name()) )
-    {
-      sharedptr<const Field> field_full = layout_item->get_full_field_details();
-      if(field_full && field_full->get_primary_key() )
-      {
-        key_found = true;
-        break;
-      }
-    }
-
-    ++column_index_key;
-  }
+  //std::cout << "DEBUG: DbAddDel::construct_specified_columns(): m_find_mode=" << m_find_mode << std::endl;
 
-  if(key_found)
+  if(m_find_mode)
   {
-    //Create the model from the ColumnRecord:
-    m_refListStore = type_model_store::create(record, m_found_set, fields, column_index_key, m_allow_view);
+    //std::cout << "DEBUG: DbAddDel::construct_specified_columns(): Creating ListStoreWithAddRow" << std::endl;
+    Glib::RefPtr<ListStoreWithAddRow> liststore = ListStoreWithAddRow::create(record, fields);
+    liststore->append();
+    m_refListStore = liststore.operator->();
+    m_refListStore_as_model = liststore;
   }
   else
   {
-    g_warning("%s: no primary key field found.", __FUNCTION__);
-    //for(type_model_store::type_vec_fields::const_iterator iter = fields.begin(); iter != fields.end(); ++iter)
-    //{
-    //  g_warning("  field: %s", (iter->get_name().c_str());
-    //}
+    //Find the primary key:
+    int column_index_key = 0;
+    bool key_found = false;
+    for(DbTreeModel::type_vec_fields::const_iterator iter = fields.begin(); iter != fields.end(); ++iter)
+    {
+      sharedptr<LayoutItem_Field> layout_item = *iter;
+      if( !(layout_item->get_has_relationship_name()) )
+      {
+        sharedptr<const Field> field_full = layout_item->get_full_field_details();
+        if(field_full && field_full->get_primary_key() )
+        {
+          key_found = true;
+          break;
+        }
+      }
 
-    m_refListStore = Glib::RefPtr<type_model_store>();
-  }
+      ++column_index_key;
+    }
 
+    if(key_found )
+    {
+      //Create the model from the ColumnRecord:
+      Glib::RefPtr<DbTreeModel> liststore  = DbTreeModel::create(record, m_found_set, fields, column_index_key, m_allow_view);
+      m_refListStore = liststore.operator->();
+      m_refListStore_as_model = liststore;
+    }
+    else
+    {
+      g_warning("%s: no primary key field found.", __FUNCTION__);
+      //for(type_model_store::type_vec_fields::const_iterator iter = fields.begin(); iter != fields.end(); ++iter)
+      //{
+      //  g_warning("  field: %s", (iter->get_name().c_str());
+      //}
+
+      Glib::RefPtr<DbTreeModel> liststore = Glib::RefPtr<DbTreeModel>();
+      m_refListStore = liststore.operator->();
+      m_refListStore_as_model = liststore;
+    }
+  }
  
-  m_TreeView.set_model(m_refListStore);
+  m_TreeView.set_model(m_refListStore_as_model);
 
 
   //Remove all View columns:
@@ -1028,7 +1048,7 @@
     if(m_TreeView.get_model())
       gtk_tree_view_set_model(m_TreeView.gobj(), 0); //This gives the same warning.
 
-    m_TreeView.set_model(m_refListStore);
+    m_TreeView.set_model(m_refListStore_as_model);
     return result;
   }
   else
@@ -1284,7 +1304,17 @@
 
 void DbAddDel::set_find_mode(bool val)
 {
+  std::cout << "DbAddDel::set_find_mode() val=" << val << std::endl;
+
+  const bool current = m_find_mode;
   m_find_mode = val;
+
+  //Recreate the model if necessary:
+  if( (current != m_find_mode) &&
+      m_refListStore)
+  {
+    construct_specified_columns();
+  }
 }
   
 void DbAddDel::set_allow_only_one_related_record(bool val)
@@ -1378,14 +1408,11 @@
 
 Gnome::Gda::Value DbAddDel::treeview_get_key(const Gtk::TreeModel::iterator& row) const
 {
-  Gnome::Gda::Value value;
-
-  if(m_refListStore)
-  {
-    return m_refListStore->get_key_value(row);
-  }
-
-  return value;
+  Glib::RefPtr<DbTreeModel> dbmodel = Glib::RefPtr<DbTreeModel>::cast_dynamic(m_refListStore_as_model);
+  if(dbmodel)
+    return dbmodel->get_key_value(row);
+  else
+    return Gnome::Gda::Value();
 }
 
 void DbAddDel::on_treeview_cell_edited_bool(const Glib::ustring& path_string, int model_column_index, int data_model_column_index)
@@ -1401,7 +1428,7 @@
   const Gtk::TreeModel::Path path(path_string);
 
   //Get the row from the path:
-  Gtk::TreeModel::iterator iter = m_refListStore->get_iter(path);
+  Gtk::TreeModel::iterator iter = m_refListStore_as_model->get_iter(path);
   if(iter)
   {
     Gtk::TreeModel::Row row = *iter;
@@ -1425,7 +1452,7 @@
     bool bIsAdd = false;
     bool bIsChange = false;
 
-    const int iCount = m_refListStore->children().size();
+    const int iCount = m_refListStore_as_model->children().size();
     if(iCount)
     {
       if(get_allow_user_actions()) //If add is possible:
@@ -1478,13 +1505,13 @@
   if(path_string.empty())
     return;
 
-  if(!m_refListStore)
+  if(!m_refListStore_as_model)
     return;
 
   const Gtk::TreeModel::Path path(path_string);
 
   //Get the row from the path:
-  Gtk::TreeModel::iterator iter = m_refListStore->get_iter(path);
+  Gtk::TreeModel::iterator iter = m_refListStore_as_model->get_iter(path);
   if(iter != get_model()->children().end())
   {
     Gtk::TreeModel::Row row = *iter;
@@ -1804,11 +1831,11 @@
 
 Glib::RefPtr<Gtk::TreeModel> DbAddDel::get_model()
 {
-  return m_refListStore;
+  return m_refListStore_as_model;
 }
 Glib::RefPtr<const Gtk::TreeModel> DbAddDel::get_model() const
 {
-  return m_refListStore;
+  return m_refListStore_as_model;
 }
 
 bool DbAddDel::get_is_first_row(const Gtk::TreeModel::iterator& iter) const
@@ -1865,7 +1892,10 @@
       //row[*m_modelcolumn_placeholder] = false;
     }
 
-    m_refListStore->set_key_value(iter, value);
+    //TODO_Performance: Cache the dynamic_cast<>ed result?
+    Glib::RefPtr<DbTreeModel> dbmodel = Glib::RefPtr<DbTreeModel>::cast_dynamic(m_refListStore_as_model);
+    if(dbmodel)
+      return dbmodel->set_key_value(iter, value);
   }
 }
 
@@ -1881,10 +1911,10 @@
   if(!iter)
     return false;
 
-  if(!m_refListStore)
+  if(!m_refListStore_as_model)
     return false;
 
-  if(iter == m_refListStore->children().end())
+  if(iter == m_refListStore_as_model->children().end())
   {
     return false;
   }
@@ -1948,11 +1978,22 @@
 
 void DbAddDel::treeviewcolumn_on_cell_data(Gtk::CellRenderer* renderer, const Gtk::TreeModel::iterator& iter, int model_column_index, int data_model_column_index)
 {
-  //std::cout << "debug: DbAddDel::treeviewcolumn_on_cell_data()" << std::endl; 
+  if(!m_refListStore_as_model)
+    return;
+
+  //std::cout << "debug: DbAddDel::treeviewcolumn_on_cell_data(): model columns count=" << m_refListStore_as_model->get_n_columns() << std::endl; 
 
 
   if(iter)
   {
+    /*
+    if(!iter->get_model_gobject())
+    {
+      std::cerr << "DbAddDel::treeviewcolumn_on_cell_data(): iter has no model" << std::endl;
+      return; 
+    }
+    */
+
     const DbAddDelColumnInfo& column_info = m_ColumnTypes[model_column_index];
 
     sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic(column_info.m_item);
@@ -2046,10 +2087,10 @@
 
 void DbAddDel::on_cell_button_clicked(const Gtk::TreeModel::Path& path)
 {
-  if(!m_refListStore)
+  if(!m_refListStore_as_model)
     return;
 
-  Gtk::TreeModel::iterator iter = m_refListStore->get_iter(path);
+  Gtk::TreeModel::iterator iter = m_refListStore_as_model->get_iter(path);
   if(iter)
   {
     select_item(iter, false /* start_editing */);
@@ -2193,9 +2234,12 @@
 
             //Note: This just uses an existing record if one already exists:
             Gnome::Gda::Value primary_key_value_used;
-            const bool test = add_related_record_for_field(layout_field, relationship, primary_key_field, primary_key_value, primary_key_value_used);
-            if(!test)
-              return;
+            if(!m_find_mode)
+            {
+              const bool test = add_related_record_for_field(layout_field, relationship, primary_key_field, primary_key_value, primary_key_value_used);
+              if(!test)
+                return;
+            }
 
             //Get the new primary_key_value if it has been created:
             primary_key_value = primary_key_value_used;
@@ -2339,6 +2383,9 @@
         return;
       }
 
+      if(m_find_mode)
+        return;
+    
       const bool added = record_new(true /* use entered field data*/, primary_key_value);
       if(added)
       {
@@ -2377,7 +2424,8 @@
     if(confirm_delete_record())
     {
       const Gnome::Gda::Value primary_key_value = get_primary_key_value(rowStart);
-      record_delete(primary_key_value);
+      if(!m_find_mode)
+        record_delete(primary_key_value);
 
       //Remove the row:
       remove_item(rowStart);

Modified: trunk/glom/utility_widgets/db_adddel/db_adddel.h
==============================================================================
--- trunk/glom/utility_widgets/db_adddel/db_adddel.h	(original)
+++ trunk/glom/utility_widgets/db_adddel/db_adddel.h	Mon Jan 12 09:27:34 2009
@@ -24,7 +24,7 @@
 #include <gtkmm.h>
 #include <glom/libglom/data_structure/layout/layoutitem_field.h>
 #include <libgdamm.h>
-#include "glom_db_treemodel.h"
+#include <glom/utility_widgets/db_adddel/treemodel_with_addrow.h>
 #include <glom/libglom/document/document_glom.h>
 #include <glom/base_db_table_data.h>
 
@@ -360,9 +360,9 @@
   Gtk::TreeView m_TreeView;
   Gtk::TreeModel::ColumnRecord m_ColumnRecord;
 
-  //typedef Gtk::ListStore type_model_store;
-  typedef DbTreeModel type_model_store;
-  Glib::RefPtr<type_model_store> m_refListStore;
+  //Either a db-backed model, or a liststore-derived find-criteria model:
+  TreeModelWithAddRow* m_refListStore; //We use this without a Glib::RefPtr to avoid the complication of ObjectBase as an MI base.
+  Glib::RefPtr<Gtk::TreeModel> m_refListStore_as_model; //To avoid repeated dynamic_casts.
 
   //Columns, not including the hidden internal columns:
   typedef std::vector<DbAddDelColumnInfo> type_ColumnTypes;

Modified: trunk/glom/utility_widgets/db_adddel/glom_db_treemodel.h
==============================================================================
--- trunk/glom/utility_widgets/db_adddel/glom_db_treemodel.h	(original)
+++ trunk/glom/utility_widgets/db_adddel/glom_db_treemodel.h	Mon Jan 12 09:27:34 2009
@@ -21,11 +21,10 @@
 #ifndef GLOM_MODE_DATA_DB_TREEMODEL_H
 #define GLOM_MODE_DATA_DB_TREEMODEL_H
 
-#include <gtkmm/treemodel.h>
+#include <glom/utility_widgets/db_adddel/treemodel_with_addrow.h>
 #include <gtkmm/treepath.h>
 #include <glom/libglom/data_structure/layout/layoutitem_field.h>
 #include <glom/libglom/connectionpool.h>
-#include "../../base_db.h"
 
 namespace Glom
 {
@@ -62,14 +61,12 @@
 
 class DbTreeModel
   : public Glib::Object,
-    public Gtk::TreeModel
+    public Gtk::TreeModel,
+    public TreeModelWithAddRow
 {
 public:
   typedef unsigned int size_type;
 
-  //typedef std::vector<LayoutItem_Field> type_vec_fields;
-  typedef Base_DB::type_vecLayoutFields type_vec_fields;
-
   friend class DbTreeModelRow;
 
 protected:

Added: trunk/glom/utility_widgets/db_adddel/liststore_with_addrow.cc
==============================================================================
--- (empty file)
+++ trunk/glom/utility_widgets/db_adddel/liststore_with_addrow.cc	Mon Jan 12 09:27:34 2009
@@ -0,0 +1,76 @@
+/* Glom
+ *
+ * Copyright (C) 2009 Openismus GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "liststore_with_addrow.h"
+
+
+
+namespace Glom
+{
+
+ListStoreWithAddRow::ListStoreWithAddRow(const Gtk::TreeModelColumnRecord& columns, const type_vec_fields& /* column_fields */)
+: Gtk::ListStore(columns)
+{
+}
+
+Glib::RefPtr<ListStoreWithAddRow> ListStoreWithAddRow::create(const Gtk::TreeModelColumnRecord& columns, const type_vec_fields& column_fields)
+{
+  return Glib::RefPtr<ListStoreWithAddRow>(new ListStoreWithAddRow(columns, column_fields));
+}
+
+void ListStoreWithAddRow::set_is_not_placeholder(const TreeModel::iterator& iter)
+{
+  //If this is the last row then add an extra row so that can be the placeholder instead.
+  if(iter == get_last_row())
+    append();
+}
+
+bool ListStoreWithAddRow::get_is_placeholder(const TreeModel::iterator& iter) const
+{
+  //The last row is always the placeholder row.
+  ListStoreWithAddRow* nonconst = const_cast<ListStoreWithAddRow*>(this); 
+  return iter == nonconst->get_last_row();
+}
+
+
+Gtk::TreeModel::iterator ListStoreWithAddRow::get_last_row()
+{
+ //The last row is always the placeholder row.
+  return Gtk::ListStore::children().end();
+}
+
+Gtk::TreeModel::iterator ListStoreWithAddRow::get_placeholder_row()
+{
+  return get_last_row();
+}
+
+void ListStoreWithAddRow::clear()
+{
+  Gtk::ListStore::clear();
+}
+
+Gtk::TreeModel::iterator ListStoreWithAddRow::erase(const iterator& iter)
+{
+  return Gtk::ListStore::erase(iter);
+}
+
+} //namespace Glom
+
+

Added: trunk/glom/utility_widgets/db_adddel/liststore_with_addrow.h
==============================================================================
--- (empty file)
+++ trunk/glom/utility_widgets/db_adddel/liststore_with_addrow.h	Mon Jan 12 09:27:34 2009
@@ -0,0 +1,65 @@
+/* Glom
+ *
+ * Copyright (C) 2009 Openismus GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GLOM_LISTSTORE_WITH_ADDROW_H
+#define GLOM_LISTSTORE_WITH_ADDROW_H
+
+#include <gtkmm/liststore.h>
+#include <glom/utility_widgets/db_adddel/treemodel_with_addrow.h>
+
+namespace Glom
+{
+
+class ListStoreWithAddRow
+  : public Gtk::ListStore,
+    public TreeModelWithAddRow
+{
+  ListStoreWithAddRow(const Gtk::TreeModelColumnRecord& columns, const type_vec_fields& column_fields);
+
+public:
+  static Glib::RefPtr<ListStoreWithAddRow> create(const Gtk::TreeModelColumnRecord& columns, const type_vec_fields& column_fields);
+
+  virtual void set_is_not_placeholder(const TreeModel::iterator& iter);
+  virtual bool get_is_placeholder(const TreeModel::iterator& iter) const;
+
+  /** Get the last row - usually the placeholder.
+   */
+  virtual TreeModel::iterator get_last_row();
+
+  /** Get the placeholder row.
+   */
+  virtual TreeModel::iterator get_placeholder_row();
+
+
+  virtual void clear();
+
+  /** Removes the given row from the list store.
+   * @param iter The iterator to the row to be removed.
+   * @result An iterator to the next row, or end() if there is none.
+   */
+  virtual iterator erase(const iterator& iter);
+
+protected:
+};
+
+} //namespace Glom
+
+#endif //GLOM_LISTSTORE_WITH_ADDROW_H
+

Added: trunk/glom/utility_widgets/db_adddel/treemodel_with_addrow.cc
==============================================================================

Added: trunk/glom/utility_widgets/db_adddel/treemodel_with_addrow.h
==============================================================================
--- (empty file)
+++ trunk/glom/utility_widgets/db_adddel/treemodel_with_addrow.h	Mon Jan 12 09:27:34 2009
@@ -0,0 +1,64 @@
+/* Glom
+ *
+ * Copyright (C) 2009 Openismus GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GLOM_TREEMODEL_WITH_ADDROW_H
+#define GLOM_TREEMODEL_WITH_ADDROW_H
+
+#include <gtkmm/treemodel.h>
+#include <glom/base_db.h>
+
+namespace Glom
+{
+
+
+class TreeModelWithAddRow
+  // We can't share this base because it would need TreeModel to be a virtual base (derived virtually from its own base): 
+  //: public Gtk::TreeModel
+  // We would need this to use Glib::RefPtr but let's avoid the risk of getting the MI wrong: public virtual Glib::ObjectBase //This is a suitable MI base class because it virtual derives from its own base.
+{
+public:
+  typedef Base_DB::type_vecLayoutFields type_vec_fields;
+
+  virtual void set_is_not_placeholder(const Gtk::TreeModel::iterator& iter) = 0;
+  virtual bool get_is_placeholder(const Gtk::TreeModel::iterator& iter) const = 0;
+
+  /** Get the last row - usually the placeholder.
+   */
+  virtual Gtk::TreeModel::iterator get_last_row() = 0;
+
+  /** Get the placeholder row.
+   */
+  virtual Gtk::TreeModel::iterator get_placeholder_row() = 0;
+
+  virtual void clear() = 0;
+
+  /** Removes the given row from the list store.
+   * @param iter The iterator to the row to be removed.
+   * @result An iterator to the next row, or end() if there is none.
+   */
+  virtual Gtk::TreeModel::iterator erase(const Gtk::TreeModel::iterator& iter) = 0;
+
+protected:
+};
+
+} //namespace Glom
+
+#endif //GLOM_TREEMODEL_WITH_ADDROW_H
+

Modified: trunk/regression_tests/Makefile.am
==============================================================================
--- trunk/regression_tests/Makefile.am	(original)
+++ trunk/regression_tests/Makefile.am	Mon Jan 12 09:27:34 2009
@@ -18,3 +18,6 @@
 test_signal_reemit_SOURCES = test_signal_reemit.cc
 test_signal_reemit_LDADD = $(GLOM_LIBS) 
 
+test_treemodel_dynamic_cast_SOURCES = test_treemodel_dynamic_cast.cc
+test_treemodel_dynamic_cast_LDADD = $(GLOM_LIBS) 
+

Added: trunk/regression_tests/test_treemodel_dynamic_cast.cc
==============================================================================
--- (empty file)
+++ trunk/regression_tests/test_treemodel_dynamic_cast.cc	Mon Jan 12 09:27:34 2009
@@ -0,0 +1,14 @@
+#include <glom/utility_widgets/db_adddel/liststore_with_addrow.h>
+#include <gtkmm.h>
+
+int main(int argc, char* argv[])
+{
+  Gtk::Main kit(argc, argv);
+
+  Gtk::TreeModelColumnRecord columns;
+  Glom::ListStoreWithAddRow::type_vec_fields column_fields;
+  Glib::RefPtr<Glom::ListStoreWithAddRow> model = Glom::ListStoreWithAddRow::create(columns, column_fields);
+
+  Glib::RefPtr<Gtk::TreeModel> treemodel = Glib::RefPtr<Gtk::TreeModel>::cast_dynamic(model);
+  std::cout << "treemodel=" << treemodel << std::endl;
+}



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