• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdeutils
  • Sitemap
  • Contact Us
 

superkaramba

karamba.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003-2004 Adam Geitgey <adam@rootnode.org>
00003  * Copyright (C) 2003 Hans Karlsson <karlsson.h@home.se>
00004  * Copyright (C) 2004,2005 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
00005  * Copyright (c) 2005 Ryan Nickell <p0z3r@earthlink.net>
00006  * Copyright (c) 2007 Alexander Wiedenbruch <mail@wiedenbruch.de>
00007  *
00008  * This file is part of SuperKaramba.
00009  *
00010  *  SuperKaramba is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  SuperKaramba is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with SuperKaramba; if not, write to the Free Software
00022  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00023  ****************************************************************************/
00024 
00025 #include "karamba.h"
00026 #include "karamba.moc"
00027 
00028 #include <QGraphicsView>
00029 #include <QGraphicsScene>
00030 #include <QStack>
00031 #include <QDesktopWidget>
00032 #include <QApplication>
00033 #include <QX11Info>
00034 #include <QBitmap>
00035 #include <QSignalMapper>
00036 
00037 #include <KDebug>
00038 #include <KWindowSystem>
00039 #include <KIcon>
00040 #include <KLocale>
00041 #include <KDirWatch>
00042 #include <KMenu>
00043 #include <KConfig>
00044 #include <KToggleAction>
00045 #include <KCmdLineArgs>
00046 
00047 #include "config-superkaramba.h"
00048 
00049 #include "karambamanager.h"
00050 
00051 #include "meters/textfield.h"
00052 #include "meters/richtextlabel.h"
00053 #include "meters/bar.h"
00054 #include "meters/graph.h"
00055 #include "meters/textlabel.h"
00056 #include "meters/input.h"
00057 #include "meters/imagelabel.h"
00058 #include "meters/clickarea.h"
00059 #include "meters/clickmap.h"
00060 
00061 #include "sensors/sensor.h"
00062 #include "sensors/mem.h"
00063 #include "sensors/disk.h"
00064 #include "sensors/network.h"
00065 #include "sensors/date.h"
00066 #include "sensors/program.h"
00067 #include "sensors/sensorparams.h"
00068 #include "sensors/textfile.h"
00069 #include "sensors/rss.h"
00070 #include "sensors/uptime.h"
00071 #include "sensors/lmsensor.h"
00072 #include "sensors/cpu.h"
00073 
00074 #ifdef PLASMASENSOR_ENABLED
00075     #include "sensors/plasmaengine.h"
00076 #endif
00077 
00078 #include "python/karamba.h"
00079 
00080 #include "karambaapp.h"
00081 #include "systemtray.h"
00082 #include "karambainterface.h"
00083 #include "mainwidget.h"
00084 #include "lineparser.h"
00085 #include "themelocale.h"
00086 #include "superkarambasettings.h"
00087 
00088 extern "C" {
00089     KDE_EXPORT QGraphicsItemGroup* startKaramba(const KUrl &theme, QGraphicsView *view)
00090     {
00091         return new Karamba(theme, view);
00092     }
00093 }
00094 
00095 class Karamba::Private
00096 {
00097     public:
00098         ThemeFile theme;
00099         QGraphicsScene *scene;
00100         QGraphicsView *view;
00101 
00102         KWindowSystem *KWinModule;
00103 
00104         bool useKross;
00105 #ifdef PYTHON_INCLUDE_PATH
00106         KarambaPython *python;
00107 #endif
00108         KarambaInterface *interface;
00109 
00110         bool foundKaramba;
00111         bool onTop;
00112         bool managed;
00113 
00114         NETWinInfo *info;
00115 
00116         QRect size;
00117 
00118         u_int desktop;
00119 
00120         u_int interval;
00121 
00122         char tempUnit;
00123 
00124         TextField *defaultTextField;
00125 
00126         int scaleStep;
00127         bool showMenu;
00128 
00129         QList<Sensor*> sensorList;
00130         QMap<QString, Sensor*> sensorMap;
00131 
00132         KMenu *popupMenu;
00133         KToggleAction *toggleLocked;
00134         KAction* reloadTheme;
00135         KMenu *themeConfMenu;
00136         KMenu *toDesktopMenu;
00137         KMenu *globalMenu;
00138 
00139         QTimer stepTimer;
00140 
00141         QSignalMapper *signalMapperConfig;
00142         QSignalMapper *signalMapperDesktop;
00143 
00144         KConfig *config;
00145 
00146         int instance;
00147 
00148         QList<KMenu*> menuList;
00149 
00150         QString prettyName;
00151 
00152         QString storedData;
00153 
00154         double updateTime;
00155 
00156         bool wantRightButton;
00157 
00158         QPoint mouseClickPos;
00159 
00160         bool globalView;
00161 
00162         bool subTheme;
00163 
00164         QPoint themeCenter;
00165 
00166         QGraphicsItemAnimation *animation;
00167         QTimeLine *timer;
00168 
00169         //OrgKdeKdesktopBackgroundInterface* backgroundInterface;
00170 
00171         bool useFancyEffects;
00172         bool useAntialiasing;
00173 
00174         bool errorInInit;
00175 
00176         K3Process *currProcess;
00177         Systemtray *systray;
00178 
00179         Private(QGraphicsView *view, int instance, bool subTheme) :
00180             scene(view ? view->scene() : 0),
00181             view(view),
00182             KWinModule(0),
00183             useKross(true),
00184 #ifdef PYTHON_INCLUDE_PATH
00185             python(0),
00186 #endif
00187             interface(0),
00188             foundKaramba(false),
00189             onTop(false),
00190             managed(false),
00191             info(0),
00192             desktop(0),
00193             interval(0),
00194             tempUnit('C'),
00195             defaultTextField(0),
00196             scaleStep(-1),
00197             showMenu(false),
00198             popupMenu(0),
00199             toggleLocked(0),
00200             reloadTheme(0),
00201             themeConfMenu(0),
00202             toDesktopMenu(0),
00203             globalMenu(0),
00204             signalMapperConfig(0),
00205             signalMapperDesktop(0),
00206             config(0),
00207             instance(instance),
00208             storedData(""),
00209             wantRightButton(false),
00210             globalView(view ? true : false),
00211             subTheme(subTheme),
00212             animation(0),
00213             timer(0),
00214             //backgroundInterface(0),
00215             useFancyEffects(true),
00216             useAntialiasing(true),
00217             errorInInit(false),
00218             currProcess(0),
00219             systray(0)
00220         {
00221         }
00222 
00223         ~Private()
00224         {
00225             delete config;
00226 
00227             delete info;
00228 
00229 #ifdef PYTHON_INCLUDE_PATH
00230             if (python) {
00231                 delete python;
00232             }
00233 #endif
00234 
00235             if (interface) {
00236                 delete interface;
00237             }
00238 
00239             qDeleteAll(sensorList);
00240             sensorList.clear();
00241 
00242             delete toDesktopMenu;
00243             delete themeConfMenu,
00244             delete toggleLocked;
00245             delete reloadTheme;
00246             delete popupMenu;
00247 
00248             delete animation;
00249             delete timer;
00250 
00251             //delete backgroundInterface;
00252 
00253             if (!globalView) {
00254                 delete view;
00255                 delete scene;
00256             }
00257 
00258             delete currProcess;
00259             delete systray;
00260         }
00261 };
00262 
00263 Karamba::Karamba(const KUrl &themeFile, QGraphicsView *view, int instance, bool subTheme, const QPoint &startPos, bool reload)
00264         : QObject(),
00265         QGraphicsItemGroup(0, view ? view->scene() : 0),
00266         d(new Private(view, instance, subTheme))
00267 {
00268     if (!d->globalView) {
00269         #ifdef PYTHON_INCLUDE_PATH
00270         KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00271         if (args->isSet("usefallback")) {
00272             d->useKross = false;
00273         }
00274         #endif
00275     }
00276 
00277     QString environment = getenv("SK_FANCY");
00278     if (!environment.compare("false", Qt::CaseInsensitive)) {
00279         d->useFancyEffects = false;
00280     }
00281 
00282     environment = getenv("SK_AA");
00283     if (!environment.compare("false", Qt::CaseInsensitive)) {
00284         d->useAntialiasing = false;
00285     }
00286 
00287     if (!d->globalView) {
00288         d->scene = new QGraphicsScene;
00289         d->scene->addItem(this);
00290         d->view = new MainWidget(d->scene);
00291 
00292         if (d->useAntialiasing) {
00293             d->view->setRenderHints(QPainter::Antialiasing |
00294                                QPainter::SmoothPixmapTransform);
00295         }
00296 
00297         d->scene->setItemIndexMethod(QGraphicsScene::NoIndex);
00298 
00299         d->view->show();
00300     }
00301 
00302     hide();
00303 
00304     if (!d->globalView) {
00305         d->view->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
00306     }
00307 
00308     if (!d->theme.set(themeFile)) {
00309         kDebug() << "Could not load theme file" ;
00310         d->errorInInit = true;
00311         QTimer::singleShot(0, this, SLOT(startKaramba()));
00312         return;
00313     }
00314 
00315     KDirWatch *dirWatch = KDirWatch::self();
00316     connect(dirWatch, SIGNAL(dirty(const QString &)),
00317             SLOT(slotFileChanged(const QString &)));
00318 
00319     if (!dirWatch->contains(d->theme.file()))
00320         dirWatch->addFile(d->theme.file());
00321 
00322     if (!d->theme.isZipTheme() && d->theme.scriptModuleExists()) {
00323         QString scriptFile = d->theme.path() + '/' + d->theme.scriptModule();
00324         if (!dirWatch->contains(scriptFile))
00325             dirWatch->addFile(scriptFile);
00326     }
00327 
00328     if (d->prettyName.isEmpty())
00329         d->prettyName = QString("%1 - %2").arg(d->theme.name()).arg(d->instance);
00330 
00331     setObjectName("karamba - " + d->prettyName);
00332 
00333     if (!d->globalView) {
00334         d->info = new NETWinInfo(QX11Info::display(), d->view->winId(),
00335                             QX11Info::appRootWindow(), NET::WMState);
00336     }
00337 
00338     d->defaultTextField = new TextField();
00339 
00340     d->KWinModule = KWindowSystem::self();
00341     connect(d->KWinModule, SIGNAL(currentDesktopChanged(int)), this,
00342             SLOT(currentDesktopChanged(int)));
00343 //TODO port it
00344     
00345 #if 0
00346     d->backgroundInterface = new org::kde::kdesktop::Background("org.kde.kdesktop", "/Background", QDBusConnection::sessionBus());
00347     connect(d->backgroundInterface, SIGNAL(backgroundChanged(int)), this,
00348             SLOT(currentWallpaperChanged(int)));
00349 #endif
00350     setAcceptsHoverEvents(true);
00351 
00352     // Setup of the Task Manager Callbacks
00353     connect(TaskManager::self(), SIGNAL(activeTaskChanged(Task::TaskPtr)), this,
00354             SLOT(activeTaskChanged(Task::TaskPtr)));
00355     connect(TaskManager::self(), SIGNAL(taskAdded(Task::TaskPtr)), this,
00356             SLOT(taskAdded(Task::TaskPtr)));
00357     connect(TaskManager::self(), SIGNAL(taskRemoved(Task::TaskPtr)), this,
00358             SLOT(taskRemoved(Task::TaskPtr)));
00359     connect(TaskManager::self(), SIGNAL(startupAdded(Startup::StartupPtr)), this,
00360             SLOT(startupAdded(Startup::StartupPtr)));
00361     connect(TaskManager::self(), SIGNAL(startupRemoved(Startup::StartupPtr)), this,
00362             SLOT(startupRemoved(Startup::StartupPtr)));
00363 
00364     d->signalMapperConfig = new QSignalMapper(this);
00365     connect(d->signalMapperConfig, SIGNAL(mapped(QObject*)), this,
00366             SLOT(slotToggleConfigOption(QObject*)));
00367 
00368     d->signalMapperDesktop = new QSignalMapper(this);
00369     connect(d->signalMapperDesktop, SIGNAL(mapped(int)), this,
00370             SLOT(slotDesktopChanged(int)));
00371 
00372     preparePopupMenu();
00373 
00374     parseConfig();
00375 
00376     QString instanceString;
00377     if (d->instance > 1)
00378         instanceString = QString("-%1").arg(d->instance);
00379 
00380     QString cfg = QDir::home().absolutePath() + "/.superkaramba/"
00381                   + d->theme.id() + instanceString + ".rc";
00382     kDebug() << cfg ;
00383 
00384     QFile themeConfigFile(cfg);
00385     // Tests if config file Exists
00386     if (!QFileInfo(themeConfigFile).exists()) {
00387         // Create config file
00388         themeConfigFile.open(QIODevice::ReadWrite);
00389         themeConfigFile.close();
00390     }
00391 
00392     d->config = new KConfig(cfg, KConfig::NoGlobals);
00393 
00394     // Karamba specific Config Entries
00395     KConfigGroup cg(d->config, "internal");
00396     bool locked = d->toggleLocked->isChecked();
00397     locked = cg.readEntry("lockedPosition", locked);
00398     d->toggleLocked->setChecked(locked);
00399 
00400     int desktop = 0;
00401     desktop = cg.readEntry("desktop", desktop);
00402     if (desktop > d->KWinModule->numberOfDesktops()) {
00403         desktop = 0;
00404     }
00405 
00406     slotDesktopChanged(desktop);
00407 
00408     cg = KConfigGroup(d->config, "theme");
00409     if (cg.hasKey("widgetPosX") && cg.hasKey("widgetPosY")) {
00410         int xpos = cg.readEntry("widgetPosX", 0);
00411         int ypos = cg.readEntry("widgetPosY", 0);
00412 
00413         if (xpos < 0)
00414             xpos = 0;
00415         if (ypos < 0)
00416             ypos = 0;
00417 
00418         if (startPos.isNull()) {
00419             moveToPos(QPoint(xpos, ypos));
00420         }
00421     }
00422 
00423     if (!startPos.isNull()) {
00424         moveToPos(startPos - d->themeCenter);
00425 
00426         d->toggleLocked->setChecked(false);
00427     }
00428 
00429     if (!d->globalView && !reload && d->useFancyEffects) {
00430         d->timer = new QTimeLine(1000);
00431         d->timer->setFrameRange(0, 1000);
00432 
00433         d->animation = new QGraphicsItemAnimation;
00434         d->animation->setItem(this);
00435         d->animation->setTimeLine(d->timer);
00436 
00437         // Use 201 here because 200.0/200.0 < 1 => theme is still scaled
00438         for (int i = 0; i < 201; i++) {
00439             d->animation->setScaleAt(i / 200.0, 1 / 200.0 * i, 1 / 200.0 * i);
00440             QPointF animPos(
00441                 boundingRect().width()/2*(1-d->animation->verticalScaleAt(i / 200.0)),
00442                 boundingRect().height()/2*(1-d->animation->horizontalScaleAt(i / 200.0))
00443             );
00444                 d->animation->setPosAt(i / 200.0, animPos);
00445         }
00446 
00447         d->timer->start();
00448     }
00449 
00450     QTimer::singleShot(0, this, SLOT(startKaramba()));
00451 
00452     if (!(d->onTop || d->managed) && !d->globalView) {
00453         KWindowSystem::setState(d->view->winId(), NET::KeepBelow);
00454         KWindowSystem::lowerWindow(d->view->winId());
00455     }
00456 }
00457 
00458 Karamba::~Karamba()
00459 {
00460     if (d->toggleLocked) // may NULL e.g. if "Could not load theme file"
00461         writeConfigData();
00462 
00463     d->scene->removeItem(this);
00464 
00465     delete d;
00466 }
00467 
00468 void Karamba::startKaramba()
00469 {
00470     if (d->errorInInit) {
00471         deleteLater();
00472         return;
00473     }
00474 
00475     KarambaManager::self()->addKaramba(this);
00476 
00477     if (d->theme.scriptModuleExists()) {
00478         kDebug() << "Loading script module: " << d->theme.scriptModule() ;
00479 
00480         d->stepTimer.setSingleShot(true);
00481 
00482         if (!d->useKross) {
00483 #ifdef PYTHON_INCLUDE_PATH
00484             d->python = new KarambaPython(d->theme, false);
00485 
00486             d->python->initWidget(this);
00487 #endif
00488         } else {
00489             d->interface = new KarambaInterface(this);
00490             bool interpreterStarted = d->interface->initInterpreter();
00491 
00492             if (!interpreterStarted) {
00493                 delete d->interface;
00494                 d->interface = 0;
00495             } else {
00496                 d->interface->startInterpreter();
00497                 d->interface->callInitWidget(this);
00498             }
00499         }
00500 
00501         update();
00502 
00503         connect(&d->stepTimer, SIGNAL(timeout()), SLOT(step()));
00504         d->stepTimer.start(d->interval);
00505     }
00506 
00507     show();
00508 }
00509 
00510 QString Karamba::prettyName() const
00511 {
00512     return d->prettyName;
00513 }
00514 
00515 void Karamba::setPrettyName(const QString &prettyThemeName)
00516 {
00517     d->prettyName = prettyThemeName;
00518 }
00519 
00520 void Karamba::step()
00521 {
00522     d->stepTimer.start(d->interval);
00523 
00524 #ifdef PYTHON_INCLUDE_PATH
00525     if (d->python)
00526         d->python->widgetUpdated(this);
00527 #endif
00528 
00529     if (d->interface)
00530         d->interface->callWidgetUpdated(this);
00531 
00532     update();
00533 }
00534 
00535 void Karamba::redrawWidget()
00536 {
00537     // Force the event loop to process the update() calls
00538     // QCoreApplication::processEvents();
00539 }
00540 
00541 bool Karamba::parseConfig()
00542 {
00543     //qDebug("karamba::parseConfig");
00544     bool passive = true;
00545 
00546     if (d->theme.open()) {
00547         QStack<QPoint> offsetStack;
00548         LineParser lineParser;
00549         int x = 0;
00550         int y = 0;
00551         int w = 0;
00552         int h = 0;
00553 
00554         offsetStack.push(QPoint(0, 0));
00555 
00556         while (d->theme.nextLine(lineParser)) {
00557             x = lineParser.getInt("X") + offsetStack.top().x();
00558             y = lineParser.getInt("Y") + offsetStack.top().y();
00559             w = lineParser.getInt("W");
00560             h = lineParser.getInt("H");
00561 
00562             if (lineParser.meter() == "KARAMBA" && !d->foundKaramba) {
00563                 d->toggleLocked->setChecked(lineParser.getBoolean("LOCKED"));
00564 
00565                 x = (x < 0) ? 0 : x;
00566                 y = (y < 0) ? 0 : y;
00567 
00568                 if (w == 0 ||  h == 0) {
00569                     w = 300;
00570                     h = 300;
00571                 }
00572 
00573                 // Store the center of the theme,
00574                 // so it can be centered when a user
00575                 // drags it from the theme dialog.
00576                 d->themeCenter = QPoint(w/2, h/2);
00577 
00578                 setFixedSize(w, h);
00579                 if (!d->globalView) {
00580                     d->view->setFixedSize(w + 5, h + 5);
00581                 }
00582 
00583                 if (lineParser.getBoolean("RIGHT")) {
00584                     QDesktopWidget *d = QApplication::desktop();
00585                     x = d->width() - w;
00586                 } else if (lineParser.getBoolean("LEFT")) {
00587                     x = 0;
00588                 }
00589 
00590                 if (lineParser.getBoolean("BOTTOM")) {
00591                     QDesktopWidget *d = QApplication::desktop();
00592                     y = d->height() - h;
00593                 } else if (lineParser.getBoolean("TOP")) {
00594                     y = 0;
00595                 }
00596 
00597                 moveToPos(QPoint(x, y));
00598 
00599                 if (lineParser.getBoolean("ONTOP")) {
00600                     d->onTop = true;
00601                     if (!d->globalView) {
00602                         KWindowSystem::setState(d->view->winId(), NET::StaysOnTop);
00603                    }
00604                 }
00605 
00606                 if (lineParser.getBoolean("MANAGED")) {
00607                     d->managed = true;
00608                     if (!d->globalView) {
00609                         Qt::WindowFlags flags = Qt::Dialog;
00610                         flags & Qt::WA_DeleteOnClose;
00611                         d->view->setWindowFlags(flags);
00612                         d->view->show();
00613                     }
00614                 } else {
00615                     if (!d->globalView) {
00616                         d->info->setState(NETWinInfo::SkipTaskbar
00617                                      | NETWinInfo::SkipPager, NETWinInfo::SkipTaskbar
00618                                      | NETWinInfo::SkipPager);
00619                     }
00620                     if (d->onTop && !d->globalView) {
00621                         KWindowSystem::setState(d->view->winId(), NET::KeepAbove);
00622                     }
00623                 }
00624 
00625                 if (lineParser.getBoolean("ONALLDESKTOPS")) {
00626                     d->desktop = 200; // ugly
00627                 }
00628 
00629                 bool dfound = false;
00630                 //int desktop = lineParser.getInt("DESKTOP", line, dfound);
00631                 if (dfound && !d->globalView) {
00632                     d->info->setDesktop(dfound);
00633                 }
00634 
00635                 if (lineParser.getBoolean("TOPBAR")) {
00636                     if (!d->globalView) {
00637                         KWindowSystem::setStrut(d->view->winId(), 0, 0, h, 0);
00638                         d->view->move(x, 0);
00639                     } else {
00640                         moveToPos(QPoint(x, 0));
00641                     }
00642 
00643                     d->toggleLocked->setChecked(true);
00644                     d->toggleLocked->setEnabled(false);
00645                 }
00646 
00647                 if (lineParser.getBoolean("BOTTOMBAR")) {
00648                     int dh = QApplication::desktop()->height();
00649                     if (d->globalView) {
00650                         moveToPos(QPoint(x, dh - h));
00651                     } else {
00652                         KWindowSystem::setStrut(d->view->winId(), 0, 0, 0, h);
00653                         d->view->move(x, dh - h);
00654                     }
00655                     d->toggleLocked->setChecked(true);
00656                     d->toggleLocked->setEnabled(false);
00657                 }
00658 
00659                 if (lineParser.getBoolean("RIGHTBAR")) {
00660                     int dw = QApplication::desktop()->width();
00661                     if (d->globalView) {
00662                         moveToPos(QPoint(dw - w, y));
00663                     } else {
00664                         KWindowSystem::setStrut(d->view->winId(), 0, w, 0, 0);
00665                         d->view->move(dw - w, y);
00666                     }
00667                     d->toggleLocked->setChecked(true);
00668                     d->toggleLocked->setEnabled(false);
00669                 }
00670 
00671                 if (lineParser.getBoolean("LEFTBAR")) {
00672                     if (d->globalView) {
00673                         moveToPos(QPoint(0, y));
00674                     } else {
00675                         KWindowSystem::setStrut(d->view->winId(), w, 0, 0, 0);
00676                         d->view->move(0, y);
00677                     }
00678                     d->toggleLocked->setChecked( true );
00679                     d->toggleLocked->setEnabled(false);
00680                 }
00681 
00682                 if (d->globalView)
00683                     setFlag(QGraphicsItem::ItemIsMovable,
00684                             d->toggleLocked->isChecked());
00685 
00686 
00687                 /* Masking gone
00688                 QString path = lineParser.getString("MASK");
00689 
00690                 QFileInfo info(path);
00691                 QString absPath;
00692                 QBitmap bmMask;
00693                 QByteArray ba;
00694                 if( info.isRelative() )
00695                 {
00696                   absPath = d->theme.path();
00697                   absPath.append(path);
00698                   ba = d->theme.readThemeFile(path);
00699                 }
00700                 else
00701                 {
00702                   absPath = path;
00703                   ba = d->theme.readThemeFile(info.fileName());
00704                 }
00705                 if(d->theme.isZipTheme())
00706                 {
00707                   bmMask.loadFromData(ba);
00708                 }
00709                 else
00710                 {
00711                   bmMask.load(absPath);
00712                 }
00713                 d->view->setMask(bmMask);
00714                 */
00715 
00716                 d->interval = lineParser.getInt("INTERVAL");
00717                 d->interval = (d->interval == 0) ? 1000 : d->interval;
00718 
00719                 QString temp = lineParser.getString("TEMPUNIT", "C").toUpper();
00720                 d->tempUnit = temp.at(0).toAscii();
00721                 d->foundKaramba = true;
00722             }
00723 
00724             if (lineParser.meter() == "THEME") {
00725                 QString path = lineParser.getString("PATH");
00726                 QFileInfo info(path);
00727                 if (info.isRelative())
00728                     path = d->theme.path() + '/' + path;
00729 
00730                 new Karamba(path/*, d->view, d->scene*/);
00731             }
00732 
00733             if (lineParser.meter() == "<GROUP>") {
00734                 int offsetX = offsetStack.top().x();
00735                 int offsetY = offsetStack.top().y();
00736                 offsetStack.push(QPoint(offsetX + lineParser.getInt("X"),
00737                                         offsetY + lineParser.getInt("Y")));
00738             }
00739 
00740             if (lineParser.meter() == "</GROUP>") {
00741                 offsetStack.pop();
00742             }
00743 
00744             if (lineParser.meter() == "CLICKAREA") {
00745                 if (!d->globalView) {
00746                     d->view->setInteractive(true);
00747                 }
00748 
00749                 bool preview = lineParser.getBoolean("PREVIEW");
00750                 ClickArea *tmp = new ClickArea(this, preview, x, y, w, h);
00751                 tmp->setOnClick(lineParser.getString("ONCLICK"));
00752 
00753 
00754                 setSensor(lineParser, (Meter*)tmp);
00755             }
00756 
00757             if (lineParser.meter() == "SENSOR=PROGRAM") {
00758                 setSensor(lineParser, 0);
00759             }
00760 
00761             if (lineParser.meter() == "IMAGE") {
00762                 QString file = lineParser.getString("PATH");
00763                 QString file_roll = lineParser.getString("PATHROLL");
00764                 int xon = lineParser.getInt("XROLL");
00765                 int yon = lineParser.getInt("YROLL");
00766                 QString tiptext = lineParser.getString("TOOLTIP");
00767                 QString name = lineParser.getString("NAME");
00768                 bool bg = lineParser.getBoolean("BACKGROUND");
00769                 xon = (xon <= 0) ? x : xon;
00770                 yon = (yon <= 0) ? y : yon;
00771 
00772                 ImageLabel *tmp = new ImageLabel(this, x, y, 0, 0);
00773                 tmp->setValue(file);
00774 
00775                 if (!file_roll.isEmpty())
00776                     tmp->parseImages(file, file_roll, x, y, xon, yon);
00777 
00778                 tmp->setBackground(bg);
00779 
00780                 if (!name.isEmpty())
00781                     tmp->setObjectName(name);
00782 
00783                 if (!tiptext.isEmpty())
00784                     tmp->setTooltip(tiptext);
00785 
00786                 setSensor(lineParser, (Meter*)tmp);
00787             }
00788 
00789             if (lineParser.meter() == "DEFAULTFONT") {
00790                 delete d->defaultTextField;
00791                 d->defaultTextField = new TextField();
00792 
00793                 d->defaultTextField->setColor(lineParser.getColor("COLOR",
00794                                              QColor("black")));
00795                 d->defaultTextField->setBGColor(lineParser.getColor("BGCOLOR",
00796                                                QColor("white")));
00797                 d->defaultTextField->setFont(lineParser.getString("FONT", "Helvetica"));
00798                 d->defaultTextField->setFontSize(lineParser.getInt("FONTSIZE", 12));
00799                 d->defaultTextField->setAlignment(lineParser.getString("ALIGN",
00800                                                  "LEFT"));
00801                 d->defaultTextField->setFixedPitch(lineParser.getBoolean("FIXEDPITCH",
00802                                                   false));
00803                 d->defaultTextField->setShadow(lineParser.getInt("SHADOW", 0));
00804             }
00805 
00806             if (lineParser.meter() == "TEXT" ||
00807                     lineParser.meter() == "CLICKMAP" ||
00808                     lineParser.meter() == "RICHTEXT" ||
00809                     lineParser.meter() == "INPUT") {
00810                 TextField defTxt;
00811 
00812                 if (d->defaultTextField)
00813                     defTxt = *d->defaultTextField;
00814 
00815                 TextField* tmpText = new TextField();
00816 
00817                 tmpText->setColor(lineParser.getColor("COLOR", defTxt.getColor()));
00818                 tmpText->setBGColor(lineParser.getColor("BGCOLOR",
00819                                                         defTxt.getBGColor()));
00820                 tmpText->setFont(lineParser.getString("FONT", defTxt.getFont()));
00821                 tmpText->setFontSize(lineParser.getInt("FONTSIZE",
00822                                                        defTxt.getFontSize()));
00823                 tmpText->setAlignment(lineParser.getString("ALIGN",
00824                                       defTxt.getAlignmentAsString()));
00825                 tmpText->setFixedPitch(lineParser.getInt("FIXEDPITCH",
00826                                        defTxt.getFixedPitch()));
00827 
00828                 tmpText->setShadow(lineParser.getInt("SHADOW", defTxt.getShadow()));
00829 
00831                 // Now handle the specifics
00832                 if (lineParser.meter() == "TEXT") {
00833                     TextLabel *tmp = new TextLabel(this, x, y, w, h);
00834                     tmp->setValue(
00835                         d->theme.locale()->translate(lineParser.getString("VALUE")));
00836                     tmp->setTextProps(tmpText);
00837 
00838                     QString name = lineParser.getString("NAME");
00839                     if (!name.isEmpty())
00840                         tmp->setObjectName(name);
00841 
00842                     setSensor(lineParser, (Meter*)tmp);
00843                 }
00844 
00845                 if (lineParser.meter() == "CLICKMAP") {
00846                     if (!d->globalView) {
00847                         d->view->setInteractive(true);
00848                     }
00849 
00850                     ClickMap *tmp = new ClickMap(this, x, y, w, h);
00851                     tmp->setTextProps(tmpText);
00852 
00853                     setSensor(lineParser, (Meter*)tmp);
00854                     // set all params
00855                     //clickList -> append(tmp);
00856                     //meterList->append( tmp );
00857 
00858                 }
00859 
00860                 if (lineParser.meter() == "RICHTEXT") {
00861                     RichTextLabel *tmp = new RichTextLabel(this, x, y, w, h);
00862 
00863                     bool dUl = lineParser.getBoolean("UNDERLINE");
00864 
00865                     tmp->setText(
00866                         d->theme.locale()->translate(lineParser.getString("VALUE")), dUl);
00867                     tmp->setTextProps(tmpText);
00868 //          tmp->setWidth(w);
00869 //          tmp->setHeight(h);
00870 
00871                     QString name = lineParser.getString("NAME");
00872                     if (!name.isEmpty())
00873                         tmp->setObjectName(name);
00874 
00875                     setSensor(lineParser, (Meter*)tmp);
00876                     //clickList->append(tmp);
00877                     //meterList->append(tmp);
00878                 }
00879 
00880                 if (lineParser.meter() == "INPUT") {
00881                     Input *tmp = new Input(this, x, y, w, h);
00882 
00883                     QString name = lineParser.getString("NAME");
00884                     //if (!name.isEmpty())
00885                     //tmp->setObjectName(name);
00886 
00887                     tmp->setTextProps(tmpText);
00888                     tmp->setValue(
00889                         d->theme.locale()->translate(lineParser.getString("VALUE")));
00890 
00891                     //meterList->append(tmp);
00892                     passive = false;
00893                 }
00894 
00895                 delete tmpText;
00896             }
00897 
00898             if (lineParser.meter() == "BAR") {
00899                 Bar *tmp = new Bar(this, x, y, w, h);
00900 
00901                 tmp->setImage(lineParser.getString("PATH"));
00902                 tmp->setVertical(lineParser.getBoolean("VERTICAL"));
00903                 tmp->setMax(lineParser.getInt("MAX", 100));
00904                 tmp->setMin(lineParser.getInt("MIN", 0));
00905                 tmp->setValue(lineParser.getInt("VALUE"));
00906 
00907                 QString name = lineParser.getString("NAME");
00908                 if (!name.isEmpty())
00909                     tmp->setObjectName(name);
00910 
00911                 setSensor(lineParser, (Meter*)tmp);
00912                 //meterList->append(tmp);
00913             }
00914 
00915             if (lineParser.meter() == "GRAPH") {
00916                 int points = lineParser.getInt("POINTS");
00917 
00918                 Graph *tmp = new Graph(this, x, y, w, h, points);
00919                 tmp->setMax(lineParser.getInt("MAX", 100));
00920                 tmp->setMin(lineParser.getInt("MIN", 0));
00921                 QString name = lineParser.getString("NAME");
00922                 if (!name.isEmpty())
00923                     tmp->setObjectName(name);
00924 
00925                 tmp->setColor(lineParser.getColor("COLOR"));
00926 
00927                 setSensor(lineParser, (Graph*)tmp);
00928                 //meterList->append(tmp);
00929             }
00930         }
00931 
00932         if (passive && !d->managed && !d->onTop && !d->globalView) {
00933             KWindowSystem::setType(d->view->winId(), NET::Dock);
00934             KWindowSystem::setState(d->view->winId(), NET::KeepBelow);
00935         }
00936 
00937         d->theme.close();
00938     }
00939     //qDebug("parseConfig ok: %d", foundKaramba);
00940     if (!d->foundKaramba) {
00941         //  interval = initKaramba( "", 0, 0, 0, 0 );
00942         //   this->close(true);
00943         //delete this;
00944         return false;
00945     } else {
00946         return true;
00947     }
00948 }
00949 
00950 void Karamba::makeActive()
00951 {
00952     if (!d->globalView) {
00953         KWindowSystem::setType(d->view->winId(), NET::Normal);
00954         KWindowSystem::setState(d->view->winId(), NET::Modal);
00955     }
00956 }
00957 
00958 void Karamba::makePassive()
00959 {
00960     if (d->managed) {
00961         return;
00962     }
00963 
00964     QList<QGraphicsItem*> items = QGraphicsItemGroup::children();
00965     foreach (QGraphicsItem* item, items) {
00966         if (dynamic_cast<Input*>(item) != 0) {
00967             return;
00968         }
00969     }
00970 
00971     if (!d->globalView) {
00972         KWindowSystem::setType(d->view->winId(), NET::Dock);
00973         KWindowSystem::setState(d->view->winId(), NET::KeepBelow);
00974     }
00975 }
00976 
00977 TextField* Karamba::getDefaultTextProps()
00978 {
00979     return d->defaultTextField;
00980 }
00981 
00982 QString Karamba::findSensorFromMap(const Sensor* sensor) const
00983 {
00984     //qDebug("karamba::findSensorFromMap");
00985     QMap<QString, Sensor*>::ConstIterator it;
00986     QMap<QString, Sensor*>::ConstIterator end(d->sensorMap.end());
00987     for (it = d->sensorMap.begin(); it != end; ++it) {
00988         if (it.value() == sensor)
00989             return it.key();
00990     }
00991     return "";
00992 }
00993 
00994 Sensor *Karamba::findSensorFromList(const Meter* meter) const
00995 {
00996     foreach(Sensor *sensor, d->sensorList) {
00997         if (sensor->hasMeter(meter))
00998             return sensor;
00999     }
01000 
01001     return 0;
01002 }
01003 
01004 void Karamba::deleteMeterFromSensors(Meter* meter)
01005 {
01006     //qDebug("karamba::deleteMeterFromSensors");
01007     Sensor* sensor = findSensorFromList(meter);
01008 
01009     if (sensor) {
01010         sensor->deleteMeter(meter);
01011         if (sensor->isEmpty()) {
01012             QString s = findSensorFromMap(sensor);
01013             d->sensorMap.remove(s);
01014             d->sensorList.removeAll(sensor);
01015             delete sensor;
01016         }
01017     }
01018 }
01019 
01020 QString Karamba::getSensor(const Meter* meter) const
01021 {
01022     Sensor* sensor = findSensorFromList(meter);
01023 
01024     if (sensor)
01025         return findSensorFromMap(sensor);
01026 
01027     return QString();
01028 }
01029 
01030 bool Karamba::removeMeter(Meter* meter)
01031 {
01032     QList<QGraphicsItem*> items = QGraphicsItemGroup::children();
01033 
01034     if (items.contains(meter)) {
01035         deleteMeterFromSensors(meter);
01036         delete meter;
01037         return true;
01038     } else
01039         return false;
01040 }
01041 
01042 void Karamba::setSensor(const LineParser& lineParser, Meter* meter)
01043 {
01044     Sensor* sensor = 0;
01045 
01046     deleteMeterFromSensors(meter);
01047 
01048     QString sens = lineParser.getString("SENSOR").toUpper();
01049 
01050     if (sens == "CPU") {
01051         QString cpuNbr = lineParser.getString("CPU");
01052         sensor = d->sensorMap["CPU"+cpuNbr];
01053 
01054         if (sensor == 0) {
01055             int interval = lineParser.getInt("INTERVAL");
01056             interval = (interval == 0) ? 1000 : interval;
01057             sensor = (d->sensorMap["CPU" + cpuNbr] = new CPUSensor(cpuNbr, interval));
01058             d->sensorList.append(sensor);
01059         }
01060 
01061         SensorParams *sp = new SensorParams(meter);
01062         sp->addParam("FORMAT",
01063                      d->theme.locale()->translate(lineParser.getString("FORMAT")));
01064 
01065         sp->addParam("DECIMALS", lineParser.getString("DECIMALS"));
01066 
01067         sensor->addMeter(sp);
01068         sensor->setMaxValue(sp);
01069     }
01070 
01071     if (sens == "MEMORY") {
01072         sensor = d->sensorMap["MEMORY"];
01073         if (sensor == 0) {
01074             int interval = lineParser.getInt("INTERVAL");
01075             interval = (interval == 0) ? 3000 : interval;
01076             sensor = (d->sensorMap["MEMORY"] = new MemSensor(interval));
01077             d->sensorList.append(sensor);
01078         }
01079 
01080         SensorParams *sp = new SensorParams(meter);
01081         sp->addParam("FORMAT",
01082                      d->theme.locale()->translate(lineParser.getString("FORMAT")));
01083 
01084         sensor->addMeter(sp);
01085         sensor->setMaxValue(sp);
01086     }
01087 
01088     if (sens == "DISK") {
01089         sensor = d->sensorMap["DISK"];
01090 
01091         if (sensor == 0) {
01092             int interval = lineParser.getInt("INTERVAL");
01093             interval = (interval == 0) ? 5000 : interval;
01094             sensor = (d->sensorMap["DISK"] = new DiskSensor(interval));
01095             d->sensorList.append(sensor);
01096         }
01097         // meter->setMax( ((DiskSensor*)sensor)->getTotalSpace(mntPt)/1024 );
01098         SensorParams *sp = new SensorParams(meter);
01099         QString mntPt = lineParser.getString("MOUNTPOINT");
01100         if (mntPt.isEmpty()) {
01101             mntPt = "/";
01102         }
01103         // remove any trailing '/' from mount points in the .theme config, our
01104         // mntMap doesn't like trailing '/'s for matching in DiskSensor
01105         if (mntPt.length() > 1 && mntPt.endsWith('/')) {
01106             mntPt.remove(mntPt.length() - 1, 1);
01107         }
01108         sp->addParam("MOUNTPOINT", mntPt);
01109         sp->addParam("FORMAT",
01110                      d->theme.locale()->translate(lineParser.getString("FORMAT")));
01111         sensor->addMeter(sp);
01112         sensor->setMaxValue(sp);
01113     }
01114 
01115     if (sens == "NETWORK") {
01116         int interval = lineParser.getInt("INTERVAL");
01117         interval = (interval == 0) ? 2000 : interval;
01118         QString device = lineParser.getString("DEVICE");
01119         sensor = d->sensorMap["NETWORK"+device];
01120 
01121         if (sensor == 0) {
01122             sensor = (d->sensorMap["NETWORK"+device] =
01123                           new NetworkSensor(device, interval));
01124             d->sensorList.append(sensor);
01125         }
01126 
01127         SensorParams *sp = new SensorParams(meter);
01128         sp->addParam("FORMAT",
01129                      d->theme.locale()->translate(lineParser.getString("FORMAT")));
01130 
01131         sp->addParam("DECIMALS", lineParser.getString("DECIMALS"));
01132         sensor->addMeter(sp);
01133     }
01134 
01135     if (sens == "UPTIME") {
01136         sensor = d->sensorMap[