Qt 4.8
qdeclarativerectangle.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 QtDeclarative 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 "private/qdeclarativerectangle_p.h"
43 #include "private/qdeclarativerectangle_p_p.h"
44 
45 #include <QPainter>
46 #include <QStringBuilder>
47 #include <QtCore/qmath.h>
48 
50 
74 {
75  _color = c;
76  _valid = (_color.alpha() && _width >= 1) ? true : false;
77  emit penChanged();
78 }
79 
81 {
82  if (_width == w && _valid)
83  return;
84 
85  _width = w;
86  _valid = (_color.alpha() && _width >= 1) ? true : false;
87  emit penChanged();
88 }
89 
90 
119 {
120  if (QDeclarativeGradient *grad = qobject_cast<QDeclarativeGradient*>(parent()))
121  grad->doUpdate();
122 }
123 
191 {
192  if (!m_gradient && !m_stops.isEmpty()) {
193  m_gradient = new QLinearGradient(0,0,0,1.0);
194  for (int i = 0; i < m_stops.count(); ++i) {
195  const QDeclarativeGradientStop *stop = m_stops.at(i);
196  m_gradient->setCoordinateMode(QGradient::ObjectBoundingMode);
197  m_gradient->setColorAt(stop->position(), stop->color());
198  }
199  }
200 
201  return m_gradient;
202 }
203 
205 {
206  delete m_gradient;
207  m_gradient = 0;
208  emit updated();
209 }
210 
211 
261 
264 {
265 }
266 
268 {
270  d->rectImage = QPixmap();
271  const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
272  d->setPaintMargin((pw+1)/2);
273  update();
274 }
275 
307 {
309  return d->getPen();
310 }
311 
335 {
336  Q_D(const QDeclarativeRectangle);
337  return d->gradient;
338 }
339 
341 {
343  if (d->gradient == gradient)
344  return;
345  static int updatedSignalIdx = -1;
346  if (updatedSignalIdx < 0)
347  updatedSignalIdx = QDeclarativeGradient::staticMetaObject.indexOfSignal("updated()");
348  if (d->doUpdateSlotIdx < 0)
349  d->doUpdateSlotIdx = QDeclarativeRectangle::staticMetaObject.indexOfSlot("doUpdate()");
350  if (d->gradient)
351  QMetaObject::disconnect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
352  d->gradient = gradient;
353  if (d->gradient)
354  QMetaObject::connect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
355  update();
356 }
357 
358 
371 {
372  Q_D(const QDeclarativeRectangle);
373  return d->radius;
374 }
375 
377 {
379  if (d->radius == radius)
380  return;
381 
382  d->radius = radius;
383  d->rectImage = QPixmap();
384  update();
386 }
387 
412 {
413  Q_D(const QDeclarativeRectangle);
414  return d->color;
415 }
416 
418 {
420  if (d->color == c)
421  return;
422 
423  d->color = c;
424  d->rectImage = QPixmap();
425  update();
426  emit colorChanged();
427 }
428 
430 {
432  if (d->rectImage.isNull()) {
433  const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
434  const int radius = qCeil(d->radius); //ensure odd numbered width/height so we get 1-pixel center
435 
436  QString key = QLatin1String("q_") % QString::number(pw) % d->color.name() % QString::number(d->color.alpha(), 16) % QLatin1Char('_') % QString::number(radius);
437  if (d->pen && d->pen->isValid())
438  key += d->pen->color().name() % QString::number(d->pen->color().alpha(), 16);
439 
440  if (!QPixmapCache::find(key, &d->rectImage)) {
441  d->rectImage = QPixmap(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2);
442  d->rectImage.fill(Qt::transparent);
443  QPainter p(&(d->rectImage));
445  if (d->pen && d->pen->isValid()) {
446  QPen pn(QColor(d->pen->color()), d->pen->width());
447  p.setPen(pn);
448  } else {
449  p.setPen(Qt::NoPen);
450  }
451  p.setBrush(d->color);
452  if (pw%2)
453  p.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, d->rectImage.width()-(pw+1), d->rectImage.height()-(pw+1)), d->radius, d->radius);
454  else
455  p.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, d->rectImage.width()-pw, d->rectImage.height()-pw), d->radius, d->radius);
456 
457  // end painting before inserting pixmap
458  // to pixmap cache to avoid a deep copy
459  p.end();
460  QPixmapCache::insert(key, d->rectImage);
461  }
462  }
463 }
464 
466 {
468  if (d->rectImage.isNull()) {
469  const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
470 
471  QString key = QLatin1String("q_") % QString::number(pw) % d->color.name() % QString::number(d->color.alpha(), 16);
472  if (d->pen && d->pen->isValid())
473  key += d->pen->color().name() % QString::number(d->pen->color().alpha(), 16);
474 
475  if (!QPixmapCache::find(key, &d->rectImage)) {
476  // Adding 5 here makes qDrawBorderPixmap() paint correctly with smooth: true
477  // See QTBUG-7999 and QTBUG-10765 for more details.
478  d->rectImage = QPixmap(pw*2 + 5, pw*2 + 5);
479  d->rectImage.fill(Qt::transparent);
480  QPainter p(&(d->rectImage));
482  if (d->pen && d->pen->isValid()) {
483  QPen pn(QColor(d->pen->color()), d->pen->width());
485  p.setPen(pn);
486  } else {
487  p.setPen(Qt::NoPen);
488  }
489  p.setBrush(d->color);
490  if (pw%2)
491  p.drawRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, d->rectImage.width()-(pw+1), d->rectImage.height()-(pw+1)));
492  else
493  p.drawRect(QRectF(qreal(pw)/2, qreal(pw)/2, d->rectImage.width()-pw, d->rectImage.height()-pw));
494 
495  // end painting before inserting pixmap
496  // to pixmap cache to avoid a deep copy
497  p.end();
498  QPixmapCache::insert(key, d->rectImage);
499  }
500  }
501 }
502 
504 {
506  if (width() <= 0 || height() <= 0)
507  return;
508  if (d->radius > 0 || (d->pen && d->pen->isValid())
509  || (d->gradient && d->gradient->gradient()) ) {
510  drawRect(*p);
511  }
512  else {
513  bool oldAA = p->testRenderHint(QPainter::Antialiasing);
514  if (d->smooth)
516  p->fillRect(QRectF(0, 0, width(), height()), d->color);
517  if (d->smooth)
519  }
520 }
521 
523 {
525  if ((d->gradient && d->gradient->gradient())
526  || d->radius > width()/2 || d->radius > height()/2
527  || width() < 3 || height() < 3) {
528  // XXX This path is still slower than the image path
529  // Image path won't work for gradients or invalid radius though
530  bool oldAA = p.testRenderHint(QPainter::Antialiasing);
531  if (d->smooth)
533  if (d->pen && d->pen->isValid()) {
534  QPen pn(QColor(d->pen->color()), d->pen->width());
536  p.setPen(pn);
537  } else {
538  p.setPen(Qt::NoPen);
539  }
540  if (d->gradient && d->gradient->gradient())
541  p.setBrush(*d->gradient->gradient());
542  else
543  p.setBrush(d->color);
544  const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
545  QRectF rect;
546  if (pw%2)
547  rect = QRectF(0.5, 0.5, width()-1, height()-1);
548  else
549  rect = QRectF(0, 0, width(), height());
550  qreal radius = d->radius;
551  if (radius > width()/2 || radius > height()/2)
552  radius = qMin(width()/2, height()/2);
553  if (radius > 0.)
554  p.drawRoundedRect(rect, radius, radius);
555  else
556  p.drawRect(rect);
557  if (d->smooth)
559  } else {
560  bool oldAA = p.testRenderHint(QPainter::Antialiasing);
562  if (d->smooth)
564 
565  const int pw = d->pen && d->pen->isValid() ? (d->pen->width()+1)/2*2 : 0;
566 
567  if (d->radius > 0)
569  else
571 
572  int xOffset = (d->rectImage.width()-1)/2;
573  int yOffset = (d->rectImage.height()-1)/2;
574  Q_ASSERT(d->rectImage.width() == 2*xOffset + 1);
575  Q_ASSERT(d->rectImage.height() == 2*yOffset + 1);
576 
577  // check whether we've eliminated the center completely
578  if (2*xOffset > width()+pw)
579  xOffset = (width()+pw)/2;
580  if (2*yOffset > height()+pw)
581  yOffset = (height()+pw)/2;
582 
583  QMargins margins(xOffset, yOffset, xOffset, yOffset);
585  //NOTE: even though our item may have qreal-based width and height, qDrawBorderPixmap only supports QRects
586  qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width()+pw, height()+pw), margins, d->rectImage, d->rectImage.rect(), margins, rules);
587 
588  if (d->smooth) {
591  }
592  }
593 }
594 
615 {
616  Q_D(const QDeclarativeRectangle);
617  return QRectF(-d->paintmargin, -d->paintmargin, d->width()+d->paintmargin*2, d->height()+d->paintmargin*2);
618 }
619 
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
double qreal
Definition: qglobal.h:1193
unsigned char c[8]
Definition: qnumeric_p.h:62
static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=0)
Definition: qobject.cpp:3194
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QDeclarativeParserStatus ** d
int qCeil(qreal v)
Definition: qmath.h:63
qreal radius() const
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
QColor color() const
static const QMetaObject staticMetaObject
This variable stores the meta-object for the class.
Definition: qobject.h:128
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
bool testRenderHint(RenderHint hint) const
Returns true if hint is set; otherwise returns false.
Definition: qpainter.h:457
The QString class provides a Unicode character string.
Definition: qstring.h:83
void update(const QRectF &rect=QRectF())
Schedules a redraw of the area covered by rect in this item.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define Q_D(Class)
Definition: qglobal.h:2482
The QPen class defines how a QPainter should draw lines and outlines of shapes.
Definition: qpen.h:64
static QPixmap * find(const QString &key)
void setRenderHint(RenderHint hint, bool on=true)
Sets the given render hint on the painter if on is true; otherwise clears the render hint...
Definition: qpainter.cpp:7620
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
The QDeclarativeItem class provides the most basic of all visual items in QML.
#define emit
Definition: qobjectdefs.h:76
const QGradient * gradient() const
void setColor(const QColor &)
static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver, int method_index)
Definition: qobject.cpp:3276
void setGradient(QDeclarativeGradient *gradient)
int indexOfSlot(const char *slot) const
Finds slot and returns its index; otherwise returns -1.
int indexOfSignal(const char *signal) const
Finds signal and returns its index; otherwise returns -1.
void setJoinStyle(Qt::PenJoinStyle pcs)
Sets the pen&#39;s join style to the given style.
Definition: qpen.cpp:753
void setColor(const QColor &c)
void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, const QPixmap &pixmap, const QRect &sourceRect, const QMargins &sourceMargins, const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
Draws the indicated sourceRect rectangle from the given pixmap into the given targetRect rectangle...
Definition: qdrawutil.cpp:1106
QDeclarativeRectangle(QDeclarativeItem *parent=0)
void setRenderHints(RenderHints hints, bool on=true)
Sets the given render hints on the painter if on is true; otherwise clears the render hints...
Definition: qpainter.cpp:7649
ushort alpha
Returns the alpha color component of this color.
Definition: qcolor.h:242
The QLinearGradient class is used in combination with QBrush to specify a linear gradient brush...
Definition: qbrush.h:280
The QGradient class is used in combination with QBrush to specify gradient fills. ...
Definition: qbrush.h:201
Holds the rules used to draw a pixmap or image split into nine segments, similar to [CSS3 border-imag...
Definition: qdrawutil.h:136
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
static bool insert(const QString &key, const QPixmap &pixmap)
Inserts a copy of the pixmap pixmap associated with the key into the cache.
int key
void setBrush(const QBrush &brush)
Sets the painter&#39;s brush to the given brush.
Definition: qpainter.cpp:4171
void setPen(const QColor &color)
Sets the painter&#39;s pen to have style Qt::SolidLine, width 0 and the specified color.
Definition: qpainter.cpp:4047
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
void drawRect(const QRectF &rect)
Draws the current rectangle with the current pen and brush.
Definition: qpainter.h:650
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
QDeclarativeGradient * gradient() const
The QDeclarativePen class provides a pen used for drawing rectangle borders on a QDeclarativeView.
The QMargins class defines the four margins of a rectangle.
Definition: qmargins.h:53
void drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode=Qt::AbsoluteSize)
Draws the given rectangle rect with rounded corners.
Definition: qpainter.cpp:4348
The QStyleOptionGraphicsItem class is used to describe the parameters needed to draw a QGraphicsItem...
Definition: qstyleoption.h:867
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
void drawRect(QPainter &painter)
bool end()
Ends painting.
Definition: qpainter.cpp:1929
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
Definition: qpainter.cpp:7420