diff --git a/kirigami.pro b/kirigami.pro index ab61b2fe..78d38bad 100644 --- a/kirigami.pro +++ b/kirigami.pro @@ -1,35 +1,52 @@ TEMPLATE = lib -CONFIG += plugin - -QT += qml quick gui svg -HEADERS += $$PWD/src/kirigamiplugin.h $$PWD/src/enums.h $$PWD/src/settings.h -SOURCES += $$PWD/src/kirigamiplugin.cpp $$PWD/src/enums.cpp $$PWD/src/settings.cpp +CONFIG += static plugin + +QT += qml quick gui quickcontrols2 svg +URI = org.kde.kirigami +QMAKE_MOC_OPTIONS += -Muri=org.kde.kirigami +HEADERS += $$PWD/src/kirigamiplugin.h \ + $$PWD/src/enums.h \ + $$PWD/src/settings.h \ + $$PWD/src/mnemonicattached.h \ + $$PWD/src/formlayoutattached.h \ + $$PWD/src/libkirigami/basictheme_p.h \ + $$PWD/src/libkirigami/kirigamipluginfactory.h \ + $$PWD/src/libkirigami/platformtheme.h +SOURCES += $$PWD/src/kirigamiplugin.cpp \ + $$PWD/src/enums.cpp \ + $$PWD/src/settings.cpp \ + $$PWD/src/mnemonicattached.cpp \ + $$PWD/src/formlayoutattached.cpp \ + $$PWD/src/libkirigami/basictheme.cpp \ + $$PWD/src/libkirigami/kirigamipluginfactory.cpp \ + $$PWD/src/libkirigami/platformtheme.cpp RESOURCES += $$PWD/kirigami.qrc +DEFINES += KIRIGAMI_BUILD_TYPE_STATIC !ios:!android { message( "compiling for desktop" ) HEADERS += $$PWD/src/desktopicon.h SOURCES += $$PWD/src/desktopicon.cpp } API_VER=1.0 TARGET = $$qtLibraryTarget(org/kde/kirigami.2/kirigamiplugin) importPath = $$[QT_INSTALL_QML]/org/kde/kirigami.2 target.path = $${importPath} controls.path = $${importPath} controls.files += $$PWD/src/controls/* #For now ignore Desktop and Plasma stuff in qmake styles.path = $${importPath}/styles styles.files += $$PWD/src/styles/* INSTALLS += target controls styles diff --git a/src/desktopicon.cpp b/src/desktopicon.cpp index 1e6c6ad5..dd16a081 100644 --- a/src/desktopicon.cpp +++ b/src/desktopicon.cpp @@ -1,484 +1,484 @@ /* * Copyright 2011 Marco Martin * Copyright 2014 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "desktopicon.h" -#include "platformtheme.h" +#include "libkirigami/platformtheme.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include class ManagedTextureNode : public QSGSimpleTextureNode { Q_DISABLE_COPY(ManagedTextureNode) public: ManagedTextureNode(); void setTexture(QSharedPointer texture); private: QSharedPointer m_texture; }; ManagedTextureNode::ManagedTextureNode() {} void ManagedTextureNode::setTexture(QSharedPointer texture) { m_texture = texture; QSGSimpleTextureNode::setTexture(texture.data()); } typedef QHash > > TexturesCache; struct ImageTexturesCachePrivate { TexturesCache cache; }; class ImageTexturesCache { public: ImageTexturesCache(); ~ImageTexturesCache(); /** * @returns the texture for a given @p window and @p image. * * If an @p image id is the same as one already provided before, we won't create * a new texture and return a shared pointer to the existing texture. */ QSharedPointer loadTexture(QQuickWindow *window, const QImage &image, QQuickWindow::CreateTextureOptions options); QSharedPointer loadTexture(QQuickWindow *window, const QImage &image); private: QScopedPointer d; }; ImageTexturesCache::ImageTexturesCache() : d(new ImageTexturesCachePrivate) { } ImageTexturesCache::~ImageTexturesCache() { } QSharedPointer ImageTexturesCache::loadTexture(QQuickWindow *window, const QImage &image, QQuickWindow::CreateTextureOptions options) { qint64 id = image.cacheKey(); QSharedPointer texture = d->cache.value(id).value(window).toStrongRef(); if (!texture) { auto cleanAndDelete = [this, window, id](QSGTexture* texture) { QHash >& textures = (d->cache)[id]; textures.remove(window); if (textures.isEmpty()) d->cache.remove(id); delete texture; }; texture = QSharedPointer(window->createTextureFromImage(image, options), cleanAndDelete); (d->cache)[id][window] = texture.toWeakRef(); } //if we have a cache in an atlas but our request cannot use an atlassed texture //create a new texture and use that //don't use removedFromAtlas() as that requires keeping a reference to the non atlased version if (!(options & QQuickWindow::TextureCanUseAtlas) && texture->isAtlasTexture()) { texture = QSharedPointer(window->createTextureFromImage(image, options)); } return texture; } QSharedPointer ImageTexturesCache::loadTexture(QQuickWindow *window, const QImage &image) { return loadTexture(window, image, 0); } Q_GLOBAL_STATIC(ImageTexturesCache, s_iconImageCache) DesktopIcon::DesktopIcon(QQuickItem *parent) : QQuickItem(parent), m_smooth(false), m_changed(false), m_active(false), m_selected(false), m_isMask(false) { setFlag(ItemHasContents, true); //FIXME: not necessary anymore connect(qApp, &QGuiApplication::paletteChanged, this, [this]() { m_changed = true; update(); }); } DesktopIcon::~DesktopIcon() { } void DesktopIcon::setSource(const QVariant &icon) { if (m_source == icon) { return; } m_source = icon; m_changed = true; if (!m_theme) { m_theme = static_cast(qmlAttachedPropertiesObject(this, true)); Q_ASSERT(m_theme); connect(m_theme, &Kirigami::PlatformTheme::colorsChanged, this, [this]() { m_changed = true; update(); }); } update(); emit sourceChanged(); } QVariant DesktopIcon::source() const { return m_source; } void DesktopIcon::setEnabled(const bool enabled) { if (enabled == QQuickItem::isEnabled()) { return; } QQuickItem::setEnabled(enabled); m_changed = true; update(); emit enabledChanged(); } void DesktopIcon::setActive(const bool active) { if (active == m_active) { return; } m_active = active; m_changed = true; update(); emit activeChanged(); } bool DesktopIcon::active() const { return m_active; } bool DesktopIcon::valid() const { return !m_source.isNull(); } void DesktopIcon::setSelected(const bool selected) { if (selected == m_selected) { return; } m_selected = selected; m_changed = true; update(); emit selectedChanged(); } bool DesktopIcon::selected() const { return m_selected; } void DesktopIcon::setIsMask(bool mask) { if (m_isMask == mask) { return; } m_isMask = mask; emit isMaskChanged(); } bool DesktopIcon::isMask() const { return m_isMask; } void DesktopIcon::setColor(const QColor &color) { if (m_color == color) { return; } m_color = color; emit colorChanged(); } QColor DesktopIcon::color() const { return m_color; } int DesktopIcon::implicitWidth() const { return 32; } int DesktopIcon::implicitHeight() const { return 32; } void DesktopIcon::setSmooth(const bool smooth) { if (smooth == m_smooth) { return; } m_smooth = smooth; m_changed = true; update(); emit smoothChanged(); } bool DesktopIcon::smooth() const { return m_smooth; } QSGNode* DesktopIcon::updatePaintNode(QSGNode* node, QQuickItem::UpdatePaintNodeData* /*data*/) { if (m_source.isNull()) { delete node; return Q_NULLPTR; } if (m_changed || node == 0) { QImage img; const QSize itemSize(width(), height()); QRect nodeRect(QPoint(0,0), itemSize); if (itemSize.width() != 0 && itemSize.height() != 0) { const QSize size = itemSize * (window() ? window()->devicePixelRatio() : qApp->devicePixelRatio()); switch(m_source.type()){ case QVariant::Pixmap: img = m_source.value().toImage(); break; case QVariant::Image: img = m_source.value(); break; case QVariant::Bitmap: img = m_source.value().toImage(); break; case QVariant::Icon: img = m_source.value().pixmap(size, iconMode(), QIcon::On).toImage(); break; case QVariant::Url: case QVariant::String: img = findIcon(size); break; case QVariant::Brush: //todo: fill here too? case QVariant::Color: img = QImage(size, QImage::Format_Alpha8); img.fill(m_source.value()); break; default: break; } if (img.isNull()){ img = QImage(size, QImage::Format_Alpha8); img.fill(Qt::transparent); } if (img.size() != size){ // At this point, the image will already be scaled, but we need to output it in // the correct aspect ratio, painted centered in the viewport. So: QRect destination(QPoint(0, 0), img.size().scaled(itemSize, Qt::KeepAspectRatio)); destination.moveCenter(nodeRect.center()); nodeRect = destination; } } m_changed = false; ManagedTextureNode* mNode = dynamic_cast(node); if (!mNode) { delete node; mNode = new ManagedTextureNode; } mNode->setTexture(s_iconImageCache->loadTexture(window(), img)); mNode->setRect(nodeRect); node = mNode; } return node; } void DesktopIcon::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { if (newGeometry.size() != oldGeometry.size()) { m_changed = true; update(); } QQuickItem::geometryChanged(newGeometry, oldGeometry); } void DesktopIcon::handleFinished(QNetworkAccessManager* qnam, QNetworkReply* reply) { if (reply->error() == QNetworkReply::NoError) { const QUrl possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); if (!possibleRedirectUrl.isEmpty()) { const QUrl redirectUrl = reply->url().resolved(possibleRedirectUrl); if (redirectUrl == reply->url()) { // no infinite redirections thank you very much reply->deleteLater(); return; } reply->deleteLater(); QNetworkRequest request(possibleRedirectUrl); request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); QNetworkReply* newReply = qnam->get(request); connect(newReply, &QNetworkReply::readyRead, this, [this, newReply](){ handleReadyRead(newReply); }); connect(newReply, &QNetworkReply::finished, this, [this, qnam, newReply](){ handleFinished(qnam, newReply); }); return; } } } void DesktopIcon::handleReadyRead(QNetworkReply* reply) { if (reply->attribute(QNetworkRequest::RedirectionTargetAttribute).isNull()) { // We're handing the event loop back while doing network work, and it turns out // this fairly regularly results in things being deleted under us. So, just // handle that and crash less :) QPointer me(this); QByteArray data; do { data.append(reply->read(32768)); // Because we are in the main thread, this could be potentially very expensive, so let's not block qApp->processEvents(); if(!me) { return; } } while(!reply->atEnd()); m_loadedImage = QImage::fromData(data); if (m_loadedImage.isNull()) { // broken image from data, inform the user of this with some useful broken-image thing... const QSize size = QSize(width(), height()) * (window() ? window()->devicePixelRatio() : qApp->devicePixelRatio()); m_loadedImage = QIcon::fromTheme("unknown").pixmap(size, iconMode(), QIcon::On).toImage(); } m_changed = true; update(); } } QImage DesktopIcon::findIcon(const QSize &size) { QImage img; QString iconSource = m_source.toString(); if (iconSource.startsWith("image://")){ QUrl iconUrl(iconSource); QString iconProviderId = iconUrl.host(); QString iconId = iconUrl.path(); QSize actualSize; QQuickImageProvider* imageProvider = dynamic_cast( qmlEngine(this)->imageProvider(iconProviderId)); if (!imageProvider) return img; switch(imageProvider->imageType()){ case QQmlImageProviderBase::Image: img = imageProvider->requestImage(iconId, &actualSize, size); break; case QQmlImageProviderBase::Pixmap: img = imageProvider->requestPixmap(iconId, &actualSize, size).toImage(); break; case QQmlImageProviderBase::Texture: case QQmlImageProviderBase::Invalid: case QQmlImageProviderBase::ImageResponse: //will have to investigate this more break; } } else if(iconSource.startsWith("http://") || iconSource.startsWith("https://")) { if(!m_loadedImage.isNull()) { return m_loadedImage.scaled(size, Qt::KeepAspectRatio, m_smooth ? Qt::SmoothTransformation : Qt::FastTransformation ); } QQmlEngine* engine = qmlEngine(this); QNetworkAccessManager* qnam; if (engine && (qnam = qmlEngine(this)->networkAccessManager())) { QNetworkRequest request(m_source.toUrl()); request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); QNetworkReply* reply = qnam->get(request); connect(reply, &QNetworkReply::readyRead, this, [this, reply](){ handleReadyRead(reply); }); connect(reply, &QNetworkReply::finished, this, [this, qnam, reply](){ handleFinished(qnam, reply); }); } // Temporary icon while we wait for the real image to load... img = QIcon::fromTheme("image-x-icon").pixmap(size, iconMode(), QIcon::On).toImage(); } else { if (iconSource.startsWith("qrc:/")){ iconSource = iconSource.mid(3); } QIcon icon(iconSource); if (icon.availableSizes().isEmpty()) { icon = m_theme->iconFromTheme(iconSource, m_color); } if (!icon.availableSizes().isEmpty()){ img = icon.pixmap(size, iconMode(), QIcon::On).toImage(); if (m_isMask || icon.isMask()) { QPainter p(&img); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(img.rect(), m_theme->textColor()); p.end(); } } } return img; } QIcon::Mode DesktopIcon::iconMode() const { if (!isEnabled()) { return QIcon::Disabled; } else if (m_selected) { return QIcon::Selected; } else if (m_active) { return QIcon::Active; } return QIcon::Normal; } diff --git a/src/kirigamiplugin.cpp b/src/kirigamiplugin.cpp index 7eb8538d..6bfb2350 100644 --- a/src/kirigamiplugin.cpp +++ b/src/kirigamiplugin.cpp @@ -1,163 +1,163 @@ /* * Copyright 2009 by Alan Alpert * Copyright 2010 by Ménard Alexis * Copyright 2010 by Marco Martin * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kirigamiplugin.h" #include "enums.h" #include "desktopicon.h" #include "settings.h" #include "formlayoutattached.h" #include "mnemonicattached.h" #include #include #include #include -#include +#include "libkirigami/platformtheme.h" static QString s_selectedStyle; //Q_INIT_RESOURCE(kirigami); #ifdef KIRIGAMI_BUILD_TYPE_STATIC #include #endif QUrl KirigamiPlugin::componentUrl(const QString &fileName) const { foreach (const QString &style, m_stylesFallbackChain) { const QString candidate = QStringLiteral("styles/") + style + QLatin1Char('/') + fileName; if (QFile::exists(resolveFilePath(candidate))) { #ifdef KIRIGAMI_BUILD_TYPE_STATIC return QUrl(QStringLiteral("qrc:/org/kde/kirigami/styles/") + style + QLatin1Char('/') + fileName); #else return QUrl(resolveFileUrl(candidate)); #endif } } #ifdef KIRIGAMI_BUILD_TYPE_STATIC return QUrl(QStringLiteral("qrc:/org/kde/kirigami/") + fileName); #else return QUrl(resolveFileUrl(fileName)); #endif } void KirigamiPlugin::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("org.kde.kirigami")); const QString style = QQuickStyle::name(); //org.kde.desktop.plasma is a couple of files that fall back to desktop by purpose if ((style.isEmpty() || style == QStringLiteral("org.kde.desktop.plasma")) && QFile::exists(resolveFilePath(QStringLiteral("/styles/org.kde.desktop")))) { #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) m_stylesFallbackChain.prepend(QStringLiteral("org.kde.desktop")); #elif defined(Q_OS_ANDROID) m_stylesFallbackChain.prepend(QStringLiteral("Material")); #else // do we have an iOS specific style? m_stylesFallbackChain.prepend(QStringLiteral("Material")); #endif } if (!style.isEmpty() && QFile::exists(resolveFilePath(QStringLiteral("/styles/") + style))) { m_stylesFallbackChain.prepend(style); //if we have plasma deps installed, use them for extra integration if (style == QStringLiteral("org.kde.desktop") && QFile::exists(resolveFilePath(QStringLiteral("/styles/org.kde.desktop.plasma")))) { m_stylesFallbackChain.prepend("org.kde.desktop.plasma"); } } else { m_stylesFallbackChain.prepend(QStringLiteral("org.kde.desktop")); } //At this point the fallback chain will be selected->org.kde.desktop->Fallback s_selectedStyle = m_stylesFallbackChain.first(); qmlRegisterSingletonType(uri, 2, 0, "Settings", [](QQmlEngine*, QJSEngine*) -> QObject* { Settings *settings = new Settings; settings->setStyle(s_selectedStyle); return settings; } ); qmlRegisterUncreatableType(uri, 2, 0, "ApplicationHeaderStyle", "Cannot create objects of type ApplicationHeaderStyle"); //old legacy retrocompatible Theme qmlRegisterSingletonType(componentUrl(QStringLiteral("Theme.qml")), uri, 2, 0, "Theme"); qmlRegisterSingletonType(componentUrl(QStringLiteral("Units.qml")), uri, 2, 0, "Units"); qmlRegisterType(componentUrl(QStringLiteral("Action.qml")), uri, 2, 0, "Action"); qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationHeader.qml")), uri, 2, 0, "AbstractApplicationHeader"); qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationWindow.qml")), uri, 2, 0, "AbstractApplicationWindow"); qmlRegisterType(componentUrl(QStringLiteral("AbstractListItem.qml")), uri, 2, 0, "AbstractListItem"); qmlRegisterType(componentUrl(QStringLiteral("ApplicationHeader.qml")), uri, 2, 0, "ApplicationHeader"); qmlRegisterType(componentUrl(QStringLiteral("ToolBarApplicationHeader.qml")), uri, 2, 0, "ToolBarApplicationHeader"); qmlRegisterType(componentUrl(QStringLiteral("ApplicationWindow.qml")), uri, 2, 0, "ApplicationWindow"); qmlRegisterType(componentUrl(QStringLiteral("BasicListItem.qml")), uri, 2, 0, "BasicListItem"); qmlRegisterType(componentUrl(QStringLiteral("OverlayDrawer.qml")), uri, 2, 0, "OverlayDrawer"); qmlRegisterType(componentUrl(QStringLiteral("ContextDrawer.qml")), uri, 2, 0, "ContextDrawer"); qmlRegisterType(componentUrl(QStringLiteral("GlobalDrawer.qml")), uri, 2, 0, "GlobalDrawer"); qmlRegisterType(componentUrl(QStringLiteral("Heading.qml")), uri, 2, 0, "Heading"); qmlRegisterType(componentUrl(QStringLiteral("Separator.qml")), uri, 2, 0, "Separator"); qmlRegisterType(componentUrl(QStringLiteral("PageRow.qml")), uri, 2, 0, "PageRow"); //The icon is "special: we have to use a wrapper class to QIcon on org.kde.desktops #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) //we know that we want a different implementation with Material and Plasma styles if (s_selectedStyle == QStringLiteral("Material") || s_selectedStyle == QStringLiteral("Plasma")) { qmlRegisterType(componentUrl(QStringLiteral("Icon.qml")), uri, 2, 0, "Icon"); } else { qmlRegisterType(uri, 2, 0, "Icon"); } #else qmlRegisterType(componentUrl(QStringLiteral("Icon.qml")), uri, 2, 0, "Icon"); #endif qmlRegisterType(componentUrl(QStringLiteral("Label.qml")), uri, 2, 0, "Label"); //TODO: uncomment for 2.3 release //qmlRegisterTypeNotAvailable(uri, 2, 3, "Label", "Label type not supported anymore, use QtQuick.Controls.Label 2.0 instead"); qmlRegisterType(componentUrl(QStringLiteral("OverlaySheet.qml")), uri, 2, 0, "OverlaySheet"); qmlRegisterType(componentUrl(QStringLiteral("Page.qml")), uri, 2, 0, "Page"); qmlRegisterType(componentUrl(QStringLiteral("ScrollablePage.qml")), uri, 2, 0, "ScrollablePage"); qmlRegisterType(componentUrl(QStringLiteral("SplitDrawer.qml")), uri, 2, 0, "SplitDrawer"); qmlRegisterType(componentUrl(QStringLiteral("SwipeListItem.qml")), uri, 2, 0, "SwipeListItem"); //2.1 qmlRegisterType(componentUrl(QStringLiteral("AbstractItemViewHeader.qml")), uri, 2, 1, "AbstractItemViewHeader"); qmlRegisterType(componentUrl(QStringLiteral("ItemViewHeader.qml")), uri, 2, 1, "ItemViewHeader"); qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationItem.qml")), uri, 2, 1, "AbstractApplicationItem"); qmlRegisterType(componentUrl(QStringLiteral("ApplicationItem.qml")), uri, 2, 1, "ApplicationItem"); //2.2 //Theme changed from a singleton to an attached property qmlRegisterUncreatableType(uri, 2, 2, "Theme", "Cannot create objects of type Theme, use it as an attached poperty"); //2.3 qmlRegisterType(componentUrl(QStringLiteral("FormLayout.qml")), uri, 2, 3, "FormLayout"); qmlRegisterUncreatableType(uri, 2, 3, "FormData", "Cannot create objects of type FormData, use it as an attached poperty"); qmlRegisterUncreatableType(uri, 2, 3, "MnemonicData", "Cannot create objects of type MnemonicData, use it as an attached poperty"); qmlProtectModule(uri, 2); } #include "moc_kirigamiplugin.cpp" diff --git a/src/libkirigami/platformtheme.h b/src/libkirigami/platformtheme.h index 99117cbf..044c18db 100644 --- a/src/libkirigami/platformtheme.h +++ b/src/libkirigami/platformtheme.h @@ -1,229 +1,235 @@ /* * Copyright (C) 2017 by Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PLATFORMTHEME_H #define PLATFORMTHEME_H #include #include #include #include +#ifndef KIRIGAMI_BUILD_TYPE_STATIC #include +#endif namespace Kirigami { class PlatformThemePrivate; /** * @class PlatformTheme platformtheme.h PlatformTheme * * This class is the base for color management in Kirigami, * different platforms can reimplement this class to integrate with * system platform colors of a given platform */ +#ifdef KIRIGAMI_BUILD_TYPE_STATIC +class PlatformTheme : public QObject +#else class KIRIGAMI2_EXPORT PlatformTheme : public QObject +#endif { Q_OBJECT /** * This enumeration describes the color set for which a color is being selected. * * Color sets define a color "environment", suitable for drawing all parts of a * given region. Colors from different sets should not be combined. */ Q_PROPERTY(ColorSet colorSet READ colorSet WRITE setColorSet NOTIFY colorSetChanged) /** * If true, the colorSet will be inherited from the colorset of a theme of one * of the ancestor items * default: true */ Q_PROPERTY(bool inherit READ inherit WRITE setInherit NOTIFY inheritChanged) // foreground colors /** * Color for normal foregrounds, usually text, but not limited to it, * anything that should be painted with a clear contrast should use this color */ Q_PROPERTY(QColor textColor READ textColor NOTIFY colorsChanged) /** * Foreground color for disabled areas, usually a mid-gray */ Q_PROPERTY(QColor disabledTextColor READ disabledTextColor NOTIFY colorsChanged) /** * Color for text that has been highlighted, often is a light color while normal text is dark */ Q_PROPERTY(QColor highlightedTextColor READ highlightedTextColor NOTIFY colorsChanged) /** * Foreground for areas that are active or requesting attention */ Q_PROPERTY(QColor activeTextColor READ activeTextColor NOTIFY colorsChanged) /** * Color for links */ Q_PROPERTY(QColor linkColor READ linkColor NOTIFY colorsChanged) /** * Color for visited links, usually a bit darker than linkColor */ Q_PROPERTY(QColor visitedLinkColor READ visitedLinkColor NOTIFY colorsChanged) /** * Foreground color for negative areas, such as critical error text */ Q_PROPERTY(QColor negativeTextColor READ negativeTextColor NOTIFY colorsChanged) /** * Foreground color for neutral areas, such as warning texts (but not critical) */ Q_PROPERTY(QColor neutralTextColor READ neutralTextColor NOTIFY colorsChanged) /** * Success messages, trusted content */ Q_PROPERTY(QColor positiveTextColor READ positiveTextColor NOTIFY colorsChanged) //background colors /** * The generic background color */ Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY colorsChanged) /** * The background color for selected areas */ Q_PROPERTY(QColor highlightColor READ highlightColor NOTIFY colorsChanged) //decoration colors /** * A decoration color that indicates active focus */ Q_PROPERTY(QColor focusColor READ focusColor NOTIFY colorsChanged) /** * A decoration color that indicates mouse hovering */ Q_PROPERTY(QColor hoverColor READ hoverColor NOTIFY colorsChanged) // font and palette Q_PROPERTY(QFont defaultFont READ defaultFont NOTIFY defaultFontChanged) Q_PROPERTY(QPalette palette READ palette NOTIFY paletteChanged) Q_ENUMS(ColorSet) public: enum ColorSet { View = 0, /** Color set for item views, usually the lightest of all */ Window, /** Default Color set for windows and "chrome" areas */ Button, /** Color set used by buttons */ Selection, /** Color set used by selectged areas */ Tooltip, /** Color set used by tooltips */ Complementary /** Color set meant to be complementary to Window: usually is a dark theme for light themes */ }; Q_ENUM(ColorSet) explicit PlatformTheme(QObject *parent = 0); ~PlatformTheme(); void setColorSet(PlatformTheme::ColorSet); PlatformTheme::ColorSet colorSet() const; bool inherit() const; void setInherit(bool inherit); //foreground colors QColor textColor() const; QColor disabledTextColor() const; QColor highlightedTextColor() const; QColor activeTextColor() const; QColor linkColor() const; QColor visitedLinkColor() const; QColor negativeTextColor() const; QColor neutralTextColor() const; QColor positiveTextColor() const; //background colors QColor backgroundColor() const; QColor highlightColor() const; //TODO: add active/positive/neutral/negative backgrounds? //decoration colors QColor focusColor() const; QColor hoverColor() const; QFont defaultFont() const; //this may is used by the desktop QQC2 to set the styleoption palettes QPalette palette() const; //this will be used by desktopicon to fetch icons with KIconLoader virtual Q_INVOKABLE QIcon iconFromTheme(const QString &name, const QColor &customColor = Qt::transparent); //QML attached property static PlatformTheme *qmlAttachedProperties(QObject *object); Q_SIGNALS: //TODO: parameters to signals as this is also a c++ api void colorsChanged(); void defaultFontChanged(const QFont &font); void colorSetChanged(Kirigami::PlatformTheme::ColorSet colorSet); void paletteChanged(const QPalette &pal); void inheritChanged(bool inherit); protected: //Setters, not accessible from QML but from implementations //foreground colors void setTextColor(const QColor &color); void setDisabledTextColor(const QColor &color); void setHighlightedTextColor(const QColor &color); void setActiveTextColor(const QColor &color); void setLinkColor(const QColor &color); void setVisitedLinkColor(const QColor &color); void setNegativeTextColor(const QColor &color); void setNeutralTextColor(const QColor &color); void setPositiveTextColor(const QColor &color); //background colors void setBackgroundColor(const QColor &color); void setHighlightColor(const QColor &color); //decoration colors void setFocusColor(const QColor &color); void setHoverColor(const QColor &color); void setDefaultFont(const QFont &defaultFont); void setPalette(const QPalette &palette); private: PlatformThemePrivate *d; friend class PlatformThemePrivate; }; } QML_DECLARE_TYPEINFO(Kirigami::PlatformTheme, QML_HAS_ATTACHED_PROPERTIES) #endif // PLATFORMTHEME_H