From 2124a1dbd3bfe24ace08b987e616fa9f17426308 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Wed, 19 May 2010 00:44:44 +0000 Subject: [PATCH] Rework how sorting works and add sorting by style Rather than going through a ton of work to ensure that every AssEvent has a sensible start time that happens to leave it in the right place after sorting, simply sort only consecutive blocks of AssDialogues and leave everything else untouched. Note that this results in different behavior when there are multiple [Events] sections in a file -- rather than moving lines between sections and keeping the number of lines per section constant, each section keeps the lines it had. As it's now easy to do, also add sorting by style name and end time. Closes #614. Originally committed to SVN as r4307. --- aegisub/src/ass_dialogue.cpp | 146 +++----------- aegisub/src/ass_dialogue.h | 72 ++----- aegisub/src/ass_entry.cpp | 30 +-- aegisub/src/ass_entry.h | 31 --- aegisub/src/ass_file.cpp | 243 ++++++----------------- aegisub/src/ass_file.h | 59 ++---- aegisub/src/ass_style.cpp | 1 - aegisub/src/ass_time.cpp | 20 +- aegisub/src/ass_time.h | 13 +- aegisub/src/dialog_timing_processor.cpp | 3 +- aegisub/src/export_framerate.cpp | 6 +- aegisub/src/frame_main.cpp | 10 +- aegisub/src/frame_main.h | 11 +- aegisub/src/frame_main_events.cpp | 43 ++-- aegisub/src/mkv_wrap.cpp | 6 +- aegisub/src/subs_grid.cpp | 6 +- aegisub/src/subs_preview.cpp | 2 +- aegisub/src/subtitle_format.cpp | 9 +- aegisub/src/subtitle_format.h | 2 +- aegisub/src/subtitle_format_ass.cpp | 7 +- aegisub/src/subtitle_format_microdvd.cpp | 4 +- aegisub/src/subtitle_format_srt.cpp | 5 +- aegisub/src/subtitle_format_ttxt.cpp | 12 +- aegisub/src/subtitle_format_txt.cpp | 8 +- 24 files changed, 220 insertions(+), 529 deletions(-) diff --git a/aegisub/src/ass_dialogue.cpp b/aegisub/src/ass_dialogue.cpp index 364471281..aac2fd53d 100644 --- a/aegisub/src/ass_dialogue.cpp +++ b/aegisub/src/ass_dialogue.cpp @@ -32,8 +32,6 @@ /// @file ass_dialogue.cpp /// @brief Class for dialogue lines in subtitles /// @ingroup subs_storage -/// - //////////// // Includes @@ -51,38 +49,40 @@ #include "utils.h" #include "vfr.h" -/// @brief Constructs AssDialogue AssDialogue ////////////////////// -/// -AssDialogue::AssDialogue() { - group = _T("[Events]"); - +/// @brief Constructs AssDialogue +AssDialogue::AssDialogue() +: Comment(false) +, Layer(0) +, Start(0) +, End(5000) +, Style(L"Default") +, Actor(L"") +, Effect(L"") +, Text(L"") +{ + group = L"[Events]"; Valid = true; - SetStartMS(0); - SetEndMS(5000); - Layer = 0; for (int i=0;i<4;i++) Margin[i] = 0; - Text = _T(""); - Style = _T("Default"); - Actor = _T(""); - Effect = _T(""); - Comment = false; - UpdateData(); } - - /// @brief DOCME /// @param _data /// @param version -/// -AssDialogue::AssDialogue(wxString _data,int version) { - // Set group - group = _T("[Events]"); - +AssDialogue::AssDialogue(wxString _data,int version) +: Comment(false) +, Layer(0) +, Start(0) +, End(5000) +, Style(L"Default") +, Actor(L"") +, Effect(L"") +, Text(L"") +{ + group = L"[Events]"; + Valid = false; // Try parsing in different ways int count = 0; - Valid = false; while (!Valid && count < 3) { Valid = Parse(_data,version); count++; @@ -95,30 +95,20 @@ AssDialogue::AssDialogue(wxString _data,int version) { throw _T("Failed parsing line."); } - // update UpdateData(); } - - /// @brief Destructor -/// AssDialogue::~AssDialogue () { Clear(); } - - /// @brief Clear -/// void AssDialogue::Clear () { ClearBlocks(); } - - /// @brief Clear blocks -/// void AssDialogue::ClearBlocks() { using std::vector; for (vector::iterator cur=Blocks.begin();cur!=Blocks.end();cur++) { @@ -127,13 +117,10 @@ void AssDialogue::ClearBlocks() { Blocks.clear(); } - - /// @brief Parse ASS Data /// @param rawData /// @param version /// @return -/// bool AssDialogue::Parse(wxString rawData, int version) { size_t pos = 0; wxString temp; @@ -168,7 +155,6 @@ bool AssDialogue::Parse(wxString rawData, int version) { // Get start time if (!tkn.HasMoreTokens()) return false; Start.ParseASS(tkn.GetNextToken()); - FixStartMS(); // Get end time if (!tkn.HasMoreTokens()) return false; @@ -227,11 +213,8 @@ bool AssDialogue::Parse(wxString rawData, int version) { return true; } - - /// @brief Make data /// @return -/// wxString AssDialogue::MakeData() { // Prepare static wxString final = _T(""); @@ -270,35 +253,23 @@ wxString AssDialogue::MakeData() { return final; } - - /// @brief Update AssDialogue's data line -/// void AssDialogue::UpdateData () { } - - /// @brief Get entry data /// @return -/// const wxString AssDialogue::GetEntryData() { return MakeData(); } - - /// @brief Set entry data /// @param newData -/// void AssDialogue::SetEntryData(wxString newData) { } - - /// @brief Get SSA version of Dialogue /// @return -/// wxString AssDialogue::GetSSAText () { // Prepare wxString work = _T(""); @@ -331,10 +302,7 @@ wxString AssDialogue::GetSSAText () { return work; } - - /// @brief Yea, I convert to ASS tags, then parse that. So sue me. -------------- Parse SRT tags -/// void AssDialogue::ParseSRTTags () { // Search and replace size_t total = 0; @@ -470,10 +438,7 @@ void AssDialogue::ParseSRTTags () { UpdateData(); } - - /// @brief Parse ASS tags -/// void AssDialogue::ParseASSTags () { // Clear blocks ClearBlocks(); @@ -567,20 +532,14 @@ void AssDialogue::ParseASSTags () { } } - - /// @brief Strip tags -/// void AssDialogue::StripTags () { static wxRegEx reg(_T("\\{[^\\{]*\\}"),wxRE_ADVANCED); reg.Replace(&Text,_T("")); } - - /// @brief Strip a specific tag /// @param tagName -/// void AssDialogue::StripTag (wxString tagName) { // Parse using std::list; @@ -609,10 +568,7 @@ void AssDialogue::StripTag (wxString tagName) { UpdateData(); } - - /// @brief TODO: Improve this code ------------------- Convert tags to SRT -/// void AssDialogue::ConvertTagsToSRT () { // Setup using std::list; @@ -712,10 +668,7 @@ void AssDialogue::ConvertTagsToSRT () { ClearBlocks(); } - - /// @brief Updates text from tags -/// void AssDialogue::UpdateText () { using std::vector; Text = _T(""); @@ -729,12 +682,9 @@ void AssDialogue::UpdateText () { } } - - /// @brief Sets margin from a string /// @param origvalue /// @param which -/// void AssDialogue::SetMarginString(const wxString origvalue,int which) { // Make it numeric wxString strvalue = origvalue; @@ -760,13 +710,10 @@ void AssDialogue::SetMarginString(const wxString origvalue,int which) { Margin[which] = value; } - - /// @brief Gets string for margin /// @param which /// @param pad /// @return -/// wxString AssDialogue::GetMarginString(int which,bool pad) { if (which < 0 || which >= 4) throw Aegisub::InvalidMarginIdError(); int value = Margin[which]; @@ -774,8 +721,6 @@ wxString AssDialogue::GetMarginString(int which,bool pad) { else return wxString::Format(_T("%i"),value); } - - void AssDialogue::ProcessParameters(AssDialogueBlockOverride::ProcessParametersCallback callback,void *userData) { // Apply for all override blocks AssDialogueBlockOverride *curBlock; @@ -789,12 +734,9 @@ void AssDialogue::ProcessParameters(AssDialogueBlockOverride::ProcessParametersC //ClearBlocks(); } - - /// @brief Checks if two lines collide /// @param target /// @return -/// bool AssDialogue::CollidesWith(AssDialogue *target) { if (!target) return false; int a = Start.GetMS(); @@ -804,11 +746,8 @@ bool AssDialogue::CollidesWith(AssDialogue *target) { return ((a < c) ? (c < b) : (a < d)); } - - /// @brief Return just the text without any overrides /// @return -/// wxString AssDialogue::GetStrippedText() const { wxString justtext = wxString(_T("")); bool inCode = false; @@ -823,7 +762,6 @@ wxString AssDialogue::GetStrippedText() const { /// @brief Clone /// @return -/// AssEntry *AssDialogue::Clone() const { // Create clone AssDialogue *final = new AssDialogue(); @@ -836,37 +774,26 @@ AssEntry *AssDialogue::Clone() const { final->Effect = Effect; final->Layer = Layer; for (int i=0;i<4;i++) final->Margin[i] = Margin[i]; - final->SetStartMS(GetStartMS()); - final->SetEndMS(GetEndMS()); + final->Start = Start; + final->End = End; final->Style = Style; final->Text = Text; - //final->SetEntryData(GetEntryData()); - // Return return final; } - - -/// @brief Constructor AssDialogueBlock ////////////////////// -/// +/// @brief Constructor AssDialogueBlock AssDialogueBlock::AssDialogueBlock () { } - - /// @brief Destructor /// @return -/// AssDialogueBlock::~AssDialogueBlock () { } - - /// @brief If it isn't a plain block, returns NULL ---------------------- Returns as a plain block /// @param base /// @return -/// AssDialogueBlockPlain *AssDialogueBlock::GetAsPlain(AssDialogueBlock *base) { if (!base) return NULL; if (base->GetType() == BLOCK_PLAIN) { @@ -875,12 +802,9 @@ AssDialogueBlockPlain *AssDialogueBlock::GetAsPlain(AssDialogueBlock *base) { return NULL; } - - /// @brief If it isn't an override block, returns NULL ---------------------------- Returns as an override block /// @param base /// @return -/// AssDialogueBlockOverride *AssDialogueBlock::GetAsOverride(AssDialogueBlock *base) { if (!base) return NULL; if (base->GetType() == BLOCK_OVERRIDE) { @@ -889,12 +813,9 @@ AssDialogueBlockOverride *AssDialogueBlock::GetAsOverride(AssDialogueBlock *base return NULL; } - - /// @brief If it isn't an drawing block, returns NULL ---------------------------- Returns as a drawing block /// @param base /// @return -/// AssDialogueBlockDrawing *AssDialogueBlock::GetAsDrawing(AssDialogueBlock *base) { if (!base) return NULL; if (base->GetType() == BLOCK_DRAWING) { @@ -903,28 +824,19 @@ AssDialogueBlockDrawing *AssDialogueBlock::GetAsDrawing(AssDialogueBlock *base) return NULL; } - - /// @brief Constructor AssDialogueBlockPlain ////////////////////// -/// AssDialogueBlockPlain::AssDialogueBlockPlain () { } - - /// @brief Constructor AssDialogueBlockDrawing ////////////////////// -/// AssDialogueBlockDrawing::AssDialogueBlockDrawing () { } - - /// @brief Multiply coordinates /// @param mx /// @param my /// @param x /// @param y -/// void AssDialogueBlockDrawing::TransformCoords(int mx,int my,double x,double y) { // HACK: Implement a proper parser ffs!! wxStringTokenizer tkn(GetText(),_T(" "),wxTOKEN_DEFAULT); @@ -963,7 +875,3 @@ void AssDialogueBlockDrawing::TransformCoords(int mx,int my,double x,double y) { text = final; } - - - - diff --git a/aegisub/src/ass_dialogue.h b/aegisub/src/ass_dialogue.h index 2e227b64c..df2816459 100644 --- a/aegisub/src/ass_dialogue.h +++ b/aegisub/src/ass_dialogue.h @@ -202,36 +202,28 @@ private: public: - /// DOCME - std::vector Blocks; // Contains information about each block of text + /// Contains information about each block of text + std::vector Blocks; - /// DOCME - bool Comment; // Is this a comment line? - - /// DOCME - int Layer; // Layer number - - /// DOCME - int Margin[4]; // Margins: 0 = Left, 1 = Right, 2 = Top (Vertical), 3 = Bottom - - /// DOCME - AssTime Start; // Starting time - - /// DOCME - AssTime End; // Ending time - - /// DOCME - wxString Style; // Style name - - /// DOCME - wxString Actor; // Actor name - - /// DOCME - wxString Effect; // Effect name - - /// DOCME - wxString Text; // Raw text data + /// Is this a comment line? + bool Comment; + /// Layer number + int Layer; + /// Margins: 0 = Left, 1 = Right, 2 = Top (Vertical), 3 = Bottom + int Margin[4]; + /// Starting time + AssTime Start; + /// Ending time + AssTime End; + /// Style name + wxString Style; + /// Actor name + wxString Actor; + /// Effect name + wxString Effect; + /// Raw text data + wxString Text; /// @brief DOCME @@ -260,30 +252,6 @@ public: void Clear(); // Wipes all data - /// @brief DOCME - /// @return - /// - virtual int GetStartMS() const { return Start.GetMS(); } - - /// @brief DOCME - /// @return - /// - virtual int GetEndMS() const { return End.GetMS(); } - - /// @brief DOCME - /// @param newStart - /// - virtual void SetStartMS(const int newStart) { AssEntry::SetStartMS(newStart); Start.SetMS(newStart); } - - /// @brief DOCME - /// @param newEnd - /// - virtual void SetEndMS(const int newEnd) { End.SetMS(newEnd); } - - /// @brief DOCME - /// - void FixStartMS() { AssEntry::SetStartMS(Start.GetMS()); } // Update StartMS in AssEntry from the Start value here - void SetMarginString(const wxString value,int which); // Set string to a margin value (0 = left, 1 = right, 2 = vertical/top, 3 = bottom) wxString GetMarginString(int which,bool pad=true); // Returns the string of a margin value (0 = left, 1 = right, 2 = vertical/top, 3 = bottom) wxString GetSSAText(); diff --git a/aegisub/src/ass_entry.cpp b/aegisub/src/ass_entry.cpp index 69151bf13..661509222 100644 --- a/aegisub/src/ass_entry.cpp +++ b/aegisub/src/ass_entry.cpp @@ -45,13 +45,11 @@ #include "ass_style.h" -/// @brief Constructs AssEntry AssEntry ////////////////////// -/// +/// @brief Constructs AssEntry AssEntry::AssEntry() { Valid = true; } - /// @brief DOCME /// @param _data /// @@ -60,26 +58,11 @@ AssEntry::AssEntry(wxString _data) { Valid = true; } - - /// @brief Destructor for AssEntry /// AssEntry::~AssEntry() { } - - -/// @brief Comparison for STL Sort -/// @param t1 -/// @param t2 -/// @return -/// -bool operator < (const AssEntry &t1, const AssEntry &t2) { - return (t1.GetStartMS() < t2.GetStartMS()); -} - - - /// @brief Returns an entry as dialogue if possible, else, returns NULL /// @param base /// @return @@ -92,8 +75,6 @@ AssDialogue *AssEntry::GetAsDialogue(AssEntry *base) { return NULL; } - - /// @brief Returns an entry as style if possible, else, returns NULL /// @param base /// @return @@ -106,8 +87,6 @@ AssStyle *AssEntry::GetAsStyle(AssEntry *base) { return NULL; } - - /// @brief Returns an entry as attachment if possible, else, returns NULL /// @param base /// @return @@ -120,8 +99,6 @@ AssAttachment *AssEntry::GetAsAttachment(AssEntry *base) { return NULL; } - - /// @brief Get SSA conversion /// @return /// @@ -136,8 +113,6 @@ wxString AssEntry::GetSSAText() { return GetEntryData(); } - - /// @brief Clone /// AssEntry *AssEntry::Clone() const { @@ -147,11 +122,8 @@ AssEntry *AssEntry::Clone() const { // Copy data final->data = data; final->group = group; - final->StartMS = StartMS; final->Valid = Valid; // Return return final; } - - diff --git a/aegisub/src/ass_entry.h b/aegisub/src/ass_entry.h index 636f97254..1901a808e 100644 --- a/aegisub/src/ass_entry.h +++ b/aegisub/src/ass_entry.h @@ -109,9 +109,6 @@ private: /// DOCME wxString data; // Raw data, exactly the same line that appears on the .ass (note that this will be in ass even if source wasn't) - /// DOCME - int StartMS; // This is only stored for sorting issues, in order to keep non-dialogue lines aligned - public: /// DOCME @@ -126,29 +123,6 @@ public: virtual AssEntry *Clone() const; - - /// @brief DOCME - /// @return - /// - virtual int GetStartMS() const { return StartMS; } - - /// @brief DOCME - /// @return - /// - virtual int GetEndMS() const { return StartMS; } - - /// @brief DOCME - /// @param newStart - /// - virtual void SetStartMS(const int newStart) { StartMS = newStart; } - - /// @brief DOCME - /// @param newEnd - /// @return - /// - virtual void SetEndMS(const int newEnd) { /* do nothing */ (void)newEnd; } - - /// @brief DOCME /// @return /// @@ -169,8 +143,3 @@ public: static AssStyle *GetAsStyle(AssEntry *base); // Returns an entry base as a style if it is valid, null otherwise static AssAttachment *GetAsAttachment(AssEntry *base);// Returns an entry base as an attachment if it is valid, null otherwise }; - -// This operator is for sorting -bool operator < (const AssEntry &t1, const AssEntry &t2); - - diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp index f5c80efe9..021e7206d 100644 --- a/aegisub/src/ass_file.cpp +++ b/aegisub/src/ass_file.cpp @@ -32,11 +32,7 @@ /// @file ass_file.cpp /// @brief Overall storage of subtitle files, undo management and more /// @ingroup subs_storage -/// - -//////////// -// Includes #include "config.h" #ifndef AGI_PRE @@ -61,28 +57,21 @@ #include "version.h" #include "vfr.h" -/// @brief AssFile constructor AssFile ////////////////////// -/// +/// @brief AssFile constructor AssFile::AssFile () { AssOverrideTagProto::LoadProtos(); Clear(); } - - /// @brief AssFile destructor -/// AssFile::~AssFile() { Clear(); } - - /// @brief Load generic subs /// @param file /// @param charset /// @param addToRecent -/// void AssFile::Load (const wxString _filename,const wxString charset,bool addToRecent) { bool ok = true; @@ -153,14 +142,11 @@ void AssFile::Load (const wxString _filename,const wxString charset,bool addToRe if (addToRecent) AddToRecent(_filename); } - - /// @brief Save a file to Hard Disk /// @param _filename /// @param setfilename /// @param addToRecent /// @param encoding -/// void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wxString encoding) { // Finds last dot int i = 0; @@ -192,12 +178,9 @@ void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wx } } - - /// @brief Saves a file to a ram vector /// @param dst /// @param encoding -/// void AssFile::SaveMemory(std::vector &dst,const wxString encoding) { // Set encoding wxString enc = encoding; @@ -240,22 +223,16 @@ void AssFile::SaveMemory(std::vector &dst,const wxString encoding) { } } - - /// @brief Exports file with proper transformations /// @param _filename -/// void AssFile::Export(wxString _filename) { AssExporter exporter(this); exporter.AddAutoFilters(); exporter.Export(_filename,_T("UTF-8")); } - - /// @brief Can save file? /// @return -/// bool AssFile::CanSave() { // ASS format? wxString ext = filename.Lower().Right(4); @@ -307,25 +284,6 @@ bool AssFile::CanSave() { return true; } - -//////////////////////////////////// -// Returns script as a single string -//wxString AssFile::GetString() { -// using std::list; -// wxString ret; -// AssEntry *entry; -// ret += 0xfeff; -// for (list::iterator cur=Line.begin();cur!=Line.end();) { -// entry = *cur; -// ret += entry->GetEntryData(); -// ret += L"\n"; -// cur++; -// } -// return ret; -//} - - - /// @brief even moving things out of order might break ASS parsing - AMZ. I strongly advice you against touching this function unless you know what you're doing; ------------------- Appends line to Ass /// @param data /// @param group @@ -333,8 +291,7 @@ bool AssFile::CanSave() { /// @param version /// @param outGroup /// @return -/// -int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxString *outGroup) { +void AssFile::AddLine (wxString data,wxString group,int &version,wxString *outGroup) { // Group AssEntry *entry = NULL; wxString origGroup = group; @@ -372,10 +329,9 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS // Create attachment if needed if (isFilename) { attach = new AssAttachment(data.Mid(10)); - attach->SetStartMS(lasttime); attach->group = group; keepGroup = group; - return lasttime; + return; } // Valid data? @@ -395,7 +351,7 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS // Not done else { - return lasttime; + return; } } } @@ -404,15 +360,12 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS if (lowGroup == _T("[events]")) { if ((data.Left(9) == _T("Dialogue:") || data.Left(8) == _T("Comment:"))) { AssDialogue *diag = new AssDialogue(data,version); - lasttime = diag->GetStartMS(); //diag->ParseASSTags(); entry = diag; - entry->SetStartMS(lasttime); entry->group = group; } if (data.Left(7) == _T("Format:")) { entry = new AssEntry(_T("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text")); - entry->SetStartMS(lasttime); entry->group = group; } } @@ -422,12 +375,10 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS if (data.Left(6) == _T("Style:")) { AssStyle *style = new AssStyle(data,version); entry = style; - entry->SetStartMS(lasttime); entry->group = group; } if (data.Left(7) == _T("Format:")) { entry = new AssEntry(_T("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding")); - entry->SetStartMS(lasttime); entry->group = group; } } @@ -438,7 +389,7 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS if (data.Left(1) == _T(";")) { // Skip stupid comments added by other programs // Of course, we'll add our own in place later... ;) - return lasttime; + return; } // Version @@ -460,26 +411,21 @@ int AssFile::AddLine (wxString data,wxString group,int lasttime,int &version,wxS // Everything entry = new AssEntry(data); - entry->SetStartMS(lasttime); entry->group = group; } // Common entry if (entry == NULL) { entry = new AssEntry(data); - entry->SetStartMS(lasttime); entry->group = group; } // Insert the line Line.push_back(entry); - return lasttime; + return; } - - /// @brief Clears contents of assfile -/// void AssFile::Clear () { for (std::list::iterator cur=Line.begin();cur != Line.end();cur++) { if (*cur) delete *cur; @@ -491,11 +437,8 @@ void AssFile::Clear () { Modified = false; } - - /// @brief Loads default subs /// @param defline -/// void AssFile::LoadDefault (bool defline) { // Clear first Clear(); @@ -503,34 +446,31 @@ void AssFile::LoadDefault (bool defline) { // Write headers AssStyle defstyle; int version = 1; - AddLine(_T("[Script Info]"),_T("[Script Info]"),-1,version); - AddLine(_T("Title: Default Aegisub file"),_T("[Script Info]"),-1,version); - AddLine(_T("ScriptType: v4.00+"),_T("[Script Info]"),-1,version); - AddLine(_T("WrapStyle: 0"), _T("[Script Info]"),-1,version); - AddLine(_T("PlayResX: 640"),_T("[Script Info]"),-1,version); - AddLine(_T("PlayResY: 480"),_T("[Script Info]"),-1,version); - AddLine(_T("ScaledBorderAndShadow: yes"),_T("[Script Info]"),-1,version); - AddLine(_T(""),_T("[Script Info]"),-1,version); - AddLine(_T("[V4+ Styles]"),_T("[V4+ Styles]"),-1,version); - AddLine(_T("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"),_T("[V4+ Styles]"),-1,version); - AddLine(defstyle.GetEntryData(),_T("[V4+ Styles]"),-1,version); - AddLine(_T(""),_T("[V4+ Styles]"),-1,version); - AddLine(_T("[Events]"),_T("[Events]"),-1,version); - AddLine(_T("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"),_T("[Events]"),-1,version); + AddLine(_T("[Script Info]"),_T("[Script Info]"),version); + AddLine(_T("Title: Default Aegisub file"),_T("[Script Info]"),version); + AddLine(_T("ScriptType: v4.00+"),_T("[Script Info]"),version); + AddLine(_T("WrapStyle: 0"), _T("[Script Info]"),version); + AddLine(_T("PlayResX: 640"),_T("[Script Info]"),version); + AddLine(_T("PlayResY: 480"),_T("[Script Info]"),version); + AddLine(_T("ScaledBorderAndShadow: yes"),_T("[Script Info]"),version); + AddLine(_T(""),_T("[Script Info]"),version); + AddLine(_T("[V4+ Styles]"),_T("[V4+ Styles]"),version); + AddLine(_T("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"),_T("[V4+ Styles]"),version); + AddLine(defstyle.GetEntryData(),_T("[V4+ Styles]"),version); + AddLine(_T(""),_T("[V4+ Styles]"),version); + AddLine(_T("[Events]"),_T("[Events]"),version); + AddLine(_T("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"),_T("[Events]"),version); if (defline) { AssDialogue def; - AddLine(def.GetEntryData(),_T("[Events]"),0,version); + AddLine(def.GetEntryData(),_T("[Events]"),version); } loaded = true; } - - /// @brief Copy constructor /// @param from -/// AssFile::AssFile (AssFile &from) { using std::list; @@ -545,11 +485,8 @@ AssFile::AssFile (AssFile &from) { } } - - /// @brief Insert a new style /// @param style -/// void AssFile::InsertStyle (AssStyle *style) { // Variables using std::list; @@ -565,7 +502,6 @@ void AssFile::InsertStyle (AssStyle *style) { if (curEntry->GetType() == ENTRY_STYLE || (lastGroup == _T("[V4+ Styles]") && curEntry->GetEntryData().substr(0,7) == _T("Format:"))) { lastStyle = cur; } - lasttime = curEntry->GetStartMS(); lastGroup = curEntry->group; } @@ -574,24 +510,20 @@ void AssFile::InsertStyle (AssStyle *style) { // Add space curEntry = new AssEntry(_T("")); curEntry->group = lastGroup; - curEntry->SetStartMS(lasttime); Line.push_back(curEntry); // Add header curEntry = new AssEntry(_T("[V4+ Styles]")); curEntry->group = _T("[V4+ Styles]"); - curEntry->SetStartMS(lasttime); Line.push_back(curEntry); // Add format line curEntry = new AssEntry(_T("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding")); curEntry->group = _T("[V4+ Styles]"); - curEntry->SetStartMS(lasttime); Line.push_back(curEntry); // Add style style->group = _T("[V4+ Styles]"); - style->SetStartMS(lasttime); Line.push_back(style); } @@ -599,16 +531,12 @@ void AssFile::InsertStyle (AssStyle *style) { else { lastStyle++; style->group = (*lastStyle)->group; - style->SetStartMS(lasttime); Line.insert(lastStyle,style); } } - - /// @brief Insert attachment /// @param attach -/// void AssFile::InsertAttachment (AssAttachment *attach) { // Search for insertion point std::list::iterator insPoint=Line.end(),cur; @@ -629,27 +557,21 @@ void AssFile::InsertAttachment (AssAttachment *attach) { // Found point, insert there if (insPoint != Line.end()) { insPoint++; - attach->SetStartMS((*insPoint)->GetStartMS()); Line.insert(insPoint,attach); } // Otherwise, create the [Fonts] group and insert else { int version=1; - int StartMS = Line.back()->GetStartMS(); - AddLine(_T(""),Line.back()->group,StartMS,version); - AddLine(attach->group,attach->group,StartMS,version); - attach->SetStartMS(StartMS); + AddLine(_T(""),Line.back()->group,version); + AddLine(attach->group,attach->group,version); Line.push_back(attach); - AddLine(_T(""),attach->group,StartMS,version); + AddLine(_T(""),attach->group,version); } } - - /// @brief Insert attachment from file /// @param filename -/// void AssFile::InsertAttachment (wxString filename) { // Get name wxFileName fname(filename); @@ -673,12 +595,9 @@ void AssFile::InsertAttachment (wxString filename) { InsertAttachment(newAttach); } - - /// @brief Gets script info /// @param _key /// @return -/// wxString AssFile::GetScriptInfo(const wxString _key) { // Prepare wxString key = _key;; @@ -709,12 +628,9 @@ wxString AssFile::GetScriptInfo(const wxString _key) { return _T(""); } - - /// @brief Get script info as int /// @param key /// @return -/// int AssFile::GetScriptInfoAsInt(const wxString key) { long temp = 0; try { @@ -726,13 +642,10 @@ int AssFile::GetScriptInfoAsInt(const wxString key) { return temp; } - - /// @brief Set a script info line /// @param _key /// @param value /// @return -/// void AssFile::SetScriptInfo(const wxString _key,const wxString value) { // Prepare wxString key = _key;; @@ -778,7 +691,6 @@ void AssFile::SetScriptInfo(const wxString _key,const wxString value) { result += value; AssEntry *entry = new AssEntry(result); entry->group = (*prev)->group; - entry->SetStartMS((*prev)->GetStartMS()); Line.insert(++prev,entry); } return; @@ -786,12 +698,9 @@ void AssFile::SetScriptInfo(const wxString _key,const wxString value) { } } - - /// @brief Get resolution /// @param sw /// @param sh -/// void AssFile::GetResolution(int &sw,int &sh) { // Height wxString temp = GetScriptInfo(_T("PlayResY")); @@ -832,11 +741,8 @@ void AssFile::GetResolution(int &sw,int &sh) { } } - - /// @brief Adds a comment to [Script Info] /// @param _comment -/// void AssFile::AddComment(const wxString _comment) { wxString comment = _T("; "); comment += _comment; @@ -853,18 +759,14 @@ void AssFile::AddComment(const wxString _comment) { AssEntry *prev = *cur; AssEntry *comm = new AssEntry(comment); comm->group = prev->group; - comm->SetStartMS(prev->GetStartMS()); Line.insert(cur,comm); break; } } } - - /// @brief Get list of styles /// @return -/// wxArrayString AssFile::GetStyles() { wxArrayString styles; AssStyle *curstyle; @@ -877,12 +779,9 @@ wxArrayString AssFile::GetStyles() { return styles; } - - /// @brief Gets style of specific name /// @param name /// @return -/// AssStyle *AssFile::GetStyle(wxString name) { AssStyle *curstyle; for (entryIter cur=Line.begin();cur!=Line.end();cur++) { @@ -894,38 +793,24 @@ AssStyle *AssFile::GetStyle(wxString name) { return NULL; } - - /// @brief Adds file name to list of recent /// @param file -/// void AssFile::AddToRecent(wxString file) { Options.AddToRecentList(file,_T("Recent sub")); } - - /// @brief List of supported wildcards /// @param mode /// @return -/// wxString AssFile::GetWildcardList(int mode) { - //if (mode == 0) return _T("All Supported Types (*.ass,*.ssa,*.srt,*.txt,*.mkv,*.mks,*.mka)|*.ass;*.ssa;*.srt;*.txt;*.mkv;*.mks;*.mka|Advanced Substation Alpha (*.ass)|*.ass|Substation Alpha (*.ssa)|*.ssa|SubRip (*.srt)|*.srt|Plain-text (*.txt)|*.txt|Matroska (*.mkv,*.mks,*.mka)|*.mkv;*.mks;*.mka"); - //else if (mode == 1) return _T("Advanced Substation Alpha (*.ass)|*.ass"); - //else if (mode == 2) return _T("All Supported Types (*.ass,*.ssa,*.srt,*.txt,*.mkv,*.mks,*.mka)|*.ass;*.ssa;*.srt;*.txt|Advanced Substation Alpha (*.ass)|*.ass|Substation Alpha (*.ssa)|*.ssa|SubRip (*.srt)|*.srt|Plain-text (*.txt)|*.txt"); - //else return _T(""); - if (mode == 0) return SubtitleFormat::GetWildcards(0); else if (mode == 1) return _T("Advanced Substation Alpha (*.ass)|*.ass"); else if (mode == 2) return SubtitleFormat::GetWildcards(1); else return _T(""); } - - /// @brief Compress/decompress for storage on stack /// @param compress -/// void AssFile::CompressForStack(bool compress) { AssDialogue *diag; for (entryIter cur=Line.begin();cur!=Line.end();cur++) { @@ -940,20 +825,14 @@ void AssFile::CompressForStack(bool compress) { } } - - /// @brief Checks if file is modified /// @return -/// bool AssFile::IsModified() { return Modified; } - - /// @brief Flag file as modified /// @param desc -/// void AssFile::FlagAsModified(wxString desc) { // Clear redo if (!RedoStack.empty()) { @@ -969,11 +848,8 @@ void AssFile::FlagAsModified(wxString desc) { StackPush(desc); } - - /// @brief Stack push /// @param desc -/// void AssFile::StackPush(wxString desc) { // Places copy on stack AssFile *curcopy = new AssFile(*top); @@ -995,10 +871,7 @@ void AssFile::StackPush(wxString desc) { } } - - /// @brief Stack pop -/// void AssFile::StackPop() { bool addcopy = false; wxString undodesc=_T(""); @@ -1029,10 +902,7 @@ void AssFile::StackPop() { } } - - /// @brief Stack redo -/// void AssFile::StackRedo() { bool addcopy = false; @@ -1058,10 +928,7 @@ void AssFile::StackRedo() { } } - - /// @brief Stack clear -/// void AssFile::StackClear() { // Clear undo for (std::list::iterator cur=UndoStack.begin();cur!=UndoStack.end();cur++) { @@ -1078,11 +945,8 @@ void AssFile::StackClear() { Popping = false; } - - /// @brief Stack reset /// @return -/// void AssFile::StackReset() { StackClear(); delete top; @@ -1090,42 +954,73 @@ void AssFile::StackReset() { StackModified = false; } - - /// @brief Returns if undo stack is empty /// @return -/// bool AssFile::IsUndoStackEmpty() { if (StackModified) return (UndoStack.size() <= 1); else return UndoStack.empty(); } - - /// @brief Returns if redo stack is empty /// @return -/// bool AssFile::IsRedoStackEmpty() { return RedoStack.empty(); } - /// @brief DOCME /// @return -/// wxString AssFile::GetUndoDescription() { return (IsUndoStackEmpty())?_T(""):(UndoStack.back())->undodescription; } - /// @brief DOCME /// @return -/// wxString AssFile::GetRedoDescription() { return (IsRedoStackEmpty())?_T(""):(RedoStack.back())->undodescription; - } +bool AssFile::CompStart(const AssDialogue* lft, const AssDialogue* rgt) { + return lft->Start < rgt->Start; +} +bool AssFile::CompEnd(const AssDialogue* lft, const AssDialogue* rgt) { + return lft->End < rgt->End; +} +bool AssFile::CompStyle(const AssDialogue* lft, const AssDialogue* rgt) { + return lft->Style < rgt->Style; +} + +void AssFile::Sort(CompFunc comp) { + Sort(Line, comp); +} +void AssFile::Sort(std::list &lst, CompFunc comp) { + // uguu c++ closures uguu + struct : public std::binary_function { + CompFunc comp; + bool operator()(const AssEntry* a, const AssEntry* b) const { + return comp(static_cast(a), static_cast(b)); + } + } compE; + compE.comp = comp; + // Sort each block of AssDialogues separately, leaving everything else untouched + for (entryIter begin = lst.begin(); begin != lst.end(); ++begin) { + if (!dynamic_cast(*begin)) continue; + entryIter end = begin; + while (end != lst.end() && dynamic_cast(*end)) ++end; + + // std::list::sort doesn't support sorting only part of the list, but + // splice is constant-time, so just sort a temp list with only the part we + // want sorted + std::list tmp; + tmp.splice(tmp.begin(), lst, begin, end); + tmp.sort(compE); + lst.splice(end, tmp); + + begin = --end; + } +} +void AssFile::Sort(std::list &lst, CompFunc comp) { + lst.sort(comp); +} /// DOCME AssFile *AssFile::top; @@ -1141,9 +1036,3 @@ bool AssFile::Popping; /// DOCME bool AssFile::StackModified; - - - - - - diff --git a/aegisub/src/ass_file.h b/aegisub/src/ass_file.h index f9a83b463..30d585de8 100644 --- a/aegisub/src/ass_file.h +++ b/aegisub/src/ass_file.h @@ -37,9 +37,6 @@ #pragma once - -/////////// -// Headers #ifndef AGI_PRE #include #include @@ -48,9 +45,6 @@ #include #endif - -////////////// -// Prototypes class FrameRate; class AssDialogue; class AssStyle; @@ -60,7 +54,7 @@ class AssDialogueBlockOverride; class AssDialogueBlockPlain; class AssEntry; - +typedef std::list::iterator entryIter; /// DOCME /// @class AssFile @@ -128,7 +122,7 @@ public: wxString GetScriptInfo(const wxString key); // Returns the value in a [Script Info] key as string. void SetScriptInfo(const wxString key,const wxString value); // Sets the value of a [Script Info] key. Adds it if it doesn't exist. void AddComment(const wxString comment); // Adds a ";" comment under [Script Info]. - int AddLine(wxString data,wxString group,int lasttime,int &version,wxString *outGroup=NULL); + void AddLine(wxString data,wxString group,int &version,wxString *outGroup=NULL); static void StackPop(); // Pop subs from stack and sets 'top' to it static void StackRedo(); // Redoes action on stack @@ -144,33 +138,24 @@ public: /// DOCME static AssFile *top; // Current script file. It is "above" the stack. + + /// Comparison function for use when sorting + typedef bool (*CompFunc)(const AssDialogue* lft, const AssDialogue* rgt); + + /// @brief Compare based on start time + static bool CompStart(const AssDialogue* lft, const AssDialogue* rgt); + /// @brief Compare based on end time + static bool CompEnd(const AssDialogue* lft, const AssDialogue* rgt); + /// @brief Compare based on end time + static bool CompStyle(const AssDialogue* lft, const AssDialogue* rgt); + + /// @brief Sort the dialogue lines in this file + /// @param comp Comparison function to use. Defaults to sorting by start time. + void Sort(CompFunc comp = CompStart); + /// @brief Sort the dialogue lines in the given list + /// @param comp Comparison function to use. Defaults to sorting by start time. + static void Sort(std::list& lst, CompFunc comp = CompStart); + /// @brief Sort the dialogue lines in the given list + /// @param comp Comparison function to use. Defaults to sorting by start time. + static void Sort(std::list& lst, CompFunc comp = CompStart); }; - - - -/// DOCME -typedef std::list::iterator entryIter; - - -////////////////////////////////////////////////////// -// Hack to get STL sort to work on a list of pointers -template - -/// DOCME -/// @class LessByPointedToValue -/// @brief DOCME -/// -/// DOCME -class LessByPointedToValue : std::binary_function { -public: - - /// @brief DOCME - /// @param x - /// @param y - /// - bool operator()(T const * x, T const * y) const { - return std::less()(*x, *y); - } -}; - - diff --git a/aegisub/src/ass_style.cpp b/aegisub/src/ass_style.cpp index c7d3059c3..a84058d34 100644 --- a/aegisub/src/ass_style.cpp +++ b/aegisub/src/ass_style.cpp @@ -549,7 +549,6 @@ AssEntry *AssStyle::Clone() const { // Copy data final->group = group; - final->SetStartMS(GetStartMS()); final->Valid = Valid; final->alignment = alignment; final->angle = angle; diff --git a/aegisub/src/ass_time.cpp b/aegisub/src/ass_time.cpp index 32fc7f828..23fdf9b95 100644 --- a/aegisub/src/ass_time.cpp +++ b/aegisub/src/ass_time.cpp @@ -53,11 +53,9 @@ #include "vfr.h" -/// @brief AssTime constructors AssTime ////////////////////// -/// -AssTime::AssTime () { - time = 0; -} +/// @brief AssTime constructors +AssTime::AssTime () : time(0) { } +AssTime::AssTime (int time) : time(time) { } @@ -271,7 +269,7 @@ wxString AssTime::GetSRTFormated () { /// @param t2 /// @return /// -bool operator < (AssTime &t1, AssTime &t2) { +bool operator < (const AssTime &t1, const AssTime &t2) { return (t1.GetMS() < t2.GetMS()); } @@ -281,7 +279,7 @@ bool operator < (AssTime &t1, AssTime &t2) { /// @param t2 /// @return /// -bool operator > (AssTime &t1, AssTime &t2) { +bool operator > (const AssTime &t1, const AssTime &t2) { return (t1.GetMS() > t2.GetMS()); } @@ -291,7 +289,7 @@ bool operator > (AssTime &t1, AssTime &t2) { /// @param t2 /// @return /// -bool operator <= (AssTime &t1, AssTime &t2) { +bool operator <= (const AssTime &t1, const AssTime &t2) { return (t1.GetMS() <= t2.GetMS()); } @@ -301,7 +299,7 @@ bool operator <= (AssTime &t1, AssTime &t2) { /// @param t2 /// @return /// -bool operator >= (AssTime &t1, AssTime &t2) { +bool operator >= (const AssTime &t1, const AssTime &t2) { return (t1.GetMS() >= t2.GetMS()); } @@ -311,7 +309,7 @@ bool operator >= (AssTime &t1, AssTime &t2) { /// @param t2 /// @return /// -bool operator == (AssTime &t1, AssTime &t2) { +bool operator == (const AssTime &t1, const AssTime &t2) { return (t1.GetMS() == t2.GetMS()); } @@ -321,7 +319,7 @@ bool operator == (AssTime &t1, AssTime &t2) { /// @param t2 /// @return /// -bool operator != (AssTime &t1, AssTime &t2) { +bool operator != (const AssTime &t1, const AssTime &t2) { return (t1.GetMS() != t2.GetMS()); } diff --git a/aegisub/src/ass_time.h b/aegisub/src/ass_time.h index 8b9e4da4c..83acdf1f0 100644 --- a/aegisub/src/ass_time.h +++ b/aegisub/src/ass_time.h @@ -64,6 +64,7 @@ public: static bool UseMSPrecision; AssTime(); + AssTime(int ms); int GetTimeHours(); int GetTimeMinutes(); @@ -80,12 +81,12 @@ public: }; // Comparison operators -bool operator == (AssTime &t1, AssTime &t2); -bool operator != (AssTime &t1, AssTime &t2); -bool operator < (AssTime &t1, AssTime &t2); -bool operator > (AssTime &t1, AssTime &t2); -bool operator <= (AssTime &t1, AssTime &t2); -bool operator >= (AssTime &t1, AssTime &t2); +bool operator == (const AssTime &t1, const AssTime &t2); +bool operator != (const AssTime &t1, const AssTime &t2); +bool operator < (const AssTime &t1, const AssTime &t2); +bool operator > (const AssTime &t1, const AssTime &t2); +bool operator <= (const AssTime &t1, const AssTime &t2); +bool operator >= (const AssTime &t1, const AssTime &t2); diff --git a/aegisub/src/dialog_timing_processor.cpp b/aegisub/src/dialog_timing_processor.cpp index 4479d1387..fbfab8665 100644 --- a/aegisub/src/dialog_timing_processor.cpp +++ b/aegisub/src/dialog_timing_processor.cpp @@ -384,14 +384,13 @@ void DialogTimingProcessor::SortDialogues() { tempDiag = grid->GetDialogue(i); if (tempDiag && StyleOK(tempDiag->Style) && !tempDiag->Comment) { if (!onlySelection->IsChecked() || grid->IsInSelection(i)) { - tempDiag->FixStartMS(); temp.push_back(tempDiag); } } } // Sort temporary list - temp.sort(LessByPointedToValue()); + AssFile::Sort(temp); // Copy temporary list to final vector Sorted.clear(); diff --git a/aegisub/src/export_framerate.cpp b/aegisub/src/export_framerate.cpp index a7bfe105b..1c6974273 100644 --- a/aegisub/src/export_framerate.cpp +++ b/aegisub/src/export_framerate.cpp @@ -284,7 +284,7 @@ void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) { // yes, let's framerate compensate the start timestamp and then use the changed value to // compensate it AGAIN 20 lines down? I DO NOT GET IT // -Fluff - //curEntry->SetStartMS(Input->GetTimeAtFrame(Output->GetFrameAtTime(curEntry->GetStartMS(),true),true)); + //curEntry->Start.SetMS(Input->GetTimeAtFrame(Output->GetFrameAtTime(curEntry->GetStartMS(),true),true)); curDialogue = AssEntry::GetAsDialogue(curEntry); // Update dialogue entries @@ -299,8 +299,8 @@ void AssTransformFramerateFilter::TransformFrameRate(AssFile *subs) { // Process stuff curDialogue->ParseASSTags(); curDialogue->ProcessParameters(TransformTimeTags,&data); - curDialogue->SetStartMS(Input->GetTimeAtFrame(Output->GetFrameAtTime(curDialogue->Start.GetMS(),true),true)); - curDialogue->SetEndMS(Input->GetTimeAtFrame(Output->GetFrameAtTime(curDialogue->End.GetMS(),false),false)); + curDialogue->Start.SetMS(Input->GetTimeAtFrame(Output->GetFrameAtTime(curDialogue->Start.GetMS(),true),true)); + curDialogue->End.SetMS(Input->GetTimeAtFrame(Output->GetFrameAtTime(curDialogue->End.GetMS(),false),false)); curDialogue->UpdateText(); curDialogue->UpdateData(); curDialogue->ClearBlocks(); diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp index ecbfb26e3..e7afabf8e 100644 --- a/aegisub/src/frame_main.cpp +++ b/aegisub/src/frame_main.cpp @@ -432,6 +432,15 @@ void FrameMain::InitMenu() { AppendBitmapMenuItem(subtitlesMenu,MENU_RECOMBINE,_("Recombine Lines"),_("Recombine subtitles when they have been split and merged"),GETIMAGE(blank_button_16)); AppendBitmapMenuItem(subtitlesMenu,MENU_SPLIT_BY_KARAOKE,_("Split Lines (by karaoke)"),_("Uses karaoke timing to split line into multiple smaller lines"),GETIMAGE(blank_button_16)); subtitlesMenu->AppendSeparator(); + wxMenu *SortMenu = new wxMenu; + wxMenuItem *SortParent = new wxMenuItem(subtitlesMenu,Menu_Subtitles_Sort_Start,_("Sort Lines"),_T(""),wxITEM_NORMAL,SortMenu); +#ifndef __APPLE__ + SortParent->SetBitmap(GETIMAGE(sort_times_button_16)); +#endif + AppendBitmapMenuItem(SortMenu,Menu_Subtitles_Sort_Start,_("&Start Time"),_("Sort all subtitles by their start times"),GETIMAGE(blank_button_16)); + AppendBitmapMenuItem(SortMenu,Menu_Subtitles_Sort_End,_("&End Time"),_("Sort all subtitles by their end times"),GETIMAGE(blank_button_16)); + AppendBitmapMenuItem(SortMenu,Menu_Subtitles_Sort_Style,_("St&yle Name"),_("Sort all subtitles by their style names"),GETIMAGE(blank_button_16)); + subtitlesMenu->Append(SortParent); AppendBitmapMenuItem(subtitlesMenu,MENU_SWAP,_("Swap Lines"),_("Swaps the two selected lines"),GETIMAGE(arrow_sort_16)); AppendBitmapMenuItem (subtitlesMenu,Menu_Edit_Select, MakeHotkeyText(_("Select Lines..."), _T("Select lines")), _("Selects lines based on defined criterea"),GETIMAGE(select_lines_button_16)); MenuBar->Append(subtitlesMenu, _("&Subtitles")); @@ -439,7 +448,6 @@ void FrameMain::InitMenu() { // Create timing menu timingMenu = new wxMenu(); AppendBitmapMenuItem(timingMenu,Menu_Edit_Shift, MakeHotkeyText(_("S&hift Times..."), _T("Shift times")), _("Shift subtitles by time or frames"),GETIMAGE(shift_times_toolbutton_16)); - AppendBitmapMenuItem(timingMenu,Menu_Edit_Sort, _("Sort by Time"), _("Sort all subtitles by their start times"),GETIMAGE(sort_times_button_16)); AppendBitmapMenuItem(timingMenu,Menu_Tools_Timing_Processor,_("Timing Post-Processor..."), _("Runs a post-processor for timing to deal with lead-ins, lead-outs, scene timing and etc."), GETIMAGE(timing_processor_toolbutton_16)); AppendBitmapMenuItem (timingMenu,Menu_Tools_Kanji_Timer,_("Kanji Timer..."),_("Open Kanji timer"),GETIMAGE(kara_timing_copier_16)); timingMenu->AppendSeparator(); diff --git a/aegisub/src/frame_main.h b/aegisub/src/frame_main.h index 23f4899cc..bb029c3a7 100644 --- a/aegisub/src/frame_main.h +++ b/aegisub/src/frame_main.h @@ -270,7 +270,9 @@ private: void OnReplace (wxCommandEvent &event); void OnJumpTo (wxCommandEvent &event); void OnShift (wxCommandEvent &event); - void OnSort (wxCommandEvent &event); + void OnSortStart (wxCommandEvent &event); + void OnSortEnd (wxCommandEvent &event); + void OnSortStyle (wxCommandEvent &event); void OnEditBoxCommit (wxCommandEvent &event); void OnOpenProperties (wxCommandEvent &event); void OnOpenStylesManager (wxCommandEvent &event); @@ -559,9 +561,6 @@ enum { /// DOCME Menu_Edit_Redo, - /// DOCME - Menu_Edit_Sort, - /// DOCME Menu_Edit_Find, @@ -617,6 +616,10 @@ enum { /// DOCME Menu_Subtitles_Insert, + + Menu_Subtitles_Sort_Start, + Menu_Subtitles_Sort_End, + Menu_Subtitles_Sort_Style, /// DOCME diff --git a/aegisub/src/frame_main_events.cpp b/aegisub/src/frame_main_events.cpp index f0073b8fd..5dbf9e8e9 100644 --- a/aegisub/src/frame_main_events.cpp +++ b/aegisub/src/frame_main_events.cpp @@ -176,7 +176,10 @@ BEGIN_EVENT_TABLE(FrameMain, wxFrame) EVT_MENU(Menu_Edit_Replace, FrameMain::OnReplace) EVT_MENU(Menu_Edit_Shift, FrameMain::OnShift) EVT_MENU(Menu_Edit_Select, FrameMain::OnSelect) - EVT_MENU(Menu_Edit_Sort, FrameMain::OnSort) + + EVT_MENU(Menu_Subtitles_Sort_Start, FrameMain::OnSortStart) + EVT_MENU(Menu_Subtitles_Sort_End, FrameMain::OnSortEnd) + EVT_MENU(Menu_Subtitles_Sort_Style, FrameMain::OnSortStyle) EVT_MENU(Menu_Tools_Properties, FrameMain::OnOpenProperties) EVT_MENU(Menu_Tools_Styles_Manager, FrameMain::OnOpenStylesManager) @@ -1693,31 +1696,27 @@ void FrameMain::OnSelect (wxCommandEvent &event) { select.ShowModal(); } - - -/// @brief Sort subtitles -/// @param event -/// -void FrameMain::OnSort (wxCommandEvent &event) { - // Ensure that StartMS is set properly - AssEntry *curEntry; - AssDialogue *curDiag; - int startMS = -1; - for (std::list::iterator cur = AssFile::top->Line.begin(); cur != AssFile::top->Line.end(); cur++) { - curEntry = *cur; - curDiag = AssEntry::GetAsDialogue(curEntry); - if (curDiag) startMS = curDiag->GetStartMS(); - curEntry->SetStartMS(startMS); - } - - // Sort - AssFile::top->Line.sort(LessByPointedToValue()); +/// @brief Sort subtitles by start time +void FrameMain::OnSortStart (wxCommandEvent &) { + AssFile::top->Sort(); + AssFile::top->FlagAsModified(_("sort")); + SubsBox->UpdateMaps(); + SubsBox->CommitChanges(); +} +/// @brief Sort subtitles by end time +void FrameMain::OnSortEnd (wxCommandEvent &) { + AssFile::top->Sort(AssFile::CompEnd); + AssFile::top->FlagAsModified(_("sort")); + SubsBox->UpdateMaps(); + SubsBox->CommitChanges(); +} +/// @brief Sort subtitles by style name +void FrameMain::OnSortStyle (wxCommandEvent &) { + AssFile::top->Sort(AssFile::CompStyle); AssFile::top->FlagAsModified(_("sort")); SubsBox->UpdateMaps(); SubsBox->CommitChanges(); } - - /// @brief Open styling assistant /// @param event diff --git a/aegisub/src/mkv_wrap.cpp b/aegisub/src/mkv_wrap.cpp index 11d37e06b..bb91a7193 100644 --- a/aegisub/src/mkv_wrap.cpp +++ b/aegisub/src/mkv_wrap.cpp @@ -387,14 +387,13 @@ void MatroskaWrapper::GetSubtitles(AssFile *target) { // Load into file wxString group = _T("[Script Info]"); - int lasttime = 0; int version = 1; if (CodecID == _T("S_TEXT/SSA")) version = 0; wxStringTokenizer token(privString,_T("\r\n"),wxTOKEN_STRTOK); while (token.HasMoreTokens()) { wxString next = token.GetNextToken(); if (next[0] == _T('[')) group = next; - lasttime = target->AddLine(next,group,lasttime,version,&group); + target->AddLine(next,group,version,&group); } // Insert "[Events]" @@ -492,10 +491,9 @@ void MatroskaWrapper::GetSubtitles(AssFile *target) { // Insert into file wxString group = _T("[Events]"); - int lasttime = 0; int version = (CodecID == _T("S_TEXT/SSA")); for (unsigned int i=0;iAddLine(subList[i],group,lasttime,version,&group); + target->AddLine(subList[i],group,version,&group); } // Close progress bar diff --git a/aegisub/src/subs_grid.cpp b/aegisub/src/subs_grid.cpp index 9feaa9ee2..2732a4293 100644 --- a/aegisub/src/subs_grid.cpp +++ b/aegisub/src/subs_grid.cpp @@ -1450,7 +1450,7 @@ bool SubtitlesGrid::SplitLineByKaraoke(int lineNumber) { if (syls.size() < 2) return false; // Insert a new line for each syllable - int start_ms = line->GetStartMS(); + int start_ms = line->Start.GetMS(); int nextpos = lineNumber; for (AssKaraokeVector::iterator syl = syls.begin(); syl != syls.end(); ++syl) { @@ -1458,9 +1458,9 @@ bool SubtitlesGrid::SplitLineByKaraoke(int lineNumber) { if (syl->unstripped_text.IsEmpty()) continue; AssDialogue *nl = new AssDialogue(line->GetEntryData()); - nl->SetStartMS(start_ms); + nl->Start.SetMS(start_ms); start_ms += syl->duration * 10; - nl->SetEndMS(start_ms); + nl->End.SetMS(start_ms); nl->Text = syl->unstripped_text; nl->UpdateData(); InsertLine(nl, nextpos++, true, false); diff --git a/aegisub/src/subs_preview.cpp b/aegisub/src/subs_preview.cpp index 320825802..58a589090 100644 --- a/aegisub/src/subs_preview.cpp +++ b/aegisub/src/subs_preview.cpp @@ -181,7 +181,7 @@ void SubtitlesPreview::UpdateBitmap(int w,int h) { subs->InsertStyle((AssStyle *)style->Clone()); subs->SetScriptInfo(_T("PlayResX"),wxString::Format(_T("%i"),w)); subs->SetScriptInfo(_T("PlayResY"),wxString::Format(_T("%i"),h)); - subs->AddLine(_T("Dialogue: 0,0:00:00.00,0:00:05.00,Preview,,0000,0000,0000,,{\\q2}") + showText,_T("[Events]"),0,ver,&outGroup); + subs->AddLine(_T("Dialogue: 0,0:00:00.00,0:00:05.00,Preview,,0000,0000,0000,,{\\q2}") + showText,_T("[Events]"),ver,&outGroup); // Apply subtitles try { diff --git a/aegisub/src/subtitle_format.cpp b/aegisub/src/subtitle_format.cpp index c44bde706..2ae154fb9 100644 --- a/aegisub/src/subtitle_format.cpp +++ b/aegisub/src/subtitle_format.cpp @@ -137,13 +137,10 @@ void SubtitleFormat::LoadDefault(bool defline) { /// @brief Add line /// @param data /// @param group -/// @param lasttime /// @param version /// @param outgroup -/// @return -/// -int SubtitleFormat::AddLine(wxString data,wxString group,int lasttime,int &version,wxString *outgroup) { - return assFile->AddLine(data,group,lasttime,version,outgroup); +void SubtitleFormat::AddLine(wxString data,wxString group,int &version,wxString *outgroup) { + assFile->AddLine(data,group,version,outgroup); } @@ -411,7 +408,7 @@ SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) { /// @brief Sort lines /// void SubtitleFormat::SortLines() { - Line->sort(LessByPointedToValue()); + AssFile::Sort(*Line); } diff --git a/aegisub/src/subtitle_format.h b/aegisub/src/subtitle_format.h index ef0ae787e..8f7a84cdc 100644 --- a/aegisub/src/subtitle_format.h +++ b/aegisub/src/subtitle_format.h @@ -115,7 +115,7 @@ protected: /// @return /// AssFile *GetAssFile() { return assFile; } - int AddLine(wxString data,wxString group,int lasttime,int &version,wxString *outgroup=NULL); + void AddLine(wxString data,wxString group,int &version,wxString *outgroup=NULL); FPSRational AskForFPS(bool showSMPTE=false); virtual wxString GetName()=0; diff --git a/aegisub/src/subtitle_format_ass.cpp b/aegisub/src/subtitle_format_ass.cpp index 44b7b1cb4..9439b7376 100644 --- a/aegisub/src/subtitle_format_ass.cpp +++ b/aegisub/src/subtitle_format_ass.cpp @@ -102,7 +102,6 @@ void ASSSubtitleFormat::ReadFile(wxString filename,wxString encoding) { // Parse file wxString curgroup; - int lasttime = -1; wxString wxbuffer; while (file.HasMoreLines()) { // Reads line @@ -112,7 +111,7 @@ void ASSSubtitleFormat::ReadFile(wxString filename,wxString encoding) { // is really [Script Info] if (curgroup.IsEmpty() && !wxbuffer.IsEmpty() && wxbuffer[0] != _T(';') && wxbuffer[0] != _T('[')) { curgroup = _T("[Script Info]"); - lasttime = AddLine(curgroup,curgroup,lasttime,version,&curgroup); + AddLine(curgroup,curgroup,version,&curgroup); } // Convert v4 styles to v4+ styles @@ -145,7 +144,7 @@ void ASSSubtitleFormat::ReadFile(wxString filename,wxString encoding) { // Add line try { - lasttime = AddLine(wxbuffer,curgroup,lasttime,version,&curgroup); + AddLine(wxbuffer,curgroup,version,&curgroup); } catch (const wchar_t *err) { Clear(); @@ -158,7 +157,7 @@ void ASSSubtitleFormat::ReadFile(wxString filename,wxString encoding) { } // Add one last empty line in case it didn't end with one - if (!wxbuffer.IsEmpty()) AddLine(_T(""),curgroup,lasttime,version); + if (!wxbuffer.IsEmpty()) AddLine(_T(""),curgroup,version); } diff --git a/aegisub/src/subtitle_format_microdvd.cpp b/aegisub/src/subtitle_format_microdvd.cpp index 1f2c42c2e..1432ee79c 100644 --- a/aegisub/src/subtitle_format_microdvd.cpp +++ b/aegisub/src/subtitle_format_microdvd.cpp @@ -176,8 +176,8 @@ void MicroDVDSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) AssDialogue *line = new AssDialogue(); line->group = _T("[Events]"); line->Style = _T("Default"); - line->SetStartMS(start); - line->SetEndMS(end); + line->Start.SetMS(start); + line->End.SetMS(end); line->Text = text; Line->push_back(line); } diff --git a/aegisub/src/subtitle_format_srt.cpp b/aegisub/src/subtitle_format_srt.cpp index 2a5fbd318..9c26f77bf 100644 --- a/aegisub/src/subtitle_format_srt.cpp +++ b/aegisub/src/subtitle_format_srt.cpp @@ -170,7 +170,6 @@ void SRTSubtitleFormat::ReadFile(wxString filename,wxString encoding) { line->Comment = false; line->UpdateData(); line->ParseSRTTags(); - line->FixStartMS(); Line->push_back(line); lines++; } @@ -182,8 +181,8 @@ void SRTSubtitleFormat::ReadFile(wxString filename,wxString encoding) { AssDialogue *line = new AssDialogue(); line->group = _T("[Events]"); line->Style = _T("Default"); - line->SetStartMS(0); - line->SetEndMS(5000); + line->Start.SetMS(0); + line->End.SetMS(5000); Line->push_back(line); } } diff --git a/aegisub/src/subtitle_format_ttxt.cpp b/aegisub/src/subtitle_format_ttxt.cpp index bdf98595b..22bcf9e09 100644 --- a/aegisub/src/subtitle_format_ttxt.cpp +++ b/aegisub/src/subtitle_format_ttxt.cpp @@ -142,8 +142,8 @@ void TTXTSubtitleFormat::ReadFile(wxString filename,wxString forceEncoding) { AssDialogue *line = new AssDialogue(); line->group = _T("[Events]"); line->Style = _T("Default"); - line->SetStartMS(0); - line->SetEndMS(5000); + line->Start.SetMS(0); + line->End.SetMS(5000); Line->push_back(line); } } @@ -173,8 +173,8 @@ bool TTXTSubtitleFormat::ProcessLine(wxXmlNode *node) { if (!text.IsEmpty()) { // Create dialogue diag = new AssDialogue(); - diag->SetStartMS(time.GetMS()); - diag->SetEndMS(36000000-10); + diag->Start.SetMS(time.GetMS()); + diag->End.SetMS(36000000-10); diag->group = _T("[Events]"); diag->Style = _T("Default"); diag->Comment = false; @@ -368,8 +368,8 @@ void TTXTSubtitleFormat::ConvertToTTXT () { // Insert blank line at the end AssDialogue *diag = new AssDialogue(); - diag->SetStartMS(lastTime.GetMS()); - diag->SetEndMS(lastTime.GetMS()+Options.AsInt(_T("Timing Default Duration"))); + diag->Start.SetMS(lastTime.GetMS()); + diag->End.SetMS(lastTime.GetMS()+Options.AsInt(_T("Timing Default Duration"))); diag->group = _T("[Events]"); diag->Style = _T("Default"); diag->Comment = false; diff --git a/aegisub/src/subtitle_format_txt.cpp b/aegisub/src/subtitle_format_txt.cpp index 21b728df9..2cb198cb7 100644 --- a/aegisub/src/subtitle_format_txt.cpp +++ b/aegisub/src/subtitle_format_txt.cpp @@ -168,8 +168,8 @@ void TXTSubtitleFormat::ReadFile(wxString filename,wxString encoding) { using na } line->Comment = isComment; line->Text = value; - line->SetStartMS(0); - line->SetEndMS(0); + line->Start.SetMS(0); + line->End.SetMS(0); line->UpdateData(); //line->ParseASSTags(); @@ -183,8 +183,8 @@ void TXTSubtitleFormat::ReadFile(wxString filename,wxString encoding) { using na AssDialogue *line = new AssDialogue(); line->group = _T("[Events]"); line->Style = _T("Default"); - line->SetStartMS(0); - line->SetEndMS(Options.AsInt(_T("Timing Default Duration"))); + line->Start.SetMS(0); + line->End.SetMS(Options.AsInt(_T("Timing Default Duration"))); Line->push_back(line); } }