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

KDE's Doxygen guidelines are available online.