14.9: Filter › Last Filter on Ctrl+Meta+F

This commit is contained in:
ZacharyZhang-NY committed 2026-10-11 06:28:14 -04:00
1 parent 0136d9d41a
commit 886b18dd7f
14 files changed
+306 -9

No files matched your search

+1
View File
@@ -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;
+49 -2
View File
@@ -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.
+8 -1
View File
@@ -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();
+5
View File
@@ -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
+4
View File
@@ -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);