Make the fact that the time is shown in hours and minutes more explicit.
[kdegames.git] / libkmahjongg / kmahjonggtileset.cpp
blob2bf53b415db1296d9271a948755c4c049e0bc45f
1 /*
2 Copyright (C) 1997 Mathias Mueller <in5y158@public.uni-hamburg.de>
3 Copyright (C) 2006 Mauricio Piacentini <mauricio@tabuleiro.com>
5 Libkmahjongg is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "kmahjonggtileset.h"
22 #include <klocale.h>
23 #include <kconfig.h>
24 #include <kconfiggroup.h>
25 #include <qimage.h>
26 #include <kstandarddirs.h>
27 #include <ksvgrenderer.h>
28 #include <QPainter>
29 #include <QPixmapCache>
30 #include <QFile>
31 #include <KDebug>
32 #include <QMap>
34 #include <stdlib.h>
36 class KMahjonggTilesetMetricsData
38 public:
39 short lvloffx; // used for 3D indentation, x value
40 short lvloffy; // used for 3D indentation, y value
41 short w; // tile width ( +border +shadow)
42 short h; // tile height ( +border +shadow)
43 short fw; // face width
44 short fh; // face height
46 KMahjonggTilesetMetricsData()
47 : lvloffx(0), lvloffy(0), w(0), h(0), fw(0), fh(0)
51 class KMahjonggTilesetPrivate
53 public:
54 KMahjonggTilesetPrivate() : isSVG(false), graphicsLoaded(false) {}
55 QList<QString> elementIdTable;
56 QMap<QString, QString> authorproperties;
58 KMahjonggTilesetMetricsData originaldata;
59 KMahjonggTilesetMetricsData scaleddata;
60 QString filename; // cache the last file loaded to save reloading it
61 QString graphicspath;
63 KSvgRenderer svg;
64 bool isSVG;
65 bool graphicsLoaded;
68 // ---------------------------------------------------------
70 KMahjonggTileset::KMahjonggTileset()
71 : d(new KMahjonggTilesetPrivate)
73 buildElementIdTable();
75 static bool _inited = false;
76 if (_inited)
77 return;
78 KGlobal::dirs()->addResourceType("kmahjonggtileset", "data", QString::fromLatin1("kmahjongglib/tilesets/"));
80 KGlobal::locale()->insertCatalog("libkmahjongglib");
81 _inited = true;
84 // ---------------------------------------------------------
86 KMahjonggTileset::~KMahjonggTileset() {
87 delete d;
90 void KMahjonggTileset::updateScaleInfo(short tilew, short tileh)
92 d->scaleddata.w = tilew;
93 d->scaleddata.h = tileh;
94 double ratio = ((qreal) d->scaleddata.w) / ((qreal) d->originaldata.w);
95 d->scaleddata.lvloffx = (short) (d->originaldata.lvloffx * ratio);
96 d->scaleddata.lvloffy = (short) (d->originaldata.lvloffy * ratio);
97 d->scaleddata.fw = (short) (d->originaldata.fw * ratio);
98 d->scaleddata.fh = (short) (d->originaldata.fh * ratio);
101 QSize KMahjonggTileset::preferredTileSize(const QSize & boardsize, int horizontalCells, int verticalCells)
103 //calculate our best tile size to fit the boardsize passed to us
104 qreal newtilew, newtileh, aspectratio;
105 qreal bw = boardsize.width();
106 qreal bh = boardsize.height();
108 //use tileface for calculation, with one complete tile in the sum for extra margin
109 qreal fullh = (d->originaldata.fh * verticalCells) + d->originaldata.h;
110 qreal fullw = (d->originaldata.fw * horizontalCells) + d->originaldata.w;
111 qreal floatw = d->originaldata.w;
112 qreal floath = d->originaldata.h;
114 if ((fullw/fullh)>(bw/bh)) {
115 //space will be left on height, use width as limit
116 aspectratio = bw/fullw;
117 } else {
118 aspectratio = bh/fullh;
120 newtilew = aspectratio * floatw;
121 newtileh = aspectratio * floath;
122 return QSize((short)newtilew, (short)newtileh);
125 bool KMahjonggTileset::loadDefault()
127 QString idx = "default.desktop";
129 QString tilesetPath = KStandardDirs::locate("kmahjonggtileset", idx);
130 kDebug() << "Inside LoadDefault(), located path at" << tilesetPath;
131 if (tilesetPath.isEmpty()) {
132 return false;
134 return loadTileset(tilesetPath);
137 QString KMahjonggTileset::authorProperty(const QString &key) const
139 return d->authorproperties[key];
142 short KMahjonggTileset::width() const
144 return d->scaleddata.w;
147 short KMahjonggTileset::height() const
149 return d->scaleddata.h;
152 short KMahjonggTileset::levelOffsetX() const
154 return d->scaleddata.lvloffx;
157 short KMahjonggTileset::levelOffsetY() const
159 return d->scaleddata.lvloffy;
163 short KMahjonggTileset::qWidth() const
165 return (short) (d->scaleddata.fw / 2.0);
168 short KMahjonggTileset::qHeight() const
170 return (short) (d->scaleddata.fh / 2.0);
173 QString KMahjonggTileset::path() const
175 return d->filename;
178 #define kTilesetVersionFormat 1
180 // ---------------------------------------------------------
181 bool KMahjonggTileset::loadTileset( const QString & tilesetPath)
184 QImage qiTiles;
185 kDebug() << "Attempting to load .desktop at" << tilesetPath;
187 //clear our properties map
188 d->authorproperties.clear();
190 // verify if it is a valid file first and if we can open it
191 QFile tilesetfile(tilesetPath);
192 if (!tilesetfile.open(QIODevice::ReadOnly)) {
193 return (false);
195 tilesetfile.close();
197 KConfig tileconfig(tilesetPath, KConfig::SimpleConfig);
198 KConfigGroup group = tileconfig.group("KMahjonggTileset");
200 d->authorproperties.insert("Name", group.readEntry("Name"));// Returns translated data
201 d->authorproperties.insert("Author", group.readEntry("Author"));
202 d->authorproperties.insert("Description", group.readEntry("Description"));
203 d->authorproperties.insert("AuthorEmail", group.readEntry("AuthorEmail"));
205 //Version control
206 int tileversion = group.readEntry("VersionFormat",0);
207 //Format is increased when we have incompatible changes, meaning that older clients are not able to use the remaining information safely
208 if (tileversion > kTilesetVersionFormat) {
209 return false;
212 QString graphName = group.readEntry("FileName");
214 d->graphicspath = KStandardDirs::locate("kmahjonggtileset", graphName);
215 kDebug() << "Using tileset at" << d->graphicspath;
216 //d->filename = graphicsPath;
218 //only SVG for now
219 d->isSVG = true;
220 if (d->graphicspath.isEmpty()) return (false);
222 d->originaldata.w = group.readEntry("TileWidth", 30);
223 d->originaldata.h = group.readEntry("TileHeight", 50);
224 d->originaldata.fw = group.readEntry("TileFaceWidth", 30);
225 d->originaldata.fh = group.readEntry("TileFaceHeight", 50);
226 d->originaldata.lvloffx = group.readEntry("LevelOffsetX", 10);
227 d->originaldata.lvloffy = group.readEntry("LevelOffsetY", 10);
229 //client application needs to call loadGraphics()
230 d->graphicsLoaded = false;
231 d->filename = tilesetPath;
233 /* if (d->isSVG) {
234 //really?
235 d->svg.load(graphicsPath);
236 if (d->svg.isValid()) {
237 d->filename = tilesetPath;
238 //invalidate our global cache
239 QPixmapCache::clear();
241 d->isSVG = true;
242 reloadTileset(QSize(d->originaldata.w, d->originaldata.h));
243 } else {
244 return( false );
246 } else {
247 //TODO add support for png??
248 return false;
251 return( true );
254 // ---------------------------------------------------------
255 bool KMahjonggTileset::loadGraphics()
257 if (d->graphicsLoaded == true) return (true) ;
258 if (d->isSVG) {
259 //really?
260 d->svg.load(d->graphicspath);
261 if (d->svg.isValid()) {
262 //invalidate our global cache
263 QPixmapCache::clear();
264 d->graphicsLoaded = true;
265 reloadTileset(QSize(d->originaldata.w, d->originaldata.h));
266 } else {
267 return( false );
269 } else {
270 //TODO add support for png??
271 return false;
274 return( true );
277 // ---------------------------------------------------------
278 bool KMahjonggTileset::reloadTileset( const QSize & newTilesize)
280 QString tilesetPath = d->filename;
282 if (QSize(d->scaleddata.w, d->scaleddata.h) == newTilesize) return false;
284 if (d->isSVG) {
285 if (d->svg.isValid()) {
286 updateScaleInfo(newTilesize.width(), newTilesize.height());
287 //rendering will be done when needed, automatically using the global cache
288 } else {
289 return( false );
291 } else {
292 //TODO add support for png???
293 return false;
296 return( true );
299 void KMahjonggTileset::buildElementIdTable() {
300 //Build a list for faster lookup of element ids, mapped to the enumeration used by GameData and BoardWidget
301 //Unselected tiles
302 for (short idx=1; idx<=4; idx++) {
303 d->elementIdTable.append(QString("TILE_%1").arg(idx));
305 //Selected tiles
306 for (short idx=1; idx<=4; idx++) {
307 d->elementIdTable.append(QString("TILE_%1_SEL").arg(idx));
309 //now faces
310 for (short idx=1; idx<=9; idx++) {
311 d->elementIdTable.append(QString("CHARACTER_%1").arg(idx));
313 for (short idx=1; idx<=9; idx++) {
314 d->elementIdTable.append(QString("BAMBOO_%1").arg(idx));
316 for (short idx=1; idx<=9; idx++) {
317 d->elementIdTable.append(QString("ROD_%1").arg(idx));
319 for (short idx=1; idx<=4; idx++) {
320 d->elementIdTable.append(QString("SEASON_%1").arg(idx));
322 for (short idx=1; idx<=4; idx++) {
323 d->elementIdTable.append(QString("WIND_%1").arg(idx));
325 for (short idx=1; idx<=3; idx++) {
326 d->elementIdTable.append(QString("DRAGON_%1").arg(idx));
328 for (short idx=1; idx<=4; idx++) {
329 d->elementIdTable.append(QString("FLOWER_%1").arg(idx));
333 QString KMahjonggTileset::pixmapCacheNameFromElementId(const QString & elementid) {
334 return authorProperty("Name")+ elementid + QString("W%1H%2").arg(d->scaleddata.w).arg(d->scaleddata.h);
337 QPixmap KMahjonggTileset::renderElement(short width, short height, const QString & elementid) {
338 //kDebug() << "render element" << elementid << width << height;
339 QImage qiRend(QSize(width, height),QImage::Format_ARGB32_Premultiplied);
340 qiRend.fill(0);
342 if (d->svg.isValid()) {
343 QPainter p(&qiRend);
344 d->svg.render(&p, elementid);
346 return QPixmap::fromImage(qiRend);
349 QPixmap KMahjonggTileset::selectedTile(int num) {
350 QPixmap pm;
351 QString elemId = d->elementIdTable.at(num+4);//selected offset in our idtable;
352 if (!QPixmapCache::find(pixmapCacheNameFromElementId(elemId), pm)) {
353 //use tile size
354 pm = renderElement(d->scaleddata.w, d->scaleddata.h, elemId);
355 QPixmapCache::insert(pixmapCacheNameFromElementId(elemId), pm);
357 return pm;
360 QPixmap KMahjonggTileset::unselectedTile(int num) {
361 QPixmap pm;
362 QString elemId = d->elementIdTable.at(num);
363 if (!QPixmapCache::find(pixmapCacheNameFromElementId(elemId), pm)) {
364 //use tile size
365 pm = renderElement(d->scaleddata.w, d->scaleddata.h, elemId);
366 QPixmapCache::insert(pixmapCacheNameFromElementId(elemId), pm);
368 return pm;
371 QPixmap KMahjonggTileset::tileface(int num) {
372 QPixmap pm;
373 if ((num + 8) >= d->elementIdTable.count()) {
374 kDebug() << "Client asked for invalid tileface id";
375 return pm;
378 QString elemId = d->elementIdTable.at(num + 8);//tileface offset in our idtable;
379 if (!QPixmapCache::find(pixmapCacheNameFromElementId(elemId), pm)) {
380 //use face size
381 pm = renderElement(d->scaleddata.fw, d->scaleddata.fh, elemId);
382 QPixmapCache::insert(pixmapCacheNameFromElementId(elemId), pm);
384 return pm;