00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <QImage>
00026 #include <QPixmap>
00027 #include <QPainter>
00028 #include <QColor>
00029 #include <QRectF>
00030 #include <QDir>
00031
00032
00033 #include <kdebug.h>
00034 #include <kstandarddirs.h>
00035
00036
00037 #include "thememanager.h"
00038 #include "lskatglobal.h"
00039 #include "deck.h"
00040
00041
00042
00043 #define CARDBACK_SVGID "back"
00044
00045
00046 ThemeManager::ThemeManager(QString cards, QString deck, QString themefile, QObject* parent, int initialSize)
00047 : QObject(parent)
00048 {
00049 mScale = initialSize;
00050 mAspectRatio = 1.0;
00051 mCardAspectRatio = 1.0;
00052 mCardFile = cards;
00053 mDeckFile = deck;
00054 mRenderer = 0;
00055 mCardRenderer = 0;
00056 mDeckRenderer = 0;
00057
00058
00059 updateCardTheme(themefile, cards, deck);
00060 }
00061
00062
00063
00064 void ThemeManager::registerTheme(Themable* ob)
00065 {
00066 mObjects[ob] = 1;
00067 }
00068
00069
00070
00071 void ThemeManager::unregisterTheme(Themable* ob)
00072 {
00073 mObjects.remove(ob);
00074 }
00075
00076
00077
00078 void ThemeManager::updateTheme(Themable* ob)
00079 {
00080 ob->changeTheme();
00081 }
00082
00083
00084
00085 void ThemeManager::updateCardTheme(QString cards, QString deck)
00086 {
00087 updateCardTheme(mThemeFile, cards, deck);
00088 }
00089 void ThemeManager::updateCardTheme(QString themefile, QString cards, QString deck)
00090 {
00091 kDebug() << "ThemeManager Pixmap cards: "<< endl;
00092 kDebug() << " Cards = " << cards << endl;
00093 kDebug() << " Deck = " << deck << endl;
00094
00095
00096 mCardFile = cards;
00097
00098 KConfig cardInfo( cards+"/index.desktop", KConfig::OnlyLocal);
00099 KConfigGroup cardGroup(&cardInfo, "KDE Backdeck");
00100 QPointF cardSize = cardGroup.readEntry("BackSize", QPointF(1.0,1.0));
00101 QString cardSVG = cardGroup.readEntry("SVG", QString());
00102 kDebug() << "cardSize = " << cardSize << endl;
00103
00104 kDebug() << "SVG card = " << cardSVG << " is " << (!cardSVG.isNull()) << endl;
00105
00106 QString svgfile = cards+"/"+cardSVG;
00107
00108 mCardRenderer = 0;
00109 if (!cardSVG.isNull())
00110 {
00111 mCardRenderer = new KSvgRenderer(this);
00112 bool result = mCardRenderer->load(svgfile);
00113 if (!result)
00114 {
00115 kFatal() << "Cannot open file " << svgfile << endl;
00116 }
00117 kDebug() << "Rendering " << svgfile << endl;
00118 }
00119
00120
00121
00122 mDeckFile = deck;
00123 QString deckIndex = deck;
00124 deckIndex.replace(".png",".desktop");
00125
00126
00127 KConfig deckInfo( deckIndex, KConfig::OnlyLocal);
00128 KConfigGroup deckGroup(&deckInfo, "KDE Cards");
00129 QString deckSVG = deckGroup.readEntry("SVG", QString());
00130
00131 QString deckDir = deck;
00132 int pos = deck.lastIndexOf(QDir::separator());
00133 if (pos > 0) deckDir = deck.left(pos);
00134
00135
00136 svgfile = deckDir+"/"+deckSVG;
00137 kDebug() << "SVG deck = " << deckSVG << " is " << (!deckSVG.isNull()) << endl;
00138
00139 mDeckRenderer = 0;
00140 if (!deckSVG.isNull())
00141 {
00142 mDeckRenderer = new KSvgRenderer(this);
00143 bool result = mDeckRenderer->load(svgfile);
00144 if (!result)
00145 {
00146 kFatal() << "Cannot open file " << svgfile << endl;
00147 }
00148 kDebug() << "Rendering " << svgfile << endl;
00149 }
00150
00151
00152 updateTheme(themefile);
00153 }
00154
00155
00156
00157
00158 void ThemeManager::updateTheme(QString themefile)
00159 {
00160
00161 mPixmapCache.clear();
00162 mThemeFile = themefile;
00163
00164
00165 QString rcfile = KStandardDirs::locate("data", themefile);
00166 kDebug() << "ThemeManager LOAD with theme "<<rcfile << endl;
00167
00168
00169 mConfig = new KConfig(rcfile, KConfig::NoGlobals);
00170 QString svgfile = config("general").readEntry("svgfile");
00171 svgfile = KStandardDirs::locate("data", svgfile);
00172 kDebug() << "Reading SVG master file = " << svgfile << endl;
00173
00174 mAspectRatio = config("general").readEntry("aspect-ratio", 1.0);
00175 mCardAspectRatio = config("general").readEntry("card-aspect-ratio", 1.0);
00176 kDebug() << "Aspect ration = " << mAspectRatio << " Cards aspect=" << mCardAspectRatio<< endl;
00177
00178
00179
00180 mRenderer = new KSvgRenderer(this);
00181 bool result = mRenderer->load(svgfile);
00182 if (!result)
00183 {
00184 kFatal() << "Cannot open file " << svgfile << endl;
00185 }
00186
00187
00188 QHashIterator<Themable*, int> it(mObjects);
00189 while (it.hasNext())
00190 {
00191 it.next();
00192 Themable* ob = it.key();
00193 ob->changeTheme();
00194 }
00195 }
00196
00197
00198
00199 void ThemeManager::rescale(int scale)
00200 {
00201 if (global_debug > 1)
00202 {
00203 if (scale==mScale)
00204 kDebug() <<" No scale change to " << scale << " If this happends to often its BAD " << endl;
00205 }
00206
00207 mScale = scale;
00208 if (global_debug > 1) kDebug() << "Rescale to " << scale<<endl;
00209
00210 QHashIterator<Themable*, int> it(mObjects);
00211 while (it.hasNext())
00212 {
00213 it.next();
00214 Themable* ob = it.key();
00215 ob->changeTheme();
00216 }
00217 }
00218
00219
00220
00221 double ThemeManager::getScale()
00222 {
00223 return (double)mScale;
00224 }
00225
00226
00227
00228 KConfigGroup ThemeManager::config(QString id)
00229 {
00230 KConfigGroup grp = mConfig->group(id);
00231 return grp;
00232 }
00233
00234
00235
00236 QString ThemeManager::calcCardSVGId(int no)
00237 {
00238 const static char *ids[] = { "back",
00239 "1_club", "1_spade", "1_heart", "1_diamond",
00240 "king_club", "king_spade", "king_heart", "king_diamond",
00241 "queen_club", "queen_spade", "queen_heart", "queen_diamond",
00242 "jack_club", "jack_spade", "jack_heart", "jack_diamond",
00243 "10_club", "10_spade", "10_heart", "10_diamond",
00244 "9_club", "9_spade", "9_heart", "9_diamond",
00245 "8_club", "8_spade", "8_heart", "8_diamond",
00246 "7_club", "7_spade", "7_heart", "7_diamond",
00247 "6_club", "6_spade", "6_heart", "6_diamond",
00248 "5_club", "5_spade", "5_heart", "5_diamond",
00249 "4_club", "4_spade", "4_heart", "4_diamond",
00250 "3_club", "3_spade", "3_heart", "3_diamond",
00251 "2_club", "2_spade", "2_heart", "2_diamond",
00252 0 };
00253 return QString(ids[no]);
00254 }
00255
00256
00257
00258 const QPixmap ThemeManager::getCard(int suite, int cardtype, double width)
00259 {
00260
00261 int no = 4*cardtype+suite+1;
00262
00263 QPixmap pm;
00264
00265 if (mCardRenderer)
00266 {
00267 QString svgid = calcCardSVGId(no);
00268 QSize size = QSize(int(width), int(width/mCardAspectRatio) );
00269
00270 pm = getPixmap(mCardRenderer, svgid, size);
00271 }
00272
00273 else
00274 {
00275 QString dir = mCardFile;
00276 QString file = QString("%1.png").arg(no);
00277 if (mPixmapCache.contains(file))
00278 {
00279 pm = mPixmapCache[file];
00280 }
00281 else if (!pm.load(dir+"/"+file))
00282 {
00283 kError() << "Cannot load card file " << dir+file << endl;
00284 }
00285 else
00286 {
00287
00288 mPixmapCache[file] = pm;
00289 }
00290 }
00291
00292
00293 double aspect = double(pm.width())/double(pm.height());
00294 if (aspect/mCardAspectRatio >1.05 || aspect/mCardAspectRatio < 0.95)
00295 {
00296
00297 return pm.scaled(int(width), int(width/mCardAspectRatio),
00298 Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00299 }
00300 else
00301 {
00302 return pm.scaledToWidth(int(width), Qt::SmoothTransformation);
00303 }
00304 }
00305
00306
00307
00308 const QPixmap ThemeManager::getCardback(double width)
00309 {
00310 QPixmap pm;
00311
00312 if (mDeckRenderer)
00313 {
00314 QString svgid = QString(CARDBACK_SVGID);
00315 QSize size = QSize(int(width), int(width/mCardAspectRatio) );
00316 pm = getPixmap(mDeckRenderer, svgid, size);
00317 }
00318
00319 else
00320 {
00321 QString file = mDeckFile;
00322 if (mPixmapCache.contains(file))
00323 {
00324 pm = mPixmapCache[file];
00325 }
00326 else if (!pm.load(file))
00327 {
00328 kError() << "Cannot load deck file " << file << endl;
00329 }
00330 else
00331 {
00332
00333 mPixmapCache[file] = pm;
00334 }
00335 }
00336
00337
00338 double aspect = double(pm.width())/double(pm.height());
00339 if (aspect/mCardAspectRatio >1.05 || aspect/mCardAspectRatio < 0.95)
00340 {
00341
00342 return pm.scaled(int(width), int(width/mCardAspectRatio),
00343 Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00344 }
00345 else
00346 {
00347 return pm.scaledToWidth(int(width), Qt::SmoothTransformation);
00348 }
00349 }
00350
00351
00352
00353 const QPixmap ThemeManager::getPixmap(KSvgRenderer* renderer, QString svgid, QSize size)
00354 {
00355 if (size.width() < 1 || size.height() < 1)
00356 kFatal() << "ThemeManager::getPixmap Cannot create svgid ID " << svgid << " with zero size " << size << endl;
00357
00358 QPixmap pixmap;
00359
00360
00361 if (mPixmapCache.contains(svgid))
00362 {
00363 pixmap = mPixmapCache[svgid];
00364 if (pixmap.size() == size)
00365 {
00366 return pixmap;
00367 }
00368 }
00369
00370
00371 QImage image(size, QImage::Format_ARGB32_Premultiplied);
00372 image.fill(0);
00373 QPainter p(&image);
00374 renderer->render(&p, svgid);
00375 pixmap = QPixmap::fromImage(image);
00376 if (pixmap.isNull())
00377 kFatal() << "ThemeManager::getPixmap Cannot load svgid ID " << svgid << endl;
00378
00379
00380 mPixmapCache[svgid] = pixmap;
00381
00382 return pixmap;
00383 }
00384
00385
00386
00387 const QPixmap ThemeManager::getPixmap(QString svgid, QSize size)
00388 {
00389 return getPixmap(mRenderer, svgid, size);
00390 }
00391
00392
00393
00394 const QPixmap ThemeManager::getPixmap(QString svgid, double width)
00395 {
00396 QRectF rect = mRenderer->boundsOnElement(svgid);
00397 double factor = width/rect.width();
00398 QSize size = QSize(int(width), int(rect.height()*factor));
00399 return getPixmap(svgid, size);
00400 }
00401
00402
00403
00404
00405 const QPixmap ThemeManager::getPixmap(QString svgid, QString svgref, double refwidth)
00406 {
00407 QRectF refrect = mRenderer->boundsOnElement(svgref);
00408 QRectF rect = mRenderer->boundsOnElement(svgid);
00409 double factor = refwidth/refrect.width();
00410 QSize size = QSize(int(rect.width()*factor), int(rect.height()*factor));
00411 return getPixmap(svgid, size);
00412 }
00413
00414
00415
00416
00417
00418 Themable::Themable()
00419 {
00420 mScale = 1.0;
00421 mThemeManager = 0;
00422 }
00423
00424
00425
00426
00427 Themable::Themable(QString id, ThemeManager* thememanager)
00428 {
00429 mScale = 1.0;
00430 mId = id;
00431 mThemeManager = thememanager;
00432 if (!thememanager) return;
00433 thememanager->registerTheme(this);
00434 }
00435
00436
00437
00438 Themable::~Themable()
00439 {
00440 if (mThemeManager) mThemeManager->unregisterTheme(this);
00441 }
00442
00443
00444