mirror of
https://github.com/crystalidea/qt-build-tools.git
synced 2025-02-02 19:27:40 +08:00
5.15: qcommandlinkbutton.cpp original
This commit is contained in:
parent
fa24e309d3
commit
caba6addab
413
5.15.2/qtbase/src/widgets/widgets/qcommandlinkbutton.cpp
Normal file
413
5.15.2/qtbase/src/widgets/widgets/qcommandlinkbutton.cpp
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the QtWidgets module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 2.0 or (at your option) the GNU General
|
||||||
|
** Public license version 3 or any later version approved by the KDE Free
|
||||||
|
** Qt Foundation. The licenses are as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||||
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qcommandlinkbutton.h"
|
||||||
|
#include "qstylepainter.h"
|
||||||
|
#include "qstyleoption.h"
|
||||||
|
#include "qtextdocument.h"
|
||||||
|
#include "qtextlayout.h"
|
||||||
|
#include "qcolor.h"
|
||||||
|
#include "qfont.h"
|
||||||
|
#include <qmath.h>
|
||||||
|
|
||||||
|
#include "private/qpushbutton_p.h"
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QCommandLinkButton
|
||||||
|
\since 4.4
|
||||||
|
\brief The QCommandLinkButton widget provides a Vista style command link button.
|
||||||
|
|
||||||
|
\ingroup basicwidgets
|
||||||
|
\inmodule QtWidgets
|
||||||
|
|
||||||
|
The command link is a new control that was introduced by Windows Vista. Its
|
||||||
|
intended use is similar to that of a radio button in that it is used to choose
|
||||||
|
between a set of mutually exclusive options. Command link buttons should not
|
||||||
|
be used by themselves but rather as an alternative to radio buttons in
|
||||||
|
Wizards and dialogs and makes pressing the "next" button redundant.
|
||||||
|
The appearance is generally similar to that of a flat pushbutton, but
|
||||||
|
it allows for a descriptive text in addition to the normal button text.
|
||||||
|
By default it will also carry an arrow icon, indicating that pressing the
|
||||||
|
control will open another window or page.
|
||||||
|
|
||||||
|
\sa QPushButton, QRadioButton
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\property QCommandLinkButton::description
|
||||||
|
\brief A descriptive label to complement the button text
|
||||||
|
|
||||||
|
Setting this property will set a descriptive text on the
|
||||||
|
button, complementing the text label. This will usually
|
||||||
|
be displayed in a smaller font than the primary text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\property QCommandLinkButton::flat
|
||||||
|
\brief This property determines whether the button is displayed as a flat
|
||||||
|
panel or with a border.
|
||||||
|
|
||||||
|
By default, this property is set to false.
|
||||||
|
|
||||||
|
\sa QPushButton::flat
|
||||||
|
*/
|
||||||
|
|
||||||
|
class QCommandLinkButtonPrivate : public QPushButtonPrivate
|
||||||
|
{
|
||||||
|
Q_DECLARE_PUBLIC(QCommandLinkButton)
|
||||||
|
|
||||||
|
public:
|
||||||
|
QCommandLinkButtonPrivate()
|
||||||
|
: QPushButtonPrivate(){}
|
||||||
|
|
||||||
|
void init();
|
||||||
|
qreal titleSize() const;
|
||||||
|
bool usingVistaStyle() const;
|
||||||
|
|
||||||
|
QFont titleFont() const;
|
||||||
|
QFont descriptionFont() const;
|
||||||
|
|
||||||
|
QRect titleRect() const;
|
||||||
|
QRect descriptionRect() const;
|
||||||
|
|
||||||
|
int textOffset() const;
|
||||||
|
int descriptionOffset() const;
|
||||||
|
int descriptionHeight(int width) const;
|
||||||
|
QColor mergedColors(const QColor &a, const QColor &b, int value) const;
|
||||||
|
|
||||||
|
int topMargin() const { return 10; }
|
||||||
|
int leftMargin() const { return 7; }
|
||||||
|
int rightMargin() const { return 4; }
|
||||||
|
int bottomMargin() const { return 10; }
|
||||||
|
|
||||||
|
QString description;
|
||||||
|
QColor currentColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mix colors a and b with a ratio in the range [0-255]
|
||||||
|
QColor QCommandLinkButtonPrivate::mergedColors(const QColor &a, const QColor &b, int value = 50) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(value >= 0);
|
||||||
|
Q_ASSERT(value <= 255);
|
||||||
|
QColor tmp = a;
|
||||||
|
tmp.setRed((tmp.red() * value) / 255 + (b.red() * (255 - value)) / 255);
|
||||||
|
tmp.setGreen((tmp.green() * value) / 255 + (b.green() * (255 - value)) / 255);
|
||||||
|
tmp.setBlue((tmp.blue() * value) / 255 + (b.blue() * (255 - value)) / 255);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont QCommandLinkButtonPrivate::titleFont() const
|
||||||
|
{
|
||||||
|
Q_Q(const QCommandLinkButton);
|
||||||
|
QFont font = q->font();
|
||||||
|
if (usingVistaStyle()) {
|
||||||
|
font.setPointSizeF(12.0);
|
||||||
|
} else {
|
||||||
|
font.setBold(true);
|
||||||
|
font.setPointSizeF(9.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note the font will be resolved against
|
||||||
|
// QPainters font, so we need to restore the mask
|
||||||
|
int resolve_mask = font.resolve_mask;
|
||||||
|
QFont modifiedFont = q->font().resolve(font);
|
||||||
|
modifiedFont.detach();
|
||||||
|
modifiedFont.resolve_mask = resolve_mask;
|
||||||
|
return modifiedFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont QCommandLinkButtonPrivate::descriptionFont() const
|
||||||
|
{
|
||||||
|
Q_Q(const QCommandLinkButton);
|
||||||
|
QFont font = q->font();
|
||||||
|
font.setPointSizeF(9.0);
|
||||||
|
|
||||||
|
// Note the font will be resolved against
|
||||||
|
// QPainters font, so we need to restore the mask
|
||||||
|
int resolve_mask = font.resolve_mask;
|
||||||
|
QFont modifiedFont = q->font().resolve(font);
|
||||||
|
modifiedFont.detach();
|
||||||
|
modifiedFont.resolve_mask = resolve_mask;
|
||||||
|
return modifiedFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect QCommandLinkButtonPrivate::titleRect() const
|
||||||
|
{
|
||||||
|
Q_Q(const QCommandLinkButton);
|
||||||
|
QRect r = q->rect().adjusted(textOffset(), topMargin(), -rightMargin(), 0);
|
||||||
|
if (description.isEmpty())
|
||||||
|
{
|
||||||
|
QFontMetrics fm(titleFont());
|
||||||
|
r.setTop(r.top() + qMax(0, (q->icon().actualSize(q->iconSize()).height()
|
||||||
|
- fm.height()) / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect QCommandLinkButtonPrivate::descriptionRect() const
|
||||||
|
{
|
||||||
|
Q_Q(const QCommandLinkButton);
|
||||||
|
return q->rect().adjusted(textOffset(), descriptionOffset(),
|
||||||
|
-rightMargin(), -bottomMargin());
|
||||||
|
}
|
||||||
|
|
||||||
|
int QCommandLinkButtonPrivate::textOffset() const
|
||||||
|
{
|
||||||
|
Q_Q(const QCommandLinkButton);
|
||||||
|
return q->icon().actualSize(q->iconSize()).width() + leftMargin() + 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QCommandLinkButtonPrivate::descriptionOffset() const
|
||||||
|
{
|
||||||
|
QFontMetrics fm(titleFont());
|
||||||
|
return topMargin() + fm.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QCommandLinkButtonPrivate::usingVistaStyle() const
|
||||||
|
{
|
||||||
|
Q_Q(const QCommandLinkButton);
|
||||||
|
//### This is a hack to detect if we are indeed running Vista style themed and not in classic
|
||||||
|
// When we add api to query for this, we should change this implementation to use it.
|
||||||
|
return q->style()->inherits("QWindowsVistaStyle")
|
||||||
|
&& q->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, nullptr) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QCommandLinkButtonPrivate::init()
|
||||||
|
{
|
||||||
|
Q_Q(QCommandLinkButton);
|
||||||
|
QPushButtonPrivate::init();
|
||||||
|
q->setAttribute(Qt::WA_Hover);
|
||||||
|
|
||||||
|
QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::PushButton);
|
||||||
|
policy.setHeightForWidth(true);
|
||||||
|
q->setSizePolicy(policy);
|
||||||
|
|
||||||
|
q->setIconSize(QSize(20, 20));
|
||||||
|
QStyleOptionButton opt;
|
||||||
|
q->initStyleOption(&opt);
|
||||||
|
q->setIcon(q->style()->standardIcon(QStyle::SP_CommandLink, &opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the height of the description text based on widget width
|
||||||
|
int QCommandLinkButtonPrivate::descriptionHeight(int widgetWidth) const
|
||||||
|
{
|
||||||
|
// Calc width of actual paragraph
|
||||||
|
int lineWidth = widgetWidth - textOffset() - rightMargin();
|
||||||
|
|
||||||
|
qreal descriptionheight = 0;
|
||||||
|
if (!description.isEmpty()) {
|
||||||
|
QTextLayout layout(description);
|
||||||
|
layout.setFont(descriptionFont());
|
||||||
|
layout.beginLayout();
|
||||||
|
while (true) {
|
||||||
|
QTextLine line = layout.createLine();
|
||||||
|
if (!line.isValid())
|
||||||
|
break;
|
||||||
|
line.setLineWidth(lineWidth);
|
||||||
|
line.setPosition(QPointF(0, descriptionheight));
|
||||||
|
descriptionheight += line.height();
|
||||||
|
}
|
||||||
|
layout.endLayout();
|
||||||
|
}
|
||||||
|
return qCeil(descriptionheight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
QSize QCommandLinkButton::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
Q_D(const QCommandLinkButton);
|
||||||
|
QSize size = sizeHint();
|
||||||
|
int minimumHeight = qMax(d->descriptionOffset() + d->bottomMargin(),
|
||||||
|
icon().actualSize(iconSize()).height() + d->topMargin());
|
||||||
|
size.setHeight(minimumHeight);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a command link with no text and a \a parent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
QCommandLinkButton::QCommandLinkButton(QWidget *parent)
|
||||||
|
: QPushButton(*new QCommandLinkButtonPrivate, parent)
|
||||||
|
{
|
||||||
|
Q_D(QCommandLinkButton);
|
||||||
|
d->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a command link with the parent \a parent and the text \a
|
||||||
|
text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
QCommandLinkButton::QCommandLinkButton(const QString &text, QWidget *parent)
|
||||||
|
: QCommandLinkButton(parent)
|
||||||
|
{
|
||||||
|
setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a command link with a \a text, a \a description, and a \a parent.
|
||||||
|
*/
|
||||||
|
QCommandLinkButton::QCommandLinkButton(const QString &text, const QString &description, QWidget *parent)
|
||||||
|
: QCommandLinkButton(text, parent)
|
||||||
|
{
|
||||||
|
setDescription(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Destructor.
|
||||||
|
*/
|
||||||
|
QCommandLinkButton::~QCommandLinkButton()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \reimp */
|
||||||
|
bool QCommandLinkButton::event(QEvent *e)
|
||||||
|
{
|
||||||
|
return QPushButton::event(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \reimp */
|
||||||
|
QSize QCommandLinkButton::sizeHint() const
|
||||||
|
{
|
||||||
|
// Standard size hints from UI specs
|
||||||
|
// Without note: 135, 41
|
||||||
|
// With note: 135, 60
|
||||||
|
Q_D(const QCommandLinkButton);
|
||||||
|
|
||||||
|
QSize size = QPushButton::sizeHint();
|
||||||
|
QFontMetrics fm(d->titleFont());
|
||||||
|
int textWidth = qMax(fm.horizontalAdvance(text()), 135);
|
||||||
|
int buttonWidth = textWidth + d->textOffset() + d->rightMargin();
|
||||||
|
int heightWithoutDescription = d->descriptionOffset() + d->bottomMargin();
|
||||||
|
|
||||||
|
size.setWidth(qMax(size.width(), buttonWidth));
|
||||||
|
size.setHeight(qMax(d->description.isEmpty() ? 41 : 60,
|
||||||
|
heightWithoutDescription + d->descriptionHeight(buttonWidth)));
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \reimp */
|
||||||
|
int QCommandLinkButton::heightForWidth(int width) const
|
||||||
|
{
|
||||||
|
Q_D(const QCommandLinkButton);
|
||||||
|
int heightWithoutDescription = d->descriptionOffset() + d->bottomMargin();
|
||||||
|
// find the width available for the description area
|
||||||
|
return qMax(heightWithoutDescription + d->descriptionHeight(width),
|
||||||
|
icon().actualSize(iconSize()).height() + d->topMargin() +
|
||||||
|
d->bottomMargin());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \reimp */
|
||||||
|
void QCommandLinkButton::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
Q_D(QCommandLinkButton);
|
||||||
|
QStylePainter p(this);
|
||||||
|
p.save();
|
||||||
|
|
||||||
|
QStyleOptionButton option;
|
||||||
|
initStyleOption(&option);
|
||||||
|
|
||||||
|
//Enable command link appearance on Vista
|
||||||
|
option.features |= QStyleOptionButton::CommandLinkButton;
|
||||||
|
option.text = QString();
|
||||||
|
option.icon = QIcon(); //we draw this ourselves
|
||||||
|
QSize pixmapSize = icon().actualSize(iconSize());
|
||||||
|
|
||||||
|
const int vOffset = isDown()
|
||||||
|
? style()->pixelMetric(QStyle::PM_ButtonShiftVertical, &option) : 0;
|
||||||
|
const int hOffset = isDown()
|
||||||
|
? style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &option) : 0;
|
||||||
|
|
||||||
|
//Draw icon
|
||||||
|
p.drawControl(QStyle::CE_PushButton, option);
|
||||||
|
if (!icon().isNull())
|
||||||
|
p.drawPixmap(d->leftMargin() + hOffset, d->topMargin() + vOffset,
|
||||||
|
icon().pixmap(pixmapSize, isEnabled() ? QIcon::Normal : QIcon::Disabled,
|
||||||
|
isChecked() ? QIcon::On : QIcon::Off));
|
||||||
|
|
||||||
|
//Draw title
|
||||||
|
QColor textColor = palette().buttonText().color();
|
||||||
|
if (isEnabled() && d->usingVistaStyle()) {
|
||||||
|
textColor = QColor(21, 28, 85);
|
||||||
|
if (underMouse() && !isDown())
|
||||||
|
textColor = QColor(7, 64, 229);
|
||||||
|
//A simple text color transition
|
||||||
|
d->currentColor = d->mergedColors(textColor, d->currentColor, 60);
|
||||||
|
option.palette.setColor(QPalette::ButtonText, d->currentColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
int textflags = Qt::TextShowMnemonic;
|
||||||
|
if (!style()->styleHint(QStyle::SH_UnderlineShortcut, &option, this))
|
||||||
|
textflags |= Qt::TextHideMnemonic;
|
||||||
|
|
||||||
|
p.setFont(d->titleFont());
|
||||||
|
p.drawItemText(d->titleRect().translated(hOffset, vOffset),
|
||||||
|
textflags, option.palette, isEnabled(), text(), QPalette::ButtonText);
|
||||||
|
|
||||||
|
//Draw description
|
||||||
|
textflags |= Qt::TextWordWrap | Qt::ElideRight;
|
||||||
|
p.setFont(d->descriptionFont());
|
||||||
|
p.drawItemText(d->descriptionRect().translated(hOffset, vOffset), textflags,
|
||||||
|
option.palette, isEnabled(), description(), QPalette::ButtonText);
|
||||||
|
p.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QCommandLinkButton::setDescription(const QString &description)
|
||||||
|
{
|
||||||
|
Q_D(QCommandLinkButton);
|
||||||
|
d->description = description;
|
||||||
|
updateGeometry();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QCommandLinkButton::description() const
|
||||||
|
{
|
||||||
|
Q_D(const QCommandLinkButton);
|
||||||
|
return d->description;
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#include "moc_qcommandlinkbutton.cpp"
|
Loading…
Reference in New Issue
Block a user