#include "./buttonoverlay.h" #include "./iconbutton.h" #include #include #include #include #include #include #include namespace QtUtilities { /*! * \class ButtonOverlay * \brief The ButtonOverlay class is used to display buttons on top of other * widgets. * * The class creates a new layout manager and sets it to the widget which is * specified * when constructing an instance. Thus this widget must not already have a * layout manager. * * The class is used to implement widget customization like ClearLineEidt and * ClearComboBox. */ /*! * \brief Constructs a button overlay for the specified \a widget. * \param widget Specifies the widget to display the buttons on. */ ButtonOverlay::ButtonOverlay(QWidget *widget) : m_widget(widget) , m_buttonWidget(new QWidget(widget)) , m_buttonLayout(new QHBoxLayout(m_buttonWidget)) , m_clearButton(nullptr) , m_infoButton(nullptr) { // setup button widget and layout const QMargins margins = widget->contentsMargins(); QStyleOption opt; opt.initFrom(m_widget); const int frameWidth = widget->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, m_widget); const int pad = 2; m_buttonLayout->setContentsMargins( margins.left() + frameWidth + pad, margins.top() + frameWidth, margins.right() + frameWidth + pad, margins.bottom() + frameWidth); m_buttonLayout->setAlignment(Qt::AlignCenter | Qt::AlignRight); widget->setLayout(m_buttonLayout); } /*! * \brief Destroys the button overlay. */ ButtonOverlay::~ButtonOverlay() { } /*! * \brief Sets whether the clear button is enabled. */ void ButtonOverlay::setClearButtonEnabled(bool enabled) { if (isClearButtonEnabled() && !enabled) { // disable clear button m_buttonLayout->removeWidget(m_clearButton); delete m_clearButton; m_clearButton = nullptr; } else if (!isClearButtonEnabled() && enabled) { // enable clear button m_clearButton = new IconButton; m_clearButton->setHidden(isCleared()); m_clearButton->setPixmap(QIcon::fromTheme(QStringLiteral("edit-clear")).pixmap(16)); m_clearButton->setGeometry(0, 0, 16, 16); m_clearButton->setToolTip(QObject::tr("Clear")); QObject::connect(m_clearButton, &IconButton::clicked, std::bind(&ButtonOverlay::handleClearButtonClicked, this)); m_buttonLayout->addWidget(m_clearButton); } } /*! * \brief Shows an info button with the specified \a pixmap and \a infoText. * * If there is already an info button enabled, it gets replaced with the new * button. * * \sa ButtonOverlay::disableInfoButton() */ void ButtonOverlay::enableInfoButton(const QPixmap &pixmap, const QString &infoText) { if (!m_infoButton) { m_infoButton = new IconButton; m_infoButton->setGeometry(0, 0, 16, 16); QObject::connect(m_infoButton, &IconButton::clicked, std::bind(&ButtonOverlay::showInfo, this)); if (m_clearButton) { m_buttonLayout->insertWidget(m_buttonLayout->count() - 2, m_infoButton); } else { m_buttonLayout->addWidget(m_infoButton); } } m_infoButton->setPixmap(pixmap); m_infoButton->setToolTip(infoText); } /*! * \brief Hides an info button if one is shown. * \sa ButtonOverlay::enableInfoButton() */ void ButtonOverlay::disableInfoButton() { if (m_infoButton) { m_buttonLayout->removeWidget(m_infoButton); delete m_infoButton; m_infoButton = nullptr; } } /*! * \brief Adds a custom \a button. * * The button overlay takes ownership over the specified \a button. */ void ButtonOverlay::addCustomButton(QWidget *button) { m_buttonLayout->addWidget(button); } /*! * \brief Inserts a custom \a button at the specified \a index. * * The button overlay takes ownership over the specified \a button. */ void ButtonOverlay::insertCustomButton(int index, QWidget *button) { m_buttonLayout->insertWidget(index, button); } /*! * \brief Removes the specified custom \a button. * * The ownership of widget remains the same as when it was added. */ void ButtonOverlay::removeCustomButton(QWidget *button) { m_buttonLayout->removeWidget(button); } /*! * \brief Updates the visibility of the clear button. * * This method is meant to be called when subclassing. */ void ButtonOverlay::updateClearButtonVisibility(bool visible) { if (m_clearButton) { m_clearButton->setVisible(visible); } } /*! * \brief Clears the related widget. * * This method is meant to be implemented when subclassing. */ void ButtonOverlay::handleClearButtonClicked() { } /*! * \brief Returns whether the related widget is cleared. * * This method is meant to be implemented when subclassing. */ bool ButtonOverlay::isCleared() const { return false; } /*! * \brief Shows the info text using a tool tip. * * This method is called when the info button is clicked. */ void ButtonOverlay::showInfo() { if (m_infoButton) { QToolTip::showText(QCursor::pos(), m_infoButton->toolTip(), m_infoButton); } } } // namespace QtUtilities