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")
|
"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_MAJOR 6)
|
||||||
set(META_VERSION_MINOR 0)
|
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})
|
set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH})
|
||||||
|
|
||||||
project(${META_PROJECT_NAME})
|
project(${META_PROJECT_NAME})
|
||||||
|
|
|
@ -37,15 +37,7 @@ ButtonOverlay::ButtonOverlay(QWidget *widget)
|
||||||
, m_clearButton(nullptr)
|
, m_clearButton(nullptr)
|
||||||
, m_infoButton(nullptr)
|
, m_infoButton(nullptr)
|
||||||
{
|
{
|
||||||
// setup button widget and layout
|
buttonLayout()->setAlignment(Qt::AlignCenter | Qt::AlignRight);
|
||||||
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);
|
widget->setLayout(m_buttonLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,4 +179,17 @@ void ButtonOverlay::showInfo()
|
||||||
QToolTip::showText(QCursor::pos(), m_infoButton->toolTip(), m_infoButton);
|
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
|
} // namespace QtUtilities
|
||||||
|
|
|
@ -9,12 +9,24 @@ QT_FORWARD_DECLARE_CLASS(QWidget)
|
||||||
QT_FORWARD_DECLARE_CLASS(QHBoxLayout)
|
QT_FORWARD_DECLARE_CLASS(QHBoxLayout)
|
||||||
QT_FORWARD_DECLARE_CLASS(QString)
|
QT_FORWARD_DECLARE_CLASS(QString)
|
||||||
QT_FORWARD_DECLARE_CLASS(QPixmap)
|
QT_FORWARD_DECLARE_CLASS(QPixmap)
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QMargins)
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QRect)
|
||||||
|
|
||||||
namespace QtUtilities {
|
namespace QtUtilities {
|
||||||
|
|
||||||
class IconButton;
|
class IconButton;
|
||||||
|
class ClearComboBox;
|
||||||
|
class ClearSpinBox;
|
||||||
|
class ClearPlainTextEdit;
|
||||||
|
class ClearLineEdit;
|
||||||
|
|
||||||
class QT_UTILITIES_EXPORT ButtonOverlay {
|
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:
|
public:
|
||||||
explicit ButtonOverlay(QWidget *widget);
|
explicit ButtonOverlay(QWidget *widget);
|
||||||
virtual ~ButtonOverlay();
|
virtual ~ButtonOverlay();
|
||||||
|
@ -36,6 +48,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void showInfo();
|
void showInfo();
|
||||||
|
void setContentsMarginsFromEditFieldRectAndFrameWidth(const QRect &editFieldRect, int frameWidth, int padding = 0);
|
||||||
|
|
||||||
QWidget *m_widget;
|
QWidget *m_widget;
|
||||||
QWidget *m_buttonWidget;
|
QWidget *m_buttonWidget;
|
||||||
|
|
|
@ -18,14 +18,11 @@ ClearComboBox::ClearComboBox(QWidget *parent)
|
||||||
: QComboBox(parent)
|
: QComboBox(parent)
|
||||||
, ButtonOverlay(this)
|
, ButtonOverlay(this)
|
||||||
{
|
{
|
||||||
const QMargins margins = contentsMargins();
|
const QStyle *const s = style();
|
||||||
QStyleOptionComboBox opt;
|
QStyleOptionComboBox opt;
|
||||||
opt.initFrom(this);
|
opt.initFrom(this);
|
||||||
const int frameWidth = style()->pixelMetric(QStyle::PM_ComboBoxFrameWidth, &opt, this);
|
setContentsMarginsFromEditFieldRectAndFrameWidth(
|
||||||
const int pad = 2;
|
s->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this), s->pixelMetric(QStyle::PM_ComboBoxFrameWidth, &opt, this));
|
||||||
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);
|
|
||||||
setClearButtonEnabled(isEditable());
|
setClearButtonEnabled(isEditable());
|
||||||
connect(this, &ClearComboBox::currentTextChanged, this, &ClearComboBox::handleTextChanged);
|
connect(this, &ClearComboBox::currentTextChanged, this, &ClearComboBox::handleTextChanged);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include "./clearlineedit.h"
|
#include "./clearlineedit.h"
|
||||||
|
|
||||||
|
#include <QStyle>
|
||||||
|
#include <QStyleOptionFrame>
|
||||||
|
|
||||||
namespace QtUtilities {
|
namespace QtUtilities {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -14,6 +17,11 @@ ClearLineEdit::ClearLineEdit(QWidget *parent)
|
||||||
: QLineEdit(parent)
|
: QLineEdit(parent)
|
||||||
, ButtonOverlay(this)
|
, 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);
|
ButtonOverlay::setClearButtonEnabled(true);
|
||||||
connect(this, &ClearLineEdit::textChanged, this, &ClearLineEdit::handleTextChanged);
|
connect(this, &ClearLineEdit::textChanged, this, &ClearLineEdit::handleTextChanged);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <QStyleOptionFrame>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -21,6 +23,11 @@ ClearPlainTextEdit::ClearPlainTextEdit(QWidget *parent)
|
||||||
{
|
{
|
||||||
// set alignment to show buttons in the bottom right corner
|
// set alignment to show buttons in the bottom right corner
|
||||||
ButtonOverlay::buttonLayout()->setAlignment(Qt::AlignBottom | Qt::AlignRight);
|
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);
|
ButtonOverlay::setClearButtonEnabled(true);
|
||||||
connect(this, &QPlainTextEdit::textChanged, this, &ClearPlainTextEdit::handleTextChanged);
|
connect(this, &QPlainTextEdit::textChanged, this, &ClearPlainTextEdit::handleTextChanged);
|
||||||
// ensure button layout is realigned when scrolling
|
// ensure button layout is realigned when scrolling
|
||||||
|
|
|
@ -21,14 +21,11 @@ ClearSpinBox::ClearSpinBox(QWidget *parent)
|
||||||
, ButtonOverlay(this)
|
, ButtonOverlay(this)
|
||||||
, m_minimumHidden(false)
|
, m_minimumHidden(false)
|
||||||
{
|
{
|
||||||
const QMargins margins = contentsMargins();
|
const QStyle *const s = style();
|
||||||
QStyleOptionComboBox opt;
|
QStyleOptionSpinBox opt;
|
||||||
opt.initFrom(this);
|
opt.initFrom(this);
|
||||||
const int frameWidth = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth, &opt, this);
|
setContentsMarginsFromEditFieldRectAndFrameWidth(
|
||||||
const int pad = 5;
|
s->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxEditField, this), s->pixelMetric(QStyle::PM_SpinBoxFrameWidth, &opt, this));
|
||||||
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);
|
|
||||||
setClearButtonEnabled(true);
|
setClearButtonEnabled(true);
|
||||||
connect(this, static_cast<void (ClearSpinBox::*)(int)>(&ClearSpinBox::valueChanged), this, &ClearSpinBox::handleValueChanged);
|
connect(this, static_cast<void (ClearSpinBox::*)(int)>(&ClearSpinBox::valueChanged), this, &ClearSpinBox::handleValueChanged);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue