Re: custom TreeModel
danny via gtkmm-list <[email protected]>
| Newsgroups | gmane.comp.gnome.gtkmm |
|---|---|
| Message-ID | <[email protected]> |
hi
well, actually, I did not find the example you are referring to. I
probably did when I was working with the original gtk2 program, though.
so I have come up with this:(gtkmm-3.22.3/demos)
--------------------------------------------------------------/* 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>
//debug#include <iostream>
#define MEMORY_TREEMODEL_COL_INT 0#define
MEMORY_TREEMODEL_COL_STRING 1
class Memory_Item{// one Memory Item will represent one chunk of
information to// be shown in the Treeview, i.e. one row with
subnodespublic: Memory_Item();
// data for top level nodes int m
i_1; std::string mi_2;
// for first level of sub nodes int
mi_A1; std::string mi_A2;
// for second level of sub nodes int
mi_B1; std::string mi_B2;};
Memory_Item::Memory_Item(){ mi_1 = mi_A1 = mi_B1 = 0; mi_
2 = mi_A2 = mi_B2 = "";}
class Memory{public: Memory();
// these we will show in the treeview std::vector
<Memory_Item> v_mi;};
Memory::Memory(){ v_mi.clear();}
class Memory_Columns: public Gtk::TreeModel::ColumnRecord{public:
Memory_Columns();
virtual ~Memory_Columns();
int Get_Columns_Count() const;
// a column for the ints Gtk::TreeModelColumn<int> col_i;
// and a column for the
strings 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(){}
intMemory_Columns::Get_Columns_Count() const{ return n_columns;}
class Memory_TreeModel : public Gtk::TreeModel , public
Glib::Object{public:
Memory_TreeModel(); virtual ~Memory_TreeModel();
static Glib::RefPtr<Memory_TreeModel> create();
void Set_Memory(Memory *m);
// the gate for the model to the information to be shown 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::TreeModelFlagsMemory_TreeModel::get_flags_vfunc() const{ return
Gtk::TreeModelFlags(0);}
intMemory_TreeModel::get_n_columns_vfunc() const{ return
m_columns.Get_Columns_Count();}
voidMemory_TreeModel::get_value_vfunc(const TreeModel::iterator& iter,
int column, Glib::ValueBase& value) const{ // what information
does one row contain? Memory_Item mi;
unsigned long l; unsigned long p; //
path //////////////////////////////////////////////////////////
// user_data contains the row number l = (unsigned long)
iter.gobj()->user_data;
if (l >= memory->v_mi.size()) { return; }
// user_data2 contains the depth of the node p = (unsigned long)
iter.gobj()->user_data2;
mi = memory->v_mi.at(l);
switch (column) { case MEMORY_TREEMODEL_COL_INT: { if (p <=
1) // top level node
{result_int = mi.mi_1;}
else if (p == 2) // first sub node level
{result_int = mi.mi_A1;}
else // second sub node level
{result_int = mi.mi_B1;}
ic.set(result_int); value.init( Glib::Value< int
>::value_type() ); value = ic; break; }
case MEMORY_TREEMODEL_COL_STRING: { // same
partitioning as for the ints if (p <= 1) {result_st
ring = mi.mi_2;} else if (p == 2) {result_string =
mi.mi_A2;} else {result_string =
mi.mi_B2;}
sc.set(result_string); value.init( Glib::Value< std::string
>::value_type() ); value = sc;
break; } }}
boolMemory_TreeModel::iter_next_vfunc(const iterator& iter, iterator&
iter_next) const{ // what is the next node from this one?
unsigned long l, p;
//////////////////////////////////////////////////////////
l = (unsigned long) iter.gobj()->user_data; p = (unsigned long)
iter.gobj()->user_data2;
if ( (l + 1 >= memory->v_mi.size()) // beyond the
last row || (p > 1))
// the sublevels have just one child, no next node
{ iter_next = iterator(); return false; } //There is no next row.
l++;
// next row
// set markers for next node iter_next.gobj()->user_data = (void *)
l; iter_next.gobj()->user_data2 = (void *) p;
return true;}
boolMemory_TreeModel::iter_children_vfunc(const iterator& parent,
iterator& iter) const{ // get the first child of this parent
node return iter_nth_child_vfunc(parent, 0, iter);}
boolMemory_TreeModel::iter_has_child_vfunc(const iterator& iter)
const{ return (iter_n_children_vfunc(iter) > 0);}
intMemory_TreeModel::iter_n_children_vfunc(const iterator& iter)
const{ unsigned long l;
int n;
////////////////////////////////////////
l = (unsigned long) iter.gobj()->user_data2;
if (l == 0) // uninitiated node { n = 0;}
else if (l <= 2) // only two sublevels of nodes { n =
1;}
else { n = 0;} // no nodes
return n;}
intMemory_TreeModel::iter_n_root_children_vfunc() const{ return
memory->v_mi.size(); // number of rows}
boolMemory_TreeModel::iter_nth_child_vfunc(const iterator& parent,
int n , iterator& iter) const{ // get the nth child of this
parent node unsigned long l, p;
////////////////////////////////////////
p = (unsigned long) parent.gobj()->user_data; l = (unsigned long)
parent.gobj()->user_data2;
if ( (l > 2) // only two sublevels of nodes
|| (n > 0)) // and one child node only { iter =
iterator(); return false; //There are no children. }
iter.gobj()->user_data = (void*) p; // row
index iter.gobj()->user_data2 = (void*) (l + 1); // sublevel
return true;}
boolMemory_TreeModel::iter_nth_root_child_vfunc(int n, iterator& iter)
const{ // get the nth row unsigned long l;
///////////////////////////////////////
l = n;
if (l >= memory->v_mi.size()) {return false; }
iter.gobj()->user_data = (void*) l; // row index
iter.gobj()->user_data2 = (void*) 1; // top level node
return true; // n <= available rows}
boolMemory_TreeModel::iter_parent_vfunc(const iterator& child,
iterator& iter) const{ // set a parent for this child unsigned
long l, p;
////////////////////////////////////////
l = (unsigned long) child.gobj()->user_data2; p = (unsigned long)
child.gobj()->user_data;
if (l <= 1) // top level { iter =
iterator();
return false; //There are no children. }
iter.gobj()->user_data = (void*) p; // row
index iter.gobj()->user_data2 = (void*) (l - 1); // one level
up
return true;}
boolMemory_TreeModel::get_iter_vfunc(const Path& path, iterator& iter)
const{ // define a node
unsigned long ps; // path_size unsigned long
ri; // row_index
/////////////////////////////////////////////
ps = path.size(); if ( (!ps) || (ps > 3))
// only two levels of subnodes
{ iter = iterator(); return false; }
iter = iterator(); //clear the input parameter.
ri = path[0];
if (ri >= memory->v_mi.size()) { iter = iterator(); return false;
}
iter.gobj()->user_data = (void*) ri; // row
index iter.gobj()->user_data2 = (void*) ps; //
sublevel iter.gobj()->user_data3 = (void*) -1; // just to show
its presence, really
return true;}
Gtk::TreeModel::PathMemory_TreeModel::get_path_vfunc(const iterator& /*
iter */) const{ //TODO: return Path();}
GTypeMemory_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.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.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.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.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();}---------------------------
-----------------------------------
adapt demo.h
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 }};
--------------------------------------------------------------
I'm not sure, though, if I really understand the purpose of virtual
bool Gtk::TreeModel::iter_parent_vfunc
(
this function finds a parent for the given child, right? but why would
that be needed, if a child can only be arrived at from a parent node in
the first place?
regards, Danny.
--------------------------------------------------------------
-----Original Message-----
Date: Sat, 14 Dec 2019 11:23:37 +0100Subject: Re: custom TreeModelCc: g
[email protected]: danny <[email protected]>From: Kjell
Ahlstedt <[email protected]>
Your custom TreeModel can perhaps be added either to the gtkmm
demo programs or to the gtkmm tutorial at
https://gitlab.gnome.org/GNOME/gtkmm-documentation. Let's decide
when you have a working program.
Have you noticed that there is a custom TreeModel example at
https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/gtkmm-3-24/exam
ples/others/treemodelcustom
? I don't know if it's a good example. Most programs under the
examples/others directory are not maintained.
Kjell
On 2019-12-12 09:37, danny via
gtkmm-list wrote:
>
>
>
> indeed! that seems to get me on my way! thanks!
>
>
>
> if/when I get this working: would you be interested in adding
> this to the gtkmm demo programs?
>
>
>
> regards, D.
>
>
>
>
>
>
>
_______________________________________________
gtkmm-list mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/gtkmm-list