2015-02-12 23:16:25 +08:00
|
|
|
// Aseprite
|
2016-04-23 00:19:06 +08:00
|
|
|
// Copyright (C) 2001-2016 David Capello
|
2015-02-12 23:16:25 +08:00
|
|
|
//
|
2016-08-27 04:02:58 +08:00
|
|
|
// This program is distributed under the terms of
|
|
|
|
// the End-User License Agreement for Aseprite.
|
2012-01-06 06:45:03 +08:00
|
|
|
|
2013-08-06 08:20:19 +08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2012-01-06 06:45:03 +08:00
|
|
|
#include "config.h"
|
2013-08-06 08:20:19 +08:00
|
|
|
#endif
|
|
|
|
|
2016-11-15 06:44:29 +08:00
|
|
|
#include "app/commands/cmd_open_file.h"
|
|
|
|
|
2013-08-06 08:20:19 +08:00
|
|
|
#include "app/app.h"
|
|
|
|
#include "app/commands/command.h"
|
|
|
|
#include "app/commands/params.h"
|
|
|
|
#include "app/console.h"
|
|
|
|
#include "app/document.h"
|
|
|
|
#include "app/file/file.h"
|
2012-06-16 10:37:59 +08:00
|
|
|
#include "app/file_selector.h"
|
2013-08-06 08:20:19 +08:00
|
|
|
#include "app/job.h"
|
|
|
|
#include "app/modules/editors.h"
|
|
|
|
#include "app/modules/gui.h"
|
|
|
|
#include "app/recent_files.h"
|
|
|
|
#include "app/ui/status_bar.h"
|
|
|
|
#include "app/ui_context.h"
|
2012-07-06 12:06:00 +08:00
|
|
|
#include "base/bind.h"
|
2016-11-02 06:14:05 +08:00
|
|
|
#include "base/fs.h"
|
2012-01-06 06:45:03 +08:00
|
|
|
#include "base/thread.h"
|
2012-07-06 12:06:00 +08:00
|
|
|
#include "base/unique_ptr.h"
|
2014-10-21 09:21:31 +08:00
|
|
|
#include "doc/sprite.h"
|
2013-08-06 08:20:19 +08:00
|
|
|
#include "ui/ui.h"
|
2012-01-06 06:45:03 +08:00
|
|
|
|
2013-10-15 06:58:11 +08:00
|
|
|
#include <cstdio>
|
2012-07-06 12:06:00 +08:00
|
|
|
|
2013-08-06 08:20:19 +08:00
|
|
|
namespace app {
|
2012-01-06 06:45:03 +08:00
|
|
|
|
2016-11-16 05:11:47 +08:00
|
|
|
class OpenFileJob : public Job, public IFileOpProgress {
|
2012-07-06 12:06:00 +08:00
|
|
|
public:
|
2013-10-15 06:58:11 +08:00
|
|
|
OpenFileJob(FileOp* fop)
|
2012-07-06 12:06:00 +08:00
|
|
|
: Job("Loading file")
|
|
|
|
, m_fop(fop)
|
|
|
|
{
|
2012-01-06 06:45:03 +08:00
|
|
|
}
|
|
|
|
|
2012-07-06 12:06:00 +08:00
|
|
|
void showProgressWindow() {
|
|
|
|
startJob();
|
2014-05-03 04:04:55 +08:00
|
|
|
|
|
|
|
if (isCanceled())
|
2015-09-29 22:27:00 +08:00
|
|
|
m_fop->stop();
|
2014-05-03 04:04:55 +08:00
|
|
|
|
|
|
|
waitJob();
|
2012-01-06 06:45:03 +08:00
|
|
|
}
|
|
|
|
|
2012-07-06 12:06:00 +08:00
|
|
|
private:
|
|
|
|
// Thread to do the hard work: load the file from the disk.
|
2014-08-15 10:07:47 +08:00
|
|
|
virtual void onJob() override {
|
2012-07-06 12:06:00 +08:00
|
|
|
try {
|
2015-09-29 22:27:00 +08:00
|
|
|
m_fop->operate(this);
|
2012-07-06 12:06:00 +08:00
|
|
|
}
|
|
|
|
catch (const std::exception& e) {
|
2015-09-29 22:27:00 +08:00
|
|
|
m_fop->setError("Error loading file:\n%s", e.what());
|
2012-07-06 12:06:00 +08:00
|
|
|
}
|
2012-01-06 06:45:03 +08:00
|
|
|
|
2015-09-29 22:27:00 +08:00
|
|
|
if (m_fop->isStop() && m_fop->document())
|
|
|
|
delete m_fop->releaseDocument();
|
2012-01-06 06:45:03 +08:00
|
|
|
|
2015-09-29 22:27:00 +08:00
|
|
|
m_fop->done();
|
2012-07-06 12:06:00 +08:00
|
|
|
}
|
2012-01-06 06:45:03 +08:00
|
|
|
|
2014-08-15 10:07:47 +08:00
|
|
|
virtual void ackFileOpProgress(double progress) override {
|
2012-07-06 12:06:00 +08:00
|
|
|
jobProgress(progress);
|
2012-01-06 06:45:03 +08:00
|
|
|
}
|
2012-07-06 12:06:00 +08:00
|
|
|
|
|
|
|
FileOp* m_fop;
|
|
|
|
};
|
2012-01-06 06:45:03 +08:00
|
|
|
|
|
|
|
OpenFileCommand::OpenFileCommand()
|
|
|
|
: Command("OpenFile",
|
|
|
|
"Open Sprite",
|
|
|
|
CmdRecordableFlag)
|
2016-11-16 05:11:47 +08:00
|
|
|
, m_repeatCheckbox(false)
|
2016-12-01 23:06:35 +08:00
|
|
|
, m_oneFrame(false)
|
2016-11-16 05:11:47 +08:00
|
|
|
, m_seqDecision(SequenceDecision::Ask)
|
2012-01-06 06:45:03 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-03-12 02:40:22 +08:00
|
|
|
void OpenFileCommand::onLoadParams(const Params& params)
|
2012-01-06 06:45:03 +08:00
|
|
|
{
|
2015-03-12 02:40:22 +08:00
|
|
|
m_filename = params.get("filename");
|
|
|
|
m_folder = params.get("folder"); // Initial folder
|
2016-11-16 05:11:47 +08:00
|
|
|
m_repeatCheckbox = (params.get("repeat_checkbox") == "true");
|
2016-12-01 23:06:35 +08:00
|
|
|
m_oneFrame = (params.get("oneframe") == "true");
|
2016-12-01 22:37:45 +08:00
|
|
|
|
|
|
|
std::string sequence = params.get("sequence");
|
2016-12-01 23:06:35 +08:00
|
|
|
if (m_oneFrame || sequence == "skip")
|
2016-12-01 22:37:45 +08:00
|
|
|
m_seqDecision = SequenceDecision::Skip;
|
2016-12-01 23:06:35 +08:00
|
|
|
else if (sequence == "agree")
|
|
|
|
m_seqDecision = SequenceDecision::Agree;
|
2016-12-01 22:37:45 +08:00
|
|
|
else
|
|
|
|
m_seqDecision = SequenceDecision::Ask;
|
2012-01-06 06:45:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenFileCommand::onExecute(Context* context)
|
|
|
|
{
|
|
|
|
Console console;
|
|
|
|
|
2016-11-15 06:44:29 +08:00
|
|
|
m_usedFiles.clear();
|
|
|
|
|
2012-01-06 06:45:03 +08:00
|
|
|
// interactive
|
2015-05-19 04:04:31 +08:00
|
|
|
if (context->isUIAvailable() && m_filename.empty()) {
|
2015-03-18 04:17:01 +08:00
|
|
|
std::string exts = get_readable_extensions();
|
2015-03-02 22:18:33 +08:00
|
|
|
|
|
|
|
// Add backslash as show_file_selector() expected a filename as
|
|
|
|
// initial path (and the file part is removed from the path).
|
|
|
|
if (!m_folder.empty() && !base::is_path_separator(m_folder[m_folder.size()-1]))
|
|
|
|
m_folder.push_back(base::path_separator);
|
|
|
|
|
2015-03-05 09:41:34 +08:00
|
|
|
m_filename = app::show_file_selector("Open", m_folder, exts,
|
2016-12-01 23:06:35 +08:00
|
|
|
FileSelectorType::Open);
|
2012-01-06 06:45:03 +08:00
|
|
|
}
|
|
|
|
|
2016-12-01 23:06:35 +08:00
|
|
|
// The user cancelled the operation through UI or isn't a filename
|
|
|
|
// specified in params.
|
|
|
|
if (m_filename.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
int flags = (m_repeatCheckbox ? FILE_LOAD_SEQUENCE_ASK_CHECKBOX: 0);
|
|
|
|
|
|
|
|
switch (m_seqDecision) {
|
|
|
|
case SequenceDecision::Ask:
|
|
|
|
flags |= FILE_LOAD_SEQUENCE_ASK;
|
|
|
|
break;
|
|
|
|
case SequenceDecision::Agree:
|
|
|
|
flags |= FILE_LOAD_SEQUENCE_YES;
|
|
|
|
break;
|
|
|
|
case SequenceDecision::Skip:
|
|
|
|
flags |= FILE_LOAD_SEQUENCE_NONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_oneFrame)
|
|
|
|
flags |= FILE_LOAD_ONE_FRAME;
|
2016-11-16 05:11:47 +08:00
|
|
|
|
2016-12-01 23:06:35 +08:00
|
|
|
base::UniquePtr<FileOp> fop(
|
|
|
|
FileOp::createLoadDocumentOperation(
|
|
|
|
context, m_filename.c_str(), flags));
|
|
|
|
bool unrecent = false;
|
2012-01-06 06:45:03 +08:00
|
|
|
|
2016-12-01 23:06:35 +08:00
|
|
|
// Do nothing (the user cancelled or something like that)
|
|
|
|
if (!fop)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (fop->hasError()) {
|
|
|
|
console.printf(fop->error().c_str());
|
|
|
|
unrecent = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (fop->isSequence()) {
|
|
|
|
|
|
|
|
if (fop->sequenceFlags() & FILE_LOAD_SEQUENCE_YES) {
|
|
|
|
m_seqDecision = SequenceDecision::Agree;
|
2012-01-06 06:45:03 +08:00
|
|
|
}
|
2016-12-01 23:06:35 +08:00
|
|
|
else if (fop->sequenceFlags() & FILE_LOAD_SEQUENCE_NONE) {
|
|
|
|
m_seqDecision = SequenceDecision::Skip;
|
2012-01-06 06:45:03 +08:00
|
|
|
}
|
|
|
|
|
2016-12-01 23:06:35 +08:00
|
|
|
m_usedFiles = fop->filenames();
|
2012-01-06 06:45:03 +08:00
|
|
|
}
|
|
|
|
else {
|
2016-12-01 23:06:35 +08:00
|
|
|
m_usedFiles.push_back(fop->filename());
|
2012-01-06 06:45:03 +08:00
|
|
|
}
|
2016-12-01 23:06:35 +08:00
|
|
|
|
|
|
|
OpenFileJob task(fop);
|
|
|
|
task.showProgressWindow();
|
|
|
|
|
|
|
|
// Post-load processing, it is called from the GUI because may require user intervention.
|
|
|
|
fop->postLoad();
|
|
|
|
|
|
|
|
// Show any error
|
|
|
|
if (fop->hasError() && !fop->isStop())
|
|
|
|
console.printf(fop->error().c_str());
|
|
|
|
|
|
|
|
Document* document = fop->document();
|
|
|
|
if (document) {
|
|
|
|
if (context->isUIAvailable())
|
|
|
|
App::instance()->recentFiles()->addRecentFile(fop->filename().c_str());
|
|
|
|
|
|
|
|
document->setContext(context);
|
|
|
|
}
|
|
|
|
else if (!fop->isStop())
|
|
|
|
unrecent = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The file was not found or was loaded loaded with errors,
|
|
|
|
// so we can remove it from the recent-file list
|
|
|
|
if (unrecent) {
|
|
|
|
if (context->isUIAvailable())
|
|
|
|
App::instance()->recentFiles()->removeRecentFile(m_filename.c_str());
|
2012-01-06 06:45:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Command* CommandFactory::createOpenFileCommand()
|
|
|
|
{
|
|
|
|
return new OpenFileCommand;
|
|
|
|
}
|
2013-08-06 08:20:19 +08:00
|
|
|
|
|
|
|
} // namespace app
|