2013-01-26 02:57:46 +01:00
|
|
|
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice appear in all copies.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
//
|
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
|
|
|
#include <libaegisub/fs_fwd.h>
|
|
|
|
#include <libaegisub/signal.h>
|
|
|
|
|
|
|
|
#include <boost/container/list.hpp>
|
|
|
|
#include <boost/filesystem/path.hpp>
|
2013-01-30 15:40:02 +01:00
|
|
|
#include <wx/timer.h>
|
2013-01-26 02:57:46 +01:00
|
|
|
|
2014-03-25 01:15:14 +01:00
|
|
|
class SelectionController;
|
2015-08-17 03:17:33 +02:00
|
|
|
namespace agi {
|
|
|
|
namespace dispatch {
|
|
|
|
class Queue;
|
|
|
|
}
|
|
|
|
struct Context;
|
|
|
|
}
|
2014-06-02 19:04:25 +02:00
|
|
|
struct AssFileCommit;
|
|
|
|
struct ProjectProperties;
|
2013-01-26 02:57:46 +01:00
|
|
|
|
|
|
|
class SubsController {
|
|
|
|
agi::Context *context;
|
|
|
|
agi::signal::Connection undo_connection;
|
2014-03-05 02:36:02 +01:00
|
|
|
agi::signal::Connection active_line_connection;
|
|
|
|
agi::signal::Connection selection_connection;
|
2014-04-17 03:27:54 +02:00
|
|
|
agi::signal::Connection text_selection_connection;
|
2013-01-26 02:57:46 +01:00
|
|
|
|
|
|
|
struct UndoInfo;
|
|
|
|
boost::container::list<UndoInfo> undo_stack;
|
|
|
|
boost::container::list<UndoInfo> redo_stack;
|
|
|
|
|
|
|
|
/// Revision counter for undo coalescing and modified state tracking
|
2013-12-12 01:29:48 +01:00
|
|
|
int commit_id = 0;
|
2013-01-26 02:57:46 +01:00
|
|
|
/// Last saved version of this file
|
2013-12-12 01:29:48 +01:00
|
|
|
int saved_commit_id = 0;
|
2013-01-26 02:57:46 +01:00
|
|
|
/// Last autosaved version of this file
|
2013-12-12 01:29:48 +01:00
|
|
|
int autosaved_commit_id = 0;
|
2015-09-28 03:18:43 +02:00
|
|
|
/// Version to use for the next commit
|
|
|
|
/// Needed to handle Save -> Undo -> Edit, which would result in the file
|
|
|
|
/// being marked unmodified if we reused commit IDs
|
|
|
|
int next_commit_id = 1;
|
2013-01-26 02:57:46 +01:00
|
|
|
|
2013-01-30 15:40:02 +01:00
|
|
|
/// Timer for triggering autosaves
|
|
|
|
wxTimer autosave_timer;
|
|
|
|
|
2015-08-17 03:17:33 +02:00
|
|
|
/// Queue which autosaves are performed on
|
|
|
|
std::unique_ptr<agi::dispatch::Queue> autosave_queue;
|
|
|
|
|
2013-01-26 02:57:46 +01:00
|
|
|
/// A new file has been opened (filename)
|
|
|
|
agi::signal::Signal<agi::fs::path> FileOpen;
|
2014-05-22 03:32:42 +02:00
|
|
|
/// The file has been saved
|
2013-01-26 02:57:46 +01:00
|
|
|
agi::signal::Signal<> FileSave;
|
|
|
|
|
|
|
|
/// The filename of the currently open file, if any
|
|
|
|
agi::fs::path filename;
|
|
|
|
|
|
|
|
/// Set the filename, updating things like the MRU and last used path
|
|
|
|
void SetFileName(agi::fs::path const& file);
|
|
|
|
|
2015-08-17 03:17:33 +02:00
|
|
|
/// Autosave the file if there have been any chances since the last autosave
|
|
|
|
void AutoSave();
|
|
|
|
|
2014-03-05 02:36:02 +01:00
|
|
|
void OnCommit(AssFileCommit c);
|
|
|
|
void OnActiveLineChanged();
|
|
|
|
void OnSelectionChanged();
|
2014-04-17 03:27:54 +02:00
|
|
|
void OnTextSelectionChanged();
|
2014-03-04 17:32:29 +01:00
|
|
|
|
2013-01-26 02:57:46 +01:00
|
|
|
public:
|
|
|
|
SubsController(agi::Context *context);
|
2014-03-25 22:49:26 +01:00
|
|
|
~SubsController();
|
2013-01-26 02:57:46 +01:00
|
|
|
|
2014-03-05 02:36:02 +01:00
|
|
|
/// Set the selection controller to use
|
|
|
|
///
|
|
|
|
/// Required due to that the selection controller is the subtitles grid, and
|
|
|
|
/// so is created long after the subtitles controller
|
2014-03-25 01:15:14 +01:00
|
|
|
void SetSelectionController(SelectionController *selection_controller);
|
2014-03-05 02:36:02 +01:00
|
|
|
|
2013-01-26 02:57:46 +01:00
|
|
|
/// The file's path and filename if any, or platform-appropriate "untitled"
|
|
|
|
agi::fs::path Filename() const;
|
|
|
|
|
|
|
|
/// Does the file have unsaved changes?
|
|
|
|
bool IsModified() const { return commit_id != saved_commit_id; };
|
|
|
|
|
|
|
|
/// @brief Load from a file
|
|
|
|
/// @param file File name
|
2014-05-22 01:23:28 +02:00
|
|
|
/// @param charset Character set of file
|
2014-06-02 19:04:25 +02:00
|
|
|
ProjectProperties Load(agi::fs::path const& file, std::string charset);
|
2013-01-26 02:57:46 +01:00
|
|
|
|
|
|
|
/// @brief Save to a file
|
|
|
|
/// @param file Path to save to
|
|
|
|
/// @param encoding Encoding to use, or empty to let the writer decide (which usually means "App/Save Charset")
|
|
|
|
void Save(agi::fs::path const& file, std::string const& encoding="");
|
|
|
|
|
|
|
|
/// Close the currently open file (i.e. open a new blank file)
|
|
|
|
void Close();
|
|
|
|
|
|
|
|
/// If there are unsaved changes, asl the user if they want to save them
|
|
|
|
/// @param allow_cancel Let the user cancel the closing
|
|
|
|
/// @return wxYES, wxNO or wxCANCEL (note: all three are true in a boolean context)
|
|
|
|
int TryToClose(bool allow_cancel = true) const;
|
|
|
|
|
|
|
|
/// Can the file be saved in its current format?
|
|
|
|
bool CanSave() const;
|
|
|
|
|
2014-05-22 16:08:22 +02:00
|
|
|
/// The file is about to be saved
|
|
|
|
/// This signal is intended for adding metadata which is awkward or
|
|
|
|
/// expensive to always keep up to date
|
|
|
|
agi::signal::Signal<> UpdateProperties;
|
|
|
|
|
2013-01-26 02:57:46 +01:00
|
|
|
DEFINE_SIGNAL_ADDERS(FileOpen, AddFileOpenListener)
|
|
|
|
DEFINE_SIGNAL_ADDERS(FileSave, AddFileSaveListener)
|
|
|
|
|
|
|
|
/// @brief Undo the last set of changes to the file
|
|
|
|
void Undo();
|
|
|
|
/// @brief Redo the last undone changes
|
|
|
|
void Redo();
|
|
|
|
/// Check if undo stack is empty
|
|
|
|
bool IsUndoStackEmpty() const { return undo_stack.size() <= 1; };
|
|
|
|
/// Check if redo stack is empty
|
|
|
|
bool IsRedoStackEmpty() const { return redo_stack.empty(); };
|
|
|
|
/// Get the description of the first undoable change
|
|
|
|
wxString GetUndoDescription() const;
|
|
|
|
/// Get the description of the first redoable change
|
|
|
|
wxString GetRedoDescription() const;
|
|
|
|
};
|