Add initial implementation of an Android icon engine
Try to use the Downloadable Font APIs from AndroidX to download the Material Symbols font. This would ideally allow us to add the official icon variations dynamically to the device's font cache. This works for several fonts from Google Fonts, but not for the fonts we need. So, for the time being, add a path where we consult the resource system for an embedded font file as well. Then an application can add e.g. the font file for the desired icons variation, and Qt will use those glyphs to render icons. Do this in the manual test, using cmake's FetchContent feature to download the font from Googlei's github repository. The incomplete mapping is based on the standard Material icons documentation at https://fonts.google.com/icons. We could in theory use the `codepoints` file that comes with the font files to create the mapping, but then we'd end up with platform specific icon names. Task-number: QTBUG-102346 Change-Id: Ibff3fe6d310a388e6111d983815ef0ddffb684c8 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
parent
dabf8a0d89
commit
f54393ba70
@ -29,6 +29,7 @@ qt_internal_add_plugin(QAndroidIntegrationPlugin
|
||||
qandroidplatformfiledialoghelper.cpp qandroidplatformfiledialoghelper.h
|
||||
qandroidplatformfontdatabase.cpp qandroidplatformfontdatabase.h
|
||||
qandroidplatformforeignwindow.cpp qandroidplatformforeignwindow.h
|
||||
qandroidplatformiconengine.cpp qandroidplatformiconengine.h
|
||||
qandroidplatformintegration.cpp qandroidplatformintegration.h
|
||||
qandroidplatformmenu.cpp qandroidplatformmenu.h
|
||||
qandroidplatformmenubar.cpp qandroidplatformmenubar.h
|
||||
|
357
src/plugins/platforms/android/qandroidplatformiconengine.cpp
Normal file
357
src/plugins/platforms/android/qandroidplatformiconengine.cpp
Normal file
@ -0,0 +1,357 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qandroidplatformiconengine.h"
|
||||
#include "androidjnimain.h"
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qjniarray.h>
|
||||
#include <QtCore/qjniobject.h>
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
#include <QtCore/qfile.h>
|
||||
#include <QtCore/qset.h>
|
||||
|
||||
#include <QtGui/qfontdatabase.h>
|
||||
#include <QtGui/qpainter.h>
|
||||
#include <QtGui/qpalette.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
Q_LOGGING_CATEGORY(lcIconEngineFontDownload, "qt.qpa.iconengine.fontdownload")
|
||||
|
||||
// the primary types to work with the FontRequest API
|
||||
Q_DECLARE_JNI_CLASS(FontRequest, "androidx/core/provider/FontRequest")
|
||||
Q_DECLARE_JNI_CLASS(FontsContractCompat, "androidx/core/provider/FontsContractCompat")
|
||||
Q_DECLARE_JNI_CLASS(FontFamilyResult, "androidx/core/provider/FontsContractCompat$FontFamilyResult")
|
||||
Q_DECLARE_JNI_CLASS(FontInfo, "androidx/core/provider/FontsContractCompat$FontInfo")
|
||||
|
||||
// various utility types
|
||||
Q_DECLARE_JNI_CLASS(List, "java/util/List"); // List is just an Interface
|
||||
Q_DECLARE_JNI_CLASS(ArrayList, "java/util/ArrayList");
|
||||
Q_DECLARE_JNI_CLASS(HashSet, "java/util/HashSet");
|
||||
Q_DECLARE_JNI_CLASS(Uri, "android/net/Uri")
|
||||
Q_DECLARE_JNI_CLASS(CancellationSignal, "android/os/CancellationSignal")
|
||||
Q_DECLARE_JNI_CLASS(ParcelFileDescriptor, "android/os/ParcelFileDescriptor")
|
||||
Q_DECLARE_JNI_CLASS(ContentResolver, "android/content/ContentResolver")
|
||||
Q_DECLARE_JNI_CLASS(PackageManager, "android/content/pm/PackageManager")
|
||||
Q_DECLARE_JNI_CLASS(ProviderInfo, "android/content/pm/ProviderInfo")
|
||||
Q_DECLARE_JNI_CLASS(PackageInfo, "android/content/pm/PackageInfo")
|
||||
Q_DECLARE_JNI_CLASS(Signature, "android/content/pm/Signature")
|
||||
|
||||
namespace FontProvider {
|
||||
|
||||
static QString fetchFont(const QString &query)
|
||||
{
|
||||
using namespace QtJniTypes;
|
||||
|
||||
static QMap<QString, QString> triedFonts;
|
||||
const auto it = triedFonts.find(query);
|
||||
if (it != triedFonts.constEnd())
|
||||
return it.value();
|
||||
|
||||
QString fontFamily;
|
||||
triedFonts[query] = fontFamily; // mark as tried
|
||||
|
||||
QStringList loadedFamilies;
|
||||
if (QFile file(query); file.open(QIODevice::ReadOnly)) {
|
||||
qCDebug(lcIconEngineFontDownload) << "Loading font from resource" << query;
|
||||
const QByteArray fontData = file.readAll();
|
||||
int fontId = QFontDatabase::addApplicationFontFromData(fontData);
|
||||
loadedFamilies << QFontDatabase::applicationFontFamilies(fontId);
|
||||
} else {
|
||||
const QString package = u"com.google.android.gms"_s;
|
||||
const QString authority = u"com.google.android.gms.fonts"_s;
|
||||
|
||||
// First we access the content provider to get the signatures of the authority for the package
|
||||
const auto context = QtAndroidPrivate::context();
|
||||
|
||||
auto packageManager = context.callMethod<PackageManager>("getPackageManager");
|
||||
if (!packageManager.isValid()) {
|
||||
qCWarning(lcIconEngineFontDownload, "Failed to instantiate PackageManager");
|
||||
return fontFamily;
|
||||
}
|
||||
const int signaturesField = PackageManager::getStaticField<int>("GET_SIGNATURES");
|
||||
auto providerInfo = packageManager.callMethod<ProviderInfo>("resolveContentProvider",
|
||||
authority, 0);
|
||||
if (!providerInfo.isValid()) {
|
||||
qCWarning(lcIconEngineFontDownload, "Failed to resolve content provider");
|
||||
return fontFamily;
|
||||
}
|
||||
const QString packageName = providerInfo.getField<QString>("packageName");
|
||||
if (packageName != package) {
|
||||
qCWarning(lcIconEngineFontDownload, "Mismatched provider package - expected '%s', got '%s'",
|
||||
package.toUtf8().constData(), packageName.toUtf8().constData());
|
||||
return fontFamily;
|
||||
}
|
||||
auto packageInfo = packageManager.callMethod<PackageInfo>("getPackageInfo",
|
||||
package, signaturesField);
|
||||
if (!packageInfo.isValid()) {
|
||||
qCWarning(lcIconEngineFontDownload, "Failed to get package info with signature field %d",
|
||||
signaturesField);
|
||||
return fontFamily;
|
||||
}
|
||||
const auto signatures = packageInfo.getField<Signature[]>("signatures");
|
||||
if (!signatures.isValid()) {
|
||||
qCWarning(lcIconEngineFontDownload, "Failed to get signature array from package info");
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
// FontRequest wants a list of sets for the certificates
|
||||
ArrayList outerList;
|
||||
HashSet innerSet;
|
||||
Q_ASSERT(outerList.isValid() && innerSet.isValid());
|
||||
|
||||
for (QJniObject signature : signatures) {
|
||||
const QJniArray<jbyte> byteArray = signature.callMethod<jbyte[]>("toByteArray");
|
||||
|
||||
// add takes an Object, not an Array
|
||||
if (!innerSet.callMethod<jboolean>("add", byteArray.object<jobject>()))
|
||||
qCWarning(lcIconEngineFontDownload, "Failed to add signature to set");
|
||||
}
|
||||
// Add the set to the list
|
||||
if (!outerList.callMethod<jboolean>("add", innerSet.object()))
|
||||
qCWarning(lcIconEngineFontDownload, "Failed to add set to certificate list");
|
||||
|
||||
// FontRequest constructor wants a List interface, not an ArrayList
|
||||
FontRequest fontRequest(authority, package, query, outerList.object<List>());
|
||||
if (!fontRequest.isValid()) {
|
||||
qCWarning(lcIconEngineFontDownload, "Failed to create font request for '%s'",
|
||||
query.toUtf8().constData());
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
// Call FontsContractCompat::fetchFonts with the FontRequest object
|
||||
auto fontFamilyResult = FontsContractCompat::callStaticMethod<FontFamilyResult>(
|
||||
"fetchFonts",
|
||||
context,
|
||||
CancellationSignal(nullptr),
|
||||
fontRequest);
|
||||
if (!fontFamilyResult.isValid()) {
|
||||
qCWarning(lcIconEngineFontDownload, "Failed to fetch fonts for query '%s'",
|
||||
query.toUtf8().constData());
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
enum class StatusCode {
|
||||
OK = 0,
|
||||
UNEXPECTED_DATA_PROVIDED = 1,
|
||||
WRONG_CERTIFICATES = 2,
|
||||
};
|
||||
|
||||
const StatusCode statusCode = fontFamilyResult.callMethod<StatusCode>("getStatusCode");
|
||||
switch (statusCode) {
|
||||
case StatusCode::OK:
|
||||
break;
|
||||
case StatusCode::UNEXPECTED_DATA_PROVIDED:
|
||||
qCWarning(lcIconEngineFontDownload, "Provider returned unexpected data for query '%s'",
|
||||
query.toUtf8().constData());
|
||||
return fontFamily;
|
||||
case StatusCode::WRONG_CERTIFICATES:
|
||||
qCWarning(lcIconEngineFontDownload, "Wrong Certificates provided in query '%s'",
|
||||
query.toUtf8().constData());
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
const auto fontInfos = fontFamilyResult.callMethod<FontInfo[]>("getFonts");
|
||||
if (!fontInfos.isValid()) {
|
||||
qCWarning(lcIconEngineFontDownload, "FontFamilyResult::getFonts returned null object for '%s'",
|
||||
query.toUtf8().constData());
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
auto contentResolver = context.callMethod<ContentResolver>("getContentResolver");
|
||||
|
||||
for (QJniObject fontInfo : fontInfos) {
|
||||
if (!fontInfo.isValid()) {
|
||||
qCDebug(lcIconEngineFontDownload, "Received null-fontInfo object, skipping");
|
||||
continue;
|
||||
}
|
||||
enum class ResultCode {
|
||||
OK = 0,
|
||||
FONT_NOT_FOUND = 1,
|
||||
FONT_UNAVAILABLE = 2,
|
||||
MALFORMED_QUERY = 3,
|
||||
};
|
||||
const ResultCode resultCode = fontInfo.callMethod<ResultCode>("getResultCode");
|
||||
switch (resultCode) {
|
||||
case ResultCode::OK:
|
||||
break;
|
||||
case ResultCode::FONT_NOT_FOUND:
|
||||
qCWarning(lcIconEngineFontDownload, "Font '%s' could not be found",
|
||||
query.toUtf8().constData());
|
||||
return fontFamily;
|
||||
case ResultCode::FONT_UNAVAILABLE:
|
||||
qCWarning(lcIconEngineFontDownload, "Font '%s' is unavailable at",
|
||||
query.toUtf8().constData());
|
||||
return fontFamily;
|
||||
case ResultCode::MALFORMED_QUERY:
|
||||
qCWarning(lcIconEngineFontDownload, "Query string '%s' is malformed",
|
||||
query.toUtf8().constData());
|
||||
return fontFamily;
|
||||
}
|
||||
auto fontUri = fontInfo.callMethod<Uri>("getUri");
|
||||
// in this case the Font URI is always a content scheme file, made
|
||||
// so the app requesting it has permissions to open
|
||||
auto fileDescriptor = contentResolver.callMethod<ParcelFileDescriptor>("openFileDescriptor",
|
||||
fontUri, u"r"_s);
|
||||
if (!fileDescriptor.isValid()) {
|
||||
qCWarning(lcIconEngineFontDownload, "Font file '%s' not accessible",
|
||||
fontUri.toString().toUtf8().constData());
|
||||
continue;
|
||||
}
|
||||
|
||||
int fd = fileDescriptor.callMethod<int>("detachFd");
|
||||
QFile file;
|
||||
file.open(fd, QFile::OpenModeFlag::ReadOnly, QFile::FileHandleFlag::AutoCloseHandle);
|
||||
const QByteArray fontData = file.readAll();
|
||||
qCDebug(lcIconEngineFontDownload) << "Font file read:" << fontData.size() << "bytes";
|
||||
int fontId = QFontDatabase::addApplicationFontFromData(fontData);
|
||||
loadedFamilies << QFontDatabase::applicationFontFamilies(fontId);
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(lcIconEngineFontDownload) << "Query '" << query << "' added families" << loadedFamilies;
|
||||
if (!loadedFamilies.isEmpty())
|
||||
fontFamily = loadedFamilies.first();
|
||||
triedFonts[query] = fontFamily;
|
||||
return fontFamily;
|
||||
}
|
||||
}
|
||||
|
||||
QAndroidPlatformIconEngine::Glyphs QAndroidPlatformIconEngine::glyphs() const
|
||||
{
|
||||
if (!QFontInfo(m_iconFont).exactMatch())
|
||||
return {};
|
||||
|
||||
static constexpr std::pair<QStringView, Glyphs> glyphMap[] = {
|
||||
{u"edit-clear", 0xe872},
|
||||
{u"edit-copy", 0xe14d},
|
||||
{u"edit-cut", 0xe14e},
|
||||
{u"edit-delete", 0xe14a},
|
||||
{u"edit-find", 0xe8b6},
|
||||
{u"edit-find-replace", 0xe881},
|
||||
{u"edit-paste", 0xe14f},
|
||||
{u"edit-redo", 0xe15a},
|
||||
{u"edit-select-all", 0xe162},
|
||||
{u"edit-undo", 0xe166},
|
||||
{u"printer", 0xe8ad},
|
||||
};
|
||||
|
||||
const auto it = std::find_if(std::begin(glyphMap), std::end(glyphMap), [this](const auto &c){
|
||||
return c.first == m_iconName;
|
||||
});
|
||||
return it != std::end(glyphMap) ? it->second : Glyphs();
|
||||
}
|
||||
|
||||
QAndroidPlatformIconEngine::QAndroidPlatformIconEngine(const QString &iconName)
|
||||
: m_iconName(iconName)
|
||||
, m_glyphs(glyphs())
|
||||
{
|
||||
// The MaterialIcons-Regular.ttf font file is available from
|
||||
// https://github.com/google/material-design-icons/tree/master/font. If it's packaged
|
||||
// as a resource with the application, then we use it. Otherwise we try to download
|
||||
// the Outlined version of Material Symbols, and failing that we try Material Icons.
|
||||
QString fontFamily = FontProvider::fetchFont(u":/qt-project.org/icons/MaterialIcons-Regular.ttf"_s);
|
||||
|
||||
const QString key = qEnvironmentVariable("QT_GOOGLE_FONTS_KEY");
|
||||
if (fontFamily.isEmpty() && !key.isEmpty())
|
||||
fontFamily = FontProvider::fetchFont(u"key=%1&name=Material+Symbols+Outlined"_s.arg(key));
|
||||
|
||||
// last resort - use the old Material Icons
|
||||
if (fontFamily.isEmpty())
|
||||
fontFamily = u"Material Icons"_s;
|
||||
m_iconFont = QFont(fontFamily);
|
||||
}
|
||||
|
||||
QAndroidPlatformIconEngine::~QAndroidPlatformIconEngine()
|
||||
{}
|
||||
|
||||
QIconEngine *QAndroidPlatformIconEngine::clone() const
|
||||
{
|
||||
return new QAndroidPlatformIconEngine(m_iconName);
|
||||
}
|
||||
|
||||
QString QAndroidPlatformIconEngine::key() const
|
||||
{
|
||||
return u"QAndroidPlatformIconEngine"_s;
|
||||
}
|
||||
|
||||
QString QAndroidPlatformIconEngine::iconName()
|
||||
{
|
||||
return m_iconName;
|
||||
}
|
||||
|
||||
bool QAndroidPlatformIconEngine::isNull()
|
||||
{
|
||||
return m_glyphs.isNull() || !QFontMetrics(m_iconFont).inFont(m_glyphs.codepoints[0]);
|
||||
}
|
||||
|
||||
QList<QSize> QAndroidPlatformIconEngine::availableSizes(QIcon::Mode, QIcon::State)
|
||||
{
|
||||
return {{16, 16}, {24, 24}, {48, 48}, {128, 128}};
|
||||
}
|
||||
|
||||
QSize QAndroidPlatformIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return QIconEngine::actualSize(size, mode, state);
|
||||
}
|
||||
|
||||
QPixmap QAndroidPlatformIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return scaledPixmap(size, mode, state, 1.0);
|
||||
}
|
||||
|
||||
QPixmap QAndroidPlatformIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
|
||||
{
|
||||
const quint64 cacheKey = calculateCacheKey(mode, state);
|
||||
if (cacheKey != m_cacheKey || m_pixmap.size() != size || m_pixmap.devicePixelRatio() != scale) {
|
||||
m_pixmap = QPixmap(size * scale);
|
||||
m_pixmap.fill(QColor(0, 0, 0, 0));
|
||||
m_pixmap.setDevicePixelRatio(scale);
|
||||
|
||||
QPainter painter(&m_pixmap);
|
||||
QFont renderFont(m_iconFont);
|
||||
renderFont.setPixelSize(size.height());
|
||||
painter.setFont(renderFont);
|
||||
|
||||
QPalette palette;
|
||||
switch (mode) {
|
||||
case QIcon::Active:
|
||||
painter.setPen(palette.color(QPalette::Active, QPalette::Accent));
|
||||
break;
|
||||
case QIcon::Normal:
|
||||
painter.setPen(palette.color(QPalette::Active, QPalette::Text));
|
||||
break;
|
||||
case QIcon::Disabled:
|
||||
painter.setPen(palette.color(QPalette::Disabled, QPalette::Accent));
|
||||
break;
|
||||
case QIcon::Selected:
|
||||
painter.setPen(palette.color(QPalette::Active, QPalette::Accent));
|
||||
break;
|
||||
}
|
||||
|
||||
const QRect rect({0, 0}, size);
|
||||
if (m_glyphs.codepoints[0] == QChar(0xffff)) {
|
||||
painter.drawText(rect, Qt::AlignCenter, QString(m_glyphs.codepoints + 1, 2));
|
||||
} else {
|
||||
for (const auto &glyph : m_glyphs.codepoints) {
|
||||
if (glyph.isNull())
|
||||
break;
|
||||
painter.drawText(rect, glyph);
|
||||
}
|
||||
}
|
||||
|
||||
m_cacheKey = cacheKey;
|
||||
}
|
||||
|
||||
return m_pixmap;
|
||||
}
|
||||
|
||||
void QAndroidPlatformIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
const qreal scale = painter->device()->devicePixelRatio();
|
||||
painter->drawPixmap(rect, scaledPixmap(rect.size(), mode, state, scale));
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
52
src/plugins/platforms/android/qandroidplatformiconengine.h
Normal file
52
src/plugins/platforms/android/qandroidplatformiconengine.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QANDROIDPLATFORMICONENGINE_H
|
||||
#define QANDROIDPLATFORMICONENGINE_H
|
||||
|
||||
#include <QtGui/qiconengine.h>
|
||||
#include <QtGui/qfont.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidPlatformIconEngine : public QIconEngine
|
||||
{
|
||||
public:
|
||||
QAndroidPlatformIconEngine(const QString &iconName);
|
||||
~QAndroidPlatformIconEngine();
|
||||
QIconEngine *clone() const override;
|
||||
QString key() const override;
|
||||
QString iconName() override;
|
||||
bool isNull() override;
|
||||
|
||||
QList<QSize> availableSizes(QIcon::Mode, QIcon::State) override;
|
||||
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
||||
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
||||
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
|
||||
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
|
||||
|
||||
private:
|
||||
static constexpr quint64 calculateCacheKey(QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
return (quint64(mode) << 32) | state;
|
||||
}
|
||||
struct Glyphs
|
||||
{
|
||||
constexpr Glyphs(char16_t g1 = 0, char16_t g2 = 0, char16_t g3 = 0) noexcept
|
||||
: codepoints{g1, g2, g3}
|
||||
{}
|
||||
constexpr bool isNull() const noexcept { return codepoints[0].isNull(); }
|
||||
const QChar codepoints[3] = {};
|
||||
};
|
||||
Glyphs glyphs() const;
|
||||
|
||||
const QString m_iconName;
|
||||
QFont m_iconFont;
|
||||
const Glyphs m_glyphs;
|
||||
mutable QPixmap m_pixmap;
|
||||
mutable quint64 m_cacheKey = {};
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QANDROIDPLATFORMICONENGINE_H
|
@ -4,6 +4,7 @@
|
||||
#include "androidjnimain.h"
|
||||
#include "androidjnimenu.h"
|
||||
#include "qandroidplatformtheme.h"
|
||||
#include "qandroidplatformiconengine.h"
|
||||
#include "qandroidplatformmenubar.h"
|
||||
#include "qandroidplatformmenu.h"
|
||||
#include "qandroidplatformmenuitem.h"
|
||||
@ -481,6 +482,15 @@ const QFont *QAndroidPlatformTheme::font(Font type) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
QIconEngine *QAndroidPlatformTheme::createIconEngine(const QString &iconName) const
|
||||
{
|
||||
static bool experimentalIconEngines = qEnvironmentVariableIsSet("QT_ENABLE_EXPERIMENTAL_ICON_ENGINES");
|
||||
if (experimentalIconEngines)
|
||||
return new QAndroidPlatformIconEngine(iconName);
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const
|
||||
{
|
||||
switch (hint) {
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
Qt::ColorScheme colorScheme() const override;
|
||||
const QPalette *palette(Palette type = SystemPalette) const override;
|
||||
const QFont *font(Font type = SystemFont) const override;
|
||||
QIconEngine *createIconEngine(const QString &iconName) const override;
|
||||
QVariant themeHint(ThemeHint hint) const override;
|
||||
QString standardButtonText(int button) const override;
|
||||
bool usePlatformNativeDialog(DialogType type) const override;
|
||||
|
@ -13,3 +13,38 @@ qt_internal_add_manual_test(iconbrowser
|
||||
Qt::Widgets
|
||||
Qt::WidgetsPrivate
|
||||
)
|
||||
|
||||
if (ANDROID)
|
||||
set(font_filename "MaterialIcons-Regular.ttf")
|
||||
if (QT_ALLOW_DOWNLOAD)
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
MaterialIcons
|
||||
URL
|
||||
"https://github.com/google/material-design-icons/raw/master/font/${font_filename}"
|
||||
DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DOWNLOAD_NAME "${font_filename}"
|
||||
DOWNLOAD_NO_EXTRACT TRUE
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(MaterialIcons)
|
||||
endif()
|
||||
|
||||
if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/${font_filename}")
|
||||
set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/${font_filename}"
|
||||
PROPERTIES QT_RESOURCE_ALIAS ${font_filename})
|
||||
target_compile_definitions(iconbrowser PRIVATE "ICONBROWSER_RESOURCE")
|
||||
qt_add_resources(iconbrowser "icons"
|
||||
PREFIX
|
||||
"/qt-project.org/icons"
|
||||
FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${font_filename}"
|
||||
)
|
||||
else()
|
||||
message(WARNING "Font file ${font_filename} not found and not downloaded!\n"
|
||||
"Make sure the font file ${font_filename} is available in ${CMAKE_CURRENT_BINARY_DIR}.\n"
|
||||
"Consider configuring with -DQT_ALLOW_DOWNLOAD=ON to download the font automatically.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -534,6 +534,10 @@ int main(int argc, char* argv[])
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
#ifdef ICONBROWSER_RESOURCE
|
||||
Q_INIT_RESOURCE(icons);
|
||||
#endif
|
||||
|
||||
IconModel model;
|
||||
|
||||
QTabWidget widget;
|
||||
|
Loading…
Reference in New Issue
Block a user