qcommandlinkbutton.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/widgets/widgets/qcommandlinkbutton.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtWidgets module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qcommandlinkbutton.h"-
41#include "qstylepainter.h"-
42#include "qstyleoption.h"-
43#include "qtextdocument.h"-
44#include "qtextlayout.h"-
45#include "qcolor.h"-
46#include "qfont.h"-
47#include <qmath.h>-
48-
49#include "private/qpushbutton_p.h"-
50-
51QT_BEGIN_NAMESPACE-
52-
53/*!-
54 \class QCommandLinkButton-
55 \since 4.4-
56 \brief The QCommandLinkButton widget provides a Vista style command link button.-
57-
58 \ingroup basicwidgets-
59 \inmodule QtWidgets-
60-
61 The command link is a new control that was introduced by Windows Vista. It's-
62 intended use is similar to that of a radio button in that it is used to choose-
63 between a set of mutually exclusive options. Command link buttons should not-
64 be used by themselves but rather as an alternative to radio buttons in-
65 Wizards and dialogs and makes pressing the "next" button redundant.-
66 The appearance is generally similar to that of a flat pushbutton, but-
67 it allows for a descriptive text in addition to the normal button text.-
68 By default it will also carry an arrow icon, indicating that pressing the-
69 control will open another window or page.-
70-
71 \sa QPushButton, QRadioButton-
72*/-
73-
74/*!-
75 \property QCommandLinkButton::description-
76 \brief A descriptive label to complement the button text-
77-
78 Setting this property will set a descriptive text on the-
79 button, complementing the text label. This will usually-
80 be displayed in a smaller font than the primary text.-
81*/-
82-
83/*!-
84 \property QCommandLinkButton::flat-
85 \brief This property determines whether the button is displayed as a flat-
86 panel or with a border.-
87-
88 By default, this property is set to false.-
89-
90 \sa QPushButton::flat-
91*/-
92-
93class QCommandLinkButtonPrivate : public QPushButtonPrivate-
94{-
95 Q_DECLARE_PUBLIC(QCommandLinkButton)-
96-
97public:-
98 QCommandLinkButtonPrivate()-
99 : QPushButtonPrivate(){}
never executed: end of block
0
100-
101 void init();-
102 qreal titleSize() const;-
103 bool usingVistaStyle() const;-
104-
105 QFont titleFont() const;-
106 QFont descriptionFont() const;-
107-
108 QRect titleRect() const;-
109 QRect descriptionRect() const;-
110-
111 int textOffset() const;-
112 int descriptionOffset() const;-
113 int descriptionHeight(int width) const;-
114 QColor mergedColors(const QColor &a, const QColor &b, int value) const;-
115-
116 int topMargin() const { return 10; }
never executed: return 10;
0
117 int leftMargin() const { return 7; }
never executed: return 7;
0
118 int rightMargin() const { return 4; }
never executed: return 4;
0
119 int bottomMargin() const { return 10; }
never executed: return 10;
0
120-
121 QString description;-
122 QColor currentColor;-
123};-
124-
125// Mix colors a and b with a ratio in the range [0-255]-
126QColor QCommandLinkButtonPrivate::mergedColors(const QColor &a, const QColor &b, int value = 50) const-
127{-
128 Q_ASSERT(value >= 0);-
129 Q_ASSERT(value <= 255);-
130 QColor tmp = a;-
131 tmp.setRed((tmp.red() * value) / 255 + (b.red() * (255 - value)) / 255);-
132 tmp.setGreen((tmp.green() * value) / 255 + (b.green() * (255 - value)) / 255);-
133 tmp.setBlue((tmp.blue() * value) / 255 + (b.blue() * (255 - value)) / 255);-
134 return tmp;
never executed: return tmp;
0
135}-
136-
137QFont QCommandLinkButtonPrivate::titleFont() const-
138{-
139 Q_Q(const QCommandLinkButton);-
140 QFont font = q->font();-
141 if (usingVistaStyle()) {
usingVistaStyle()Description
TRUEnever evaluated
FALSEnever evaluated
0
142 font.setPointSizeF(12.0);-
143 } else {
never executed: end of block
0
144 font.setBold(true);-
145 font.setPointSizeF(9.0);-
146 }
never executed: end of block
0
147-
148 // Note the font will be resolved against-
149 // QPainters font, so we need to restore the mask-
150 int resolve_mask = font.resolve_mask;-
151 QFont modifiedFont = q->font().resolve(font);-
152 modifiedFont.detach();-
153 modifiedFont.resolve_mask = resolve_mask;-
154 return modifiedFont;
never executed: return modifiedFont;
0
155}-
156-
157QFont QCommandLinkButtonPrivate::descriptionFont() const-
158{-
159 Q_Q(const QCommandLinkButton);-
160 QFont font = q->font();-
161 font.setPointSizeF(9.0);-
162-
163 // Note the font will be resolved against-
164 // QPainters font, so we need to restore the mask-
165 int resolve_mask = font.resolve_mask;-
166 QFont modifiedFont = q->font().resolve(font);-
167 modifiedFont.detach();-
168 modifiedFont.resolve_mask = resolve_mask;-
169 return modifiedFont;
never executed: return modifiedFont;
0
170}-
171-
172QRect QCommandLinkButtonPrivate::titleRect() const-
173{-
174 Q_Q(const QCommandLinkButton);-
175 QRect r = q->rect().adjusted(textOffset(), topMargin(), -rightMargin(), 0);-
176 if (description.isEmpty())
description.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
177 {-
178 QFontMetrics fm(titleFont());-
179 r.setTop(r.top() + qMax(0, (q->icon().actualSize(q->iconSize()).height()-
180 - fm.height()) / 2));-
181 }
never executed: end of block
0
182-
183 return r;
never executed: return r;
0
184}-
185-
186QRect QCommandLinkButtonPrivate::descriptionRect() const-
187{-
188 Q_Q(const QCommandLinkButton);-
189 return q->rect().adjusted(textOffset(), descriptionOffset(),
never executed: return q->rect().adjusted(textOffset(), descriptionOffset(), -rightMargin(), -bottomMargin());
0
190 -rightMargin(), -bottomMargin());
never executed: return q->rect().adjusted(textOffset(), descriptionOffset(), -rightMargin(), -bottomMargin());
0
191}-
192-
193int QCommandLinkButtonPrivate::textOffset() const-
194{-
195 Q_Q(const QCommandLinkButton);-
196 return q->icon().actualSize(q->iconSize()).width() + leftMargin() + 6;
never executed: return q->icon().actualSize(q->iconSize()).width() + leftMargin() + 6;
0
197}-
198-
199int QCommandLinkButtonPrivate::descriptionOffset() const-
200{-
201 QFontMetrics fm(titleFont());-
202 return topMargin() + fm.height();
never executed: return topMargin() + fm.height();
0
203}-
204-
205bool QCommandLinkButtonPrivate::usingVistaStyle() const-
206{-
207 Q_Q(const QCommandLinkButton);-
208 //### This is a hack to detect if we are indeed running Vista style themed and not in classic-
209 // When we add api to query for this, we should change this implementation to use it.-
210 return q->style()->inherits("QWindowsVistaStyle")
never executed: return q->style()->inherits("QWindowsVistaStyle") && !q->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal);
0
211 && !q->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal);
never executed: return q->style()->inherits("QWindowsVistaStyle") && !q->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal);
0
212}-
213-
214void QCommandLinkButtonPrivate::init()-
215{-
216 Q_Q(QCommandLinkButton);-
217 QPushButtonPrivate::init();-
218 q->setAttribute(Qt::WA_Hover);-
219-
220 QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::PushButton);-
221 policy.setHeightForWidth(true);-
222 q->setSizePolicy(policy);-
223-
224 q->setIconSize(QSize(20, 20));-
225 QStyleOptionButton opt;-
226 q->initStyleOption(&opt);-
227 q->setIcon(q->style()->standardIcon(QStyle::SP_CommandLink, &opt));-
228}
never executed: end of block
0
229-
230// Calculates the height of the description text based on widget width-
231int QCommandLinkButtonPrivate::descriptionHeight(int widgetWidth) const-
232{-
233 // Calc width of actual paragraph-
234 int lineWidth = widgetWidth - textOffset() - rightMargin();-
235-
236 qreal descriptionheight = 0;-
237 if (!description.isEmpty()) {
!description.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
238 QTextLayout layout(description);-
239 layout.setFont(descriptionFont());-
240 layout.beginLayout();-
241 while (true) {-
242 QTextLine line = layout.createLine();-
243 if (!line.isValid())
!line.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
244 break;
never executed: break;
0
245 line.setLineWidth(lineWidth);-
246 line.setPosition(QPointF(0, descriptionheight));-
247 descriptionheight += line.height();-
248 }
never executed: end of block
0
249 layout.endLayout();-
250 }
never executed: end of block
0
251 return qCeil(descriptionheight);
never executed: return qCeil(descriptionheight);
0
252}-
253-
254/*!-
255 \reimp-
256 */-
257QSize QCommandLinkButton::minimumSizeHint() const-
258{-
259 Q_D(const QCommandLinkButton);-
260 QSize size = sizeHint();-
261 int minimumHeight = qMax(d->descriptionOffset() + d->bottomMargin(),-
262 icon().actualSize(iconSize()).height() + d->topMargin());-
263 size.setHeight(minimumHeight);-
264 return size;
never executed: return size;
0
265}-
266-
267/*!-
268 Constructs a command link with no text and a \a parent.-
269*/-
270-
271QCommandLinkButton::QCommandLinkButton(QWidget *parent)-
272: QPushButton(*new QCommandLinkButtonPrivate, parent)-
273{-
274 Q_D(QCommandLinkButton);-
275 d->init();-
276}
never executed: end of block
0
277-
278/*!-
279 Constructs a command link with the parent \a parent and the text \a-
280 text.-
281*/-
282-
283QCommandLinkButton::QCommandLinkButton(const QString &text, QWidget *parent)-
284 : QPushButton(*new QCommandLinkButtonPrivate, parent)-
285{-
286 Q_D(QCommandLinkButton);-
287 setText(text);-
288 d->init();-
289}
never executed: end of block
0
290-
291/*!-
292 Constructs a command link with a \a text, a \a description, and a \a parent.-
293*/-
294QCommandLinkButton::QCommandLinkButton(const QString &text, const QString &description, QWidget *parent)-
295 : QPushButton(*new QCommandLinkButtonPrivate, parent)-
296{-
297 Q_D(QCommandLinkButton);-
298 setText(text);-
299 setDescription(description);-
300 d->init();-
301}
never executed: end of block
0
302-
303/*!-
304 Destructor.-
305*/-
306QCommandLinkButton::~QCommandLinkButton()-
307{-
308}-
309-
310/*! \reimp */-
311bool QCommandLinkButton::event(QEvent *e)-
312{-
313 return QPushButton::event(e);
never executed: return QPushButton::event(e);
0
314}-
315-
316/*! \reimp */-
317QSize QCommandLinkButton::sizeHint() const-
318{-
319// Standard size hints from UI specs-
320// Without note: 135, 41-
321// With note: 135, 60-
322 Q_D(const QCommandLinkButton);-
323-
324 QSize size = QPushButton::sizeHint();-
325 QFontMetrics fm(d->titleFont());-
326 int textWidth = qMax(fm.width(text()), 135);-
327 int buttonWidth = textWidth + d->textOffset() + d->rightMargin();-
328 int heightWithoutDescription = d->descriptionOffset() + d->bottomMargin();-
329-
330 size.setWidth(qMax(size.width(), buttonWidth));-
331 size.setHeight(qMax(d->description.isEmpty() ? 41 : 60,-
332 heightWithoutDescription + d->descriptionHeight(buttonWidth)));-
333 return size;
never executed: return size;
0
334}-
335-
336/*! \reimp */-
337int QCommandLinkButton::heightForWidth(int width) const-
338{-
339 Q_D(const QCommandLinkButton);-
340 int heightWithoutDescription = d->descriptionOffset() + d->bottomMargin();-
341 // find the width available for the description area-
342 return qMax(heightWithoutDescription + d->descriptionHeight(width),
never executed: return qMax(heightWithoutDescription + d->descriptionHeight(width), icon().actualSize(iconSize()).height() + d->topMargin() + d->bottomMargin());
0
343 icon().actualSize(iconSize()).height() + d->topMargin() +
never executed: return qMax(heightWithoutDescription + d->descriptionHeight(width), icon().actualSize(iconSize()).height() + d->topMargin() + d->bottomMargin());
0
344 d->bottomMargin());
never executed: return qMax(heightWithoutDescription + d->descriptionHeight(width), icon().actualSize(iconSize()).height() + d->topMargin() + d->bottomMargin());
0
345}-
346-
347/*! \reimp */-
348void QCommandLinkButton::paintEvent(QPaintEvent *)-
349{-
350 Q_D(QCommandLinkButton);-
351 QStylePainter p(this);-
352 p.save();-
353-
354 QStyleOptionButton option;-
355 initStyleOption(&option);-
356-
357 //Enable command link appearance on Vista-
358 option.features |= QStyleOptionButton::CommandLinkButton;-
359 option.text = QString();-
360 option.icon = QIcon(); //we draw this ourselves-
361 QSize pixmapSize = icon().actualSize(iconSize());-
362-
363 int vOffset = isDown() ? style()->pixelMetric(QStyle::PM_ButtonShiftVertical) : 0;
isDown()Description
TRUEnever evaluated
FALSEnever evaluated
0
364 int hOffset = isDown() ? style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal) : 0;
isDown()Description
TRUEnever evaluated
FALSEnever evaluated
0
365-
366 //Draw icon-
367 p.drawControl(QStyle::CE_PushButton, option);-
368 if (!icon().isNull())
!icon().isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
369 p.drawPixmap(d->leftMargin() + hOffset, d->topMargin() + vOffset,
never executed: p.drawPixmap(d->leftMargin() + hOffset, d->topMargin() + vOffset, icon().pixmap(pixmapSize, isEnabled() ? QIcon::Normal : QIcon::Disabled, isChecked() ? QIcon::On : QIcon::Off));
0
370 icon().pixmap(pixmapSize, isEnabled() ? QIcon::Normal : QIcon::Disabled,
never executed: p.drawPixmap(d->leftMargin() + hOffset, d->topMargin() + vOffset, icon().pixmap(pixmapSize, isEnabled() ? QIcon::Normal : QIcon::Disabled, isChecked() ? QIcon::On : QIcon::Off));
0
371 isChecked() ? QIcon::On : QIcon::Off));
never executed: p.drawPixmap(d->leftMargin() + hOffset, d->topMargin() + vOffset, icon().pixmap(pixmapSize, isEnabled() ? QIcon::Normal : QIcon::Disabled, isChecked() ? QIcon::On : QIcon::Off));
0
372-
373 //Draw title-
374 QColor textColor = palette().buttonText().color();-
375 if (isEnabled() && d->usingVistaStyle()) {
isEnabled()Description
TRUEnever evaluated
FALSEnever evaluated
d->usingVistaStyle()Description
TRUEnever evaluated
FALSEnever evaluated
0
376 textColor = QColor(21, 28, 85);-
377 if (underMouse() && !isDown())
underMouse()Description
TRUEnever evaluated
FALSEnever evaluated
!isDown()Description
TRUEnever evaluated
FALSEnever evaluated
0
378 textColor = QColor(7, 64, 229);
never executed: textColor = QColor(7, 64, 229);
0
379 //A simple text color transition-
380 d->currentColor = d->mergedColors(textColor, d->currentColor, 60);-
381 option.palette.setColor(QPalette::ButtonText, d->currentColor);-
382 }
never executed: end of block
0
383-
384 int textflags = Qt::TextShowMnemonic;-
385 if (!style()->styleHint(QStyle::SH_UnderlineShortcut, &option, this))
!style()->styl...&option, this)Description
TRUEnever evaluated
FALSEnever evaluated
0
386 textflags |= Qt::TextHideMnemonic;
never executed: textflags |= Qt::TextHideMnemonic;
0
387-
388 p.setFont(d->titleFont());-
389 p.drawItemText(d->titleRect().translated(hOffset, vOffset),-
390 textflags, option.palette, isEnabled(), text(), QPalette::ButtonText);-
391-
392 //Draw description-
393 textflags |= Qt::TextWordWrap | Qt::ElideRight;-
394 p.setFont(d->descriptionFont());-
395 p.drawItemText(d->descriptionRect().translated(hOffset, vOffset), textflags,-
396 option.palette, isEnabled(), description(), QPalette::ButtonText);-
397 p.restore();-
398}
never executed: end of block
0
399-
400void QCommandLinkButton::setDescription(const QString &description)-
401{-
402 Q_D(QCommandLinkButton);-
403 d->description = description;-
404 updateGeometry();-
405 update();-
406}
never executed: end of block
0
407-
408QString QCommandLinkButton::description() const-
409{-
410 Q_D(const QCommandLinkButton);-
411 return d->description;
never executed: return d->description;
0
412}-
413-
414QT_END_NAMESPACE-
415-
416#include "moc_qcommandlinkbutton.cpp"-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9