File indexing completed on 2024-05-05 03:48:22

0001 /*
0002     File                 : ColorMapsManager.h
0003     Project              : LabPlot
0004     Description          : widget showing the available color maps
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2021 Alexander Semke <alexander.semke@web.de>
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "tools/ColorMapsManager.h"
0011 #include "backend/lib/macros.h"
0012 
0013 #include <QFile>
0014 #include <QJsonArray>
0015 #include <QJsonDocument>
0016 #include <QJsonObject>
0017 #include <QJsonValue>
0018 #include <QMessageBox>
0019 #include <QPainter>
0020 #include <QPixmap>
0021 #include <QStandardPaths>
0022 
0023 #include <KLocalizedString>
0024 
0025 ColorMapsManager* ColorMapsManager::m_instance{nullptr};
0026 
0027 /*!
0028     \class ColorMapsManager
0029     \brief color maps manager. singleton class holding the information about the data and metadata of the available color maps.
0030 
0031     \ingroup kdefrontend
0032  */
0033 ColorMapsManager::ColorMapsManager() {
0034     m_jsonDir = QStandardPaths::locate(QStandardPaths::AppDataLocation, QLatin1String("colormaps"), QStandardPaths::LocateDirectory);
0035     loadCollections();
0036 }
0037 
0038 ColorMapsManager::~ColorMapsManager() = default;
0039 
0040 ColorMapsManager* ColorMapsManager::instance() {
0041     if (!m_instance)
0042         m_instance = new ColorMapsManager();
0043 
0044     return m_instance;
0045 }
0046 
0047 QStringList ColorMapsManager::collectionNames() const {
0048     return m_collections.keys();
0049 }
0050 
0051 QString ColorMapsManager::collectionInfo(const QString& name) const {
0052     return m_collections[name];
0053 }
0054 
0055 /*!
0056  * \brief returns the list of the color map names for the collection \c collecitonName
0057  */
0058 QStringList ColorMapsManager::colorMapNames(const QString& collectionName) {
0059     // load the collection if not done yet
0060     if (!m_colorMaps.contains(collectionName)) {
0061         // color maps of the currently selected collection not loaded yet -> load them
0062         QString path = m_jsonDir + QLatin1Char('/') + collectionName + QStringLiteral(".json");
0063         QFile collectionFile(path);
0064         if (collectionFile.open(QIODevice::ReadOnly)) {
0065             QJsonDocument doc = QJsonDocument::fromJson(collectionFile.readAll());
0066             if (!doc.isObject()) {
0067                 QDEBUG("Invalid definition of " << path)
0068                 return {};
0069             }
0070 
0071             const QJsonObject& colorMaps = doc.object();
0072             const auto& keys = colorMaps.keys();
0073             m_colorMaps[collectionName] = keys;
0074 
0075             // load colors
0076             for (const auto& key : keys) {
0077                 if (m_colors.find(key) == m_colors.end()) {
0078                     QStringList colors;
0079                     const auto& colorsArray = colorMaps.value(key).toArray();
0080                     for (const auto& color : colorsArray)
0081                         colors << color.toString();
0082                     m_colors[key] = colors;
0083                 }
0084             }
0085         }
0086     }
0087 
0088     return m_colorMaps[collectionName];
0089 }
0090 
0091 QVector<QColor> ColorMapsManager::colors() const {
0092     return m_colormap;
0093 }
0094 
0095 void ColorMapsManager::render(QPixmap& pixmap, const QString& name) {
0096     if (name.isEmpty())
0097         return;
0098 
0099     if (!m_colors.contains(name)) {
0100         for (const auto& name : collectionNames())
0101             colorMapNames(name);
0102     }
0103 
0104     // convert from the string RGB represetation to QColor
0105     m_colormap.clear();
0106     for (auto& rgb : m_colors[name]) {
0107         QStringList rgbValues = rgb.split(QLatin1Char(','));
0108         if (rgbValues.count() == 3)
0109             m_colormap << QColor(rgbValues.at(0).toInt(), rgbValues.at(1).toInt(), rgbValues.at(2).toInt());
0110         else if (rgbValues.count() == 4)
0111             m_colormap << QColor(rgbValues.at(1).toInt(), rgbValues.at(2).toInt(), rgbValues.at(3).toInt());
0112     }
0113 
0114     // render the preview pixmap
0115     int height = 80;
0116     int width = 200;
0117     int count = m_colormap.count();
0118     pixmap = QPixmap(width, height);
0119     QPainter p(&pixmap);
0120     int i = 0;
0121     for (auto& color : m_colormap) {
0122         p.setPen(color);
0123         p.setBrush(color);
0124         p.drawRect(i * width / count, 0, width / count, height);
0125         ++i;
0126     }
0127 }
0128 
0129 /**
0130  * @brief Processes the json metadata file that contains the list of colormap collections.
0131  */
0132 void ColorMapsManager::loadCollections() {
0133     const QString& fileName = m_jsonDir + QLatin1String("/ColormapCollections.json");
0134     QFile file(fileName);
0135 
0136     if (file.open(QIODevice::ReadOnly)) {
0137         QJsonDocument document = QJsonDocument::fromJson(file.readAll());
0138         file.close();
0139         if (!document.isArray()) {
0140             QDEBUG("Invalid definition of " << fileName)
0141             return;
0142         }
0143 
0144         for (const QJsonValueRef col : document.array()) {
0145             const QJsonObject& collection = col.toObject();
0146             const QString& name = collection[QLatin1String("name")].toString();
0147             const QString& desc = collection[QLatin1String("description")].toString();
0148             m_collections[name] = desc;
0149         }
0150     } else
0151         QMessageBox::critical(nullptr,
0152                               i18n("File not found"),
0153                               i18n("Couldn't open the color map collections file %1. Please check your installation.", fileName));
0154 }