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

KDE's Doxygen guidelines are available online.