From 6fa586049f7e9562d1f7f647304e58dbf79d37aa Mon Sep 17 00:00:00 2001 From: Thomas Kroes Date: Wed, 20 Nov 2024 08:48:48 +0100 Subject: [PATCH] Work on highlighting system --- ManiVault/src/AbstractActionsManager.h | 22 +++ ManiVault/src/actions/WidgetAction.cpp | 54 ++++--- ManiVault/src/actions/WidgetAction.h | 152 +++++++++++++----- .../src/actions/WidgetActionContextMenu.cpp | 2 +- .../actions/WidgetActionHighlightWidget.cpp | 93 ++++++++--- .../src/actions/WidgetActionHighlightWidget.h | 41 ++++- .../src/actions/WidgetActionMimeData.cpp | 47 ++++-- .../src/actions/WidgetActionViewWidget.cpp | 8 +- .../src/actions/WidgetActionViewWidget.h | 2 +- ManiVault/src/models/ActionsFilterModel.cpp | 30 ++-- ManiVault/src/models/ActionsFilterModel.h | 8 +- ManiVault/src/widgets/ActionsWidget.cpp | 6 +- 12 files changed, 334 insertions(+), 131 deletions(-) diff --git a/ManiVault/src/AbstractActionsManager.h b/ManiVault/src/AbstractActionsManager.h index 2747f3fa0..30a3562ae 100644 --- a/ManiVault/src/AbstractActionsManager.h +++ b/ManiVault/src/AbstractActionsManager.h @@ -337,6 +337,28 @@ class CORE_EXPORT AbstractActionsManager : public AbstractManager } } + /** + * Get a list of candidate connections between descendants of \p widgetActionLhs and \p widgetActionRhs + * @param widgetActionLhs Pointer to widget action + * @param widgetActionRhs Pointer to widget action + * @return List of candidate connections + */ + static std::vector> getCandidateConnectionsForDescendants(const gui::WidgetAction* widgetActionLhs, const gui::WidgetAction* widgetActionRhs) { + const auto widgetActionDescendantsLhs = widgetActionLhs->getChildren(true); + const auto widgetActionDescendantsRhs = widgetActionRhs->getChildren(true); + + std::vector> candidateConnections; + + for (const auto widgetActionDescendantLhs : widgetActionDescendantsLhs) { + for (const auto widgetActionDescendantRhs : widgetActionDescendantsRhs) { + if (widgetActionDescendantLhs->getTypeString() == widgetActionDescendantRhs->getTypeString()) + candidateConnections.push_back({ widgetActionDescendantLhs, widgetActionDescendantRhs }); + } + } + + return candidateConnections; + } + protected: /** diff --git a/ManiVault/src/actions/WidgetAction.cpp b/ManiVault/src/actions/WidgetAction.cpp index a521ef1df..b5c18450e 100644 --- a/ManiVault/src/actions/WidgetAction.cpp +++ b/ManiVault/src/actions/WidgetAction.cpp @@ -50,15 +50,10 @@ WidgetAction::WidgetAction(QObject* parent, const QString& title) : _cachedConnectionPermissions(static_cast(ConnectionPermissionFlag::None)), _scope(Scope::Private), _publicAction(nullptr), - _connectedActions(), - _settingsPrefix(), - _highlighting(HighlightOption::None), - _popupSizeHint(), - _overrideSizeHint(), + _highlightVisible(false), + _highlightMode(HighlightMode::Light), _configuration(static_cast(ConfigurationFlag::Default)), - _location(), _namedIcon(""), - _widgetConfigurationFunction(), _badge(this) { Q_ASSERT(!title.isEmpty()); @@ -75,7 +70,6 @@ WidgetAction::WidgetAction(QObject* parent, const QString& title) : if (projects().hasProject()) setStudioMode(projects().getCurrentProject()->getStudioModeAction().isChecked(), false); } - } WidgetAction::~WidgetAction() @@ -230,39 +224,59 @@ void WidgetAction::setDefaultWidgetFlag(const std::int32_t& widgetFlag, bool uns _defaultWidgetFlags |= static_cast(widgetFlag); } -WidgetAction::HighlightOption WidgetAction::getHighlighting() const +WidgetAction::HighlightMode WidgetAction::getHighlightMode() const { - return _highlighting; + return _highlightMode; } -bool WidgetAction::isHighlighted() const +bool WidgetAction::isHighlightVisible() const { - return (_highlighting == HighlightOption::Moderate) || (_highlighting == HighlightOption::Strong); + return _highlightVisible; } -void WidgetAction::setHighlighting(const HighlightOption& highlighting) +void WidgetAction::setHighlightMode(const HighlightMode& highlightMode) { - if (highlighting == _highlighting) + if (highlightMode == _highlightMode) return; - _highlighting = highlighting; + _highlightMode = highlightMode; - emit highlightingChanged(_highlighting); + emit highlightModeChanged(_highlightMode); } -void WidgetAction::setHighlighted(bool highlighted) +void WidgetAction::setHighlightVisible(bool highlightVisible) { - setHighlighting(highlighted ? HighlightOption::Moderate : HighlightOption::None); + if (highlightVisible == _highlightVisible) + return; + + _highlightVisible = highlightVisible; + + emit highlightVisibilityChanged(_highlightVisible); } void WidgetAction::highlight() { - setHighlighted(true); + setHighlightVisible(true); } void WidgetAction::unHighlight() { - setHighlighted(false); + setHighlightVisible(false); +} + +QString WidgetAction::getHighlightDescription() const +{ + return _highlightDescription; +} + +void WidgetAction::setHighlightDescription(const QString& highlightDescription) +{ + if (highlightDescription == _highlightDescription) + return; + + _highlightDescription = highlightDescription; + + emit highlightDescriptionChanged(_highlightDescription); } WidgetAction::Scope WidgetAction::getScope() const diff --git a/ManiVault/src/actions/WidgetAction.h b/ManiVault/src/actions/WidgetAction.h index 9a7b05366..e82b91f69 100644 --- a/ManiVault/src/actions/WidgetAction.h +++ b/ManiVault/src/actions/WidgetAction.h @@ -60,9 +60,9 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable /** Map scope enum to scope name */ static QMap scopeNames; - /** Describes the highlight options */ - enum class HighlightOption { - None, /** Action is not highlighted */ + /** Describes the highlight modes */ + enum class HighlightMode { + Light, /** Action is slightly highlighted */ Moderate, /** Action is moderately highlighted */ Strong /** Action is strongly highlighted */ }; @@ -121,7 +121,7 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable WidgetAction(QObject* parent, const QString& title); /** Destructor */ - ~WidgetAction(); + ~WidgetAction() override; public: // Hierarchy queries @@ -170,6 +170,46 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable return ancestors; } + /** + * Establish whether the widget action has an ancestor of \p WidgetActionType + * @return Boolean determining whether the widget action has an ancestor of the specified type + */ + template + bool hasAncestorOfType() const { + auto currentParent = dynamic_cast(parent()); + + std::int32_t numberOfAncestorsOfType = 0; + + while (currentParent) { + if (dynamic_cast(currentParent)) + ++numberOfAncestorsOfType; + + currentParent = currentParent->parent(); + } + + return numberOfAncestorsOfType > 0; + } + + /** + * Establish whether the widget action has an ancestor of \p WidgetActionType + * @param typeString Widget action type string to search for + * @return Boolean determining whether the widget action has an ancestor of the specified type + */ + bool hasAncestorOfType(const QString& typeString) const { + auto currentParent = parent(); + + std::int32_t numberOfAncestorsOfType = 0; + + while (currentParent) { + if (typeString == getTypeString(currentParent)) + ++numberOfAncestorsOfType; + + currentParent = currentParent->parent(); + } + + return numberOfAncestorsOfType > 0; + } + /** * Get child actions of \p WidgetActionType, possibly \p recursively * @param recursively Get children recursively @@ -288,7 +328,7 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * Compute the location of the action and update the cached location if it changed * @param recursive Whether to also update child actions recursively */ - virtual void updateLocation(bool recursive = true) final; + void updateLocation(bool recursive = true); public: @@ -317,13 +357,13 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * Establish whether this action is positioned at the top of the hierarchy * @return Boolean determining whether this action is positioned at the top of the hierarchy */ - virtual bool isRoot() const final; + bool isRoot() const; /** * Establish whether this action is positioned at the bottom of the hierarchy * @return Boolean determining whether this action is positioned at the bottom of the hierarchy */ - virtual bool isLeaf() const final; + bool isLeaf() const; public: // Widgets @@ -332,7 +372,7 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * @param parent Parent widget * @return Pointer to created widget */ - virtual QWidget* createWidget(QWidget* parent) override final; + QWidget* createWidget(QWidget* parent) override; /** * Create widget with pointer to \p parent widget and \p widgetFlags @@ -340,7 +380,7 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * @param widgetFlags Widget flags * @return Pointer to created widget */ - virtual QWidget* createWidget(QWidget* parent, const std::int32_t& widgetFlags) final; + QWidget* createWidget(QWidget* parent, const std::int32_t& widgetFlags); /** * Create widget with pointer to \p parent widget, \p widgetFlags and \p widgetConfigurationFunction @@ -349,7 +389,7 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * @param widgetConfigurationFunction Configuration function to run after the widget is created (overrides WidgetAction#_widgetConfigurationFunction) * @return Pointer to created widget */ - virtual QWidget* createWidget(QWidget* parent, const std::int32_t& widgetFlags, const WidgetConfigurationFunction& widgetConfigurationFunction) final; + QWidget* createWidget(QWidget* parent, const std::int32_t& widgetFlags, const WidgetConfigurationFunction& widgetConfigurationFunction); /** * Create widget with pointer to \p parent widget and \p widgetConfigurationFunction @@ -357,7 +397,7 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * @param widgetConfigurationFunction Configuration function to run after the widget is created (overrides WidgetAction#_widgetConfigurationFunction) * @return Pointer to created widget */ - virtual QWidget* createWidget(QWidget* parent, const WidgetConfigurationFunction& widgetConfigurationFunction) final; + QWidget* createWidget(QWidget* parent, const WidgetConfigurationFunction& widgetConfigurationFunction); /** * Create collapsed widget @@ -366,7 +406,7 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * @param widgetConfigurationFunction Configuration function to run after the widget is created (overrides WidgetAction#_widgetConfigurationFunction) * @return Pointer to collapsed widget */ - virtual QWidget* createCollapsedWidget(QWidget* parent, std::int32_t widgetFlags = 0) const final; + QWidget* createCollapsedWidget(QWidget* parent, std::int32_t widgetFlags = 0) const; /** * Create collapsed widget @@ -375,7 +415,7 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * @param widgetConfigurationFunction Configuration function to run after the widget is created (overrides WidgetAction#_widgetConfigurationFunction) * @return Pointer to collapsed widget */ - virtual QWidget* createCollapsedWidget(QWidget* parent, std::int32_t widgetFlags, const WidgetConfigurationFunction& widgetConfigurationFunction) const final; + QWidget* createCollapsedWidget(QWidget* parent, std::int32_t widgetFlags, const WidgetConfigurationFunction& widgetConfigurationFunction) const; /** * Create label widget @@ -383,7 +423,7 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * @param widgetFlags Label widget configuration flags * @return Pointer to widget */ - virtual QWidget* createLabelWidget(QWidget* parent, const std::int32_t& widgetFlags = 0x00001) const final; + QWidget* createLabelWidget(QWidget* parent, const std::int32_t& widgetFlags = 0x00001) const; /** * Get the context menu for the action @@ -393,25 +433,25 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable virtual QMenu* getContextMenu(QWidget* parent = nullptr); /** Get the sort index */ - virtual std::int32_t getSortIndex() const final; + std::int32_t getSortIndex() const; /** * Set the sort index * @param sortIndex Sorting index */ - virtual void setSortIndex(const std::int32_t& sortIndex) final; + void setSortIndex(const std::int32_t& sortIndex); /** * Get stretch * @return The stretch factor */ - virtual std::int32_t getStretch() const final; + std::int32_t getStretch() const; /** * Set stretch to \p stretch * @param stretch Stretch factor */ - virtual void setStretch(const std::int32_t& stretch) final; + void setStretch(const std::int32_t& stretch); /** * Get widget configuration function @@ -438,19 +478,19 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * Get force hidden * @return Boolean determining whether the widget action should be forcibly hidden (regardless of the visibility setting in the base QWidgetAction class) */ - virtual bool getForceHidden() const final; + bool getForceHidden() const; /** * Set force hidden to \p forceHidden * @param forceHidden Boolean determining whether the widget action should be forcibly hidden (regardless of the enabled visibility in the base QWidgetAction class) */ - virtual void setForceHidden(bool forceHidden) final; + void setForceHidden(bool forceHidden); /** * Re-implement the isVisible() getter from the base QWidgetAction class to support the force hidden functionality * @return Boolean determining whether the widget action is visible or not */ - virtual bool isVisible() const final; + bool isVisible() const; public: // Disabled @@ -458,19 +498,19 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable * Get force disabled * @return Boolean determining whether the widget action should be forcibly disabled (regardless of the enabled setting in the base QWidgetAction class) */ - virtual bool getForceDisabled() const final; + bool getForceDisabled() const; /** * Set force disabled to \p forceDisabled * @param forceDisabled Boolean determining whether the widget action should be forcibly disabled (regardless of the enabled setting in the base QWidgetAction class) */ - virtual void setForceDisabled(bool forceDisabled) final; + void setForceDisabled(bool forceDisabled); /** * Re-implement the isEnabled() getter from the base QWidgetAction class to support the force disabled functionality * @return Boolean determining whether the widget action is enabled or not */ - virtual bool isEnabled() const final; + bool isEnabled() const; public: // Text @@ -483,52 +523,64 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable public: // Widget flags /** Gets the default widget flags */ - virtual std::int32_t getDefaultWidgetFlags() const final; + std::int32_t getDefaultWidgetFlags() const; /** * Set the widget flags * @param widgetFlags Widget flags */ - virtual void setDefaultWidgetFlags(const std::int32_t& widgetFlags) final; + void setDefaultWidgetFlags(const std::int32_t& widgetFlags); /** * Set a single widget flag on/off * @param widgetFlag Widget flag to set on/off * @param unset Whether to unset the default widget flag */ - virtual void setDefaultWidgetFlag(const std::int32_t& widgetFlag, bool unset = false) final; + void setDefaultWidgetFlag(const std::int32_t& widgetFlag, bool unset = false); public: // Highlighting /** - * Get highlighting - * @return Highlight option + * Get highlight mode + * @return Highlight mode */ - virtual HighlightOption getHighlighting() const final; + HighlightMode getHighlightMode() const; /** * Determine whether the action is in a highlighted state or not * @return Boolean determining whether the action is in a highlighted state or not */ - virtual bool isHighlighted() const final; + bool isHighlightVisible() const; /** - * Set highlighting to \p highlighting - * @param highlighting Highlighting state + * Set highlight mode to \p highlightMode + * @param highlightMode Highlight mode */ - virtual void setHighlighting(const HighlightOption& highlighting) final; + void setHighlightMode(const HighlightMode& highlightMode); /** - * Set highlighted to \p highlighted - * @param highlighted Boolean determining whether the action is in a normal highlighted state or not + * Set highlight visibility to \p highlightVisible + * @param highlightVisible Boolean determining whether the action is in a highlighted state or not */ - virtual void setHighlighted(bool highlighted) final; + void setHighlightVisible(bool highlightVisible); /** Convenience method to highlight the action */ - virtual void highlight() final; + void highlight(); /** Convenience method to un-highlight the action */ - virtual void unHighlight() final; + void unHighlight(); + + /** + * Get highlight description + * @return Highlight description + */ + QString getHighlightDescription() const; + + /** + * Set highlight description to \p highlightDescription + * @param highlightDescription Highlight description + */ + void setHighlightDescription(const QString& highlightDescription); public: // Scope @@ -938,10 +990,22 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable void forceDisabledChanged(bool forceDisabled); /** - * Signals that the highlighting options changed to \p highlightOption - * @param highlightOption Current highlight option + * Signals that the highlight visibility changed to \p highlightVisible + * @param highlightVisible Boolean determining whether the highlight is visible + */ + void highlightVisibilityChanged(bool highlightVisible); + + /** + * Signals that the highlight mode changed to \p highlightMode + * @param highlightMode Current highlight mode + */ + void highlightModeChanged(const HighlightMode& highlightMode); + + /** + * Signals that the highlight description changed to \p highlightDescription + * @param highlightDescription Current highlight description */ - void highlightingChanged(const HighlightOption& highlightOption); + void highlightDescriptionChanged(const QString& highlightDescription); /** * Signals that the published state changed @@ -1022,7 +1086,9 @@ class CORE_EXPORT WidgetAction : public QWidgetAction, public util::Serializable QPointer _publicAction; /** Public action to which this action is connected (nullptr if not connected) */ QVector _connectedActions; /** Pointers to widget actions that are connected to this action */ QString _settingsPrefix; /** If non-empty, the prefix is used to save the contents of the widget action to settings with the Qt settings API */ - HighlightOption _highlighting; /** Highlighting state */ + bool _highlightVisible; /** Whether the action is highlighted in actions */ + HighlightMode _highlightMode; /** Highlight mode */ + QString _highlightDescription; /** Highlight description */ QSize _popupSizeHint; /** Size hint of the popup */ QSize _overrideSizeHint; /** Override size hint (use with caution) */ std::int32_t _configuration; /** Configuration flags */ diff --git a/ManiVault/src/actions/WidgetActionContextMenu.cpp b/ManiVault/src/actions/WidgetActionContextMenu.cpp index 5294fccc0..16b627274 100644 --- a/ManiVault/src/actions/WidgetActionContextMenu.cpp +++ b/ManiVault/src/actions/WidgetActionContextMenu.cpp @@ -86,7 +86,7 @@ WidgetActionContextMenu::WidgetActionContextMenu(QWidget* parent, WidgetActions actionsFilterModel.setSourceModel(&mv::actions().getActionsListModel()); actionsFilterModel.getScopeFilterAction().setSelectedOptions({ "Public" }); - actionsFilterModel.getTypeFilterAction().setString(firstAction->getTypeString()); + actionsFilterModel.getTypeFilterAction().setStrings({ firstAction->getTypeString() }); const auto numberOfRows = actionsFilterModel.rowCount(); diff --git a/ManiVault/src/actions/WidgetActionHighlightWidget.cpp b/ManiVault/src/actions/WidgetActionHighlightWidget.cpp index 4977f7bdb..ba6cb8af5 100644 --- a/ManiVault/src/actions/WidgetActionHighlightWidget.cpp +++ b/ManiVault/src/actions/WidgetActionHighlightWidget.cpp @@ -15,6 +15,12 @@ WidgetActionHighlightWidget::WidgetActionHighlightWidget(QWidget* parent, Widget setStyleSheet(QString("background-color: %1;").arg(palette().highlight().color().name())); setAttribute(Qt::WA_TransparentForMouseEvents); + + auto layout = new QVBoxLayout(); + + layout->addWidget(&_descriptionLabel); + + setLayout(layout); } WidgetAction* WidgetActionHighlightWidget::getAction() @@ -24,8 +30,11 @@ WidgetAction* WidgetActionHighlightWidget::getAction() void WidgetActionHighlightWidget::setAction(WidgetAction* action) { - if (_action != nullptr) - disconnect(_action, &WidgetAction::highlightingChanged, this, nullptr); + if (_action != nullptr) { + disconnect(_action, &WidgetAction::highlightVisibilityChanged, this, nullptr); + disconnect(_action, &WidgetAction::highlightModeChanged, this, nullptr); + disconnect(_action, &WidgetAction::highlightDescriptionChanged, this, nullptr); + } _action = action; @@ -35,39 +44,73 @@ void WidgetActionHighlightWidget::setAction(WidgetAction* action) if (_action->isPublic()) return; - connect(_action, &WidgetAction::highlightingChanged, this, &WidgetActionHighlightWidget::highlightingChanged); + connect(_action, &WidgetAction::highlightVisibilityChanged, this, &WidgetActionHighlightWidget::highlightVisibilityChanged); + connect(_action, &WidgetAction::highlightModeChanged, this, &WidgetActionHighlightWidget::highlightModeChanged); + connect(_action, &WidgetAction::highlightDescriptionChanged, this, &WidgetActionHighlightWidget::highlightDescriptionChanged); - highlightingChanged(_action->getHighlighting()); + highlightModeChanged(_action->getHighlightMode()); } -void WidgetActionHighlightWidget::highlightingChanged(const WidgetAction::HighlightOption& highlighting) +QString WidgetActionHighlightWidget::getDescription() const { - switch (highlighting) - { - case WidgetAction::HighlightOption::None: - { - _widgetFader.setOpacity(0.0f, 500); + return _description; +} - break; - } +void WidgetActionHighlightWidget::setHighlightDescription(const QString& description) +{ + if (description == _description) + return; - case WidgetAction::HighlightOption::Moderate: - { - _widgetFader.setOpacity(0.25f, 200); - - break; - } + _description = description; + + _descriptionLabel.setText(_description); +} + +void WidgetActionHighlightWidget::highlightVisibilityChanged(bool highlightVisible) +{ + updateHighlight(); +} - case WidgetAction::HighlightOption::Strong: +void WidgetActionHighlightWidget::highlightModeChanged(const WidgetAction::HighlightMode& highlightMode) +{ + updateHighlight(); +} + +void WidgetActionHighlightWidget::highlightDescriptionChanged(const QString& highlightDescription) +{ + _descriptionLabel.setText(highlightDescription); +} + +void WidgetActionHighlightWidget::updateHighlight() +{ + if (_action->isHighlightVisible()) { + switch (_action->getHighlightMode()) { - _widgetFader.setOpacity(0.6f, 200); + case WidgetAction::HighlightMode::Light: + { + _widgetFader.setOpacity(0.2f, 500); - break; - } + break; + } + + case WidgetAction::HighlightMode::Moderate: + { + _widgetFader.setOpacity(0.5f, 200); + + break; + } + + case WidgetAction::HighlightMode::Strong: + { + _widgetFader.setOpacity(0.9f, 200); - default: - break; + break; + } + } + } + else { + _widgetFader.setOpacity(0.0f, 500); } } -} \ No newline at end of file +} diff --git a/ManiVault/src/actions/WidgetActionHighlightWidget.h b/ManiVault/src/actions/WidgetActionHighlightWidget.h index 2148a4559..893aa4b7d 100644 --- a/ManiVault/src/actions/WidgetActionHighlightWidget.h +++ b/ManiVault/src/actions/WidgetActionHighlightWidget.h @@ -9,6 +9,8 @@ #include "WidgetAction.h" +#include + namespace mv::gui { /** @@ -43,17 +45,46 @@ class CORE_EXPORT WidgetActionHighlightWidget final : public OverlayWidget */ void setAction(WidgetAction* action); + /** + * Get the highlight description + * @return Highlight description string + */ + QString getDescription() const ; + + /** + * Set the description string to \p description + * @param description Highlight description string + */ + void setHighlightDescription(const QString& description); + private: /** - * Invoked when the action highlighting state changes (update the visual representation of the highlight) - * @param highlighting Action highlighting state + * Invoked when the action highlight visibility changes (update the visual representation of the highlight) + * @param highlightVisible Action highlighting visibility */ - void highlightingChanged(const WidgetAction::HighlightOption& highlighting); + void highlightVisibilityChanged(bool highlightVisible); + + /** + * Invoked when the action highlight mode changes (update the visual representation of the highlight) + * @param highlightMode Action highlight mode + */ + void highlightModeChanged(const WidgetAction::HighlightMode& highlightMode); + + /** + * Invoked when the action highlight description changes (update the text of the highlight label) + * @param highlightDescription Action highlight description + */ + void highlightDescriptionChanged(const QString& highlightDescription); + + /** Updates the highlight representation */ + void updateHighlight(); private: - WidgetAction* _action; /** Pointer to widget action to highlight */ - mv::util::WidgetFader _widgetFader; /** Widget fader for animating the widget opacity */ + WidgetAction* _action; /** Pointer to widget action to highlight */ + mv::util::WidgetFader _widgetFader; /** Widget fader for animating the widget opacity */ + QString _description; /** Description related to the highlight */ + QLabel _descriptionLabel; /** Description label */ }; } \ No newline at end of file diff --git a/ManiVault/src/actions/WidgetActionMimeData.cpp b/ManiVault/src/actions/WidgetActionMimeData.cpp index 8e8c8ea80..4d04a516a 100644 --- a/ManiVault/src/actions/WidgetActionMimeData.cpp +++ b/ManiVault/src/actions/WidgetActionMimeData.cpp @@ -4,23 +4,39 @@ #include "WidgetActionMimeData.h" +#include + namespace mv::gui { WidgetActionMimeData::WidgetActionMimeData(WidgetAction* action) : - QMimeData(), - _action(action), - _highlightActions() + _action(action) { - ActionsListModel actionsListModel; /** Actions list model */ - ActionsFilterModel actionsFilterModel; /** Filtered actions model */ + ActionsFilterModel actionsFilterModel; - actionsFilterModel.setSourceModel(&actionsListModel); + actionsFilterModel.setSourceModel(& mv::actions().getActionsListModel()); actionsFilterModel.getScopeFilterAction().setSelectedOptions({ "Private" }); - actionsFilterModel.getTypeFilterAction().setString(getAction()->getTypeString()); + + QStringList actionTypes { getAction()->getTypeString() }; + + for (const auto& child : getAction()->getChildren(true)) + actionTypes << child->getTypeString(); + + actionTypes.removeDuplicates(); + + qDebug() << actionTypes; + + actionsFilterModel.getTypeFilterAction().setStrings(actionTypes); for (int rowIndex = 0; rowIndex < actionsFilterModel.rowCount(); ++rowIndex) { auto candidateAction = actionsFilterModel.getAction(rowIndex); + const auto connections = AbstractActionsManager::getCandidateConnectionsForDescendants(getAction(), candidateAction); + + //qDebug() << candidateAction->text() << connections.size(); + + //if (connections.empty()) + // continue; + if (candidateAction == getAction()) continue; @@ -30,12 +46,23 @@ WidgetActionMimeData::WidgetActionMimeData(WidgetAction* action) : if (!candidateAction->mayConnect(WidgetAction::Gui)) continue; - if (candidateAction->isHighlighted()) + if (candidateAction->isHighlightVisible()) candidateAction->unHighlight(); - if (candidateAction->isConnected() && (candidateAction->getPublicAction() == getAction())) + if (getAction()->getTypeString() != candidateAction->getTypeString()) { + if (connections.empty()) + continue; + + candidateAction->setHighlightMode(WidgetAction::HighlightMode::Light); + candidateAction->setHighlightDescription(QString("%1 indirect connection(1)").arg(QString::number(connections.size()))); + } else { + candidateAction->setHighlightMode(WidgetAction::HighlightMode::Moderate); + } + + if (candidateAction->isConnected() && (candidateAction->getPublicAction() == getAction())) continue; + //candidateAction->highlight(); _highlightActions << candidateAction; } @@ -56,4 +83,4 @@ QStringList WidgetActionMimeData::formats() const return { format() }; } -} \ No newline at end of file +} diff --git a/ManiVault/src/actions/WidgetActionViewWidget.cpp b/ManiVault/src/actions/WidgetActionViewWidget.cpp index 735790819..300587f10 100644 --- a/ManiVault/src/actions/WidgetActionViewWidget.cpp +++ b/ManiVault/src/actions/WidgetActionViewWidget.cpp @@ -27,7 +27,7 @@ WidgetActionViewWidget::WidgetActionViewWidget(QWidget* parent, WidgetAction* ac _widgetFlags(widgetFlags), _highlightWidget(new WidgetActionHighlightWidget(this, action)), _badgeOverlayWidget(nullptr), - _cachedHighlighting(0) + _cachedHighlightMode(0) { setAcceptDrops(true); } @@ -130,16 +130,16 @@ void WidgetActionViewWidget::dragEnterEvent(QDragEnterEvent* dragEnterEvent) if (numberOfCandidateConnections == 0) return; - _cachedHighlighting = static_cast(getAction()->getHighlighting()); + _cachedHighlightMode = static_cast(getAction()->getHighlightMode()); - getAction()->setHighlighting(WidgetAction::HighlightOption::Strong); + getAction()->setHighlightMode(WidgetAction::HighlightMode::Strong); dragEnterEvent->acceptProposedAction(); } void WidgetActionViewWidget::dragLeaveEvent(QDragLeaveEvent* dragLeaveEvent) { - getAction()->setHighlighting(static_cast(_cachedHighlighting)); + getAction()->setHighlightMode(static_cast(_cachedHighlightMode)); } void WidgetActionViewWidget::dropEvent(QDropEvent* dropEvent) diff --git a/ManiVault/src/actions/WidgetActionViewWidget.h b/ManiVault/src/actions/WidgetActionViewWidget.h index f64e8f70e..42e978314 100644 --- a/ManiVault/src/actions/WidgetActionViewWidget.h +++ b/ManiVault/src/actions/WidgetActionViewWidget.h @@ -101,7 +101,7 @@ class CORE_EXPORT WidgetActionViewWidget : public QWidget std::int32_t _widgetFlags; /** Widget creation flags */ WidgetActionHighlightWidget* _highlightWidget; /** Pointer to highlight widget */ std::unique_ptr _badgeOverlayWidget; /** Pointer to badge overlay widget */ - std::int32_t _cachedHighlighting; /** Cached highlighting */ + std::int32_t _cachedHighlightMode; /** Cached highlighting */ }; } diff --git a/ManiVault/src/models/ActionsFilterModel.cpp b/ManiVault/src/models/ActionsFilterModel.cpp index d0e524ecd..0682343d1 100644 --- a/ManiVault/src/models/ActionsFilterModel.cpp +++ b/ManiVault/src/models/ActionsFilterModel.cpp @@ -29,23 +29,23 @@ ActionsFilterModel::ActionsFilterModel(QObject* parent /*= nullptr*/) : { setRecursiveFilteringEnabled(true); - _typeFilterHumanReadableAction.setClearable(true); - _typeFilterHumanReadableAction.setCompleter(&_typeCompleter); + //_typeFilterHumanReadableAction.setClearable(true); + //_typeFilterHumanReadableAction.setCompleter(&_typeCompleter); _scopeFilterAction.setDefaultWidgetFlags(OptionsAction::ComboBox | OptionsAction::Selection); - connect(&_typeFilterAction, &StringAction::stringChanged, this, &ActionsFilterModel::invalidate); - connect(&_typeFilterHumanReadableAction, &StringAction::stringChanged, this, &ActionsFilterModel::invalidate); + connect(&_typeFilterAction, &StringsAction::stringsChanged, this, &ActionsFilterModel::invalidate); + connect(&_typeFilterHumanReadableAction, &StringsAction::stringsChanged, this, &ActionsFilterModel::invalidate); connect(&_scopeFilterAction, &OptionsAction::selectedOptionsChanged, this, &ActionsFilterModel::invalidate); connect(&_publicRootOnlyAction, &ToggleAction::toggled, this, &ActionsFilterModel::invalidate); - const auto updateTypeFilterActionCompleter = [this]() -> void { - _typeFilterHumanReadableAction.getCompleter()->setModel(new QStringListModel(actions().getActionTypesHumanFriendly())); - }; + //const auto updateTypeFilterActionCompleter = [this]() -> void { + // _typeFilterHumanReadableAction.getCompleter()->setModel(new QStringListModel(actions().getActionTypesHumanFriendly())); + //}; - updateTypeFilterActionCompleter(); + //updateTypeFilterActionCompleter(); - connect(&actions(), &AbstractActionsManager::actionTypesHumanFriendlyChanged, this, updateTypeFilterActionCompleter); + //connect(&actions(), &AbstractActionsManager::actionTypesHumanFriendlyChanged, this, updateTypeFilterActionCompleter); //_filterInternalUseAction.setDefaultWidgetFlags(OptionsAction::ComboBox | OptionsAction::Selection); //_filterForceHiddenAction.setDefaultWidgetFlags(OptionsAction::ComboBox | OptionsAction::Selection); @@ -85,21 +85,21 @@ bool ActionsFilterModel::filterAcceptsRow(int row, const QModelIndex& parent) co return false; } - const auto typeFilter = _typeFilterAction.getString(); + const auto typeFilter = _typeFilterAction.getStrings(); if (!typeFilter.isEmpty()) { - const auto type = getSourceData(index, AbstractActionsModel::Column::Type, Qt::EditRole).toString(); + const auto actionType = getSourceData(index, AbstractActionsModel::Column::Type, Qt::EditRole).toString(); - if (type != typeFilter) + if (!typeFilter.contains(actionType)) return false; } - const auto typeFilterHumanReadable = _typeFilterHumanReadableAction.getString(); + const auto typeFilterHumanReadable = _typeFilterHumanReadableAction.getStrings(); if (!typeFilterHumanReadable.isEmpty()) { - const auto type = getSourceData(index, AbstractActionsModel::Column::Type, Qt::DisplayRole).toString(); + const auto actionTypeHumanReadable = getSourceData(index, AbstractActionsModel::Column::Type, Qt::DisplayRole).toString(); - if (type != typeFilter) + if (!typeFilterHumanReadable.contains(actionTypeHumanReadable)) return false; } diff --git a/ManiVault/src/models/ActionsFilterModel.h b/ManiVault/src/models/ActionsFilterModel.h index cb60d0024..913528e52 100644 --- a/ManiVault/src/models/ActionsFilterModel.h +++ b/ManiVault/src/models/ActionsFilterModel.h @@ -69,8 +69,8 @@ class CORE_EXPORT ActionsFilterModel final : public SortFilterProxyModel public: // Action getters - gui::StringAction& getTypeFilterAction() { return _typeFilterAction; } - gui::StringAction& getTypeFilterHumanReadableAction() { return _typeFilterHumanReadableAction; } + gui::StringsAction& getTypeFilterAction() { return _typeFilterAction; } + gui::StringsAction& getTypeFilterHumanReadableAction() { return _typeFilterHumanReadableAction; } gui::OptionsAction& getScopeFilterAction() { return _scopeFilterAction; } gui::OptionsAction& getFilterForceHiddenAction() { return _filterForceHiddenAction; } gui::OptionsAction& getFilterForceDisabledAction() { return _filterForceDisabledAction; } @@ -81,8 +81,8 @@ class CORE_EXPORT ActionsFilterModel final : public SortFilterProxyModel gui::TriggerAction& getRemoveFiltersAction() { return _removeFiltersAction; } private: - gui::StringAction _typeFilterAction; /** Action for filtering by action type */ - gui::StringAction _typeFilterHumanReadableAction; /** Action for filtering by human-readable action type */ + gui::StringsAction _typeFilterAction; /** Action for filtering by action type */ + gui::StringsAction _typeFilterHumanReadableAction; /** Action for filtering by human-readable action type */ QCompleter _typeCompleter; /** Completer for human-readable action type filter */ gui::OptionsAction _scopeFilterAction; /** Action for filtering based on action scope */ gui::OptionsAction _filterForceHiddenAction; /** Filter actions based on their force hidden state */ diff --git a/ManiVault/src/widgets/ActionsWidget.cpp b/ManiVault/src/widgets/ActionsWidget.cpp index fd6a5c6dc..4213dcdee 100644 --- a/ManiVault/src/widgets/ActionsWidget.cpp +++ b/ManiVault/src/widgets/ActionsWidget.cpp @@ -247,7 +247,7 @@ void ActionsWidget::highlightActions(const QModelIndexList& selectedRows, bool h void ActionsWidget::highlightActions(const PersistentModelIndices& highlightModelIndices, bool highlight) { for (const auto& highlightedAction : _highlightedActions) - highlightedAction->setHighlighted(false); + highlightedAction->setHighlightVisible(false); _highlightedActions.clear(); @@ -259,13 +259,13 @@ void ActionsWidget::highlightActions(const PersistentModelIndices& highlightMode _highlightedActions << action; - action->setHighlighted(highlight); + action->setHighlightVisible(highlight); if (!action->isPublic()) continue; for (auto connectedAction : action->getConnectedActions()) { - connectedAction->setHighlighted(highlight); + connectedAction->setHighlightVisible(highlight); _highlightedActions << connectedAction; }