diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp index a78e5d8d3..8d4944138 100644 --- a/aegisub/src/ass_file.cpp +++ b/aegisub/src/ass_file.cpp @@ -730,8 +730,8 @@ bool AssFile::CompEffect(const AssDialogue* lft, const AssDialogue* rgt) { return lft->Effect < rgt->Effect; } -void AssFile::Sort(CompFunc comp) { - Sort(Line, comp); +void AssFile::Sort(CompFunc comp, std::set const& limit) { + Sort(Line, comp, limit); } namespace { struct AssEntryComp : public std::binary_function { @@ -740,15 +740,20 @@ namespace { return comp(static_cast(a), static_cast(b)); } }; + + inline bool is_dialogue(AssEntry *e, std::set const& limit) { + AssDialogue *d = dynamic_cast(e); + return d && (limit.empty() || limit.count(d)); + } } -void AssFile::Sort(std::list &lst, CompFunc comp) { +void AssFile::Sort(std::list &lst, CompFunc comp, std::set const& limit) { AssEntryComp 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; + if (!is_dialogue(*begin, limit)) continue; entryIter end = begin; - while (end != lst.end() && dynamic_cast(*end)) ++end; + while (end != lst.end() && is_dialogue(*end, limit)) ++end; // used instead of std::list::sort for partial list sorting std::list tmp; diff --git a/aegisub/src/ass_file.h b/aegisub/src/ass_file.h index 53b179f6d..e39829fb4 100644 --- a/aegisub/src/ass_file.h +++ b/aegisub/src/ass_file.h @@ -40,6 +40,7 @@ #ifndef AGI_PRE #include #include +#include #include #include @@ -241,10 +242,12 @@ public: /// @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); + /// @param limit If non-empty, only lines in this set are sorted + void Sort(CompFunc comp = CompStart, std::set const& limit = std::set()); /// @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); + /// @param limit If non-empty, only lines in this set are sorted + static void Sort(std::list& lst, CompFunc comp = CompStart, std::set const& limit = std::set()); /// @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); diff --git a/aegisub/src/command/grid.cpp b/aegisub/src/command/grid.cpp index e555d5181..c35c4b097 100644 --- a/aegisub/src/command/grid.cpp +++ b/aegisub/src/command/grid.cpp @@ -114,6 +114,27 @@ struct grid_sort_actor : public Command { } }; +struct validate_sel_multiple : public Command { + CMD_TYPE(COMMAND_VALIDATE) + + bool Validate(const agi::Context *c) { + return c->selectionController->GetSelectedSet().size() > 1; + } +}; + +/// Sort all selected subtitles by their actor names +struct grid_sort_actor_selected : public validate_sel_multiple { + CMD_NAME("grid/sort/actor/selected") + STR_MENU("&Actor Name") + STR_DISP("Actor Name") + STR_HELP("Sort selected subtitles by their actor names") + + void operator()(agi::Context *c) { + c->ass->Sort(AssFile::CompActor, c->selectionController->GetSelectedSet()); + c->ass->Commit(_("sort"), AssFile::COMMIT_ORDER); + } +}; + /// Sort all subtitles by their effects struct grid_sort_effect : public Command { CMD_NAME("grid/sort/effect") @@ -127,6 +148,19 @@ struct grid_sort_effect : public Command { } }; +/// Sort all selected subtitles by their effects +struct grid_sort_effect_selected : public validate_sel_multiple { + CMD_NAME("grid/sort/effect/selected") + STR_MENU("&Effect") + STR_DISP("Effect") + STR_HELP("Sort selected subtitles by their effects") + + void operator()(agi::Context *c) { + c->ass->Sort(AssFile::CompEffect, c->selectionController->GetSelectedSet()); + c->ass->Commit(_("sort"), AssFile::COMMIT_ORDER); + } +}; + /// Sort all subtitles by their end times. struct grid_sort_end : public Command { CMD_NAME("grid/sort/end") @@ -140,6 +174,19 @@ struct grid_sort_end : public Command { } }; +/// Sort all selected subtitles by their end times. +struct grid_sort_end_selected : public validate_sel_multiple { + CMD_NAME("grid/sort/end/selected") + STR_MENU("&End Time") + STR_DISP("End Time") + STR_HELP("Sort selected subtitles by their end times") + + void operator()(agi::Context *c) { + c->ass->Sort(AssFile::CompEnd, c->selectionController->GetSelectedSet()); + c->ass->Commit(_("sort"), AssFile::COMMIT_ORDER); + } +}; + /// Sort all subtitles by their start times. struct grid_sort_start : public Command { CMD_NAME("grid/sort/start") @@ -153,6 +200,19 @@ struct grid_sort_start : public Command { } }; +/// Sort all selected subtitles by their start times. +struct grid_sort_start_selected : public validate_sel_multiple { + CMD_NAME("grid/sort/start/selected") + STR_MENU("&Start Time") + STR_DISP("Start Time") + STR_HELP("Sort selected subtitles by their start times") + + void operator()(agi::Context *c) { + c->ass->Sort(AssFile::CompStart, c->selectionController->GetSelectedSet()); + c->ass->Commit(_("sort"), AssFile::COMMIT_ORDER); + } +}; + /// Sort all subtitles by their style names struct grid_sort_style : public Command { CMD_NAME("grid/sort/style") @@ -166,6 +226,19 @@ struct grid_sort_style : public Command { } }; +/// Sort all selected subtitles by their style names +struct grid_sort_style_selected : public validate_sel_multiple { + CMD_NAME("grid/sort/style/selected") + STR_MENU("St&yle Name") + STR_DISP("Style Name") + STR_HELP("Sort selected subtitles by their style names") + + void operator()(agi::Context *c) { + c->ass->Sort(AssFile::CompStyle, c->selectionController->GetSelectedSet()); + c->ass->Commit(_("sort"), AssFile::COMMIT_ORDER); + } +}; + /// Cycle through tag hiding modes. struct grid_tag_cycle_hiding : public Command { CMD_NAME("grid/tag/cycle_hiding") @@ -340,6 +413,11 @@ namespace cmd { reg(new grid_sort_end); reg(new grid_sort_start); reg(new grid_sort_style); + reg(new grid_sort_actor_selected); + reg(new grid_sort_effect_selected); + reg(new grid_sort_end_selected); + reg(new grid_sort_start_selected); + reg(new grid_sort_style_selected); reg(new grid_move_down); reg(new grid_move_up); reg(new grid_swap); diff --git a/aegisub/src/libresrc/default_menu.json b/aegisub/src/libresrc/default_menu.json index 015ae646c..22f3976fa 100644 --- a/aegisub/src/libresrc/default_menu.json +++ b/aegisub/src/libresrc/default_menu.json @@ -83,7 +83,8 @@ { "command" : "edit/line/recombine" }, { "command" : "edit/line/split/by_karaoke" }, {}, - { "submenu" : "main/subtitle/sort lines", "text" : "Sort Lines" }, + { "submenu" : "main/subtitle/sort lines", "text" : "Sort All Lines" }, + { "submenu" : "main/subtitle/sort selected lines", "text" : "Sort Selected Lines" }, { "command" : "grid/swap" }, { "command" : "tool/line/select" }, { "command" : "subtitle/select/all" } @@ -106,6 +107,13 @@ { "command" : "grid/sort/actor" }, { "command" : "grid/sort/effect" } ], + "main/subtitle/sort selected lines" : [ + { "command" : "grid/sort/start/selected" }, + { "command" : "grid/sort/end/selected" }, + { "command" : "grid/sort/style/selected" }, + { "command" : "grid/sort/actor/selected" }, + { "command" : "grid/sort/effect/selected" } + ], "main/timing" : [ { "command" : "time/shift" }, { "command" : "tool/time/postprocess" },