1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
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 http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qquickiconimage_p.h"
38#include "qquickiconimage_p_p.h"
39
40#include <QtCore/qmath.h>
41#include <QtQuick/private/qquickimagebase_p_p.h>
42
43QT_BEGIN_NAMESPACE
44
45QQuickIconImagePrivate::~QQuickIconImagePrivate()
46{
47 qDeleteAll(c: icon.entries);
48 icon.entries.clear();
49}
50
51bool QQuickIconImagePrivate::updateDevicePixelRatio(qreal targetDevicePixelRatio)
52{
53 if (isThemeIcon) {
54 devicePixelRatio = calculateDevicePixelRatio();
55 return true;
56 }
57
58 return QQuickImagePrivate::updateDevicePixelRatio(targetDevicePixelRatio);
59}
60
61void QQuickIconImagePrivate::updateIcon()
62{
63 Q_Q(QQuickIconImage);
64 // Both geometryChanged() and QQuickImageBase::sourceSizeChanged()
65 // (which we connect to updateIcon() in the constructor) can be called as a result
66 // of updateIcon() changing the various sizes, so we must check that we're not recursing.
67 if (updatingIcon)
68 return;
69
70 updatingIcon = true;
71
72 QSize size = sourcesize;
73 // If no size is specified for theme icons, it will use the smallest available size.
74 if (size.width() <= 0)
75 size.setWidth(q->width());
76 if (size.height() <= 0)
77 size.setHeight(q->height());
78
79 const qreal dpr = calculateDevicePixelRatio();
80 const QIconLoaderEngineEntry *entry = QIconLoaderEngine::entryForSize(info: icon, size: size * dpr, scale: qCeil(v: dpr));
81
82 if (entry) {
83 QQmlContext *context = qmlContext(q);
84 const QUrl entryUrl = QUrl::fromLocalFile(localfile: entry->filename);
85 url = context ? context->resolvedUrl(entryUrl) : entryUrl;
86 isThemeIcon = true;
87 } else {
88 url = source;
89 isThemeIcon = false;
90 }
91 q->load();
92
93 updatingIcon = false;
94}
95
96void QQuickIconImagePrivate::updateFillMode()
97{
98 Q_Q(QQuickIconImage);
99 // If we start with a sourceSize of 28x28 and then set sourceSize.width to 24, the fillMode
100 // will change to PreserveAspectFit (because pixmapSize.width() > width()), which causes the
101 // pixmap to be reloaded at its original size of 28x28, which causes the fillMode to change
102 // to Pad (because pixmapSize.width() <= width()), and so on.
103 if (updatingFillMode)
104 return;
105
106 updatingFillMode = true;
107
108 const QSize pixmapSize = QSize(pix.width(), pix.height()) / calculateDevicePixelRatio();
109 if (pixmapSize.width() > q->width() || pixmapSize.height() > q->height())
110 q->setFillMode(QQuickImage::PreserveAspectFit);
111 else
112 q->setFillMode(QQuickImage::Pad);
113
114 updatingFillMode = false;
115}
116
117qreal QQuickIconImagePrivate::calculateDevicePixelRatio() const
118{
119 Q_Q(const QQuickIconImage);
120 return q->window() ? q->window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio();
121}
122
123QQuickIconImage::QQuickIconImage(QQuickItem *parent)
124 : QQuickImage(*(new QQuickIconImagePrivate), parent)
125{
126 setFillMode(Pad);
127}
128
129QString QQuickIconImage::name() const
130{
131 Q_D(const QQuickIconImage);
132 return d->icon.iconName;
133}
134
135void QQuickIconImage::setName(const QString &name)
136{
137 Q_D(QQuickIconImage);
138 if (d->icon.iconName == name)
139 return;
140
141 qDeleteAll(c: d->icon.entries);
142 d->icon = QIconLoader::instance()->loadIcon(iconName: name);
143 if (isComponentComplete())
144 d->updateIcon();
145 emit nameChanged();
146}
147
148QColor QQuickIconImage::color() const
149{
150 Q_D(const QQuickIconImage);
151 return d->color;
152}
153
154void QQuickIconImage::setColor(const QColor &color)
155{
156 Q_D(QQuickIconImage);
157 if (d->color == color)
158 return;
159
160 d->color = color;
161 if (isComponentComplete())
162 d->updateIcon();
163 emit colorChanged();
164}
165
166void QQuickIconImage::setSource(const QUrl &source)
167{
168 Q_D(QQuickIconImage);
169 if (d->source == source)
170 return;
171
172 d->source = source;
173 if (isComponentComplete())
174 d->updateIcon();
175 emit sourceChanged(source);
176}
177
178void QQuickIconImage::componentComplete()
179{
180 Q_D(QQuickIconImage);
181 QQuickImage::componentComplete();
182 d->updateIcon();
183 QObjectPrivate::connect(sender: this, signal: &QQuickImageBase::sourceSizeChanged, receiverPrivate: d, slot: &QQuickIconImagePrivate::updateIcon);
184}
185
186void QQuickIconImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
187{
188 Q_D(QQuickIconImage);
189 QQuickImage::geometryChanged(newGeometry, oldGeometry);
190 if (isComponentComplete() && newGeometry.size() != oldGeometry.size())
191 d->updateIcon();
192}
193
194void QQuickIconImage::itemChange(ItemChange change, const ItemChangeData &value)
195{
196 Q_D(QQuickIconImage);
197 if (change == ItemDevicePixelRatioHasChanged)
198 d->updateIcon();
199 QQuickImage::itemChange(change, value);
200}
201
202void QQuickIconImage::pixmapChange()
203{
204 Q_D(QQuickIconImage);
205 QQuickImage::pixmapChange();
206 d->updateFillMode();
207
208 // Don't apply the color if we're recursing (updateFillMode() can cause us to recurse).
209 if (!d->updatingFillMode && d->color.alpha() > 0) {
210 QImage image = d->pix.image();
211 if (!image.isNull()) {
212 QPainter painter(&image);
213 painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
214 painter.fillRect(image.rect(), color: d->color);
215 d->pix.setImage(image);
216 }
217 }
218}
219
220QT_END_NAMESPACE
221

source code of qtquickcontrols2/src/quickcontrols2/qquickiconimage.cpp