First commit

This commit is contained in:
Stefano Moretti
2021-12-18 19:11:48 +01:00
commit 32a567a950
38 changed files with 2620 additions and 0 deletions

41
src/core.cpp Normal file
View File

@ -0,0 +1,41 @@
#include <BaseUI/core.h>
#include <QCoreApplication>
#include <QQmlEngine>
#include <QQuickStyle>
#include <QDebug>
#include "icons.h"
static void initialize(QQmlEngine *engine)
{
#ifdef BASEUI_EMBED_QML
Q_INIT_RESOURCE(baseui_qml);
engine->addImportPath(":/imports");
#endif
QString path = "/BaseUI/icons/";
#ifdef BASEUI_EMBED_ICONS
Q_INIT_RESOURCE(baseui_icons);
path = ":/imports" + path;
#else
path = QCoreApplication::applicationDirPath() + path;
#endif
Icons::registerIcons(engine, path);
}
namespace BaseUI
{
void init(QQmlEngine *engine)
{
QQuickStyle::setStyle("Material");
initialize(engine);
qmlRegisterSingletonType<Icons>("BaseUI", 1, 0, "Icons", Icons::singletonProvider);
}
}

111
src/iconprovider.h Normal file
View File

@ -0,0 +1,111 @@
#ifndef ICONPROVIDER_H
#define ICONPROVIDER_H
#include <QQuickImageProvider>
#include <QFont>
#include <QDebug>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QPainter>
#include <QFontMetrics>
class IconProvider : public QQuickImageProvider
{
public:
explicit IconProvider(const QString &family, const QString &codesPath)
: QQuickImageProvider(QQuickImageProvider::Image)
, font(family)
{
QFile file(codesPath);
if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) {
auto jd = QJsonDocument::fromJson(file.readAll());
if (!jd.isNull())
codepoints = jd.object();
else
qWarning() << "Invalid codepoints JSON file" << codesPath;
} else {
qWarning() << "Cannot open icon codes file" << codesPath;
qWarning() << file.errorString();
}
}
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override
{
int width = 48;
int height = 48;
if (requestedSize.width() > 0)
width = requestedSize.width();
if (requestedSize.height() > 0)
height = requestedSize.height();
if (size)
*size = QSize(width, height);
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
QStringList args = id.split(",", QString::SkipEmptyParts);
#else
QStringList args = id.split(",", Qt::SkipEmptyParts);
#endif
QString iconChar("?");
if (!args.isEmpty()) {
QString name = args.takeFirst();
if (codepoints.value(name).isUndefined())
qWarning() << "Icon name" << name << "not found in" << font.family();
else
iconChar = codepoints[name].toString();
} else {
qWarning() << "Icon name empty";
}
font.setPixelSize(width < height ? width : height);
QFontMetrics fm(font);
double widthRatio = double(width) / fm.boundingRect(iconChar).width();
if (widthRatio < 1.0)
font.setPixelSize(font.pixelSize() * widthRatio);
QImage image(width, height, QImage::Format_RGBA8888);
image.fill(Qt::transparent);
QPainter painter(&image);
for (const QString &arg : args) {
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
QStringList attr = arg.split("=", QString::SkipEmptyParts);
#else
QStringList attr = arg.split("=", Qt::SkipEmptyParts);
#endif
if (attr.isEmpty() || attr.size() > 2) {
qWarning() << "Argument" << arg << "not valid.";
} else if (attr[0] == "color") {
if (attr.size() == 2)
painter.setPen(attr[1]);
else
qWarning() << "Attribute color needs a value";
} else if (attr[0] == "hflip") {
painter.setTransform(QTransform(-1, 0, 0, 0, 1, 0, width, 0, 1));
} else if (attr[0] == "vflip") {
painter.setTransform(QTransform(1, 0, 0, 0, -1, 0, 0, height, 1));
} else {
qWarning() << "Unknown attribute" << attr;
}
}
painter.setFont(font);
painter.drawText(QRect(0, 0, width, height), Qt::AlignCenter, iconChar);
return image;
}
QStringList keys() { return codepoints.keys(); }
private:
QJsonObject codepoints;
QFont font;
};
#endif // ICONPROVIDER_H

55
src/icons.cpp Normal file
View File

@ -0,0 +1,55 @@
#include "icons.h"
#include <QDebug>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QVariant>
#include <QQmlEngine>
#include <QFontDatabase>
#include <QColor>
#include "iconprovider.h"
Icons::Icons(QObject *parent)
: QQmlPropertyMap(this, parent)
{
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
}
Icons *Icons::instance()
{
static Icons instance_;
return &instance_;
}
QObject *Icons::singletonProvider(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
{
Q_UNUSED(qmlEngine)
Q_UNUSED(jsEngine)
return instance();
}
void Icons::registerIcons(QQmlEngine *engine, const QString &path)
{
QString iconProviderName = "baseui_icons";
if (QFontDatabase::addApplicationFont(path + "MaterialIcons-Regular.ttf") == -1)
qWarning() << "Failed to load font Material";
auto iconProvider = new IconProvider("Material Icons", path + "codepoints.json");
engine->addImageProvider(iconProviderName, iconProvider);
#if (QT_VERSION < QT_VERSION_CHECK(6, 1, 0))
for (const QString &key : iconProvider->keys())
instance()->insert(key, QVariant("image://" + iconProviderName + "/" + key + ","));
#else
QVariantHash hash;
for (const QString &key : iconProvider->keys())
hash.insert(key, QVariant("image://" + iconProviderName + "/" + key + ","));
instance()->insert(hash);
#endif
}

28
src/icons.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef ICONS_H
#define ICONS_H
#include <QQmlPropertyMap>
class QQmlEngine;
class QJSEngine;
class Icons : public QQmlPropertyMap
{
Q_OBJECT
public:
Icons(QObject *parent = nullptr);
static Icons *instance();
static QObject *singletonProvider(QQmlEngine *qmlEngine, QJSEngine *jsEngine);
static void registerIcons(QQmlEngine *engine, const QString &path);
protected:
template <typename DerivedType>
explicit Icons(DerivedType *derived, QObject *parent = nullptr)
: QQmlPropertyMap(derived, parent)
{}
};
#endif