14.9: Filter › Last Filter on Ctrl+Meta+F
This commit is contained in:
14 files changed
+306
-9
No files matched your search
@@ -441,6 +441,7 @@ private:
|
||||
QFutureWatcher<RasterMade> m_rasterCommit;
|
||||
std::optional<FilterEdit> m_filterEdit;
|
||||
FilterSettings m_filterSettings;
|
||||
std::optional<FilterKind> m_lastFilter;
|
||||
QFutureWatcher<Filtered> m_filterPreview;
|
||||
// Out until its finish runs: setFuture drops a pending signal.
|
||||
bool m_filterRendering = false;
|
||||
|
||||
@@ -16,7 +16,7 @@ bool EditorSession::canContentAwareFill() const
|
||||
return canAdjustColors() && selection().has_value() && !m_hueSaturation;
|
||||
}
|
||||
|
||||
void EditorSession::beginFilter(FilterKind kind)
|
||||
void EditorSession::beginFilter(FilterKind kind, bool repeating)
|
||||
{
|
||||
if (kind == FilterKind::contentAwareFill && !canContentAwareFill())
|
||||
return;
|
||||
@@ -61,7 +61,9 @@ void EditorSession::beginFilter(FilterKind kind)
|
||||
if (fillsCanvas)
|
||||
m_filterEdit->canvas = canvas;
|
||||
m_filterEdit->startedEmpty = startedEmpty;
|
||||
updateFilter(m_filterEdit->settings, true);
|
||||
m_filterEdit->repeating = repeating;
|
||||
// An automatic filter commits its preview, so needs one.
|
||||
updateFilter(m_filterEdit->settings, !repeating || isAutomatic(kind));
|
||||
} catch (const ProjectError &error) {
|
||||
setBrushError(QString::fromUtf8(error.what()));
|
||||
} catch (const ExportError &error) {
|
||||
@@ -69,6 +71,49 @@ void EditorSession::beginFilter(FilterKind kind)
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSession::setLastFilter(std::optional<FilterKind> kind)
|
||||
{
|
||||
m_lastFilter = kind;
|
||||
notify();
|
||||
}
|
||||
|
||||
bool EditorSession::canRepeatLastFilter() const
|
||||
{
|
||||
if (!m_lastFilter || m_filterEdit || m_hueSaturation)
|
||||
return false;
|
||||
return m_lastFilter == FilterKind::vignette ? canVignette() : canAdjustColors();
|
||||
}
|
||||
|
||||
void EditorSession::repeatLastFilter(std::function<void()> done)
|
||||
{
|
||||
if (!canRepeatLastFilter()) {
|
||||
qCWarning(lcApp) << "no last filter to run here";
|
||||
if (done)
|
||||
QMetaObject::invokeMethod(this, done, Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
const FilterKind kind = m_lastFilter.value();
|
||||
const auto run = [this, kind, done] {
|
||||
beginFilter(kind, true);
|
||||
if (!m_filterEdit) {
|
||||
if (done)
|
||||
QMetaObject::invokeMethod(this, done, Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
// Nothing applied: no panel is left to close it.
|
||||
commitFilter([this, id = m_filterEdit->id, done] {
|
||||
if (m_filterEdit && m_filterEdit->id == id)
|
||||
cancelFilter();
|
||||
if (done)
|
||||
done();
|
||||
});
|
||||
};
|
||||
if (m_gradientEdit)
|
||||
commitGradient(run);
|
||||
else
|
||||
run();
|
||||
}
|
||||
|
||||
void EditorSession::updateFilter(const FilterSettings &settings, bool preview)
|
||||
{
|
||||
if (!m_filterEdit || m_filterEdit->committing)
|
||||
@@ -243,6 +288,8 @@ void EditorSession::commitFilter(std::function<void()> done)
|
||||
m_filterPreviewFor = QUuid();
|
||||
if (edit.kind != FilterKind::cameraRaw)
|
||||
m_filterSettings = edit.settings;
|
||||
if (repeatsAsLastFilter(edit.kind))
|
||||
m_lastFilter = edit.kind;
|
||||
setIsProjectBusy(true);
|
||||
m_committingFilter = Committing{edit.id, std::move(done)};
|
||||
// A mask hides the background, which can come back.
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
// Swift's Filters extension: one filter at a time.
|
||||
public:
|
||||
bool canContentAwareFill() const;
|
||||
void beginFilter(FilterKind kind);
|
||||
// `repeating` is Last Filter: no preview unless automatic, no panel.
|
||||
void beginFilter(FilterKind kind, bool repeating = false);
|
||||
// What Filter › Last Filter runs again.
|
||||
std::optional<FilterKind> lastFilter() const { return m_lastFilter; }
|
||||
void setLastFilter(std::optional<FilterKind> kind);
|
||||
bool canRepeatLastFilter() const;
|
||||
// The last filter again, its settings kept, one step.
|
||||
void repeatLastFilter(std::function<void()> done = {});
|
||||
// The settings normalized; Preview off drops the queue and preview.
|
||||
void updateFilter(const FilterSettings &settings, bool preview);
|
||||
void cancelFilter();
|
||||
|
||||
@@ -53,6 +53,11 @@ QString rawValue(BackgroundQuality quality)
|
||||
return quality == BackgroundQuality::basic ? QStringLiteral("Basic") : QStringLiteral("Advanced");
|
||||
}
|
||||
|
||||
bool repeatsAsLastFilter(FilterKind kind)
|
||||
{
|
||||
return kind != FilterKind::contentAwareFill && !isImageAdjustment(kind);
|
||||
}
|
||||
|
||||
bool isImageAdjustment(FilterKind kind)
|
||||
{
|
||||
return kind == FilterKind::curves || kind == FilterKind::exposure || kind == FilterKind::gradientMap || kind == FilterKind::grain
|
||||
|
||||
@@ -26,6 +26,8 @@ QString rawValue(FilterKind kind);
|
||||
bool isAutomatic(FilterKind kind);
|
||||
// The Image menu's colour adjustments, not under Filter.
|
||||
bool isImageAdjustment(FilterKind kind);
|
||||
// The Filter menu's own, which Last Filter runs again.
|
||||
bool repeatsAsLastFilter(FilterKind kind);
|
||||
// Swift's allCases, the menus' order.
|
||||
inline constexpr std::array allFilterKinds{FilterKind::gaussianBlur, FilterKind::motionBlur, FilterKind::addNoise,
|
||||
FilterKind::vignette, FilterKind::bloomGlow, FilterKind::dither,
|
||||
@@ -183,6 +185,8 @@ public:
|
||||
std::optional<QRectF> canvas;
|
||||
// The layer had no pixels: the filter began clear.
|
||||
bool startedEmpty = false;
|
||||
// Last Filter: applied at once, without preview or panel.
|
||||
bool repeating = false;
|
||||
|
||||
private:
|
||||
void grow(const QRectF &extent);
|
||||
|
||||
Reference in new issue
Block a user