mirror of https://github.com/odrling/Aegisub
Pull even more of the subs load logic into Project
The relative order of the on-file-load logic matters, so signals don't work very well for it. Doing it all explicitly in Project fixes a bunch of inconsistent issues related to restoring saved state. Closes #1759.
This commit is contained in:
parent
3bd6c302c3
commit
e061ac8755
|
@ -120,7 +120,6 @@ BaseGrid::BaseGrid(wxWindow* parent, agi::Context *context)
|
||||||
|
|
||||||
connections = agi::signal::make_vector({
|
connections = agi::signal::make_vector({
|
||||||
context->ass->AddCommitListener(&BaseGrid::OnSubtitlesCommit, this),
|
context->ass->AddCommitListener(&BaseGrid::OnSubtitlesCommit, this),
|
||||||
context->subsController->AddFileOpenListener(&BaseGrid::OnSubtitlesOpen, this),
|
|
||||||
|
|
||||||
context->selectionController->AddActiveLineListener(&BaseGrid::OnActiveLineChanged, this),
|
context->selectionController->AddActiveLineListener(&BaseGrid::OnActiveLineChanged, this),
|
||||||
context->selectionController->AddSelectionListener([&]{ Refresh(false); }),
|
context->selectionController->AddSelectionListener([&]{ Refresh(false); }),
|
||||||
|
@ -176,10 +175,6 @@ void BaseGrid::OnSubtitlesCommit(int type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseGrid::OnSubtitlesOpen() {
|
|
||||||
ScrollTo(context->ass->Properties.scroll_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseGrid::OnShowColMenu(wxCommandEvent &event) {
|
void BaseGrid::OnShowColMenu(wxCommandEvent &event) {
|
||||||
int item = event.GetId() - MENU_SHOW_COL;
|
int item = event.GetId() - MENU_SHOW_COL;
|
||||||
bool new_value = !columns_visible[item];
|
bool new_value = !columns_visible[item];
|
||||||
|
|
|
@ -92,11 +92,8 @@ class BaseGrid final : public wxWindow {
|
||||||
void OnShowColMenu(wxCommandEvent &event);
|
void OnShowColMenu(wxCommandEvent &event);
|
||||||
void OnSize(wxSizeEvent &event);
|
void OnSize(wxSizeEvent &event);
|
||||||
void OnSubtitlesCommit(int type);
|
void OnSubtitlesCommit(int type);
|
||||||
void OnSubtitlesOpen();
|
|
||||||
void OnActiveLineChanged(AssDialogue *);
|
void OnActiveLineChanged(AssDialogue *);
|
||||||
|
|
||||||
void ScrollTo(int y);
|
|
||||||
|
|
||||||
void AdjustScrollbar();
|
void AdjustScrollbar();
|
||||||
void SetColumnWidths();
|
void SetColumnWidths();
|
||||||
|
|
||||||
|
@ -120,6 +117,7 @@ public:
|
||||||
~BaseGrid();
|
~BaseGrid();
|
||||||
|
|
||||||
void SetByFrame(bool state);
|
void SetByFrame(bool state);
|
||||||
|
void ScrollTo(int y);
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
|
@ -149,7 +149,7 @@ FrameMain::FrameMain()
|
||||||
SetDropTarget(new AegisubFileDropTarget(context.get()));
|
SetDropTarget(new AegisubFileDropTarget(context.get()));
|
||||||
|
|
||||||
StartupLog("Load default file");
|
StartupLog("Load default file");
|
||||||
context->subsController->Close();
|
context->project->CloseSubtitles();
|
||||||
|
|
||||||
StartupLog("Display main window");
|
StartupLog("Display main window");
|
||||||
AddFullScreenButton(this);
|
AddFullScreenButton(this);
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
|
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
|
|
||||||
|
#include "ass_dialogue.h"
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "async_video_provider.h"
|
#include "async_video_provider.h"
|
||||||
#include "audio_controller.h"
|
#include "audio_controller.h"
|
||||||
|
#include "base_grid.h"
|
||||||
#include "charset_detect.h"
|
#include "charset_detect.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "dialog_progress.h"
|
#include "dialog_progress.h"
|
||||||
|
@ -29,7 +31,9 @@
|
||||||
#include "include/aegisub/video_provider.h"
|
#include "include/aegisub/video_provider.h"
|
||||||
#include "mkv_wrap.h"
|
#include "mkv_wrap.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "selection_controller.h"
|
||||||
#include "subs_controller.h"
|
#include "subs_controller.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "video_controller.h"
|
#include "video_controller.h"
|
||||||
#include "video_display.h"
|
#include "video_display.h"
|
||||||
|
|
||||||
|
@ -95,17 +99,18 @@ void Project::SetPath(agi::fs::path& var, const char *token, const char *mru, ag
|
||||||
UpdateRelativePaths();
|
UpdateRelativePaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::DoLoadSubtitles(agi::fs::path const& path, std::string encoding) {
|
bool Project::DoLoadSubtitles(agi::fs::path const& path, std::string encoding, ProjectProperties &properties) {
|
||||||
try {
|
try {
|
||||||
if (encoding.empty())
|
if (encoding.empty())
|
||||||
encoding = CharSetDetect::GetEncoding(path);
|
encoding = CharSetDetect::GetEncoding(path);
|
||||||
}
|
}
|
||||||
catch (agi::UserCancelException const&) {
|
catch (agi::UserCancelException const&) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileNotFound const&) {
|
catch (agi::fs::FileNotFound const&) {
|
||||||
config::mru->Remove("Subtitle", path);
|
config::mru->Remove("Subtitle", path);
|
||||||
return ShowError(path.string() + " not found.");
|
ShowError(path.string() + " not found.");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encoding != "binary") {
|
if (encoding != "binary") {
|
||||||
|
@ -113,48 +118,67 @@ void Project::DoLoadSubtitles(agi::fs::path const& path, std::string encoding) {
|
||||||
// distinguish them based on filename alone, and just ignore failures
|
// distinguish them based on filename alone, and just ignore failures
|
||||||
// rather than trying to differentiate between malformed timecodes
|
// rather than trying to differentiate between malformed timecodes
|
||||||
// files and things that aren't timecodes files at all
|
// files and things that aren't timecodes files at all
|
||||||
try { return DoLoadTimecodes(path); } catch (...) { }
|
try { DoLoadTimecodes(path); return false; } catch (...) { }
|
||||||
try { return DoLoadKeyframes(path); } catch (...) { }
|
try { DoLoadKeyframes(path); return false; } catch (...) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
context->subsController->Load(path, encoding);
|
properties = context->subsController->Load(path, encoding);
|
||||||
}
|
}
|
||||||
catch (agi::UserCancelException const&) { return; }
|
catch (agi::UserCancelException const&) { return false; }
|
||||||
catch (agi::fs::FileNotFound const&) {
|
catch (agi::fs::FileNotFound const&) {
|
||||||
config::mru->Remove("Subtitle", path);
|
config::mru->Remove("Subtitle", path);
|
||||||
return ShowError(path.string() + " not found.");
|
ShowError(path.string() + " not found.");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
return ShowError(e.GetMessage());
|
ShowError(e.GetMessage());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
catch (std::exception const& e) {
|
catch (std::exception const& e) {
|
||||||
return ShowError(std::string(e.what()));
|
ShowError(std::string(e.what()));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
return ShowError(wxString("Unknown error"));
|
ShowError(wxString("Unknown error"));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Selection sel;
|
||||||
|
AssDialogue *active_line = nullptr;
|
||||||
|
if (!context->ass->Events.empty()) {
|
||||||
|
int row = mid<int>(0, properties.active_row, context->ass->Events.size() - 1);
|
||||||
|
active_line = &*std::next(context->ass->Events.begin(), row);
|
||||||
|
sel.insert(active_line);
|
||||||
|
}
|
||||||
|
context->selectionController->SetSelectionAndActive(std::move(sel), active_line);
|
||||||
|
context->subsGrid->ScrollTo(properties.scroll_position);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::LoadSubtitles(agi::fs::path const& path, std::string encoding) {
|
void Project::LoadSubtitles(agi::fs::path const& path, std::string encoding) {
|
||||||
DoLoadSubtitles(path, encoding);
|
ProjectProperties properties;
|
||||||
LoadUnloadFiles();
|
if (DoLoadSubtitles(path, encoding, properties))
|
||||||
|
LoadUnloadFiles(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::CloseSubtitles() {
|
void Project::CloseSubtitles() {
|
||||||
context->subsController->Close();
|
context->subsController->Close();
|
||||||
config::path->SetToken("?script", "");
|
config::path->SetToken("?script", "");
|
||||||
LoadUnloadFiles();
|
LoadUnloadFiles(context->ass->Properties);
|
||||||
|
auto line = &*context->ass->Events.begin();
|
||||||
|
context->selectionController->SetSelectionAndActive({line}, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::LoadUnloadFiles() {
|
void Project::LoadUnloadFiles(ProjectProperties properties) {
|
||||||
auto load_linked = OPT_GET("App/Auto/Load Linked Files")->GetInt();
|
auto load_linked = OPT_GET("App/Auto/Load Linked Files")->GetInt();
|
||||||
if (!load_linked) return;
|
if (!load_linked) return;
|
||||||
|
|
||||||
auto audio = config::path->MakeAbsolute(context->ass->Properties.audio_file, "?script");
|
auto audio = config::path->MakeAbsolute(properties.audio_file, "?script");
|
||||||
auto video = config::path->MakeAbsolute(context->ass->Properties.video_file, "?script");
|
auto video = config::path->MakeAbsolute(properties.video_file, "?script");
|
||||||
auto timecodes = config::path->MakeAbsolute(context->ass->Properties.timecodes_file, "?script");
|
auto timecodes = config::path->MakeAbsolute(properties.timecodes_file, "?script");
|
||||||
auto keyframes = config::path->MakeAbsolute(context->ass->Properties.keyframes_file, "?script");
|
auto keyframes = config::path->MakeAbsolute(properties.keyframes_file, "?script");
|
||||||
|
|
||||||
if (video == video_file && audio == audio_file && keyframes == keyframes_file && timecodes == timecodes_file)
|
if (video == video_file && audio == audio_file && keyframes == keyframes_file && timecodes == timecodes_file)
|
||||||
return;
|
return;
|
||||||
|
@ -189,14 +213,14 @@ void Project::LoadUnloadFiles() {
|
||||||
CloseVideo();
|
CloseVideo();
|
||||||
else if ((loaded_video = DoLoadVideo(video))) {
|
else if ((loaded_video = DoLoadVideo(video))) {
|
||||||
auto vc = context->videoController.get();
|
auto vc = context->videoController.get();
|
||||||
vc->JumpToFrame(context->ass->Properties.video_position);
|
vc->JumpToFrame(properties.video_position);
|
||||||
|
|
||||||
auto ar_mode = static_cast<AspectRatio>(context->ass->Properties.ar_mode);
|
auto ar_mode = static_cast<AspectRatio>(properties.ar_mode);
|
||||||
if (ar_mode == AspectRatio::Custom)
|
if (ar_mode == AspectRatio::Custom)
|
||||||
vc->SetAspectRatio(context->ass->Properties.ar_value);
|
vc->SetAspectRatio(properties.ar_value);
|
||||||
else
|
else
|
||||||
vc->SetAspectRatio(ar_mode);
|
vc->SetAspectRatio(ar_mode);
|
||||||
context->videoDisplay->SetZoom(context->ass->Properties.video_zoom);
|
context->videoDisplay->SetZoom(properties.video_zoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,13 +499,11 @@ void Project::LoadList(std::vector<agi::fs::path> const& files) {
|
||||||
audio = file;
|
audio = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subs.empty())
|
ProjectProperties properties;
|
||||||
DoLoadSubtitles(subs);
|
if (!subs.empty()) {
|
||||||
|
if (!DoLoadSubtitles(subs, "", properties))
|
||||||
// Loading video will clear the audio file script header, so make sure we
|
subs.clear();
|
||||||
// end up loading the audio if the newly loaded subs has some
|
}
|
||||||
if (!video.empty() && audio.empty() && !context->ass->Properties.audio_file.empty())
|
|
||||||
audio = config::path->MakeAbsolute(context->ass->Properties.audio_file, "?script");
|
|
||||||
|
|
||||||
if (!video.empty()) {
|
if (!video.empty()) {
|
||||||
DoLoadVideo(video);
|
DoLoadVideo(video);
|
||||||
|
@ -508,5 +530,5 @@ void Project::LoadList(std::vector<agi::fs::path> const& files) {
|
||||||
DoLoadAudio(video_file, true);
|
DoLoadAudio(video_file, true);
|
||||||
|
|
||||||
if (!subs.empty())
|
if (!subs.empty())
|
||||||
LoadUnloadFiles();
|
LoadUnloadFiles(properties);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ class AudioProvider;
|
||||||
class DialogProgress;
|
class DialogProgress;
|
||||||
class wxString;
|
class wxString;
|
||||||
namespace agi { struct Context; }
|
namespace agi { struct Context; }
|
||||||
|
struct ProjectProperties;
|
||||||
|
|
||||||
class Project {
|
class Project {
|
||||||
std::unique_ptr<::AudioProvider> audio_provider;
|
std::unique_ptr<::AudioProvider> audio_provider;
|
||||||
|
@ -51,13 +52,13 @@ class Project {
|
||||||
void ShowError(wxString const& message);
|
void ShowError(wxString const& message);
|
||||||
void ShowError(std::string const& message);
|
void ShowError(std::string const& message);
|
||||||
|
|
||||||
void DoLoadSubtitles(agi::fs::path const& path, std::string encoding="");
|
bool DoLoadSubtitles(agi::fs::path const& path, std::string encoding, ProjectProperties &properties);
|
||||||
void DoLoadAudio(agi::fs::path const& path, bool quiet);
|
void DoLoadAudio(agi::fs::path const& path, bool quiet);
|
||||||
bool DoLoadVideo(agi::fs::path const& path);
|
bool DoLoadVideo(agi::fs::path const& path);
|
||||||
void DoLoadTimecodes(agi::fs::path const& path);
|
void DoLoadTimecodes(agi::fs::path const& path);
|
||||||
void DoLoadKeyframes(agi::fs::path const& path);
|
void DoLoadKeyframes(agi::fs::path const& path);
|
||||||
|
|
||||||
void LoadUnloadFiles();
|
void LoadUnloadFiles(ProjectProperties properties);
|
||||||
void UpdateRelativePaths();
|
void UpdateRelativePaths();
|
||||||
void ReloadAudio();
|
void ReloadAudio();
|
||||||
void ReloadVideo();
|
void ReloadVideo();
|
||||||
|
|
|
@ -20,27 +20,10 @@
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "include/aegisub/context.h"
|
#include "include/aegisub/context.h"
|
||||||
#include "subs_controller.h"
|
#include "subs_controller.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
SelectionController::SelectionController(agi::Context *c)
|
SelectionController::SelectionController(agi::Context *c) : context(c) { }
|
||||||
: context(c)
|
|
||||||
, open_connection(c->subsController->AddFileOpenListener(&SelectionController::OnSubtitlesOpen, this))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SelectionController::OnSubtitlesOpen() {
|
|
||||||
selection.clear();
|
|
||||||
active_line = nullptr;
|
|
||||||
if (!context->ass->Events.empty()) {
|
|
||||||
int row = mid<int>(0, context->ass->Properties.active_row, context->ass->Events.size() - 1);
|
|
||||||
active_line = &*std::next(context->ass->Events.begin(), row);
|
|
||||||
selection.insert(active_line);
|
|
||||||
}
|
|
||||||
AnnounceSelectedSetChanged();
|
|
||||||
AnnounceActiveLineChanged(active_line);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SelectionController::SetSelectedSet(Selection new_selection) {
|
void SelectionController::SetSelectedSet(Selection new_selection) {
|
||||||
selection = std::move(new_selection);
|
selection = std::move(new_selection);
|
||||||
|
|
|
@ -46,11 +46,6 @@ class SelectionController {
|
||||||
Selection selection; ///< Currently selected lines
|
Selection selection; ///< Currently selected lines
|
||||||
AssDialogue *active_line = nullptr; ///< The currently active line or 0 if none
|
AssDialogue *active_line = nullptr; ///< The currently active line or 0 if none
|
||||||
|
|
||||||
agi::signal::Connection open_connection;
|
|
||||||
|
|
||||||
void OnSubtitlesOpen();
|
|
||||||
void OnSubtitlesSave();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SelectionController(agi::Context *context);
|
SelectionController(agi::Context *context);
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ void SubsController::SetSelectionController(SelectionController *selection_contr
|
||||||
selection_connection = context->selectionController->AddSelectionListener(&SubsController::OnSelectionChanged, this);
|
selection_connection = context->selectionController->AddSelectionListener(&SubsController::OnSelectionChanged, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsController::Load(agi::fs::path const& filename, std::string charset) {
|
ProjectProperties SubsController::Load(agi::fs::path const& filename, std::string charset) {
|
||||||
AssFile temp;
|
AssFile temp;
|
||||||
|
|
||||||
SubtitleFormat::GetReader(filename, charset)->ReadFile(&temp, filename, context->project->Timecodes(), charset);
|
SubtitleFormat::GetReader(filename, charset)->ReadFile(&temp, filename, context->project->Timecodes(), charset);
|
||||||
|
@ -185,6 +185,7 @@ void SubsController::Load(agi::fs::path const& filename, std::string charset) {
|
||||||
temp.Events.push_back(*new AssDialogue);
|
temp.Events.push_back(*new AssDialogue);
|
||||||
|
|
||||||
context->ass->swap(temp);
|
context->ass->swap(temp);
|
||||||
|
auto props = context->ass->Properties;
|
||||||
|
|
||||||
SetFileName(filename);
|
SetFileName(filename);
|
||||||
|
|
||||||
|
@ -207,6 +208,7 @@ void SubsController::Load(agi::fs::path const& filename, std::string charset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FileOpen(filename);
|
FileOpen(filename);
|
||||||
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsController::Save(agi::fs::path const& filename, std::string const& encoding) {
|
void SubsController::Save(agi::fs::path const& filename, std::string const& encoding) {
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
#include <wx/timer.h>
|
#include <wx/timer.h>
|
||||||
|
|
||||||
struct AssFileCommit;
|
|
||||||
class SelectionController;
|
class SelectionController;
|
||||||
|
|
||||||
namespace agi { struct Context; }
|
namespace agi { struct Context; }
|
||||||
|
struct AssFileCommit;
|
||||||
|
struct ProjectProperties;
|
||||||
|
|
||||||
class SubsController {
|
class SubsController {
|
||||||
agi::Context *context;
|
agi::Context *context;
|
||||||
|
@ -82,7 +82,7 @@ public:
|
||||||
/// @brief Load from a file
|
/// @brief Load from a file
|
||||||
/// @param file File name
|
/// @param file File name
|
||||||
/// @param charset Character set of file
|
/// @param charset Character set of file
|
||||||
void Load(agi::fs::path const& file, std::string charset);
|
ProjectProperties Load(agi::fs::path const& file, std::string charset);
|
||||||
|
|
||||||
/// @brief Save to a file
|
/// @brief Save to a file
|
||||||
/// @param file Path to save to
|
/// @param file Path to save to
|
||||||
|
|
Loading…
Reference in New Issue