From 9c7119fdc29cf2bb306e8684d280cfe7ee78bd96 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Wed, 21 May 2014 18:32:42 -0700 Subject: [PATCH] Redesign how project metadata is stored in the file Remove it from the script info section and put it in its own section that isn't tracked by undo and make it not stringly typed. Removes the need for the gross hack where changes are slipped in just before saving to circumvent the undo system, cuts down on the uses of string literals to identify fields, and probably improves performance a little. --- src/ass_file.cpp | 18 +------- src/ass_file.h | 29 ++++++++---- src/ass_parser.cpp | 89 ++++++++++++++++++++++++++++++++++-- src/ass_parser.h | 4 ++ src/auto4_base.cpp | 27 ++++------- src/auto4_base.h | 6 +-- src/base_grid.cpp | 13 ++---- src/base_grid.h | 1 - src/dialog_export.cpp | 15 +++--- src/dialog_style_manager.cpp | 9 ++-- src/project.cpp | 87 ++++++++++++++++------------------- src/project.h | 9 ++-- src/selection_controller.cpp | 12 ++--- src/selection_controller.h | 1 - src/subs_controller.cpp | 4 +- src/subs_controller.h | 9 ++-- src/subtitle_format_ass.cpp | 37 +++++++++++++++ src/video_controller.cpp | 32 ++++--------- src/video_controller.h | 7 --- src/video_display.cpp | 9 ++-- src/video_display.h | 2 - 21 files changed, 240 insertions(+), 180 deletions(-) diff --git a/src/ass_file.cpp b/src/ass_file.cpp index e7598054c..8397ff132 100644 --- a/src/ass_file.cpp +++ b/src/ass_file.cpp @@ -84,6 +84,7 @@ void AssFile::swap(AssFile& from) throw() { Events.swap(from.Events); Attachments.swap(from.Attachments); Extradata.swap(from.Extradata); + std::swap(Properties, from.Properties); std::swap(next_extradata_id, from.next_extradata_id); } @@ -121,22 +122,6 @@ int AssFile::GetScriptInfoAsInt(std::string const& key) const { return atoi(GetScriptInfo(key).c_str()); } -std::string AssFile::GetUIState(std::string const& key) const { - auto value = GetScriptInfo("Aegisub " + key); - if (value.empty()) - value = GetScriptInfo(key); - return value; -} - -int AssFile::GetUIStateAsInt(std::string const& key) const { - return atoi(GetUIState(key).c_str()); -} - -void AssFile::SaveUIState(std::string const& key, std::string const& value) { - if (OPT_GET("App/Save UI State")->GetBool()) - SetScriptInfo("Aegisub " + key, value); -} - void AssFile::SetScriptInfo(std::string const& key, std::string const& value) { for (auto it = Info.begin(); it != Info.end(); ++it) { if (boost::iequals(key, it->Key())) { @@ -300,4 +285,3 @@ void AssFile::CleanExtradata() { Extradata.erase(id); } } - diff --git a/src/ass_file.h b/src/ass_file.h index 6e864c0cd..bc098c727 100644 --- a/src/ass_file.h +++ b/src/ass_file.h @@ -27,11 +27,6 @@ // // Aegisub Project http://www.aegisub.org/ -/// @file ass_file.h -/// @see ass_file.cpp -/// @ingroup subs_storage -/// - #include "ass_entry.h" #include @@ -58,6 +53,26 @@ struct AssFileCommit { AssDialogue *single_line; }; +struct ProjectProperties { + std::string automation_scripts; + std::string export_filters; + std::string export_encoding; + std::string style_storage; + std::string audio_file; + std::string video_file; + std::string timecodes_file; + std::string keyframes_file; + std::map automation_settings; + + // UI State + double video_zoom = 0.; + double ar_value = 0.; + int scroll_position = 0; + int active_row = 0; + int ar_mode = 0; + int video_position = 0; +}; + class AssFile { /// A set of changes has been committed to the file (AssFile::COMMITType) agi::signal::Signal const&> AnnounceCommit; @@ -69,6 +84,7 @@ public: EntryList Events; std::vector Attachments; AegisubExtradataMap Extradata; + ProjectProperties Properties; uint32_t next_extradata_id = 0; @@ -104,9 +120,6 @@ public: std::string GetScriptInfo(std::string const& key) const; /// Set the value of a [Script Info] key. Adds it if it doesn't exist. void SetScriptInfo(std::string const& key, std::string const& value); - std::string GetUIState(std::string const& key) const; - int GetUIStateAsInt(std::string const& key) const; - void SaveUIState(std::string const& key, std::string const& value); /// @brief Add a new extradata entry /// @param key Class identifier/owner for the extradata diff --git a/src/ass_parser.cpp b/src/ass_parser.cpp index ced410ec4..f2cb17c2e 100644 --- a/src/ass_parser.cpp +++ b/src/ass_parser.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -31,9 +32,71 @@ #include #include #include +#include +#include + +class AssParser::HeaderToProperty { + using field = boost::variant< + std::string ProjectProperties::*, + int ProjectProperties::*, + double ProjectProperties::* + >; + std::unordered_map fields; + +public: + HeaderToProperty() + : fields({ + {"Automation Scripts", &ProjectProperties::automation_scripts}, + {"Export Filters", &ProjectProperties::export_filters}, + {"Export Encoding", &ProjectProperties::export_encoding}, + {"Last Style Storage", &ProjectProperties::style_storage}, + {"Audio URI", &ProjectProperties::audio_file}, + {"Audio File", &ProjectProperties::audio_file}, + {"Video File", &ProjectProperties::video_file}, + {"Timecodes File", &ProjectProperties::timecodes_file}, + {"Keyframes File", &ProjectProperties::keyframes_file}, + {"Video Zoom Percent", &ProjectProperties::video_zoom}, + {"Scroll Position", &ProjectProperties::scroll_position}, + {"Active Line", &ProjectProperties::active_row}, + {"Video Position", &ProjectProperties::video_position}, + {"Video AR Mode", &ProjectProperties::ar_mode}, + {"Video AR Value", &ProjectProperties::ar_value}, + {"Aegisub Video Zoom Percent", &ProjectProperties::video_zoom}, + {"Aegisub Scroll Position", &ProjectProperties::scroll_position}, + {"Aegisub Active Line", &ProjectProperties::active_row}, + {"Aegisub Video Position", &ProjectProperties::video_position} + }) + { + } + + bool ProcessProperty(AssFile *target, std::string const& key, std::string const& value) { + auto it = fields.find(key); + if (it != end(fields)) { + using namespace agi::util; + struct { + using result_type = void; + ProjectProperties &obj; + std::string const& value; + void operator()(std::string ProjectProperties::*f) const { obj.*f = value; } + void operator()(int ProjectProperties::*f) const { try_parse(value, &(obj.*f)); } + void operator()(double ProjectProperties::*f) const { try_parse(value, &(obj.*f)); } + } visitor {target->Properties, value}; + boost::apply_visitor(visitor, it->second); + return true; + } + + if (boost::starts_with(key, "Automation Settings ")) { + target->Properties.automation_settings[key.substr(strlen("Automation Settings"))] = value; + return true; + } + + return false; + } +}; AssParser::AssParser(AssFile *target, int version) -: target(target) +: property_handler(new HeaderToProperty) +, target(target) , version(version) , state(&AssParser::ParseScriptInfoLine) { @@ -94,7 +157,23 @@ void AssParser::ParseScriptInfoLine(std::string const& data) { size_t pos = data.find(':'); if (pos == data.npos) return; - target->Info.push_back(*new AssInfo(data.substr(0, pos), boost::trim_left_copy(data.substr(pos + 1)))); + auto key = data.substr(0, pos); + auto value = data.substr(pos + 1); + boost::trim_left(value); + + if (!property_handler->ProcessProperty(target, key, value)) + target->Info.push_back(*new AssInfo(std::move(key), std::move(value))); +} + +void AssParser::ParseMetadataLine(std::string const& data) { + size_t pos = data.find(':'); + if (pos == data.npos) return; + + auto key = data.substr(0, pos); + auto value = data.substr(pos + 1); + boost::trim_left(value); + + property_handler->ProcessProperty(target, key, value); } void AssParser::ParseEventLine(std::string const& data) { @@ -171,12 +250,14 @@ void AssParser::AddLine(std::string const& data) { state = &AssParser::ParseEventLine; else if (low == "[script info]") state = &AssParser::ParseScriptInfoLine; + else if (low == "[aegisub project garbage]") + state = &AssParser::ParseMetadataLine; + else if (low == "[aegisub extradata]") + state = &AssParser::ParseExtradataLine; else if (low == "[graphics]") state = &AssParser::ParseGraphicsLine; else if (low == "[fonts]") state = &AssParser::ParseFontLine; - else if (low == "[aegisub extradata]") - state = &AssParser::ParseExtradataLine; else state = &AssParser::UnknownLine; return; diff --git a/src/ass_parser.h b/src/ass_parser.h index c51c20204..41396fb1f 100644 --- a/src/ass_parser.h +++ b/src/ass_parser.h @@ -20,6 +20,9 @@ class AssAttachment; class AssFile; class AssParser { + class HeaderToProperty; + std::unique_ptr property_handler; + AssFile *target; int version; std::unique_ptr attach; @@ -29,6 +32,7 @@ class AssParser { void ParseEventLine(std::string const& data); void ParseStyleLine(std::string const& data); void ParseScriptInfoLine(std::string const& data); + void ParseMetadataLine(std::string const& data); void ParseFontLine(std::string const& data); void ParseGraphicsLine(std::string const& data); void ParseExtradataLine(std::string const &data); diff --git a/src/auto4_base.cpp b/src/auto4_base.cpp index 16eb35acd..8f15129fd 100644 --- a/src/auto4_base.cpp +++ b/src/auto4_base.cpp @@ -182,14 +182,14 @@ namespace Automation4 { std::string ExportFilter::GetScriptSettingsIdentifier() { - return inline_string_encode("Automation Settings " + GetName()); + return inline_string_encode(GetName()); } wxWindow* ExportFilter::GetConfigDialogWindow(wxWindow *parent, agi::Context *c) { config_dialog = GenerateConfigDialog(parent, c); if (config_dialog) { - std::string val = c->ass->GetScriptInfo(GetScriptSettingsIdentifier()); + std::string const& val = c->ass->Properties.automation_settings[GetScriptSettingsIdentifier()]; if (!val.empty()) config_dialog->Unserialise(val); return config_dialog->CreateWindow(parent); @@ -199,11 +199,8 @@ namespace Automation4 { } void ExportFilter::LoadSettings(bool is_default, agi::Context *c) { - if (config_dialog) { - std::string val = config_dialog->Serialise(); - if (!val.empty()) - c->ass->SetScriptInfo(GetScriptSettingsIdentifier(), val); - } + if (config_dialog) + c->ass->Properties.automation_settings[GetScriptSettingsIdentifier()] = config_dialog->Serialise(); } // ProgressSink @@ -285,10 +282,6 @@ namespace Automation4 { } // ScriptManager - ScriptManager::~ScriptManager() - { - } - void ScriptManager::Add(std::unique_ptr