source: trunk/src/gui/widgets/qcommandlinkbutton.cpp@ 5

Last change on this file since 5 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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