File indexing completed on 2024-04-21 04:05:21

0001 /*
0002     SPDX-FileCopyrightText: 1997 Mathias Mueller <in5y158@public.uni-hamburg.de>
0003     SPDX-FileCopyrightText: 2006 Mauricio Piacentini <mauricio@tabuleiro.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 // own
0009 #include "kmahjonggbackground.h"
0010 
0011 // Qt
0012 #include <QFile>
0013 #include <QPainter>
0014 #include <QPixmap>
0015 #include <QPixmapCache>
0016 #include <QSvgRenderer>
0017 #include <QGuiApplication>
0018 
0019 // KF
0020 #include <KConfig>
0021 #include <KConfigGroup>
0022 #include <KLocalizedString>
0023 
0024 // LibKMahjongg
0025 #include "libkmahjongg_debug.h"
0026 
0027 class KMahjonggBackgroundPrivate
0028 {
0029 public:
0030     KMahjonggBackgroundPrivate() = default;
0031 
0032 public:
0033     QString name;
0034     QString description;
0035     QString license;
0036     QString copyrightText;
0037     QString version;
0038     QString website;
0039     QString bugReportUrl;
0040     QString authorName;
0041     QString authorEmailAddress;
0042 
0043     QString pixmapCacheNameFromElementId(const QString &elementid, short width, short height);
0044     QPixmap renderBG(short width, short height);
0045 
0046     QPixmap backgroundPixmap;
0047     QBrush backgroundBrush;
0048     QString filename;
0049     QString graphicspath;
0050     short w = 1;
0051     short h = 1;
0052 
0053     QSvgRenderer svg;
0054 
0055     bool graphicsLoaded = false;
0056     bool isPlain = false;
0057     bool isTiled = true;
0058     bool isSVG = false;
0059 };
0060 
0061 KMahjonggBackground::KMahjonggBackground()
0062     : d_ptr(new KMahjonggBackgroundPrivate)
0063 {
0064 }
0065 
0066 KMahjonggBackground::~KMahjonggBackground() = default;
0067 
0068 bool KMahjonggBackground::loadDefault()
0069 {
0070     // Set default background here.
0071     const QString bgPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kmahjongglib/backgrounds/egyptian.desktop"));
0072     qCDebug(LIBKMAHJONGG_LOG) << "Inside LoadDefault(), located background at" << bgPath;
0073     if (bgPath.isEmpty()) {
0074         return false;
0075     }
0076     return load(bgPath, 0, 0);
0077 }
0078 
0079 #define kBGVersionFormat 1
0080 
0081 bool KMahjonggBackground::load(const QString &file, short width, short height)
0082 {
0083     Q_D(KMahjonggBackground);
0084 
0085     // qCDebug(LIBKMAHJONGG_LOG) << "Background loading";
0086     d->isSVG = false;
0087 
0088     // qCDebug(LIBKMAHJONGG_LOG) << "Attempting to load .desktop at" << file;
0089 
0090     // verify if it is a valid file first and if we can open it
0091     QFile bgfile(file);
0092     if (!bgfile.open(QIODevice::ReadOnly)) {
0093         return false;
0094     }
0095     bgfile.close();
0096 
0097     KConfig bgconfig(file, KConfig::SimpleConfig);
0098     KConfigGroup group = bgconfig.group(QStringLiteral("KMahjonggBackground"));
0099 
0100     d->isPlain = group.readEntry("Plain", 0) != 0;
0101     d->name = group.readEntry("Name"); // Returns translated data
0102     d->description = group.readEntry("Description");
0103     d->license = group.readEntry("License");
0104     d->copyrightText = group.readEntry("Copyright");
0105     d->version = group.readEntry("Version");
0106     d->website = group.readEntry("Website");
0107     d->bugReportUrl = group.readEntry("BugReportUrl");
0108     d->authorName = group.readEntry("Author");
0109     d->authorEmailAddress = group.readEntry("AuthorEmail");
0110 
0111     // Version control
0112     int bgversion = group.readEntry("VersionFormat", 0);
0113     // Format is increased when we have incompatible changes, meaning that older clients are not able to use the remaining information safely
0114     if (bgversion > kBGVersionFormat) {
0115         return false;
0116     }
0117 
0118     if (d->isPlain) {
0119         // qCDebug(LIBKMAHJONGG_LOG) << "Using plain background";
0120         d->graphicspath.clear();
0121         d->filename = file;
0122         return true;
0123     }
0124 
0125     QString graphName = group.readEntry("FileName");
0126 
0127     d->graphicspath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kmahjongglib/backgrounds/") + graphName);
0128 
0129     qCDebug(LIBKMAHJONGG_LOG) << "Using background at" << d->graphicspath;
0130 
0131     if (d->graphicspath.isEmpty()) {
0132         return false;
0133     }
0134 
0135     if (group.readEntry("Tiled", 0) != 0) {
0136         d->w = group.readEntry("Width", 0);
0137         d->h = group.readEntry("Height", 0);
0138         d->isTiled = true;
0139     } else {
0140         d->w = width;
0141         d->h = height;
0142         d->isTiled = false;
0143     }
0144     d->graphicsLoaded = false;
0145     d->filename = file;
0146     return true;
0147 }
0148 
0149 bool KMahjonggBackground::loadGraphics()
0150 {
0151     Q_D(KMahjonggBackground);
0152 
0153     if (d->graphicsLoaded || d->isPlain) {
0154         return true;
0155     }
0156 
0157     d->svg.load(d->graphicspath);
0158     if (d->svg.isValid()) {
0159         d->isSVG = true;
0160     } else {
0161         // qCDebug(LIBKMAHJONGG_LOG) << "could not load svg";
0162         return false;
0163     }
0164     return true;
0165 }
0166 
0167 void KMahjonggBackground::sizeChanged(int newW, int newH)
0168 {
0169     Q_D(KMahjonggBackground);
0170 
0171     // in tiled mode we do not care about the whole field size
0172     if (d->isTiled || d->isPlain) {
0173         return;
0174     }
0175 
0176     if (newW == d->w && newH == d->h) {
0177         return;
0178     }
0179     d->w = newW;
0180     d->h = newH;
0181 }
0182 
0183 QString KMahjonggBackgroundPrivate::pixmapCacheNameFromElementId(const QString &elementid, short width, short height)
0184 {
0185     return name + elementid + QStringLiteral("W%1H%2").arg(width).arg(height);
0186 }
0187 
0188 QPixmap KMahjonggBackgroundPrivate::renderBG(short width, short height)
0189 {
0190     QPixmap qiRend(width, height);
0191     qiRend.fill(Qt::transparent);
0192 
0193     if (svg.isValid()) {
0194         QPainter p(&qiRend);
0195         svg.render(&p);
0196     }
0197     return qiRend;
0198 }
0199 
0200 QBrush &KMahjonggBackground::getBackground()
0201 {
0202     Q_D(KMahjonggBackground);
0203 
0204     if (d->isPlain) {
0205         d->backgroundBrush = QBrush(QPixmap());
0206     } else {
0207         const qreal dpr = qApp->devicePixelRatio();
0208         const short width = d->w * dpr;
0209         const short height = d->h * dpr;
0210 
0211         // using raw pixmap size with cache id, as the rendering is done dpr-ignorant
0212         const QString pixmapCacheName = d->pixmapCacheNameFromElementId(d->filename, width, height);
0213         if (!QPixmapCache::find(pixmapCacheName, &d->backgroundPixmap)) {
0214             d->backgroundPixmap = d->renderBG(width, height);
0215             d->backgroundPixmap.setDevicePixelRatio(dpr);
0216             QPixmapCache::insert(pixmapCacheName, d->backgroundPixmap);
0217         }
0218         d->backgroundBrush = QBrush(d->backgroundPixmap);
0219     }
0220     return d->backgroundBrush;
0221 }
0222 
0223 QString KMahjonggBackground::path() const
0224 {
0225     Q_D(const KMahjonggBackground);
0226 
0227     return d->filename;
0228 }
0229 
0230 QString KMahjonggBackground::name() const
0231 {
0232     Q_D(const KMahjonggBackground);
0233 
0234     return d->name;
0235 }
0236 
0237 QString KMahjonggBackground::description() const
0238 {
0239     Q_D(const KMahjonggBackground);
0240 
0241     return d->description;
0242 }
0243 
0244 QString KMahjonggBackground::license() const
0245 {
0246     Q_D(const KMahjonggBackground);
0247 
0248     return d->license;
0249 }
0250 
0251 QString KMahjonggBackground::copyrightText() const
0252 {
0253     Q_D(const KMahjonggBackground);
0254 
0255     return d->copyrightText;
0256 }
0257 
0258 QString KMahjonggBackground::version() const
0259 {
0260     Q_D(const KMahjonggBackground);
0261 
0262     return d->version;
0263 }
0264 
0265 QString KMahjonggBackground::website() const
0266 {
0267     Q_D(const KMahjonggBackground);
0268 
0269     return d->website;
0270 }
0271 
0272 QString KMahjonggBackground::bugReportUrl() const
0273 {
0274     Q_D(const KMahjonggBackground);
0275 
0276     return d->bugReportUrl;
0277 }
0278 
0279 QString KMahjonggBackground::authorName() const
0280 {
0281     Q_D(const KMahjonggBackground);
0282 
0283     return d->authorName;
0284 }
0285 
0286 QString KMahjonggBackground::authorEmailAddress() const
0287 {
0288     Q_D(const KMahjonggBackground);
0289 
0290     return d->authorEmailAddress;
0291 }
0292 
0293 bool KMahjonggBackground::isPlain() const
0294 {
0295     Q_D(const KMahjonggBackground);
0296 
0297     return d->isPlain;
0298 }