/* === S Y N F I G ========================================================= */ /*! \file layergrouptreestore.cpp ** \brief Template File ** ** $Id$ ** ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley ** Copyright (c) 2008 Chris Moore ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as ** published by the Free Software Foundation; either version 2 of ** the License, or (at your option) any later version. ** ** This package is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** \endlegal */ /* ========================================================================= */ /* === H E A D E R S ======================================================= */ #ifdef USING_PCH # include "pch.h" #else #ifdef HAVE_CONFIG_H # include #endif #include "trees/layergrouptreestore.h" #include "iconcontroller.h" #include #include #include #include #include "app.h" #include "instance.h" #include #include "docks/dockmanager.h" #include "docks/dockable.h" #include #include #include "general.h" #endif /* === U S I N G =========================================================== */ using namespace std; using namespace etl; using namespace synfig; using namespace studio; /* === M A C R O S ========================================================= */ #define GROUP_NEST_CHAR '.' /* === G L O B A L S ======================================================= */ /* === P R O C E D U R E S ================================================= */ /* === M E T H O D S ======================================================= */ static LayerGroupTreeStore::Model& ModelHack() { static LayerGroupTreeStore::Model* model(0); if(!model)model=new LayerGroupTreeStore::Model; return *model; } LayerGroupTreeStore::LayerGroupTreeStore(etl::loose_handle canvas_interface_): Gtk::TreeStore (ModelHack()), canvas_interface_ (canvas_interface_) { layer_icon=Gtk::Button().render_icon_pixbuf(Gtk::StockID("synfig-layer"),Gtk::ICON_SIZE_SMALL_TOOLBAR); group_icon=Gtk::Button().render_icon_pixbuf(Gtk::StockID("synfig-group"),Gtk::ICON_SIZE_SMALL_TOOLBAR); // Connect Signals to Terminals canvas_interface()->signal_layer_status_changed().connect(sigc::mem_fun(*this,&studio::LayerGroupTreeStore::on_layer_status_changed)); canvas_interface()->signal_layer_new_description().connect(sigc::mem_fun(*this,&studio::LayerGroupTreeStore::on_layer_new_description)); canvas_interface()->get_canvas()->signal_group_added().connect(sigc::hide_return(sigc::mem_fun(*this,&studio::LayerGroupTreeStore::on_group_added))); canvas_interface()->get_canvas()->signal_group_removed().connect(sigc::hide_return(sigc::mem_fun(*this,&studio::LayerGroupTreeStore::on_group_removed))); canvas_interface()->get_canvas()->signal_group_changed().connect(sigc::hide_return(sigc::mem_fun(*this,&studio::LayerGroupTreeStore::on_group_changed))); canvas_interface()->get_canvas()->signal_group_pair_added().connect(sigc::hide_return(sigc::mem_fun(*this,&studio::LayerGroupTreeStore::on_group_pair_added))); canvas_interface()->get_canvas()->signal_group_pair_removed().connect(sigc::hide_return(sigc::mem_fun(*this,&studio::LayerGroupTreeStore::on_group_pair_removed))); rebuild(); } LayerGroupTreeStore::~LayerGroupTreeStore() { //clear(); if (getenv("SYNFIG_DEBUG_DESTRUCTORS")) synfig::info("LayerGroupTreeStore::~LayerGroupTreeStore(): Deleted"); } bool LayerGroupTreeStore::search_func(const Glib::RefPtr&,int,const Glib::ustring& x,const TreeModel::iterator& iter) { const Model model; Glib::ustring substr(x.uppercase()); Glib::ustring label((*iter)[model.label]); label=label.uppercase(); return label.find(substr)==Glib::ustring::npos; } Glib::RefPtr LayerGroupTreeStore::create(etl::loose_handle canvas_interface_) { return Glib::RefPtr(new LayerGroupTreeStore(canvas_interface_)); } void LayerGroupTreeStore::get_value_vfunc (const Gtk::TreeModel::iterator& iter, int column, Glib::ValueBase& value)const { if(column==model.child_layers.index()) { Glib::Value x; g_value_init(x.gobj(),x.value_type()); if((bool)(*iter)[model.is_group]) { set layer_set(canvas_interface()->get_canvas()->get_layers_in_group((Glib::ustring)(*iter)[model.group_name])); x.set(LayerList(layer_set.begin(),layer_set.end())); } else if((bool)(*iter)[model.is_layer]) { LayerList layer_list; layer_list.push_back((Layer::Handle)(*iter)[model.layer]); x.set(layer_list); } g_value_init(value.gobj(),x.value_type()); value=x; } else if(column==model.all_layers.index()) { Glib::Value x; g_value_init(x.gobj(),x.value_type()); if((bool)(*iter)[model.is_group]) { LayerList layer_list; Gtk::TreeModel::iterator child_iter(iter->children().begin()); for(;child_iter;++child_iter) { LayerList layer_list2((LayerList)(*child_iter)[model.all_layers]); for(;layer_list2.size();layer_list2.pop_front()) layer_list.push_back(layer_list2.front()); } x.set(layer_list); } else if((bool)(*iter)[model.is_layer]) { LayerList layer_list; layer_list.push_back((Layer::Handle)(*iter)[model.layer]); x.set(layer_list); } g_value_init(value.gobj(),x.value_type()); value=x; } else if(column==model.group_name.index()) { if((bool)(*iter)[model.is_group]) return Gtk::TreeStore::get_value_vfunc(iter,column,value); return get_value_vfunc(iter->parent(),column,value); } else if(column==model.parent_group_name.index()) { if(iter->parent()) return get_value_vfunc(iter->parent(),model.group_name.index(),value); Glib::Value x; g_value_init(x.gobj(),x.value_type()); x.set(Glib::ustring()); g_value_init(value.gobj(),x.value_type()); value=x; } else if(column==model.label.index()) { if((bool)(*iter)[model.is_group]) { Glib::Value x; g_value_init(x.gobj(),x.value_type()); Glib::ustring group_name((*iter)[model.group_name]); // Get rid of any parent group crap while(group_name.find(GROUP_NEST_CHAR)!=Glib::ustring::npos) group_name=Glib::ustring(group_name,group_name.find(GROUP_NEST_CHAR)+1,Glib::ustring::npos); x.set(group_name); g_value_init(value.gobj(),x.value_type()); value=x; } else if((bool)(*iter)[model.is_layer]) { synfig::Layer::Handle layer((*iter)[model.layer]); if(!layer)return; Glib::Value x; g_value_init(x.gobj(),x.value_type()); x.set(layer->get_non_empty_description()); g_value_init(value.gobj(),x.value_type()); //g_value_copy(x.gobj(),value.gobj()); value=x; } } else if(column==model.tooltip.index()) { synfig::Layer::Handle layer((*iter)[model.layer]); if(!layer)return; Glib::Value x; g_value_init(x.gobj(),x.value_type()); x.set(layer->get_local_name()); g_value_init(value.gobj(),x.value_type()); //g_value_copy(x.gobj(),value.gobj()); value=x; } else if(column==model.canvas.index()) { synfig::Layer::Handle layer((*iter)[model.layer]); if(!layer)return; Glib::Value x; g_value_init(x.gobj(),x.value_type()); x.set(layer->get_canvas()); g_value_init(value.gobj(),x.value_type()); //g_value_copy(x.gobj(),value.gobj()); value=x; } else if(column==model.active.index()) { Glib::Value x; g_value_init(x.gobj(),x.value_type()); if((bool)(*iter)[model.is_layer]) { synfig::Layer::Handle layer((*iter)[model.layer]); x.set(layer->active()); } else if((bool)(*iter)[model.is_group]) { int activecount(0),total(0); Gtk::TreeModel::iterator child_iter(iter->children().begin()); for(;child_iter;++child_iter) { total++; if((*child_iter)[model.active]) activecount++; } x.set(activecount>0); } else x.set(false); g_value_init(value.gobj(),x.value_type()); g_value_copy(x.gobj(),value.gobj()); } else if(column==model.icon.index()) { Glib::Value > x; g_value_init(x.gobj(),x.value_type()); if((bool)(*iter)[model.is_layer]) { synfig::Layer::Handle layer((*iter)[model.layer]); if(!layer)return; //x.set(layer_icon); x.set(get_tree_pixbuf_layer(layer->get_name())); } if((bool)(*iter)[model.is_group]) x.set(group_icon); g_value_init(value.gobj(),x.value_type()); g_value_copy(x.gobj(),value.gobj()); } else Gtk::TreeStore::get_value_vfunc(iter,column,value); } void LayerGroupTreeStore::set_value_impl(const Gtk::TreeModel::iterator& iter, int column, const Glib::ValueBase& value) { //if(!iterator_sane(row)) // return; if(column>=get_n_columns_vfunc()) { g_warning("LayerGroupTreeStore::set_value_impl: Bad column (%d)",column); return; } if(!g_value_type_compatible(G_VALUE_TYPE(value.gobj()),get_column_type_vfunc(column))) { g_warning("LayerGroupTreeStore::set_value_impl: Bad value type"); return; } try { if(column==model.label.index()) { Glib::Value x; g_value_init(x.gobj(),model.label.type()); g_value_copy(value.gobj(),x.gobj()); if((bool)(*iter)[model.is_layer]) { synfig::Layer::Handle layer((*iter)[model.layer]); if(!layer) return; synfig::String new_desc(x.get()); if(new_desc==layer->get_local_name()) new_desc=synfig::String(); if(new_desc==layer->get_description()) return; synfigapp::Action::Handle action(synfigapp::Action::create("LayerSetDesc")); if(!action) return; action->set_param("canvas",canvas_interface()->get_canvas()); action->set_param("canvas_interface",canvas_interface()); action->set_param("layer",layer); action->set_param("new_description",synfig::String(x.get())); canvas_interface()->get_instance()->perform_action(action); return; } else if((bool)(*iter)[model.is_group]) { synfig::String group((Glib::ustring)(*iter)[model.label]); synfig::String new_group(x.get()); if(x.get()==group) return; Glib::ustring group_name((*iter)[model.group_name]); group=group_name; new_group.clear(); // Get rid of any parent group crap while(group_name.find(GROUP_NEST_CHAR)!=Glib::ustring::npos) { new_group+=Glib::ustring(group_name,0,group_name.find(GROUP_NEST_CHAR)+1); group_name=Glib::ustring(group_name,group_name.find(GROUP_NEST_CHAR)+1,Glib::ustring::npos); } new_group+=x.get(); // Check to see if this group is real or not. // If it isn't real, then renaming it is a cinch. // We know it isn't real if it doesn't have any // children yet. if(iter->children().empty()) { (*iter)[model.group_name]=new_group; } else { synfigapp::Action::Handle action(synfigapp::Action::create("GroupRename")); if(!action) return; action->set_param("canvas",canvas_interface()->get_canvas()); action->set_param("canvas_interface",canvas_interface()); action->set_param("group",group); action->set_param("new_group",new_group); canvas_interface()->get_instance()->perform_action(action); } return; } return; } else if(column==model.active.index()) { Glib::Value x; g_value_init(x.gobj(),model.active.type()); g_value_copy(value.gobj(),x.gobj()); if((bool)(*iter)[model.is_layer]) { synfig::Layer::Handle layer((*iter)[model.layer]); if(!layer)return; synfigapp::Action::Handle action(synfigapp::Action::create("LayerActivate")); if(!action) return; action->set_param("canvas",canvas_interface()->get_canvas()); action->set_param("canvas_interface",canvas_interface()); action->set_param("layer",layer); action->set_param("new_status",bool(x.get())); canvas_interface()->get_instance()->perform_action(action); return; } else if(!iter->children().empty()) { synfigapp::Action::PassiveGrouper group( get_canvas_interface()->get_instance().get(), String( x.get()?_("Activate "):_("Deactivate ") )+(Glib::ustring)(*iter)[model.label] ); Gtk::TreeModel::iterator child_iter(iter->children().begin()); for(;child_iter;++child_iter) (*child_iter)[model.active]=x.get(); Gtk::TreeStore::set_value_impl(iter,column, value); } } else Gtk::TreeStore::set_value_impl(iter,column, value); } catch(std::exception x) { g_warning("%s", x.what()); } } bool LayerGroupTreeStore::row_draggable_vfunc (const TreeModel::Path& /*path*/)const { //if(!get_iter(path)) return false; // Gtk::TreeModel::Row row(*get_iter(path)); return true; } bool LayerGroupTreeStore::drag_data_get_vfunc (const TreeModel::Path& path, Gtk::SelectionData& selection_data)const { if(!const_cast(this)->get_iter(path)) return false; //synfig::info("Dragged data of type \"%s\"",selection_data.get_data_type()); //synfig::info("Dragged data of target \"%s\"",gdk_atom_name(selection_data->target)); //synfig::info("Dragged selection=\"%s\"",gdk_atom_name(selection_data->selection)); Gtk::TreeModel::Row row(*const_cast(this)->get_iter(path)); if((bool)row[model.is_layer]) { Layer* layer(((Layer::Handle)row[model.layer]).get()); assert(layer); std::vector layers; layers.push_back(layer); selection_data.set("LAYER", 8, reinterpret_cast(&layers.front()), sizeof(void*)*layers.size()); return true; } else if((bool)row[model.is_group]) { synfig::String group((Glib::ustring)row[model.group_name]); if(group.empty()) return false; selection_data.set("GROUP", 8, reinterpret_cast(&*group.begin()), sizeof(void*)*group.size()); return true; } return false; } bool LayerGroupTreeStore::drag_data_delete_vfunc (const TreeModel::Path& /*path*/) { return true; } bool LayerGroupTreeStore::row_drop_possible_vfunc (const TreeModel::Path& dest, const Gtk::SelectionData& selection_data)const { Gtk::TreeIter iter(const_cast(this)->get_iter(dest)); if(!iter) return false; if(synfig::String(selection_data.get_data_type())=="LAYER") return true; if(synfig::String(selection_data.get_data_type())=="GROUP") { synfig::String dest_group((Glib::ustring)(*iter)[model.group_name]); synfig::String src_group(reinterpret_cast(selection_data.get_data())); //synfig::String src_group(const_cast(selection_data.get_data())); // Avoid putting a group inside of itself if(dest_group.size()>src_group.size() && src_group==String(dest_group,0,src_group.size())) return false; return true; } return false; //synfig::info("possible_drop -- data of type \"%s\"",selection_data.get_data_type()); //synfig::info("possible_drop -- data of target \"%s\"",gdk_atom_name(selection_data->target)); //synfig::info("possible_drop -- selection=\"%s\"",gdk_atom_name(selection_data->selection)); //Gtk::TreeModel::Row row(*get_iter(dest)); /* if(synfig::String(selection_data.get_data_type())=="LAYER" && (bool)true) return true; */ return false; } bool LayerGroupTreeStore::drag_data_received_vfunc (const TreeModel::Path& dest, const Gtk::SelectionData& selection_data) { if(!get_iter(dest)) return false; // bool ret=false; //int i(0); Gtk::TreeModel::Row row(*get_iter(dest)); //synfig::info("Dropped data of type \"%s\"",selection_data.get_data_type()); //synfig::info("Dropped data of target \"%s\"",gdk_atom_name(selection_data->target)); //synfig::info("Dropped selection=\"%s\"",gdk_atom_name(selection_data->selection)); synfigapp::Action::PassiveGrouper passive_grouper(canvas_interface()->get_instance().get(),_("Reset")); if ((selection_data.get_length() >= 0) && (selection_data.get_format() == 8)) { synfig::String dest_group; dest_group=(Glib::ustring)row[model.group_name]; if(dest_group.empty()) return false; if(synfig::String(selection_data.get_data_type())=="LAYER") { synfigapp::Action::Handle action(synfigapp::Action::create("GroupAddLayers")); if(!action) return false; action->set_param("canvas",canvas_interface()->get_canvas()); action->set_param("canvas_interface",canvas_interface()); action->set_param("group",dest_group); for(unsigned int i=0;i(const_cast(selection_data.get_data()))[i]); assert(layer); action->set_param("layer",layer); } if(!canvas_interface()->get_instance()->perform_action(action)) { passive_grouper.cancel(); return false; } return true; } if(synfig::String(selection_data.get_data_type())=="GROUP") { synfig::String src_group(reinterpret_cast(selection_data.get_data())); synfig::String group(src_group); // Get rid of any parent group crap while(group.find(GROUP_NEST_CHAR)!=Glib::ustring::npos) group=Glib::ustring(group,group.find(GROUP_NEST_CHAR)+1,Glib::ustring::npos); group=dest_group+GROUP_NEST_CHAR+group; synfigapp::Action::Handle action(synfigapp::Action::create("GroupRename")); if(!action) return false; action->set_param("canvas",canvas_interface()->get_canvas()); action->set_param("canvas_interface",canvas_interface()); action->set_param("group",src_group); action->set_param("new_group",group); if(!canvas_interface()->get_instance()->perform_action(action)) { passive_grouper.cancel(); return false; } return true; } } /* // Save the selection data synfigapp::SelectionManager::LayerList selected_layer_list=canvas_interface()->get_selection_manager()->get_selected_layers(); if ((selection_data.get_length() >= 0) && (selection_data.get_format() == 8)) { Canvas::Handle dest_canvas; Layer::Handle dest_layer; dest_canvas=(Canvas::Handle)(row[model.canvas]); dest_layer=(Layer::Handle)(row[model.layer]); assert(dest_canvas); if(!dest_layer) return false; int dest_layer_depth=dest_layer->get_depth(); if(synfig::String(selection_data.get_data_type())=="LAYER")for(i=0;i(const_cast(selection_data.get_data()))[i]); assert(src); if(dest_layer==src) continue; // In this case, we are just moving. // if(dest_canvas==src->get_canvas()) { if(dest_canvas==src->get_canvas() && dest_layer_depth && dest_layer_depth>src->get_depth()) dest_layer_depth--; if(dest_canvas==src->get_canvas() && dest_layer_depth==src->get_depth()) continue; synfigapp::Action::Handle action(synfigapp::Action::create("LayerMove")); action->set_param("canvas",dest_canvas); action->set_param("canvas_interface",canvas_interface()); action->set_param("layer",src); action->set_param("new_index",dest_layer_depth); action->set_param("dest_canvas",dest_canvas); if(canvas_interface()->get_instance()->perform_action(action)) { ret=true; } else { passive_grouper.cancel(); return false; } continue; } } } synfig::info("I supposedly moved %d layers",i); // Reselect the previously selected layers canvas_interface()->get_selection_manager()->set_selected_layers(selected_layer_list); return ret; */ return false; } void LayerGroupTreeStore::rebuild() { rebuilding=true; // etl::clock timer;timer.reset(); try { // Clear out the current list clear(); Canvas::Handle canvas(canvas_interface()->get_canvas()); std::set groups(canvas->get_groups()); for(;groups.size();groups.erase(groups.begin())) { String group(*groups.begin()); Gtk::TreeRow row(on_group_added(group)); std::set layers(canvas->get_layers_in_group(group)); for(;layers.size();layers.erase(layers.begin())) { Gtk::TreeRow layer_row(*(prepend(row.children()))); Layer::Handle layer(*layers.begin()); set_row_layer(layer_row,layer); } } // Go ahead and add all the layers /*std::for_each( canvas_interface()->get_canvas()->rbegin(), canvas_interface()->get_canvas()->rend(), sigc::mem_fun(*this, &studio::LayerGroupTreeStore::on_layer_added) );*/ } catch(...) { rebuilding=false; throw; } rebuilding=false; // synfig::info("LayerGroupTreeStore::rebuild() took %f seconds",float(timer())); } void LayerGroupTreeStore::refresh() { rebuild(); } void LayerGroupTreeStore::refresh_row(Gtk::TreeModel::Row &row) { if((bool)row[model.is_layer]) { Layer::Handle layer=row[model.layer]; //if(layer->dynamic_param_list().count("z_depth")) // row[model.z_depth]=Time::begin(); } Gtk::TreeModel::Children children = row.children(); Gtk::TreeModel::Children::iterator iter; if(!children.empty()) for(iter = children.begin(); iter && iter != children.end(); ++iter) { Gtk::TreeRow row=*iter; refresh_row(row); } } void LayerGroupTreeStore::set_row_layer(Gtk::TreeRow &row,synfig::Layer::Handle &handle) { row[model.is_layer] = true; row[model.is_group] = false; row[model.layer] = handle; } Gtk::TreeRow LayerGroupTreeStore::on_group_added(synfig::String group) { // Check to see if this group perhaps already // exists { Gtk::TreeModel::Children::iterator iter; if(find_group_row(group, iter)) return *iter; } if(group.find(GROUP_NEST_CHAR)!=String::npos) { Gtk::TreeModel::Children::iterator iter; String parent_name; do { if(parent_name.size()) parent_name+=GROUP_NEST_CHAR; parent_name+=string(group,0,group.find(GROUP_NEST_CHAR)); if(!find_group_row(parent_name, iter)) iter=on_group_added(parent_name); group=String(group,group.find(GROUP_NEST_CHAR)+1,String::npos); }while(group.find(GROUP_NEST_CHAR)!=String::npos); if(parent_name.size()) parent_name+=GROUP_NEST_CHAR; parent_name+=group; if(iter) { Gtk::TreeRow row(*(prepend(iter->children()))); row[model.group_name]=parent_name; row[model.is_layer]=false; row[model.is_group]=true; on_activity(); return row; } } Gtk::TreeRow row(*(append())); row[model.group_name]=group; row[model.is_layer]=false; row[model.is_group]=true; on_activity(); return row; } bool LayerGroupTreeStore::on_group_removed(synfig::String group) { Gtk::TreeModel::Children::iterator iter; if(find_group_row(group,iter) && iter->children().size()==0) erase(iter); else return false; return true; } bool LayerGroupTreeStore::on_group_changed(synfig::String /*group*/) { return true; } void LayerGroupTreeStore::on_group_pair_added(synfig::String group, etl::handle layer) { if(!layer->get_canvas()) return; Gtk::TreeModel::Children::iterator iter; if(!find_group_row(group, iter)) iter=on_group_added(group); Gtk::TreeRow layer_row(*(append(iter->children()))); set_row_layer(layer_row,layer); on_activity(); } void LayerGroupTreeStore::on_group_pair_removed(synfig::String group, etl::handle layer) { if(!layer->get_canvas()) return; Gtk::TreeModel::Children::iterator iter; if(!find_group_row(group, iter)) return; Gtk::TreeModel::Children::iterator prev,layer_iter; if(!find_layer_row_(layer, layer->get_canvas(), iter->children(), layer_iter, prev)) return; erase(layer_iter); on_activity(); } void LayerGroupTreeStore::on_activity() { // If we aren't rebuilding and the last action // had something to do with groups, then go // ahead and present the groups dialog. if(!rebuilding && canvas_interface()->get_instance()->get_most_recent_action_name().find("Group")!=String::npos) try { App::dock_manager->find_dockable("groups").present(); } catch(...) { } } void LayerGroupTreeStore::on_layer_status_changed(synfig::Layer::Handle handle,bool /*x*/) { Gtk::TreeModel::Children::iterator iter; if(find_layer_row(handle,iter)) (*iter)[model.layer]=handle; else { // Not need to send a warning when a layer changes its status and // it is not found in any group. //synfig::warning("Couldn't find layer to be activated in layer list. Rebuilding index..."); rebuild(); } } void LayerGroupTreeStore::on_layer_new_description(synfig::Layer::Handle handle,synfig::String desc) { Gtk::TreeModel::Children::iterator iter; if(find_layer_row(handle,iter)) { Gtk::TreeRow row(*iter); Layer::Handle layer(row[model.layer]); if(desc.empty()) { //row[model.label]=layer->get_local_name(); row[model.tooltip]=Glib::ustring(_("Layer")); } else //row[model.label]=layer->get_description(); row[model.tooltip]=layer->get_local_name(); } else { rebuild(); } } bool LayerGroupTreeStore::find_layer_row_(const synfig::Layer::Handle &layer, synfig::Canvas::Handle canvas, Gtk::TreeModel::Children layers, Gtk::TreeModel::Children::iterator &iter, Gtk::TreeModel::Children::iterator &prev) { assert(layer); //if(layer->get_canvas()==canvas) { for(iter=prev=layers.begin(); iter && iter != layers.end(); prev=iter++) { Gtk::TreeModel::Row row = *iter; if((bool)row[model.is_layer] && layer==(synfig::Layer::Handle)row[model.layer]) return true; } iter=children().end(); //return false; } Gtk::TreeModel::Children::iterator iter2; for(iter2 = layers.begin(); iter2 && iter2 != layers.end(); ++iter2) { Gtk::TreeModel::Row row = *iter2; assert((bool)true); if(row.children().empty()) continue; /*Canvas::Handle canvas((*row.children().begin())[model.canvas]); if(!canvas) continue; */ if(find_layer_row_(layer,canvas,iter2->children(),iter,prev)) return true; } iter=children().end(); return false; } bool LayerGroupTreeStore::find_layer_row(const synfig::Layer::Handle &layer, Gtk::TreeModel::Children::iterator &iter) { Gtk::TreeModel::Children::iterator prev; return find_layer_row_(layer,canvas_interface()->get_canvas(),children(),iter,prev); } bool LayerGroupTreeStore::find_group_row(const synfig::String &group, Gtk::TreeModel::Children::iterator &iter) { Gtk::TreeModel::Children::iterator prev; return find_group_row_(group,children(),iter,prev); } bool LayerGroupTreeStore::find_group_row_(const synfig::String &group, Gtk::TreeModel::Children layers, Gtk::TreeModel::Children::iterator &iter, Gtk::TreeModel::Children::iterator &prev) { //if(layer->get_canvas()==canvas) { for(iter=prev=layers.begin(); iter && iter != layers.end(); prev=iter++) { Gtk::TreeModel::Row row = *iter; if((bool)row[model.is_group] && group==(Glib::ustring)row[model.group_name]) return true; } iter=children().end(); //return false; } Gtk::TreeModel::Children::iterator iter2; for(iter2 = layers.begin(); iter2 && iter2 != layers.end(); ++iter2) { Gtk::TreeModel::Row row = *iter2; assert((bool)true); if(row.children().empty()) continue; if(find_group_row_(group,iter2->children(),iter,prev)) return true; } iter=children().end(); return false; } bool LayerGroupTreeStore::find_prev_layer_row(const synfig::Layer::Handle &layer, Gtk::TreeModel::Children::iterator &prev) { Gtk::TreeModel::Children::iterator iter; if(!find_layer_row_(layer,canvas_interface()->get_canvas(),children(),iter,prev)) return false; if(iter==children().begin()) return false; return true; }