From 7210ea17d8cae980924a63b9955b15ce44d50374 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sun, 16 Jan 2011 07:16:40 +0000 Subject: [PATCH] Add pre-save signal to AssFile and move most of the logic in FrameMain::SaveSubtitles to slots for this signal Originally committed to SVN as r5207. --- aegisub/src/ass_file.cpp | 41 ++++----- aegisub/src/ass_file.h | 6 ++ aegisub/src/command/subtitle.cpp | 2 +- aegisub/src/frame_main.cpp | 150 +++++++++++++++---------------- aegisub/src/frame_main.h | 1 + aegisub/src/subs_grid.cpp | 11 --- aegisub/src/subs_grid.h | 2 - aegisub/src/video_context.cpp | 34 +++++-- aegisub/src/video_context.h | 6 +- 9 files changed, 126 insertions(+), 127 deletions(-) diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp index 8d3fa26c5..898c0cb1e 100644 --- a/aegisub/src/ass_file.cpp +++ b/aegisub/src/ass_file.cpp @@ -172,34 +172,23 @@ void AssFile::Load(const wxString &_filename,wxString charset,bool addToRecent) FileOpen(filename); } -void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wxString encoding) { - // Finds last dot - int i = 0; - for (i=(int)_filename.size();--i>=0;) { - if (_filename[i] == '.') break; - } - wxString extension = _filename.substr(i+1); - extension.Lower(); +void AssFile::Save(wxString filename, bool setfilename, bool addToRecent, wxString encoding) { + SubtitleFormat *writer = SubtitleFormat::GetWriter(filename); + if (!writer) + throw "Unknown file type."; - // Get writer - SubtitleFormat *writer = SubtitleFormat::GetWriter(_filename); - - // Write file - if (writer) { - writer->SetTarget(this); - writer->WriteFile(_filename,encoding); - } - - // Couldn't find a type - else throw _T("Unknown file type."); - - // Add to recent - if (addToRecent) AddToRecent(_filename); - - // Done if (setfilename) { savedCommitId = commitId; - filename = _filename; + filename = filename; + } + + FileSave(); + + writer->SetTarget(this); + writer->WriteFile(filename, encoding); + + if (addToRecent) { + AddToRecent(filename); } } @@ -776,6 +765,8 @@ AssStyle *AssFile::GetStyle(wxString name) { void AssFile::AddToRecent(wxString file) { config::mru->Add("Subtitle", STD_STR(file)); + wxFileName filepath(file); + OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filepath.GetPath())); } wxString AssFile::GetWildcardList(int mode) { diff --git a/aegisub/src/ass_file.h b/aegisub/src/ass_file.h index 4dd6b70b0..1d233cdcb 100644 --- a/aegisub/src/ass_file.h +++ b/aegisub/src/ass_file.h @@ -72,8 +72,14 @@ class AssFile { /// Last saved version of this file int savedCommitId; + /// A set of changes has been committed to the file (AssFile::CommitType) agi::signal::Signal AnnounceCommit; + /// A new file has been opened (filename) agi::signal::Signal FileOpen; + /// The file is about to be saved + /// This signal is intended for adding metadata such as video filename, + /// frame number, etc. Ideally this would all be done immediately rather + /// than waiting for a save, but that causes (more) issues with undo agi::signal::Signal<> FileSave; public: diff --git a/aegisub/src/command/subtitle.cpp b/aegisub/src/command/subtitle.cpp index ac8a9857f..28285ff9e 100644 --- a/aegisub/src/command/subtitle.cpp +++ b/aegisub/src/command/subtitle.cpp @@ -231,7 +231,7 @@ struct subtitle_new : public Command { STR_HELP("New subtitles.") void operator()(agi::Context *c) { - c->SubsGrid->LoadDefault(); + c->ass->LoadDefault(); } }; diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp index 718c25779..7a63fffd5 100644 --- a/aegisub/src/frame_main.cpp +++ b/aegisub/src/frame_main.cpp @@ -210,8 +210,6 @@ FrameMain::FrameMain (wxArrayString args) SetDropTarget(new AegisubFileDropTarget(this)); // Parse arguments - StartupLog(_T("Initialize empty file")); - SubsGrid->LoadDefault(); StartupLog(_T("Load files specified on command line")); LoadList(args); @@ -458,57 +456,44 @@ void FrameMain::LoadSubtitles(wxString filename,wxString charset) { /// @param saveas /// @param withCharset /// @return -bool FrameMain::SaveSubtitles(bool saveas,bool withCharset) { - // Try to get filename from file +bool FrameMain::SaveSubtitles(bool saveas, bool withCharset) { wxString filename; - if (saveas == false && ass->CanSave()) filename = ass->filename; + if (!saveas && ass->CanSave()) { + filename = ass->filename; + } - // Failed, ask user - if (filename.IsEmpty()) { + if (filename.empty()) { temp_context->videoContext->Stop(); wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString()); wxFileName origPath(ass->filename); - filename = wxFileSelector(_("Save subtitles file"),path,origPath.GetName() + _T(".ass"),_T("ass"),AssFile::GetWildcardList(1),wxFD_SAVE | wxFD_OVERWRITE_PROMPT,this); + filename = wxFileSelector(_("Save subtitles file"), path, origPath.GetName() + ".ass", "ass", AssFile::GetWildcardList(1), wxFD_SAVE | wxFD_OVERWRITE_PROMPT, this); + } + if (filename.empty()) { + return false; } - // Actually save - if (!filename.empty()) { - // Store path - wxFileName filepath(filename); - OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filepath.GetPath())); - - // Fix me, ghetto hack for correct relative path generation in SynchronizeProject() - ass->filename = filename; - - // Synchronize - SynchronizeProject(); - - // Get charset - wxString charset = _T(""); - if (withCharset) { - charset = wxGetSingleChoice(_("Choose charset code:"), _T("Charset"),agi::charset::GetEncodingsList(),this,-1, -1,true,250,200); - if (charset.IsEmpty()) return false; - } - - // Save - try { - ass->Save(filename,true,true,charset); - } - catch (const agi::Exception& err) { - wxMessageBox(lagi_wxString(err.GetMessage()), "Error", wxOK | wxICON_ERROR, NULL); - return false; - } - catch (const wchar_t *err) { - wxMessageBox(wxString(err), _T("Error"), wxOK | wxICON_ERROR, NULL); - return false; - } - catch (...) { - wxMessageBox(_T("Unknown error"), _T("Error"), wxOK | wxICON_ERROR, NULL); - return false; - } - return true; + wxString charset; + if (withCharset) { + charset = wxGetSingleChoice(_("Choose charset code:"), "Charset", agi::charset::GetEncodingsList(),this,-1, -1,true,250,200); + if (charset.empty()) return false; } - return false; + + try { + ass->Save(filename, true, true, charset); + } + catch (const agi::Exception& err) { + wxMessageBox(lagi_wxString(err.GetMessage()), "Error", wxOK | wxICON_ERROR, NULL); + return false; + } + catch (const wchar_t *err) { + wxMessageBox(wxString(err), _T("Error"), wxOK | wxICON_ERROR, NULL); + return false; + } + catch (...) { + wxMessageBox(_T("Unknown error"), _T("Error"), wxOK | wxICON_ERROR, NULL); + return false; + } + return true; } /// @brief Try to close subtitles @@ -627,41 +612,6 @@ void FrameMain::SynchronizeProject() { ass->SetScriptInfo(_T("Video Position"),seekpos); ass->SetScriptInfo(_T("VFR File"),MakeRelativePath(temp_context->videoContext->GetTimecodesName(),ass->filename)); ass->SetScriptInfo(_T("Keyframes File"),MakeRelativePath(temp_context->videoContext->GetKeyFramesName(),ass->filename)); - - // Store Automation script data - // Algorithm: - // 1. If script filename has Automation Base Path as a prefix, the path is relative to that (ie. "$") - // 2. Otherwise try making it relative to the ass filename - // 3. If step 2 failed, or absolut path is shorter than path relative to ass, use absolute path ("/") - // 4. Otherwise, use path relative to ass ("~") -#ifdef WITH_AUTOMATION - wxString scripts_string; - wxString autobasefn(lagi_wxString(OPT_GET("Path/Automation/Base")->GetString())); - - const std::vector &scripts = local_scripts->GetScripts(); - for (unsigned int i = 0; i < scripts.size(); i++) { - Automation4::Script *script = scripts[i]; - - if (i != 0) - scripts_string += _T("|"); - - wxString autobase_rel, assfile_rel; - wxString scriptfn(script->GetFilename()); - autobase_rel = MakeRelativePath(scriptfn, autobasefn); - assfile_rel = MakeRelativePath(scriptfn, ass->filename); - - if (autobase_rel.size() <= scriptfn.size() && autobase_rel.size() <= assfile_rel.size()) { - scriptfn = _T("$") + autobase_rel; - } else if (assfile_rel.size() <= scriptfn.size() && assfile_rel.size() <= autobase_rel.size()) { - scriptfn = _T("~") + assfile_rel; - } else { - scriptfn = _T("/") + wxFileName(scriptfn).GetFullPath(wxPATH_UNIX); - } - - scripts_string += scriptfn; - } - ass->SetScriptInfo(_T("Automation Scripts"), scripts_string); -#endif } void FrameMain::OnVideoOpen() { @@ -1404,6 +1354,46 @@ void FrameMain::OnSubtitlesOpen() { SetDisplayMode(1,1); } +void FrameMain::OnSubtitlesSave() { + UpdateTitle(); + + // Store Automation script data + // Algorithm: + // 1. If script filename has Automation Base Path as a prefix, the path is relative to that (ie. "$") + // 2. Otherwise try making it relative to the ass filename + // 3. If step 2 failed, or absolute path is shorter than path relative to ass, use absolute path ("/") + // 4. Otherwise, use path relative to ass ("~") +#ifdef WITH_AUTOMATION + wxString scripts_string; + wxString autobasefn(lagi_wxString(OPT_GET("Path/Automation/Base")->GetString())); + + const std::vector &scripts = local_scripts->GetScripts(); + for (unsigned int i = 0; i < scripts.size(); i++) { + Automation4::Script *script = scripts[i]; + + if (i != 0) + scripts_string += _T("|"); + + wxString autobase_rel, assfile_rel; + wxString scriptfn(script->GetFilename()); + autobase_rel = MakeRelativePath(scriptfn, autobasefn); + assfile_rel = MakeRelativePath(scriptfn, ass->filename); + + if (autobase_rel.size() <= scriptfn.size() && autobase_rel.size() <= assfile_rel.size()) { + scriptfn = _T("$") + autobase_rel; + } else if (assfile_rel.size() <= scriptfn.size() && assfile_rel.size() <= autobase_rel.size()) { + scriptfn = _T("~") + assfile_rel; + } else { + scriptfn = _T("/") + wxFileName(scriptfn).GetFullPath(wxPATH_UNIX); + } + + scripts_string += scriptfn; + } + ass->SetScriptInfo(_T("Automation Scripts"), scripts_string); +#endif + +} + void FrameMain::OnKeyDown(wxKeyEvent &event) { hotkey::check("Main Frame", event.GetKeyCode(), event.GetUnicodeKey(), event.GetModifiers()); } diff --git a/aegisub/src/frame_main.h b/aegisub/src/frame_main.h index 9c6319db1..ddd43527d 100644 --- a/aegisub/src/frame_main.h +++ b/aegisub/src/frame_main.h @@ -175,6 +175,7 @@ private: void OnSubtitlesCommit(); void OnSubtitlesOpen(); + void OnSubtitlesSave(); public: diff --git a/aegisub/src/subs_grid.cpp b/aegisub/src/subs_grid.cpp index 6c9850b90..2617a3a14 100644 --- a/aegisub/src/subs_grid.cpp +++ b/aegisub/src/subs_grid.cpp @@ -752,17 +752,6 @@ void SubtitlesGrid::OnAudioClip(wxCommandEvent &) { } } -/// @brief Clears grid and sets it to default -/// @param _ass -void SubtitlesGrid::LoadDefault () { - ass->LoadDefault(); - ClearMaps(); - UpdateMaps(); - - SetActiveLine(GetDialogue(0)); - SelectRow(0); -} - /// @brief Swaps two lines /// @param n1 /// @param n2 diff --git a/aegisub/src/subs_grid.h b/aegisub/src/subs_grid.h index d5b5a6bbc..eec73bbb1 100644 --- a/aegisub/src/subs_grid.h +++ b/aegisub/src/subs_grid.h @@ -109,8 +109,6 @@ public: SubtitlesGrid(FrameMain* parentFrame,wxWindow *parent, wxWindowID id, AssFile *subs, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxWANTS_CHARS, const wxString& name = wxPanelNameStr); ~SubtitlesGrid(); - void LoadDefault(); - /// @brief Jump to the start/end time of the current subtitle line /// @param start Start vs. End time void SetVideoToSubs(bool start); diff --git a/aegisub/src/video_context.cpp b/aegisub/src/video_context.cpp index 892e51c78..bf6cf1a9e 100644 --- a/aegisub/src/video_context.cpp +++ b/aegisub/src/video_context.cpp @@ -199,7 +199,8 @@ void VideoContext::SetVideo(const wxString &filename) { } provider->LoadSubtitles(grid->ass); - grid->ass->AddCommitListener(&VideoContext::SubtitlesChanged, this); + grid->ass->AddCommitListener(&VideoContext::OnSubtitlesCommit, this); + grid->ass->AddCommitListener(&VideoContext::OnSubtitlesSave, this); VideoOpen(); KeyframesOpen(keyFrames); TimecodesOpen(FPS()); @@ -222,7 +223,7 @@ void VideoContext::Reload() { } } -void VideoContext::SubtitlesChanged() { +void VideoContext::OnSubtitlesCommit() { if (!IsLoaded()) return; bool wasPlaying = isPlaying; @@ -234,6 +235,29 @@ void VideoContext::SubtitlesChanged() { if (wasPlaying) Play(); } +void VideoContext::OnSubtitlesSave() { + if (!IsLoaded()) { + grid->ass->SetScriptInfo("Video File", ""); + grid->ass->SetScriptInfo("Video Aspect Ratio", ""); + grid->ass->SetScriptInfo("Video Position", ""); + grid->ass->SetScriptInfo("VFR File", ""); + grid->ass->SetScriptInfo("Keyframes File", ""); + return; + } + + wxString ar; + if (arType == 4) + ar = wxString::Format("c%g", arValue); + else + ar = wxString::Format("%d", arType); + + grid->ass->SetScriptInfo("Video File", MakeRelativePath(videoName, grid->ass->filename)); + grid->ass->SetScriptInfo("Video Aspect Ratio", ar); + grid->ass->SetScriptInfo("Video Position", wxString::Format("%d", frame_n)); + grid->ass->SetScriptInfo("VFR File", MakeRelativePath(GetTimecodesName(), grid->ass->filename)); + grid->ass->SetScriptInfo("Keyframes File", MakeRelativePath(GetKeyFramesName(), grid->ass->filename)); +} + void VideoContext::JumpToFrame(int n) { if (!IsLoaded()) return; @@ -466,7 +490,7 @@ void VideoContext::LoadKeyframes(wxString filename) { if (kf.second != 0.) { ovrFPS = agi::vfr::Framerate(kf.second); ovrTimecodeFile.clear(); - SubtitlesChanged(); + OnSubtitlesCommit(); TimecodesOpen(ovrFPS); } config::mru->Add("Keyframes", STD_STR(filename)); @@ -503,7 +527,7 @@ void VideoContext::LoadTimecodes(wxString filename) { ovrFPS = agi::vfr::Framerate(STD_STR(filename)); ovrTimecodeFile = filename; config::mru->Add("Timecodes", STD_STR(filename)); - SubtitlesChanged(); + OnSubtitlesCommit(); TimecodesOpen(ovrFPS); } catch (const agi::acs::AcsError&) { @@ -526,7 +550,7 @@ void VideoContext::SaveTimecodes(wxString filename) { void VideoContext::CloseTimecodes() { ovrFPS = agi::vfr::Framerate(); ovrTimecodeFile.clear(); - SubtitlesChanged(); + OnSubtitlesCommit(); TimecodesOpen(videoFPS); } diff --git a/aegisub/src/video_context.h b/aegisub/src/video_context.h index f86fb5f54..757684bbb 100644 --- a/aegisub/src/video_context.h +++ b/aegisub/src/video_context.h @@ -155,6 +155,9 @@ private: void OnVideoError(VideoProviderErrorEvent const& err); void OnSubtitlesError(SubtitlesProviderErrorEvent const& err); + void OnSubtitlesCommit(); + void OnSubtitlesSave(); + public: /// DOCME SubtitlesGrid *grid; @@ -233,9 +236,6 @@ public: /// @param end Type of time void JumpToTime(int ms, agi::vfr::Time end = agi::vfr::START); - /// @brief Refresh the subtitle provider - void SubtitlesChanged(); - /// @brief Get the height and width of the current script /// @param[out] w Width /// @param[out] h Height