2021-10-29 10:05:51 +03:00
|
|
|
/*
|
|
|
|
* Copyright (C) by Oleksandr Zolotov <alex@nextcloud.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, 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.
|
|
|
|
*/
|
|
|
|
|
2021-08-17 16:39:18 +03:00
|
|
|
#include "iconutils.h"
|
|
|
|
|
|
|
|
#include <theme.h>
|
|
|
|
|
|
|
|
#include <QFile>
|
2021-10-29 10:05:51 +03:00
|
|
|
#include <QLoggingCategory>
|
2021-08-17 16:39:18 +03:00
|
|
|
#include <QPainter>
|
|
|
|
#include <QPixmapCache>
|
|
|
|
#include <QSvgRenderer>
|
|
|
|
|
2021-10-29 10:05:51 +03:00
|
|
|
namespace {
|
|
|
|
QString findSvgFilePath(const QString &fileName, const QStringList &possibleColors)
|
|
|
|
{
|
2021-11-03 11:00:33 +03:00
|
|
|
QString result;
|
|
|
|
result = QString{OCC::Theme::themePrefix} + fileName;
|
|
|
|
if (QFile::exists(result)) {
|
|
|
|
return result;
|
|
|
|
} else {
|
|
|
|
for (const auto &color : possibleColors) {
|
|
|
|
result = QString{OCC::Theme::themePrefix} + color + QStringLiteral("/") + fileName;
|
|
|
|
|
|
|
|
if (QFile::exists(result)) {
|
|
|
|
return result;
|
|
|
|
}
|
2021-10-29 10:05:51 +03:00
|
|
|
}
|
2021-11-03 11:00:33 +03:00
|
|
|
result.clear();
|
2021-10-29 10:05:51 +03:00
|
|
|
}
|
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
return result;
|
2021-10-29 10:05:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-17 16:39:18 +03:00
|
|
|
namespace OCC {
|
|
|
|
namespace Ui {
|
2021-11-03 11:00:33 +03:00
|
|
|
namespace IconUtils {
|
|
|
|
Q_LOGGING_CATEGORY(lcIconUtils, "nextcloud.gui.iconutils", QtInfoMsg)
|
|
|
|
QPixmap pixmapForBackground(const QString &fileName, const QColor &backgroundColor)
|
|
|
|
{
|
|
|
|
Q_ASSERT(!fileName.isEmpty());
|
2021-10-29 10:05:51 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
const auto pixmapColor = backgroundColor.isValid() && !Theme::isDarkColor(backgroundColor)
|
|
|
|
? QColorConstants::Svg::black
|
|
|
|
: QColorConstants::Svg::white;
|
|
|
|
;
|
|
|
|
return createSvgPixmapWithCustomColorCached(fileName, pixmapColor);
|
|
|
|
}
|
2021-10-29 10:05:51 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
QImage createSvgImageWithCustomColor(const QString &fileName, const QColor &customColor, QSize *originalSize, const QSize &requestedSize)
|
|
|
|
{
|
|
|
|
Q_ASSERT(!fileName.isEmpty());
|
|
|
|
Q_ASSERT(customColor.isValid());
|
2021-10-29 10:05:51 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
QImage result{};
|
2021-08-17 16:39:18 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
if (fileName.isEmpty() || !customColor.isValid()) {
|
2023-02-13 17:19:14 +03:00
|
|
|
qCWarning(lcIconUtils) << "invalid fileName or customColor";
|
2021-11-03 11:00:33 +03:00
|
|
|
return result;
|
|
|
|
}
|
2021-08-17 16:39:18 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
// some icons are present in white or black only, so, we need to check both when needed
|
|
|
|
const auto iconBaseColors = QStringList{QStringLiteral("black"), QStringLiteral("white")};
|
|
|
|
|
|
|
|
// check if there is an existing image matching the custom color
|
|
|
|
{
|
|
|
|
const auto customColorName = [&customColor]() {
|
|
|
|
auto result = customColor.name();
|
|
|
|
if (result.startsWith(QStringLiteral("#"))) {
|
|
|
|
if (result == QStringLiteral("#000000")) {
|
|
|
|
result = QStringLiteral("black");
|
|
|
|
}
|
|
|
|
if (result == QStringLiteral("#ffffff")) {
|
|
|
|
result = QStringLiteral("white");
|
|
|
|
}
|
2021-10-29 10:05:51 +03:00
|
|
|
}
|
2021-11-03 11:00:33 +03:00
|
|
|
return result;
|
|
|
|
}();
|
2021-10-29 10:05:51 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
if (iconBaseColors.contains(customColorName)) {
|
2022-09-28 14:26:57 +03:00
|
|
|
if (requestedSize.width() > 0 && requestedSize.height() > 0) {
|
|
|
|
result = QIcon(QString{OCC::Theme::themePrefix} + customColorName + QStringLiteral("/") + fileName).pixmap(requestedSize).toImage();
|
|
|
|
} else {
|
|
|
|
result = QImage{QString{OCC::Theme::themePrefix} + customColorName + QStringLiteral("/") + fileName};
|
|
|
|
}
|
2021-11-03 11:00:33 +03:00
|
|
|
if (!result.isNull()) {
|
|
|
|
return result;
|
2021-10-29 10:05:51 +03:00
|
|
|
}
|
2021-11-03 11:00:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// find the first matching svg file
|
|
|
|
const auto sourceSvg = findSvgFilePath(fileName, iconBaseColors);
|
|
|
|
|
|
|
|
Q_ASSERT(!sourceSvg.isEmpty());
|
|
|
|
if (sourceSvg.isEmpty()) {
|
2023-02-13 17:19:14 +03:00
|
|
|
qCWarning(lcIconUtils) << "Failed to find base SVG file for" << fileName;
|
2021-11-03 11:00:33 +03:00
|
|
|
return result;
|
|
|
|
}
|
2021-10-29 10:05:51 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
result = drawSvgWithCustomFillColor(sourceSvg, customColor, originalSize, requestedSize);
|
2021-08-17 16:39:18 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
Q_ASSERT(!result.isNull());
|
|
|
|
if (result.isNull()) {
|
2023-02-13 17:19:14 +03:00
|
|
|
qCWarning(lcIconUtils) << "Failed to load pixmap for" << fileName;
|
2021-11-03 11:00:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2021-10-29 10:05:51 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
QPixmap createSvgPixmapWithCustomColorCached(const QString &fileName, const QColor &customColor, QSize *originalSize, const QSize &requestedSize)
|
|
|
|
{
|
|
|
|
QPixmap cachedPixmap;
|
2021-08-17 16:39:18 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
const auto customColorName = customColor.name();
|
2021-08-17 16:39:18 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
const QString cacheKey = fileName + QStringLiteral(",") + customColorName;
|
2021-10-29 10:05:51 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
// check for existing QPixmap in cache
|
|
|
|
if (QPixmapCache::find(cacheKey, &cachedPixmap)) {
|
|
|
|
if (originalSize) {
|
|
|
|
*originalSize = {};
|
2021-08-17 16:39:18 +03:00
|
|
|
}
|
2021-11-03 11:00:33 +03:00
|
|
|
return cachedPixmap;
|
|
|
|
}
|
2021-08-17 16:39:18 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
cachedPixmap = QPixmap::fromImage(createSvgImageWithCustomColor(fileName, customColor, originalSize, requestedSize));
|
2021-08-17 16:39:18 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
if (!cachedPixmap.isNull()) {
|
|
|
|
QPixmapCache::insert(cacheKey, cachedPixmap);
|
|
|
|
}
|
2021-08-17 16:39:18 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
return cachedPixmap;
|
|
|
|
}
|
2021-10-29 10:05:51 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
QImage drawSvgWithCustomFillColor(
|
|
|
|
const QString &sourceSvgPath, const QColor &fillColor, QSize *originalSize, const QSize &requestedSize)
|
|
|
|
{
|
|
|
|
QSvgRenderer svgRenderer;
|
2021-08-17 16:39:18 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
if (!svgRenderer.load(sourceSvgPath)) {
|
|
|
|
qCWarning(lcIconUtils) << "Could no load initial SVG image";
|
|
|
|
return {};
|
|
|
|
}
|
2021-08-17 16:39:18 +03:00
|
|
|
|
2021-11-03 11:00:33 +03:00
|
|
|
const auto reqSize = requestedSize.isValid() ? requestedSize : svgRenderer.defaultSize();
|
|
|
|
|
|
|
|
if (originalSize) {
|
|
|
|
*originalSize = svgRenderer.defaultSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
// render source image
|
|
|
|
QImage svgImage(reqSize, QImage::Format_ARGB32);
|
|
|
|
{
|
|
|
|
QPainter svgImagePainter(&svgImage);
|
|
|
|
svgImage.fill(Qt::GlobalColor::transparent);
|
|
|
|
svgRenderer.render(&svgImagePainter);
|
2021-08-17 16:39:18 +03:00
|
|
|
}
|
2021-11-03 11:00:33 +03:00
|
|
|
|
|
|
|
// draw target image with custom fillColor
|
|
|
|
QImage image(reqSize, QImage::Format_ARGB32);
|
|
|
|
image.fill(QColor(fillColor));
|
|
|
|
{
|
|
|
|
QPainter imagePainter(&image);
|
|
|
|
imagePainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
|
|
|
imagePainter.drawImage(0, 0, svgImage);
|
|
|
|
}
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
}
|
2021-08-17 16:39:18 +03:00
|
|
|
}
|
|
|
|
}
|