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:
Thomas Goyne 2014-06-02 10:04:25 -07:00
parent 3bd6c302c3
commit e061ac8755
9 changed files with 65 additions and 69 deletions

View File

@ -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];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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) {

View File

@ -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