This example has a Gtk::TreeView widget, with a Gtk::ListStore model.
File: examplewindow.h
#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H
#include <gtkmm.h>
class ExampleWindow : public Gtk::Window
{
public:
ExampleWindow();
virtual ~ExampleWindow();
protected:
//Signal handlers:
virtual void on_button_quit();
//Tree model columns:
class ModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
ModelColumns()
{ add(m_col_id); add(m_col_name); }
Gtk::TreeModelColumn<unsigned int> m_col_id;
Gtk::TreeModelColumn<Glib::ustring> m_col_name;
};
ModelColumns m_Columns;
//Child widgets:
Gtk::VBox m_VBox;
Gtk::ScrolledWindow m_ScrolledWindow;
Gtk::TreeView m_TreeView;
Glib::RefPtr<Gtk::ListStore> m_refTreeModel;
Gtk::HButtonBox m_ButtonBox;
Gtk::Button m_Button_Quit;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc
#include <gtkmm/main.h>
#include "examplewindow.h"
int main(int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
ExampleWindow window;
Gtk::Main::run(window); //Shows the window and returns when it is closed.
return 0;
}
File: examplewindow.cc
#include <iostream>
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
: m_Button_Quit("Quit")
{
set_title("Gtk::TreeView (ListStore) example");
set_border_width(5);
set_default_size(400, 200);
add(m_VBox);
//Add the TreeView, inside a ScrolledWindow, with the button underneath:
m_ScrolledWindow.add(m_TreeView);
//Only show the scrollbars when they are necessary:
m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
m_VBox.pack_start(m_ScrolledWindow);
m_VBox.pack_start(m_ButtonBox, Gtk::PACK_SHRINK);
m_ButtonBox.pack_start(m_Button_Quit, Gtk::PACK_SHRINK);
m_ButtonBox.set_border_width(5);
m_ButtonBox.set_layout(Gtk::BUTTONBOX_END);
m_Button_Quit.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_button_quit) );
//Create the Tree model:
m_refTreeModel = Gtk::ListStore::create(m_Columns);
m_TreeView.set_model(m_refTreeModel);
//Fill the TreeView's model
Gtk::TreeModel::Row row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 1;
row[m_Columns.m_col_name] = "Billy Bob";
row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 2;
row[m_Columns.m_col_name] = "Joey Jojo";
row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 3;
row[m_Columns.m_col_name] = "Rob McRoberts";
//Add the TreeView's view columns:
m_TreeView.append_column("ID", m_Columns.m_col_id);
m_TreeView.append_column("Name", m_Columns.m_col_name);
//Make all the columns reorderable:
//This is not necessary, but it's nice to show the feature.
//You can use TreeView::set_column_drag_function() to more
//finely control column drag and drop.
for(guint i = 0; i < 2; i++)
{
Gtk::TreeView::Column* pColumn = m_TreeView.get_column(i);
pColumn->set_reorderable();
}
show_all_children();
}
ExampleWindow::~ExampleWindow()
{
}
void ExampleWindow::on_button_quit()
{
hide();
}
This example is very similar to the ListStore example, but uses a Gtk::TreeStore model instead, and adds children to the rows.
File: examplewindow.h
#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H
#include <gtkmm.h>
class ExampleWindow : public Gtk::Window
{
public:
ExampleWindow();
virtual ~ExampleWindow();
protected:
//Signal handlers:
virtual void on_button_quit();
virtual void on_treeview_row_activated(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
//Tree model columns:
class ModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
ModelColumns()
{ add(m_col_id); add(m_col_name); }
Gtk::TreeModelColumn<int> m_col_id;
Gtk::TreeModelColumn<Glib::ustring> m_col_name;
};
ModelColumns m_Columns;
//Child widgets:
Gtk::VBox m_VBox;
Gtk::ScrolledWindow m_ScrolledWindow;
Gtk::TreeView m_TreeView;
Glib::RefPtr<Gtk::TreeStore> m_refTreeModel;
Gtk::HButtonBox m_ButtonBox;
Gtk::Button m_Button_Quit;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc
#include <gtkmm/main.h>
#include "examplewindow.h"
int main(int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
ExampleWindow window;
Gtk::Main::run(window); //Shows the window and returns when it is closed.
return 0;
}
File: examplewindow.cc
#include <iostream>
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
: m_Button_Quit("Quit")
{
set_title("Gtk::TreeView (TreeStore) example");
set_border_width(5);
set_default_size(400, 200);
add(m_VBox);
//Add the TreeView, inside a ScrolledWindow, with the button underneath:
m_ScrolledWindow.add(m_TreeView);
//Only show the scrollbars when they are necessary:
m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
m_VBox.pack_start(m_ScrolledWindow);
m_VBox.pack_start(m_ButtonBox, Gtk::PACK_SHRINK);
m_ButtonBox.pack_start(m_Button_Quit, Gtk::PACK_SHRINK);
m_ButtonBox.set_border_width(5);
m_ButtonBox.set_layout(Gtk::BUTTONBOX_END);
m_Button_Quit.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_button_quit) );
//Create the Tree model:
m_refTreeModel = Gtk::TreeStore::create(m_Columns);
m_TreeView.set_model(m_refTreeModel);
//All the items to be reordered with drag-and-drop:
m_TreeView.set_reorderable();
//Fill the TreeView's model
Gtk::TreeModel::Row row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 1;
row[m_Columns.m_col_name] = "Billy Bob";
Gtk::TreeModel::Row childrow = *(m_refTreeModel->append(row.children()));
childrow[m_Columns.m_col_id] = 11;
childrow[m_Columns.m_col_name] = "Billy Bob Junior";
childrow = *(m_refTreeModel->append(row.children()));
childrow[m_Columns.m_col_id] = 12;
childrow[m_Columns.m_col_name] = "Sue Bob";
row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 2;
row[m_Columns.m_col_name] = "Joey Jojo";
row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 3;
row[m_Columns.m_col_name] = "Rob McRoberts";
childrow = *(m_refTreeModel->append(row.children()));
childrow[m_Columns.m_col_id] = 31;
childrow[m_Columns.m_col_name] = "Xavier McRoberts";
//Add the TreeView's view columns:
m_TreeView.append_column("ID", m_Columns.m_col_id);
m_TreeView.append_column("Name", m_Columns.m_col_name);
//Connect signal:
m_TreeView.signal_row_activated().connect( sigc::mem_fun(*this, &ExampleWindow::on_treeview_row_activated) );
show_all_children();
}
ExampleWindow::~ExampleWindow()
{
}
void ExampleWindow::on_button_quit()
{
hide();
}
void ExampleWindow::on_treeview_row_activated(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* /* column */)
{
Gtk::TreeModel::iterator iter = m_refTreeModel->get_iter(path);
if(iter)
{
Gtk::TreeModel::Row row = *iter;
std::cout << "Row activated: ID=" << row[m_Columns.m_col_id] << ", Name=" << row[m_Columns.m_col_name] << std::endl;
}
}
This example is identical to the ListStore example, but it uses TreeView::append_column_editable() instead of TreeView::append_column().
File: examplewindow.h
#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H
#include <gtkmm.h>
class ExampleWindow : public Gtk::Window
{
public:
ExampleWindow();
virtual ~ExampleWindow();
protected:
//Signal handlers:
virtual void on_button_quit();
//Tree model columns:
class ModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
ModelColumns()
{ add(m_col_id); add(m_col_name); add(m_col_foo); }
Gtk::TreeModelColumn<unsigned int> m_col_id;
Gtk::TreeModelColumn<Glib::ustring> m_col_name;
Gtk::TreeModelColumn<bool> m_col_foo;
};
ModelColumns m_Columns;
//Child widgets:
Gtk::VBox m_VBox;
Gtk::ScrolledWindow m_ScrolledWindow;
Gtk::TreeView m_TreeView;
Glib::RefPtr<Gtk::ListStore> m_refTreeModel;
Gtk::HButtonBox m_ButtonBox;
Gtk::Button m_Button_Quit;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc
#include <gtkmm/main.h>
#include "examplewindow.h"
int main(int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
ExampleWindow window;
Gtk::Main::run(window); //Shows the window and returns when it is closed.
return 0;
}
File: examplewindow.cc
#include <iostream>
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
: m_Button_Quit("Quit")
{
set_title("Gtk::TreeView Editable Cells example");
set_border_width(5);
set_default_size(400, 200);
add(m_VBox);
//Add the TreeView, inside a ScrolledWindow, with the button underneath:
m_ScrolledWindow.add(m_TreeView);
//Only show the scrollbars when they are necessary:
m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
m_VBox.pack_start(m_ScrolledWindow);
m_VBox.pack_start(m_ButtonBox, Gtk::PACK_SHRINK);
m_ButtonBox.pack_start(m_Button_Quit, Gtk::PACK_SHRINK);
m_ButtonBox.set_border_width(5);
m_ButtonBox.set_layout(Gtk::BUTTONBOX_END);
m_Button_Quit.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_button_quit) );
//Create the Tree model:
m_refTreeModel = Gtk::ListStore::create(m_Columns);
m_TreeView.set_model(m_refTreeModel);
//Fill the TreeView's model
Gtk::TreeModel::Row row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 1;
row[m_Columns.m_col_name] = "Billy Bob";
row[m_Columns.m_col_foo] = true;
row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 2;
row[m_Columns.m_col_name] = "Joey Jojo";
row[m_Columns.m_col_foo] = true;
row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 3;
row[m_Columns.m_col_name] = "Rob McRoberts";
row[m_Columns.m_col_foo] = false;
//Add the TreeView's view columns:
m_TreeView.append_column_editable("ID", m_Columns.m_col_id);
m_TreeView.append_column_editable("Name", m_Columns.m_col_name);
m_TreeView.append_column_editable("foo", m_Columns.m_col_foo);
show_all_children();
}
ExampleWindow::~ExampleWindow()
{
}
void ExampleWindow::on_button_quit()
{
hide();
}
This example is much like the TreeStore example, but has 2 extra columns to indicate whether the row can be dragged, and whether it can receive drag-and-dropped rows. It uses a derived Gtk::TreeStore which overrides the virtual functions as described in the TreeView Drag and Drop section..
File: treemodel_dnd.h
#ifndef GTKMM_EXAMPLE_TREEMODEL_DND_H
#define GTKMM_EXAMPLE_TREEMODEL_DND_H
#include <gtkmm.h>
class TreeModel_Dnd : public Gtk::TreeStore
{
protected:
TreeModel_Dnd();
public:
//Tree model columns:
class ModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
ModelColumns()
{ add(m_col_id); add(m_col_name); add(m_col_draggable); add(m_col_receivesdrags); }
Gtk::TreeModelColumn<int> m_col_id;
Gtk::TreeModelColumn<Glib::ustring> m_col_name;
Gtk::TreeModelColumn<bool> m_col_draggable;
Gtk::TreeModelColumn<bool> m_col_receivesdrags;
};
ModelColumns m_Columns;
static Glib::RefPtr<TreeModel_Dnd> create();
protected:
//Overridden virtual functions:
virtual bool row_draggable_vfunc(const Gtk::TreeModel::Path& path) const;
virtual bool row_drop_possible_vfunc(const Gtk::TreeModel::Path& dest, const Gtk::SelectionData& selection_data) const;
};
#endif //GTKMM_EXAMPLE_TREEMODEL_DND_H
File: examplewindow.h
#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H
#include <gtkmm.h>
#include "treemodel_dnd.h"
class ExampleWindow : public Gtk::Window
{
public:
ExampleWindow();
virtual ~ExampleWindow();
protected:
//Signal handlers:
virtual void on_button_quit();
//Child widgets:
Gtk::VBox m_VBox;
Gtk::ScrolledWindow m_ScrolledWindow;
Gtk::TreeView m_TreeView;
Glib::RefPtr<TreeModel_Dnd> m_refTreeModel;
Gtk::HButtonBox m_ButtonBox;
Gtk::Button m_Button_Quit;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc
#include <gtkmm/main.h>
#include "examplewindow.h"
int main(int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
ExampleWindow window;
Gtk::Main::run(window); //Shows the window and returns when it is closed.
return 0;
}
File: treemodel_dnd.cc
#include "treemodel_dnd.h"
#include <iostream>
TreeModel_Dnd::TreeModel_Dnd()
{
//We can't just call Gtk::TreeModel(m_Columns) in the initializer list
//because m_Columns does not exist when the base class constructor runs.
//And we can't have a static m_Columns instance, because that would be
//instantiated before the gtkmm type system.
//So, we use this method, which should only be used just after creation:
set_column_types(m_Columns);
}
Glib::RefPtr<TreeModel_Dnd> TreeModel_Dnd::create()
{
return Glib::RefPtr<TreeModel_Dnd>( new TreeModel_Dnd() );
}
bool TreeModel_Dnd::row_draggable_vfunc(const Gtk::TreeModel::Path& path) const
{
//Make the value of the "draggable" column determine whether this row can be dragged:
TreeModel_Dnd* unconstThis = const_cast<TreeModel_Dnd*>(this); //TODO: Add a const version of get_iter to TreeModel:
const_iterator iter = unconstThis->get_iter(path);
//const_iterator iter = get_iter(path);
if(iter)
{
Row row = *iter;
bool is_draggable = row[m_Columns.m_col_draggable];
return is_draggable;
}
return Gtk::TreeStore::row_draggable_vfunc(path);
}
bool TreeModel_Dnd::row_drop_possible_vfunc(const Gtk::TreeModel::Path& dest, const Gtk::SelectionData& selection_data) const
{
//Make the value of the "receives drags" column determine whether a row can be dragged into it:
//dest is the path that the row would have after it has been dropped:
//But in this case we are more interested in the parent row:
Gtk::TreeModel::Path dest_parent = dest;
bool dest_is_not_top_level = dest_parent.up();
if(!dest_is_not_top_level || dest_parent.empty())
{
//The user wants to move something to the top-level.
//Let's always allow that.
}
else
{
//Get an iterator for the row at this path:
//We must unconst this. This should not be necessary with a future version of gtkmm.
TreeModel_Dnd* unconstThis = const_cast<TreeModel_Dnd*>(this); //TODO: Add a const version of get_iter to TreeModel:
const_iterator iter_dest_parent = unconstThis->get_iter(dest_parent);
//const_iterator iter_dest_parent = get_iter(dest);
if(iter_dest_parent)
{
Row row = *iter_dest_parent;
bool receives_drags = row[m_Columns.m_col_receivesdrags];
return receives_drags;
}
}
//You could also examine the row being dragged (via selection_data)
//if you must look at both rows to see whether a drop should be allowed.
//You could use
//TODO: Add const version of get_from_selection_data(): Glib::RefPtr<const Gtk::TreeModel> refThis = Glib::RefPtr<const Gtk::TreeModel>(this);
//Glib::RefPtr<Gtk::TreeModel> refThis = Glib::RefPtr<Gtk::TreeModel>(const_cast<TreeModel_Dnd*>(this));
//refThis->reference(); //, true /* take_copy */)
//Gtk::TreeModel::Path path_dragged_row;
//Gtk::TreeModel::Path::get_from_selection_data(selection_data, refThis, path_dragged_row);
return Gtk::TreeStore::row_drop_possible_vfunc(dest, selection_data);
}
File: examplewindow.cc
#include <iostream>
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
: m_Button_Quit(Gtk::Stock::QUIT)
{
set_title("Gtk::TreeView (Drag and Drop) example");
set_border_width(5);
set_default_size(400, 200);
add(m_VBox);
//Add the TreeView, inside a ScrolledWindow, with the button underneath:
m_ScrolledWindow.add(m_TreeView);
//Only show the scrollbars when they are necessary:
m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
m_VBox.pack_start(m_ScrolledWindow);
m_VBox.pack_start(m_ButtonBox, Gtk::PACK_SHRINK);
m_ButtonBox.pack_start(m_Button_Quit, Gtk::PACK_SHRINK);
m_ButtonBox.set_border_width(5);
m_ButtonBox.set_layout(Gtk::BUTTONBOX_END);
m_Button_Quit.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_button_quit) );
//Create the Tree model:
//Use our derived model, which overrides some Gtk::TreeDragDest and Gtk::TreeDragSource virtual functions:
m_refTreeModel = TreeModel_Dnd::create(); //The columns are declared in the overridden TreeModel.
m_TreeView.set_model(m_refTreeModel);
//Enable Drag-and-Drop of TreeView rows:
//See also the derived TreeModel's *_vfunc overrides.
m_TreeView.enable_model_drag_source();
m_TreeView.enable_model_drag_dest();
//Fill the TreeView's model
Gtk::TreeModel::Row row = *(m_refTreeModel->append());
row[m_refTreeModel->m_Columns.m_col_id] = 1;
row[m_refTreeModel->m_Columns.m_col_name] = "Billy Bob";
row[m_refTreeModel->m_Columns.m_col_draggable] = true;
row[m_refTreeModel->m_Columns.m_col_receivesdrags] = true;
Gtk::TreeModel::Row childrow = *(m_refTreeModel->append(row.children()));
childrow[m_refTreeModel->m_Columns.m_col_id] = 11;
childrow[m_refTreeModel->m_Columns.m_col_name] = "Billy Bob Junior";
childrow[m_refTreeModel->m_Columns.m_col_draggable] = true;
childrow[m_refTreeModel->m_Columns.m_col_receivesdrags] = true;
childrow = *(m_refTreeModel->append(row.children()));
childrow[m_refTreeModel->m_Columns.m_col_id] = 12;
childrow[m_refTreeModel->m_Columns.m_col_name] = "Sue Bob";
childrow[m_refTreeModel->m_Columns.m_col_draggable] = true;
childrow[m_refTreeModel->m_Columns.m_col_receivesdrags] = true;
row = *(m_refTreeModel->append());
row[m_refTreeModel->m_Columns.m_col_id] = 2;
row[m_refTreeModel->m_Columns.m_col_name] = "Joey Jojo";
row[m_refTreeModel->m_Columns.m_col_draggable] = true;
row[m_refTreeModel->m_Columns.m_col_receivesdrags] = true;
row = *(m_refTreeModel->append());
row[m_refTreeModel->m_Columns.m_col_id] = 3;
row[m_refTreeModel->m_Columns.m_col_name] = "Rob McRoberts";
row[m_refTreeModel->m_Columns.m_col_draggable] = true;
row[m_refTreeModel->m_Columns.m_col_receivesdrags] = true;
childrow = *(m_refTreeModel->append(row.children()));
childrow[m_refTreeModel->m_Columns.m_col_id] = 31;
childrow[m_refTreeModel->m_Columns.m_col_name] = "Xavier McRoberts";
childrow[m_refTreeModel->m_Columns.m_col_draggable] = true;
childrow[m_refTreeModel->m_Columns.m_col_receivesdrags] = true;
//Add the TreeView's view columns:
m_TreeView.append_column("ID", m_refTreeModel->m_Columns.m_col_id);
m_TreeView.append_column("Name", m_refTreeModel->m_Columns.m_col_name);
m_TreeView.append_column_editable("Draggable", m_refTreeModel->m_Columns.m_col_draggable);
m_TreeView.append_column_editable("Receives Drags", m_refTreeModel->m_Columns.m_col_receivesdrags);
show_all_children();
}
ExampleWindow::~ExampleWindow()
{
}
void ExampleWindow::on_button_quit()
{
hide();
}
This example is much like the ListStore example, but derives a custom TreeView in order to override the button_press_event, and also to encapsulate the tree model code in our derived class. See the TreeView Popup Context Menu section.
File: treeview_withpopup.h
#ifndef GTKMM_EXAMPLE_TREEVIEW_WITHPOPUP_H
#define GTKMM_EXAMPLE_TREEVIEW_WITHPOPUP_H
#include <gtkmm.h>
class TreeView_WithPopup : public Gtk::TreeView
{
public:
TreeView_WithPopup();
virtual ~TreeView_WithPopup();
protected:
// Override Signal handler:
// Alternatively, use signal_button_press_event().connect_notify()
virtual bool on_button_press_event(GdkEventButton *ev);
//Signal handler for popup menu items:
virtual void on_menu_file_popup_generic();
//Tree model columns:
class ModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
ModelColumns()
{ add(m_col_id); add(m_col_name); }
Gtk::TreeModelColumn<unsigned int> m_col_id;
Gtk::TreeModelColumn<Glib::ustring> m_col_name;
};
ModelColumns m_Columns;
//The Tree model:
Glib::RefPtr<Gtk::ListStore> m_refTreeModel;
Gtk::Menu m_Menu_Popup;
};
#endif //GTKMM_EXAMPLE_TREEVIEW_WITHPOPUP_H
File: examplewindow.h
#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H
#include <gtkmm.h>
#include "treeview_withpopup.h"
class ExampleWindow : public Gtk::Window
{
public:
ExampleWindow();
virtual ~ExampleWindow();
protected:
//Signal handlers:
virtual void on_button_quit();
//Child widgets:
Gtk::VBox m_VBox;
Gtk::ScrolledWindow m_ScrolledWindow;
TreeView_WithPopup m_TreeView;
Gtk::HButtonBox m_ButtonBox;
Gtk::Button m_Button_Quit;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc
#include <gtkmm/main.h>
#include "examplewindow.h"
int main(int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
ExampleWindow window;
Gtk::Main::run(window); //Shows the window and returns when it is closed.
return 0;
}
File: examplewindow.cc
#include <iostream>
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
: m_Button_Quit("Quit")
{
set_title("Gtk::TreeView (ListStore) example");
set_border_width(5);
set_default_size(400, 200);
add(m_VBox);
//Add the TreeView, inside a ScrolledWindow, with the button underneath:
m_ScrolledWindow.add(m_TreeView);
//Only show the scrollbars when they are necessary:
m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
m_VBox.pack_start(m_ScrolledWindow);
m_VBox.pack_start(m_ButtonBox, Gtk::PACK_SHRINK);
m_ButtonBox.pack_start(m_Button_Quit, Gtk::PACK_SHRINK);
m_ButtonBox.set_border_width(5);
m_ButtonBox.set_layout(Gtk::BUTTONBOX_END);
m_Button_Quit.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_button_quit) );
show_all_children();
}
ExampleWindow::~ExampleWindow()
{
}
void ExampleWindow::on_button_quit()
{
hide();
}
File: treeview_withpopup.cc
#include "treeview_withpopup.h"
#include <iostream>
TreeView_WithPopup::TreeView_WithPopup()
{
//Create the Tree model:
m_refTreeModel = Gtk::ListStore::create(m_Columns);
set_model(m_refTreeModel);
//Fill the TreeView's model
Gtk::TreeModel::Row row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 1;
row[m_Columns.m_col_name] = "right-click on this";
row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 2;
row[m_Columns.m_col_name] = "or this";
row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 3;
row[m_Columns.m_col_name] = "or this, for a popup context menu";
//Add the TreeView's view columns:
append_column("ID", m_Columns.m_col_id);
append_column("Name", m_Columns.m_col_name);
//Fill popup menu:
{
Gtk::Menu::MenuList& menulist = m_Menu_Popup.items();
menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Edit",
sigc::mem_fun(*this, &TreeView_WithPopup::on_menu_file_popup_generic) ) );
menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Process",
sigc::mem_fun(*this, &TreeView_WithPopup::on_menu_file_popup_generic) ) );
menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Remove",
sigc::mem_fun(*this, &TreeView_WithPopup::on_menu_file_popup_generic) ) );
}
m_Menu_Popup.accelerate(*this);
}
TreeView_WithPopup::~TreeView_WithPopup()
{
}
bool TreeView_WithPopup::on_button_press_event(GdkEventButton* event)
{
//Call base class, to allow normal handling,
//such as allowing the row to be selected by the right-click:
bool return_value = TreeView::on_button_press_event(event);
//Then do our custom stuff:
if( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) )
{
m_Menu_Popup.popup(event->button, event->time);
}
return return_value;
}
void TreeView_WithPopup::on_menu_file_popup_generic()
{
std::cout << "A popup menu item was selected." << std::endl;
Glib::RefPtr<Gtk::TreeView::Selection> refSelection = get_selection();
if(refSelection)
{
Gtk::TreeModel::iterator iter = refSelection->get_selected();
if(iter)
{
int id = (*iter)[m_Columns.m_col_id];
std::cout << " Selected ID=" << id << std::endl;
}
}
}