From cd9d6f1cfb30daadd50356ad819eee9d82d61a59 Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Tue, 18 Mar 2008 02:09:33 +0000 Subject: [PATCH] Some refactoring and a new way to read data. Originally committed to SVN as r2077. --- aegilib/include/aegilib/action.h | 14 +- aegilib/include/aegilib/actionlist.h | 6 +- aegilib/include/aegilib/controller.h | 147 +++++++++--------- aegilib/include/aegilib/exception.h | 1 + aegilib/include/aegilib/format.h | 4 +- aegilib/include/aegilib/section.h | 14 +- aegilib/include/aegilib/section_entry.h | 60 +++---- .../include/aegilib/section_entry_dialogue.h | 8 +- aegilib/include/aegilib/section_entry_style.h | 8 +- aegilib/src/action.cpp | 20 +-- aegilib/src/actionlist.cpp | 14 +- aegilib/src/controller.cpp | 49 +++++- aegilib/src/exception.cpp | 1 + aegilib/src/formats/format_ass.cpp | 16 +- aegilib/src/formats/format_ass.h | 6 +- aegilib/src/formats/format_ass_dialogue.h | 4 +- aegilib/src/formats/format_ass_plain.h | 4 +- aegilib/src/formats/format_ass_style.cpp | 6 +- aegilib/src/formats/format_ass_style.h | 8 +- aegilib/src/model.cpp | 10 +- aegilib/src/section.cpp | 57 +++++-- aegilib/src/section_entry.cpp | 26 ++-- aegilib/src/tokenizer.cpp | 2 +- aegilib/test/src/main.cpp | 29 ++-- aegilib/todo.txt | 7 +- 25 files changed, 316 insertions(+), 205 deletions(-) diff --git a/aegilib/include/aegilib/action.h b/aegilib/include/aegilib/action.h index 9c29e8985..c5187fec4 100644 --- a/aegilib/include/aegilib/action.h +++ b/aegilib/include/aegilib/action.h @@ -40,7 +40,7 @@ namespace Gorgonsub { // Prototypes class Model; - class SectionEntry; + class Entry; class Action; class Section; typedef shared_ptr ActionPtr; @@ -60,12 +60,12 @@ namespace Gorgonsub { // Insert line class ActionInsert : public Action { private: - shared_ptr entry; + shared_ptr entry; const String section; int lineNumber; public: - ActionInsert(shared_ptr entry,int line,const String §ion); + ActionInsert(shared_ptr entry,int line,const String §ion); ~ActionInsert() {} ActionPtr GetAntiAction(const Model &model) const; @@ -89,14 +89,14 @@ namespace Gorgonsub { // Modify line class ActionModify : public Action { private: - shared_ptr entry; + shared_ptr entry; shared_ptr delta; const String section; int lineNumber; bool noTextFields; public: - ActionModify(shared_ptr entry,int line,const String §ion,bool noTextFields); + ActionModify(shared_ptr entry,int line,const String §ion,bool noTextFields); ActionModify(shared_ptr delta,int line,const String §ion); ~ActionModify() {} @@ -107,14 +107,14 @@ namespace Gorgonsub { // Modify several line class ActionModifyBatch : public Action { private: - std::vector > entries; + std::vector > entries; std::vector > deltas; Selection selection; const String section; bool noTextFields; public: - ActionModifyBatch(std::vector > entries,std::vector > deltas,Selection selection,const String §ion,bool noTextFields); + ActionModifyBatch(std::vector > entries,std::vector > deltas,Selection selection,const String §ion,bool noTextFields); ~ActionModifyBatch() {} ActionPtr GetAntiAction(const Model &model) const; diff --git a/aegilib/include/aegilib/actionlist.h b/aegilib/include/aegilib/actionlist.h index 4ce1b4508..d18350074 100644 --- a/aegilib/include/aegilib/actionlist.h +++ b/aegilib/include/aegilib/actionlist.h @@ -71,10 +71,10 @@ namespace Gorgonsub { void AddAction(const ActionPtr action); void Finish(); - void InsertLine(SectionEntryPtr line,int position=-1,const String section=L""); + void InsertLine(EntryPtr line,int position=-1,const String section=L""); void RemoveLine(int position,const String section); - SectionEntryPtr ModifyLine(int position,const String section); - std::vector ModifyLines(Selection selection,const String section); + EntryPtr ModifyLine(int position,const String section); + std::vector ModifyLines(Selection selection,const String section); }; typedef shared_ptr ActionListPtr; diff --git a/aegilib/include/aegilib/controller.h b/aegilib/include/aegilib/controller.h index cda7bb2e7..d45f86c45 100644 --- a/aegilib/include/aegilib/controller.h +++ b/aegilib/include/aegilib/controller.h @@ -1,71 +1,76 @@ -// 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,const String owner=L"",bool undoAble=true); - - void LoadFile(const String filename,const String encoding=L""); - void SaveFile(const String filename,const String encoding=L"UTF-8"); - - bool CanUndo(const String owner=L"") const; - bool CanRedo(const String owner=L"") const; - void Undo(const String owner=L""); - void Redo(const String owner=L""); - - SectionEntryDialoguePtr CreateDialogue(); - SectionEntryStylePtr CreateStyle(); - - const FormatPtr GetFormat() const; - }; - -} +// 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,const String owner=L"",bool undoAble=true); + + void LoadFile(const String filename,const String encoding=L""); + void SaveFile(const String filename,const String encoding=L"UTF-8"); + + bool CanUndo(const String owner=L"") const; + bool CanRedo(const String owner=L"") const; + void Undo(const String owner=L""); + void Redo(const String owner=L""); + + DialoguePtr CreateDialogue() const; + StylePtr CreateStyle() const; + + DialogueConstPtr GetDialogue(size_t n) const; + DialogueConstPtr GetStyle(size_t n) const; + StyleConstPtr GetStyle(String name) const; + EntryConstPtr GetEntry(size_t n,String section) const; + + const FormatPtr GetFormat() const; + }; + +} diff --git a/aegilib/include/aegilib/exception.h b/aegilib/include/aegilib/exception.h index 69b42e06a..4a674e4b8 100644 --- a/aegilib/include/aegilib/exception.h +++ b/aegilib/include/aegilib/exception.h @@ -53,6 +53,7 @@ namespace Gorgonsub { Unsupported_Format_Feature, Invalid_Token, Out_Of_Range, + Invalid_Section, TODO }; diff --git a/aegilib/include/aegilib/format.h b/aegilib/include/aegilib/format.h index ca8c8676e..041b2088b 100644 --- a/aegilib/include/aegilib/format.h +++ b/aegilib/include/aegilib/format.h @@ -67,8 +67,8 @@ 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; + virtual DialoguePtr CreateDialogue() const = 0; + virtual StylePtr CreateStyle() const = 0; }; typedef shared_ptr FormatPtr; diff --git a/aegilib/include/aegilib/section.h b/aegilib/include/aegilib/section.h index 57909bc06..990ded267 100644 --- a/aegilib/include/aegilib/section.h +++ b/aegilib/include/aegilib/section.h @@ -45,8 +45,9 @@ namespace Gorgonsub { // Section class class Section { private: - std::vector entries; + std::vector entries; std::map properties; + std::map index; String name; public: @@ -65,12 +66,15 @@ namespace Gorgonsub { size_t GetPropertyCount() const; String GetPropertyName(size_t index) const; + // Indexed + EntryPtr GetFromIndex(String key) const; + // Entries - void AddEntry(SectionEntryPtr entry,int pos=-1); + void AddEntry(EntryPtr entry,int pos=-1); void RemoveEntryByIndex(size_t index); - void RemoveEntry(SectionEntryPtr entry); - SectionEntryPtr GetEntry(size_t index) const; - SectionEntryPtr& GetEntryRef(size_t index); + void RemoveEntry(EntryPtr entry); + EntryPtr GetEntry(size_t index) const; + EntryPtr& GetEntryRef(size_t index); size_t GetEntryCount() const; }; typedef shared_ptr
SectionPtr; diff --git a/aegilib/include/aegilib/section_entry.h b/aegilib/include/aegilib/section_entry.h index bbd5458ac..ad33fe4ef 100644 --- a/aegilib/include/aegilib/section_entry.h +++ b/aegilib/include/aegilib/section_entry.h @@ -50,51 +50,53 @@ namespace Gorgonsub { }; // Prototypes - class SectionEntry; - class SectionEntryPlain; - class SectionEntryDialogue; - class SectionEntryStyle; - class SectionEntryFile; - class SectionEntryRaw; - typedef shared_ptr SectionEntryPtr; - typedef shared_ptr SectionEntryPlainPtr; - typedef shared_ptr SectionEntryDialoguePtr; - typedef shared_ptr SectionEntryStylePtr; - typedef shared_ptr SectionEntryFilePtr; - typedef shared_ptr SectionEntryRawPtr; - typedef shared_ptr SectionEntryConstPtr; - typedef shared_ptr SectionEntryPlainConstPtr; - typedef shared_ptr SectionEntryDialogueConstPtr; - typedef shared_ptr SectionEntryStyleConstPtr; - typedef shared_ptr SectionEntryFileConstPtr; - typedef shared_ptr SectionEntryRawConstPtr; + class Entry; + class PlainText; + class Dialogue; + class Style; + class Attachment; + class RawEntry; + typedef shared_ptr EntryPtr; + typedef shared_ptr PlainTextPtr; + typedef shared_ptr<Dialogue> DialoguePtr; + typedef shared_ptr<Style> StylePtr; + typedef shared_ptr<Attachment> AttachmentPtr; + typedef shared_ptr<RawEntry> RawEntryPtr; + typedef shared_ptr<const Entry> EntryConstPtr; + typedef shared_ptr<const PlainText> PlainTextConstPtr; + typedef shared_ptr<const Dialogue> DialogueConstPtr; + typedef shared_ptr<const Style> StyleConstPtr; + typedef shared_ptr<const Attachment> AttachmentConstPtr; + typedef shared_ptr<const RawEntry> RawEntryConstPtr; // Section entry class - class SectionEntry { + class Entry { protected: - virtual ~SectionEntry() {} + virtual ~Entry() {} const String& EmptyString() const; public: virtual SectionEntryType GetType() const =0; virtual String GetDefaultGroup() const =0; - virtual SectionEntryPtr Clone() const =0; + virtual EntryPtr Clone() const =0; virtual DeltaCoderPtr GetDeltaCoder() const { return DeltaCoderPtr(); } + virtual bool IsIndexable() const { return false; } + virtual String GetIndexName() const { return L""; } - static const SectionEntryPlainPtr GetAsPlain(const SectionEntryPtr &ptr); - static const SectionEntryDialoguePtr GetAsDialogue(const SectionEntryPtr &ptr); - static const SectionEntryDialogueConstPtr GetAsDialogue(const SectionEntryConstPtr &ptr); - static const SectionEntryStylePtr GetAsStyle(const SectionEntryPtr &ptr); - static const SectionEntryFilePtr GetAsFile(const SectionEntryPtr &ptr); - static const SectionEntryRawPtr GetAsRaw(const SectionEntryPtr &ptr); + static const PlainTextPtr GetAsPlain(const EntryPtr &ptr); + static const DialoguePtr GetAsDialogue(const EntryPtr &ptr); + static const DialogueConstPtr GetAsDialogue(const EntryConstPtr &ptr); + static const StylePtr GetAsStyle(const EntryPtr &ptr); + static const AttachmentPtr GetAsFile(const EntryPtr &ptr); + static const RawEntryPtr GetAsRaw(const EntryPtr &ptr); }; // Section plain-text entry - class SectionEntryPlain : public SectionEntry { + class PlainText : public Entry { public: SectionEntryType GetType() const { return SECTION_ENTRY_PLAIN; } - virtual ~SectionEntryPlain() {} + virtual ~PlainText() {} virtual String GetText() const =0; virtual void SetText(const String &_data) =0; }; diff --git a/aegilib/include/aegilib/section_entry_dialogue.h b/aegilib/include/aegilib/section_entry_dialogue.h index 14486e1c1..3e7b66ecd 100644 --- a/aegilib/include/aegilib/section_entry_dialogue.h +++ b/aegilib/include/aegilib/section_entry_dialogue.h @@ -43,18 +43,18 @@ namespace Gorgonsub { // Dialogue class - class SectionEntryDialogue : public SectionEntry { + class Dialogue : public Entry { private: static const bool dodgeWarning = true; - void ThrowUnsupported() const { if (dodgeWarning) throw Exception(Exception::Unsupported_Format_Feature); } + void ThrowUnsupported() const { if (dodgeWarning) THROW_GORGON_EXCEPTION(Exception::Unsupported_Format_Feature); } public: // Destructor - virtual ~SectionEntryDialogue() {} + virtual ~Dialogue() {} // Type SectionEntryType GetType() const { return SECTION_ENTRY_DIALOGUE; } - SectionEntryDialogue *GetAsDialogue() { return this; } + Dialogue *GetAsDialogue() { return this; } // Capabilities virtual bool HasText() const { return false; } diff --git a/aegilib/include/aegilib/section_entry_style.h b/aegilib/include/aegilib/section_entry_style.h index 6ec729662..e2b0b5b40 100644 --- a/aegilib/include/aegilib/section_entry_style.h +++ b/aegilib/include/aegilib/section_entry_style.h @@ -43,18 +43,18 @@ namespace Gorgonsub { // Style class - class SectionEntryStyle : public SectionEntry { + class Style : public Entry { private: static const bool dodgeWarning = true; - void ThrowUnsupported() const { if (dodgeWarning) throw Exception(Exception::Unsupported_Format_Feature); } + void ThrowUnsupported() const { if (dodgeWarning) THROW_GORGON_EXCEPTION(Exception::Unsupported_Format_Feature); } public: // Destructor - virtual ~SectionEntryStyle() {} + virtual ~Style() {} // Type SectionEntryType GetType() const { return SECTION_ENTRY_STYLE; } - SectionEntryStyle *GetAsStyle() { return this; } + Style *GetAsStyle() { return this; } // Read accessors virtual String GetName() const=0; diff --git a/aegilib/src/action.cpp b/aegilib/src/action.cpp index 46b384b7d..0103a9879 100644 --- a/aegilib/src/action.cpp +++ b/aegilib/src/action.cpp @@ -49,7 +49,7 @@ SectionPtr Action::GetSection(const Model &model,const String &name) const /////////////// // Constructor -ActionInsert::ActionInsert(shared_ptr<SectionEntry> data,int line,const String &sName) +ActionInsert::ActionInsert(shared_ptr<Entry> data,int line,const String &sName) : entry(data), lineNumber(line), section(sName) {} @@ -93,7 +93,7 @@ ActionRemove::ActionRemove(int line,const String &sName) ActionPtr ActionRemove::GetAntiAction(const Model &model) const { SectionPtr sect = GetSection(model,section); - SectionEntryPtr entry = sect->GetEntry(lineNumber); + EntryPtr entry = sect->GetEntry(lineNumber); return ActionPtr(new ActionInsert(entry,lineNumber,section)); } @@ -104,7 +104,7 @@ void ActionRemove::Execute(Model &model) { // Find the section to remote it from String sect = section; - if (sect.IsEmpty()) throw Exception(Exception::TODO); // TODO + if (sect.IsEmpty()) THROW_GORGON_EXCEPTION(Exception::TODO); // TODO SectionPtr section = GetSection(model,sect); // Remove the line @@ -116,7 +116,7 @@ void ActionRemove::Execute(Model &model) //////////////// // Constructors -ActionModify::ActionModify(shared_ptr<SectionEntry> data,int line,const String &sName,bool _noTextFields) +ActionModify::ActionModify(shared_ptr<Entry> data,int line,const String &sName,bool _noTextFields) : entry(data), lineNumber(line), section(sName), noTextFields(_noTextFields) {} ActionModify::ActionModify(shared_ptr<void> _delta,int line,const String &sName) @@ -129,7 +129,7 @@ ActionPtr ActionModify::GetAntiAction(const Model &model) const { // Get section and original line SectionPtr sect = GetSection(model,section); - SectionEntryPtr oldEntry = sect->GetEntry(lineNumber); + EntryPtr oldEntry = sect->GetEntry(lineNumber); // Try to get a delta DeltaCoderPtr deltaCoder = oldEntry->GetDeltaCoder(); @@ -158,7 +158,7 @@ void ActionModify::Execute(Model &model) // Modify the line if (delta) { - SectionEntryPtr &ref = sect->GetEntryRef(lineNumber); + EntryPtr &ref = sect->GetEntryRef(lineNumber); ref->GetDeltaCoder()->ApplyDelta(delta,ref); } else sect->GetEntryRef(lineNumber) = entry; @@ -167,7 +167,7 @@ void ActionModify::Execute(Model &model) ////////////////////////// Batch Modify line ////////////////////////// -ActionModifyBatch::ActionModifyBatch(std::vector<shared_ptr<SectionEntry> > _entries, std::vector<shared_ptr<void> > _deltas, Selection _selection,const String &_section,bool _noTextFields) +ActionModifyBatch::ActionModifyBatch(std::vector<shared_ptr<Entry> > _entries, std::vector<shared_ptr<void> > _deltas, Selection _selection,const String &_section,bool _noTextFields) : entries(_entries), deltas(_deltas), selection(_selection), section(_section), noTextFields(_noTextFields) {} ActionPtr ActionModifyBatch::GetAntiAction(const Model &model) const @@ -176,12 +176,12 @@ ActionPtr ActionModifyBatch::GetAntiAction(const Model &model) const SectionPtr sect = GetSection(model,section); size_t len = selection.GetCount(); std::vector<VoidPtr> _deltas(len); - std::vector<SectionEntryPtr> oldEntries(len); + std::vector<EntryPtr> oldEntries(len); // For each line... for (size_t i=0;i<len;i++) { // Get old entry - SectionEntryPtr oldEntry = sect->GetEntry(selection.GetLine(i)); + EntryPtr oldEntry = sect->GetEntry(selection.GetLine(i)); // Try to get a delta DeltaCoderPtr deltaCoder = oldEntry->GetDeltaCoder(); @@ -208,7 +208,7 @@ void ActionModifyBatch::Execute(Model &model) // For each line... for (size_t i=0;i<len;i++) { if (i < deltas.size() && deltas[i]) { - SectionEntryPtr &ref = sect->GetEntryRef(selection.GetLine(i)); + EntryPtr &ref = sect->GetEntryRef(selection.GetLine(i)); ref->GetDeltaCoder()->ApplyDelta(deltas[i],ref); } else sect->GetEntryRef(selection.GetLine(i)) = entries[i]; diff --git a/aegilib/src/actionlist.cpp b/aegilib/src/actionlist.cpp index 5214477d7..b81ed7fe3 100644 --- a/aegilib/src/actionlist.cpp +++ b/aegilib/src/actionlist.cpp @@ -58,7 +58,7 @@ ActionList::~ActionList() // Add an action to the queue void ActionList::AddAction(const ActionPtr action) { - if (!valid) throw Exception(Exception::Invalid_ActionList); + if (!valid) THROW_GORGON_EXCEPTION(Exception::Invalid_ActionList); actions.push_back(action); if (actions.size() > 2) { int a = 0; @@ -71,7 +71,7 @@ void ActionList::AddAction(const ActionPtr action) // Add an action to the start of the queue void ActionList::AddActionStart(const ActionPtr action) { - if (!valid) throw Exception(Exception::Invalid_ActionList); + if (!valid) THROW_GORGON_EXCEPTION(Exception::Invalid_ActionList); actions.push_front(action); if (actions.size() > 2) { int a = 0; @@ -104,7 +104,7 @@ void ActionList::Finish() ////////////////////////////////// // Create an "insert line" action -void ActionList::InsertLine(SectionEntryPtr line,int position,const String section) +void ActionList::InsertLine(EntryPtr line,int position,const String section) { ActionPtr action = ActionPtr (new ActionInsert(line,position,section)); AddAction(action); @@ -122,10 +122,10 @@ void ActionList::RemoveLine(int position,const String section) ///////////////////////////////// // Insert a "modify line" action -SectionEntryPtr ActionList::ModifyLine(int position,const String section) +EntryPtr ActionList::ModifyLine(int position,const String section) { SectionPtr sect = model.GetSection(section); - SectionEntryPtr entry = sect->GetEntry(position)->Clone(); + EntryPtr entry = sect->GetEntry(position)->Clone(); ActionPtr action = ActionPtr (new ActionModify(entry,position,section,false)); AddAction(action); return entry; @@ -134,13 +134,13 @@ SectionEntryPtr ActionList::ModifyLine(int position,const String section) //////////////////////////////////////// // Insert a "modify lines" batch action -std::vector<SectionEntryPtr> ActionList::ModifyLines(Selection selection,const String section) +std::vector<EntryPtr> ActionList::ModifyLines(Selection selection,const String section) { // Get section SectionPtr sect = model.GetSection(section); // Generate entries - std::vector<SectionEntryPtr> entries(selection.GetCount()); + std::vector<EntryPtr> entries(selection.GetCount()); size_t len = selection.GetRanges(); size_t n = 0; for (size_t i=0;i<len;i++) { diff --git a/aegilib/src/controller.cpp b/aegilib/src/controller.cpp index 1498ab072..5d7cd784c 100644 --- a/aegilib/src/controller.cpp +++ b/aegilib/src/controller.cpp @@ -86,11 +86,11 @@ const FormatPtr Controller::GetFormat() const ////////////////// // Create entries -SectionEntryDialoguePtr Controller::CreateDialogue() +DialoguePtr Controller::CreateDialogue() const { return GetFormat()->CreateDialogue(); } -SectionEntryStylePtr Controller::CreateStyle() +StylePtr Controller::CreateStyle() const { return GetFormat()->CreateStyle(); } @@ -114,3 +114,48 @@ void Controller::Redo(const String owner) { model.Redo(owner); } + + +//////////////////////// +// Get the nth dialogue +DialogueConstPtr Controller::GetDialogue(size_t n) const +{ + // TODO + (void) n; + THROW_GORGON_EXCEPTION(Exception::TODO); +} + + +///////////////////// +// Get the nth style +DialogueConstPtr Controller::GetStyle(size_t n) const +{ + // TODO + (void) n; + THROW_GORGON_EXCEPTION(Exception::TODO); +} + + +/////////////////////// +// Get a style by name +StyleConstPtr Controller::GetStyle(String name) const +{ + // Get section + StylePtr dummy = CreateStyle(); + String section = dummy->GetDefaultGroup(); + SectionPtr sect = model.GetSection(section); + if (!sect) THROW_GORGON_EXCEPTION(Exception::Invalid_Section); + + // Return from index + return dynamic_pointer_cast<const Style> (sect->GetFromIndex(name)); +} + + +//////////////// +// Get an entry +EntryConstPtr Controller::GetEntry(size_t n,String section) const +{ + SectionPtr sect = model.GetSection(section); + if (!sect) THROW_GORGON_EXCEPTION(Exception::Invalid_Section); + return sect->GetEntry(n); +} diff --git a/aegilib/src/exception.cpp b/aegilib/src/exception.cpp index be59e3280..f171ecb6a 100644 --- a/aegilib/src/exception.cpp +++ b/aegilib/src/exception.cpp @@ -66,6 +66,7 @@ const char* Exception::GetMessageChar(int code) case Unsupported_Format_Feature: return "This feature is not supported by this format."; case Invalid_Token: return "Invalid type for this token."; case Out_Of_Range: return "Out of range."; + case Invalid_Section: return "Invalid section."; case TODO: return "TODO"; } return "Invalid code."; diff --git a/aegilib/src/formats/format_ass.cpp b/aegilib/src/formats/format_ass.cpp index 1d4edad4c..6a37a6c96 100644 --- a/aegilib/src/formats/format_ass.cpp +++ b/aegilib/src/formats/format_ass.cpp @@ -136,7 +136,7 @@ void FormatHandlerASS::Load(wxInputStream &file,const String encoding) if (cur[0] == L'[') continue; // Create and insert line - SectionEntryPtr entry = MakeEntry(cur,section,version); + EntryPtr entry = MakeEntry(cur,section,version); if (entry) section->AddEntry(entry); } } @@ -182,11 +182,11 @@ void FormatHandlerASS::Save(wxOutputStream &file,const String encoding) /////////////// // Create line -SectionEntryPtr FormatHandlerASS::MakeEntry(const String &data,SectionPtr section,int version) +EntryPtr FormatHandlerASS::MakeEntry(const String &data,SectionPtr section,int version) { // Variables const String group = section->GetName(); - SectionEntryPtr final; + EntryPtr final; // Attachments if (group == _T("Fonts") || group == _T("Graphics")) { @@ -226,17 +226,17 @@ SectionEntryPtr FormatHandlerASS::MakeEntry(const String &data,SectionPtr sectio // Script info else if (group == _T("Script Info")) { // Discard comments - if (data.Left(1) == _T(";")) return SectionEntryPtr(); + if (data.Left(1) == _T(";")) return EntryPtr(); // Parse property size_t pos = data.Find(_T(':')); - if (pos == wxNOT_FOUND) return SectionEntryPtr(); + if (pos == wxNOT_FOUND) return EntryPtr(); wxString key = data.Left(pos).Trim(true).Trim(false); wxString value = data.Mid(pos+1).Trim(true).Trim(false); // Insert property section->SetProperty(key,value); - return SectionEntryPtr(); + return EntryPtr(); } // Unknown group, just leave it intact @@ -316,7 +316,7 @@ void FormatHandlerASS::ProcessGroup(String cur,String &curGroup,int &version) { if (versionString == _T("v4.00")) trueVersion = 0; else if (versionString == _T("v4.00+")) trueVersion = 1; else if (versionString == _T("v4.00++")) trueVersion = 2; - else throw Exception(Exception::Unknown_Format); + else THROW_GORGON_EXCEPTION(Exception::Unknown_Format); if (trueVersion != version) { // TODO: issue warning? version = trueVersion; @@ -356,7 +356,7 @@ void FormatHandlerASS::WriteSection(TextFileWriter &writer,SectionPtr section) // Write contents size_t entries = section->GetEntryCount(); for (size_t i=0;i<entries;i++) { - SectionEntryConstPtr entry = section->GetEntry(i); + EntryConstPtr entry = section->GetEntry(i); shared_ptr<const SerializeText> serial = dynamic_pointer_cast<const SerializeText>(entry); writer.WriteLineToFile(serial->ToText(formatVersion)); } diff --git a/aegilib/src/formats/format_ass.h b/aegilib/src/formats/format_ass.h index d05b2a81e..7a23cd7ee 100644 --- a/aegilib/src/formats/format_ass.h +++ b/aegilib/src/formats/format_ass.h @@ -54,7 +54,7 @@ namespace Gorgonsub { private: int formatVersion; - SectionEntryPtr MakeEntry(const String &data,SectionPtr section,int version); + EntryPtr MakeEntry(const String &data,SectionPtr section,int version); void ProcessGroup(String cur,String &curGroup,int &version); void WriteSection(TextFileWriter &writer,SectionPtr section); @@ -78,8 +78,8 @@ namespace Gorgonsub { bool HasMargins() const { return true; } bool HasActors() const { return true; } - SectionEntryDialoguePtr CreateDialogue() const { return SectionEntryDialoguePtr(new DialogueASS()); } - SectionEntryStylePtr CreateStyle() const { return SectionEntryStylePtr(new StyleASS()); } + DialoguePtr CreateDialogue() const { return DialoguePtr(new DialogueASS()); } + StylePtr CreateStyle() const { return StylePtr(new StyleASS()); } }; // Substation Alpha diff --git a/aegilib/src/formats/format_ass_dialogue.h b/aegilib/src/formats/format_ass_dialogue.h index 93b0ea343..97a095635 100644 --- a/aegilib/src/formats/format_ass_dialogue.h +++ b/aegilib/src/formats/format_ass_dialogue.h @@ -42,7 +42,7 @@ namespace Gorgonsub { // Dialogue - class DialogueASS : public SectionEntryDialogue, public SerializeText { + class DialogueASS : public Dialogue, public SerializeText { friend class DialogueASSDeltaCoder; private: @@ -62,7 +62,7 @@ namespace Gorgonsub { // Basic features String GetDefaultGroup() const { return L"Events"; } - SectionEntryPtr Clone() const { return SectionEntryPtr(new DialogueASS(*this)); } + EntryPtr Clone() const { return EntryPtr(new DialogueASS(*this)); } //DeltaCoderPtr GetDeltaCoder() const { return DeltaCoderPtr(new DialogueASSDeltaCoder()); } // Capabilities diff --git a/aegilib/src/formats/format_ass_plain.h b/aegilib/src/formats/format_ass_plain.h index ee61a8e56..8e2b64d92 100644 --- a/aegilib/src/formats/format_ass_plain.h +++ b/aegilib/src/formats/format_ass_plain.h @@ -40,7 +40,7 @@ namespace Gorgonsub { // Raw line - class PlainASS : public SectionEntryPlain, public SerializeText { + class PlainASS : public PlainText, public SerializeText { private: String data; String ToText(int param) const { (void)param; return data; } @@ -51,7 +51,7 @@ namespace Gorgonsub { // Basic features String GetDefaultGroup() const { return L"Events"; } - SectionEntryPtr Clone() const { return SectionEntryPtr(new PlainASS(*this)); } + EntryPtr Clone() const { return EntryPtr(new PlainASS(*this)); } String GetText() const { return data; } void SetText(const String &_data) { data = _data; } diff --git a/aegilib/src/formats/format_ass_style.cpp b/aegilib/src/formats/format_ass_style.cpp index e574ed28d..8bdd2966f 100644 --- a/aegilib/src/formats/format_ass_style.cpp +++ b/aegilib/src/formats/format_ass_style.cpp @@ -238,8 +238,8 @@ String StyleASS::ToText(int version) const String StyleASS::GetDefaultGroup() const { switch (formatVersion) { - case 0: return L"V4 Events"; - case 1: return L"V4+ Events"; - default: return L"V4++ Events"; + case 0: return L"V4 Styles"; + case 1: return L"V4+ Styles"; + default: return L"V4++ Styles"; } } diff --git a/aegilib/src/formats/format_ass_style.h b/aegilib/src/formats/format_ass_style.h index 73ec26c6d..91de444e1 100644 --- a/aegilib/src/formats/format_ass_style.h +++ b/aegilib/src/formats/format_ass_style.h @@ -41,7 +41,7 @@ namespace Gorgonsub { // Style - class StyleASS : public SectionEntryStyle, public SerializeText { + class StyleASS : public Style, public SerializeText { private: String name; String font; @@ -80,7 +80,11 @@ namespace Gorgonsub { // Basic features String GetDefaultGroup() const; - SectionEntryPtr Clone() const { return SectionEntryPtr(new StyleASS(*this)); } + EntryPtr Clone() const { return EntryPtr(new StyleASS(*this)); } + + // Indexing + virtual bool IsIndexable() const { return true; } + virtual String GetIndexName() const { return GetName(); } // Read accessors String GetName() const { return name; } diff --git a/aegilib/src/model.cpp b/aegilib/src/model.cpp index f5fe33b42..3b6a0cb9a 100644 --- a/aegilib/src/model.cpp +++ b/aegilib/src/model.cpp @@ -99,12 +99,12 @@ void Model::Load(wxInputStream &input,const FormatPtr _format,const String encod // TODO // No format found - throw Exception(Exception::No_Format_Handler); + THROW_GORGON_EXCEPTION(Exception::No_Format_Handler); } // Get handler FormatHandlerPtr handler = _format->GetHandler(*this); - if (!handler) throw Exception(Exception::No_Format_Handler); + if (!handler) THROW_GORGON_EXCEPTION(Exception::No_Format_Handler); // Clear the model first Clear(); @@ -124,12 +124,12 @@ void Model::Save(wxOutputStream &output,const FormatPtr _format,const String enc // Use another format if (_format && _format != format) { // TODO - throw Exception(Exception::TODO); + THROW_GORGON_EXCEPTION(Exception::TODO); } // Get handler FormatHandlerPtr handler = format->GetHandler(*this); - if (!handler) throw Exception(Exception::No_Format_Handler); + if (!handler) THROW_GORGON_EXCEPTION(Exception::No_Format_Handler); // Load handler->Save(output,encoding); @@ -141,7 +141,7 @@ void Model::Save(wxOutputStream &output,const FormatPtr _format,const String enc void Model::AddSection(String name) { SectionPtr prev = GetSection(name); - if (prev) throw Exception(Exception::Section_Already_Exists); + if (prev) THROW_GORGON_EXCEPTION(Exception::Section_Already_Exists); sections.push_back(SectionPtr(new Section(name))); } diff --git a/aegilib/src/section.cpp b/aegilib/src/section.cpp index 0c8ee74c3..06bf222a8 100644 --- a/aegilib/src/section.cpp +++ b/aegilib/src/section.cpp @@ -48,38 +48,65 @@ Section::Section(String _name) /////////////////// // Append an entry -void Section::AddEntry(SectionEntryPtr entry,int pos) +void Section::AddEntry(EntryPtr entry,int pos) { + // Insert to entry list if (pos == -1) entries.push_back(entry); else entries.insert(entries.begin()+pos,entry); + + // Add to index too if it's indexable + if (entry->IsIndexable()) { + index[entry->GetIndexName()] = entry; + } } -void Section::RemoveEntryByIndex(size_t index) + +///////////////////////// +// Removes the nth entry +void Section::RemoveEntryByIndex(size_t i) { - entries.erase(entries.begin()+index); + // Get entry iterator and erase + std::vector<EntryPtr>::iterator entry = entries.begin()+i; + entries.erase(entry); + + // If it's indexable, remove it from index as well + if ((*entry)->IsIndexable()) index.erase((*entry)->GetIndexName()); } -void Section::RemoveEntry(SectionEntryPtr entry) + +///////////////////////////////// +// Removes an entry by its value +void Section::RemoveEntry(EntryPtr entry) { size_t len = entries.size(); for (size_t i=0;i<len;i++) { if (entries[i] == entry) { entries.erase(entries.begin()+i); + if (entry->IsIndexable()) index.erase(entry->GetIndexName()); return; } } } -SectionEntryPtr Section::GetEntry(size_t index) const + +//////////////////////////// +// Retrieves entry by index +EntryPtr Section::GetEntry(size_t i) const { - return entries[index]; + return entries[i]; } -SectionEntryPtr& Section::GetEntryRef(size_t index) + +///////////////////////////////////// +// Retrieves a reference to an entry +EntryPtr& Section::GetEntryRef(size_t i) { - return entries[index]; + return entries[i]; } + +///////////////////////// +// Get number of entries size_t Section::GetEntryCount() const { return entries.size(); @@ -131,11 +158,21 @@ size_t Section::GetPropertyCount() const /////////////////////////////////// // Get name of a property by index -String Section::GetPropertyName(size_t index) const +String Section::GetPropertyName(size_t n) const { std::map<String,String>::const_iterator iter=properties.begin(); for (size_t i=0 ; iter!=properties.end() ; iter++,i++) { - if (i == index) return iter->first; + if (i == n) return iter->first; } return L""; } + + +/////////////////////// +// Retrieve from index +EntryPtr Section::GetFromIndex(String key) const +{ + std::map<String,EntryPtr>::const_iterator result = index.find(key); + if (result != index.end()) return result->second; + return EntryPtr(); +} diff --git a/aegilib/src/section_entry.cpp b/aegilib/src/section_entry.cpp index 1a9b4acd6..28be77765 100644 --- a/aegilib/src/section_entry.cpp +++ b/aegilib/src/section_entry.cpp @@ -42,34 +42,34 @@ using namespace Gorgonsub; ///////////////////////////////// // Returns a static empty string -const String& SectionEntry::EmptyString() const +const String& Entry::EmptyString() const { static const String str = _T(""); return str; } -const SectionEntryPlainPtr SectionEntry::GetAsPlain(const SectionEntryPtr &ptr) +const PlainTextPtr Entry::GetAsPlain(const EntryPtr &ptr) { - (void) ptr; return SectionEntryPlainPtr(); + (void) ptr; return PlainTextPtr(); } -const SectionEntryDialoguePtr SectionEntry::GetAsDialogue(const SectionEntryPtr &ptr) +const DialoguePtr Entry::GetAsDialogue(const EntryPtr &ptr) { - return dynamic_pointer_cast<SectionEntryDialogue>(ptr); + return dynamic_pointer_cast<Dialogue>(ptr); } -const SectionEntryDialogueConstPtr SectionEntry::GetAsDialogue(const SectionEntryConstPtr &ptr) +const DialogueConstPtr Entry::GetAsDialogue(const EntryConstPtr &ptr) { - return dynamic_pointer_cast<const SectionEntryDialogue>(ptr); + return dynamic_pointer_cast<const Dialogue>(ptr); } -const SectionEntryStylePtr SectionEntry::GetAsStyle(const SectionEntryPtr &ptr) +const StylePtr Entry::GetAsStyle(const EntryPtr &ptr) { - return dynamic_pointer_cast<SectionEntryStyle>(ptr); + return dynamic_pointer_cast<Style>(ptr); } -const SectionEntryFilePtr SectionEntry::GetAsFile(const SectionEntryPtr &ptr) +const AttachmentPtr Entry::GetAsFile(const EntryPtr &ptr) { - (void) ptr; return SectionEntryFilePtr(); + (void) ptr; return AttachmentPtr(); } -const SectionEntryRawPtr SectionEntry::GetAsRaw(const SectionEntryPtr &ptr) +const RawEntryPtr Entry::GetAsRaw(const EntryPtr &ptr) { - (void) ptr; return SectionEntryRawPtr(); + (void) ptr; return RawEntryPtr(); } diff --git a/aegilib/src/tokenizer.cpp b/aegilib/src/tokenizer.cpp index 24a2fa2d5..9a73cfffb 100644 --- a/aegilib/src/tokenizer.cpp +++ b/aegilib/src/tokenizer.cpp @@ -72,7 +72,7 @@ int Tokenizer::GetPosition() String Tokenizer::GetString(bool trim) { // Has any more? - if (!HasMoreTokens()) throw Exception(Exception::Invalid_Token); + if (!HasMoreTokens()) THROW_GORGON_EXCEPTION(Exception::Invalid_Token); // Find token size_t len = string.Length(); diff --git a/aegilib/test/src/main.cpp b/aegilib/test/src/main.cpp index c6eded80d..3b33c90a1 100644 --- a/aegilib/test/src/main.cpp +++ b/aegilib/test/src/main.cpp @@ -71,21 +71,25 @@ int main() control.SaveFile(L"subs_out.ass",L"UTF-8"); timer.Pause(); cout << "Done in " << timer.Time() << " ms.\n"; - system("pause"); // Issue an action - cout << "Executing action 100 times... "; +#ifdef WXDEBUG + const int n = 1; +#else + const int n = 100; +#endif + cout << "Executing action " << n << " times... "; timer.Start(); - for (size_t i=0;i<100;i++) { + for (size_t i=0;i<n;i++) { ActionListPtr actions = control.CreateActionList(L"Test"); Selection selection; selection.AddRange(Range(0,5000)); selection.AddRange(Range(4500,5500)); selection.AddRange(Range(9000,9100)); - std::vector<SectionEntryPtr> entries = actions->ModifyLines(selection,L"Events"); + std::vector<EntryPtr> entries = actions->ModifyLines(selection,L"Events"); size_t len = entries.size(); for (size_t i=0;i<len;i++) { - SectionEntryDialoguePtr diag = dynamic_pointer_cast<SectionEntryDialogue> (entries[i]); + DialoguePtr diag = dynamic_pointer_cast<Dialogue> (entries[i]); diag->SetStartTime(diag->GetStartTime() - 55555); diag->SetEndTime(diag->GetEndTime() + 5555); } @@ -93,24 +97,29 @@ int main() } timer.Pause(); cout << "Done in " << timer.Time() << " ms.\n"; - system("pause"); // Rollback - cout << "Undoing 99 times... "; - for (size_t i=0;i<99;i++) { + cout << "Undoing " << n << " times... "; + for (size_t i=0;i<n-1;i++) { control.Undo(); } cout << "Done.\n"; // Undo - cout << "Undoing and redoing 1000 times... "; + cout << "Undoing and redoing " << n*10 << " times... "; timer.Start(); - for (size_t i=0;i<1000;i++) { + for (size_t i=0;i<n*10;i++) { control.Undo(); control.Redo(); } timer.Pause(); cout << "Done in " << timer.Time() << " ms.\n"; + + // Get style test + StyleConstPtr style = control.GetStyle(L"japro1_star"); + cout << "Style " << style->GetName().mb_str() << " font is " << style->GetFontName().mb_str() << " " << style->GetFontSize() << ".\n"; + + // Save a few more control.SaveFile(L"subs_out2.ass",L"UTF-8"); control.Undo(); control.SaveFile(L"subs_out3.ass",L"UTF-8"); diff --git a/aegilib/todo.txt b/aegilib/todo.txt index b6546dcaf..89cb57177 100644 --- a/aegilib/todo.txt +++ b/aegilib/todo.txt @@ -14,6 +14,7 @@ x = done [x] Text file reader/writer [ ] Automatic character set detection [ ] Conversion between subtitle formats +[ ] Format comformity checks [ ] Override tag support [:] ASS format support [ ] ASS override tags @@ -21,6 +22,7 @@ x = done [ ] Matroska-embedded subtitles support [ ] DVD subtitles support (*) [ ] Blu-Ray subtitles support (*) +[ ] OCR support (through Tesseract) (*) [:] Time helper class [:] Colour helper class @@ -28,11 +30,12 @@ x = done [x] Exception class [x] Basic manipulation system +[.] Reading subtitles data from model +[x] Inserting/removing/modifying lines +[.] Multi-line manipulation via selections [:] Undo/redo stack [ ] Owner-based undo/redo operations [x] Delta coded undo/redo -[.] Multi-line manipulation via selections -[ ] Reading subtitles data from model [x] Basic MVC structure [.] Controller