diff --git a/widgets/buttonoverlay.cpp b/widgets/buttonoverlay.cpp index fecd571..ce2217d 100644 --- a/widgets/buttonoverlay.cpp +++ b/widgets/buttonoverlay.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -227,17 +228,52 @@ void ButtonOverlay::insertCustomButton(int index, QWidget *button) } /*! - * \brief Removes the specified custom \a button. + * \brief Removes the specified custom \a button; does nothing if \a button has not been added. * * The ownership of widget remains the same as when it was added. - * - * \remarks This function enforces the "custom approach" mentioned in the class documentation - * and should therefore be avoided. */ void ButtonOverlay::removeCustomButton(QWidget *button) { - fallbackToUsingCustomLayout(); - m_buttonLayout->removeWidget(button); + if (isUsingCustomLayout()) { + m_buttonLayout->removeWidget(button); + } +} + +/*! + * \brief Adds a custom \a action. + */ +void ButtonOverlay::addCustomAction(QAction *action) +{ + if (auto *const le = lineEditForWidget()) { + le->addAction(action, QLineEdit::TrailingPosition); + } else { + addCustomButton(IconButton::fromAction(action, reinterpret_cast(this))); + } +} + +/*! + * \brief Inserts a custom \a action at the specified \a index. + */ +void ButtonOverlay::insertCustomAction(int index, QAction *action) +{ + if (auto *const le = lineEditForWidget()) { + const auto actions = le->actions(); + le->insertAction(index < actions.size() ? actions[index] : nullptr, action); + } else { + insertCustomButton(index, IconButton::fromAction(action, reinterpret_cast(this))); + } +} + +/*! + * \brief Removes the specified custom \a action; does nothing if \a action has not been added. + */ +void ButtonOverlay::removeCustomAction(QAction *action) +{ + if (auto *const le = lineEditForWidget()) { + le->removeAction(action); + } else { + removeCustomButton(IconButton::fromAction(action, reinterpret_cast(this))); + } } /*! @@ -284,19 +320,23 @@ void ButtonOverlay::fallbackToUsingCustomLayout() } // disable QLineEdit's clear button and actions; save configuration - const auto clearButtonEnabled = isClearButtonEnabled(); - if (clearButtonEnabled) { - setClearButtonEnabled(false); - } - auto *const iconAction = static_cast(m_infoButtonOrAction); + auto clearButtonEnabled = false; + auto *iconAction = static_cast(m_infoButtonOrAction); QPixmap infoPixmap; QString infoText; - if (iconAction) { - const auto icon = iconAction->icon(); - const auto sizes = icon.availableSizes(); - infoPixmap = icon.pixmap(sizes.empty() ? QSize(16, 16) : sizes.front()); - infoText = iconAction->toolTip(); - disableInfoButton(); + QList actions; + if (auto const *le = lineEditForWidget()) { + if ((clearButtonEnabled = le->isClearButtonEnabled())) { + setClearButtonEnabled(false); + } + if ((iconAction = static_cast(m_infoButtonOrAction))) { + const auto icon = iconAction->icon(); + const auto sizes = icon.availableSizes(); + infoPixmap = icon.pixmap(sizes.empty() ? QSize(16, 16) : sizes.front()); + infoText = iconAction->toolTip(); + disableInfoButton(); + } + actions = le->actions(); } // initialize custom layout @@ -313,6 +353,9 @@ void ButtonOverlay::fallbackToUsingCustomLayout() if (iconAction) { enableInfoButton(infoPixmap, infoText); } + for (auto *const action : actions) { + addCustomAction(action); + } } /*! diff --git a/widgets/buttonoverlay.h b/widgets/buttonoverlay.h index 08cb54c..49f7aa6 100644 --- a/widgets/buttonoverlay.h +++ b/widgets/buttonoverlay.h @@ -5,6 +5,7 @@ #include +QT_FORWARD_DECLARE_CLASS(QAction) QT_FORWARD_DECLARE_CLASS(QWidget) QT_FORWARD_DECLARE_CLASS(QHBoxLayout) QT_FORWARD_DECLARE_CLASS(QString) @@ -43,6 +44,9 @@ public: void addCustomButton(QWidget *button); void insertCustomButton(int index, QWidget *button); void removeCustomButton(QWidget *button); + void addCustomAction(QAction *action); + void insertCustomAction(int index, QAction *action); + void removeCustomAction(QAction *action); virtual bool isCleared() const; protected: diff --git a/widgets/iconbutton.cpp b/widgets/iconbutton.cpp index 3a983dc..54cd043 100644 --- a/widgets/iconbutton.cpp +++ b/widgets/iconbutton.cpp @@ -1,10 +1,14 @@ #include "./iconbutton.h" +#include + #include #include #include #include +using namespace CppUtilities; + namespace QtUtilities { /*! @@ -29,6 +33,46 @@ IconButton::~IconButton() { } +/*! + * \brief Creates an IconButton for the specified \a action. + * \remarks Calling this function on the same action twice with the same \a id yields the + * same instance. + */ +IconButton *IconButton::fromAction(QAction *action, std::uintptr_t id) +{ + const auto propertyName = argsToString("iconButton-", id); + const auto existingIconButton = action->property(propertyName.data()); + if (!existingIconButton.isNull()) { + return existingIconButton.value(); + } + auto *const iconButton = new IconButton; + iconButton->assignDataFromAction(action); + action->setProperty(propertyName.data(), QVariant::fromValue(iconButton)); + connect(action, &QAction::changed, iconButton, &IconButton::assignDataFromActionChangedSignal); + connect(iconButton, &IconButton::clicked, action, &QAction::trigger); + return iconButton; +} + +/*! + * \brief Internally called to assign data from a QAction to the icon button. + */ +void IconButton::assignDataFromActionChangedSignal() +{ + assignDataFromAction(qobject_cast(QObject::sender())); +} + +/*! + * \brief Internally called to assign data from a QAction to the icon button. + */ +void IconButton::assignDataFromAction(const QAction *action) +{ + auto const icon = action->icon(); + const auto sizes = icon.availableSizes(); + const auto text = action->text(); + setPixmap(icon.pixmap(sizes.empty() ? QSize(16, 16) : sizes.front())); + setToolTip(text.isEmpty() ? action->toolTip() : text); +} + QSize IconButton::sizeHint() const { #if QT_VERSION >= 0x050100 @@ -77,4 +121,5 @@ void IconButton::keyReleaseEvent(QKeyEvent *event) QAbstractButton::keyReleaseEvent(event); event->accept(); } + } // namespace QtUtilities diff --git a/widgets/iconbutton.h b/widgets/iconbutton.h index fbb04c9..68ceb5a 100644 --- a/widgets/iconbutton.h +++ b/widgets/iconbutton.h @@ -4,8 +4,11 @@ #include "../global.h" #include +#include #include +#include + namespace QtUtilities { class QT_UTILITIES_EXPORT IconButton : public QAbstractButton { @@ -16,6 +19,7 @@ public: explicit IconButton(QWidget *parent = nullptr); ~IconButton() override; + static IconButton *fromAction(QAction *action, std::uintptr_t id = 0); const QPixmap &pixmap() const; void setPixmap(const QPixmap &pixmap); QSize sizeHint() const override; @@ -25,6 +29,10 @@ protected: void keyPressEvent(QKeyEvent *event) override; void keyReleaseEvent(QKeyEvent *event) override; +private Q_SLOTS: + void assignDataFromActionChangedSignal(); + void assignDataFromAction(const QAction *action); + private: QPixmap m_pixmap; };