Improve button overlay so buttons will not be shown over e.g. spin box buttons
* Unify/streamline code * Use Qt::SC_ComboBoxEditField/Qt::SC_SpinBoxEditField to determine the edit area for better compatibility accorss various styles
This commit is contained in:
parent
9b7ad3375c
commit
7db2fd02fc
|
@ -10,7 +10,7 @@ set(META_APP_DESCRIPTION
|
|||
"Common Qt related C++ classes and routines used by my applications such as dialogs, widgets and models")
|
||||
set(META_VERSION_MAJOR 6)
|
||||
set(META_VERSION_MINOR 0)
|
||||
set(META_VERSION_PATCH 6)
|
||||
set(META_VERSION_PATCH 7)
|
||||
set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH})
|
||||
|
||||
project(${META_PROJECT_NAME})
|
||||
|
|
|
@ -37,15 +37,7 @@ ButtonOverlay::ButtonOverlay(QWidget *widget)
|
|||
, 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);
|
||||
buttonLayout()->setAlignment(Qt::AlignCenter | Qt::AlignRight);
|
||||
widget->setLayout(m_buttonLayout);
|
||||
}
|
||||
|
||||
|
@ -187,4 +179,17 @@ void ButtonOverlay::showInfo()
|
|||
QToolTip::showText(QCursor::pos(), m_infoButton->toolTip(), m_infoButton);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the contents margins of the button layout so the overlay buttons will only be shown over the \a editFieldRect and
|
||||
* not interfere with e.g. spin box buttons.
|
||||
*/
|
||||
void ButtonOverlay::setContentsMarginsFromEditFieldRectAndFrameWidth(const QRect &editFieldRect, int frameWidth, int padding)
|
||||
{
|
||||
const auto margins = m_widget->contentsMargins();
|
||||
const auto buttonWidth = m_widget->width() - editFieldRect.width();
|
||||
buttonLayout()->setContentsMargins(margins.left() + frameWidth + padding, margins.top() + frameWidth,
|
||||
margins.right() + frameWidth + padding + buttonWidth, margins.bottom() + frameWidth);
|
||||
}
|
||||
|
||||
} // namespace QtUtilities
|
||||
|
|
|
@ -9,12 +9,24 @@ QT_FORWARD_DECLARE_CLASS(QWidget)
|
|||
QT_FORWARD_DECLARE_CLASS(QHBoxLayout)
|
||||
QT_FORWARD_DECLARE_CLASS(QString)
|
||||
QT_FORWARD_DECLARE_CLASS(QPixmap)
|
||||
QT_FORWARD_DECLARE_CLASS(QMargins)
|
||||
QT_FORWARD_DECLARE_CLASS(QRect)
|
||||
|
||||
namespace QtUtilities {
|
||||
|
||||
class IconButton;
|
||||
class ClearComboBox;
|
||||
class ClearSpinBox;
|
||||
class ClearPlainTextEdit;
|
||||
class ClearLineEdit;
|
||||
|
||||
class QT_UTILITIES_EXPORT ButtonOverlay {
|
||||
// allow these derived classes to use private helpers provided by ButtonOverlay
|
||||
friend class ClearComboBox;
|
||||
friend class ClearSpinBox;
|
||||
friend class ClearPlainTextEdit;
|
||||
friend class ClearLineEdit;
|
||||
|
||||
public:
|
||||
explicit ButtonOverlay(QWidget *widget);
|
||||
virtual ~ButtonOverlay();
|
||||
|
@ -36,6 +48,7 @@ protected:
|
|||
|
||||
private:
|
||||
void showInfo();
|
||||
void setContentsMarginsFromEditFieldRectAndFrameWidth(const QRect &editFieldRect, int frameWidth, int padding = 0);
|
||||
|
||||
QWidget *m_widget;
|
||||
QWidget *m_buttonWidget;
|
||||
|
|
|
@ -18,14 +18,11 @@ ClearComboBox::ClearComboBox(QWidget *parent)
|
|||
: QComboBox(parent)
|
||||
, ButtonOverlay(this)
|
||||
{
|
||||
const QMargins margins = contentsMargins();
|
||||
const QStyle *const s = style();
|
||||
QStyleOptionComboBox opt;
|
||||
opt.initFrom(this);
|
||||
const int frameWidth = style()->pixelMetric(QStyle::PM_ComboBoxFrameWidth, &opt, this);
|
||||
const int pad = 2;
|
||||
const int buttonWidth = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxArrow, this).width();
|
||||
buttonLayout()->setContentsMargins(margins.left() + frameWidth + pad, margins.top() + frameWidth,
|
||||
margins.right() + frameWidth + pad + buttonWidth, margins.bottom() + frameWidth);
|
||||
setContentsMarginsFromEditFieldRectAndFrameWidth(
|
||||
s->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this), s->pixelMetric(QStyle::PM_ComboBoxFrameWidth, &opt, this));
|
||||
setClearButtonEnabled(isEditable());
|
||||
connect(this, &ClearComboBox::currentTextChanged, this, &ClearComboBox::handleTextChanged);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "./clearlineedit.h"
|
||||
|
||||
#include <QStyle>
|
||||
#include <QStyleOptionFrame>
|
||||
|
||||
namespace QtUtilities {
|
||||
|
||||
/*!
|
||||
|
@ -14,6 +17,11 @@ ClearLineEdit::ClearLineEdit(QWidget *parent)
|
|||
: QLineEdit(parent)
|
||||
, ButtonOverlay(this)
|
||||
{
|
||||
const QStyle *const s = style();
|
||||
QStyleOptionFrame opt;
|
||||
opt.initFrom(this);
|
||||
setContentsMarginsFromEditFieldRectAndFrameWidth(s->subElementRect(QStyle::SE_LineEditContents, &opt, this),
|
||||
s->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, m_widget), s->pixelMetric(QStyle::PM_LayoutVerticalSpacing, &opt, m_widget));
|
||||
ButtonOverlay::setClearButtonEnabled(true);
|
||||
connect(this, &ClearLineEdit::textChanged, this, &ClearLineEdit::handleTextChanged);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <QHBoxLayout>
|
||||
#include <QScrollBar>
|
||||
#include <QStyle>
|
||||
#include <QStyleOptionFrame>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -21,6 +23,11 @@ ClearPlainTextEdit::ClearPlainTextEdit(QWidget *parent)
|
|||
{
|
||||
// set alignment to show buttons in the bottom right corner
|
||||
ButtonOverlay::buttonLayout()->setAlignment(Qt::AlignBottom | Qt::AlignRight);
|
||||
const QStyle *const s = style();
|
||||
QStyleOptionFrame opt;
|
||||
opt.initFrom(this);
|
||||
setContentsMarginsFromEditFieldRectAndFrameWidth(s->subElementRect(QStyle::SE_FrameContents, &opt, this),
|
||||
s->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, m_widget), s->pixelMetric(QStyle::PM_LayoutVerticalSpacing, &opt, m_widget));
|
||||
ButtonOverlay::setClearButtonEnabled(true);
|
||||
connect(this, &QPlainTextEdit::textChanged, this, &ClearPlainTextEdit::handleTextChanged);
|
||||
// ensure button layout is realigned when scrolling
|
||||
|
|
|
@ -21,14 +21,11 @@ ClearSpinBox::ClearSpinBox(QWidget *parent)
|
|||
, ButtonOverlay(this)
|
||||
, m_minimumHidden(false)
|
||||
{
|
||||
const QMargins margins = contentsMargins();
|
||||
QStyleOptionComboBox opt;
|
||||
const QStyle *const s = style();
|
||||
QStyleOptionSpinBox opt;
|
||||
opt.initFrom(this);
|
||||
const int frameWidth = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth, &opt, this);
|
||||
const int pad = 5;
|
||||
const int buttonWidth = style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxUp, this).width() + 10;
|
||||
buttonLayout()->setContentsMargins(margins.left() + frameWidth + pad, margins.top() + frameWidth,
|
||||
margins.right() + frameWidth + pad + buttonWidth, margins.bottom() + frameWidth);
|
||||
setContentsMarginsFromEditFieldRectAndFrameWidth(
|
||||
s->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxEditField, this), s->pixelMetric(QStyle::PM_SpinBoxFrameWidth, &opt, this));
|
||||
setClearButtonEnabled(true);
|
||||
connect(this, static_cast<void (ClearSpinBox::*)(int)>(&ClearSpinBox::valueChanged), this, &ClearSpinBox::handleValueChanged);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue