OmaPhoto 1.0.0: the Linux port of Compositor
A layered image editor for Linux and Omarchy, ported from Compositor (github.com/robbietilton/Compositor), whose Swift source is its specification. It reads and writes Compositor's .comp projects. Packages for Ubuntu, Fedora and Arch come from the release workflow; scripts/install/ holds one install script per distribution family, and flake.nix serves NixOS. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
c864304695
564 files changed
+100804
No files matched your search
@@ -0,0 +1,327 @@
|
||||
#include "UI/CompositorMenus.h"
|
||||
#include "Logging.h"
|
||||
#include <QApplication>
|
||||
#include <QMenu>
|
||||
|
||||
namespace {
|
||||
// An entry's name: Hue/Saturation is newHueSaturationAdjustment.
|
||||
QString adjustmentName(AdjustmentKind kind)
|
||||
{
|
||||
return QStringLiteral("new%1Adjustment").arg(rawValue(kind).remove(QLatin1Char(' ')).remove(QLatin1Char('/')));
|
||||
}
|
||||
|
||||
// A filter's entry from Swift's title: gaussianBlur.
|
||||
QString filterName(FilterKind kind)
|
||||
{
|
||||
QString name = rawValue(kind);
|
||||
name.remove(QLatin1Char(' '));
|
||||
name[0] = name[0].toLower();
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
CompositorMenus::CompositorMenus(ProjectWorkspace &workspace, QMenuBar &bar, QWidget &window)
|
||||
: QObject(&bar), m_workspace(workspace), m_window(window)
|
||||
{
|
||||
QMenu *file = bar.addMenu(QStringLiteral("&File"));
|
||||
add(file, QStringLiteral("newCanvas"), QStringLiteral("New Canvas…"), QKeySequence(Qt::CTRL | Qt::Key_N), [this] { projects().newCanvas(); });
|
||||
add(file, QStringLiteral("openProject"), QStringLiteral("Open Project…"), QKeySequence(Qt::CTRL | Qt::Key_O), [this] { projects().open(); });
|
||||
add(file, QStringLiteral("importImages"), QStringLiteral("Import Images…"), QKeySequence(), [this] { session().setShowsImporter(true); });
|
||||
file->addSeparator();
|
||||
add(file, QStringLiteral("save"), QStringLiteral("Save"), QKeySequence(Qt::CTRL | Qt::Key_S), [this] { projects().save(); });
|
||||
add(file, QStringLiteral("saveAs"), QStringLiteral("Save As…"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_S), [this] { projects().save(true); });
|
||||
file->addSeparator();
|
||||
add(file, QStringLiteral("exportPNG"), QStringLiteral("Export PNG…"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_E), [this] { projects().exportPNG(); });
|
||||
add(file, QStringLiteral("exportJPEG"), QStringLiteral("Export JPEG…"), QKeySequence(Qt::CTRL | Qt::ALT | Qt::SHIFT | Qt::Key_S),
|
||||
[this] { projects().exportJPEG(); });
|
||||
file->addSeparator();
|
||||
add(file, QStringLiteral("closeProject"), QStringLiteral("Close Project"), QKeySequence(Qt::CTRL | Qt::Key_W), [this] { projects().close(&m_window); });
|
||||
|
||||
QMenu *edit = bar.addMenu(QStringLiteral("&Edit"));
|
||||
add(edit, QStringLiteral("undo"), QStringLiteral("Undo"), QKeySequence(Qt::CTRL | Qt::Key_Z), [this] {
|
||||
if (m_field)
|
||||
m_field->undo();
|
||||
else if (InlineTextEditor *text = typedText())
|
||||
text->undo();
|
||||
else
|
||||
session().undo();
|
||||
});
|
||||
add(edit, QStringLiteral("redo"), QStringLiteral("Redo"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_Z), [this] {
|
||||
if (m_field)
|
||||
m_field->redo();
|
||||
else if (InlineTextEditor *text = typedText())
|
||||
text->redo();
|
||||
else
|
||||
session().redo();
|
||||
});
|
||||
edit->addSeparator();
|
||||
// Cut, Copy and Paste check when chosen, as Swift's do.
|
||||
add(edit, QStringLiteral("cut"), QStringLiteral("Cut"), QKeySequence(Qt::CTRL | Qt::Key_X), [this] {
|
||||
if (m_field)
|
||||
m_field->cut();
|
||||
else if (InlineTextEditor *text = typedText())
|
||||
text->cut();
|
||||
else if (session().selection() && session().canCopyPixels())
|
||||
session().cutSelection();
|
||||
else
|
||||
qCWarning(lcApp) << "nothing to cut";
|
||||
});
|
||||
add(edit, QStringLiteral("copy"), QStringLiteral("Copy"), QKeySequence(Qt::CTRL | Qt::Key_C), [this] {
|
||||
if (m_field)
|
||||
m_field->copy();
|
||||
else if (InlineTextEditor *text = typedText())
|
||||
text->copy();
|
||||
else if (session().canCopyPixels())
|
||||
session().copySelection();
|
||||
else
|
||||
qCWarning(lcApp) << "nothing to copy";
|
||||
});
|
||||
add(edit, QStringLiteral("copyMerged"), QStringLiteral("Copy Merged"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_C), [this] { session().copyMergedSelection(); });
|
||||
add(edit, QStringLiteral("paste"), QStringLiteral("Paste"), QKeySequence(Qt::CTRL | Qt::Key_V), [this] {
|
||||
if (m_field)
|
||||
m_field->paste();
|
||||
else if (InlineTextEditor *text = typedText())
|
||||
text->paste();
|
||||
else if (session().canPaste())
|
||||
session().paste();
|
||||
else
|
||||
qCWarning(lcApp) << "nothing to paste";
|
||||
});
|
||||
edit->addSeparator();
|
||||
// Text fields delete the selection, else back from the caret.
|
||||
add(edit, QStringLiteral("fillForeground"), QStringLiteral("Fill with Foreground Color"), QKeySequence(Qt::ALT | Qt::Key_Backspace), [this] {
|
||||
if (!m_field) {
|
||||
session().fillSelection(EditorSession::FillSource::foreground);
|
||||
return;
|
||||
}
|
||||
if (!m_field->hasSelectedText())
|
||||
m_field->cursorWordBackward(true);
|
||||
m_field->backspace();
|
||||
});
|
||||
add(edit, QStringLiteral("fillBackground"), QStringLiteral("Fill with Background Color"), QKeySequence(Qt::CTRL | Qt::Key_Backspace), [this] {
|
||||
if (!m_field) {
|
||||
session().fillSelection(EditorSession::FillSource::background);
|
||||
return;
|
||||
}
|
||||
if (!m_field->hasSelectedText())
|
||||
m_field->home(true);
|
||||
m_field->backspace();
|
||||
});
|
||||
add(edit, QStringLiteral("clearSelectionPixels"), QStringLiteral("Clear Selection Pixels"), QKeySequence(), [this] { session().clearSelectedPixels(); });
|
||||
add(edit, QStringLiteral("contentAwareFill"), QStringLiteral("Content-Aware Fill…"), QKeySequence(Qt::SHIFT | Qt::Key_Backspace),
|
||||
[this] { session().beginFilter(FilterKind::contentAwareFill); });
|
||||
|
||||
QMenu *view = bar.addMenu(QStringLiteral("&View"));
|
||||
add(view, QStringLiteral("fit"), QStringLiteral("Fit Canvas"), QKeySequence(Qt::CTRL | Qt::Key_0), [this] { session().fit(); });
|
||||
add(view, QStringLiteral("actualPixels"), QStringLiteral("Actual Pixels"), QKeySequence(Qt::CTRL | Qt::Key_1), [this] { session().zoom(1); });
|
||||
add(view, QStringLiteral("zoomIn"), QStringLiteral("Zoom In"), QKeySequence(Qt::CTRL | Qt::Key_Equal), [this] { session().zoom(session().viewport.zoom() * 1.25); });
|
||||
add(view, QStringLiteral("zoomOut"), QStringLiteral("Zoom Out"), QKeySequence(Qt::CTRL | Qt::Key_Minus), [this] { session().zoom(session().viewport.zoom() / 1.25); });
|
||||
add(view, QStringLiteral("pixelGrid"), QStringLiteral("Pixel Grid (800% and above)"), QKeySequence(), [this] { session().setShowsPixelGrid(!session().showsPixelGrid()); })
|
||||
->setCheckable(true);
|
||||
// Ctrl+H: the Move tool's box; the desktop hides apps.
|
||||
add(view, QStringLiteral("transformControls"), QStringLiteral("Show Transform Controls"), QKeySequence(Qt::CTRL | Qt::Key_H),
|
||||
[this] { session().setShowsTransformControls(!session().showsTransformControls()); })
|
||||
->setCheckable(true);
|
||||
|
||||
QMenu *select = bar.addMenu(QStringLiteral("&Select"));
|
||||
// Text fields keep their own Select All.
|
||||
add(select, QStringLiteral("selectAll"), QStringLiteral("All"), QKeySequence(Qt::CTRL | Qt::Key_A), [this] {
|
||||
if (m_field)
|
||||
m_field->selectAll();
|
||||
else if (InlineTextEditor *text = typedText())
|
||||
text->selectAll();
|
||||
else
|
||||
session().selectAll();
|
||||
});
|
||||
add(select, QStringLiteral("deselect"), QStringLiteral("Deselect"), QKeySequence(Qt::CTRL | Qt::Key_D), [this] { session().deselect(); });
|
||||
add(select, QStringLiteral("inverse"), QStringLiteral("Inverse"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_I), [this] { session().invertSelection(); });
|
||||
add(select, QStringLiteral("layerPixels"), QStringLiteral("Layer's Pixels"), QKeySequence(), [this] {
|
||||
if (const std::optional<QUuid> id = session().activeLayerID())
|
||||
session().loadLayerSelection(*id);
|
||||
});
|
||||
add(select, QStringLiteral("maskBlackAreas"), QStringLiteral("Mask's Black Areas"), QKeySequence(), [this] {
|
||||
if (const std::optional<QUuid> id = session().activeLayerID())
|
||||
session().loadMaskSelection(*id);
|
||||
});
|
||||
select->addSeparator();
|
||||
add(select, QStringLiteral("expandSelection"), QStringLiteral("Expand by 1 px"), QKeySequence(), [this] { session().expandSelection(session().selectionExpandAmount()); });
|
||||
add(select, QStringLiteral("contractSelection"), QStringLiteral("Contract by 1 px"), QKeySequence(), [this] { session().contractSelection(session().selectionContractAmount()); });
|
||||
|
||||
QMenu *image = bar.addMenu(QStringLiteral("&Image"));
|
||||
add(image, QStringLiteral("curves"), QStringLiteral("Curves…"), QKeySequence(Qt::CTRL | Qt::Key_M), [this] { session().beginFilter(FilterKind::curves); });
|
||||
add(image, QStringLiteral("levels"), QStringLiteral("Levels…"), QKeySequence(Qt::CTRL | Qt::Key_L), [this] { session().beginLevels(); });
|
||||
add(image, QStringLiteral("hueSaturation"), QStringLiteral("Hue/Saturation…"), QKeySequence(Qt::CTRL | Qt::Key_U),
|
||||
[this] { session().beginHueSaturation(); });
|
||||
for (const FilterKind kind : {FilterKind::exposure, FilterKind::gradientMap, FilterKind::grain})
|
||||
add(image, filterName(kind), rawValue(kind) + QStringLiteral("…"), QKeySequence(), [this, kind] { session().beginFilter(kind); });
|
||||
add(image, QStringLiteral("invert"), QStringLiteral("Invert"), QKeySequence(Qt::CTRL | Qt::Key_I), [this] { session().invertPixels(); });
|
||||
image->addSeparator();
|
||||
add(image, QStringLiteral("canvasSize"), QStringLiteral("Canvas Size…"), QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_C), [this] { projects().canvasSize(); });
|
||||
add(image, QStringLiteral("imageSize"), QStringLiteral("Image Size…"), QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_I), [this] { projects().imageSize(); });
|
||||
image->addSeparator();
|
||||
add(image, QStringLiteral("flipCanvasHorizontal"), QStringLiteral("Flip Canvas Horizontal"), QKeySequence(), [this] { session().flipCanvas(true); });
|
||||
add(image, QStringLiteral("flipCanvasVertical"), QStringLiteral("Flip Canvas Vertical"), QKeySequence(), [this] { session().flipCanvas(false); });
|
||||
|
||||
QMenu *filter = bar.addMenu(QStringLiteral("Fil&ter"));
|
||||
for (const FilterKind kind : allFilterKinds) {
|
||||
if (kind != FilterKind::contentAwareFill && !isImageAdjustment(kind))
|
||||
add(filter, filterName(kind), rawValue(kind) + QStringLiteral("…"), QKeySequence(), [this, kind] { session().beginFilter(kind); });
|
||||
}
|
||||
|
||||
QMenu *layer = bar.addMenu(QStringLiteral("&Layer"));
|
||||
QMenu *adjustments = layer->addMenu(QStringLiteral("New Adjustment Layer"));
|
||||
adjustments->menuAction()->setObjectName(QStringLiteral("newAdjustmentLayer"));
|
||||
for (const AdjustmentKind kind : allAdjustmentKinds)
|
||||
add(adjustments, adjustmentName(kind), rawValue(kind) + QStringLiteral("…"), QKeySequence(), [this, kind] { session().addAdjustment(kind); });
|
||||
add(layer, QStringLiteral("editAdjustment"), QStringLiteral("Edit Adjustment…"), QKeySequence(),
|
||||
[this] { session().setAdjustmentEditingID(session().activeLayerID()); });
|
||||
layer->addSeparator();
|
||||
// Swift's transformCommand: with selected pixels, Transform Selection.
|
||||
add(layer, QStringLiteral("transformLayer"), QStringLiteral("Transform Layer"), QKeySequence(Qt::CTRL | Qt::Key_T), [this] { session().transformCommand(); });
|
||||
// Swift's layerViaCopy: a selection makes it Layer via Copy.
|
||||
add(layer, QStringLiteral("layerViaCopy"), QStringLiteral("Duplicate Layer"), QKeySequence(Qt::CTRL | Qt::Key_J), [this] { session().layerViaCopy(); });
|
||||
layer->addSeparator();
|
||||
add(layer, QStringLiteral("clippingMask"), QStringLiteral("Create Clipping Mask"), QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_G), [this] {
|
||||
if (const std::optional<QUuid> id = session().activeLayerID())
|
||||
session().toggleClippingMask(*id);
|
||||
});
|
||||
layer->addSeparator();
|
||||
add(layer, QStringLiteral("groupLayers"), QStringLiteral("Group Selected Layers"), QKeySequence(Qt::CTRL | Qt::Key_G), [this] { session().groupSelectedLayers(); });
|
||||
add(layer, QStringLiteral("moveOutOfFolder"), QStringLiteral("Move Out of Folder"), QKeySequence(), [this] { session().moveActiveLayerOutOfGroup(); });
|
||||
add(layer, QStringLiteral("newBlankLayer"), QStringLiteral("New Blank Layer"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_N), [this] { session().addBlankLayer(); });
|
||||
add(layer, QStringLiteral("renameLayer"), QStringLiteral("Rename Layer…"), QKeySequence(), [this] { session().setRenamingLayerID(session().activeLayerID()); });
|
||||
add(layer, QStringLiteral("layerVisibility"), QStringLiteral("Hide Layer"), QKeySequence(), [this] {
|
||||
if (const std::optional<QUuid> id = session().activeLayerID())
|
||||
session().toggleLayerVisibility(*id);
|
||||
});
|
||||
layer->addSeparator();
|
||||
add(layer, QStringLiteral("moveLayerUp"), QStringLiteral("Move Layer Up"), QKeySequence(Qt::CTRL | Qt::Key_BracketRight), [this] { session().moveActiveLayer(1); });
|
||||
add(layer, QStringLiteral("moveLayerDown"), QStringLiteral("Move Layer Down"), QKeySequence(Qt::CTRL | Qt::Key_BracketLeft), [this] { session().moveActiveLayer(-1); });
|
||||
add(layer, QStringLiteral("mergeLayers"), QStringLiteral("Merge Down"), QKeySequence(Qt::CTRL | Qt::Key_E), [this] { session().mergeLayers(); });
|
||||
layer->addSeparator();
|
||||
add(layer, QStringLiteral("flipHorizontal"), QStringLiteral("Flip Layer Horizontal"), QKeySequence(), [this] { session().flipLayers(true); });
|
||||
add(layer, QStringLiteral("flipVertical"), QStringLiteral("Flip Layer Vertical"), QKeySequence(), [this] { session().flipLayers(false); });
|
||||
layer->addSeparator();
|
||||
add(layer, QStringLiteral("deleteLayer"), QStringLiteral("Delete Layer"), QKeySequence(), [this] { session().deleteLayerOrMask(); });
|
||||
|
||||
connect(&m_workspace, &ProjectWorkspace::changed, this, &CompositorMenus::watchFront);
|
||||
// A field gaining or losing focus changes Undo's meaning.
|
||||
connect(qApp, &QApplication::focusChanged, this, &CompositorMenus::focusMoved);
|
||||
watchFront();
|
||||
}
|
||||
|
||||
QAction *CompositorMenus::add(QMenu *menu, const QString &name, const QString &text, const QKeySequence &shortcut, const std::function<void()> &run)
|
||||
{
|
||||
QAction *made = menu->addAction(text);
|
||||
made->setObjectName(name);
|
||||
made->setShortcut(shortcut);
|
||||
connect(made, &QAction::triggered, this, run);
|
||||
return made;
|
||||
}
|
||||
|
||||
QAction *CompositorMenus::action(const QString &name) const
|
||||
{
|
||||
return parent()->findChild<QAction *>(name);
|
||||
}
|
||||
|
||||
void CompositorMenus::watchFront()
|
||||
{
|
||||
// The front tab's session drives every entry.
|
||||
if (m_watchedTab != std::optional(m_workspace.current().id)) {
|
||||
m_watchedTab = m_workspace.current().id;
|
||||
disconnect(m_sessionWatch);
|
||||
m_sessionWatch = connect(&session(), &EditorSession::changed, this, &CompositorMenus::synchronize);
|
||||
}
|
||||
synchronize();
|
||||
}
|
||||
|
||||
void CompositorMenus::focusMoved(QWidget *, QWidget *to)
|
||||
{
|
||||
// The menu bar borrows focus; the field keeps Undo.
|
||||
if (qobject_cast<QMenuBar *>(to) == nullptr) {
|
||||
m_field = qobject_cast<QLineEdit *>(to);
|
||||
m_canvas = qobject_cast<CanvasView *>(to);
|
||||
}
|
||||
synchronize();
|
||||
}
|
||||
|
||||
void CompositorMenus::synchronize()
|
||||
{
|
||||
EditorSession &s = session();
|
||||
ProjectController &p = projects();
|
||||
const std::optional<ImageLayer> active = s.activeLayer();
|
||||
const bool drawn = s.document().has_value();
|
||||
// Swift's text branch: open text makes the entries bare.
|
||||
const bool typing = m_field != nullptr || s.textDraft().has_value();
|
||||
action(QStringLiteral("newCanvas"))->setEnabled(p.canStart());
|
||||
action(QStringLiteral("openProject"))->setEnabled(p.canStart());
|
||||
action(QStringLiteral("importImages"))->setEnabled(!s.levels() && !s.showsBusy() && !s.isImporting() && !s.showsNewDocument());
|
||||
action(QStringLiteral("save"))->setEnabled(drawn && p.canStart());
|
||||
action(QStringLiteral("saveAs"))->setEnabled(drawn && p.canStart());
|
||||
action(QStringLiteral("exportPNG"))->setEnabled(drawn && p.canStart());
|
||||
action(QStringLiteral("exportJPEG"))->setEnabled(drawn && p.canStart());
|
||||
action(QStringLiteral("closeProject"))->setEnabled(p.canStart());
|
||||
// In a field, Undo is the field's and bare.
|
||||
action(QStringLiteral("undo"))->setText(!typing && s.canUndo() ? QStringLiteral("Undo %1").arg(s.history.undoName()) : QStringLiteral("Undo"));
|
||||
action(QStringLiteral("undo"))->setEnabled(typing || s.canUndo());
|
||||
action(QStringLiteral("redo"))->setText(!typing && s.canRedo() ? QStringLiteral("Redo %1").arg(s.history.redoName()) : QStringLiteral("Redo"));
|
||||
action(QStringLiteral("redo"))->setEnabled(typing || s.canRedo());
|
||||
for (const char *name : {"fit", "actualPixels", "zoomIn", "zoomOut"})
|
||||
action(QString::fromLatin1(name))->setEnabled(drawn);
|
||||
action(QStringLiteral("pixelGrid"))->setChecked(s.showsPixelGrid());
|
||||
action(QStringLiteral("transformControls"))->setChecked(s.showsTransformControls());
|
||||
action(QStringLiteral("transformControls"))->setEnabled(s.tool() == NavigationTool::move && s.document().has_value());
|
||||
const bool selected = s.selection().has_value();
|
||||
action(QStringLiteral("selectAll"))->setEnabled(drawn);
|
||||
action(QStringLiteral("deselect"))->setEnabled(selected && s.canEditSelection());
|
||||
action(QStringLiteral("inverse"))->setEnabled(selected && s.canEditSelection());
|
||||
action(QStringLiteral("layerPixels"))->setEnabled(active && active->asset && s.canEditSelection());
|
||||
action(QStringLiteral("maskBlackAreas"))->setEnabled(active && active->mask && s.canEditSelection());
|
||||
action(QStringLiteral("expandSelection"))->setText(QStringLiteral("Expand by %1 px").arg(s.selectionExpandAmount()));
|
||||
action(QStringLiteral("expandSelection"))->setEnabled(s.canModifySelection());
|
||||
action(QStringLiteral("contractSelection"))->setText(QStringLiteral("Contract by %1 px").arg(s.selectionContractAmount()));
|
||||
action(QStringLiteral("contractSelection"))->setEnabled(s.canModifySelection());
|
||||
action(QStringLiteral("levels"))->setEnabled(s.canAdjustColors() && !s.hueSaturation());
|
||||
for (const FilterKind kind : allFilterKinds) {
|
||||
if (kind != FilterKind::contentAwareFill)
|
||||
action(filterName(kind))->setEnabled(s.canAdjustColors() && !s.hueSaturation());
|
||||
}
|
||||
action(QStringLiteral("hueSaturation"))->setEnabled(s.canAdjustColors());
|
||||
action(QStringLiteral("invert"))->setText(s.isMaskSelected() ? QStringLiteral("Invert Mask") : QStringLiteral("Invert"));
|
||||
action(QStringLiteral("invert"))->setEnabled(s.canInvert());
|
||||
action(QStringLiteral("canvasSize"))->setEnabled(drawn && p.canStart());
|
||||
action(QStringLiteral("imageSize"))->setEnabled(drawn && p.canStart());
|
||||
action(QStringLiteral("flipCanvasHorizontal"))->setEnabled(s.canEditLayers());
|
||||
action(QStringLiteral("flipCanvasVertical"))->setEnabled(s.canEditLayers());
|
||||
action(QStringLiteral("newAdjustmentLayer"))->setEnabled(s.canEditLayers());
|
||||
action(QStringLiteral("editAdjustment"))->setEnabled(s.canEditLayers() && active && active->adjustment);
|
||||
action(QStringLiteral("transformLayer"))->setText(s.canTransformSelection() ? QStringLiteral("Transform Selection") : QStringLiteral("Transform Layer"));
|
||||
action(QStringLiteral("transformLayer"))->setEnabled(s.canTransform() || s.canTransformSelection());
|
||||
action(QStringLiteral("clippingMask"))->setText(active && active->maskSourceID ? QStringLiteral("Release Clipping Mask") : QStringLiteral("Create Clipping Mask"));
|
||||
action(QStringLiteral("clippingMask"))->setEnabled(s.activeLayerID() && s.canToggleClippingMask(*s.activeLayerID()));
|
||||
action(QStringLiteral("groupLayers"))->setEnabled(s.canEditLayers());
|
||||
action(QStringLiteral("moveOutOfFolder"))->setEnabled(s.canEditLayers() && active && active->parentID);
|
||||
action(QStringLiteral("newBlankLayer"))->setEnabled(s.canEditLayers());
|
||||
action(QStringLiteral("renameLayer"))->setEnabled(s.canEditLayers() && active);
|
||||
action(QStringLiteral("layerVisibility"))->setText(active && !active->isVisible ? QStringLiteral("Show Layer") : QStringLiteral("Hide Layer"));
|
||||
action(QStringLiteral("layerVisibility"))->setEnabled(s.canEditLayers() && active);
|
||||
action(QStringLiteral("moveLayerUp"))->setEnabled(s.canMoveActiveLayer(1));
|
||||
action(QStringLiteral("moveLayerDown"))->setEnabled(s.canMoveActiveLayer(-1));
|
||||
action(QStringLiteral("copyMerged"))->setEnabled(s.canCopyMerged());
|
||||
action(QStringLiteral("contentAwareFill"))->setEnabled(s.canContentAwareFill());
|
||||
action(QStringLiteral("fillForeground"))->setEnabled(s.canEditPixels());
|
||||
action(QStringLiteral("fillBackground"))->setEnabled(s.canEditPixels());
|
||||
action(QStringLiteral("clearSelectionPixels"))->setEnabled(s.selection().has_value() && s.canEditPixels());
|
||||
action(QStringLiteral("layerViaCopy"))->setText(s.selection() ? QStringLiteral("Layer via Copy") : QStringLiteral("Duplicate Layer"));
|
||||
action(QStringLiteral("layerViaCopy"))->setEnabled(s.canCopyPixels() || (!s.selection() && s.canEditLayers() && active && !active->isGroup));
|
||||
action(QStringLiteral("mergeLayers"))->setText(s.mergeTitle());
|
||||
action(QStringLiteral("mergeLayers"))->setEnabled(s.canMergeLayers());
|
||||
action(QStringLiteral("flipHorizontal"))->setEnabled(s.canTransform());
|
||||
action(QStringLiteral("flipVertical"))->setEnabled(s.canTransform());
|
||||
const std::optional<LayerEffectSelection> effect = s.selectedEffect();
|
||||
action(QStringLiteral("deleteLayer"))->setText(effect ? QStringLiteral("Delete ") + rawValue(effect->kind)
|
||||
: s.isMaskSelected() && active && active->mask ? QStringLiteral("Delete Layer Mask")
|
||||
: s.selectedLayerIDs().size() > 1 ? QStringLiteral("Delete Layers")
|
||||
: QStringLiteral("Delete Layer"));
|
||||
action(QStringLiteral("deleteLayer"))->setEnabled(s.canEditLayers() && active);
|
||||
}
|
||||
Reference in new issue
Block a user