X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-studio%2Ftags%2Fstable%2Fsrc%2Fgtkmm%2Fkeyframetreestore.cpp;fp=synfig-studio%2Ftags%2Fstable%2Fsrc%2Fgtkmm%2Fkeyframetreestore.cpp;h=df40eacd56db63c8480c9c88a8f2e99fef97c62a;hb=4cb5360f578f79e5d9e234570018d762ea0a964f;hp=0000000000000000000000000000000000000000;hpb=91c14fb028f8cbf78be64623aded885725606f78;p=synfig.git diff --git a/synfig-studio/tags/stable/src/gtkmm/keyframetreestore.cpp b/synfig-studio/tags/stable/src/gtkmm/keyframetreestore.cpp new file mode 100644 index 0000000..df40eac --- /dev/null +++ b/synfig-studio/tags/stable/src/gtkmm/keyframetreestore.cpp @@ -0,0 +1,883 @@ +/* === S Y N F I G ========================================================= */ +/*! \file keyframetreestore.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** 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 "keyframetreestore.h" +#include +#include "iconcontroler.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "onemoment.h" +#include + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +KeyframeTreeStore_Class KeyframeTreeStore::keyframe_tree_store_class_; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +struct _keyframe_iterator +{ + synfig::KeyframeList::iterator iter; + int ref_count; + int index; +}; + +/* +Gtk::TreeModel::iterator keyframe_iter_2_model_iter(synfig::KeyframeList::iterator iter,int index) +{ + Gtk::TreeModel::iterator ret; + + _keyframe_iterator*& data(static_cast<_keyframe_iterator*&>(ret->gobj()->user_data)); + data=new _keyframe_iterator(); + data->ref_count=1; + data->iter=iter; + data->index=index; + + return ret; +} +*/ + +synfig::KeyframeList::iterator model_iter_2_keyframe_iter(Gtk::TreeModel::iterator iter) +{ + _keyframe_iterator* data(static_cast<_keyframe_iterator*>(iter->gobj()->user_data)); + if(!data) + throw std::runtime_error("bad data"); + return data->iter; +} + +int get_index_from_model_iter(Gtk::TreeModel::iterator iter) +{ + _keyframe_iterator* data(static_cast<_keyframe_iterator*>(iter->gobj()->user_data)); + if(!data) + throw std::runtime_error("bad data"); + return data->index; +} + + +/* +#ifndef TreeRowReferenceHack +class TreeRowReferenceHack +{ + GtkTreeRowReference *gobject_; +public: + TreeRowReferenceHack(): + gobject_(0) + { + } + + TreeRowReferenceHack(const Glib::RefPtr& model, const Gtk::TreeModel::Path& path): + gobject_ ( gtk_tree_row_reference_new(model->gobj(), const_cast(path.gobj())) ) + { + } + + TreeRowReferenceHack(const TreeRowReferenceHack &x): + gobject_ ( x.gobject_?gtk_tree_row_reference_copy(x.gobject_):0 ) + { + + } + + void swap(TreeRowReferenceHack & other) + { + GtkTreeRowReference *const temp = gobject_; + gobject_ = other.gobject_; + other.gobject_ = temp; + } + + const TreeRowReferenceHack & + operator=(const TreeRowReferenceHack &rhs) + { + TreeRowReferenceHack temp (rhs); + swap(temp); + return *this; + } + + ~TreeRowReferenceHack() + { + if(gobject_) + gtk_tree_row_reference_free(gobject_); + } + + Gtk::TreeModel::Path get_path() { return Gtk::TreeModel::Path(gtk_tree_row_reference_get_path(gobject_),false); } + GtkTreeRowReference *gobj() { return gobject_; } +}; +#endif +*/ + +/* === P R O C E D U R E S ================================================= */ + +void clear_iterator(GtkTreeIter* iter) +{ + iter->stamp=0; + iter->user_data=iter->user_data2=iter->user_data3=0; +} + +/* === M E T H O D S ======================================================= */ + +const Glib::Class& +KeyframeTreeStore_Class::init() +{ + if(!gtype_) + { + class_init_func_ = &KeyframeTreeStore_Class::class_init_function; + + const GTypeInfo derived_info = + { + sizeof(GObjectClass), + NULL, + NULL, + class_init_func_, + NULL, + NULL, + sizeof(GObject), + 0, + 0, + NULL + }; + + gtype_ = g_type_register_static(G_TYPE_OBJECT, "KeyframeTreeStore", &derived_info, GTypeFlags(0)); + Gtk::TreeModel::add_interface(get_type()); + } + return *this; +} + +void +KeyframeTreeStore_Class::class_init_function(gpointer g_class, gpointer class_data) +{ + // ??? +} + +KeyframeTreeStore::KeyframeTreeStore(etl::loose_handle canvas_interface_): + Glib::ObjectBase ("KeyframeTreeStore"), + Glib::Object (Glib::ConstructParams(keyframe_tree_store_class_.init(), (char*) 0)), + canvas_interface_ (canvas_interface_) +{ + reset_stamp(); + //reset_path_table(); + + canvas_interface()->signal_keyframe_added().connect(sigc::mem_fun(*this,&studio::KeyframeTreeStore::add_keyframe)); + canvas_interface()->signal_keyframe_removed().connect(sigc::mem_fun(*this,&studio::KeyframeTreeStore::remove_keyframe)); + canvas_interface()->signal_keyframe_changed().connect(sigc::mem_fun(*this,&studio::KeyframeTreeStore::change_keyframe)); +} + +KeyframeTreeStore::~KeyframeTreeStore() +{ + synfig::info("KeyframeTreeStore::~KeyframeTreeStore(): Deleted"); +} + +Glib::RefPtr +KeyframeTreeStore::create(etl::loose_handle canvas_interface_) +{ + KeyframeTreeStore *store(new KeyframeTreeStore(canvas_interface_)); + Glib::RefPtr ret(store); + assert(ret); + return ret; +} + +void +KeyframeTreeStore::reset_stamp() +{ + stamp_=time(0)+reinterpret_cast(this); +} + +/* +void +KeyframeTreeStore::reset_path_table() +{ + Gtk::TreeModel::Children::iterator iter; + const Gtk::TreeModel::Children children(children()); + path_table_.clear(); + for(iter = children.begin(); iter != children.end(); ++iter) + { + Gtk::TreeModel::Row row(*iter); + path_table_[(Keyframe)row[model.keyframe]]=TreeRowReferenceHack(Glib::RefPtr(this),Gtk::TreePath(row)); + } +} +*/ + + +inline bool +KeyframeTreeStore::iterator_sane(const GtkTreeIter* iter)const +{ + if(iter && iter->stamp==stamp_) + return true; + g_warning("KeyframeTreeStore::iterator_sane(): Bad iterator stamp"); + return false; +} + +inline bool +KeyframeTreeStore::iterator_sane(const Gtk::TreeModel::iterator& iter)const +{ + return iterator_sane(iter->gobj()); +} + +inline void +KeyframeTreeStore::dump_iterator(const GtkTreeIter* gtk_iter, const Glib::ustring &name)const +{ +#if 0 + if(!gtk_iter) + { + g_warning("KeyframeTreeStore::dump_iterator: \"%s\" is NULL (Root?)",name.c_str()); + return; + } + + _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data)); + + if(gtk_iter->stamp!=stamp_ || !iter) + { + g_warning("KeyframeTreeStore::dump_iterator: \"%s\" is INVALID",name.c_str()); + return; + } + + if((unsigned)iter->index>=canvas_interface()->get_canvas()->keyframe_list().size()) + g_warning("KeyframeTreeStore::dump_iterator: \"%s\"(%p) has bad index(index:%d)",name.c_str(),gtk_iter,iter->index); + + g_warning("KeyframeTreeStore::dump_iterator: \"%s\"(%p) ref:%d, index:%d, time:%s",name.c_str(),gtk_iter,iter->ref_count,iter->index,iter->iter->get_time().get_string().c_str()); +#endif +} + +inline void +KeyframeTreeStore::dump_iterator(const Gtk::TreeModel::iterator& iter, const Glib::ustring &name)const +{ + dump_iterator(iter->gobj(),name); +} + +int +KeyframeTreeStore::time_sorter(const Gtk::TreeModel::iterator &rhs,const Gtk::TreeModel::iterator &lhs) +{ + const Model model; + + _keyframe_iterator *rhs_iter(static_cast<_keyframe_iterator*>(rhs->gobj()->user_data)); + _keyframe_iterator *lhs_iter(static_cast<_keyframe_iterator*>(lhs->gobj()->user_data)); + + Time diff(rhs_iter->iter->get_time()-lhs_iter->iter->get_time()); + if(diff<0) + return -1; + if(diff>0) + return 1; + return 0; +} + +void +KeyframeTreeStore::set_value_impl(const Gtk::TreeModel::iterator& row, int column, const Glib::ValueBase& value) +{ + if(!iterator_sane(row)) + return; + + if(column>=get_n_columns_vfunc()) + { + g_warning("KeyframeTreeStore::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("KeyframeTreeStore::set_value_impl: Bad value type"); + return; + } + + _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(row.gobj()->user_data)); + + try + { + if(column==model.time_delta.index()) + { + Glib::Value x; + g_value_init(x.gobj(),model.time.type()); + g_value_copy(value.gobj(),x.gobj()); + + Time new_delta(x.get()); + if(new_delta<=Time::zero()+Time::epsilon()) + { + // Bad value + return; + } + + Time old_delta((*row)[model.time_delta]); + if(old_delta<=Time::zero()+Time::epsilon()) + { + // Bad old delta + return; + } + //Gtk::TreeModel::iterator row(row); + //row++; + //if(!row)return; + + Time change_delta(new_delta-old_delta); + + if(change_delta<=Time::zero()+Time::epsilon() &&change_delta>=Time::zero()-Time::epsilon()) + { + // Not an error, just no change + return; + } + + { + Keyframe keyframe((*row)[model.keyframe]); + synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set_delta")); + + if(!action)return; + + action->set_param("canvas",canvas_interface()->get_canvas()); + action->set_param("canvas_interface",canvas_interface()); + action->set_param("keyframe",keyframe); + action->set_param("delta",change_delta); + + canvas_interface()->get_instance()->perform_action(action); + } + + return; + } + else + if(column==model.time.index()) + { + OneMoment one_moment; + + Glib::Value x; + g_value_init(x.gobj(),model.time.type()); + g_value_copy(value.gobj(),x.gobj()); + synfig::Keyframe keyframe(*iter->iter); + + synfig::info("KeyframeTreeStore::set_value_impl():old_time=%s",keyframe.get_time().get_string().c_str()); + keyframe.set_time(x.get()); + synfig::info("KeyframeTreeStore::set_value_impl():new_time=%s",keyframe.get_time().get_string().c_str()); + + synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set")); + + if(!action) + return; + + action->set_param("canvas",canvas_interface()->get_canvas()); + action->set_param("canvas_interface",canvas_interface()); + action->set_param("keyframe",keyframe); + + canvas_interface()->get_instance()->perform_action(action); + } + else if(column==model.description.index()) + { + Glib::Value x; + g_value_init(x.gobj(),model.description.type()); + g_value_copy(value.gobj(),x.gobj()); + synfig::Keyframe keyframe(*iter->iter); + keyframe.set_description(x.get()); + + synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_set")); + + if(!action) + return; + + action->set_param("canvas",canvas_interface()->get_canvas()); + action->set_param("canvas_interface",canvas_interface()); + action->set_param("keyframe",keyframe); + + canvas_interface()->get_instance()->perform_action(action); + } + else if(column==model.keyframe.index()) + { + g_warning("KeyframeTreeStore::set_value_impl: This column is read-only"); + } + else + { + assert(0); + } + } + catch(std::exception x) + { + g_warning(x.what()); + } +} + +Gtk::TreeModelFlags +KeyframeTreeStore::get_flags_vfunc () +{ + return Gtk::TREE_MODEL_LIST_ONLY; +} + +int +KeyframeTreeStore::get_n_columns_vfunc () +{ + return model.size(); +} + +GType +KeyframeTreeStore::get_column_type_vfunc (int index) +{ + return model.types()[index]; +} + +bool +KeyframeTreeStore::iter_next_vfunc (const iterator& xiter, iterator& iter_next) const +{ + if(!iterator_sane(xiter)) return false; + + _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(xiter.gobj()->user_data)); + + if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end()) + return false; + + _keyframe_iterator *next(new _keyframe_iterator()); + iter_next.gobj()->user_data=static_cast(next); + next->ref_count=1; + next->index=iter->index+1; + next->iter=iter->iter; + ++next->iter; + + if(next->iter==canvas_interface()->get_canvas()->keyframe_list().end()) + return false; + + iter_next.gobj()->stamp=stamp_; + + return true; +} + +/* +bool +KeyframeTreeStore::iter_next_vfunc (GtkTreeIter* gtk_iter) +{ + if(!iterator_sane(gtk_iter)) return false; + + _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data)); + + // If we are already at the end, then we are very invalid + if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end()) + return false; + + ++(iter->iter); + + if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end()) + { + --(iter->iter); + return false; + } + (iter->index)++; + return true; +} + +bool +KeyframeTreeStore::iter_children_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* parent) +{ + dump_iterator(gtk_iter,"gtk_iter"); + dump_iterator(parent,"parent"); + + if(!parent || !iterator_sane(parent)) + { + clear_iterator(gtk_iter); + return false; + } + + _keyframe_iterator *iter(new _keyframe_iterator()); + iter->ref_count=1; + iter->index=0; + iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin(); + + gtk_iter->user_data=static_cast(iter); + gtk_iter->stamp=stamp_; + + return true; +} + +bool +KeyframeTreeStore::iter_has_child_vfunc (const GtkTreeIter*parent) +{ + dump_iterator(parent,"parent"); + + if(parent) + return false; + + return true; +} + +int +KeyframeTreeStore::iter_n_children_vfunc (const GtkTreeIter* parent) +{ + dump_iterator(parent,"parent"); + + if(parent) + return 0; + + return canvas_interface()->get_canvas()->keyframe_list().size(); +} +*/ + +int +KeyframeTreeStore::iter_n_root_children_vfunc () const +{ + return canvas_interface()->get_canvas()->keyframe_list().size(); +} + +bool +KeyframeTreeStore::iter_nth_root_child_vfunc (int n, iterator& xiter)const +{ + if(canvas_interface()->get_canvas()->keyframe_list().size()==0) + { + return false; + } + + if(n<0) + { + g_warning("KeyframeTreeStore::iter_nth_root_child_vfunc: Out of range (negative index)"); + return false; + } + if(n && (unsigned)n>=canvas_interface()->get_canvas()->keyframe_list().size()) + { + g_warning("KeyframeTreeStore::iter_nth_child_vfunc: Out of range (large index)"); + return false; + } + + _keyframe_iterator *iter(new _keyframe_iterator()); + iter->ref_count=1; + iter->index=n; + iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin(); + while(n--) + { + if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end()) + { + g_warning("KeyframeTreeStore::iter_nth_child_vfunc: >>>BUG<<< in %s on line %d",__FILE__,__LINE__); + delete iter; + return false; + } + ++iter->iter; + } + xiter.gobj()->user_data=static_cast(iter); + xiter.gobj()->stamp=stamp_; + return true; +} + +/* +bool +KeyframeTreeStore::iter_nth_child_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* parent, int n) +{ + dump_iterator(parent,"parent"); + + if(parent) + { + g_warning("KeyframeTreeStore::iter_nth_child_vfunc: I am a list"); + clear_iterator(gtk_iter); + return false; + } + + + + _keyframe_iterator *iter(new _keyframe_iterator()); + iter->ref_count=1; + iter->index=n; + iter->iter=canvas_interface()->get_canvas()->keyframe_list().begin(); + while(n--) + { + if(iter->iter==canvas_interface()->get_canvas()->keyframe_list().end()) + { + g_warning("KeyframeTreeStore::iter_nth_child_vfunc: >>>BUG<<< in %s on line %d",__FILE__,__LINE__); + delete iter; + clear_iterator(gtk_iter); + return false; + } + ++iter->iter; + } + + gtk_iter->user_data=static_cast(iter); + gtk_iter->stamp=stamp_; + return true; +} + +bool +KeyframeTreeStore::iter_parent_vfunc (GtkTreeIter* gtk_iter, const GtkTreeIter* child) +{ + dump_iterator(child,"child"); + iterator_sane(child); + clear_iterator(gtk_iter); + return false; +} +*/ + +void +KeyframeTreeStore::ref_node_vfunc (iterator& xiter)const +{ + GtkTreeIter* gtk_iter(xiter.gobj()); + if(!gtk_iter || !iterator_sane(gtk_iter)) return; + + _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data)); + iter->ref_count++; +} + +void +KeyframeTreeStore::unref_node_vfunc (iterator& xiter)const +{ + GtkTreeIter* gtk_iter(xiter.gobj()); + if(!gtk_iter || !iterator_sane(gtk_iter)) return; + + _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data)); + iter->ref_count--; + if(!iter->ref_count) + { + delete iter; + + // Make this iterator invalid + gtk_iter->stamp=0; + } +} + +Gtk::TreeModel::Path +KeyframeTreeStore::get_path_vfunc (const TreeModel::iterator& gtk_iter)const +{ + Gtk::TreeModel::Path path; + + // If this is the root node, then return + // a root path + if(!iterator_sane(gtk_iter)) + return path; + + _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->gobj()->user_data)); + + path.append_index(iter->index); + + return path; +} + +bool +KeyframeTreeStore::get_iter_vfunc (const Gtk::TreeModel::Path& path, iterator& iter)const +{ + if(path.get_depth()>=1) + return iter_nth_root_child_vfunc(path.front(),iter); + + // Error case + g_warning("KeyframeTreeStore::get_iter_vfunc(): Bad path \"%s\"",path.to_string().c_str()); + //clear_iterator(iter); + return false; +} + +bool +KeyframeTreeStore::iter_is_valid (const iterator& iter) const +{ + return iterator_sane(iter); +} + +void +KeyframeTreeStore::get_value_vfunc (const Gtk::TreeModel::iterator& gtk_iter, int column, Glib::ValueBase& value)const +{ + dump_iterator(gtk_iter,"gtk_iter"); + if(!iterator_sane(gtk_iter)) + return; + + _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->gobj()->user_data)); + + switch(column) + { + case 0: // Time + { + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + x.set(iter->iter->get_time()); + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + return; + } + case 3: // Time Delta + { + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + synfig::Keyframe prev_keyframe(*iter->iter); + synfig::Keyframe keyframe; + { + KeyframeList::iterator tmp(iter->iter); + tmp++; + if(tmp==get_canvas()->keyframe_list().end()) + { + x.set(Time(0)); + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + return; + } + keyframe=*tmp; + } + + Time delta(0); + try { + delta=keyframe.get_time()-prev_keyframe.get_time(); + }catch(...) { } + x.set(delta); + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + return; + } + case 1: // Description + { + g_value_init(value.gobj(),G_TYPE_STRING); + g_value_set_string(value.gobj(),iter->iter->get_description().c_str()); + return; + } + case 2: // Keyframe + { + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + x.set(*iter->iter); + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + return; + } + default: + break; + } +} + +Gtk::TreeModel::Row +KeyframeTreeStore::find_row(const synfig::Keyframe &keyframe) +{ + Gtk::TreeModel::Row row(*(children().begin())); + dump_iterator(row,"find_row,begin"); + const GtkTreeIter *gtk_iter(row.gobj()); + if(!iterator_sane(gtk_iter)) + throw std::runtime_error(_("Unable to find Keyframe in table")); + + _keyframe_iterator *iter(static_cast<_keyframe_iterator*>(gtk_iter->user_data)); + + synfig::KeyframeList &keyframe_list(canvas_interface()->get_canvas()->keyframe_list()); + if(keyframe_list.empty()) + throw std::runtime_error(_("There are no keyframes n this canvas")); + + iter->index=0; + + for(iter->iter=keyframe_list.begin();iter->iter!=keyframe_list.end() && *iter->iter!=keyframe;++iter->iter) + { + iter->index++; + } + if(iter->iter==keyframe_list.end()) + throw std::runtime_error(_("Unable to find Keyframe in table")); + return row; +} + +void +KeyframeTreeStore::add_keyframe(Keyframe keyframe) +{ + try + { + Gtk::TreeRow row(find_row(keyframe)); + dump_iterator(row.gobj(),"add_keyframe,row"); + Gtk::TreePath path(get_path(row)); + + row_inserted(path,row); + + old_keyframe_list=get_canvas()->keyframe_list(); + //old_keyframe_list.add(keyframe); + //old_keyframe_list.sort(); + } + catch(std::exception x) + { + g_warning(x.what()); + } +} + +void +KeyframeTreeStore::remove_keyframe(Keyframe keyframe) +{ + try + { + if(1) + { + Gtk::TreeRow row(find_row(keyframe)); + dump_iterator(row,"remove_keyframe,row"); + Gtk::TreePath path(get_path(row)); + row_deleted(path); + + old_keyframe_list.erase(keyframe); + } + else + { + g_warning("KeyframeTreeStore::remove_keyframe: Keyframe not in table"); + } + } + catch(std::exception x) + { + DEBUGPOINT(); + g_warning(x.what()); + } +} + +void +KeyframeTreeStore::change_keyframe(Keyframe keyframe) +{ + try + { + Gtk::TreeRow row(find_row(keyframe)); + + unsigned int new_index(get_index_from_model_iter(row)); + unsigned int old_index(0); + synfig::KeyframeList::iterator iter; + for(old_index=0,iter=old_keyframe_list.begin();iter!=old_keyframe_list.end() && (UniqueID)*iter!=(UniqueID)keyframe;++iter,old_index++); + + if(iter!=old_keyframe_list.end() && new_index!=old_index) + { + DEBUGPOINT(); + std::vector new_order; + for(unsigned int i=0;inew_index) + { + new_order.erase(new_order.begin()+new_index); + new_order.insert(new_order.begin()+old_index,new_index); + + //new_order[old_index]= + + rows_reordered (Path(), iterator(), &new_order[0]); + } + old_keyframe_list=get_canvas()->keyframe_list(); + + row=find_row(keyframe); + } + + dump_iterator(row,"change_keyframe,row"); + row_changed(get_path(row),row); + } + catch(std::exception x) + { + DEBUGPOINT(); + g_warning(x.what()); + } +}