/* * 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 #include #include #include #include #include #include #include #include #include "SubtitleEditor.h" #include #include "utility.h" #include "SubtitleText.h" #include "Config.h" #include "MenuBar.h" #include "DialogSplit.h" #include "DialogPreferences.h" #include "DialogFind.h" #include "DialogSpellChecking.h" #include "SubtitleSystem.h" namespace SE { ISubtitleEditor* getInstance() { return SubtitleEditor::getInstance(); } } SubtitleEditor* SubtitleEditor::m_static_subtitleEditor = NULL; SubtitleEditor* SubtitleEditor::getInstance() { if(m_static_subtitleEditor == NULL) { se_debug(SE_DEBUG_APP); Glib::RefPtr refXml = Gnome::Glade::Xml::create(get_share_dir("subtitleeditor.glade")); refXml->get_widget_derived("window-subtitleeditor", m_static_subtitleEditor); } return m_static_subtitleEditor; } /* * */ SubtitleEditor::SubtitleEditor(BaseObjectType* cobject, const Glib::RefPtr& refGlade) :Gtk::Window(cobject), m_treeviewSubtitle(NULL) { se_debug(SE_DEBUG_APP); m_static_subtitleEditor = this; m_dialogFindAndReplace = NULL; m_dialogScale = NULL; m_dialogChangeFPS = NULL; m_dialogMoveSubtitles = NULL; Gtk::VBox* vbox = NULL; refGlade->get_widget("vbox-all", vbox); refGlade->get_widget("statusbar", m_statusbar); refGlade->get_widget_derived("frame-timing-system", m_timingSystem); refGlade->get_widget_derived("treeview-subtitle", m_treeviewSubtitle); MenuBar* menubar = manage(new MenuBar(*this)); vbox->pack_start(*menubar, false,false); vbox->reorder_child(*menubar, 0); se_debug_message(SE_DEBUG_APP, "load AccelMap"); // on va chercher la configuration clavier Glib::ustring path_se_accelmap = Glib::build_filename(Glib::build_filename(Glib::get_home_dir(), ".subtitleeditor"), "accelmap"); Gtk::AccelMap::load(path_se_accelmap); //config se_debug_message(SE_DEBUG_APP, "load Config"); loadCfg(); } /* * */ SubtitleEditor::~SubtitleEditor() { se_debug(SE_DEBUG_APP); se_debug_message(SE_DEBUG_APP, "Save config"); saveCfg(); se_debug_message(SE_DEBUG_APP, "save ~/.subtitleeditor"); // on sauvegarde la configuration clavier Glib::ustring path_se = Glib::build_filename(Glib::get_home_dir(), ".subtitleeditor"); Glib::ustring path_se_accelmap = Glib::build_filename(path_se, "accelmap"); Gtk::AccelMap::save(path_se_accelmap); //ask_to_save_on_exit(); se_debug_message(SE_DEBUG_APP, "Delete dialog"); delete m_dialogMoveSubtitles; delete m_dialogFindAndReplace; delete m_dialogScale; delete m_dialogChangeFPS; } /* * */ void SubtitleEditor::show() { // cela rend le lancement de l'app plus rapide s'il on connect // le model a la vue maintenant ... getSubtitleView()->set_model(getDocument()->get_subtitle_model()); Gtk::Window::show(); } /* * */ void SubtitleEditor::open_subtitle(const Glib::ustring &file) { if(getDocument()->open(file, "")) setStatusbar(_("Loaded file \"%s\" (%s, %s)"), file.c_str(), getDocument()->getFormat().c_str(), getDocument()->getCharset().c_str()); else setStatusbar(_("Error loading file \"%s\""), file.c_str()); } /* * */ void SubtitleEditor::open_movie(const Glib::ustring &uri) { getDocument()->m_uriMovie = uri; } /* * */ void SubtitleEditor::loadCfg() { Config &cfg = Config::getInstance(); bool boolean = false; //int integer = 0; int width=0, height=0; if(cfg.get_value_int("general", "width", width) && cfg.get_value_int("general", "height", height)) set_default_size(width, height); else set_default_size(600,400); if(cfg.get_value_bool("general", "maximize", boolean)) { if(boolean) maximize(); } else cfg.set_value_bool("general", "maximize", false); } /* * */ void SubtitleEditor::saveCfg() { Config &cfg = Config::getInstance(); cfg.set_value_int("general", "width", get_width()); cfg.set_value_int("general", "height", get_height()); //cfg.set_value_bool("general", "maximize", ); } /* * */ SubtitleView* SubtitleEditor::getSubtitleView() { return m_treeviewSubtitle; } /* * */ Document* SubtitleEditor::getDocument() { return &m_refDocument; } /* * */ void SubtitleEditor::setStatusbar(const char *format, ...) { int context = m_statusbar->get_context_id("txt"); //m_statusbar->remove_message(0, context); // m_statusbar->push(txt, context); va_list args; char *formatted = NULL; va_start(args, format); formatted = g_strdup_vprintf(format, args); va_end(args); m_statusbar->push(formatted, context); g_free(formatted); } /* * */ void SubtitleEditor::createMenuBar() { //MenuBar *menubar= manage(new MenuBar(*this)); //vbox.pack_start(*menubar, false,false); } /* * */ void SubtitleEditor::on_new_subtitle() { se_debug(SE_DEBUG_APP); getDocument()->clear(); setStatusbar(_("New Document")); } /* * */ void SubtitleEditor::ask_to_save_on_exit() { bool askToSaveOnExit = false; if( Config::getInstance().get_value_bool("general", "ask-to-save-on-exit", askToSaveOnExit)) { if(askToSaveOnExit) { Gtk::MessageDialog dialog(*this, _("Do you want saving the subtitle before the exit ?"), false, Gtk::MESSAGE_QUESTION , Gtk::BUTTONS_YES_NO ,true); if(dialog.run() == Gtk::RESPONSE_YES) on_save_subtitle(); } } } /* * */ void SubtitleEditor::on_quit() { se_debug(SE_DEBUG_APP); Gtk::Main::quit(); } /* * on utilise l'extention du fichier pour ouvrir selon le type */ void SubtitleEditor::on_open_subtitle() { se_debug(SE_DEBUG_APP); Glib::ustring file ; m_dialogOpenSubtitle.show(); if(m_dialogOpenSubtitle.run() == Gtk::RESPONSE_OK) { file = m_dialogOpenSubtitle.get_filename(); if(getDocument()->open(file, m_dialogOpenSubtitle.getEncoding())) setStatusbar(_("Loaded file \"%s\" (%s, %s)."), file.c_str(), getDocument()->getFormat().c_str(), getDocument()->getCharset().c_str()); else setStatusbar(_("Error loading file \"%s\"."), file.c_str()); } m_dialogOpenSubtitle.hide(); } /* * */ void SubtitleEditor::on_open_media_for_timing() { se_debug(SE_DEBUG_APP); DialogOpenMedia dialog; if(dialog.run() == Gtk::RESPONSE_OK) { Glib::ustring uri = dialog.get_uri(); dialog.hide(); if(m_timingSystem->open_media(uri)) { Signal::getInstance().setup_view("timing"); // if(m_timingSystem->get_waveform() != NULL) getDocument()->m_uriMovie = m_timingSystem->get_waveform()->uri; } } } /* * */ void SubtitleEditor::on_save_waveform() { se_debug(SE_DEBUG_APP); DialogSaveWaveform dialog; if(dialog.run() == Gtk::RESPONSE_OK) { Glib::ustring uri = dialog.get_uri(); dialog.hide(); if(uri.substr(uri.size()-3, 3) != ".wf") uri+=".wf"; if(m_timingSystem->save_waveform(uri)) setStatusbar(_("Save waveform in \"%s\""), uri.c_str()); else setStatusbar(_("Save Waveform failed")); } } /* * */ void SubtitleEditor::on_timing_play_previous_subtitle() { se_debug(SE_DEBUG_APP); Gtk::TreeIter iter = m_treeviewSubtitle->getSelected(); if(!iter) iter = getDocument()->get_subtitle_model()->getFirst(); else iter = getDocument()->get_subtitle_model()->find_previous(iter); if(iter) { m_timingSystem->play_subtitle(iter); } } /* * */ void SubtitleEditor::on_timing_play_current_subtitle() { se_debug(SE_DEBUG_APP); Gtk::TreeIter iter = m_treeviewSubtitle->getSelected(); if(!iter) iter = getDocument()->get_subtitle_model()->getFirst(); if(iter) m_timingSystem->play_subtitle(iter); } /* * */ void SubtitleEditor::on_timing_play_next_subtitle() { se_debug(SE_DEBUG_APP); Gtk::TreeIter iter = m_treeviewSubtitle->getSelected(); if(!iter) iter = getDocument()->get_subtitle_model()->getFirst(); else iter = getDocument()->get_subtitle_model()->find_next(iter); if(iter) { m_timingSystem->play_subtitle(iter); } } /* * */ void SubtitleEditor::on_timing_stop() { se_debug(SE_DEBUG_APP); m_timingSystem->stop(); } /* * */ void SubtitleEditor::on_timing_play_previous_second() { se_debug(SE_DEBUG_APP); SubtitleModifier subtitle(m_treeviewSubtitle->getSelected()); if(!subtitle) return; SubtitleTime time = subtitle.get_start(); m_timingSystem->play_subtitle(time - SubtitleTime(0,0,1,0), time); } /* * */ void SubtitleEditor::on_timing_play_first_second() { se_debug(SE_DEBUG_APP); SubtitleModifier subtitle(m_treeviewSubtitle->getSelected()); if(!subtitle) return; SubtitleTime time = subtitle.get_start(); m_timingSystem->play_subtitle(time, time + SubtitleTime(0,0,1,0)); } /* * */ void SubtitleEditor::on_timing_play_last_second() { se_debug(SE_DEBUG_APP); SubtitleModifier subtitle(m_treeviewSubtitle->getSelected()); if(!subtitle) return; SubtitleTime time = subtitle.get_end(); m_timingSystem->play_subtitle(time - SubtitleTime(0,0,1,0), time); } /* * */ void SubtitleEditor::on_timing_play_next_second() { se_debug(SE_DEBUG_APP); SubtitleModifier subtitle(m_treeviewSubtitle->getSelected()); if(!subtitle) return; SubtitleTime time = subtitle.get_end(); m_timingSystem->play_subtitle(time, time + SubtitleTime(0,0,1,0)); } /* * */ void SubtitleEditor::on_open_movie() { se_debug(SE_DEBUG_APP); m_dialogOpenMovie.show(); if(m_dialogOpenMovie.run() == Gtk::RESPONSE_OK) { Glib::ustring uri = m_dialogOpenMovie.get_uri(); getDocument()->m_uriMovie = uri; } m_dialogOpenMovie.hide(); } /* * */ void SubtitleEditor::on_save_subtitle() { se_debug(SE_DEBUG_APP); if(!getDocument()->filenameDocument.empty()) { Glib::ustring fmt = getDocument()->getFormat(); Glib::ustring filename = getDocument()->filenameDocument; Glib::ustring charset = getDocument()->getCharset(); if(getDocument()->save(filename, fmt)) setStatusbar(_("Saving file \"%s\" (%s, %s)."), filename.c_str(), fmt.c_str(), charset.c_str()); else setStatusbar(_("The file \"%s\" (%s, %s) has not been saved."), filename.c_str(), fmt.c_str(), charset.c_str()); } else { on_save_as_subtitle(); } } /* * */ void SubtitleEditor::on_save_as_subtitle() { se_debug(SE_DEBUG_APP); m_dialogSaveSubtitle.show(); if(m_dialogSaveSubtitle.run() == Gtk::RESPONSE_OK) { Glib::ustring file = m_dialogSaveSubtitle.get_filename(); Glib::ustring encoding = m_dialogSaveSubtitle.getEncoding(); Glib::ustring fmt = m_dialogSaveSubtitle.getFormat(); if(getDocument()->save(file, fmt, encoding)) setStatusbar(_("Saving file \"%s\" (%s, %s)."), file.c_str(), fmt.c_str(), encoding.c_str()); else setStatusbar(_("The file \"%s\" (%s, %s) has not been saved."), file.c_str(), fmt.c_str(), encoding.c_str()); } m_dialogSaveSubtitle.hide(); } /* * */ void SubtitleEditor::on_import_text() { se_debug(SE_DEBUG_APP); m_dialogImportText.show(); if(m_dialogImportText.run() == Gtk::RESPONSE_OK) { Glib::ustring filename = m_dialogImportText.get_filename(); getDocument()->clear(); SubtitleText text(getDocument()); if(text.open(filename, m_dialogImportText.getEncoding())) setStatusbar(_("Import text \"%s\"."), filename.c_str()); else setStatusbar(_("Import Text \"%s\" failed."), filename.c_str()); } m_dialogImportText.hide(); } /* * */ void SubtitleEditor::on_export_text() { se_debug(SE_DEBUG_APP); m_dialogExportText.show(); if(m_dialogExportText.run() == Gtk::RESPONSE_OK) { Glib::ustring filename = m_dialogExportText.get_filename(); Glib::ustring encoding = m_dialogExportText.getEncoding(); SubtitleText text(getDocument()); if(text.save(filename, encoding)) setStatusbar(_("Export text \"%s\" (%s)."), filename.c_str(), encoding.c_str()); else setStatusbar(_("Export Text \"%s\" (%s) failed."), filename.c_str(), encoding.c_str()); } m_dialogExportText.hide(); } /* * */ void SubtitleEditor::on_properties() { se_debug(SE_DEBUG_APP); DialogScriptProperties * dialog = NULL; create_dialog("dialog-script-properties", &dialog); dialog->execute(); delete dialog; } /* * */ void SubtitleEditor::on_play_movie() { se_debug(SE_DEBUG_APP); Document *doc = getDocument(); /* if(doc->filenameDocument.empty()) { se_debug_message(SE_DEBUG_APP, "filenameDocument == NULL"); setStatusbar(_("I can't play movie")); return; } */ if(doc->m_uriMovie.empty()) { se_debug_message(SE_DEBUG_APP, "m_uriMovie == NULL"); setStatusbar(_("I can't play movie. Please select a movie")); on_open_movie(); return; } Glib::ustring subtitle_name = "subtitle." + SubtitleSystem::getInstance().get_extension(doc->getFormat()); // on ecrit un fichier tmp pour les sous titres.. Glib::ustring subtitle_file = Glib::build_filename(Glib::get_tmp_dir(), subtitle_name); se_debug_message(SE_DEBUG_APP, "Save temp subtitle <%s>", subtitle_file.c_str()); getDocument()->save(subtitle_file, doc->getFormat(), "", false); se_debug_message(SE_DEBUG_APP, "Select subtitle for start movie"); long position = 0; // si il y a un subtitle de select // alors on commence a partir de ça position moins 4 sec Gtk::TreeIter iter = m_treeviewSubtitle->getSelected(); if(iter) { SubtitleColumnRecorder m_column; SubtitleTime time = SubtitleTime((*iter)[m_column.start]) - SubtitleTime(0,0,4,0); position = time.hours*3600 + time.mins*60 + time.secs; } se_debug_message(SE_DEBUG_APP, "Create cmd line"); /* * #subtitle_file * #subtitle_uri * #video_file * #video_uri * #seconds */ Config &cfg = Config::getInstance(); Glib::ustring player; if(cfg.get_value_string("video-player", "default", player)) { Glib::ustring cmd; if(cfg.get_value_string("video-player", player, cmd)) { Glib::ustring video_uri = getDocument()->m_uriMovie; Glib::ustring video_file = Glib::filename_from_uri(video_uri); Glib::ustring seconds = to_string(position); Glib::ustring subtitle_uri = Glib::filename_to_uri(subtitle_file); find_and_replace(cmd, "#video_file", video_file); find_and_replace(cmd, "#video_uri", video_uri); find_and_replace(cmd, "#subtitle_file", subtitle_file); find_and_replace(cmd, "#subtitle_uri", subtitle_uri); find_and_replace(cmd, "#seconds", seconds); std::cout << std::endl << cmd << std::endl << std::endl; se_debug_message(SE_DEBUG_APP, "exec: %s", cmd.c_str()); Glib::spawn_command_line_async(cmd); } } else { // error } } /* * */ void SubtitleEditor::on_move_subtitles() { se_debug(SE_DEBUG_APP); create_dialog("dialog-move-subtitles", &m_dialogMoveSubtitles); m_dialogMoveSubtitles->show(); m_dialogMoveSubtitles->execute(); m_dialogMoveSubtitles->hide(); } /* * */ void SubtitleEditor::on_add_100_ms() { se_debug(SE_DEBUG_APP); Glib::RefPtr selection = getSubtitleView()->get_selection(); std::vector rows = selection->get_selected_rows(); if(rows.size() > 0) { SubtitleTime time(0,0,0,100); // for all selection for(unsigned int i=0; iget_subtitle_model()->get_iter(rows[i])); // add 100 ms subtitle.set_start( subtitle.get_start() + time); subtitle.set_end( subtitle.get_end() + time); // emit signal changed Signal::getInstance().subtitle_time_changed(subtitle.get_iter()); } } } /* * */ void SubtitleEditor::on_remove_100_ms() { se_debug(SE_DEBUG_APP); Glib::RefPtr selection = getSubtitleView()->get_selection(); std::vector rows = selection->get_selected_rows(); if(rows.size() > 0) { SubtitleTime time(0,0,0,100); // for all selection for(unsigned int i=0; iget_subtitle_model()->get_iter(rows[i])); // remove 100 ms subtitle.set_start( subtitle.get_start() - time); subtitle.set_end( subtitle.get_end() - time); // emit signal changed Signal::getInstance().subtitle_time_changed(subtitle.get_iter()); } } } /* * */ void SubtitleEditor::on_add_100_ms_to_start() { se_debug(SE_DEBUG_APP); Glib::RefPtr selection = getSubtitleView()->get_selection(); std::vector rows = selection->get_selected_rows(); if(rows.size() > 0) { SubtitleTime time(0,0,0,100); // for all selection for(unsigned int i=0; iget_subtitle_model()->get_iter(rows[i])); // add 100 ms subtitle.set_start( subtitle.get_start() + time); // emit signal changed Signal::getInstance().subtitle_time_changed(subtitle.get_iter()); } } } /* * */ void SubtitleEditor::on_remove_100_ms_to_start() { se_debug(SE_DEBUG_APP); Glib::RefPtr selection = getSubtitleView()->get_selection(); std::vector rows = selection->get_selected_rows(); if(rows.size() > 0) { SubtitleTime time(0,0,0,100); // for all selection for(unsigned int i=0; iget_subtitle_model()->get_iter(rows[i])); // remove 100 ms subtitle.set_start( subtitle.get_start() - time); // emit signal changed Signal::getInstance().subtitle_time_changed(subtitle.get_iter()); } } } /* * */ void SubtitleEditor::on_add_100_ms_to_duration() { se_debug(SE_DEBUG_APP); Glib::RefPtr selection = getSubtitleView()->get_selection(); std::vector rows = selection->get_selected_rows(); if(rows.size() > 0) { SubtitleTime time(0,0,0,100); // for all selection for(unsigned int i=0; iget_subtitle_model()->get_iter(rows[i])); // remove 100 ms subtitle.set_end( subtitle.get_end() + time); // emit signal changed Signal::getInstance().subtitle_time_changed(subtitle.get_iter()); } } } /* * */ void SubtitleEditor::on_remove_100_ms_to_duration() { se_debug(SE_DEBUG_APP); Glib::RefPtr selection = getSubtitleView()->get_selection(); std::vector rows = selection->get_selected_rows(); if(rows.size() > 0) { SubtitleTime time(0,0,0,100); // for all selection for(unsigned int i=0; iget_subtitle_model()->get_iter(rows[i])); // remove 100 ms subtitle.set_end( subtitle.get_end() - time); // emit signal changed Signal::getInstance().subtitle_time_changed(subtitle.get_iter()); } } } /* * */ void SubtitleEditor::on_select_previous_subtitle() { se_debug(SE_DEBUG_APP); Gtk::TreeIter it = getSubtitleView()->getSelected(); if(it) { Gtk::TreeIter previous = getDocument()->get_subtitle_model()->find_previous(it); if(previous) getSubtitleView()->select_and_set_cursor(previous); } else { it = getDocument()->get_subtitle_model()->getFirst(); if(it) getSubtitleView()->select_and_set_cursor(it); } } /* * */ void SubtitleEditor::on_select_next_subtitle() { se_debug(SE_DEBUG_APP); Gtk::TreeIter it = getSubtitleView()->getSelected(); if(it) { Gtk::TreeIter next = getDocument()->get_subtitle_model()->find_next(it); if(next) getSubtitleView()->select_and_set_cursor(next); } else { it = getDocument()->get_subtitle_model()->getFirst(); if(it) getSubtitleView()->select_and_set_cursor(it); } } /* * */ void SubtitleEditor::on_insert_before_subtitle() { se_debug(SE_DEBUG_APP); Gtk::TreeIter select = m_treeviewSubtitle->getSelected(); if(!select) { // si le model est vide alors on crée un par defaut if(getDocument()->m_subtitleModel->getSize() == 0) { Gtk::TreeIter it = getDocument()->m_subtitleModel->append(); m_treeviewSubtitle->select_and_set_cursor(it); } return; } SubtitleTime time_start; SubtitleModifier prev( getDocument()->m_subtitleModel->find_previous(select)); if(prev) { time_start = prev.get_end(); } // on recupere le temps de depart pour s'en servir comme temps de fin SubtitleTime time_end = SubtitleModifier(*select).get_start(); Gtk::TreeIter new_iter = getDocument()->m_subtitleModel->insertBefore(select); SubtitleModifier ni(new_iter); ni.set_start(time_start); ni.set_end(time_end); getSubtitleView()->select_and_set_cursor(new_iter); } /* * */ void SubtitleEditor::on_insert_after_subtitle() { se_debug(SE_DEBUG_APP); Gtk::TreeIter iter_select = m_treeviewSubtitle->getSelected(); if(!iter_select) { // si le model est vide alors on crée un par defaut if(getDocument()->m_subtitleModel->getSize() == 0) { Gtk::TreeIter it = getDocument()->m_subtitleModel->append(); m_treeviewSubtitle->select_and_set_cursor(it); } return; } SubtitleColumnRecorder m_column; SubtitleTime time_start, time_end; time_start = SubtitleTime((*iter_select)[m_column.end]); Gtk::TreeIter next = getDocument()->m_subtitleModel->find_next(iter_select); if(next) { time_end = SubtitleTime((*next)[m_column.start]); } else // s'il n'y a pas de suivant par defaut on ajoute 2 secs time_end = time_start + SubtitleTime(0,0,2,0); Gtk::TreeIter new_iter = getDocument()->m_subtitleModel->insertAfter(iter_select); SubtitleModifier ni(new_iter); ni.set_start(time_start); ni.set_end(time_end); getSubtitleView()->select_and_set_cursor(new_iter); } /* * */ void SubtitleEditor::on_delete_subtitle() { se_debug(SE_DEBUG_APP); std::vector rows = getSubtitleView()->get_selection()->get_selected_rows(); if(rows.size() > 0) { Glib::RefPtr selection = getSubtitleView()->get_selection(); Glib::RefPtr model = getDocument()->get_subtitle_model(); while((rows = selection->get_selected_rows()).size() > 0) { model->erase(model->get_iter(rows[0])); } model->rebuild_column_num(); } } /* * */ void SubtitleEditor::on_change_fps() { se_debug(SE_DEBUG_APP); create_dialog("dialog-change-fps", &m_dialogChangeFPS); m_dialogChangeFPS->execute(); } /* * */ void SubtitleEditor::on_scale() { se_debug(SE_DEBUG_APP); create_dialog("dialog-scale", &m_dialogScale); m_dialogScale->execute(); } /* * tools */ void SubtitleEditor::on_find() { se_debug(SE_DEBUG_APP); create_dialog("dialog-find-and-replace", &m_dialogFindAndReplace); m_dialogFindAndReplace->execute(); } /* * */ void SubtitleEditor::on_find_next() { se_debug(SE_DEBUG_APP); if(m_dialogFindAndReplace == NULL) { on_find(); return; } create_dialog("dialog-find-and-replace", &m_dialogFindAndReplace); m_dialogFindAndReplace->findNext(); } /* * TODO : utility.h */ bool find_and_replace2(Glib::ustring &source, const Glib::ustring &str_find, const Glib::ustring &str_replace) { //g_return_if_fail(source.size()); //g_return_if_fail(str_find.size()); if(source.size()==0) return false; if(str_find.size()==0) return false; // on regarde si le txt rechercher ce trouve dans la source Glib::ustring::size_type pos = source.find(str_find, 0); // on regarde si il l'a trouver au moins une fois pour retrouner true if(pos == Glib::ustring::npos) return false; // tant qu'il est dans la source on le recherche while(pos != Glib::ustring::npos) { source.replace(pos, str_find.size(), str_replace); pos = source.find(str_find, pos); } return true; } /* * */ void SubtitleEditor::on_find_and_replace() { se_debug(SE_DEBUG_APP); DialogFindAndReplace *m_dialogFindAndReplace = NULL; create_dialog("dialog-find-and-replace", &m_dialogFindAndReplace); m_dialogFindAndReplace->execute(); delete m_dialogFindAndReplace; } /* * */ void SubtitleEditor::on_remove_line_nul() { se_debug(SE_DEBUG_APP); SubtitleColumnRecorder m_column; Glib::ustring text; Gtk::TreeIter iter = getDocument()->m_subtitleModel->getFirst(); for(; iter; ) { text = (*iter)[m_column.text]; if(text.size() == 0 || text == " ") { iter = getDocument()->m_subtitleModel->erase(iter); } else ++iter; } } /* * on verifie la validiter du temps */ void SubtitleEditor::on_check_time() { se_debug(SE_DEBUG_APP); SubtitleColumnRecorder m_column; Gtk::TreeIter iter = getDocument()->m_subtitleModel->getFirst(); /* Gtk::TreeIter iter; iter = m_treeviewSubtitle->getSelected(); //++iter; if(!iter || iter == getDocument()->m_subtitleModel->getLast()) iter = getDocument()->m_subtitleModel->getFirst(); */ SubtitleTime start, end; SubtitleTime prev_start, prev_end; for(; iter; ++iter) { start = SubtitleTime((*iter)[m_column.start]); end = SubtitleTime((*iter)[m_column.end]); // on verifie que end et bien > a start if(end <= start) { m_treeviewSubtitle->select_and_set_cursor(iter); setStatusbar(_("Check Time Error : start > end")); return; } // on verifie qu'il est bien > au precedant if(start < prev_start) { m_treeviewSubtitle->select_and_set_cursor(iter); setStatusbar(_("Check Time : Overlapping with previous subtitle")); return; } if(start < prev_end) { m_treeviewSubtitle->select_and_set_cursor(iter); setStatusbar(_("Check Time : Overlapping with previous subtitle")); return; } prev_start = start; prev_end = end; } setStatusbar(_("Check Time OK!")); } /* * */ void SubtitleEditor::on_spell_check() { se_debug(SE_DEBUG_APP); #ifdef HAVE_ENCHANT_SUPPORT DialogSpellChecking *spell = NULL; create_dialog("dialog-spell-checking", &spell); spell->execute(); delete spell; #endif//HAVE_ENCHANT_SUPPORT } /* * */ void SubtitleEditor::on_set_all_end_time() { se_debug(SE_DEBUG_APP); m_dialogSetAllEndTime.show(); if(m_dialogSetAllEndTime.run()==Gtk::RESPONSE_OK) { SubtitleTime time = m_dialogSetAllEndTime.get_time(); SubtitleColumnRecorder m_column; Gtk::TreeIter it = getDocument()->m_subtitleModel->getFirst(); if(m_dialogSetAllEndTime.get_type() == DialogSetAllEndTime::ADD) { for(; it; ++it) { SubtitleModifier subtitle(it); SubtitleTime it_time_end = subtitle.get_end() + time; // verification il n'est pas trop long avec le prochain st Gtk::TreeIter it_next = getDocument()->m_subtitleModel->find_next(it); if(it_next) { SubtitleTime next_time_start = SubtitleTime((*it_next)[m_column.start]); if(it_time_end > next_time_start) { it_time_end = next_time_start; } } // mise a jour subtitle.set_end(it_time_end); } } else // SET { for(; it; ++it) { SubtitleModifier subtitle(it); SubtitleTime it_time_end = subtitle.get_start(); it_time_end = it_time_end + time; // verification il n'est pas trop long avec le prochain st Gtk::TreeIter it_next = getDocument()->m_subtitleModel->find_next(it); if(it_next) { SubtitleTime next_time_start = SubtitleTime((*it_next)[m_column.start]); if(it_time_end > next_time_start) { it_time_end = next_time_start; } } // mise a jour subtitle.set_end(it_time_end); } } } m_dialogSetAllEndTime.hide(); } /* * */ void SubtitleEditor::on_about() { se_debug(SE_DEBUG_APP); DialogAbout about; about.run(); } /* * */ void SubtitleEditor::on_style_editor() { se_debug(SE_DEBUG_APP); DialogStyleEditor* m_dialogStyleEditor = NULL; create_dialog("dialog-style-editor", &m_dialogStyleEditor); m_dialogStyleEditor->execute(); delete m_dialogStyleEditor; } /* * */ void SubtitleEditor::on_preferences() { se_debug(SE_DEBUG_APP); DialogPreferences* m_dialogPreferences = NULL; create_dialog("dialog-preferences", &m_dialogPreferences); m_dialogPreferences->run(); delete m_dialogPreferences; } /* * */ void SubtitleEditor::on_apply_translation() { se_debug(SE_DEBUG_APP); Gtk::TreeIter iter = getDocument()->m_subtitleModel->getFirst(); for(; iter; ++iter) { SubtitleModifier subtitle(iter); Glib::ustring translation = subtitle.get_translation(); if(!translation.empty()) subtitle.set_text(translation); } setStatusbar(_("The translation was applied.")); } /* * */ void SubtitleEditor::on_split() { se_debug(SE_DEBUG_APP); DialogSplit* m_dialogSplit= NULL; create_dialog("dialog-split", &m_dialogSplit); m_dialogSplit->execute(); delete m_dialogSplit; } void SubtitleEditor::on_joint() { se_debug(SE_DEBUG_APP); DialogOpenSubtitle dialog; if(dialog.run() == Gtk::RESPONSE_OK) { Glib::ustring file = dialog.get_filename(); Glib::ustring charset = dialog.getEncoding(); if(getDocument()->open(file, charset, false)) { setStatusbar(_("Joint \"%s\" (%s) in this document."), file.c_str(), getDocument()->getCharset().c_str()); } else { setStatusbar(_("Joint: Error loading file \"%s\" (%s)."), file.c_str(), charset.c_str()); } getDocument()->get_subtitle_model()->rebuild_column_num(); } } /* * */ template bool SubtitleEditor::create_dialog(const Glib::ustring &name, T **dialog) { se_debug_message(SE_DEBUG_APP, "create %s", name.c_str()); if(*dialog == NULL) { // TODO : try catch... Glib::RefPtr refXml = Gnome::Glade::Xml::create(get_share_dir(name + ".glade")); refXml->get_widget_derived(name, *dialog); return true; } return true; } /* * */ void SubtitleEditor::on_move_subtitle_text_forward() { se_debug(SE_DEBUG_APP); Gtk::TreeIter it = getSubtitleView()->getSelected(); if(it) { /* // recupere le texte des sous-titres à partir de la selection std::vector strings; for(Gtk::TreeIter it2=it; it2; ++it2) strings.push_back(SubtitleModifier(it2).get_text()); // on avance SubtitleModifier(it).set_text(""); ++it; // on applique les modifications avec un decalage for(unsigned int i=0; it; ++it, ++i) { SubtitleModifier(it).set_text(strings[i]); } // ajoute le derniers Gtk::TreeIter last = getDocument()->get_subtitle_model()->append(); SubtitleModifier last_iter(last).set_text(strings.back()); */ } } /* * */ void SubtitleEditor::on_move_subtitle_text_backward() { se_debug(SE_DEBUG_APP); }