From fa9efe578bd1a309cbea56ea5b3859b864ebd37b Mon Sep 17 00:00:00 2001 From: fan12321 Date: Tue, 10 Jun 2025 16:19:22 +0200 Subject: [PATCH 1/2] add horizontal and vertical flip --- src/GeneralAction.cpp | 18 +++++++++- src/GeneralAction.h | 4 +++ src/Layer.cpp | 19 +++++++++-- src/LayersModel.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++- src/LayersModel.h | 39 ++++++++++++++++++++++ 5 files changed, 154 insertions(+), 4 deletions(-) diff --git a/src/GeneralAction.cpp b/src/GeneralAction.cpp index de49d898..cdceb937 100644 --- a/src/GeneralAction.cpp +++ b/src/GeneralAction.cpp @@ -13,7 +13,9 @@ GeneralAction::GeneralAction(QObject* parent, const QString& title) : _colorAction(this, "Color"), _nameAction(this, "Name"), _positionAction(this, "Position"), - _scaleAction(this, "Scale", 0.0f, 1000000.0f, 100.0f, 1) + _scaleAction(this, "Scale", 0.0f, 1000000.0f, 100.0f, 1), + _flipHorizontalAction(this, "Horizontal flip", false), + _flipVerticalAction(this, "Vertical flip", false) { addAction(&_visibleAction); addAction(&_datasetNameAction); @@ -21,6 +23,8 @@ GeneralAction::GeneralAction(QObject* parent, const QString& title) : addAction(&_nameAction); addAction(&_positionAction); addAction(&_scaleAction); + addAction(&_flipHorizontalAction); + addAction(&_flipVerticalAction); _datasetNameAction.setConnectionPermissionsToForceNone(); _datasetNameAction.setEnabled(false); @@ -33,6 +37,8 @@ GeneralAction::GeneralAction(QObject* parent, const QString& title) : _datasetNameAction.setToolTip("Name of the images dataset"); _nameAction.setToolTip("Name of the layer"); _scaleAction.setToolTip("Layer scale in percentages"); + _flipHorizontalAction.setToolTip("Flip the layer horizontally"); + _flipVerticalAction.setToolTip("Flip the layer vertically"); _scaleAction.setSuffix("%"); } @@ -67,6 +73,8 @@ void GeneralAction::initialize(Layer* layer) connect(&_visibleAction, &ToggleAction::toggled, this, updateBounds); connect(&_positionAction, &PositionAction::changed, this, updateBounds); connect(&_scaleAction, &DecimalAction::valueChanged, this, updateBounds); + connect(&_flipHorizontalAction, &ToggleAction::toggled, this, updateBounds); + connect(&_flipVerticalAction, &ToggleAction::toggled, this, updateBounds); connect(&_colorAction, &ColorAction::colorChanged, this, updateBounds); connect(&_colorAction, &ColorAction::colorChanged, this, render); @@ -94,6 +102,8 @@ void GeneralAction::connectToPublicAction(WidgetAction* publicAction, bool recur actions().connectPrivateActionToPublicAction(&_nameAction, &publicGeneralAction->getNameAction(), recursive); actions().connectPrivateActionToPublicAction(&_positionAction, &publicGeneralAction->getPositionAction(), recursive); actions().connectPrivateActionToPublicAction(&_scaleAction, &publicGeneralAction->getScaleAction(), recursive); + actions().connectPrivateActionToPublicAction(&_flipHorizontalAction, &publicGeneralAction->getFlipHorizontalAction(), recursive); + actions().connectPrivateActionToPublicAction(&_flipVerticalAction, &publicGeneralAction->getFlipVerticalAction(), recursive); } GroupAction::connectToPublicAction(publicAction, recursive); @@ -110,6 +120,8 @@ void GeneralAction::disconnectFromPublicAction(bool recursive) actions().disconnectPrivateActionFromPublicAction(&_nameAction, recursive); actions().disconnectPrivateActionFromPublicAction(&_positionAction, recursive); actions().disconnectPrivateActionFromPublicAction(&_scaleAction, recursive); + actions().disconnectPrivateActionFromPublicAction(&_flipHorizontalAction, recursive); + actions().disconnectPrivateActionFromPublicAction(&_flipVerticalAction, recursive); } GroupAction::disconnectFromPublicAction(recursive); @@ -124,6 +136,8 @@ void GeneralAction::fromVariantMap(const QVariantMap& variantMap) _nameAction.fromParentVariantMap(variantMap); _positionAction.fromParentVariantMap(variantMap); _scaleAction.fromParentVariantMap(variantMap); + _flipHorizontalAction.fromParentVariantMap(variantMap); + _flipVerticalAction.fromParentVariantMap(variantMap); } QVariantMap GeneralAction::toVariantMap() const @@ -135,6 +149,8 @@ QVariantMap GeneralAction::toVariantMap() const _nameAction.insertIntoVariantMap(variantMap); _positionAction.insertIntoVariantMap(variantMap); _scaleAction.insertIntoVariantMap(variantMap); + _flipHorizontalAction.insertIntoVariantMap(variantMap); + _flipVerticalAction.insertIntoVariantMap(variantMap); return variantMap; } \ No newline at end of file diff --git a/src/GeneralAction.h b/src/GeneralAction.h index e3546178..999280bc 100644 --- a/src/GeneralAction.h +++ b/src/GeneralAction.h @@ -75,6 +75,8 @@ class GeneralAction : public GroupAction StringAction& getNameAction() { return _nameAction; } PositionAction& getPositionAction() { return _positionAction; } DecimalAction& getScaleAction() { return _scaleAction; } + ToggleAction& getFlipHorizontalAction() { return _flipHorizontalAction; } + ToggleAction& getFlipVerticalAction() { return _flipVerticalAction; } protected: Layer* _layer; /** Pointer to owning layer */ @@ -84,6 +86,8 @@ class GeneralAction : public GroupAction StringAction _nameAction; /** Name action */ PositionAction _positionAction; /** Position action */ DecimalAction _scaleAction; /** Scale action */ + ToggleAction _flipHorizontalAction; /** Flip horizontal action */ + ToggleAction _flipVerticalAction; /** Flip vertical action */ }; Q_DECLARE_METATYPE(GeneralAction) diff --git a/src/Layer.cpp b/src/Layer.cpp index 9a82d505..094c94ca 100644 --- a/src/Layer.cpp +++ b/src/Layer.cpp @@ -120,6 +120,8 @@ void Layer::initialize(ImageViewerPlugin* imageViewerPlugin, const mv::DatasetgetGeneralAction().getFlipHorizontalAction().isChecked() ? Qt::Checked : Qt::Unchecked); +} + +QVariant LayersModel::FlipHorizontalItem::data(int role /*= Qt::UserRole + 1*/) const +{ + switch (role) { + case Qt::EditRole: + return getLayer()->getGeneralAction().getFlipHorizontalAction().isChecked(); + + case Qt::ToolTipRole: + return QString("Layer is flipped horizontally: %1").arg(data(Qt::EditRole).toBool() ? "yes" : "no"); + + case Qt::CheckStateRole: + return data(Qt::EditRole).toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked; + + default: + break; + } + + return Item::data(role); +} +void LayersModel::FlipHorizontalItem::setData(const QVariant& value, int role /* = Qt::UserRole + 1 */) +{ + switch (role) { + case Qt::CheckStateRole: + getLayer()->getGeneralAction().getFlipHorizontalAction().setChecked(value.toBool()); + break; + + default: + Item::setData(value, role); + } +} +LayersModel::FlipVerticalItem::FlipVerticalItem(Layer* layer) : + Item(layer) +{ + setCheckable(true); + setCheckState(getLayer()->getGeneralAction().getFlipVerticalAction().isChecked() ? Qt::Checked : Qt::Unchecked); +} +QVariant LayersModel::FlipVerticalItem::data(int role /*= Qt::UserRole + 1*/) const +{ + switch (role) { + case Qt::EditRole: + return getLayer()->getGeneralAction().getFlipVerticalAction().isChecked(); + + case Qt::ToolTipRole: + return QString("Layer is flipped vertically: %1").arg(data(Qt::EditRole).toBool() ? "yes" : "no"); + + case Qt::CheckStateRole: + return data(Qt::EditRole).toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked; + + default: + break; + } + + return Item::data(role); +} +void LayersModel::FlipVerticalItem::setData(const QVariant& value, int role /* = Qt::UserRole + 1 */) +{ + switch (role) { + case Qt::CheckStateRole: + getLayer()->getGeneralAction().getFlipVerticalAction().setChecked(value.toBool()); + break; + + default: + Item::setData(value, role); + } +} + LayersModel::ColorItem::ColorItem(Layer* layer) : Item(layer) { @@ -389,6 +461,8 @@ LayersModel::Row::Row(Layer* layer) append(new HeightItem(layer)); append(new ScaleItem(layer)); append(new OpacityItem(layer)); + append(new FlipHorizontalItem(layer)); + append(new FlipVerticalItem(layer)); } QMap LayersModel::columnInfo = QMap({ @@ -400,7 +474,9 @@ QMap LayersModel::columnInfo { LayersModel::Column::ImageWidth, { "Width", "Width", "Width of the image" } }, { LayersModel::Column::ImageHeight, { "Height", "Height", "Height of the image" } }, { LayersModel::Column::Scale, { "Scale", "Scale", "Scale of the image" } }, - { LayersModel::Column::Opacity, { "Opacity", "Opacity", "Layer transparency" } } + { LayersModel::Column::Opacity, { "Opacity", "Opacity", "Layer transparency" } }, + { LayersModel::Column::FlipHorizontal, { "Horizontal Flip", "Horizontal Flip", "Whether the layer is flipped horizontally or not" } }, + { LayersModel::Column::FlipVertical, { "Vertical Flip", "Vertical Flip", "Whether the layer is flipped vertically or not" } } }); LayersModel::LayersModel(ImageViewerPlugin* imageViewerPlugin) : diff --git a/src/LayersModel.h b/src/LayersModel.h index dc12dafa..f27dd808 100644 --- a/src/LayersModel.h +++ b/src/LayersModel.h @@ -28,6 +28,8 @@ class LayersModel final : public QStandardItemModel, public mv::util::Serializab ImageHeight, /** Height of the image(s) */ Scale, /** Layer scale */ Opacity, /** Layer opacity */ + FlipHorizontal, /** Flip layer horizontally */ + FlipVertical, /** Flip layer vertically */ Count }; @@ -115,6 +117,43 @@ class LayersModel final : public QStandardItemModel, public mv::util::Serializab void setData(const QVariant& value, int role /* = Qt::UserRole + 1 */) override; }; + class FlipHorizontalItem final : public Item { + public: + + /** + * Construct with \p layer + * @param layer Pointer to layer to display item for + */ + FlipHorizontalItem(Layer* layer); + + /** + * Get model data for \p role + * @return Data for \p role in variant form + */ + QVariant data(int role = Qt::UserRole + 1) const override; + + /** Set model data to \p value for \p role */ + void setData(const QVariant& value, int role /* = Qt::UserRole + 1 */) override; + }; + class FlipVerticalItem final : public Item { + public: + + /** + * Construct with \p layer + * @param layer Pointer to layer to display item for + */ + FlipVerticalItem(Layer* layer); + + /** + * Get model data for \p role + * @return Data for \p role in variant form + */ + QVariant data(int role = Qt::UserRole + 1) const override; + + /** Set model data to \p value for \p role */ + void setData(const QVariant& value, int role /* = Qt::UserRole + 1 */) override; + }; + /** Standard model item class for the layer color */ class ColorItem final : public Item { public: From e20562c7a9be36a2fc90855b15679e76b1ed1750 Mon Sep 17 00:00:00 2001 From: Thomas Kroes Date: Wed, 11 Jun 2025 08:47:41 +0200 Subject: [PATCH 2/2] Add notifications --- src/GeneralAction.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/GeneralAction.cpp b/src/GeneralAction.cpp index cdceb937..5dc0fbdf 100644 --- a/src/GeneralAction.cpp +++ b/src/GeneralAction.cpp @@ -85,6 +85,27 @@ void GeneralAction::initialize(Layer* layer) updateDatasetNameAction(); connect(_layer->getImagesDataset().get(), &DatasetImpl::locationChanged, this, updateDatasetNameAction); + + const auto showNotificationFlipX = [this]() -> void { + static bool notificationShownFlipX = false; + + if (!notificationShownFlipX) { + notificationShownFlipX = true; + _layer->getImageViewerPlugin().addNotification("Image is flipped horizontally for display purposes; the underlying data structure is not altered."); + } + }; + + const auto showNotificationFlipY = [this]() -> void { + static bool notificationShownFlipY = false; + + if (!notificationShownFlipY) { + notificationShownFlipY = true; + _layer->getImageViewerPlugin().addNotification("Image is flipped vertically for display purposes; the underlying data structure is not altered."); + } + }; + + connect(&_flipHorizontalAction, &ToggleAction::toggled, this, showNotificationFlipX); + connect(&_flipVerticalAction, &ToggleAction::toggled, this, showNotificationFlipY); } void GeneralAction::connectToPublicAction(WidgetAction* publicAction, bool recursive)