From b073b7d28dc7a5020ecdafab36379386986f48e4 Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Fri, 14 Mar 2008 02:02:48 +0000 Subject: [PATCH] Gorgonsub is now capable of doing some simple manipulation (i.e. line insertion). Originally committed to SVN as r2048. --- aegilib/aegilib.vcproj | 14 ++- aegilib/include/aegilib/action.h | 11 ++- .../aegilib/{manipulator.h => actionlist.h} | 22 +++-- aegilib/include/aegilib/controller.h | 66 +++++++++++++ aegilib/include/aegilib/exception.h | 5 +- aegilib/include/aegilib/format.h | 4 + aegilib/include/aegilib/format_handler.h | 13 +++ aegilib/include/aegilib/gorgonsub.h | 2 +- aegilib/include/aegilib/model.h | 42 +++++---- aegilib/include/aegilib/section.h | 2 +- aegilib/include/aegilib/section_entry.h | 2 + aegilib/src/action.cpp | 3 +- .../src/{manipulator.cpp => actionlist.cpp} | 37 ++++++-- aegilib/src/controller.cpp | 93 +++++++++++++++++++ aegilib/src/exception.cpp | 3 +- aegilib/src/formats/format_ass.cpp | 14 +-- aegilib/src/formats/format_ass.h | 91 +++++++++--------- aegilib/src/formats/format_ass_style.cpp | 19 +++- aegilib/src/model.cpp | 82 ++++++++-------- aegilib/src/section.cpp | 5 +- aegilib/test/src/main.cpp | 19 +++- 21 files changed, 404 insertions(+), 145 deletions(-) rename aegilib/include/aegilib/{manipulator.h => actionlist.h} (83%) rename aegilib/src/{manipulator.cpp => actionlist.cpp} (75%) create mode 100644 aegilib/src/controller.cpp diff --git a/aegilib/aegilib.vcproj b/aegilib/aegilib.vcproj index e61b48e82..5a96dd816 100644 --- a/aegilib/aegilib.vcproj +++ b/aegilib/aegilib.vcproj @@ -160,6 +160,10 @@ RelativePath=".\include\aegilib\action.h" > + + @@ -196,10 +200,6 @@ RelativePath=".\include\aegilib\gorgontime.h" > - - @@ -253,7 +253,11 @@ > + + data; + String section; int par1; public: Action(); - Action(ActionType type,shared_ptr data,int par1); + Action(ActionType type,shared_ptr data,const String §ion,int par1); - ActionType GetType() { return type; } - shared_ptr GetData() { return data; } - int GetLineNumber() { return par1; } + ActionType GetType() const { return type; } + shared_ptr GetData() const { return data; } + int GetLineNumber() const { return par1; } + String GetSection() const { return section; } }; }; diff --git a/aegilib/include/aegilib/manipulator.h b/aegilib/include/aegilib/actionlist.h similarity index 83% rename from aegilib/include/aegilib/manipulator.h rename to aegilib/include/aegilib/actionlist.h index 26e5d5c90..f0aa27e38 100644 --- a/aegilib/include/aegilib/manipulator.h +++ b/aegilib/include/aegilib/actionlist.h @@ -37,13 +37,17 @@ #include #include "action.h" #include "gorgonstring.h" +#include "section_entry.h" namespace Gorgonsub { - // Manipulator class - class Manipulator { + // Prototypes + class Controller; + + // ActionList class + class ActionList { friend class Model; - friend class std::list; + friend class Controller; private: String actionName; @@ -51,14 +55,18 @@ namespace Gorgonsub { std::list actions; bool valid; - Manipulator(); + ActionList(); + ActionList(Model &model,const String actionName); + void Start(const String actionName); public: - Manipulator(Model &model,String actionName); - ~Manipulator(); + ~ActionList(); void AddAction(const Action &action); - void Flush(); + void Finish(); + + void InsertLine(SectionEntryPtr line,int position=-1,const String section=L""); }; + typedef shared_ptr ActionListPtr; }; diff --git a/aegilib/include/aegilib/controller.h b/aegilib/include/aegilib/controller.h index e69de29bb..c955e94db 100644 --- a/aegilib/include/aegilib/controller.h +++ b/aegilib/include/aegilib/controller.h @@ -0,0 +1,66 @@ +// Copyright (c) 2008, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB/GORGONSUB +// +// Website: http://www.aegisub.net +// Contact: mailto:amz@aegisub.net +// + +#pragma once +#include "gorgonstring.h" +#include "tr1.h" +#include "format.h" + +namespace Gorgonsub { + + // Prototypes + class Model; + class ActionList; + typedef shared_ptr ActionListPtr; + + // Controller class + class Controller { + private: + Model &model; + + public: + Controller (Model &model); + ActionListPtr CreateActionList(const String title); + + void LoadFile(const String filename,const String encoding=L""); + void SaveFile(const String filename,const String encoding=L"UTF-8"); + + SectionEntryDialoguePtr CreateDialogue(); + SectionEntryStylePtr CreateStyle(); + + const FormatPtr GetFormat() const; + }; + +}; diff --git a/aegilib/include/aegilib/exception.h b/aegilib/include/aegilib/exception.h index 146d4c229..de7ce948b 100644 --- a/aegilib/include/aegilib/exception.h +++ b/aegilib/include/aegilib/exception.h @@ -46,12 +46,13 @@ namespace Gorgonsub { enum ExceptionList { Unknown, No_Format_Handler, - Invalid_Manipulator, + Invalid_ActionList, Section_Already_Exists, Unknown_Format, Parse_Error, Unsupported_Format_Feature, - Invalid_Token + Invalid_Token, + TODO }; Exception(ExceptionList code); diff --git a/aegilib/include/aegilib/format.h b/aegilib/include/aegilib/format.h index 27621373e..941b93545 100644 --- a/aegilib/include/aegilib/format.h +++ b/aegilib/include/aegilib/format.h @@ -36,6 +36,7 @@ #pragma once #include "gorgonstring.h" #include "tr1.h" +#include "section_entry.h" namespace Gorgonsub { // Prototypes @@ -65,6 +66,9 @@ namespace Gorgonsub { virtual int GetTimingPrecision() const { return 10; } // In milliseconds virtual int GetMaxTime() const { return 36000000-10; } // In milliseconds, default 9h 59min 59.99s + + virtual SectionEntryDialoguePtr CreateDialogue() const = 0; + virtual SectionEntryStylePtr CreateStyle() const = 0; }; typedef shared_ptr FormatPtr; diff --git a/aegilib/include/aegilib/format_handler.h b/aegilib/include/aegilib/format_handler.h index 0eabb20f5..a7e839a65 100644 --- a/aegilib/include/aegilib/format_handler.h +++ b/aegilib/include/aegilib/format_handler.h @@ -35,16 +35,29 @@ #pragma once #include "gorgonstring.h" +#include "model.h" #include "tr1.h" namespace Gorgonsub { // Format handler interface class FormatHandler { + private: + Model &model; + protected: virtual ~FormatHandler() {} + Model &GetModel() const { return model; } + + void AddSection(String name) { model.AddSection(name); } + SectionPtr GetSection(String name) const { return model.GetSection(name); } + SectionPtr GetSectionByIndex(size_t index) const { return model.GetSectionByIndex(index); } + size_t GetSectionCount() const { return model.GetSectionCount(); } + public: + FormatHandler(Model &_model) : model(_model) {} + virtual void Load(wxInputStream &file,const String encoding) = 0; virtual void Save(wxOutputStream &file,const String encoding) = 0; }; diff --git a/aegilib/include/aegilib/gorgonsub.h b/aegilib/include/aegilib/gorgonsub.h index d7f8900e4..49f4c40d5 100644 --- a/aegilib/include/aegilib/gorgonsub.h +++ b/aegilib/include/aegilib/gorgonsub.h @@ -44,7 +44,7 @@ #include "format.h" #include "format_handler.h" #include "format_manager.h" -#include "manipulator.h" +#include "actionlist.h" #include "section.h" #include "section_entry_dialogue.h" #include "section_entry_style.h" diff --git a/aegilib/include/aegilib/model.h b/aegilib/include/aegilib/model.h index 8166d1d8a..acdce1b96 100644 --- a/aegilib/include/aegilib/model.h +++ b/aegilib/include/aegilib/model.h @@ -37,7 +37,7 @@ #include #include #include -#include "manipulator.h" +#include "actionlist.h" #include "section.h" namespace Gorgonsub { @@ -51,9 +51,12 @@ namespace Gorgonsub { // Model class // Stores the subtitle data class Model { - friend class Manipulator; + friend class FormatHandler; + friend class ActionList; + friend class Controller; + typedef std::list ViewList; - typedef std::list ActionStack; + typedef std::list ActionStack; typedef shared_ptr FormatPtr; private: @@ -62,30 +65,31 @@ namespace Gorgonsub { ActionStack redoStack; ViewList listeners; bool readOnly; + FormatPtr format; - void ProcessActionList(const Manipulator &actionList,bool insertInStack); - Manipulator CreateAntiManipulator(const Manipulator &manipulator); + void ProcessActionList(const ActionList &actionList,bool insertInStack); + void DoAction(const Action &action); + ActionListPtr CreateAntiActionList(const ActionListPtr &manipulator); + + bool CanUndo(const String owner=L"") const; + bool CanRedo(const String owner=L"") const; + bool Undo(const String owner=L""); + bool Redo(const String owner=L""); + void DispatchNotifications(const Notification ¬ification) const; - public: - const Format& GetFormat() const; - void AddListener(ViewPtr listener); - - void Clear(); - void Load(wxInputStream &input,const FormatPtr format=FormatPtr(),const String encoding=L""); - void Save(wxOutputStream &output,const FormatPtr format=FormatPtr(),const String encoding=L"UTF-8"); - void LoadFile(const String filename,const String encoding=L""); - void SaveFile(const String filename,const String encoding=L"UTF-8"); - void AddSection(String name); SectionPtr GetSection(String name) const; SectionPtr GetSectionByIndex(size_t index) const; size_t GetSectionCount() const; - bool CanUndo(const String owner=L"") const; - bool CanRedo(const String owner=L"") const; - bool Undo(const String owner=L""); - bool Redo(const String owner=L""); + void Clear(); + void Load(wxInputStream &input,const FormatPtr format=FormatPtr(),const String encoding=L""); + void Save(wxOutputStream &output,const FormatPtr format=FormatPtr(),const String encoding=L"UTF-8"); + + public: + const FormatPtr GetFormat() const { return format; } + void AddListener(ViewPtr listener); }; }; diff --git a/aegilib/include/aegilib/section.h b/aegilib/include/aegilib/section.h index 49323e5a8..cfb41f6e7 100644 --- a/aegilib/include/aegilib/section.h +++ b/aegilib/include/aegilib/section.h @@ -66,7 +66,7 @@ namespace Gorgonsub { String GetPropertyName(size_t index) const; // Entries - void AddEntry(SectionEntryPtr entry); + void AddEntry(SectionEntryPtr entry,int pos=-1); void RemoveEntryByIndex(size_t index); void RemoveEntry(SectionEntryPtr entry); SectionEntryConstPtr GetEntry(size_t index) const; diff --git a/aegilib/include/aegilib/section_entry.h b/aegilib/include/aegilib/section_entry.h index 568db9fb4..d1a348df9 100644 --- a/aegilib/include/aegilib/section_entry.h +++ b/aegilib/include/aegilib/section_entry.h @@ -76,6 +76,8 @@ namespace Gorgonsub { public: virtual SectionEntryType GetType() const =0; + virtual String GetDefaultGroup() const =0; + static const SectionEntryPlainPtr GetAsPlain(const SectionEntryPtr &ptr); static const SectionEntryDialoguePtr GetAsDialogue(const SectionEntryPtr &ptr); static const SectionEntryDialogueConstPtr GetAsDialogue(const SectionEntryConstPtr &ptr); diff --git a/aegilib/src/action.cpp b/aegilib/src/action.cpp index 0a590af85..ae50dc701 100644 --- a/aegilib/src/action.cpp +++ b/aegilib/src/action.cpp @@ -46,9 +46,10 @@ Action::Action() ////////////////////////////// // Initialization constructor -Action::Action(ActionType _type,shared_ptr _data,int _par1) +Action::Action(ActionType _type,shared_ptr _data,const String &_section,int _par1) { type = _type; data = _data; par1 = _par1; + section = _section; } diff --git a/aegilib/src/manipulator.cpp b/aegilib/src/actionlist.cpp similarity index 75% rename from aegilib/src/manipulator.cpp rename to aegilib/src/actionlist.cpp index e023f0f95..7384b21ad 100644 --- a/aegilib/src/manipulator.cpp +++ b/aegilib/src/actionlist.cpp @@ -39,34 +39,42 @@ using namespace Gorgonsub; /////////////// // Constructor -Manipulator::Manipulator(Model &_model,String _actionName) +ActionList::ActionList(Model &_model,String _actionName) : model(_model) { - actionName = _actionName; - valid = true; + Start(_actionName); } ////////////// // Destructor -Manipulator::~Manipulator() +ActionList::~ActionList() { - Flush(); } ////////////////////////////// // Add an action to the queue -void Manipulator::AddAction(const Action &action) +void ActionList::AddAction(const Action &action) { - if (!valid) throw Exception(Exception::Invalid_Manipulator); + if (!valid) throw Exception(Exception::Invalid_ActionList); actions.push_back(action); } -//////////////////////////////// -// Flush the queue to the model -void Manipulator::Flush() +///////////////////////////// +// Starts performing actions +void ActionList::Start(const String name) +{ + if (valid) Finish(); + actionName = name; + valid = true; +} + + +//////////////////////// +// Ends the action list +void ActionList::Finish() { if (valid) { model.ProcessActionList(*this,false); @@ -74,3 +82,12 @@ void Manipulator::Flush() valid = false; } } + + +////////////////////////////////// +// Create an "insert line" action +void ActionList::InsertLine(SectionEntryPtr line,int position,const String section) +{ + Action action = Action(ACTION_INSERT,line,section,position); + AddAction(action); +} diff --git a/aegilib/src/controller.cpp b/aegilib/src/controller.cpp new file mode 100644 index 000000000..10dc5c423 --- /dev/null +++ b/aegilib/src/controller.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2008, Rodrigo Braz Monteiro +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB/GORGONSUB +// +// Website: http://www.aegisub.net +// Contact: mailto:amz@aegisub.net +// + +#include "Gorgonsub.h" +using namespace Gorgonsub; + + +/////////////// +// Constructor +Controller::Controller(Model &_model) +: model(_model) +{ +} + + +///////////////////////// +// Create an action list +ActionListPtr Controller::CreateActionList(const String title) +{ + return ActionListPtr (new ActionList(model,title)); +} + + +/////////////// +// Load a file +void Controller::LoadFile(const String filename,const String encoding) +{ + const FormatPtr handler = FormatManager::GetFormatFromFilename(filename,true); + wxFileInputStream stream(filename); + model.Load(stream,handler,encoding); +} + + +/////////////// +// Save a file +void Controller::SaveFile(const String filename,const String encoding) +{ + const FormatPtr handler = FormatManager::GetFormatFromFilename(filename,true); + wxFileOutputStream stream(filename); + model.Save(stream,handler,encoding); +} + + +////////////// +// Get format +const FormatPtr Controller::GetFormat() const +{ + return model.GetFormat(); +} + + +////////////////// +// Create entries +SectionEntryDialoguePtr Controller::CreateDialogue() +{ + return GetFormat()->CreateDialogue(); +} +SectionEntryStylePtr Controller::CreateStyle() +{ + return GetFormat()->CreateStyle(); +} diff --git a/aegilib/src/exception.cpp b/aegilib/src/exception.cpp index bc7542aab..fe2125db5 100644 --- a/aegilib/src/exception.cpp +++ b/aegilib/src/exception.cpp @@ -53,12 +53,13 @@ String Exception::GetMessage(int code) switch (code) { case Unknown: return L"Unknown."; case No_Format_Handler: return L"Could not find a suitable format handler."; - case Invalid_Manipulator: return L"Invalid manipulator."; + case Invalid_ActionList: return L"Invalid manipulator."; case Section_Already_Exists: return L"The specified section already exists in this model."; case Unknown_Format: return L"The specified file format is unknown."; case Parse_Error: return L"Parse error."; case Unsupported_Format_Feature: return L"This feature is not supported by this format."; case Invalid_Token: return L"Invalid type for this token."; + case TODO: return L"TODO"; } return L"Invalid code."; } diff --git a/aegilib/src/formats/format_ass.cpp b/aegilib/src/formats/format_ass.cpp index 0921591a4..92b5590d0 100644 --- a/aegilib/src/formats/format_ass.cpp +++ b/aegilib/src/formats/format_ass.cpp @@ -89,7 +89,7 @@ StringArray FormatASS2::GetWriteExtensions() const /////////////// // Constructor FormatHandlerASS::FormatHandlerASS(Model &_model,int version) -: model(_model), formatVersion(version) +: FormatHandler(_model), formatVersion(version) { } @@ -125,10 +125,10 @@ void FormatHandlerASS::Load(wxInputStream &file,const String encoding) ProcessGroup(cur,curGroup,version); // Insert group if it doesn't already exist - if (prevGroup != curGroup) section = model.GetSection(curGroup); + if (prevGroup != curGroup) section = GetSection(curGroup); if (!section) { - model.AddSection(curGroup); - section = model.GetSection(curGroup); + AddSection(curGroup); + section = GetSection(curGroup); } // Skip [] lines @@ -157,9 +157,9 @@ void FormatHandlerASS::Save(wxOutputStream &file,const String encoding) sections.Add(L"Graphics"); // Look for remaining sections - size_t totalSections = model.GetSectionCount(); + size_t totalSections = GetSectionCount(); for (size_t i=0;iGetName(); + String name = GetSectionByIndex(i)->GetName(); if (sections.Index(name,false,false) == wxNOT_FOUND) sections.Add(name); } @@ -167,7 +167,7 @@ void FormatHandlerASS::Save(wxOutputStream &file,const String encoding) size_t len = sections.size(); for (size_t i=0;i margin; + array margin; int layer; bool isComment; @@ -137,6 +96,7 @@ namespace Gorgonsub { bool HasTime() const { return true; } bool HasStyle() const { return true; } bool HasMargins() const { return true; } + String GetDefaultGroup() const { return L"Events"; } // Read accessors const String& GetText() const { return text; } @@ -166,6 +126,7 @@ namespace Gorgonsub { String name; String font; float fontSize; + int formatVersion; array colour; // 0 = Primary, 1 = Secondary, 2 = Tertiary, 3 = Outline, 4 = Shadow array margin; @@ -203,6 +164,8 @@ namespace Gorgonsub { float GetFontSize() const { return fontSize; } Colour GetColour(int n) const { return colour.at(n); } int GetMargin(int n) const { return margin.at(n); } + + String GetDefaultGroup() const; }; // Raw line @@ -217,6 +180,50 @@ namespace Gorgonsub { String GetText() const { return data; } void SetText(const String &_data) { data = _data; } + String GetDefaultGroup() const { return L"Events"; } + }; + + // Advanced Substation Alpha format base class + class FormatASSFamily : public Format { + public: + virtual ~FormatASSFamily() {} + + bool CanStoreText() const { return true; } + bool CanUseTime() const { return true; } + + bool HasStyles() const { return true; } + bool HasMargins() const { return true; } + bool HasActors() const { return true; } + + SectionEntryDialoguePtr CreateDialogue() const { return SectionEntryDialoguePtr(new DialogueASS()); } + SectionEntryStylePtr CreateStyle() const { return SectionEntryStylePtr(new StyleASS()); } + }; + + // Substation Alpha + class FormatSSA : public FormatASSFamily { + public: + FormatHandlerPtr GetHandler(Model &model) const { return FormatHandlerPtr(new FormatHandlerASS(model,0)); } + String GetName() const { return L"Substation Alpha"; } + StringArray GetReadExtensions() const; + StringArray GetWriteExtensions() const; + }; + + // Advanced Substation Alpha + class FormatASS : public FormatASSFamily { + public: + FormatHandlerPtr GetHandler(Model &model) const { return FormatHandlerPtr(new FormatHandlerASS(model,1)); } + String GetName() const { return L"Advanced Substation Alpha"; } + StringArray GetReadExtensions() const; + StringArray GetWriteExtensions() const; + }; + + // Advanced Substation Alpha 2 + class FormatASS2 : public FormatASSFamily { + public: + FormatHandlerPtr GetHandler(Model &model) const { return FormatHandlerPtr(new FormatHandlerASS(model,2)); } + String GetName() const { return L"Advanced Substation Alpha 2"; } + StringArray GetReadExtensions() const; + StringArray GetWriteExtensions() const; }; }; diff --git a/aegilib/src/formats/format_ass_style.cpp b/aegilib/src/formats/format_ass_style.cpp index b8d727025..e99c9bab1 100644 --- a/aegilib/src/formats/format_ass_style.cpp +++ b/aegilib/src/formats/format_ass_style.cpp @@ -43,7 +43,9 @@ using namespace Gorgonsub; // Constructors StyleASS::StyleASS() { + formatVersion = 1; } + StyleASS::StyleASS(String data,int version) { // Try parsing with all different versions @@ -128,8 +130,11 @@ bool StyleASS::Parse(String data,int version) relativeTo = 0; if (version == 2) relativeTo = tkn.GetInt(); - // End + // Read it all? if (tkn.HasMore()) return false; + + // Done + formatVersion = version; return true; } @@ -226,3 +231,15 @@ String StyleASS::ToText(int version) const // Done return final; } + + +///////////////////// +// Get default group +String StyleASS::GetDefaultGroup() const +{ + switch (formatVersion) { + case 0: return L"V4 Events"; + case 1: return L"V4+ Events"; + default: return L"V4++ Events"; + } +} diff --git a/aegilib/src/model.cpp b/aegilib/src/model.cpp index 0ef6a0e87..fc700462d 100644 --- a/aegilib/src/model.cpp +++ b/aegilib/src/model.cpp @@ -58,27 +58,54 @@ void Model::DispatchNotifications(const Notification ¬ification) const //////////////////////////// // Processes an action list -void Model::ProcessActionList(const Manipulator &actionList,bool insertInStack) +void Model::ProcessActionList(const ActionList &_actionList,bool insertInStack) { + // Copy the list + ActionListPtr actions = ActionListPtr(new ActionList(_actionList)); + // Inserts the opposite into the undo stack if (insertInStack) { - undoStack.push_back(CreateAntiManipulator(actionList)); + undoStack.push_back(CreateAntiActionList(actions)); redoStack.clear(); } - // Do action - // TODO + // Do actions + std::list::iterator cur; + for (cur=actions->actions.begin();cur!=actions->actions.end();cur++) { + DoAction(*cur); + } // Notify listeners DispatchNotifications(Notification()); } -//////////////////////////////////////////////////////////////////////// -// Create an anti-manipulator to undo the actions made by a manipulator -Manipulator Model::CreateAntiManipulator(const Manipulator &src) +///////////////////// +// Execute an action +void Model::DoAction(const Action &action) { - Manipulator dst(*this,src.actionName); + switch (action.GetType()) { + case ACTION_INSERT: { + // Get the line + SectionEntryPtr entry = static_pointer_cast(action.GetData()); + + // Find the section to insert it on + String sectionName = action.GetSection(); + if (sectionName.IsEmpty()) sectionName = entry->GetDefaultGroup(); + SectionPtr section = GetSection(sectionName); + + // Insert the line + section->AddEntry(entry,action.GetLineNumber()); + } + } +} + + +////////////////////////////////////////////////////////////////////// +// Create an anti-actionlist to undo the actions made by a actionlist +ActionListPtr Model::CreateAntiActionList(const ActionListPtr &src) +{ + ActionListPtr dst(new ActionList(*this,src->actionName)); // TODO return dst; } @@ -86,10 +113,10 @@ Manipulator Model::CreateAntiManipulator(const Manipulator &src) ////////////////// // Load subtitles -void Model::Load(wxInputStream &input,const FormatPtr format,const String encoding) +void Model::Load(wxInputStream &input,const FormatPtr _format,const String encoding) { // Autodetect format - if (!format) { + if (!_format) { // TODO // No format found @@ -97,7 +124,7 @@ void Model::Load(wxInputStream &input,const FormatPtr format,const String encodi } // Get handler - FormatHandlerPtr handler = format->GetHandler(*this); + FormatHandlerPtr handler = _format->GetHandler(*this); if (!handler) throw Exception(Exception::No_Format_Handler); // Clear the model first @@ -105,19 +132,20 @@ void Model::Load(wxInputStream &input,const FormatPtr format,const String encodi // Load handler->Load(input,encoding); + + // Set the format + format = _format; } ////////////////// // Save subtitles -void Model::Save(wxOutputStream &output,const FormatPtr format,const String encoding) +void Model::Save(wxOutputStream &output,const FormatPtr _format,const String encoding) { - // Autodetect format - if (!format) { + // Use another format + if (_format && _format != format) { // TODO - - // No format found - throw Exception(Exception::No_Format_Handler); + throw Exception(Exception::TODO); } // Get handler @@ -129,26 +157,6 @@ void Model::Save(wxOutputStream &output,const FormatPtr format,const String enco } -/////////////// -// Load a file -void Model::LoadFile(const String filename,const String encoding) -{ - const FormatPtr handler = FormatManager::GetFormatFromFilename(filename,true); - wxFileInputStream stream(filename); - Load(stream,handler,encoding); -} - - -/////////////// -// Save a file -void Model::SaveFile(const String filename,const String encoding) -{ - const FormatPtr handler = FormatManager::GetFormatFromFilename(filename,true); - wxFileOutputStream stream(filename); - Save(stream,handler,encoding); -} - - ///////////////////////// // Inserts a new section void Model::AddSection(String name) diff --git a/aegilib/src/section.cpp b/aegilib/src/section.cpp index dad459130..25993ed7f 100644 --- a/aegilib/src/section.cpp +++ b/aegilib/src/section.cpp @@ -48,9 +48,10 @@ Section::Section(String _name) /////////////////// // Append an entry -void Section::AddEntry(SectionEntryPtr entry) +void Section::AddEntry(SectionEntryPtr entry,int pos) { - entries.push_back(entry); + if (pos == -1) entries.push_back(entry); + else entries.insert(entries.begin()+pos,entry); } void Section::RemoveEntryByIndex(size_t index) diff --git a/aegilib/test/src/main.cpp b/aegilib/test/src/main.cpp index 30285fc70..e2d72b6ed 100644 --- a/aegilib/test/src/main.cpp +++ b/aegilib/test/src/main.cpp @@ -52,20 +52,29 @@ int main () { // Subtitles model Model subs; + Controller control(subs); // Load subtitles cout << "Loading file... "; - subs.LoadFile(L"subs_in.ass",L"UTF-8"); + control.LoadFile(L"subs_in.ass",L"UTF-8"); cout << "Done.\n"; - // Modify subtitles - cout << "Modifying file..."; - // TODO + // Create line to be inserted + cout << "Creating data... "; + SectionEntryDialoguePtr line = control.CreateDialogue(); + line->SetText(L"Hi, testing insertion of lines!"); + cout << "Done.\n"; + + // Create action list + cout << "Processing actions... "; + ActionListPtr actions = control.CreateActionList(L"Insert line"); + actions->InsertLine(line,2); + actions->Finish(); cout << "Done.\n"; // Save subtitles cout << "Saving file... "; - subs.SaveFile(L"subs_out.ass",L"UTF-8"); + control.SaveFile(L"subs_out.ass",L"UTF-8"); cout << "Done.\n"; }