Qt 4.8
qcommandlinkbutton.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui 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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
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 #include <qmath.h>
50 
51 #include "private/qpushbutton_p.h"
52 
54 
105 {
107 
108 public:
110  : QPushButtonPrivate(){}
111 
112  void init();
113  qreal titleSize() const;
114  bool usingVistaStyle() const;
115 
116  QFont titleFont() const;
117  QFont descriptionFont() const;
118 
119  QRect titleRect() const;
120  QRect descriptionRect() const;
121 
122  int textOffset() const;
123  int descriptionOffset() const;
124  int descriptionHeight(int width) const;
125  QColor mergedColors(const QColor &a, const QColor &b, int value) const;
126 
127  int topMargin() const { return 10; }
128  int leftMargin() const { return 7; }
129  int rightMargin() const { return 4; }
130  int bottomMargin() const { return 10; }
131 
134 };
135 
136 // Mix colors a and b with a ratio in the range [0-255]
137 QColor QCommandLinkButtonPrivate::mergedColors(const QColor &a, const QColor &b, int value = 50) const
138 {
139  Q_ASSERT(value >= 0);
140  Q_ASSERT(value <= 255);
141  QColor tmp = a;
142  tmp.setRed((tmp.red() * value) / 255 + (b.red() * (255 - value)) / 255);
143  tmp.setGreen((tmp.green() * value) / 255 + (b.green() * (255 - value)) / 255);
144  tmp.setBlue((tmp.blue() * value) / 255 + (b.blue() * (255 - value)) / 255);
145  return tmp;
146 }
147 
149 {
150  Q_Q(const QCommandLinkButton);
151  QFont font = q->font();
152  if (usingVistaStyle()) {
153  font.setPointSizeF(12.0);
154  } else {
155  font.setBold(true);
156  font.setPointSizeF(9.0);
157  }
158 
159  // Note the font will be resolved against
160  // QPainters font, so we need to restore the mask
161  int resolve_mask = font.resolve_mask;
162  QFont modifiedFont = q->font().resolve(font);
163  modifiedFont.detach();
164  modifiedFont.resolve_mask = resolve_mask;
165  return modifiedFont;
166 }
167 
169 {
170  Q_Q(const QCommandLinkButton);
171  QFont font = q->font();
172  font.setPointSizeF(9.0);
173 
174  // Note the font will be resolved against
175  // QPainters font, so we need to restore the mask
176  int resolve_mask = font.resolve_mask;
177  QFont modifiedFont = q->font().resolve(font);
178  modifiedFont.detach();
179  modifiedFont.resolve_mask = resolve_mask;
180  return modifiedFont;
181 }
182 
184 {
185  Q_Q(const QCommandLinkButton);
186  QRect r = q->rect().adjusted(textOffset(), topMargin(), -rightMargin(), 0);
187  if (description.isEmpty())
188  {
189  QFontMetrics fm(titleFont());
190  r.setTop(r.top() + qMax(0, (q->icon().actualSize(q->iconSize()).height()
191  - fm.height()) / 2));
192  }
193 
194  return r;
195 }
196 
198 {
199  Q_Q(const QCommandLinkButton);
200  return q->rect().adjusted(textOffset(), descriptionOffset(),
201  -rightMargin(), -bottomMargin());
202 }
203 
205 {
206  Q_Q(const QCommandLinkButton);
207  return q->icon().actualSize(q->iconSize()).width() + leftMargin() + 6;
208 }
209 
211 {
212  QFontMetrics fm(titleFont());
213  return topMargin() + fm.height();
214 }
215 
217 {
218  Q_Q(const QCommandLinkButton);
219  //### This is a hack to detect if we are indeed running Vista style themed and not in classic
220  // When we add api to query for this, we should change this implementation to use it.
221  return q->style()->inherits("QWindowsVistaStyle")
222  && !q->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal);
223 }
224 
226 {
229  q->setAttribute(Qt::WA_Hover);
230 
232  policy.setHeightForWidth(true);
233  q->setSizePolicy(policy);
234 
235  q->setIconSize(QSize(20, 20));
236  QStyleOptionButton opt;
237  q->initStyleOption(&opt);
238  q->setIcon(q->style()->standardIcon(QStyle::SP_CommandLink, &opt));
239 }
240 
241 // Calculates the height of the description text based on widget width
243 {
244  // Calc width of actual paragraph
245  int lineWidth = widgetWidth - textOffset() - rightMargin();
246 
247  qreal descriptionheight = 0;
248  if (!description.isEmpty()) {
250  layout.setFont(descriptionFont());
251  layout.beginLayout();
252  while (true) {
253  QTextLine line = layout.createLine();
254  if (!line.isValid())
255  break;
256  line.setLineWidth(lineWidth);
257  line.setPosition(QPointF(0, descriptionheight));
258  descriptionheight += line.height();
259  }
260  layout.endLayout();
261  }
262  return qCeil(descriptionheight);
263 }
264 
269 {
270  Q_D(const QCommandLinkButton);
271  QSize size = sizeHint();
272  int minimumHeight = qMax(d->descriptionOffset() + d->bottomMargin(),
273  icon().actualSize(iconSize()).height() + d->topMargin());
274  size.setHeight(minimumHeight);
275  return size;
276 }
277 
284 {
286  d->init();
287 }
288 
295  : QPushButton(*new QCommandLinkButtonPrivate, parent)
296 {
298  setText(text);
299  d->init();
300 }
301 
306  : QPushButton(*new QCommandLinkButtonPrivate, parent)
307 {
309  setText(text);
310  setDescription(description);
311  d->init();
312 }
313 
316 {
317  return QPushButton::event(e);
318 }
319 
322 {
323 // Standard size hints from UI specs
324 // Without note: 135, 41
325 // With note: 135, 60
326  Q_D(const QCommandLinkButton);
327 
329  QFontMetrics fm(d->titleFont());
330  int textWidth = qMax(fm.width(text()), 135);
331  int buttonWidth = textWidth + d->textOffset() + d->rightMargin();
332  int heightWithoutDescription = d->descriptionOffset() + d->bottomMargin();
333 
334  size.setWidth(qMax(size.width(), buttonWidth));
335  size.setHeight(qMax(d->description.isEmpty() ? 41 : 60,
336  heightWithoutDescription + d->descriptionHeight(buttonWidth)));
337  return size;
338 }
339 
342 {
343  Q_D(const QCommandLinkButton);
344  int heightWithoutDescription = d->descriptionOffset() + d->bottomMargin();
345  // find the width available for the description area
346  return qMax(heightWithoutDescription + d->descriptionHeight(width),
347  icon().actualSize(iconSize()).height() + d->topMargin() +
348  d->bottomMargin());
349 }
350 
353 {
355  QStylePainter p(this);
356  p.save();
357 
358  QStyleOptionButton option;
359  initStyleOption(&option);
360 
361  //Enable command link appearance on Vista
363  option.text = QString();
364  option.icon = QIcon(); //we draw this ourselves
365  QSize pixmapSize = icon().actualSize(iconSize());
366 
367  int vOffset = isDown() ? style()->pixelMetric(QStyle::PM_ButtonShiftVertical) : 0;
368  int hOffset = isDown() ? style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal) : 0;
369 
370  //Draw icon
372  if (!icon().isNull())
373  p.drawPixmap(d->leftMargin() + hOffset, d->topMargin() + vOffset,
374  icon().pixmap(pixmapSize, isEnabled() ? QIcon::Normal : QIcon::Disabled,
376 
377  //Draw title
378  QColor textColor = palette().buttonText().color();
379  if (isEnabled() && d->usingVistaStyle()) {
380  textColor = QColor(21, 28, 85);
381  if (underMouse() && !isDown())
382  textColor = QColor(7, 64, 229);
383  //A simple text color transition
384  d->currentColor = d->mergedColors(textColor, d->currentColor, 60);
385  option.palette.setColor(QPalette::ButtonText, d->currentColor);
386  }
387 
388  int textflags = Qt::TextShowMnemonic;
389  if (!style()->styleHint(QStyle::SH_UnderlineShortcut, &option, this))
390  textflags |= Qt::TextHideMnemonic;
391 
392  p.setFont(d->titleFont());
393  p.drawItemText(d->titleRect().translated(hOffset, vOffset),
394  textflags, option.palette, isEnabled(), text(), QPalette::ButtonText);
395 
396  //Draw description
397  textflags |= Qt::TextWordWrap | Qt::ElideRight;
398  p.setFont(d->descriptionFont());
399  p.drawItemText(d->descriptionRect().translated(hOffset, vOffset), textflags,
401  p.restore();
402 }
403 
405 {
407  d->description = description;
408  updateGeometry();
409  update();
410 }
411 
413 {
414  Q_D(const QCommandLinkButton);
415  return d->description;
416 }
417 
419 
void setRed(int red)
Sets the red color component of this color to red.
Definition: qcolor.cpp:1143
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
double d
Definition: qnumeric_p.h:62
QRect adjusted(int x1, int y1, int x2, int y2) const
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition: qrect.h:431
bool event(QEvent *e)
Reimplemented Function
bool isChecked() const
double qreal
Definition: qglobal.h:1193
The QFontMetrics class provides font metrics information.
Definition: qfontmetrics.h:65
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QString text() const
void setText(const QString &text)
const QColor & color() const
Returns the brush color.
Definition: qbrush.h:183
void setPosition(const QPointF &pos)
Moves the line to position pos.
QSize size() const
void drawControl(QStyle::ControlElement ce, const QStyleOption &opt)
Use the widget&#39;s style to draw a control element ce specified by QStyleOption option.
Definition: qstylepainter.h:87
int qCeil(qreal v)
Definition: qmath.h:63
QLayout * layout
Definition: qwidget_p.h:704
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=0, const QWidget *widget=0) const =0
Returns the value of the given pixel metric.
QColor mergedColors(const QColor &a, const QColor &b, int value) const
void paintEvent(QPaintEvent *)
Reimplemented Function
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
void setFont(const QFont &f)
Sets the layout&#39;s font to the given font.
The QTextLine class represents a line of text inside a QTextLayout.
Definition: qtextlayout.h:197
void setGreen(int green)
Sets the green color component of this color to green.
Definition: qcolor.cpp:1170
void restore()
Restores the current painter state (pops a saved state off the stack).
Definition: qpainter.cpp:1620
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
bool isDown() const
The QPushButton widget provides a command button.
Definition: qpushbutton.h:57
long ASN1_INTEGER_get ASN1_INTEGER * a
void setLineWidth(qreal width)
Lays out the line with the given width.
bool underMouse() const
Returns true if the widget is under the mouse cursor; otherwise returns false.
Definition: qwidget.h:996
ushort red
Returns the red color component of this color.
Definition: qcolor.h:243
QString text
the text of the button
Definition: qstyleoption.h:290
QSize sizeHint() const
Reimplemented Function
The QString class provides a Unicode character string.
Definition: qstring.h:83
void setHeight(int h)
Sets the height to the given height.
Definition: qsize.h:135
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define Q_D(Class)
Definition: qglobal.h:2482
bool isValid() const
Returns true if this text line is valid; otherwise returns false.
Definition: qtextlayout.h:201
void save()
Saves the current painter state (pushes the state onto a stack).
Definition: qpainter.cpp:1590
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
QStyle * style() const
Definition: qwidget.cpp:2742
#define Q_Q(Class)
Definition: qglobal.h:2483
void setWidth(int w)
Sets the width to the given width.
Definition: qsize.h:132
void update()
Updates the widget unless updates are disabled or the widget is hidden.
Definition: qwidget.cpp:10883
void setHeightForWidth(bool b)
Definition: qsizepolicy.h:135
QFont resolve(const QFont &) const
Returns a new QFont that has attributes copied from other that have not been previously set on this f...
Definition: qfont.cpp:1983
int width() const
Returns the width.
Definition: qsize.h:126
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void setBold(bool)
If enable is true sets the font&#39;s weight to QFont::Bold ; otherwise sets the weight to QFont::Normal...
Definition: qfont.h:352
QSize minimumSizeHint() const
Reimplemented Function
uint resolve_mask
Definition: qfont.h:344
void initStyleOption(QStyleOptionButton *option) const
Initialize option with the values from this QPushButton.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
int width() const
void setTop(int pos)
Sets the top edge of the rectangle to the given y coordinate.
Definition: qrect.h:261
QIcon icon
the icon of the button
Definition: qstyleoption.h:291
const QPalette & palette() const
bool event(QEvent *e)
Reimplemented Function
const char * styleHint(const QFontDef &request)
QSize sizeHint() const
Reimplemented Function
void drawItemText(const QRect &r, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole=QPalette::NoRole)
Definition: qstylepainter.h:97
QCommandLinkButton(QWidget *parent=0)
Constructs a command link with no text and a parent.
ButtonFeatures features
a bitwise OR of the features that describe this button
Definition: qstyleoption.h:289
void setBlue(int blue)
Sets the blue color component of this color to blue.
Definition: qcolor.cpp:1199
bool isEnabled() const
Definition: qwidget.h:948
QPalette palette
the palette that should be used when painting the control
Definition: qstyleoption.h:92
int top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:243
The QTextLayout class is used to lay out and render text.
Definition: qtextlayout.h:105
QSize iconSize() const
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
void setDescription(const QString &description)
ushort blue
Returns the blue color component of this color.
Definition: qcolor.h:245
The QFont class specifies a font used for drawing text.
Definition: qfont.h:64
QTextLine createLine()
Returns a new text line to be laid out if there is text to be inserted into the layout; otherwise ret...
QSize actualSize(const QSize &size, Mode mode=Normal, State state=Off) const
Returns the actual size of the icon for the requested size, mode, and state.
Definition: qicon.cpp:730
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
void setColor(ColorGroup cg, ColorRole cr, const QColor &color)
Sets the color in the specified color group, used for the given color role, to the specified solid co...
Definition: qpalette.h:201
void detach()
Detaches the font object from common font data.
Definition: qfont.cpp:803
int height() const
Returns the height.
Definition: qsize.h:129
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
int descriptionHeight(int width) const
QObject * parent
Definition: qobject.h:92
QString description() const
void setPointSizeF(qreal)
Sets the point size to pointSize.
Definition: qfont.cpp:1121
QPixmap pixmap(const QSize &size, Mode mode=Normal, State state=Off) const
Returns a pixmap with the requested size, mode, and state, generating one if necessary.
Definition: qicon.cpp:693
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device...
Definition: qpainter.cpp:5619
The QStylePainter class is a convenience class for drawing QStyle elements inside a widget...
Definition: qstylepainter.h:55
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
void setFont(const QFont &f)
Sets the painter&#39;s font to the given font.
Definition: qpainter.cpp:4288
const QBrush & buttonText() const
Returns the button text foreground brush of the current color group.
Definition: qpalette.h:138
void endLayout()
Ends the layout process.
void updateGeometry()
Notifies the layout system that this widget has changed and may need to change geometry.
Definition: qwidget.cpp:10372
The QCommandLinkButton widget provides a Vista style command link button.
int height() const
Returns the height of the font.
The QPaintEvent class contains event parameters for paint events.
Definition: qevent.h:298
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
The QStyleOptionButton class is used to describe the parameters for drawing buttons.
Definition: qstyleoption.h:279
ushort green
Returns the green color component of this color.
Definition: qcolor.h:244
qreal height() const
Returns the line&#39;s height.
int heightForWidth(int) const
Reimplemented Function
void beginLayout()
Begins the layout process.
static bool isNull(const QVariant::Private *d)
Definition: qvariant.cpp:300
QIcon icon() const
The QIcon class provides scalable icons in different modes and states.
Definition: qicon.h:60