Gorgonsub is now capable of doing some simple manipulation (i.e. line insertion).

Originally committed to SVN as r2048.
This commit is contained in:
Rodrigo Braz Monteiro 2008-03-14 02:02:48 +00:00
parent bb425f8a86
commit b073b7d28d
21 changed files with 404 additions and 145 deletions

View file

@ -160,6 +160,10 @@
RelativePath=".\include\aegilib\action.h" RelativePath=".\include\aegilib\action.h"
> >
</File> </File>
<File
RelativePath=".\include\aegilib\actionlist.h"
>
</File>
<File <File
RelativePath=".\include\aegilib\colour.h" RelativePath=".\include\aegilib\colour.h"
> >
@ -196,10 +200,6 @@
RelativePath=".\include\aegilib\gorgontime.h" RelativePath=".\include\aegilib\gorgontime.h"
> >
</File> </File>
<File
RelativePath=".\include\aegilib\manipulator.h"
>
</File>
<File <File
RelativePath=".\include\aegilib\model.h" RelativePath=".\include\aegilib\model.h"
> >
@ -253,7 +253,11 @@
> >
</File> </File>
<File <File
RelativePath=".\src\manipulator.cpp" RelativePath=".\src\actionlist.cpp"
>
</File>
<File
RelativePath=".\src\controller.cpp"
> >
</File> </File>
<File <File

View file

@ -34,6 +34,7 @@
// //
#pragma once #pragma once
#include "gorgonstring.h"
namespace Gorgonsub { namespace Gorgonsub {
// The different types of actions available // The different types of actions available
@ -48,14 +49,16 @@ namespace Gorgonsub {
private: private:
ActionType type; ActionType type;
shared_ptr<void> data; shared_ptr<void> data;
String section;
int par1; int par1;
public: public:
Action(); Action();
Action(ActionType type,shared_ptr<void> data,int par1); Action(ActionType type,shared_ptr<void> data,const String &section,int par1);
ActionType GetType() { return type; } ActionType GetType() const { return type; }
shared_ptr<void> GetData() { return data; } shared_ptr<void> GetData() const { return data; }
int GetLineNumber() { return par1; } int GetLineNumber() const { return par1; }
String GetSection() const { return section; }
}; };
}; };

View file

@ -37,13 +37,17 @@
#include <list> #include <list>
#include "action.h" #include "action.h"
#include "gorgonstring.h" #include "gorgonstring.h"
#include "section_entry.h"
namespace Gorgonsub { namespace Gorgonsub {
// Manipulator class // Prototypes
class Manipulator { class Controller;
// ActionList class
class ActionList {
friend class Model; friend class Model;
friend class std::list<Manipulator>; friend class Controller;
private: private:
String actionName; String actionName;
@ -51,14 +55,18 @@ namespace Gorgonsub {
std::list<Action> actions; std::list<Action> actions;
bool valid; bool valid;
Manipulator(); ActionList();
ActionList(Model &model,const String actionName);
void Start(const String actionName);
public: public:
Manipulator(Model &model,String actionName); ~ActionList();
~Manipulator();
void AddAction(const Action &action); void AddAction(const Action &action);
void Flush(); void Finish();
void InsertLine(SectionEntryPtr line,int position=-1,const String section=L"");
}; };
typedef shared_ptr<ActionList> ActionListPtr;
}; };

View file

@ -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<ActionList> 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;
};
};

View file

@ -46,12 +46,13 @@ namespace Gorgonsub {
enum ExceptionList { enum ExceptionList {
Unknown, Unknown,
No_Format_Handler, No_Format_Handler,
Invalid_Manipulator, Invalid_ActionList,
Section_Already_Exists, Section_Already_Exists,
Unknown_Format, Unknown_Format,
Parse_Error, Parse_Error,
Unsupported_Format_Feature, Unsupported_Format_Feature,
Invalid_Token Invalid_Token,
TODO
}; };
Exception(ExceptionList code); Exception(ExceptionList code);

View file

@ -36,6 +36,7 @@
#pragma once #pragma once
#include "gorgonstring.h" #include "gorgonstring.h"
#include "tr1.h" #include "tr1.h"
#include "section_entry.h"
namespace Gorgonsub { namespace Gorgonsub {
// Prototypes // Prototypes
@ -65,6 +66,9 @@ namespace Gorgonsub {
virtual int GetTimingPrecision() const { return 10; } // In milliseconds virtual int GetTimingPrecision() const { return 10; } // In milliseconds
virtual int GetMaxTime() const { return 36000000-10; } // In milliseconds, default 9h 59min 59.99s 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<Format> FormatPtr; typedef shared_ptr<Format> FormatPtr;

View file

@ -35,16 +35,29 @@
#pragma once #pragma once
#include "gorgonstring.h" #include "gorgonstring.h"
#include "model.h"
#include "tr1.h" #include "tr1.h"
namespace Gorgonsub { namespace Gorgonsub {
// Format handler interface // Format handler interface
class FormatHandler { class FormatHandler {
private:
Model &model;
protected: protected:
virtual ~FormatHandler() {} 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: public:
FormatHandler(Model &_model) : model(_model) {}
virtual void Load(wxInputStream &file,const String encoding) = 0; virtual void Load(wxInputStream &file,const String encoding) = 0;
virtual void Save(wxOutputStream &file,const String encoding) = 0; virtual void Save(wxOutputStream &file,const String encoding) = 0;
}; };

View file

@ -44,7 +44,7 @@
#include "format.h" #include "format.h"
#include "format_handler.h" #include "format_handler.h"
#include "format_manager.h" #include "format_manager.h"
#include "manipulator.h" #include "actionlist.h"
#include "section.h" #include "section.h"
#include "section_entry_dialogue.h" #include "section_entry_dialogue.h"
#include "section_entry_style.h" #include "section_entry_style.h"

View file

@ -37,7 +37,7 @@
#include <list> #include <list>
#include <vector> #include <vector>
#include <wx/wfstream.h> #include <wx/wfstream.h>
#include "manipulator.h" #include "actionlist.h"
#include "section.h" #include "section.h"
namespace Gorgonsub { namespace Gorgonsub {
@ -51,9 +51,12 @@ namespace Gorgonsub {
// Model class // Model class
// Stores the subtitle data // Stores the subtitle data
class Model { class Model {
friend class Manipulator; friend class FormatHandler;
friend class ActionList;
friend class Controller;
typedef std::list<ViewPtr> ViewList; typedef std::list<ViewPtr> ViewList;
typedef std::list<const Manipulator> ActionStack; typedef std::list<ActionListPtr> ActionStack;
typedef shared_ptr<Format> FormatPtr; typedef shared_ptr<Format> FormatPtr;
private: private:
@ -62,30 +65,31 @@ namespace Gorgonsub {
ActionStack redoStack; ActionStack redoStack;
ViewList listeners; ViewList listeners;
bool readOnly; bool readOnly;
FormatPtr format;
void ProcessActionList(const Manipulator &actionList,bool insertInStack); void ProcessActionList(const ActionList &actionList,bool insertInStack);
Manipulator CreateAntiManipulator(const Manipulator &manipulator); 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 &notification) const; void DispatchNotifications(const Notification &notification) 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); void AddSection(String name);
SectionPtr GetSection(String name) const; SectionPtr GetSection(String name) const;
SectionPtr GetSectionByIndex(size_t index) const; SectionPtr GetSectionByIndex(size_t index) const;
size_t GetSectionCount() const; size_t GetSectionCount() const;
bool CanUndo(const String owner=L"") const; void Clear();
bool CanRedo(const String owner=L"") const; void Load(wxInputStream &input,const FormatPtr format=FormatPtr(),const String encoding=L"");
bool Undo(const String owner=L""); void Save(wxOutputStream &output,const FormatPtr format=FormatPtr(),const String encoding=L"UTF-8");
bool Redo(const String owner=L"");
public:
const FormatPtr GetFormat() const { return format; }
void AddListener(ViewPtr listener);
}; };
}; };

View file

@ -66,7 +66,7 @@ namespace Gorgonsub {
String GetPropertyName(size_t index) const; String GetPropertyName(size_t index) const;
// Entries // Entries
void AddEntry(SectionEntryPtr entry); void AddEntry(SectionEntryPtr entry,int pos=-1);
void RemoveEntryByIndex(size_t index); void RemoveEntryByIndex(size_t index);
void RemoveEntry(SectionEntryPtr entry); void RemoveEntry(SectionEntryPtr entry);
SectionEntryConstPtr GetEntry(size_t index) const; SectionEntryConstPtr GetEntry(size_t index) const;

View file

@ -76,6 +76,8 @@ namespace Gorgonsub {
public: public:
virtual SectionEntryType GetType() const =0; virtual SectionEntryType GetType() const =0;
virtual String GetDefaultGroup() const =0;
static const SectionEntryPlainPtr GetAsPlain(const SectionEntryPtr &ptr); static const SectionEntryPlainPtr GetAsPlain(const SectionEntryPtr &ptr);
static const SectionEntryDialoguePtr GetAsDialogue(const SectionEntryPtr &ptr); static const SectionEntryDialoguePtr GetAsDialogue(const SectionEntryPtr &ptr);
static const SectionEntryDialogueConstPtr GetAsDialogue(const SectionEntryConstPtr &ptr); static const SectionEntryDialogueConstPtr GetAsDialogue(const SectionEntryConstPtr &ptr);

View file

@ -46,9 +46,10 @@ Action::Action()
////////////////////////////// //////////////////////////////
// Initialization constructor // Initialization constructor
Action::Action(ActionType _type,shared_ptr<void> _data,int _par1) Action::Action(ActionType _type,shared_ptr<void> _data,const String &_section,int _par1)
{ {
type = _type; type = _type;
data = _data; data = _data;
par1 = _par1; par1 = _par1;
section = _section;
} }

View file

@ -39,34 +39,42 @@ using namespace Gorgonsub;
/////////////// ///////////////
// Constructor // Constructor
Manipulator::Manipulator(Model &_model,String _actionName) ActionList::ActionList(Model &_model,String _actionName)
: model(_model) : model(_model)
{ {
actionName = _actionName; Start(_actionName);
valid = true;
} }
////////////// //////////////
// Destructor // Destructor
Manipulator::~Manipulator() ActionList::~ActionList()
{ {
Flush();
} }
////////////////////////////// //////////////////////////////
// Add an action to the queue // 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); actions.push_back(action);
} }
//////////////////////////////// /////////////////////////////
// Flush the queue to the model // Starts performing actions
void Manipulator::Flush() void ActionList::Start(const String name)
{
if (valid) Finish();
actionName = name;
valid = true;
}
////////////////////////
// Ends the action list
void ActionList::Finish()
{ {
if (valid) { if (valid) {
model.ProcessActionList(*this,false); model.ProcessActionList(*this,false);
@ -74,3 +82,12 @@ void Manipulator::Flush()
valid = false; 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);
}

View file

@ -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();
}

View file

@ -53,12 +53,13 @@ String Exception::GetMessage(int code)
switch (code) { switch (code) {
case Unknown: return L"Unknown."; case Unknown: return L"Unknown.";
case No_Format_Handler: return L"Could not find a suitable format handler."; 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 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 Unknown_Format: return L"The specified file format is unknown.";
case Parse_Error: return L"Parse error."; case Parse_Error: return L"Parse error.";
case Unsupported_Format_Feature: return L"This feature is not supported by this format."; 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 Invalid_Token: return L"Invalid type for this token.";
case TODO: return L"TODO";
} }
return L"Invalid code."; return L"Invalid code.";
} }

View file

@ -89,7 +89,7 @@ StringArray FormatASS2::GetWriteExtensions() const
/////////////// ///////////////
// Constructor // Constructor
FormatHandlerASS::FormatHandlerASS(Model &_model,int version) 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); ProcessGroup(cur,curGroup,version);
// Insert group if it doesn't already exist // Insert group if it doesn't already exist
if (prevGroup != curGroup) section = model.GetSection(curGroup); if (prevGroup != curGroup) section = GetSection(curGroup);
if (!section) { if (!section) {
model.AddSection(curGroup); AddSection(curGroup);
section = model.GetSection(curGroup); section = GetSection(curGroup);
} }
// Skip [] lines // Skip [] lines
@ -157,9 +157,9 @@ void FormatHandlerASS::Save(wxOutputStream &file,const String encoding)
sections.Add(L"Graphics"); sections.Add(L"Graphics");
// Look for remaining sections // Look for remaining sections
size_t totalSections = model.GetSectionCount(); size_t totalSections = GetSectionCount();
for (size_t i=0;i<totalSections;i++) { for (size_t i=0;i<totalSections;i++) {
String name = model.GetSectionByIndex(i)->GetName(); String name = GetSectionByIndex(i)->GetName();
if (sections.Index(name,false,false) == wxNOT_FOUND) sections.Add(name); 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(); size_t len = sections.size();
for (size_t i=0;i<len;i++) { for (size_t i=0;i<len;i++) {
// See if it exists // See if it exists
SectionPtr section = model.GetSection(sections[i]); SectionPtr section = GetSection(sections[i]);
if (section) { if (section) {
// Add a spacer // Add a spacer
if (i != 0) writer.WriteLineToFile(_T("")); if (i != 0) writer.WriteLineToFile(_T(""));

View file

@ -57,7 +57,6 @@ namespace Gorgonsub {
// Advanced Substation Alpha format handler // Advanced Substation Alpha format handler
class FormatHandlerASS : public FormatHandler { class FormatHandlerASS : public FormatHandler {
private: private:
Model &model;
int formatVersion; int formatVersion;
SectionEntryPtr MakeEntry(const String &data,SectionPtr section,int version); SectionEntryPtr MakeEntry(const String &data,SectionPtr section,int version);
@ -72,46 +71,6 @@ namespace Gorgonsub {
void Save(wxOutputStream &file,const String encoding); void Save(wxOutputStream &file,const String encoding);
}; };
// 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; }
};
// 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;
};
// Dialogue // Dialogue
class DialogueASS : public SectionEntryDialogue, public SerializeText { class DialogueASS : public SectionEntryDialogue, public SerializeText {
private: private:
@ -120,7 +79,7 @@ namespace Gorgonsub {
String effect; String effect;
String actor; String actor;
Time start,end; Time start,end;
array<int,4> margin; array<short,4> margin;
int layer; int layer;
bool isComment; bool isComment;
@ -137,6 +96,7 @@ namespace Gorgonsub {
bool HasTime() const { return true; } bool HasTime() const { return true; }
bool HasStyle() const { return true; } bool HasStyle() const { return true; }
bool HasMargins() const { return true; } bool HasMargins() const { return true; }
String GetDefaultGroup() const { return L"Events"; }
// Read accessors // Read accessors
const String& GetText() const { return text; } const String& GetText() const { return text; }
@ -166,6 +126,7 @@ namespace Gorgonsub {
String name; String name;
String font; String font;
float fontSize; float fontSize;
int formatVersion;
array<Colour,5> colour; // 0 = Primary, 1 = Secondary, 2 = Tertiary, 3 = Outline, 4 = Shadow array<Colour,5> colour; // 0 = Primary, 1 = Secondary, 2 = Tertiary, 3 = Outline, 4 = Shadow
array<int,4> margin; array<int,4> margin;
@ -203,6 +164,8 @@ namespace Gorgonsub {
float GetFontSize() const { return fontSize; } float GetFontSize() const { return fontSize; }
Colour GetColour(int n) const { return colour.at(n); } Colour GetColour(int n) const { return colour.at(n); }
int GetMargin(int n) const { return margin.at(n); } int GetMargin(int n) const { return margin.at(n); }
String GetDefaultGroup() const;
}; };
// Raw line // Raw line
@ -217,6 +180,50 @@ namespace Gorgonsub {
String GetText() const { return data; } String GetText() const { return data; }
void SetText(const String &_data) { data = _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;
}; };
}; };

View file

@ -43,7 +43,9 @@ using namespace Gorgonsub;
// Constructors // Constructors
StyleASS::StyleASS() StyleASS::StyleASS()
{ {
formatVersion = 1;
} }
StyleASS::StyleASS(String data,int version) StyleASS::StyleASS(String data,int version)
{ {
// Try parsing with all different versions // Try parsing with all different versions
@ -128,8 +130,11 @@ bool StyleASS::Parse(String data,int version)
relativeTo = 0; relativeTo = 0;
if (version == 2) relativeTo = tkn.GetInt(); if (version == 2) relativeTo = tkn.GetInt();
// End // Read it all?
if (tkn.HasMore()) return false; if (tkn.HasMore()) return false;
// Done
formatVersion = version;
return true; return true;
} }
@ -226,3 +231,15 @@ String StyleASS::ToText(int version) const
// Done // Done
return final; 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";
}
}

View file

@ -58,27 +58,54 @@ void Model::DispatchNotifications(const Notification &notification) const
//////////////////////////// ////////////////////////////
// Processes an action list // 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 // Inserts the opposite into the undo stack
if (insertInStack) { if (insertInStack) {
undoStack.push_back(CreateAntiManipulator(actionList)); undoStack.push_back(CreateAntiActionList(actions));
redoStack.clear(); redoStack.clear();
} }
// Do action // Do actions
// TODO std::list<Action>::iterator cur;
for (cur=actions->actions.begin();cur!=actions->actions.end();cur++) {
DoAction(*cur);
}
// Notify listeners // Notify listeners
DispatchNotifications(Notification()); DispatchNotifications(Notification());
} }
//////////////////////////////////////////////////////////////////////// /////////////////////
// Create an anti-manipulator to undo the actions made by a manipulator // Execute an action
Manipulator Model::CreateAntiManipulator(const Manipulator &src) 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<SectionEntry>(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 // TODO
return dst; return dst;
} }
@ -86,10 +113,10 @@ Manipulator Model::CreateAntiManipulator(const Manipulator &src)
////////////////// //////////////////
// Load subtitles // 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 // Autodetect format
if (!format) { if (!_format) {
// TODO // TODO
// No format found // No format found
@ -97,7 +124,7 @@ void Model::Load(wxInputStream &input,const FormatPtr format,const String encodi
} }
// Get handler // Get handler
FormatHandlerPtr handler = format->GetHandler(*this); FormatHandlerPtr handler = _format->GetHandler(*this);
if (!handler) throw Exception(Exception::No_Format_Handler); if (!handler) throw Exception(Exception::No_Format_Handler);
// Clear the model first // Clear the model first
@ -105,19 +132,20 @@ void Model::Load(wxInputStream &input,const FormatPtr format,const String encodi
// Load // Load
handler->Load(input,encoding); handler->Load(input,encoding);
// Set the format
format = _format;
} }
////////////////// //////////////////
// Save subtitles // 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 // Use another format
if (!format) { if (_format && _format != format) {
// TODO // TODO
throw Exception(Exception::TODO);
// No format found
throw Exception(Exception::No_Format_Handler);
} }
// Get handler // 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 // Inserts a new section
void Model::AddSection(String name) void Model::AddSection(String name)

View file

@ -48,9 +48,10 @@ Section::Section(String _name)
/////////////////// ///////////////////
// Append an entry // 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) void Section::RemoveEntryByIndex(size_t index)

View file

@ -52,20 +52,29 @@ int main () {
// Subtitles model // Subtitles model
Model subs; Model subs;
Controller control(subs);
// Load subtitles // Load subtitles
cout << "Loading file... "; cout << "Loading file... ";
subs.LoadFile(L"subs_in.ass",L"UTF-8"); control.LoadFile(L"subs_in.ass",L"UTF-8");
cout << "Done.\n"; cout << "Done.\n";
// Modify subtitles // Create line to be inserted
cout << "Modifying file..."; cout << "Creating data... ";
// TODO 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"; cout << "Done.\n";
// Save subtitles // Save subtitles
cout << "Saving file... "; cout << "Saving file... ";
subs.SaveFile(L"subs_out.ass",L"UTF-8"); control.SaveFile(L"subs_out.ass",L"UTF-8");
cout << "Done.\n"; cout << "Done.\n";
} }