Kirigami2

icon.cpp
1/*
2 * SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org>
3 * SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8#include "icon.h"
9#include "scenegraph/managedtexturenode.h"
10
11#include "platform/platformtheme.h"
12#include "platform/units.h"
13
14#include <QBitmap>
15#include <QDebug>
16#include <QGuiApplication>
17#include <QIcon>
18#include <QNetworkReply>
19#include <QPainter>
20#include <QPropertyAnimation>
21#include <QQuickImageProvider>
22#include <QQuickWindow>
23#include <QSGSimpleTextureNode>
24#include <QSGTexture>
25#include <QScreen>
26
27Q_GLOBAL_STATIC(ImageTexturesCache, s_iconImageCache)
28
29Icon::Icon(QQuickItem *parent)
30 : QQuickItem(parent)
31 , m_active(false)
32 , m_selected(false)
33 , m_isMask(false)
34{
35 setFlag(ItemHasContents, true);
36 // Using 32 because Icon used to redefine implicitWidth and implicitHeight and hardcode them to 32
37 setImplicitSize(32, 32);
38
40 connect(this, &QQuickItem::enabledChanged, this, [this]() {
41 polish();
42 });
43}
44
45Icon::~Icon()
46{
47}
48
49void Icon::componentComplete()
50{
52
53 QQmlEngine *engine = qmlEngine(this);
54 Q_ASSERT(engine);
55 m_units = engine->singletonInstance<Kirigami::Platform::Units *>("org.kde.kirigami.platform", "Units");
56 Q_ASSERT(m_units);
57 m_animation = new QPropertyAnimation(this);
58 connect(m_animation, &QPropertyAnimation::valueChanged, this, &Icon::valueChanged);
59 connect(m_animation, &QPropertyAnimation::finished, this, [this]() {
60 m_oldIcon = QImage();
61 m_textureChanged = true;
62 update();
63 });
64 m_animation->setTargetObject(this);
65 m_animation->setEasingCurve(QEasingCurve::InOutCubic);
66 m_animation->setDuration(m_units->longDuration());
67 connect(m_units, &Kirigami::Platform::Units::longDurationChanged, m_animation, [this]() {
68 m_animation->setDuration(m_units->longDuration());
69 });
70 updatePaintedGeometry();
71}
72
73void Icon::setSource(const QVariant &icon)
74{
75 if (m_source == icon) {
76 return;
77 }
78 m_source = icon;
79
80 if (!m_theme) {
81 m_theme = static_cast<Kirigami::Platform::PlatformTheme *>(qmlAttachedPropertiesObject<Kirigami::Platform::PlatformTheme>(this, true));
82 Q_ASSERT(m_theme);
83
84 connect(m_theme, &Kirigami::Platform::PlatformTheme::colorsChanged, this, &QQuickItem::polish);
85 }
86
87 if (m_networkReply) {
88 // if there was a network query going on, interrupt it
89 m_networkReply->close();
90 }
91 m_loadedImage = QImage();
92 setStatus(Loading);
93
94 polish();
95 Q_EMIT sourceChanged();
96 Q_EMIT validChanged();
97}
98
100{
101 return m_source;
102}
103
104void Icon::setActive(const bool active)
105{
106 if (active == m_active) {
107 return;
108 }
109 m_active = active;
110 polish();
111 Q_EMIT activeChanged();
112}
113
114bool Icon::active() const
115{
116 return m_active;
117}
118
119bool Icon::valid() const
120{
121 // TODO: should this be return m_status == Ready?
122 // Consider an empty URL invalid, even though isNull() will say false
123 if (m_source.canConvert<QUrl>() && m_source.toUrl().isEmpty()) {
124 return false;
125 }
126
127 return !m_source.isNull();
128}
129
130void Icon::setSelected(const bool selected)
131{
132 if (selected == m_selected) {
133 return;
134 }
135 m_selected = selected;
136 polish();
137 Q_EMIT selectedChanged();
138}
139
140bool Icon::selected() const
141{
142 return m_selected;
143}
144
145void Icon::setIsMask(bool mask)
146{
147 if (m_isMask == mask) {
148 return;
149 }
150
151 m_isMask = mask;
152 polish();
153 Q_EMIT isMaskChanged();
154}
155
156bool Icon::isMask() const
157{
158 return m_isMask;
159}
160
161void Icon::setColor(const QColor &color)
162{
163 if (m_color == color) {
164 return;
165 }
166
167 m_color = color;
168 polish();
169 Q_EMIT colorChanged();
170}
171
172QColor Icon::color() const
173{
174 return m_color;
175}
176
177QSGNode *Icon::createSubtree(qreal initialOpacity)
178{
179 auto opacityNode = new QSGOpacityNode{};
180 opacityNode->setFlag(QSGNode::OwnedByParent, true);
181 opacityNode->setOpacity(initialOpacity);
182
183 auto *mNode = new ManagedTextureNode;
184
185 mNode->setTexture(s_iconImageCache->loadTexture(window(), m_icon, QQuickWindow::TextureCanUseAtlas));
186
187 opacityNode->appendChildNode(mNode);
188
189 return opacityNode;
190}
191
192void Icon::updateSubtree(QSGNode *node, qreal opacity)
193{
194 auto opacityNode = static_cast<QSGOpacityNode *>(node);
195 opacityNode->setOpacity(opacity);
196
197 auto textureNode = static_cast<ManagedTextureNode *>(opacityNode->firstChild());
198 textureNode->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
199}
200
201QSGNode *Icon::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData * /*data*/)
202{
203 if (m_source.isNull() || qFuzzyIsNull(width()) || qFuzzyIsNull(height())) {
204 delete node;
205 return nullptr;
206 }
207
208 if (!node) {
209 node = new QSGNode{};
210 }
211
212 if (m_animation && m_animation->state() == QAbstractAnimation::Running) {
213 if (node->childCount() < 2) {
214 node->appendChildNode(createSubtree(0.0));
215 m_textureChanged = true;
216 }
217
218 // Rather than doing a perfect crossfade, first fade in the new texture
219 // then fade out the old texture. This is done to avoid the underlying
220 // color bleeding through when both textures are at ~0.5 opacity, which
221 // causes flickering if the two textures are very similar.
222 updateSubtree(node->firstChild(), 2.0 - m_animValue * 2.0);
223 updateSubtree(node->lastChild(), m_animValue * 2.0);
224 } else {
225 if (node->childCount() == 0) {
226 node->appendChildNode(createSubtree(1.0));
227 m_textureChanged = true;
228 }
229
230 if (node->childCount() > 1) {
231 auto toRemove = node->firstChild();
232 node->removeChildNode(toRemove);
233 delete toRemove;
234 }
235
236 updateSubtree(node->firstChild(), 1.0);
237 }
238
239 if (m_textureChanged) {
240 auto mNode = static_cast<ManagedTextureNode *>(node->lastChild()->firstChild());
241 mNode->setTexture(s_iconImageCache->loadTexture(window(), m_icon, QQuickWindow::TextureCanUseAtlas));
242 m_textureChanged = false;
243 m_sizeChanged = true;
244 }
245
246 if (m_sizeChanged) {
247 const QSizeF iconPixSize(m_icon.width() / m_devicePixelRatio, m_icon.height() / m_devicePixelRatio);
248 const QSizeF itemPixSize = QSizeF((size() * m_devicePixelRatio).toSize()) / m_devicePixelRatio;
249 QRectF nodeRect(QPoint(0, 0), itemPixSize);
250
251 if (itemPixSize.width() != 0 && itemPixSize.height() != 0) {
252 if (iconPixSize != itemPixSize) {
253 // At this point, the image will already be scaled, but we need to output it in
254 // the correct aspect ratio, painted centered in the viewport. So:
255 QRectF destination(QPointF(0, 0), QSizeF(m_icon.size()).scaled(m_paintedSize, Qt::KeepAspectRatio));
256 destination.moveCenter(nodeRect.center());
257 destination.moveTopLeft(QPointF(destination.topLeft().toPoint() * m_devicePixelRatio) / m_devicePixelRatio);
258 nodeRect = destination;
259 }
260 }
261
262 for (int i = 0; i < node->childCount(); ++i) {
263 auto mNode = static_cast<ManagedTextureNode *>(node->childAtIndex(i)->firstChild());
264 mNode->setRect(nodeRect);
265 }
266
267 m_sizeChanged = false;
268 }
269
270 return node;
271}
272
273void Icon::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
274{
275 QQuickItem::geometryChange(newGeometry, oldGeometry);
276 if (newGeometry.size() != oldGeometry.size()) {
277 m_sizeChanged = true;
278 updatePaintedGeometry();
279 polish();
280 }
281}
282
283void Icon::handleRedirect(QNetworkReply *reply)
284{
285 QNetworkAccessManager *qnam = reply->manager();
286 if (reply->error() != QNetworkReply::NoError) {
287 return;
288 }
289 const QUrl possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
290 if (!possibleRedirectUrl.isEmpty()) {
291 const QUrl redirectUrl = reply->url().resolved(possibleRedirectUrl);
292 if (redirectUrl == reply->url()) {
293 // no infinite redirections thank you very much
294 reply->deleteLater();
295 return;
296 }
297 reply->deleteLater();
298 QNetworkRequest request(possibleRedirectUrl);
300 m_networkReply = qnam->get(request);
301 connect(m_networkReply.data(), &QNetworkReply::finished, this, [this]() {
302 handleFinished(m_networkReply);
303 });
304 }
305}
306
307void Icon::handleFinished(QNetworkReply *reply)
308{
309 if (!reply) {
310 return;
311 }
312
313 reply->deleteLater();
315 handleRedirect(reply);
316 return;
317 }
318
319 m_loadedImage = QImage();
320
321 const QString filename = reply->url().fileName();
322 if (!m_loadedImage.load(reply, filename.mid(filename.indexOf(QLatin1Char('.'))).toLatin1().constData())) {
323 // broken image from data, inform the user of this with some useful broken-image thing...
324 m_loadedImage = iconPixmap(QIcon::fromTheme(m_fallback));
325 }
326
327 polish();
328}
329
330void Icon::updatePolish()
331{
333
334 if (window()) {
335 m_devicePixelRatio = window()->effectiveDevicePixelRatio();
336 }
337
338 if (m_source.isNull()) {
339 setStatus(Ready);
340 updatePaintedGeometry();
341 update();
342 return;
343 }
344
345 const QSize itemSize(width(), height());
346 if (itemSize.width() != 0 && itemSize.height() != 0) {
347 const QSize size = itemSize;
348
349 if (m_animation) {
350 m_animation->stop();
351 m_oldIcon = m_icon;
352 }
353
354 switch (m_source.userType()) {
356 m_icon = m_source.value<QPixmap>().toImage();
357 break;
359 m_icon = m_source.value<QImage>();
360 break;
362 m_icon = m_source.value<QBitmap>().toImage();
363 break;
364 case QMetaType::QIcon: {
365 m_icon = iconPixmap(m_source.value<QIcon>());
366 break;
367 }
368 case QMetaType::QUrl:
370 m_icon = findIcon(size);
371 break;
373 // todo: fill here too?
375 m_icon = QImage(size, QImage::Format_Alpha8);
376 m_icon.fill(m_source.value<QColor>());
377 break;
378 default:
379 break;
380 }
381
382 if (m_icon.isNull()) {
383 m_icon = QImage(size, QImage::Format_Alpha8);
384 m_icon.fill(Qt::transparent);
385 }
386
387 const QColor tintColor = //
388 !m_color.isValid() || m_color == Qt::transparent //
389 ? (m_selected ? m_theme->highlightedTextColor() : m_theme->textColor())
390 : m_color;
391
392 // TODO: initialize m_isMask with icon.isMask()
393 if (tintColor.alpha() > 0 && isMask()) {
394 QPainter p(&m_icon);
395 p.setCompositionMode(QPainter::CompositionMode_SourceIn);
396 p.fillRect(m_icon.rect(), tintColor);
397 p.end();
398 }
399 }
400
401 // don't animate initial setting
402 bool animated = m_animated && !m_oldIcon.isNull() && !m_sizeChanged && !m_blockNextAnimation;
403
404 if (animated && m_animation) {
405 m_animValue = 0.0;
406 m_animation->setStartValue((qreal)0);
407 m_animation->setEndValue((qreal)1);
408 m_animation->start();
409 } else {
410 if (m_animation) {
411 m_animation->stop();
412 }
413 m_animValue = 1.0;
414 m_blockNextAnimation = false;
415 }
416 m_textureChanged = true;
417 updatePaintedGeometry();
418 update();
419}
420
421QImage Icon::findIcon(const QSize &size)
422{
423 QImage img;
424 QString iconSource = m_source.toString();
425
426 if (iconSource.startsWith(QLatin1String("image://"))) {
427 QUrl iconUrl(iconSource);
428 QString iconProviderId = iconUrl.host();
429 // QUrl path has the "/" prefix while iconId does not
430 QString iconId = iconUrl.path().remove(0, 1);
431
432 QSize actualSize;
433 auto engine = qmlEngine(this);
434 if (!engine) {
435 return img;
436 }
437 QQuickImageProvider *imageProvider = dynamic_cast<QQuickImageProvider *>(engine->imageProvider(iconProviderId));
438 if (!imageProvider) {
439 return img;
440 }
441 switch (imageProvider->imageType()) {
443 img = imageProvider->requestImage(iconId, &actualSize, size);
444 if (!img.isNull()) {
445 setStatus(Ready);
446 }
447 break;
449 img = imageProvider->requestPixmap(iconId, &actualSize, size).toImage();
450 if (!img.isNull()) {
451 setStatus(Ready);
452 }
453 break;
455 if (!m_loadedImage.isNull()) {
456 setStatus(Ready);
458 }
459 QQuickAsyncImageProvider *provider = dynamic_cast<QQuickAsyncImageProvider *>(imageProvider);
460 auto response = provider->requestImageResponse(iconId, size);
461 connect(response, &QQuickImageResponse::finished, this, [iconId, response, this]() {
462 if (response->errorString().isEmpty()) {
463 QQuickTextureFactory *textureFactory = response->textureFactory();
464 if (textureFactory) {
465 m_loadedImage = textureFactory->image();
466 delete textureFactory;
467 }
468 if (m_loadedImage.isNull()) {
469 // broken image from data, inform the user of this with some useful broken-image thing...
470 m_loadedImage = iconPixmap(QIcon::fromTheme(m_fallback));
471 setStatus(Error);
472 } else {
473 setStatus(Ready);
474 }
475 polish();
476 }
477 response->deleteLater();
478 });
479 // Temporary icon while we wait for the real image to load...
480 img = iconPixmap(QIcon::fromTheme(m_placeholder));
481 break;
482 }
484 QQuickTextureFactory *textureFactory = imageProvider->requestTexture(iconId, &actualSize, size);
485 if (textureFactory) {
486 img = textureFactory->image();
487 }
488 if (img.isNull()) {
489 // broken image from data, or the texture factory wasn't healthy, inform the user of this with some useful broken-image thing...
490 img = iconPixmap(QIcon::fromTheme(m_fallback));
491 setStatus(Error);
492 } else {
493 setStatus(Ready);
494 }
495 break;
496 }
498 // will have to investigate this more
499 setStatus(Error);
500 break;
501 }
502 } else if (iconSource.startsWith(QLatin1String("http://")) || iconSource.startsWith(QLatin1String("https://"))) {
503 if (!m_loadedImage.isNull()) {
504 setStatus(Ready);
506 }
507 const auto url = m_source.toUrl();
508 QQmlEngine *engine = qmlEngine(this);
509 QNetworkAccessManager *qnam;
510 if (engine && (qnam = engine->networkAccessManager()) && (!m_networkReply || m_networkReply->url() != url)) {
511 QNetworkRequest request(url);
513 m_networkReply = qnam->get(request);
514 connect(m_networkReply.data(), &QNetworkReply::finished, this, [this]() {
515 handleFinished(m_networkReply);
516 });
517 }
518 // Temporary icon while we wait for the real image to load...
519 img = iconPixmap(QIcon::fromTheme(m_placeholder));
520 } else {
521 if (iconSource.startsWith(QLatin1String("qrc:/"))) {
522 iconSource = iconSource.mid(3);
523 } else if (iconSource.startsWith(QLatin1String("file:/"))) {
524 iconSource = QUrl(iconSource).path();
525 }
526
527 const QIcon icon = loadFromTheme(iconSource);
528
529 if (!icon.isNull()) {
530 img = iconPixmap(icon);
531 setStatus(Ready);
532 }
533 }
534
535 if (!iconSource.isEmpty() && img.isNull()) {
536 setStatus(Error);
537 img = iconPixmap(QIcon::fromTheme(m_fallback));
538 }
539 return img;
540}
541
542QIcon::Mode Icon::iconMode() const
543{
544 if (!isEnabled()) {
545 return QIcon::Disabled;
546 } else if (m_selected) {
547 return QIcon::Selected;
548 } else if (m_active) {
549 return QIcon::Active;
550 }
551 return QIcon::Normal;
552}
553
555{
556 return m_fallback;
557}
558
559void Icon::setFallback(const QString &fallback)
560{
561 if (m_fallback != fallback) {
562 m_fallback = fallback;
563 Q_EMIT fallbackChanged(fallback);
564 }
565}
566
568{
569 return m_placeholder;
570}
571
572void Icon::setPlaceholder(const QString &placeholder)
573{
574 if (m_placeholder != placeholder) {
575 m_placeholder = placeholder;
576 Q_EMIT placeholderChanged(placeholder);
577 }
578}
579
580void Icon::setStatus(Status status)
581{
582 if (status == m_status) {
583 return;
584 }
585
586 m_status = status;
587 Q_EMIT statusChanged();
588}
589
591{
592 return m_status;
593}
594
595qreal Icon::paintedWidth() const
596{
597 return std::round(m_paintedSize.width());
598}
599
600qreal Icon::paintedHeight() const
601{
602 return std::round(m_paintedSize.height());
603}
604
605QSize Icon::iconSizeHint() const
606{
607 if (!m_roundToIconSize) {
608 return QSize(width(), height());
609 } else if (m_units) {
610 return QSize(m_units->iconSizes()->roundedIconSize(std::min(width(), height())), m_units->iconSizes()->roundedIconSize(std::min(width(), height())));
611 } else {
612 return QSize(std::min(width(), height()), std::min(width(), height()));
613 }
614}
615
616QImage Icon::iconPixmap(const QIcon &icon) const
617{
618 const QSize actualSize = icon.actualSize(iconSizeHint());
619 QIcon sourceIcon = icon;
620
621 // if we have a non-default theme we need to load the icon with
622 // the right colors
623 const QQmlEngine *engine = qmlEngine(this);
624 if (engine && !engine->property("_kirigamiTheme").toString().isEmpty()) {
625 const QString iconName = icon.name();
626 if (!iconName.isEmpty() && QIcon::hasThemeIcon(iconName)) {
627 sourceIcon = loadFromTheme(iconName);
628 }
629 }
630
631 return sourceIcon.pixmap(actualSize, m_devicePixelRatio, iconMode(), QIcon::On).toImage();
632}
633
634QIcon Icon::loadFromTheme(const QString &iconName) const
635{
636 const QColor tintColor = !m_color.isValid() || m_color == Qt::transparent ? (m_selected ? m_theme->highlightedTextColor() : m_theme->textColor()) : m_color;
637 return m_theme->iconFromTheme(iconName, tintColor);
638}
639
640void Icon::updatePaintedGeometry()
641{
642 QSizeF newSize;
643 if (!m_icon.width() || !m_icon.height()) {
644 newSize = {0, 0};
645 } else {
646 qreal roundedWidth = m_units ? m_units->iconSizes()->roundedIconSize(std::min(width(), height())) : 32;
647 roundedWidth = std::round(roundedWidth * m_devicePixelRatio) / m_devicePixelRatio;
648
649 if (QSizeF roundedSize(roundedWidth, roundedWidth); size() == roundedSize) {
650 m_paintedSize = roundedSize;
651 m_textureChanged = true;
652 update();
653 Q_EMIT paintedAreaChanged();
654 return;
655 }
656 if (m_roundToIconSize && m_units) {
657 if (m_icon.width() > m_icon.height()) {
658 newSize = QSizeF(roundedWidth, m_icon.height() * (roundedWidth / static_cast<qreal>(m_icon.width())));
659 } else {
660 newSize = QSizeF(roundedWidth, roundedWidth);
661 }
662 } else {
663 const QSizeF iconPixSize(m_icon.width() / m_devicePixelRatio, m_icon.height() / m_devicePixelRatio);
664
665 const qreal w = widthValid() ? width() : iconPixSize.width();
666 const qreal widthScale = w / iconPixSize.width();
667 const qreal h = heightValid() ? height() : iconPixSize.height();
668 const qreal heightScale = h / iconPixSize.height();
669
670 if (widthScale <= heightScale) {
671 newSize = QSizeF(w, widthScale * iconPixSize.height());
672 } else if (heightScale < widthScale) {
673 newSize = QSizeF(heightScale * iconPixSize.width(), h);
674 }
675 }
676 }
677 if (newSize != m_paintedSize) {
678 m_paintedSize = newSize;
679 m_textureChanged = true;
680 update();
681 Q_EMIT paintedAreaChanged();
682 }
683}
684
685bool Icon::isAnimated() const
686{
687 return m_animated;
688}
689
690void Icon::setAnimated(bool animated)
691{
692 if (m_animated == animated) {
693 return;
694 }
695
696 m_animated = animated;
697 Q_EMIT animatedChanged();
698}
699
700bool Icon::roundToIconSize() const
701{
702 return m_roundToIconSize;
703}
704
705void Icon::setRoundToIconSize(bool roundToIconSize)
706{
707 if (m_roundToIconSize == roundToIconSize) {
708 return;
709 }
710
711 const QSizeF oldPaintedSize = m_paintedSize;
712
713 m_roundToIconSize = roundToIconSize;
714 Q_EMIT roundToIconSizeChanged();
715
716 updatePaintedGeometry();
717 if (oldPaintedSize != m_paintedSize) {
718 Q_EMIT paintedAreaChanged();
719 m_textureChanged = true;
720 update();
721 }
722}
723
724void Icon::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
725{
727 m_blockNextAnimation = true;
728 if (window()) {
729 m_devicePixelRatio = window()->effectiveDevicePixelRatio();
730 }
731 polish();
732 } else if (change == QQuickItem::ItemSceneChange) {
733 if (m_window) {
734 disconnect(m_window.data(), &QWindow::visibleChanged, this, &Icon::windowVisibleChanged);
735 }
736 m_window = value.window;
737 if (m_window) {
738 connect(m_window.data(), &QWindow::visibleChanged, this, &Icon::windowVisibleChanged);
739 m_devicePixelRatio = m_window->effectiveDevicePixelRatio();
740 }
741 } else if (change == ItemVisibleHasChanged && value.boolValue) {
742 m_blockNextAnimation = true;
743 }
744 QQuickItem::itemChange(change, value);
745}
746
747void Icon::valueChanged(const QVariant &value)
748{
749 m_animValue = value.toReal();
750 update();
751}
752
753void Icon::windowVisibleChanged(bool visible)
754{
755 if (visible) {
756 m_blockNextAnimation = true;
757 }
758}
759
760#include "moc_icon.cpp"
qreal paintedHeight
The height of the painted area measured in pixels.
Definition icon.h:163
QString placeholder
The name of an icon from the icon theme to show while the icon set in source is being loaded.
Definition icon.h:88
qreal paintedWidth
The width of the painted area measured in pixels.
Definition icon.h:155
bool selected
Whether this icon will use the QIcon::Selected mode when drawing the icon, resulting in a graphical e...
Definition icon.h:122
bool valid
Whether this icon's source is valid and it is being used.
Definition icon.h:108
bool animated
If set, icon will blend when the source is changed.
Definition icon.h:168
QColor color
The color to use when drawing this icon when isMask is enabled.
Definition icon.h:139
Icon::Status status
Whether the icon is correctly loaded, is asynchronously loading or there was an error.
Definition icon.h:147
bool roundToIconSize
If set, icon will round the painted size to defined icon sizes.
Definition icon.h:173
Status
Definition icon.h:176
@ Ready
No icon has been set.
Definition icon.h:178
@ Loading
The icon loaded correctly.
Definition icon.h:179
QString fallback
The name of a fallback icon to load from the icon theme when the source cannot be found.
Definition icon.h:75
QML_ELEMENTQVariant source
The source of this icon.
Definition icon.h:65
bool isMask
Whether this icon will be treated as a mask.
Definition icon.h:131
bool active
Whether this icon will use the QIcon::Active mode when drawing the icon, resulting in a graphical eff...
Definition icon.h:103
Q_SCRIPTABLE CaptureState status()
QAction * actualSize(const QObject *recvr, const char *slot, QObject *parent)
int alpha() const const
bool isValid() const const
QSize actualSize(QWindow *window, const QSize &size, Mode mode, State state) const const
QPixmap pixmap(QWindow *window, const QSize &size, Mode mode, State state) const const
QIcon fromTheme(const QString &name)
bool hasThemeIcon(const QString &name)
bool isNull() const const
QString name() const const
bool isNull() const const
QNetworkReply * get(const QNetworkRequest &request)
QVariant attribute(QNetworkRequest::Attribute code) const const
NetworkError error() const const
QNetworkAccessManager * manager() const const
QUrl url() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
bool disconnect(const QMetaObject::Connection &connection)
QVariant property(const char *name) const const
CompositionMode_SourceIn
QImage toImage() const const
QQmlImageProviderBase * imageProvider(const QString &providerId) const const
QNetworkAccessManager * networkAccessManager() const const
T singletonInstance(QAnyStringView uri, QAnyStringView typeName)
virtual QQuickImageResponse * requestImageResponse(const QString &id, const QSize &requestedSize)=0
virtual ImageType imageType() const const override
virtual QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)
virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
virtual QQuickTextureFactory * requestTexture(const QString &id, QSize *size, const QSize &requestedSize)
virtual void componentComplete() override
void enabledChanged()
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
bool heightValid() const const
virtual void itemChange(ItemChange change, const ItemChangeData &value)
void polish()
QSizeF size() const const
void smoothChanged(bool)
void update()
virtual void updatePolish()
bool widthValid() const const
QQuickWindow * window() const const
virtual QImage image() const const
qreal effectiveDevicePixelRatio() const const
QSizeF size() const const
void appendChildNode(QSGNode *node)
QSGNode * childAtIndex(int i) const const
int childCount() const const
QSGNode * firstChild() const const
QSGNode * lastChild() const const
void removeChildNode(QSGNode *node)
void setFlag(Flag f, bool enabled)
qreal height() const const
qreal width() const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString mid(qsizetype position, qsizetype n) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
KeepAspectRatio
transparent
SmoothTransformation
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString fileName(ComponentFormattingOptions options) const const
bool isEmpty() const const
QUrl resolved(const QUrl &relative) const const
bool isNull() const const
qreal toReal(bool *ok) const const
QString toString() const const
QUrl toUrl() const const
void valueChanged(const QVariant &value)
void visibleChanged(bool arg)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 7 2025 11:48:08 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.