Re: custom TreeModel



well, I was trying to come up with a good demo, because I have always felt that people will like to fill a treeview directly from their own data

it has been a while since I have worked woth gtkmm, so I adapted the following from a working program against gtk-2:

the Gtk::Window* do_treeview_memory() locks into the existing demos code (gtkmm-3.22.3/demos/gtk-demo)

the allocation of the treemodel seems to fail, and I only get an empty window

(gtkmm-demo:6194): GLib-GObject-WARNING **: attempting to add an interface (GtkTreeModel) to class (gtkmm__CustomObject_16Memory_TreeModel) after class_init
(gtkmm-demo:6194): Gtk-CRITICAL **: gtk_tree_view_set_model: assertion 'model == NULL || GTK_IS_TREE_MODEL (model)' failed

(and when I will get past that: I obviously haven't tested the callback routines yet...)

regards, Danny.
-------------------------

/* Tree View/Tree Store
 *
 * The GtkTreeStore is used to store data in tree form, to be
 * used later on by a GtkTreeView to display it. This demo builds
 * a simple list of nodes in memory and displays it in the GtkTreeStore. 
 *
 */

#include <gtkmm.h>

#define MEMORY_TREEMODEL_COL_INT        0
#define MEMORY_TREEMODEL_COL_STRING     1

class Memory_Item
{
public:
Memory_Item();

int row_index;

int mi_1;
std::string mi_2;

int mi_A1;
std::string mi_A2;

int mi_B1;
std::string mi_B2;
};

Memory_Item::Memory_Item()
{
row_index = mi_1 = mi_A1 = mi_B1 = 0;
mi_2 = mi_A2 = mi_B2 = "";
}


class Memory
{
public:
Memory();

Memory_Item* Get_Nth_Row(int nth_row);

std::vector <Memory_Item>      v_mi;
};

Memory::Memory()
{
v_mi.clear();
}

Memory_Item*
Memory::Get_Nth_Row(int nth_row)
{
return &(v_mi[nth_row]);
};

class Memory_Columns: public Gtk::TreeModel::ColumnRecord
{
public:

Memory_Columns();

    virtual ~Memory_Columns();

    int Get_Columns_Count() const;

    Gtk::TreeModelColumn<int> col_i;

    Gtk::TreeModelColumn<Glib::ustring> col_s;

private:

    int n_columns;
};

Memory_Columns::Memory_Columns()
{
  n_columns = 0;

  add(col_i); n_columns++;
  add(col_s); n_columns++;
}

Memory_Columns::~Memory_Columns()
{
}

int
Memory_Columns::Get_Columns_Count() const
{
  return n_columns;
}

class  Memory_TreeModel
  : public Glib::Object,
    public Gtk::TreeModel
{
public:

Memory_TreeModel();
  virtual ~Memory_TreeModel();

  static    Glib::RefPtr<Memory_TreeModel> create();

  void      Set_Memory(Memory *m);

  Memory                     *memory;

protected:

   // Overrides:
   virtual Gtk::TreeModelFlags get_flags_vfunc() const;
   virtual int get_n_columns_vfunc() const;
   virtual GType get_column_type_vfunc(int index) const;
   virtual void get_value_vfunc(const TreeModel::iterator& iter, int column, Glib::ValueBase& value) const;

   bool iter_next_vfunc(const iterator& iter, iterator& iter_next) const;

   virtual bool iter_children_vfunc(const iterator& parent, iterator& iter) const;
   virtual bool iter_has_child_vfunc(const iterator& iter) const;
   virtual int iter_n_children_vfunc(const iterator& iter) const;
   virtual int iter_n_root_children_vfunc() const;
   virtual bool iter_nth_child_vfunc(const iterator& parent, int n, iterator& iter) const;
   virtual bool iter_nth_root_child_vfunc(int n, iterator& iter) const;
   virtual bool iter_parent_vfunc(const iterator& child, iterator& iter) const;
   virtual Path get_path_vfunc(const iterator& iter) const;
   virtual bool get_iter_vfunc(const Path& path, iterator& iter) const;

private:

   typedef Gtk::TreeModelColumn<Glib::ustring>  StringColumn;
   typedef Gtk::TreeModelColumn<int>            IntColumn;

   mutable IntColumn::ValueType                 ic;
   mutable StringColumn::ValueType              sc;

   mutable StringColumn                         s_c;
   mutable IntColumn                            i_c;

   mutable int                                  result_int;
   mutable std::string                          result_string;

   Memory_Columns               m_columns;
};

Memory_TreeModel::Memory_TreeModel()
: Glib::ObjectBase( typeid(Memory_TreeModel) ),
  Glib::Object()
{
 Gtk::TreeModel::add_interface( Glib::Object::get_type() );

 memory = 0;

 sc.init( StringColumn::ValueType::value_type() );
 ic.init( IntColumn::ValueType::value_type() );
}

Memory_TreeModel::~Memory_TreeModel()
{

}

Glib::RefPtr<Memory_TreeModel>
Memory_TreeModel::create()
{
  return
  Glib::RefPtr<Memory_TreeModel> (new Memory_TreeModel );
}

Gtk::TreeModelFlags
Memory_TreeModel::get_flags_vfunc() const
{
   return Gtk::TreeModelFlags(0);
}

int
Memory_TreeModel::get_n_columns_vfunc() const
{
   return m_columns.Get_Columns_Count();
}

void
Memory_TreeModel::get_value_vfunc(const TreeModel::iterator& iter, int column, Glib::ValueBase& value) const
{
  Memory_Item *mi;

  //////////////////////////////////////////////////////////

  mi = (Memory_Item *) iter.gobj()->user_data;

  if (mi == 0) { return; }

  switch (column)
  {
  case MEMORY_TREEMODEL_COL_INT:
    {
     result_int = mi->mi_1;

     ic.set(result_int);
     value.init( Glib::Value< int >::value_type() );
     value = ic;
     break;
    }

  case MEMORY_TREEMODEL_COL_STRING:
    {
     result_string = mi->mi_2;

     sc.set(result_string);
     value.init( Glib::Value< std::string >::value_type() );
     value = sc;

     break;
    }
  }
}

bool
Memory_TreeModel::iter_next_vfunc(const iterator& iter, iterator& iter_next) const
{
  Memory_Item *mi;

  int                   new_offset;

  //////////////////////////////////////////////////////////

  //cout << "iter_next_vfunc" << "\n";

  if
  ((void*) iter.gobj()->user_data == 0)
  { iter_next = iterator(); return false; }  //There is no next row.

  mi = (Memory_Item *) iter.gobj()->user_data;

  new_offset = mi->row_index + 1;

  if (new_offset >=  memory->v_mi.size())
  { iter_next = iterator(); return false; }  //There is no next row.

  mi = memory->Get_Nth_Row(new_offset);

  iter_next.gobj()->user_data = (void*) &mi;

  return true;
}

bool
Memory_TreeModel::iter_children_vfunc(const iterator& parent, iterator& iter) const
{
  return iter_nth_child_vfunc(parent, 0, iter);
}

bool
Memory_TreeModel::iter_has_child_vfunc(const iterator& iter) const
{
  return (iter_n_children_vfunc(iter) > 0);
}

int
Memory_TreeModel::iter_n_children_vfunc(const iterator& iter) const
{
  return 0; //There are no children
}

int
Memory_TreeModel::iter_n_root_children_vfunc() const
{
  return
  memory->v_mi.size();  // number of rows
}

bool
Memory_TreeModel::iter_nth_child_vfunc(const iterator& parent, int /* n */, iterator& iter) const
{
  iter = iterator();
  return false; //There are no children.
}

bool
Memory_TreeModel::iter_nth_root_child_vfunc(int n, iterator& iter) const
{
  Memory_Item *mi;

  //////////////////////////////////////////////////////////

  if (!mi) {return false; }

  if (n < memory->v_mi.size())
  {
   mi = memory->Get_Nth_Row(n);

   iter.gobj()->user_data = (void*) mi;

   return true;    // n <= available rows
  }

  return false;     // n > available rows
}

bool
Memory_TreeModel::iter_parent_vfunc(const iterator& child, iterator& iter) const
{
  iter = iterator();
  return false; //There are no children, so no parents.
}

bool
Memory_TreeModel::get_iter_vfunc(const Path& path, iterator& iter) const
{
   unsigned               ps;     // path_size
   int                    ri;     // row_index

   Memory_Item *mi;

   /////////////////////////////////////////////

   if (!memory) {return false; }

   ps = path.size();
   if (   (!ps)
       || (ps > 1))                //There are no children.
   { iter = iterator(); return false; }

   iter = iterator(); //clear the input parameter.
   //iter.set_stamp(m_stamp);

   ri = path[0];

   if (ri >= memory->v_mi.size())
   { iter = iterator(); return false; }

   mi = memory->Get_Nth_Row(ri);

   iter.gobj()->user_data = (void*) mi;

   return true;
}

Gtk::TreeModel::Path
Memory_TreeModel::get_path_vfunc(const iterator& /* iter */) const
{
   //TODO:
   return Path();
}

GType
Memory_TreeModel::get_column_type_vfunc(int index) const
{
  switch (index)
  {
  case MEMORY_TREEMODEL_COL_INT:
    {
     return i_c.type();
     break;
    }
  case MEMORY_TREEMODEL_COL_STRING:
    {
     return s_c.type();
     break;
    }
  default:
    {
     return 0;
     break;
    }
  }
}

class Example_TreeView_Memory : public Gtk::Window
{
public:
  Example_TreeView_Memory();
  ~Example_TreeView_Memory() override;

protected:
  //vfunc overrides:
  void on_realize() override;

  void fill_memory();

  //Member widgets:
  Gtk::Box m_VBox;
  Gtk::ScrolledWindow m_ScrolledWindow;
  Gtk::Label m_Label;

  Memory_Columns   memcol;
  Glib::RefPtr<Memory_TreeModel> treemodel;
  Gtk::TreeView             treeview;

  Memory mem_ory;
};


//Called by DemoWindow;
Gtk::Window* do_treeview_memory()
{
  return new Example_TreeView_Memory();
}


Example_TreeView_Memory::Example_TreeView_Memory()
: m_VBox(Gtk::ORIENTATION_VERTICAL, 8),
  m_Label("Analysis Sheet")
{
  set_title("Memory analysis");
  set_border_width(8);
  set_default_size(650, 400);

  add(m_VBox);
  m_VBox.pack_start(m_Label, Gtk::PACK_SHRINK);

  m_ScrolledWindow.set_shadow_type(Gtk::SHADOW_ETCHED_IN);
  m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
  m_VBox.pack_start(m_ScrolledWindow);

  /* fill memory */
  fill_memory();

  /* create model */
  treemodel = Memory_TreeModel::create();
  treemodel->memory = &mem_ory;

  /* treeview */
  treeview.append_column("Integer", memcol.col_i);
  treeview.append_column("String", memcol.col_s);
  treeview.set_model(treemodel);

  Glib::RefPtr<Gtk::TreeSelection> refTreeSelection = treeview.get_selection();
  refTreeSelection->set_mode(Gtk::SELECTION_MULTIPLE);

  m_ScrolledWindow.add(treeview);

  show_all();
}

Example_TreeView_Memory::~Example_TreeView_Memory()
{
}

void Example_TreeView_Memory::fill_memory()
{
Memory_Item mi;

mi.row_index = 1;
mi.mi_1 = 1; mi.mi_2 = "item 1"; mi.mi_A1 = 11; mi.mi_A2 = "item A11"; mi.mi_B1 = 111; mi.mi_B2 = "item B111";
mem_ory.v_mi.push_back(mi);

mi.row_index = 2;
mi.mi_1 = 2; mi.mi_2 = "item 2"; mi.mi_A1 = 22; mi.mi_A2 = "item A22"; mi.mi_B1 = 222; mi.mi_B2 = "item B222";
mem_ory.v_mi.push_back(mi);

mi.row_index = 3;
mi.mi_1 = 3; mi.mi_2 = "item 3"; mi.mi_A1 = 33; mi.mi_A2 = "item A33"; mi.mi_B1 = 333; mi.mi_B2 = "item B333";
mem_ory.v_mi.push_back(mi);

mi.row_index = 4;
mi.mi_1 = 4; mi.mi_2 = "item 4"; mi.mi_A1 = 44; mi.mi_A2 = "item A44"; mi.mi_B1 = 444; mi.mi_B2 = "item B444";
mem_ory.v_mi.push_back(mi);
}


void Example_TreeView_Memory::on_realize()
{
  treeview.expand_all();

  //call base class:
  Window::on_realize();
}

-------------------------
demos.h

#ifndef _DEMOS_H
#define _DEMOS_H

#include "demowindow.h"

typedef sigc::slot<Gtk::Window*> type_slotDo;

struct Demo
{
  const char* title;
  const char* filename;
  type_slotDo slot; //The method to call.
  Demo* children;
};


Gtk::Window* do_appwindow();
Gtk::Window* do_builder();
Gtk::Window* do_buttonbox();
Gtk::Window* do_change_display();
Gtk::Window* do_colorsel();
Gtk::Window* do_dialog();
Gtk::Window* do_drawingarea();
Gtk::Window* do_flowbox();
Gtk::Window* do_gestures();
Gtk::Window* do_glarea();
Gtk::Window* do_headerbar();
Gtk::Window* do_iconbrowser();
Gtk::Window* do_iconview();
Gtk::Window* do_images();
Gtk::Window* do_menus();
Gtk::Window* do_overlay();
Gtk::Window* do_panes();
Gtk::Window* do_pixbufs();
Gtk::Window* do_shortcuts();
Gtk::Window* do_sizegroup();
Gtk::Window* do_stack();
Gtk::Window* do_stacksidebar();
Gtk::Window* do_textview();

Gtk::Window* do_treeview_editable_cells();
Gtk::Window* do_treeview_liststore();
Gtk::Window* do_treeview_treestore();
Gtk::Window* do_treeview_memory();

Demo child0[] =
{
  { "Editable Cells", "example_treeview_editable_cells.cc", sigc::ptr_fun(&do_treeview_editable_cells), nullptr },
  { "List Store", "example_treeview_liststore.cc", sigc::ptr_fun(&do_treeview_liststore), nullptr },
  { "Tree Store", "example_treeview_treestore.cc", sigc::ptr_fun(&do_treeview_treestore), nullptr },
  { "Memory Tree Store", "example_treeview_memory.cc", sigc::ptr_fun(&do_treeview_memory), nullptr },
  { nullptr, nullptr, type_slotDo(), nullptr }
};

Demo testgtk_demos[] =
{
  { "Application main window", "example_appwindow.cc", sigc::ptr_fun(&do_appwindow), nullptr },
  { "Builder", "example_builder.cc", sigc::ptr_fun(&do_builder), nullptr },
  { "Button Boxes", "example_buttonbox.cc",  sigc::ptr_fun(&do_buttonbox), nullptr },
  { "Change Display", "example_change_display.cc", sigc::ptr_fun(&do_change_display), nullptr },
  { "Color Selector", "example_colorsel.cc", sigc::ptr_fun(&do_colorsel), nullptr },
  { "Dialog and Message Boxes", "example_dialog.cc", sigc::ptr_fun(&do_dialog), nullptr },
  { "Drawing Area", "example_drawingarea.cc", sigc::ptr_fun(&do_drawingarea), nullptr },
  { "Flow Box", "example_flowbox.cc",  sigc::ptr_fun(&do_flowbox), nullptr },
  { "Gestures", "example_gestures.cc",  sigc::ptr_fun(&do_gestures), nullptr },
  { "Header Bar", "example_headerbar.cc",  sigc::ptr_fun(&do_headerbar), nullptr },
  { "Icon Browser", "example_iconbrowser.cc", sigc::ptr_fun(&do_iconbrowser), nullptr },
  { "Icon View", "example_iconview.cc", sigc::ptr_fun(&do_iconview), nullptr },
  { "Images", "example_images.cc", sigc::ptr_fun(&do_images), nullptr },
  { "Menus", "example_menus.cc", sigc::ptr_fun(&do_menus), nullptr },
  { "OpenGL Area", "example_glarea.cc", sigc::ptr_fun(&do_glarea), nullptr },
  { "Overlay", "example_overlay.cc", sigc::ptr_fun(&do_overlay), nullptr },
  { "Paned Widgets", "example_panes.cc", sigc::ptr_fun(&do_panes), nullptr },
  { "Pixbufs", "example_pixbufs.cc", sigc::ptr_fun(&do_pixbufs), nullptr },
  { "Shortcuts Window", "example_shortcuts.cc", sigc::ptr_fun(&do_shortcuts), nullptr },
  { "Size Groups", "example_sizegroup.cc", sigc::ptr_fun(&do_sizegroup), nullptr },
  { "Stack", "example_stack.cc", sigc::ptr_fun(&do_stack), nullptr },
  { "Stack Sidebar", "example_stacksidebar.cc", sigc::ptr_fun(&do_stacksidebar), nullptr },
  { "Text Widget", "example_textview.cc", sigc::ptr_fun(&do_textview), nullptr },
  { "Tree View", "", type_slotDo(), child0 },
  { nullptr, nullptr, type_slotDo(), nullptr }
};

#endif //_DEMOS_H
please show the rest of the class declaration, including what/how it inherits, and how you instantiate it.
-------------------------


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