/* * subtitle editor * * http://kitone.free.fr/subtitleeditor/ * * Copyright @ 2005-2006, kitone * * Contact: kitone at free dot fr * * This program 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 program 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. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * See gpl.txt for more information regarding the GNU General Public License. * * * \file * \brief * \author kitone (kitone at free dot fr) */ #include "SubtitleModel.h" #include "SubtitleModifier.h" /* * */ SubtitleModel::SubtitleModel() { set_column_types(m_column); } /* * */ Gtk::TreeIter SubtitleModel::append() { Gtk::TreeIter it = Gtk::ListStore::append(); init(it); (*it)[m_column.num] = getSize(); return it; } /* * insert sub avant iter et retourne l'iter de sub * et declale tout les autres (sub.num) */ Gtk::TreeIter SubtitleModel::insertBefore(Gtk::TreeIter &iter) { Gtk::TreeIter res = insert(iter); init(res); // on recupere ça place (*res)[m_column.num] = (unsigned int)(*iter)[m_column.num]; for(; iter; ++iter) { (*iter)[m_column.num] = (*iter)[m_column.num] + 1; } return res; } /* * insert sub apres iter et retourne l'iter de sub * et declale tout les autres (sub.num) */ Gtk::TreeIter SubtitleModel::insertAfter(Gtk::TreeIter &iter) { Gtk::TreeIter res = insert_after(iter); init(res); // on recupere ça place (*res)[m_column.num] = (*iter)[m_column.num] +1; ++iter; // le nouveau ajouter ++iter; // le suivant on commence a partir de lui for(; iter; ++iter) { (*iter)[m_column.num] = (*iter)[m_column.num] + 1; } return res; } /* * efface un subtitle, on init les suivants avec le bon num */ void SubtitleModel::remove(Gtk::TreeIter &it) { Gtk::TreeIter iter = erase(it); for(; iter; ++iter) { (*iter)[m_column.num] = (*iter)[m_column.num] - 1; } } void SubtitleModel::remove(unsigned int start, unsigned int end) { g_return_if_fail(end > start); Gtk::TreeIter a = find(start); Gtk::TreeIter b = find(end); g_return_if_fail(a); //g_return_if_fail(b); if(b) { ++b; for( ; a!=b; ) { a = erase(a); } // on decale num des suivants si il y en a if(b) { int diff = end - start +1; for(; b; ++b) { (*b)[m_column.num] = (*b)[m_column.num] - diff; } } } else { for(; a; ) { a = erase(a); } } } /* * init l'iter a 0 */ void SubtitleModel::init(Gtk::TreeIter &iter) { SubtitleTime time = SubtitleTime::null(); (*iter)[m_column.num] = 0; (*iter)[m_column.start] = time.str(); (*iter)[m_column.end] = time.str(); (*iter)[m_column.duration] = time.str(); (*iter)[m_column.text] = ""; // (*iter)[m_column.layer] = "0"; (*iter)[m_column.style] = "Default"; //(*iter)[m_column.name] = ""; // (*iter)[m_column.marginL] = "0"; (*iter)[m_column.marginR] = "0"; (*iter)[m_column.marginV] = "0"; //(*iter)[m_column.effect] = ""; //(*iter)[m_column.translation] = ""; // (*iter)[m_column.characters_per_line] = "0"; } /* * retourne le premier element de la list * ou un iterator invalide */ Gtk::TreeIter SubtitleModel::getFirst() { if(getSize() > 0) { Gtk::TreeNodeChildren rows = children(); return rows.begin(); } Gtk::TreeIter nul; return nul; } /* * retourne le dernier element de la list * ou un iterator invalide */ Gtk::TreeIter SubtitleModel::getLast() { if(getSize() > 0) { Gtk::TreeNodeChildren rows = children(); return rows.end(); } Gtk::TreeIter nul; return nul; } /* * retourne le nombre d'element dans la list */ unsigned int SubtitleModel::getSize() { //Gtk::TreeNodeChildren rows = children(); return children().size(); } /* * FONCTION DE RECHERCHE **************************************************** */ /* * recherche un subtitle grace a son numero */ Gtk::TreeIter SubtitleModel::find(unsigned int num) { Gtk::TreeNodeChildren rows = children(); for(Gtk::TreeIter it = rows.begin(); it; ++it) { if((*it)[m_column.num] == num) return it; } Gtk::TreeIter nul; return nul; } /* * recherche un subtitle grace au temps * si time est compris entre start et end */ Gtk::TreeIter SubtitleModel::find(const SubtitleTime &time) { Gtk::TreeNodeChildren rows = children(); for(Gtk::TreeIter it = rows.begin(); it; ++it) { if(SubtitleTime((*it)[m_column.start]) >= time && SubtitleTime((*it)[m_column.end]) <= time) return it; } Gtk::TreeIter nul; return nul; } /* * recherche un soustitre par rapport au temps * mais seulement si il est compris ou superieur au temps */ Gtk::TreeIter SubtitleModel::find_in_or_after(const SubtitleTime &time) { Gtk::TreeNodeChildren rows = children(); for(Gtk::TreeIter it = rows.begin(); it; ++it) { SubtitleTime s((*it)[m_column.start]); SubtitleTime e((*it)[m_column.end]); if(s >= time) return it; } Gtk::TreeIter nul; return nul; } /* * hack ? */ bool compare_str(const Glib::ustring &src, const Glib::ustring &txt) { unsigned int size = src.size(); if(txt.size() < size) { for(unsigned int i=0; i<=size-txt.size(); ++i) { if(src.substr(i, txt.size()) == txt) { return true; } } } return false; } /* * recherche a partir de start (+1) dans le text des subtitles */ Gtk::TreeIter SubtitleModel::find_text( Gtk::TreeIter &start, const Glib::ustring &text) { if(start) { Glib::ustring it_text; Gtk::TreeIter it=start; ++it; for(; it; ++it) { it_text = (*it)[m_column.text]; if(compare_str(it_text, text)) return it; } } Gtk::TreeIter nul; return nul; } /* * recherche l'iterator precedant iter */ Gtk::TreeIter SubtitleModel::find_previous(Gtk::TreeIter &iter) { Gtk::TreeIter res; Gtk::TreeNodeChildren rows = children(); for(Gtk::TreeIter it = rows.begin(); it; ++it) { if(it == iter) return res; res = it; } return res; } /* * recherche l'iterator suivant iter * (c'est pour la forme dans notre cas un simple ++iter donne la solution) */ Gtk::TreeIter SubtitleModel::find_next(Gtk::TreeIter &iter) { Gtk::TreeIter res = iter; ++res; return res; } /* * FONCTION D'EDITION ****************************************************** */ /* * deplace tous les sous titres entre start et end de msecs. */ void SubtitleModel::move_in(unsigned int start, unsigned int end, unsigned int msecs) { Gtk::TreeNodeChildren rows = children(); for(Gtk::TreeIter it = rows.begin(); it; ++it) { unsigned int num = (*it)[m_column.num]; if(num >= start && num <= end) { SubtitleModifier subtitle(it); SubtitleTime time_start = subtitle.get_start(); SubtitleTime time_end = subtitle.get_end(); time_start.move(msecs); time_end.move(msecs); subtitle.set_start(time_start); subtitle.set_end(time_end); } } } /* * deplace tous les sous titres entre start et end de msecs. */ void SubtitleModel::move_all(unsigned int start, unsigned int msecs) { Gtk::TreeNodeChildren rows = children(); for(Gtk::TreeIter it = rows.begin(); it; ++it) { unsigned int num = (*it)[m_column.num]; if(num >= start) { SubtitleModifier subtitle(it); SubtitleTime time_start = subtitle.get_start(); SubtitleTime time_end = subtitle.get_end(); time_start.move(msecs); time_end.move(msecs); subtitle.set_start(time_start); subtitle.set_end(time_end); } } } /* * fait une copy de src dans this */ void SubtitleModel::copy(Glib::RefPtr src) { g_return_if_fail(src); #define SET(col, cast) (*new_it)[m_column.col] = (cast)(*it)[m_column.col] Gtk::TreeNodeChildren rows = src->children(); for(Gtk::TreeIter it = rows.begin(); it; ++it) { Gtk::TreeIter new_it = Gtk::ListStore::append(); SET(num, unsigned int); SET(layer, Glib::ustring); SET(start, Glib::ustring); SET(end, Glib::ustring); SET(duration, Glib::ustring); SET(style, Glib::ustring); SET(name, Glib::ustring); SET(marginL, Glib::ustring); SET(marginR, Glib::ustring); SET(marginV, Glib::ustring); SET(effect, Glib::ustring); SET(text, Glib::ustring); SET(translation, Glib::ustring); SET(characters_per_line, Glib::ustring); } #undef SET } /* * check la colonne num pour init de [1,size] */ void SubtitleModel::rebuild_column_num() { unsigned int id=1; Gtk::TreeNodeChildren rows = children(); for(Gtk::TreeIter it = rows.begin(); it; ++it, ++id) { (*it)[m_column.num] = id; } }