summaryrefslogtreecommitdiffstats
path: root/ksim/library/themeloader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ksim/library/themeloader.cpp')
-rw-r--r--ksim/library/themeloader.cpp1266
1 files changed, 1266 insertions, 0 deletions
diff --git a/ksim/library/themeloader.cpp b/ksim/library/themeloader.cpp
new file mode 100644
index 0000000..7c42dcd
--- /dev/null
+++ b/ksim/library/themeloader.cpp
@@ -0,0 +1,1266 @@
+/* ksim - a system monitor for kde
+ *
+ * Copyright (C) 2001 Robbie Ward <linuxphreak@gmx.co.uk>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "themeloader.h"
+#include <ksimconfig.h>
+#include "themetypes.h"
+#include "common.h"
+
+#include <qfile.h>
+#include <qstringlist.h>
+#include <qvaluevector.h>
+#include <qregexp.h>
+#include <qapplication.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qimage.h>
+#include <qbitmap.h>
+
+#include <kdebug.h>
+#include <ksimpleconfig.h>
+#include <kglobalsettings.h>
+#include <kstandarddirs.h>
+#include <kglobal.h>
+
+class KSim::Theme::Private
+{
+ public:
+ Private(const QValueVector<QString> &names,
+ const QStringList &list) : fileNames(names),
+ imageTypes(list) {}
+
+ QStringList file;
+ QStringList dFile;
+ KConfig *globalReader;
+ QString altTheme;
+ QString location;
+ const QValueVector<QString> &fileNames;
+ const QStringList &imageTypes;
+ int alternative;
+ int font;
+ bool recolour;
+
+ QString readOption(const QString &entry,
+ bool useGlobal = true,
+ const QString &defValue = QString::null)
+ {
+ QString text;
+ QStringList::ConstIterator it;
+ for (it = file.begin(); it != file.end(); ++it) {
+ if ((*it).find(entry) != -1) {
+ text = QStringList::split("=", (*it))[1].stripWhiteSpace();
+ }
+ }
+
+ if (!text.isEmpty() || dFile.isEmpty())
+ return text;
+
+ QStringList::ConstIterator it2;
+ for (it2 = dFile.begin(); it2 != dFile.end(); ++it) {
+ if ((*it2).find(entry) != -1) {
+ text = QStringList::split("=", (*it2))[1].stripWhiteSpace();
+ }
+ }
+
+ if (!text.isEmpty())
+ return text;
+
+ if (!globalReader || !useGlobal)
+ return defValue;
+
+ text = globalReader->readEntry(entry, defValue);
+ return text;
+ }
+};
+
+class KSim::ThemeLoader::Private
+{
+ public:
+ QValueVector<QString> fileNames;
+ QStringList imageTypes;
+ KConfig *globalReader;
+ bool recolour;
+ QColor pixelColour;
+};
+
+bool KSim::Theme::operator==(const KSim::Theme &rhs) const
+{
+ return d == rhs.d;
+}
+
+bool KSim::Theme::operator!=(const KSim::Theme &rhs) const
+{
+ return !(operator==(rhs));
+}
+
+KSim::Theme &KSim::Theme::operator=(const KSim::Theme &rhs)
+{
+ if (*this == rhs)
+ return *this;
+
+ delete d;
+ d = rhs.d;
+ return *this;
+}
+
+KSim::Theme::~Theme()
+{
+ delete d;
+}
+
+const QString &KSim::Theme::path() const
+{
+ return d->location;
+}
+
+QString KSim::Theme::name() const
+{
+ QString name = d->location;
+ if (name.endsWith("/"))
+ name.remove(name.length() - 1, 1);
+
+ return name.remove(0, name.findRev("/") + 1);
+}
+
+QString KSim::Theme::author() const
+{
+ QString author(d->readOption("author", false));
+ return author.replace(QRegExp("\""), QString::null);
+}
+
+int KSim::Theme::fontItem() const
+{
+ return d->font;
+}
+
+int KSim::Theme::alternative() const
+{
+ return d->alternative;
+}
+
+int KSim::Theme::alternatives() const
+{
+ return d->readOption("theme_alternatives").toInt();
+}
+
+int KSim::Theme::chartWidthRef(int defValue) const
+{
+ return internalNumEntry("chart_width_ref", defValue);
+}
+
+int KSim::Theme::chartWidthMin(int defValue) const
+{
+ return internalNumEntry("chart_width_min", defValue);
+}
+
+bool KSim::Theme::scaling(bool defValue) const
+{
+ return internalNumEntry("allow_scaling", defValue);
+}
+
+int KSim::Theme::frameTopHeight(int defValue) const
+{
+ return KMIN(2, internalNumEntry("frame_top_height", defValue));
+}
+
+int KSim::Theme::frameBottomHeight(int defValue) const
+{
+ return KMIN(2, internalNumEntry("frame_bottom_height", defValue));
+}
+
+int KSim::Theme::frameLeftWidth(int defValue) const
+{
+ return KMIN(2, internalNumEntry("frame_left_width", defValue));
+}
+
+int KSim::Theme::frameRightWidth(int defValue) const
+{
+ return KMIN(2, internalNumEntry("frame_right_width", defValue));
+}
+
+QRect KSim::Theme::frameTopBorder(const QRect &defValue) const
+{
+ return internalRectEntry("frame_top_border", defValue);
+}
+
+QRect KSim::Theme::frameBottomBorder(const QRect &defValue) const
+{
+ return internalRectEntry("frame_bottom_border", defValue);
+}
+
+QRect KSim::Theme::frameLeftBorder(const QRect &defValue) const
+{
+ return internalRectEntry("frame_left_border", defValue);
+}
+
+QRect KSim::Theme::frameRightBorder(const QRect &defValue) const
+{
+ return internalRectEntry("frame_right_border", defValue);
+}
+
+QColor KSim::Theme::chartInColour(const QColor &defValue) const
+{
+ if (d->recolour)
+ return QApplication::palette().active().background();
+
+ return internalColourEntry("chart_in_color", defValue);
+}
+
+QColor KSim::Theme::chartInColourGrid(const QColor &defValue) const
+{
+ return internalColourEntry("chart_in_color_grid", defValue);
+}
+
+QColor KSim::Theme::chartOutColour(const QColor &defValue) const
+{
+ if (d->recolour)
+ return QApplication::palette().active().background();
+
+ return internalColourEntry("chart_out_color", defValue);
+}
+
+QColor KSim::Theme::chartOutColourGrid(const QColor &defValue) const
+{
+ return internalColourEntry("chart_out_color_grid", defValue);
+}
+
+bool KSim::Theme::bgGridMode(bool defValue) const
+{
+ return internalNumEntry("bg_grid_mode", defValue);
+}
+
+int KSim::Theme::rxLedX(int defValue) const
+{
+ return internalNumEntry("rx_led_x", defValue);
+}
+
+int KSim::Theme::rxLedY(int defValue) const
+{
+ return internalNumEntry("rx_led_y", defValue);
+}
+
+int KSim::Theme::txLedX(int defValue) const
+{
+ return internalNumEntry("tx_led_x", defValue);
+}
+
+int KSim::Theme::txLedY(int defValue) const
+{
+ return internalNumEntry("tx_led_y", defValue);
+}
+
+int KSim::Theme::mailFrames(int defValue) const
+{
+ return internalNumEntry("decal_mail_frames", defValue);
+}
+
+int KSim::Theme::mailDelay(int defValue) const
+{
+ return internalNumEntry("decal_mail_delay", defValue);
+}
+
+int KSim::Theme::krellSliderDepth(int defValue) const
+{
+ return internalNumEntry("krell_slider_depth", defValue);
+}
+
+int KSim::Theme::krellSliderXHot(int defValue) const
+{
+ return internalNumEntry("krell_slider_x_hot", defValue);
+}
+
+QRect KSim::Theme::sliderPanel(const QRect &defValue) const
+{
+ return internalRectEntry("bg_slider_panel_border", defValue);
+}
+
+QRect KSim::Theme::sliderMeter(const QRect &defValue) const
+{
+ return internalRectEntry("bg_slider_meter_border", defValue);
+}
+
+QRect KSim::Theme::timerBorder(const QRect &defValue) const
+{
+ return internalRectEntry("bg_timer_border", defValue);
+}
+
+QRect KSim::Theme::buttonPanelBorder(const QRect &defValue) const
+{
+ return internalRectEntry("button_panel_border", defValue);
+}
+
+QRect KSim::Theme::buttonMeterBorder(const QRect &defValue) const
+{
+ return internalRectEntry("button_meter_border", defValue);
+}
+
+QFont KSim::Theme::largeFont() const
+{
+ QString font(internalStringEntry("large_font", QString::null));
+
+ if (font.isEmpty())
+ return QApplication::font();
+
+ QFont themeFont;
+ themeFont.setRawName(font.replace(QRegExp("\""), QString::null));
+ return themeFont;
+}
+
+QFont KSim::Theme::normalFont() const
+{
+ QString font(internalStringEntry("normal_font", QString::null));
+
+ if (font.isEmpty())
+ return QApplication::font();
+
+ QFont themeFont;
+ themeFont.setRawName(font.replace(QRegExp("\""), QString::null));
+ return themeFont;
+}
+
+QFont KSim::Theme::smallFont() const
+{
+ QString font(internalStringEntry("small_font", QString::null));
+
+ if (font.isEmpty())
+ return QApplication::font();
+
+ QFont themeFont;
+ themeFont.setRawName(font.replace(QRegExp("\""), QString::null));
+ return themeFont;
+}
+
+QFont KSim::Theme::currentFont() const
+{
+ switch (fontItem()) {
+ case 0:
+ return smallFont();
+ break;
+ case 1:
+ return normalFont();
+ break;
+ case 2:
+ return largeFont();
+ break;
+ case 3:
+ return KSim::ThemeLoader::currentFont();
+ break;
+ case 4:
+ return KGlobalSettings::generalFont();
+ break;
+ }
+
+ return QFont();
+}
+
+QString KSim::Theme::meterPixmap(int type, bool useDefault) const
+{
+ QString imageFile = createType(type, d->location);
+ QString text;
+ QString file = d->fileNames[7];
+
+ QStringList::ConstIterator it;
+ for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) {
+ if (QFile::exists(imageFile + file + d->altTheme + "." + *it)) {
+ text = imageFile + file + d->altTheme + "." + *it;
+ break;
+ }
+ else
+ if (QFile::exists(d->location + file + d->altTheme + "." + *it)) {
+ text = d->location + file + d->altTheme + "." + *it;
+ break;
+ }
+ }
+
+ if (text.isNull() && useDefault)
+ return KSim::ThemeLoader::defaultUrl() + d->fileNames[7] + ".png";
+
+ return text;
+}
+
+QString KSim::Theme::panelPixmap(int type, bool useDefault) const
+{
+ QString imageFile = createType(type, d->location);
+ QString text;
+ QString file = d->fileNames[6];
+
+ QStringList::ConstIterator it;
+ for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) {
+ if (QFile::exists(imageFile + file + d->altTheme + "." + *it)) {
+ text = imageFile + file + d->altTheme + "." + *it;
+ break;
+ }
+ else
+ if (QFile::exists(d->location + file + d->altTheme + "." + *it)) {
+ text = d->location + file + d->altTheme + "." + *it;
+ break;
+ }
+ }
+
+ if (text.isNull() && useDefault)
+ return KSim::ThemeLoader::defaultUrl() + d->fileNames[6] + ".png";
+
+ return text;
+}
+
+QString KSim::Theme::ledPixmap(int type, bool useDefault) const
+{
+ QString imageFile = createType(type, d->location);
+ QString text;
+ QString file = d->fileNames[30];
+
+ QStringList::ConstIterator it;
+ for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) {
+ if (QFile::exists(imageFile + file + d->altTheme + "." + *it)) {
+ text = imageFile + file + d->altTheme + "." + *it;
+ break;
+ }
+ else
+ if (QFile::exists(d->location + file + d->altTheme + "." + *it)) {
+ text = d->location + file + d->altTheme + "." + *it;
+ break;
+ }
+ }
+
+ if (text.isNull() && useDefault)
+ return KSim::ThemeLoader::defaultUrl() + d->fileNames[30] + ".png";
+
+ return text;
+}
+
+QString KSim::Theme::framePixmap(int type, bool useDefault) const
+{
+ QString text;
+ QString file;
+
+ switch (type) {
+ case Types::TopFrame:
+ file = d->fileNames[0];
+ break;
+ case Types::BottomFrame:
+ file = d->fileNames[1];
+ break;
+ case Types::LeftFrame:
+ file = d->fileNames[2];
+ break;
+ case Types::RightFrame:
+ file = d->fileNames[3];
+ break;
+ }
+
+ QStringList::ConstIterator it;
+ for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) {
+ if (QFile::exists(d->location + file + d->altTheme + "." + *it)) {
+ text = d->location + file + d->altTheme + "." + *it;
+ break;
+ }
+ }
+
+ if (text.isNull() && useDefault) {
+ switch (type) {
+ case Types::TopFrame:
+ return KSim::ThemeLoader::defaultUrl() + d->fileNames[0] + ".png";
+ break;
+ case Types::BottomFrame:
+ return KSim::ThemeLoader::defaultUrl() + d->fileNames[1] + ".png";
+ break;
+ case Types::LeftFrame:
+ return KSim::ThemeLoader::defaultUrl() + d->fileNames[2] + ".png";
+ break;
+ case Types::RightFrame:
+ return KSim::ThemeLoader::defaultUrl() + d->fileNames[3] + ".png";
+ break;
+ }
+ }
+
+ return text;
+}
+
+QString KSim::Theme::chartPixmap(bool useDefault) const
+{
+ return loader(4, useDefault);
+}
+
+QString KSim::Theme::gridPixmap(bool useDefault) const
+{
+ return loader(5, useDefault);
+}
+
+QString KSim::Theme::krellPanelPixmap(bool useDefault) const
+{
+ return loader(14, useDefault);
+}
+
+QString KSim::Theme::krellMeterPixmap(bool useDefault) const
+{
+ return loader(15, useDefault);
+}
+
+QString KSim::Theme::krellSliderPixmap(bool useDefault) const
+{
+ return loader(16, useDefault);
+}
+
+QString KSim::Theme::dataInPixmap(bool useDefault) const
+{
+ return loader(18, useDefault);
+}
+
+QString KSim::Theme::dataOutPixmap(bool useDefault) const
+{
+ return loader(20, useDefault);
+}
+
+QString KSim::Theme::mailPixmap(bool useDefault) const
+{
+ QString imageFile = createType(KSim::Types::Mail, d->location);
+ QString text;
+ QString file = d->fileNames[25];
+
+ QStringList::ConstIterator it;
+ for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) {
+ if (QFile::exists(imageFile + file + d->altTheme + "." + *it)) {
+ text = imageFile + file + d->altTheme + "." + *it;
+ break;
+ }
+ else
+ if (QFile::exists(d->location + file + d->altTheme + "." + *it)) {
+ text = d->location + file + d->altTheme + "." + *it;
+ break;
+ }
+ }
+
+ if (text.isNull() && useDefault)
+ return KSim::ThemeLoader::defaultUrl()
+ + createType(KSim::Types::Mail, QString::null) + file + ".png";
+
+ return text;
+}
+
+QPixmap KSim::Theme::splitPixmap(PixmapType type, uint itemNo,
+ bool useDefault) const
+{
+ return pixmapToList(type, itemNo, useDefault)[itemNo];
+}
+
+QValueList<QPixmap> KSim::Theme::pixmapToList(PixmapType type,
+ int limitAmount, bool useDefault) const
+{
+ QImage image;
+ int xOffset = 0;
+ int yOffset = 0;
+ int depth = 0;
+
+ switch (type) {
+ case KrellPanel:
+ depth = readIntEntry("StylePanel", "*.krell_depth");
+ xOffset = readIntEntry("StylePanel", "*.krell_x_hot");
+ yOffset = readIntEntry("StylePanel", "*.krell_yoff");
+ image.load(krellPanelPixmap(useDefault));
+ kdDebug(2003) << "KSim::Theme: type = KrellPanel" << endl;
+ break;
+ case KrellMeter:
+ depth = readIntEntry("StyleMeter", "*.krell_depth");
+ xOffset = readIntEntry("StyleMeter", "*.krell_x_hot");
+ yOffset = readIntEntry("StyleMeter", "*.krell_yoff");
+ image.load(krellMeterPixmap(useDefault));
+ kdDebug(2003) << "KSim::Theme: type = KrellMeter" << endl;
+ break;
+ case KrellSlider:
+ depth = krellSliderDepth();
+ image.load(krellSliderPixmap(useDefault));
+ kdDebug(2003) << "KSim::Theme: type = KrellSlider" << endl;
+ break;
+ default:
+ return QValueList<QPixmap>();
+ break;
+ }
+
+ if (image.isNull())
+ return QValueList<QPixmap>();
+
+ QValueList<QPixmap> list;
+ int size = image.height();
+ if (depth)
+ size = image.height() / depth;
+
+ KSim::ThemeLoader::self().reColourImage(image);
+ QPixmap pixmap = image;
+ QPixmap newPixmap(image.width() - xOffset, size);
+
+ for (int i = 0; i < (depth + 1); ++i) {
+ newPixmap.fill();
+
+ if (pixmap.mask()) {
+ QBitmap mask(newPixmap.size());
+ bitBlt(&mask, 0, 0, pixmap.mask(), xOffset, yOffset,
+ image.width() - xOffset, size);
+ newPixmap.setMask(mask);
+ }
+
+ bitBlt(&newPixmap, 0, 0, &pixmap, xOffset, yOffset,
+ image.width() - xOffset, size);
+
+ list.append(newPixmap);
+
+ if (limitAmount == i)
+ break;
+ }
+
+ kdDebug(2003) << "KSim::Theme: size = " << size << endl;
+ kdDebug(2003) << "KSim::Theme: depth = " << depth << endl;
+ kdDebug(2003) << "KSim::Theme: xOffset = " << xOffset << endl;
+ kdDebug(2003) << "KSim::Theme: yOffset = " << xOffset << endl;
+
+ return list;
+}
+
+int KSim::Theme::transparency(const QString &itemType,
+ const QString &entry) const
+{
+ return readIntEntry(itemType, entry);
+}
+
+bool KSim::Theme::textShadow(const QString &itemType,
+ const QString &entry) const
+{
+ if (d->recolour)
+ return false;
+
+ QString shadow = readEntry(itemType, entry);
+ if (shadow.isEmpty() || shadow.findRev("none") != -1)
+ return false;
+
+ return true;
+}
+
+QColor KSim::Theme::shadowColour(const QString &itemType,
+ const QString &entry) const
+{
+ return readColourEntry(itemType, entry, 1);
+}
+
+QColor KSim::Theme::textColour(const QString &itemType,
+ const QString &entry) const
+{
+ if (d->recolour)
+ return KGlobalSettings::textColor();
+
+ return readColourEntry(itemType, entry, 0);
+}
+
+int KSim::Theme::readIntEntry(const QString &itemType,
+ const QString &entry) const
+{
+ QString entryName = itemType + " " + entry;
+ return internalNumEntry(entryName, 0);
+}
+
+QRect KSim::Theme::readRectEntry(const QString &itemType,
+ const QString &entry) const
+{
+ QString entryName = itemType + " " + entry;
+ return internalRectEntry(entryName, QRect());
+}
+
+QString KSim::Theme::readEntry(const QString &itemType,
+ const QString &entry) const
+{
+ QString entryName = itemType + " " + entry;
+ return internalStringEntry(entryName, QString::null);
+}
+
+QString KSim::Theme::readColourEntry(const QString &itemType,
+ const QString &entry, int row) const
+{
+ QString color = readEntry(itemType, entry);
+ if (color.isEmpty())
+ color = QString::fromLatin1("#ffffff #ffffff");
+
+ return QStringList::split(' ', color)[row];
+}
+
+QFont KSim::Theme::readFontEntry(const QString &itemType,
+ const QString &entry) const
+{
+ const QString &font = readEntry(itemType, entry);
+
+ // If only there was a better way of doing this
+ if (font == "small_font")
+ return smallFont();
+ else
+ if (font == "normal_font")
+ return normalFont();
+ else
+ if (font == "large_font")
+ return largeFont();
+
+ return QFont();
+}
+
+bool KSim::Theme::fontColours(int type, const QString &string, QFont &font,
+ QColor &text, QColor &shadow, bool &showShadow) const
+{
+ QString key = KSim::Types::typeToString(type, false);
+ bool repaint = false;
+
+ // set colours from the string 'key'
+ if (!readEntry(string, key + ".textcolor").isEmpty()) {
+ text= textColour(string, key + ".textcolor");
+ shadow = shadowColour(string, key + ".textcolor");
+ showShadow = textShadow(string, key + ".textcolor");
+ repaint = true;
+ }
+ else {
+ text= textColour(string, "*.textcolor");
+ shadow = shadowColour(string, "*.textcolor");
+ showShadow = textShadow(string, "*.textcolor");
+ }
+
+ // set fonts from the string 'key'
+ if (!readEntry(string, key + ".font").isEmpty()) {
+ if (KSim::ThemeLoader::currentFontItem() != 3) {
+ font = readFontEntry(string, key + ".font");
+ repaint = true;
+ }
+ }
+ else {
+ font = currentFont();
+ }
+
+ return repaint;
+}
+
+bool KSim::Theme::fontColours(const KSim::Base *const base, QFont &font,
+ QColor &text, QColor &shadow, bool &showShadow) const
+{
+ if (!base)
+ return false;
+
+ return fontColours(base->type(), base->configString(), font,
+ text, shadow, showShadow);
+}
+
+KSim::Theme::Theme()
+{
+ d = 0;
+}
+
+KSim::Theme::Theme(const QString &url, const QString &fileName, int alt,
+ const QValueVector<QString> &vector, const QStringList &list,
+ KConfig *globalReader)
+{
+ create(vector, list, globalReader);
+ init(url, fileName, alt);
+
+ KSim::Config::config()->setGroup("Misc");
+ d->recolour = KSim::Config::config()->readBoolEntry("ReColourTheme", false);
+}
+
+void KSim::Theme::create(const QValueVector<QString> &vector,
+ const QStringList &list, KConfig *globalReader)
+{
+ d = new Private(vector, list);
+ d->globalReader = globalReader;
+}
+
+void KSim::Theme::init(const QString &url, const QString &fileName, int alt)
+{
+ d->altTheme = KSim::ThemeLoader::alternativeAsString(alt);
+ d->location = url;
+ d->alternative = alt;
+ d->font = KSim::ThemeLoader::currentFontItem();
+
+ d->file = QStringList::split("\n", parseConfig(url, fileName));
+
+ if (alt != 0)
+ d->dFile = QStringList::split("\n", parseConfig(url, "gkrellmrc"));
+}
+
+void KSim::Theme::reparse(const QString &url, const QString &fileName, int alt)
+{
+ init(url, fileName, alt);
+}
+
+QString KSim::Theme::parseConfig(const QString &url,
+ const QString &fileName)
+{
+ return KSim::ThemeLoader::self().parseConfig(url, fileName);
+}
+
+QString KSim::Theme::loader(int value, bool useDefault) const
+{
+ QString text;
+ QString file = d->fileNames[value];
+
+ QStringList::ConstIterator it;
+ for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) {
+ if (QFile::exists(d->location + file + d->altTheme + "." + *it)) {
+ text = d->location + file + d->altTheme + "." + *it;
+ break;
+ }
+ }
+
+ if (text.isNull() && useDefault)
+ return KSim::ThemeLoader::defaultUrl() + d->fileNames[value] + ".png";
+
+ return text;
+}
+
+QString KSim::Theme::createType(int type, const QString &text) const
+{
+ if (type == Types::None)
+ return text;
+
+ return text + KSim::Types::typeToString(type);
+}
+
+void KSim::Theme::setRecolour(bool value)
+{
+ if (!d)
+ return;
+
+ d->recolour = value;
+}
+
+// Keep the ugliness here to make the rest
+// of the class readable
+int KSim::Theme::internalNumEntry(const QString &entry, int defValue) const
+{
+ return d->readOption(entry, true, QString::number(defValue)).toInt();
+}
+
+QRect KSim::Theme::internalRectEntry(const QString &entry,
+ const QRect &defValue) const
+{
+ QString rect;
+ rect += QString::number(defValue.left());
+ rect += ",";
+ rect += QString::number(defValue.top());
+ rect += ",";
+ rect += QString::number(defValue.width());
+ rect += ",";
+ rect += QString::number(defValue.height());
+
+ QStringList list = QStringList::split(",", d->readOption(entry, true, rect));
+ QRect rect2(list[0].toInt(), list[1].toInt(), list[2].toInt(), list[3].toInt());
+
+ return rect2;
+}
+
+QColor KSim::Theme::internalColourEntry(const QString &entry,
+ const QColor &defValue) const
+{
+ return d->readOption(entry, true, defValue.name());
+}
+
+QString KSim::Theme::internalStringEntry(const QString &entry,
+ const QString &defValue) const
+{
+ return d->readOption(entry, true, defValue);
+}
+
+// check if the dir is writable, if not generate the new file in the home dir
+#define KSIM_THEME_URL(url) \
+{ \
+}
+
+KSim::ThemeLoader *KSim::ThemeLoader::m_self = 0; // initialize pointer
+KSim::ThemeLoader &KSim::ThemeLoader::self()
+{
+ if (!m_self) { // is it the first call?
+ m_self = new KSim::ThemeLoader; // create sole instance
+ qAddPostRoutine(cleanup);
+ }
+
+ return *m_self; // address of sole instance
+}
+
+bool KSim::ThemeLoader::isDifferent() const
+{
+ // if the theme path, theme alternative or the
+ // specified font has changed then we should
+ // return true, else false
+
+ KSim::Config::config()->setGroup("Misc");
+ bool recolour = KSim::Config::config()->readBoolEntry("ReColourTheme", false);
+
+ return (current().path() != currentUrl()
+ || current().alternative() != currentAlternative()
+ || current().fontItem() != currentFontItem()
+ || d->recolour != recolour);
+}
+
+void KSim::ThemeLoader::reload()
+{
+ reColourItems();
+ grabColour();
+
+ if (!isDifferent())
+ return;
+
+ if (currentUrl() != defaultUrl()) {
+ if (!d->globalReader)
+ d->globalReader = new KConfig(defaultUrl() + "gkrellmrc_ksim");
+ }
+ else {
+ delete d->globalReader;
+ d->globalReader = 0;
+ }
+
+ if (m_theme.d)
+ m_theme.d->globalReader = d->globalReader;
+
+ QString fileName = QString::fromLatin1("gkrellmrc") + alternativeAsString();
+ m_theme.reparse(currentUrl(), fileName, currentAlternative());
+}
+
+const KSim::Theme &KSim::ThemeLoader::current() const
+{
+ return m_theme;
+}
+
+KSim::Theme KSim::ThemeLoader::theme(const QString &url,
+ const QString &rcFile, int alt) const
+{
+ return KSim::Theme(url, rcFile, alt, d->fileNames,
+ d->imageTypes, d->globalReader);
+}
+
+void KSim::ThemeLoader::reColourImage(QImage &image)
+{
+ if (!d->recolour || image.isNull())
+ return;
+
+ QColor color = QApplication::palette().active().background();
+ QImage output(image.width(), image.height(), 32);
+ output.setAlphaBuffer(image.hasAlphaBuffer());
+
+ Q_UINT32 r = color.red();
+ Q_UINT32 g = color.green();
+ Q_UINT32 b = color.blue();
+ Q_UINT32 *write = reinterpret_cast<Q_UINT32 *>(output.bits());
+ Q_UINT32 *read = reinterpret_cast<Q_UINT32 *>(image.bits());
+ int size = image.width() * image.height();
+
+ for (int pos = 0; pos < size; pos++)
+ {
+ QRgb basePix = static_cast<QRgb>(*read);
+
+ // Here, we assume that source is really gray, so R=G=B=I
+ // Use blue since it's very easy to extract.
+ Q_UINT32 i = qBlue(basePix);
+
+ Q_UINT32 cr = (r * i + 128) >> 8; // Fixed point..
+ Q_UINT32 cg = (g * i + 128) >> 8;
+ Q_UINT32 cb = (b * i + 128) >> 8;
+
+ Q_UINT32 alpha = qAlpha(basePix);
+ *write = qRgba(cr, cg, cb, alpha);
+ write++;
+ read++;
+ }
+
+ image = output;
+}
+
+QString KSim::ThemeLoader::parseConfig(const QString &url,
+ const QString &fileName)
+{
+ QFile origFile(url + fileName);
+
+ if (!origFile.open(IO_ReadOnly))
+ return QString::null;
+
+ QTextStream origStream(&origFile);
+ QString text;
+ QRegExp reg("\\*"); // regexp for '*' chars
+ QRegExp number("[0-9]+"); // regexp for all numbers
+ QRegExp numbers("[0-9]+,[0-9]+,[0-9]+,[0-9]+"); // regexp for int,int,int,int
+ QRegExp minus("[a-zA-Z]+ \\- [a-zA-Z]+"); // regexp for 'someText - someText'
+ while (!origStream.atEnd()) {
+ QString line(origStream.readLine().simplifyWhiteSpace());
+
+ if (line.find(reg) == 0) // find the location of the * comments
+ // replace all * comments with # comments so KConfig doesn't complain
+ line.replace(reg, "#");
+
+ if (line.find("#") == -1) { // find the location of the string 'gkrellmms'
+ if (line.findRev("=") == -1) { // if found we check for the string '='
+ int numLoc = line.findRev(numbers);
+ if (numLoc != -1)
+ // if '=' doesn't exist we add one so KConfig doesn't complain
+ line.insert(numLoc, " = ");
+
+ numLoc = line.findRev(number);
+ if (numLoc != -1)
+ // if '=' doesn't exist we add one so KConfig doesn't complain
+ line.insert(numLoc, " = ");
+
+ numLoc = line.findRev(minus);
+ if (numLoc != -1)
+ // replace the '-' with an '=' so KConfig doesn't get confused
+ line.replace(QRegExp("-"), "=");
+ }
+ }
+
+ text.append(line).append('\n');
+ }
+
+ return text;
+}
+
+// GKrellM themes seem to be rather inconsistant
+// so the following code changes the dir structure
+// of a theme to be more consistant, but the dir structure
+// is still compliant with GKrellM.
+void KSim::ThemeLoader::parseDir(const QString &url, int alt)
+{
+ if ( !QFileInfo( url ).isWritable() && currentName() != "ksim" )
+ {
+ QString homePath = QDir::current().path();
+ homePath = locateLocal( "data", "ksim" )
+ + QString::fromLatin1( "/themes" )
+ + homePath.right( homePath.length()
+ - homePath.findRev( QRegExp( "\\/" ),
+ homePath.length() ) );
+
+ if ( !QFile::exists( homePath ) )
+ KStandardDirs::makeDir( homePath );
+
+ kdWarning() << "Cant write to current dir, setting dir to "
+ << homePath << endl;
+
+ QDir::setCurrent( homePath );
+ }
+
+ int alternatives = ++alt;
+
+ QStringList formats;
+ QStringList panels;
+ QStringList meters;
+
+ formats << "png" << "jpg" << "jpeg" << "gif" << "xpm";
+ panels << "inet" << "net" << "proc" << "cpu" << "disk";
+ meters << "mem" << "fs" << "mail" << "apm" << "uptime"
+ << "clock" << "cal" << "timer" << "host" << "swap";
+
+ QDir directory;
+ for (int i = 0; i < alternatives; ++i) {
+ QString altString = KSim::ThemeLoader::alternativeAsString(i);
+ if (alternatives == 1 || i == 0)
+ altString = QString::null;
+
+ QStringList::ConstIterator format;
+ for (format = formats.begin(); format != formats.end(); ++format) {
+ // go through the meters array and move the files to the correct dir/filename
+ QStringList::Iterator meter;
+ for (meter = meters.begin(); meter != meters.end(); ++meter) {
+ QString bgMeter = QString::fromLatin1("bg_meter_");
+ if (QFile::exists(bgMeter + (*meter) + altString + "." + (*format))) {
+ if (KStandardDirs::makeDir(url + (*meter)))
+ directory.rename(bgMeter + (*meter) + altString + "." + (*format),
+ (*meter) + "/bg_meter" + altString + "." + (*format));
+ }
+ }
+
+ // go through the panels array and move the files to the correct dir/filename
+ QStringList::ConstIterator panel;
+ for (panel = panels.begin(); panel != panels.end(); ++panel) {
+ QString bgPanel = QString::fromLatin1("bg_panel_");
+ if (QFile::exists(bgPanel + (*panel) + altString + "." + (*format))) {
+ if (KStandardDirs::makeDir(url + (*panel)))
+ directory.rename(bgPanel + (*panel) + altString + "." + (*format),
+ (*panel) + "/bg_panel" + altString + "." + (*format));
+ }
+ }
+
+ // fix stupid themes that have a bg_panel image in the host dir
+ QString tempFile = QString::fromLatin1("host/bg_panel");
+ if (QFile::exists(tempFile + altString + "." + (*format)))
+ directory.rename(tempFile + altString + "." + (*format), "host/bg_meter"
+ + altString + "." + (*format));
+
+ // move decal_net_leds* to the net folder to be more consistant
+ tempFile = QString::fromLatin1("decal_net_leds");
+ if (QFile::exists(tempFile + altString + "." + (*format))) {
+ if (KStandardDirs::makeDir(url + "net"))
+ directory.rename(tempFile + altString + "." + (*format),
+ "net/decal_net_leds" + altString + "." + (*format));
+ }
+ }
+ }
+}
+
+void KSim::ThemeLoader::validate()
+{
+ if (!QFile::exists(currentUrl())) {
+ KSim::Config::config()->setGroup("Theme");
+ KSim::Config::config()->writeEntry("Name", "ksim");
+ KSim::Config::config()->writeEntry("Alternative", 0);
+ KSim::Config::config()->sync();
+ }
+}
+
+void KSim::ThemeLoader::themeColours(QWidget *widget)
+{
+ widget->setEraseColor(d->pixelColour);
+}
+
+QString KSim::ThemeLoader::currentName()
+{
+ KSim::Config::config()->setGroup("Theme");
+ return KSim::Config::config()->readEntry("Name", "ksim");
+}
+
+QString KSim::ThemeLoader::currentUrl()
+{
+ KSim::Config::config()->setGroup("Theme");
+ QString folder(KSim::Config::config()->readEntry("Name"));
+ folder.prepend("ksim/themes/").append("/");
+ QString dirName(KGlobal::dirs()->findResourceDir("data", folder));
+ dirName += folder;
+
+ return dirName;
+}
+
+QString KSim::ThemeLoader::defaultUrl()
+{
+ return KGlobal::dirs()->findDirs("data", "ksim/themes/ksim").first();
+}
+
+int KSim::ThemeLoader::currentAlternative()
+{
+ KSim::Config::config()->setGroup("Theme");
+ int alternative = KSim::Config::config()->readNumEntry("Alternative");
+
+ if ( alternative > self().current().alternatives() )
+ alternative = self().current().alternatives();
+
+ return alternative;
+}
+
+QString KSim::ThemeLoader::alternativeAsString(int alt)
+{
+ int alternative = (alt == -1 ? currentAlternative() : alt);
+ return (alternative == 0 ? QString::null : QString::fromLatin1("_")
+ + QString::number(alternative));
+}
+
+QFont KSim::ThemeLoader::currentFont()
+{
+ if (currentFontItem() != 3)
+ return self().current().currentFont();
+
+ KSim::Config::config()->setGroup("Theme");
+ return KSim::Config::config()->readFontEntry("Font");
+}
+
+int KSim::ThemeLoader::currentFontItem()
+{
+ KSim::Config::config()->setGroup("Theme");
+ return KSim::Config::config()->readNumEntry("FontItem", 0);
+}
+
+KSim::ThemeLoader::ThemeLoader()
+{
+ m_self = this;
+
+ d = new Private;
+ d->imageTypes << "png" << "jpg" << "jpeg" << "xpm" << "gif";
+
+ if (currentUrl() != defaultUrl())
+ d->globalReader = new KConfig(defaultUrl() + "gkrellmrc_ksim");
+ else
+ d->globalReader = 0;
+
+ d->fileNames.resize(31);
+ d->fileNames[0] = "frame_top";
+ d->fileNames[1] = "frame_bottom";
+ d->fileNames[2] = "frame_left";
+ d->fileNames[3] = "frame_right";
+ d->fileNames[4] = "bg_chart";
+ d->fileNames[5] = "bg_grid";
+ d->fileNames[6] = "bg_panel";
+ d->fileNames[7] = "bg_meter";
+ d->fileNames[8] = "bg_slider_panel";
+ d->fileNames[9] = "bg_slider_meter";
+ d->fileNames[10] = "button_panel_in";
+ d->fileNames[11] = "button_panel_out";
+ d->fileNames[12] = "button_meter_in";
+ d->fileNames[13] = "button_meter_out";
+ d->fileNames[14] = "krell_panel";
+ d->fileNames[15] = "krell_meter";
+ d->fileNames[16] = "krell_slider";
+ d->fileNames[17] = "decal_misc";
+ d->fileNames[18] = "data_in";
+ d->fileNames[19] = "data_in_grid";
+ d->fileNames[20] = "data_out";
+ d->fileNames[21] = "data_out_grid";
+ d->fileNames[22] = "krell";
+ d->fileNames[23] = "spacer_top";
+ d->fileNames[24] = "spacer_bottom";
+ d->fileNames[25] = "decal_mail";
+ d->fileNames[26] = "krell_penguin";
+ d->fileNames[27] = "bg_volt";
+ d->fileNames[28] = "decal_timer_button";
+ d->fileNames[29] = "bg_timer";
+ d->fileNames[30] = "decal_net_leds";
+
+ m_theme.create(d->fileNames, d->imageTypes, d->globalReader);
+
+ QString fileName = QString::fromLatin1("gkrellmrc") + alternativeAsString();
+ m_theme.init(currentUrl(), fileName, currentAlternative());
+
+ reColourItems();
+ grabColour();
+}
+
+KSim::ThemeLoader::~ThemeLoader()
+{
+ delete d->globalReader;
+ delete d;
+}
+
+void KSim::ThemeLoader::cleanup()
+{
+ if (!m_self)
+ return;
+
+ delete m_self;
+ m_self = 0;
+}
+
+void KSim::ThemeLoader::reColourItems()
+{
+ KSim::Config::config()->setGroup("Misc");
+ d->recolour = KSim::Config::config()->readBoolEntry("ReColourTheme", false);
+ m_theme.setRecolour(d->recolour);
+}
+
+void KSim::ThemeLoader::grabColour()
+{
+ KSim::Config::config()->setGroup("Theme");
+ QPoint pos(2, 2);
+ pos = KSim::Config::config()->readPointEntry("PixelLocation", &pos);
+
+ QImage image(current().meterPixmap(Types::None));
+ reColourImage(image);
+ d->pixelColour = image.pixel(pos.x(), pos.y());
+}