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: 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::slot(*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); show_all_children(); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_button_quit() { hide(); } 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; } 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(); //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: 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::slot(*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); show_all_children(); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_button_quit() { hide(); } 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; } 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: 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::slot(*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(); } 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; } 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: 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: 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: explicit TreeModel_Dnd(const Gtk::TreeModelColumnRecord& columns); 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; }; static ModelColumns m_Columns; static Glib::RefPtr<TreeModel_Dnd> create(); protected: //Overridden virtual functions: virtual bool row_draggable_vfunc(const Gtk::TreeModel::Path& path); virtual bool row_drop_possible_vfunc(const Gtk::TreeModel::Path& dest, GtkSelectionData* selection_data); }; #endif //GTKMM_EXAMPLE_TREEMODEL_DND_H 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::slot(*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(); } 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> //Initialize static data: TreeModel_Dnd::ModelColumns TreeModel_Dnd::m_Columns; TreeModel_Dnd::TreeModel_Dnd(const Gtk::TreeModelColumnRecord& columns) : Gtk::TreeStore(columns) { } Glib::RefPtr<TreeModel_Dnd> TreeModel_Dnd::create() { return Glib::RefPtr<TreeModel_Dnd>( new TreeModel_Dnd(m_Columns) ); } bool TreeModel_Dnd::row_draggable_vfunc(const Gtk::TreeModel::Path& path) { //Make the value of the "draggable" column determine whether this row can be dragged: 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, GtkSelectionData* selection_data) { //Make the value of the "receives drags" column determine whether a row can be dragged into it: //dest is the path of the row after which the dragged path would be dropped. //But in this case we are more interested in the parent row: const_iterator iter = get_iter(dest); if(iter) { const_iterator iter_parent = iter->parent(); if(iter_parent) { Row row = *iter_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. //TODO: Demonstrate this when the API has been corrected to use Gtk::SelectionData instead of GtkSelectionData, //and use Gtk::TreePath::get_from_selection_data(selection_data, model, path) return Gtk::TreeStore::row_drop_possible_vfunc(dest, selection_data); } |