mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-01 10:13:22 +00:00
Improve handling of image sequences when dropping files or opening multiple files
Now we can repeat the same action (Agree/Skip the all sequence of images) for all the dropped files/selected files in the "Open File" dialog (as in the CLI new behavior).
This commit is contained in:
parent
1255b17738
commit
8c0f81cbba
@ -617,40 +617,20 @@ bool CliProcessor::openFile(Context* ctx, CliOpenFile& cof)
|
||||
m_delegate->beforeOpenFile(cof);
|
||||
|
||||
Doc* oldDoc = ctx->activeDocument();
|
||||
auto openCommand = static_cast<OpenFileCommand*>(Commands::instance()->byId(CommandId::OpenFile()));
|
||||
Params params;
|
||||
params.set("filename", cof.filename.c_str());
|
||||
if (cof.oneFrame)
|
||||
params.set("oneframe", "true");
|
||||
else {
|
||||
switch (m_lastDecision) {
|
||||
case OpenFileCommand::SequenceDecision::Ask:
|
||||
params.set("sequence", "ask");
|
||||
params.set("repeat_checkbox", "true");
|
||||
break;
|
||||
case OpenFileCommand::SequenceDecision::Skip:
|
||||
params.set("sequence", "skip");
|
||||
break;
|
||||
case OpenFileCommand::SequenceDecision::Agree:
|
||||
params.set("sequence", "agree");
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx->executeCommand(openCommand, params);
|
||||
|
||||
m_batch.open(ctx,
|
||||
cof.filename,
|
||||
cof.oneFrame);
|
||||
|
||||
// Mark used file names as "already processed" so we don't try to
|
||||
// open then again
|
||||
for (const auto& usedFn : openCommand->usedFiles()) {
|
||||
for (const auto& usedFn : m_batch.usedFiles()) {
|
||||
auto fn = base::normalize_path(usedFn);
|
||||
m_usedFiles.insert(fn);
|
||||
|
||||
os::instance()->markCliFileAsProcessed(fn);
|
||||
}
|
||||
|
||||
// Future decision for other files in the CLI
|
||||
if (openCommand->seqDecision() != OpenFileCommand::SequenceDecision::Ask)
|
||||
m_lastDecision = openCommand->seqDecision();
|
||||
|
||||
Doc* doc = ctx->activeDocument();
|
||||
// If the active document is equal to the previous one, it
|
||||
// means that we couldn't open this specific document.
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
#include "app/cli/cli_delegate.h"
|
||||
#include "app/cli/cli_open_file.h"
|
||||
#include "app/commands/cmd_open_file.h"
|
||||
#include "app/doc_exporter.h"
|
||||
#include "app/util/open_batch.h"
|
||||
#include "doc/selected_layers.h"
|
||||
|
||||
#include <memory>
|
||||
@ -64,7 +64,7 @@ namespace app {
|
||||
// Files already used in the CLI processing (e.g. when used to
|
||||
// load a sequence of files) so we don't ask for them again.
|
||||
std::set<std::string> m_usedFiles;
|
||||
OpenFileCommand::SequenceDecision m_lastDecision = OpenFileCommand::SequenceDecision::Ask;
|
||||
OpenBatchOfFiles m_batch;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -123,6 +123,12 @@ void OpenFileCommand::onExecute(Context* context)
|
||||
// The user cancelled the operation through UI
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user selected several files, show the checkbox to repeat
|
||||
// the action for future filenames in the batch of selected files
|
||||
// to open.
|
||||
if (filenames.size() > 1)
|
||||
m_repeatCheckbox = true;
|
||||
}
|
||||
else
|
||||
#endif // ENABLE_UI
|
||||
@ -153,7 +159,11 @@ void OpenFileCommand::onExecute(Context* context)
|
||||
if (m_oneFrame)
|
||||
flags |= FILE_LOAD_ONE_FRAME;
|
||||
|
||||
for (const auto& filename : filenames) {
|
||||
std::string filename;
|
||||
while (!filenames.empty()) {
|
||||
filename = filenames[0];
|
||||
filenames.erase(filenames.begin());
|
||||
|
||||
std::unique_ptr<FileOp> fop(
|
||||
FileOp::createLoadDocumentOperation(
|
||||
context, filename, flags));
|
||||
@ -171,14 +181,27 @@ void OpenFileCommand::onExecute(Context* context)
|
||||
if (fop->isSequence()) {
|
||||
if (fop->sequenceFlags() & FILE_LOAD_SEQUENCE_YES) {
|
||||
m_seqDecision = SequenceDecision::Agree;
|
||||
flags &= ~FILE_LOAD_SEQUENCE_ASK;
|
||||
flags |= FILE_LOAD_SEQUENCE_YES;
|
||||
}
|
||||
else if (fop->sequenceFlags() & FILE_LOAD_SEQUENCE_NONE) {
|
||||
m_seqDecision = SequenceDecision::Skip;
|
||||
flags &= ~FILE_LOAD_SEQUENCE_ASK;
|
||||
flags |= FILE_LOAD_SEQUENCE_NONE;
|
||||
}
|
||||
|
||||
for (std::string fn : fop->filenames()) {
|
||||
fn = base::normalize_path(fn);
|
||||
m_usedFiles.push_back(fn);
|
||||
|
||||
auto it = std::find(filenames.begin(), filenames.end(), fn);
|
||||
if (it != filenames.end())
|
||||
filenames.erase(it);
|
||||
}
|
||||
m_usedFiles = fop->filenames();
|
||||
}
|
||||
else {
|
||||
m_usedFiles.push_back(fop->filename());
|
||||
auto fn = base::normalize_path(fop->filename());
|
||||
m_usedFiles.push_back(fn);
|
||||
}
|
||||
|
||||
OpenFileJob task(fop.get());
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui/toolbar.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/open_batch.h"
|
||||
#include "base/clamp.h"
|
||||
#include "base/fs.h"
|
||||
#include "base/memory.h"
|
||||
@ -367,7 +368,9 @@ void defer_invalid_rect(const gfx::Rect& rc)
|
||||
defered_invalid_region.createUnion(defered_invalid_region, gfx::Region(rc));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Manager event handler.
|
||||
|
||||
bool CustomizedGuiManager::onProcessMessage(Message* msg)
|
||||
{
|
||||
#ifdef ENABLE_STEAM
|
||||
@ -392,6 +395,7 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg)
|
||||
if (getForegroundWindow() == App::instance()->mainWindow()) {
|
||||
base::paths files = static_cast<DropFilesMessage*>(msg)->files();
|
||||
UIContext* ctx = UIContext::instance();
|
||||
OpenBatchOfFiles batch;
|
||||
|
||||
while (!files.empty()) {
|
||||
auto fn = files.front();
|
||||
@ -422,14 +426,11 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg)
|
||||
}
|
||||
// Other extensions will be handled as an image/sprite
|
||||
else {
|
||||
OpenFileCommand cmd;
|
||||
Params params;
|
||||
params.set("filename", fn.c_str());
|
||||
params.set("repeat_checkbox", "true");
|
||||
ctx->executeCommandFromMenuOrShortcut(&cmd, params);
|
||||
batch.open(ctx, fn,
|
||||
false); // Open all frames
|
||||
|
||||
// Remove all used file names from the "dropped files"
|
||||
for (const auto& usedFn : cmd.usedFiles()) {
|
||||
for (const auto& usedFn : batch.usedFiles()) {
|
||||
auto it = std::find(files.begin(), files.end(), usedFn);
|
||||
if (it != files.end())
|
||||
files.erase(it);
|
||||
|
64
src/app/util/open_batch.h
Normal file
64
src/app/util/open_batch.h
Normal file
@ -0,0 +1,64 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_UTIL_OPEN_BATCH_H_INCLUDED
|
||||
#define APP_UTIL_OPEN_BATCH_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/commands/cmd_open_file.h"
|
||||
#include "app/context.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
// Helper class to a batch of files and handle the loading of image
|
||||
// sequences and repeat the selected action of the user (Agree/Skip
|
||||
// to open the sequence, and Repeat the action for all other
|
||||
// elements)
|
||||
class OpenBatchOfFiles {
|
||||
public:
|
||||
void open(Context* ctx,
|
||||
const std::string& fn,
|
||||
const bool oneFrame) {
|
||||
Params params;
|
||||
params.set("filename", fn.c_str());
|
||||
|
||||
if (oneFrame)
|
||||
params.set("oneframe", "true");
|
||||
else {
|
||||
switch (m_lastDecision) {
|
||||
case OpenFileCommand::SequenceDecision::Ask:
|
||||
params.set("sequence", "ask");
|
||||
params.set("repeat_checkbox", "true");
|
||||
break;
|
||||
case OpenFileCommand::SequenceDecision::Skip:
|
||||
params.set("sequence", "skip");
|
||||
break;
|
||||
case OpenFileCommand::SequenceDecision::Agree:
|
||||
params.set("sequence", "agree");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->executeCommandFromMenuOrShortcut(&m_cmd, params);
|
||||
|
||||
// Future decision for other files in the CLI
|
||||
auto d = m_cmd.seqDecision();
|
||||
if (d != OpenFileCommand::SequenceDecision::Ask)
|
||||
m_lastDecision = d;
|
||||
}
|
||||
|
||||
const base::paths& usedFiles() const {
|
||||
return m_cmd.usedFiles();
|
||||
}
|
||||
|
||||
private:
|
||||
OpenFileCommand m_cmd;
|
||||
OpenFileCommand::SequenceDecision m_lastDecision = OpenFileCommand::SequenceDecision::Ask;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user