1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
#include "editable_iconview.h"
#include <gtk/gtk.h>
//------------------------------------------------------------------------------
EditableIconView::EditableIconView(const Glib::RefPtr<Gtk::TreeModel> & model)
: Gtk::IconView(model)
{
#if GTK_MINOR_VERSION >= 18
gtk_icon_view_set_item_padding(gobj(), 4);
#endif
}
//------------------------------------------------------------------------------
EditableIconView::EditableIconView()
: Gtk::IconView()
{}
//------------------------------------------------------------------------------
bool EditableIconView::on_button_press_event(GdkEventButton *event)
{
// Handle Gtk::IconView event first so it can do its logic before we are in
const bool ret = Gtk::IconView::on_button_press_event(event);
// Recheck here if we have correct model set for the IconView. It is possible
// that we are dealing with Gtk::ListStore
if (_model)
{
// Get the item at the mouse position, it is the one we need to decide on editing
Gtk::TreeModel::Path path;
if (get_item_at_pos((int)event->x, (int)event->y, path))
{
const bec::NodeId node(_model->get_node_for_path(path));
Gtk::CellRenderer *cell(0);
get_item_at_pos((int)event->x, (int)event->y, path, cell);
if (node.is_valid() && _model->get_be_model()->is_editable(node))
{
// Check if it was the item selected before. We do not want to start edit
// on newly clicked item
if (_selected_path.gobj() && _selected_path.to_string() == path.to_string())
{
if ( cell && GTK_IS_CELL_RENDERER_TEXT(cell->gobj()) )
{
Gtk::CellRendererText* rend = static_cast<Gtk::CellRendererText*>(cell);
// Enable editing, without that we are not able to start editing as gtk's code checks
// for cellrenderer to be editable
rend->property_editable() = true;
// connect signal so we can handle editing_done. Handling editing_done allows
// us to update model, otherwise gtk won't pass new value to the model
_start_conn = rend->signal_editing_started().connect(sigc::mem_fun(this, &EditableIconView::edit_started));
#if GTK_VERSION_GT(2,14)
set_cursor(path, *cell, true);
#else
// gtkmm shipped with RHEL5.4 doesn't have set_cursor(), even tho gtk does
gtk_icon_view_set_cursor(gobj(), path.gobj(), cell->gobj(), TRUE);
#endif
// Disable editing, otherwise we will start edit on the next clicking on a different item
rend->property_editable() = false;
}
}
}
}
// Update selected path so we can detect second single click on the item
_selected_path = path;
}
return ret;
}
//------------------------------------------------------------------------------
void EditableIconView::edit_started(Gtk::CellEditable* editable, const Glib::ustring& path)
{
_start_conn.disconnect();
if (editable)
_done_conn = editable->signal_editing_done().connect(sigc::bind(sigc::mem_fun(this, &EditableIconView::edit_done), editable));
}
//------------------------------------------------------------------------------
void EditableIconView::edit_done(Gtk::CellEditable* editable)
{
Gtk::Entry* entry = static_cast<Gtk::Entry*>(editable);
if (entry)
{
Gtk::TreeModel::iterator iter = _model->get_iter(_selected_path);
Gtk::TreeModel::Row row = *iter;
if (row)
{
std::string data("");
row.get_value(get_text_column(), data);
if (data != entry->get_text())
row.set_value(get_text_column(), entry->get_text());
}
}
_done_conn.disconnect();
}
|