Skip to content

Commit

Permalink
Improve handling of image sequences when dropping files or opening mu…
Browse files Browse the repository at this point in the history
…ltiple 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).
  • Loading branch information
dacap committed Jul 30, 2020
1 parent 1255b17 commit 8c0f81c
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 36 deletions.
30 changes: 5 additions & 25 deletions src/app/cli/cli_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions src/app/cli/cli_processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand Down
29 changes: 26 additions & 3 deletions src/app/commands/cmd_open_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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));
Expand All @@ -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());
Expand Down
13 changes: 7 additions & 6 deletions src/app/modules/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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();
Expand Down Expand Up @@ -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);
Expand Down
64 changes: 64 additions & 0 deletions src/app/util/open_batch.h
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 8c0f81c

Please sign in to comment.