karamba.cpp

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  *
00007  * This file is part of SuperKaramba.
00008  *
00009  *  SuperKaramba is free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  SuperKaramba is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with SuperKaramba; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  ****************************************************************************/
00023 
00024 #include "karamba_python.h"
00025 #include "dcopinterface_stub.h"
00026 #include "richtextlabel.h"
00027 #include "karamba.h"
00028 #include "karambaapp.h"
00029 #include "themesdlg.h"
00030 #include "lineparser.h"
00031 #include "themelocale.h"
00032 #include "superkarambasettings.h"
00033 
00034 #include <kdebug.h>
00035 #include <kmessagebox.h>
00036 #include <krun.h>
00037 #include <klocale.h>
00038 #include <kwin.h>
00039 #include <kdeversion.h>
00040 #include <kdirwatch.h>
00041 
00042 #include <kparts/componentfactory.h>
00043 #include <kparts/part.h>
00044 
00045 #include <qdir.h>
00046 #include <qwidgetlist.h>
00047 
00048 // Menu IDs
00049 #define EDITSCRIPT 1
00050 #define THEMECONF  2
00051 
00052 karamba::karamba(QString fn, QString name, bool reloading, int instance,
00053     bool sub_theme):
00054     QWidget(0,"karamba", Qt::WGroupLeader | WStyle_Customize |
00055             WRepaintNoErase| WStyle_NoBorder | WDestructiveClose  ),
00056     meterList(0), imageList(0), clickList(0), kpop(0), widgetMask(0),
00057     config(0), kWinModule(0), tempUnit('C'), m_instance(instance),
00058     sensorList(0), timeList(0),
00059     themeConfMenu(0), toDesktopMenu(0), kglobal(0), clickPos(0, 0), accColl(0),
00060     menuAccColl(0), toggleLocked(0), pythonIface(0), defaultTextField(0),
00061     trayMenuSeperatorId(-1), trayMenuQuitId(-1), trayMenuToggleId(-1),
00062     trayMenuThemeId(-1),
00063     m_sysTimer(NULL)
00064 {
00065   themeStarted = false;
00066   want_right_button = false;
00067   prettyName = name;
00068   m_sub_theme = sub_theme;
00069 
00070   KURL url;
00071 
00072   if(fn.find('/') == -1)
00073     url.setFileName(fn);
00074   else
00075     url = fn;
00076   if(!m_theme.set(url))
00077   {
00078     setFixedSize(0, 0);
00079     QTimer::singleShot(100, this, SLOT(killWidget()));
00080     return;
00081   }
00082   // Add self to list of open themes
00083   // This also updates instance number
00084   karambaApp->addKaramba(this, reloading);
00085 
00086   if(prettyName.isEmpty())
00087     prettyName = QString("%1 - %2").arg(m_theme.name()).arg(m_instance);
00088 
00089   kdDebug() << "Starting theme: " << m_theme.name()
00090             << " pretty name: " << prettyName << endl;
00091   QString qName = "karamba - " + prettyName;
00092   setName(qName.ascii());
00093 
00094   KDirWatch *dirWatch = new KDirWatch( this );
00095   connect(dirWatch, SIGNAL( dirty( const QString & ) ),
00096           SLOT( slotFileChanged( const QString & ) ) );
00097   dirWatch->addFile(m_theme.file());
00098   if(!m_theme.isZipTheme() && m_theme.pythonModuleExists())
00099   {
00100     QString pythonFile = m_theme.path() + "/" + m_theme.pythonModule() + ".py";
00101     dirWatch->addFile(pythonFile);
00102   }
00103 
00104   widgetUpdate = true;
00105 
00106   // Creates KConfig Object
00107   QString instanceString;
00108   if(m_instance > 1)
00109     instanceString = QString("-%1").arg(m_instance);
00110   QString cfg = QDir::home().absPath() + "/.superkaramba/"
00111       + m_theme.id() + instanceString + ".rc";
00112   kdDebug() << cfg << endl;
00113   QFile themeConfigFile(cfg);
00114   // Tests if config file Exists
00115   if (!QFileInfo(themeConfigFile).exists())
00116   {
00117     // Create config file
00118     themeConfigFile.open(IO_ReadWrite);
00119     themeConfigFile.close();
00120   }
00121 
00122   config = new KConfig(cfg, false, false);
00123   config -> sync();
00124   config -> setGroup("internal");
00125 
00126   m_reloading = reloading;
00127   if(m_theme.pythonModuleExists())
00128   {
00129     kdDebug() << "Loading python module: " << m_theme.pythonModule() << endl;
00130     QTimer::singleShot(0, this, SLOT(initPythonInterface()));
00131   }
00132 
00133   widgetMask = 0;
00134   info = new NETWinInfo( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMState );
00135 
00136   // could be replaced with TaskManager
00137   kWinModule = new KWinModule();
00138   desktop = 0;
00139 
00140   connect( kWinModule,SIGNAL(currentDesktopChanged(int)), this,
00141            SLOT(currentDesktopChanged(int)) );
00142   connect( kapp, SIGNAL(backgroundChanged(int)), this,
00143            SLOT(currentWallpaperChanged(int)));
00144 
00145   // Setup of the Task Manager Callbacks
00146   connect(&taskManager, SIGNAL(activeTaskChanged(Task*)), this,
00147            SLOT(activeTaskChanged(Task*)) );
00148   connect(&taskManager, SIGNAL(taskAdded(Task*)), this,
00149            SLOT(taskAdded(Task*)) );
00150   connect(&taskManager, SIGNAL(taskRemoved(Task*)), this,
00151            SLOT(taskRemoved(Task*)) );
00152   connect(&taskManager, SIGNAL(startupAdded(Startup*)), this,
00153            SLOT(startupAdded(Startup*)) );
00154   connect(&taskManager, SIGNAL(startupRemoved(Startup*)), this,
00155            SLOT(startupRemoved(Startup*)) );
00156 
00157   themeConfMenu = new KPopupMenu( this);
00158   themeConfMenu -> setCheckable(true);
00159 
00160   /* XXX - need to be able to delete all these DesktopChangeSlot objects */
00161   DesktopChangeSlot *dslot;
00162 
00163   int mid;
00164 
00165   toDesktopMenu = new KPopupMenu (this);
00166   toDesktopMenu -> setCheckable(true);
00167   mid = toDesktopMenu -> insertItem (i18n("&All Desktops"),
00168                                      dslot = new DesktopChangeSlot(this,0),
00169                                      SLOT(receive()));
00170   dslot->setMenuId(mid);
00171 
00172   toDesktopMenu -> insertSeparator();
00173   for (int ndesktop=1; ndesktop <= kWinModule->numberOfDesktops(); ndesktop++)
00174   {
00175     QString name = i18n("Desktop &");
00176     name += ('0' + ndesktop);
00177 
00178     mid = toDesktopMenu -> insertItem (name,
00179         dslot = new DesktopChangeSlot(this, ndesktop), SLOT(receive()));
00180     dslot->setMenuId(mid);
00181   }
00182 
00183 
00184   kpop = new KPopupMenu( this );
00185   kpop -> setCheckable(true);
00186 
00187   accColl = new KActionCollection( this );
00188   menuAccColl = new KActionCollection( this );
00189 
00190   kpop->insertItem( SmallIconSet("reload"),i18n("Update"), this,
00191                     SLOT(updateSensors()), Key_F5 );
00192   toggleLocked = new KToggleAction (  i18n("Toggle &Locked Position"),
00193                                       SmallIconSet("locked"),
00194                                       CTRL+Key_L, this,
00195                                       SLOT( slotToggleLocked() ),
00196                                       accColl, "Locked position" );
00197   accColl->insert(toggleLocked);
00198   toggleLocked -> setChecked(true);
00199 
00200   toggleLocked->plug(kpop);
00201 
00202   toggleFastTransforms = new KToggleAction(i18n("Use &Fast Image Scaling"),
00203                          CTRL+Key_F, this,
00204                          SLOT( slotToggleFastTransforms() ),
00205                          accColl, "Fast transformations");
00206 
00207   accColl->insert(toggleFastTransforms);
00208   toggleFastTransforms -> setChecked(true);
00209 
00210   toggleFastTransforms -> plug(kpop);
00211 
00212   kpop->insertSeparator();
00213 
00214   kpop->insertItem(i18n("Configure &Theme"), themeConfMenu, THEMECONF);
00215   kpop->setItemEnabled(THEMECONF, false);
00216   kpop->insertItem(i18n("To Des&ktop"), toDesktopMenu);
00217 
00218   kpop->insertItem( SmallIconSet("reload3"),i18n("&Reload Theme"),this,
00219                     SLOT(reloadConfig()), CTRL+Key_R );
00220   kpop->insertItem( SmallIconSet("fileclose"),i18n("&Close This Theme"), this,
00221                     SLOT(killWidget()), CTRL+Key_C );
00222 
00223   if(!SuperKarambaSettings::showSysTray())
00224     showMenuExtension();
00225 
00226   kpop->polish();
00227 
00228   numberOfConfMenuItems = 0;
00229 
00230   systray = 0;
00231   foundKaramba = false;
00232   onTop = false;
00233   managed = false;
00234   fixedPosition = false;
00235   defaultTextField = new TextField();
00236 
00237   meterList = new QObjectList();
00238   meterList->setAutoDelete( true );
00239   sensorList = new QObjectList();
00240   sensorList->setAutoDelete( true );
00241   clickList = new QObjectList();
00242   timeList = new QObjectList();
00243   imageList = new QObjectList();
00244   menuList = new QObjectList();
00245   menuList->setAutoDelete( true );
00246 
00247   client = kapp->dcopClient();
00248   if (!client->isAttached())
00249     client->attach();
00250   appId = client->registerAs(qApp->name());
00251 
00252 
00253   setBackgroundMode( NoBackground);
00254   if( !(onTop || managed))
00255     KWin::lowerWindow( winId() );
00256 
00257   if( !parseConfig() )
00258   {
00259     setFixedSize(0,0);
00260     QTimer::singleShot( 100, this, SLOT(killWidget()) );
00261     qWarning("Could not read config file.");
00262   }
00263   else
00264   {
00265     kroot = new KarambaRootPixmap((QWidget*)this);
00266     kroot->start();
00267   }
00268 
00269   // Karamba specific Config Entries
00270   bool locked = toggleLocked->isChecked();
00271   locked = config->readBoolEntry("lockedPosition", locked);
00272   toggleLocked->setChecked(locked);
00273   slotToggleLocked();
00274 
00275   if (!config -> readBoolEntry("fastTransforms", true))
00276   {
00277     toggleFastTransforms -> setChecked(false);
00278     slotToggleFastTransforms();
00279   }
00280 
00281   desktop = config -> readNumEntry("desktop", desktop);
00282   if (desktop > kWinModule->numberOfDesktops())
00283   {
00284     desktop = 0;
00285   }
00286 
00287   if (desktop)
00288   {
00289     info->setDesktop( desktop );
00290   }
00291   else
00292     info->setDesktop( NETWinInfo::OnAllDesktops);
00293 
00294   // Read Themespecific Config Entries
00295   config -> setGroup("theme");
00296   if (config -> hasKey("widgetPosX") && config -> hasKey("widgetPosY"))
00297   {
00298     int xpos = config -> readNumEntry("widgetPosX");
00299     int ypos = config -> readNumEntry("widgetPosY");
00300 
00301     if (xpos < 0)
00302       xpos = 0;
00303     if (ypos < 0)
00304       ypos = 0;
00305     move(xpos, ypos);
00306   }
00307 
00308   haveUpdated = 0;
00309   this->setMouseTracking(true);
00310 
00311 
00312   setFocusPolicy(QWidget::StrongFocus);
00313 }
00314 
00315 karamba::~karamba()
00316 {
00317   //qDebug("karamba::~karamba");
00318   //Remove self from list of open themes
00319   karambaApp->deleteKaramba(this, m_reloading);
00320 
00321   widgetClosed();
00322   if(m_theme.isValid())
00323     writeConfigData();
00324 
00325   delete config;
00326 
00327   if(meterList != 0)
00328   {
00329     meterList->clear();
00330     delete meterList;
00331   }
00332 
00333   if( sensorList != 0 )
00334   {
00335     sensorList->clear();
00336     delete sensorList;
00337   }
00338 
00339   if( imageList != 0 )
00340   {
00341     imageList->clear();
00342     delete imageList;
00343   }
00344 
00345   if( clickList != 0 )
00346   {
00347     clickList->clear();
00348     delete clickList;
00349   }
00350 
00351   if( timeList != 0 )
00352   {
00353     timeList->clear();
00354     delete timeList;
00355   }
00356 
00357   delete toggleLocked;
00358   delete accColl;
00359   delete menuAccColl;
00360   delete themeConfMenu;
00361   delete kpop;
00362   delete widgetMask;
00363   delete kWinModule;
00364   delete defaultTextField;
00365   if (pythonIface != NULL)
00366     delete pythonIface;
00367 }
00368 
00369 bool karamba::parseConfig()
00370 {
00371   //qDebug("karamba::parseConfig");
00372   bool passive = true;
00373 
00374   if(m_theme.open())
00375   {
00376     QValueStack<QPoint> offsetStack;
00377     LineParser lineParser;
00378     int x=0;
00379     int y=0;
00380     int w=0;
00381     int h=0;
00382 
00383     offsetStack.push(QPoint(0,0));
00384 
00385     while(m_theme.nextLine(lineParser))
00386     {
00387       x = lineParser.getInt("X") + offsetStack.top().x();
00388       y = lineParser.getInt("Y") + offsetStack.top().y();
00389       w = lineParser.getInt("W");
00390       h = lineParser.getInt("H");
00391 
00392       if(lineParser.meter() == "KARAMBA" && !foundKaramba )
00393       {
00394         //qDebug("karamba found");
00395         toggleLocked->setChecked(lineParser.getBoolean("LOCKED"));
00396         slotToggleLocked();
00397 
00398         x = ( x < 0 ) ? 0:x;
00399         y = ( y < 0 ) ? 0:y;
00400 
00401         if( w == 0 ||  h == 0)
00402         {
00403           w = 300;
00404           h = 300;
00405         }
00406         setFixedSize(w,h);
00407 
00408         if(lineParser.getBoolean("RIGHT"))
00409         {
00410           QDesktopWidget *d = QApplication::desktop();
00411           x = d->width() - w;
00412         }
00413         else if(lineParser.getBoolean("LEFT"))
00414         {
00415           x = 0;
00416         }
00417 
00418         if(lineParser.getBoolean("BOTTOM"))
00419         {
00420           QDesktopWidget *d = QApplication::desktop();
00421           y = d->height() - h;
00422         }
00423         else if(lineParser.getBoolean("TOP"))
00424         {
00425           y = 0;
00426         }
00427 
00428         move(x,y);
00429         //pm = QPixmap(size());
00430 
00431         if(lineParser.getBoolean("ONTOP"))
00432         {
00433           onTop = true;
00434           KWin::setState( winId(), NET::StaysOnTop );
00435         }
00436 
00437         if(lineParser.getBoolean("MANAGED"))
00438         {
00439           managed = true;
00440           reparent(0, Qt::WType_Dialog | WStyle_Customize | WStyle_NormalBorder
00441                       |  WRepaintNoErase | WDestructiveClose, pos());
00442         }
00443         else
00444         {
00445           info->setState( NETWinInfo::SkipTaskbar
00446               | NETWinInfo::SkipPager,NETWinInfo::SkipTaskbar
00447               | NETWinInfo::SkipPager );
00448           if (onTop)
00449           {
00450             KWin::setState( winId(), NET::StaysOnTop );
00451 
00452           }
00453         }
00454 
00455         if (lineParser.getBoolean("ONALLDESKTOPS"))
00456         {
00457           desktop = 200; // ugly
00458         }
00459 
00460 
00461         bool dfound=false;
00462         //int desktop = lineParser.getInt("DESKTOP", line, dfound);
00463         if (dfound)
00464         {
00465           info->setDesktop( dfound );
00466         }
00467         if(lineParser.getBoolean("TOPBAR"))
00468         {
00469           move(x,0);
00470           KWin::setStrut( winId(), 0, 0, h, 0 );
00471           toggleLocked->setChecked( true );
00472           slotToggleLocked();
00473           toggleLocked->setEnabled(false);
00474         }
00475 
00476         if(lineParser.getBoolean("BOTTOMBAR"))
00477         {
00478           int dh = QApplication::desktop()->height();
00479           move( x, dh - h );
00480           KWin::setStrut( winId(), 0, 0, 0, h );
00481           toggleLocked->setChecked( true );
00482           slotToggleLocked();
00483           toggleLocked->setEnabled(false);
00484         }
00485 
00486         if(lineParser.getBoolean("RIGHTBAR"))
00487         {
00488           int dw = QApplication::desktop()->width();
00489           move( dw - w, y );
00490           KWin::setStrut( winId(), 0, w, 0, 0 );
00491           toggleLocked->setChecked( true );
00492           slotToggleLocked();
00493           toggleLocked->setEnabled(false);
00494         }
00495 
00496         if(lineParser.getBoolean("LEFTBAR"))
00497         {
00498           move( 0, y );
00499           KWin::setStrut( winId(), w, 0, 0, 0 );
00500           toggleLocked->setChecked( true );
00501           slotToggleLocked();
00502           toggleLocked->setEnabled(false);
00503         }
00504 
00505         QString path = lineParser.getString("MASK");
00506 
00507         QFileInfo info(path);
00508         QString absPath;
00509         QBitmap bmMask;
00510         QByteArray ba;
00511         if( info.isRelative() )
00512         {
00513           absPath.setAscii(m_theme.path().ascii());
00514           absPath.append(path.ascii());
00515           ba = m_theme.readThemeFile(path);
00516         }
00517         else
00518         {
00519           absPath.setAscii(path.ascii());
00520           ba = m_theme.readThemeFile(info.fileName());
00521         }
00522         if(m_theme.isZipTheme())
00523         {
00524           bmMask.loadFromData(ba);
00525         }
00526         else
00527         {
00528           bmMask.load(absPath);
00529         }
00530         setMask(bmMask);
00531 
00532         m_interval = lineParser.getInt("INTERVAL");
00533         m_interval = (m_interval == 0) ? 1000 : m_interval;
00534 
00535         QString temp = lineParser.getString("TEMPUNIT", "C").upper();
00536         tempUnit = temp.ascii()[0];
00537         foundKaramba = true;
00538       }
00539 
00540       if(lineParser.meter() == "THEME")
00541       {
00542         QString path = lineParser.getString("PATH");
00543         QFileInfo info(path);
00544         if( info.isRelative())
00545           path = m_theme.path() +"/" + path;
00546         (new karamba( path, QString() ))->show();
00547       }
00548 
00549       if(lineParser.meter() == "<GROUP>")
00550       {
00551         int offsetX = offsetStack.top().x();
00552         int offsetY = offsetStack.top().y();
00553         offsetStack.push( QPoint( offsetX + lineParser.getInt("X"),
00554                                   offsetY + lineParser.getInt("Y")));
00555       }
00556 
00557       if(lineParser.meter() == "</GROUP>")
00558       {
00559         offsetStack.pop();
00560       }
00561 
00562       if(lineParser.meter() == "CLICKAREA")
00563       {
00564         if( !hasMouseTracking() )
00565           setMouseTracking(true);
00566         ClickArea *tmp = new ClickArea(this, x, y, w, h );
00567         tmp->setOnClick(lineParser.getString("ONCLICK"));
00568 
00569         setSensor(lineParser, (Meter*)tmp);
00570         clickList->append( tmp );
00571         if( lineParser.getBoolean("PREVIEW"))
00572           meterList->append( tmp );
00573       }
00574 
00575       // program sensor without a meter
00576       if(lineParser.meter() == "SENSOR=PROGRAM")
00577       {
00578         setSensor(lineParser, 0 );
00579       }
00580 
00581       if(lineParser.meter() == "IMAGE")
00582       {
00583         QString file = lineParser.getString("PATH");
00584         QString file_roll = lineParser.getString("PATHROLL");
00585         int xon = lineParser.getInt("XROLL");
00586         int yon = lineParser.getInt("YROLL");
00587         QString tiptext = lineParser.getString("TOOLTIP");
00588         QString name = lineParser.getString("NAME");
00589         bool bg = lineParser.getBoolean("BACKGROUND");
00590         xon = ( xon <= 0 ) ? x:xon;
00591         yon = ( yon <= 0 ) ? y:yon;
00592 
00593         ImageLabel *tmp = new ImageLabel(this, x, y, 0, 0);
00594         tmp->setValue(file);
00595         if(!file_roll.isEmpty())
00596           tmp->parseImages(file, file_roll, x,y, xon, yon);
00597         tmp->setBackground(bg);
00598         if (!name.isEmpty())
00599           tmp->setName(name.ascii());
00600         if (!tiptext.isEmpty())
00601           tmp->setTooltip(tiptext);
00602 
00603         connect(tmp, SIGNAL(pixmapLoaded()), this, SLOT(externalStep()));
00604         setSensor(lineParser, (Meter*) tmp );
00605         meterList->append (tmp );
00606         imageList->append (tmp );
00607       }
00608 
00609       if(lineParser.meter() == "DEFAULTFONT" )
00610       {
00611         delete defaultTextField;
00612         defaultTextField = new TextField( );
00613 
00614         defaultTextField->setColor(lineParser.getColor("COLOR",
00615                                    QColor("black")));
00616         defaultTextField->setBGColor(lineParser.getColor("BGCOLOR",
00617                                      QColor("white")));
00618         defaultTextField->setFont(lineParser.getString("FONT", "Helvetica"));
00619         defaultTextField->setFontSize(lineParser.getInt("FONTSIZE", 12));
00620         defaultTextField->setAlignment(lineParser.getString("ALIGN",
00621                                        "LEFT"));
00622         defaultTextField->setFixedPitch(lineParser.getBoolean("FIXEDPITCH",
00623                                         false));
00624         defaultTextField->setShadow(lineParser.getInt("SHADOW", 0));
00625       }
00626 
00627       if(lineParser.meter() == "TEXT" ||
00628          lineParser.meter() == "CLICKMAP" ||
00629          lineParser.meter() == "RICHTEXT" ||
00630          lineParser.meter() == "INPUT")
00631       {
00632         TextField defTxt;
00633 
00634         if(defaultTextField)
00635           defTxt = *defaultTextField;
00636 
00637         TextField* tmpText = new TextField();
00638 
00639         tmpText->setColor(lineParser.getColor("COLOR", defTxt.getColor()));
00640         tmpText->setBGColor(lineParser.getColor("BGCOLOR",
00641                             defTxt.getBGColor()));
00642         tmpText->setFont(lineParser.getString("FONT", defTxt.getFont()));
00643         tmpText->setFontSize(lineParser.getInt("FONTSIZE",
00644                              defTxt.getFontSize()));
00645         tmpText->setAlignment(lineParser.getString("ALIGN",
00646                               defTxt.getAlignmentAsString()));
00647         tmpText->setFixedPitch(lineParser.getInt("FIXEDPITCH",
00648                                defTxt.getFixedPitch()));
00649 
00650         tmpText->setShadow(lineParser.getInt("SHADOW", defTxt.getShadow()));
00651 
00652         // ////////////////////////////////////////////////////
00653         // Now handle the specifics
00654         if(lineParser.meter() == "TEXT")
00655         {
00656 
00657           TextLabel *tmp = new TextLabel(this, x, y, w, h );
00658           tmp->setTextProps(tmpText);
00659           tmp->setValue(
00660               m_theme.locale()->translate(lineParser.getString("VALUE").ascii()));
00661 
00662           QString name = lineParser.getString("NAME");
00663           if (!name.isEmpty())
00664             tmp->setName(name.ascii());
00665 
00666           setSensor(lineParser, (Meter*)tmp);
00667           meterList->append ( tmp );
00668         }
00669 
00670         if(lineParser.meter() == "CLICKMAP")
00671         {
00672           if( !hasMouseTracking() )
00673             setMouseTracking(true);
00674           ClickMap *tmp = new ClickMap(this, x, y, w, h);
00675           tmp->setTextProps( tmpText );
00676 
00677           setSensor(lineParser, (Meter*)tmp);
00678           // set all params
00679           clickList -> append(tmp);
00680           meterList->append( tmp );
00681 
00682         }
00683 
00684         if(lineParser.meter() == "RICHTEXT")
00685         {
00686           RichTextLabel *tmp = new RichTextLabel(this, x, y, w, h);
00687 
00688           bool dUl = lineParser.getBoolean("UNDERLINE");
00689 
00690           tmp->setText(
00691               m_theme.locale()->translate(lineParser.getString("VALUE").ascii()), dUl);
00692           tmp->setTextProps( tmpText );
00693           tmp->setWidth(w);
00694           tmp->setHeight(h);
00695 
00696           QString name = lineParser.getString("NAME");
00697           if (!name.isEmpty())
00698             tmp->setName(name.ascii());
00699 
00700           setSensor(lineParser, (Meter*)tmp);
00701           clickList -> append(tmp);
00702           meterList->append ( tmp );
00703         }
00704 
00705         if(lineParser.meter() == "INPUT")
00706         {
00707           Input *tmp = new Input(this, x, y, w, h);
00708 
00709           QString name = lineParser.getString("NAME");
00710           if (!name.isEmpty())
00711             tmp->setName(name.ascii());
00712 
00713           tmp->setTextProps(tmpText);
00714           tmp->setValue(
00715               m_theme.locale()->translate(lineParser.getString("VALUE").ascii()));
00716 
00717           meterList->append(tmp);
00718           passive = false;
00719         }
00720       }
00721 
00722       if(lineParser.meter() == "BAR")
00723       {
00724         Bar *tmp = new Bar(this, x, y, w, h );
00725         tmp->setImage(lineParser.getString("PATH").ascii());
00726         tmp->setVertical(lineParser.getBoolean("VERTICAL"));
00727         tmp->setMax(lineParser.getInt("MAX", 100));
00728         tmp->setMin(lineParser.getInt("MIN", 0));
00729         tmp->setValue(lineParser.getInt("VALUE"));
00730         QString name = lineParser.getString("NAME");
00731         if (!name.isEmpty())
00732           tmp->setName(name.ascii());
00733         setSensor(lineParser, (Meter*)tmp );
00734         meterList->append ( tmp );
00735       }
00736 
00737       if(lineParser.meter() == "GRAPH")
00738       {
00739         int points = lineParser.getInt("POINTS");
00740 
00741         Graph *tmp = new Graph(this, x, y, w, h, points);
00742         tmp->setMax(lineParser.getInt("MAX", 100));
00743         tmp->setMin(lineParser.getInt("MIN", 0));
00744         QString name = lineParser.getString("NAME");
00745         if (!name.isEmpty())
00746           tmp->setName(name.ascii());
00747 
00748         tmp->setColor(lineParser.getColor("COLOR"));
00749 
00750         setSensor(lineParser, (Graph*)tmp);
00751         meterList->append ( tmp );
00752       }
00753     }
00754 
00755     if(passive && !managed)
00756     {
00757       // Matthew Kay: set window type to "dock"
00758       // (plays better with taskbar themes this way)
00759       KWin::setType(winId(), NET::Dock);
00760       #if defined(KDE_MAKE_VERSION)
00761         #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,9)
00762           //KDE 3.2 addition for the always on top issues
00763           KWin::setState(winId(), NET::KeepBelow);
00764         #endif
00765       #endif
00766     }
00767 
00768     m_theme.close();
00769   }
00770   //qDebug("parseConfig ok: %d", foundKaramba);
00771   if( !foundKaramba )
00772   {
00773     //  interval = initKaramba( "", 0, 0, 0, 0 );
00774     //   this->close(true);
00775     //delete this;
00776     return false;
00777   }
00778   else
00779   {
00780     return true;
00781   }
00782 }
00783 
00784 void karamba::start()
00785 {
00786   m_sysTimer = new QTimer(this);
00787 
00788   connect(m_sysTimer, SIGNAL(timeout()), SLOT(step()));
00789 
00790   m_sysTimer->start(m_interval);
00791 
00792     //Start the widget running
00793   QTimer::singleShot( 0, this, SLOT(step()) );
00794 
00795   if( !(onTop || managed) )
00796     lowerTimer.start();
00797 }
00798 
00799 void karamba::makeActive()
00800 {
00801   KWin::setType(winId(), NET::Normal);
00802 
00803   #if defined(KDE_MAKE_VERSION)
00804     #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,9)
00805       //KDE 3.2 addition for the always on top issues
00806       KWin::setState(winId(), NET::Modal);
00807     #endif
00808   #endif
00809 }
00810 
00811 void karamba::makePassive()
00812 {
00813   if(managed)
00814     return;
00815 
00816   QObject *meter;
00817   for (meter = meterList->first(); meter; meter = meterList->next())
00818   {
00819     if((meter)->isA("Input"))
00820       return;
00821   }
00822 
00823   // Matthew Kay: set window type to "dock" (plays better with taskbar themes
00824   // this way)
00825   KWin::setType(winId(), NET::Dock);
00826   #if defined(KDE_MAKE_VERSION)
00827     #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,9)
00828       //KDE 3.2 addition for the always on top issues
00829       KWin::setState(winId(), NET::KeepBelow);
00830     #endif
00831   #endif
00832 }
00833 
00834 void karamba::popupNotify(int)
00835 {
00836   //qDebug("karamba::popupNotify");
00837 }
00838 
00839 void karamba::reloadConfig()
00840 {
00841   //qDebug("karamba::reloadConfig: %s", m_theme.file().ascii());
00842   writeConfigData();
00843   if(m_theme.exists())
00844   {
00845     QFileInfo fileInfo( m_theme.file() );
00846     (new karamba(m_theme.file(), fileInfo.baseName(), true, m_instance))->show();
00847   }
00848   closeTheme(true);
00849 }
00850 
00851 void karamba::closeTheme(bool reloading)
00852 {
00853   m_reloading = reloading;
00854   close();
00855 }
00856 
00857 void karamba::killWidget()
00858 {
00859   closeTheme();
00860 }
00861 
00862 void karamba::initPythonInterface()
00863 {
00864   pythonIface = new KarambaPython(m_theme, m_reloading);
00865 }
00866 
00867 void karamba::editConfig()
00868 {
00869   //qDebug("karamba::editConfig");
00870   QFileInfo fileInfo( m_theme.file() );
00871   QString path;
00872 
00873   if( fileInfo.isRelative() )
00874   {
00875     path = m_theme.path() + "/" + m_theme.file();
00876   }
00877   else
00878   {
00879     path = m_theme.file();
00880   }
00881 
00882   KRun::runURL( KURL( path ), "text/plain" );
00883 }
00884 
00885 void karamba::editScript()
00886 {
00887   //qDebug("karamba::editScript");
00888   QFileInfo fileInfo( m_theme.file() );
00889   QString path;
00890 
00891   if( fileInfo.isRelative() )
00892   {
00893       path = m_theme.path() + "/" + m_theme.name() + ".py";
00894   }
00895   else
00896   {
00897       path = QFileInfo(m_theme.file()).dirPath() + "/" + m_theme.name() + ".py";
00898   }
00899   KRun::runURL( KURL( path ), "text/plain" );
00900 }
00901 
00902 QString karamba::findSensorFromMap(Sensor* sensor)
00903 {
00904   //qDebug("karamba::findSensorFromMap");
00905   QMap<QString,Sensor*>::ConstIterator it;
00906   QMap<QString,Sensor*>::ConstIterator end( sensorMap.end() );
00907   for ( it = sensorMap.begin(); it != end; ++it )
00908   {
00909     if (it.data() == sensor)
00910       return it.key();
00911   }
00912   return "";
00913 }
00914 
00915 Sensor* karamba::findSensorFromList(Meter* meter)
00916 {
00917   //qDebug("karamba::findSensorFromList");
00918   QObjectListIt it( *sensorList ); // iterate over meters
00919 
00920   while ( it != 0 )
00921   {
00922     if (((Sensor*) *it)->hasMeter(meter))
00923       return ((Sensor*)*it);
00924     ++it;
00925   }
00926   return NULL;
00927 }
00928 
00929 QString karamba::getSensor(Meter* meter)
00930 {
00931   //qDebug("karamba::getSensor");
00932   QString s;
00933   Sensor* sensor = findSensorFromList(meter);
00934   if (sensor)
00935     s = findSensorFromMap(sensor);
00936   return s;
00937 }
00938 
00939 void karamba::deleteMeterFromSensors(Meter* meter)
00940 {
00941   //qDebug("karamba::deleteMeterFromSensors");
00942   Sensor* sensor = findSensorFromList(meter);
00943 
00944   if (sensor)
00945   {
00946     sensor->deleteMeter(meter);
00947     if (sensor->isEmpty())
00948     {
00949       QString s = findSensorFromMap(sensor);
00950       sensorMap.erase(s);
00951       sensorList->removeRef(sensor);
00952     }
00953   }
00954 }
00955 
00956 void karamba::setSensor(const LineParser& lineParser, Meter* meter)
00957 {
00958   //qDebug("karamba::setSensor");
00959   Sensor* sensor = 0;
00960 
00961   deleteMeterFromSensors(meter);
00962 
00963   QString sens = lineParser.getString("SENSOR").upper();
00964 
00965   if( sens == "CPU" )
00966   {
00967     QString cpuNbr = lineParser.getString("CPU");
00968     sensor = sensorMap["CPU"+cpuNbr];
00969     if (sensor == 0)
00970     {
00971       int interval = lineParser.getInt("INTERVAL");
00972       interval = (interval == 0)?1000:interval;
00973       sensor = ( sensorMap["CPU"+cpuNbr] = new CPUSensor( cpuNbr, interval ) );
00974       sensorList->append( sensor );
00975     }
00976     SensorParams *sp = new SensorParams(meter);
00977     sp->addParam("FORMAT",
00978                  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
00979     sp->addParam("DECIMALS",lineParser.getString("DECIMALS"));
00980 
00981     sensor->addMeter(sp);
00982     sensor->setMaxValue(sp);
00983 
00984   }
00985 
00986   if( sens == "MEMORY" )
00987   {
00988     sensor = sensorMap["MEMORY"];
00989     if (sensor == 0)
00990     {
00991       int interval = lineParser.getInt("INTERVAL");
00992       interval = (interval == 0)?3000:interval;
00993       sensor = ( sensorMap["MEMORY"] = new MemSensor( interval ) );
00994       sensorList->append( sensor );
00995     }
00996     SensorParams *sp = new SensorParams(meter);
00997     sp->addParam("FORMAT",
00998         m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
00999 
01000     sensor->addMeter(sp);
01001     sensor->setMaxValue(sp);
01002   }
01003 
01004 
01005   if( sens == "DISK" )
01006   {
01007     sensor = sensorMap["DISK"];
01008     if (sensor == 0)
01009     {
01010       int interval = lineParser.getInt("INTERVAL");
01011       interval = (interval == 0)?5000:interval;
01012       sensor = ( sensorMap["DISK"] = new DiskSensor( interval ) );
01013       connect( sensor, SIGNAL(initComplete()), this, SLOT(externalStep()) );
01014       sensorList->append( sensor );
01015     }
01016     // meter->setMax( ((DiskSensor*)sensor)->getTotalSpace(mntPt)/1024 );
01017     SensorParams *sp = new SensorParams(meter);
01018     QString mntPt = lineParser.getString("MOUNTPOINT");
01019     if( mntPt.isEmpty()  )
01020     {
01021         mntPt = "/";
01022     }
01023     // remove any trailing '/' from mount points in the .theme config, our
01024     // mntMap doesn't like trailing '/'s for matching in DiskSensor
01025     if( mntPt.length() > 1 && mntPt.endsWith("/") )
01026     {
01027         mntPt.remove( mntPt.length()-1, 1 );
01028     }
01029     sp->addParam("MOUNTPOINT",mntPt);
01030     sp->addParam("FORMAT",
01031                  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
01032     sensor->addMeter(sp);
01033     sensor->setMaxValue(sp);
01034   }
01035 
01036   if( sens == "NETWORK")
01037   {
01038     int interval = lineParser.getInt("INTERVAL");
01039     interval = (interval == 0)?2000:interval;
01040     QString device = lineParser.getString("DEVICE");
01041     sensor = sensorMap["NETWORK"+device];
01042     if (sensor == 0)
01043     {
01044       sensor = ( sensorMap["NETWORK"+device] =
01045           new NetworkSensor(device, interval));
01046       sensorList->append( sensor );
01047     }
01048     SensorParams *sp = new SensorParams(meter);
01049     sp->addParam("FORMAT",
01050                  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
01051     sp->addParam("DECIMALS", lineParser.getString("DECIMALS"));
01052     sensor->addMeter(sp);
01053   }
01054 
01055   if( sens == "UPTIME" )
01056   {
01057     sensor = sensorMap["UPTIME"];
01058     if (sensor == 0)
01059     {
01060       int interval = lineParser.getInt("INTERVAL");
01061       interval = (interval == 0)?60000:interval;
01062       sensor = ( sensorMap["UPTIME"] = new UptimeSensor( interval ));
01063       sensorList->append( sensor );
01064 
01065     }
01066     SensorParams *sp = new SensorParams(meter);
01067     sp->addParam("FORMAT",
01068                  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
01069     sensor->addMeter(sp);
01070   }
01071 
01072   if( sens == "SENSOR" )
01073   {
01074     sensor = sensorMap["SENSOR"];
01075     if (sensor == 0)
01076     {
01077       int interval = lineParser.getInt("INTERVAL");
01078       interval = (interval == 0)?30000:interval;
01079       sensor = (sensorMap["SENSOR"] = new SensorSensor(interval, tempUnit));
01080       sensorList->append( sensor );
01081     }
01082     SensorParams *sp = new SensorParams(meter);
01083     sp->addParam("FORMAT",
01084                  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
01085     sp->addParam("TYPE", lineParser.getString("TYPE"));
01086     sensor->addMeter(sp);
01087   }
01088 
01089 
01090   if( sens == "TEXTFILE" )
01091   {
01092     QString path = lineParser.getString("PATH");
01093     bool rdf = lineParser.getBoolean("RDF");
01094     sensor = sensorMap["TEXTFILE"+path];
01095     if (sensor == 0)
01096     {
01097       int interval = lineParser.getInt("INTERVAL");
01098       interval = ( interval == 0 )?60000:interval;
01099       QString encoding = lineParser.getString("ENCODING");
01100 
01101       sensor = ( sensorMap["TEXTFILE"+path] =
01102                    new TextFileSensor( path, rdf, interval, encoding ) );
01103       sensorList->append( sensor );
01104     }
01105     SensorParams *sp = new SensorParams(meter);
01106     sp->addParam("LINE",QString::number(lineParser.getInt("LINE")));
01107     sensor->addMeter(sp);
01108   }
01109 
01110 
01111   if( sens == "TIME")
01112   {
01113     sensor = sensorMap["DATE"];
01114     if (sensor == 0)
01115     {
01116       int interval = lineParser.getInt("INTERVAL");
01117       interval = (interval == 0)?60000:interval;
01118       sensor = ( sensorMap["DATE"] = new DateSensor( interval ) );
01119       sensorList->append( sensor );
01120       timeList->append( sensor );
01121     }
01122     SensorParams *sp = new SensorParams(meter);
01123     sp->addParam("FORMAT",
01124                  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
01125     sp->addParam("CALWIDTH",lineParser.getString("CALWIDTH"));
01126     sp->addParam("CALHEIGHT",lineParser.getString("CALHEIGHT"));
01127     sensor->addMeter(sp);
01128   }
01129 
01130 #ifdef HAVE_XMMS
01131 
01132   if( sens == "XMMS" )
01133   {
01134     sensor = sensorMap["XMMS"];
01135     if (sensor == 0)
01136     {
01137       int interval = lineParser.getInt("INTERVAL");
01138       interval = (interval == 0)?1000:interval;
01139       QString encoding = lineParser.getString("ENCODING");
01140 
01141       sensor = ( sensorMap["XMMS"] = new XMMSSensor( interval, encoding ) );
01142       sensorList->append( sensor );
01143     }
01144     SensorParams *sp = new SensorParams(meter);
01145     sp->addParam("FORMAT",
01146                  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
01147     sensor->addMeter(sp);
01148     sensor->setMaxValue(sp);
01149   }
01150 #endif // HAVE_XMMS
01151 
01152 
01153   if( sens == "NOATUN" )
01154   {
01155     sensor = sensorMap["NOATUN"];
01156     if (sensor == 0)
01157     {
01158       int interval = lineParser.getInt("INTERVAL");
01159       interval = (interval == 0)?1000:interval;
01160       sensor = ( sensorMap["NOATUN"] = new NoatunSensor( interval, client ) );
01161       sensorList->append( sensor );
01162     }
01163     SensorParams *sp = new SensorParams(meter);
01164     sp->addParam("FORMAT",
01165                  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
01166     sensor->addMeter(sp);
01167     sensor->setMaxValue(sp);
01168   }
01169 
01170   if( sens == "PROGRAM")
01171   {
01172     QString progName = lineParser.getString("PROGRAM");
01173     sensor = sensorMap["PROGRAM"+progName];
01174     if (sensor == 0)
01175     {
01176       int interval = lineParser.getInt("INTERVAL");
01177       interval = (interval == 0)?3600000:interval;
01178       QString encoding = lineParser.getString("ENCODING");
01179 
01180       sensor = (sensorMap["PROGRAM"+progName] =
01181                   new ProgramSensor( progName, interval, encoding ) );
01182       sensorList->append( sensor );
01183     }
01184     SensorParams *sp = new SensorParams(meter);
01185     sp->addParam( "LINE", QString::number(lineParser.getInt("LINE")));
01186     sp->addParam( "THEMAPATH", m_theme.path() );
01187     sensor->addMeter(sp);
01188   }
01189 
01190   if( sens == "RSS" )
01191   {
01192     QString source = lineParser.getString("SOURCE");
01193     QString format =
01194         m_theme.locale()->translate(lineParser.getString("FORMAT").ascii());
01195 
01196     sensor = sensorMap["RSS"+source];
01197     if (sensor == 0)
01198     {
01199       int interval = lineParser.getInt( "INTERVAL");
01200       interval = ( interval == 0 )?60000:interval;
01201       QString encoding = lineParser.getString("ENCODING");
01202 
01203       sensor = ( sensorMap["RSS"+source] =
01204                    new RssSensor( source, interval, format, encoding ) );
01205       sensorList->append( sensor );
01206     }
01207     SensorParams *sp = new SensorParams(meter);
01208     sp->addParam("SOURCE",lineParser.getString("SOURCE"));
01209     sensor->addMeter(sp);
01210   }
01211 
01212   if (sensor != 0)
01213   {
01214     QTimer::singleShot( 0, sensor, SLOT(update()) );
01215     sensor->start();
01216   }
01217 }
01218 
01219 void karamba::slotFileChanged( const QString & )
01220 {
01221   reloadConfig();
01222 }
01223 
01224 void karamba::passMenuOptionChanged(QString key, bool value)
01225 {
01226   //Everything below is to call the python callback function
01227   if (pythonIface && pythonIface->isExtensionLoaded())
01228     pythonIface->menuOptionChanged(this, key, value);
01229 }
01230 
01231 void karamba::setIncomingData(QString theme, QString obj)
01232 {
01233   KarambaApplication* app = (KarambaApplication*)qApp;
01234 
01235   kdDebug() << "karamba::setIncomingData " << theme << obj << endl;
01236    //QByteArray data;
01237    //QDataStream dataStream( data, IO_WriteOnly );
01238    //dataStream << theme;
01239    //dataStream << txt;
01240 
01241    //kapp->dcopClient()->send( app->dcopClient()->appId(), "KarambaIface", "themeNotify(QString,QString)", data );
01242 
01243   DCOPClient *c = kapp->dcopClient();
01244   if (!c->isAttached())
01245     c->attach();
01246 
01247   if(app->dcopStub())
01248     app->dcopStub()->setIncomingData(theme, obj);
01249 }
01250 
01251 void karamba::callTheme(QString theme, QString txt)
01252 {
01253   KarambaApplication* app = (KarambaApplication*)qApp;
01254   kdDebug() << "karamba::callTheme " << theme << txt << endl;
01255   //qWarning("karamba::callTheme");
01256    //QByteArray data;
01257    //QDataStream dataStream( data, IO_WriteOnly );
01258    //dataStream << theme;
01259    //dataStream << txt;
01260 
01261    //kapp->dcopClient()->send( app->dcopClient()->appId(), "KarambaIface", "themeNotify(QString,QString)", data );
01262 
01263   DCOPClient *c = kapp->dcopClient();
01264   if (!c->isAttached())
01265     c->attach();
01266 
01267   if(app->dcopStub())
01268     app->dcopStub()->themeNotify(theme, txt);
01269 }
01270 
01271 void karamba::themeNotify(QString theme, QString txt)
01272 {
01273   kdDebug() << "karamba::themeNotify" << theme << txt << endl;
01274   if (pythonIface->isExtensionLoaded())
01275   {
01276       pythonIface->themeNotify(this, theme.ascii(), txt.ascii());
01277   }
01278 }
01279 
01280 void karamba::meterClicked(QMouseEvent* e, Meter* meter)
01281 {
01282   //qWarning("karamba::meterClicked");
01283   if (pythonIface && pythonIface->isExtensionLoaded() && haveUpdated)
01284   {
01285     int button = 0;
01286 
01287     if( e->button() == Qt::LeftButton )
01288       button = 1;
01289     else if( e->button() == Qt::MidButton )
01290       button = 2;
01291     else if( e->button() == Qt::RightButton )
01292       button = 3;
01293 
01294     if (RichTextLabel* richText = dynamic_cast<RichTextLabel*>(meter))
01295     {
01296       pythonIface->meterClicked(this, richText->anchorAt(e->x(), e->y()),
01297                                 button);
01298     }
01299     else
01300     {
01301       pythonIface->meterClicked(this, meter, button);
01302     }
01303   }
01304 }
01305 
01306 void karamba::changeInterval(int interval)
01307 {
01308   if (m_sysTimer != NULL)
01309     m_sysTimer->changeInterval(interval);
01310 }
01311 
01312 void karamba::passClick(QMouseEvent *e)
01313 {
01314   //qDebug("karamba::passClick");
01315   QObjectListIt it2( *timeList ); // iterate over meters
01316   while ( it2 != 0 )
01317   {
01318     (( DateSensor* ) *it2)->toggleCalendar( e );
01319     ++it2;
01320   }
01321 
01322 
01323   // We create a temporary click list here because original
01324   // can change during the loop (infinite loop Bug 994359)
01325   QObjectList clickListTmp(*clickList);
01326   QObjectListIt it(clickListTmp);
01327   while (it != 0)
01328   {
01329     Meter* meter = (Meter*)(*it);
01330     // Check if meter is still in list
01331     if (clickList->containsRef(meter) && meter->click(e))
01332     {
01333       // callback
01334       meterClicked(e, meter);
01335     }
01336     ++it;
01337   }
01338 
01339   //Everything below is to call the python callback function
01340   if (pythonIface && pythonIface->isExtensionLoaded() && haveUpdated)
01341   {
01342     int button = 0;
01343 
01344     if( e->button() == Qt::LeftButton )
01345       button = 1;
01346     else if( e->button() == Qt::MidButton )
01347       button = 2;
01348     else if( e->button() == Qt::RightButton )
01349       button = 3;
01350 
01351     pythonIface->widgetClicked(this, e->x(), e->y(), button);
01352   }
01353 }
01354 
01355 void karamba::passWheelClick( QWheelEvent *e )
01356 {
01357   //qDebug("karamba::passWheelClick");
01358   //Everything below is to call the python callback function
01359   if (pythonIface && pythonIface->isExtensionLoaded() && haveUpdated)
01360   {
01361     int button = 0;
01362 
01363     if( e->delta() > 0 )
01364       button = 4;
01365     else
01366       button = 5;
01367 
01368     pythonIface->widgetClicked(this, e->x(), e->y(), button);
01369   }
01370 }
01371 
01372 void karamba::management_popup( void )
01373 {
01374   kpop->popup(QCursor::pos());
01375 }
01376 
01377 void karamba::mousePressEvent( QMouseEvent *e )
01378 {
01379   //qDebug("karamba::mousePressEvent");
01380   if( e->button() == RightButton && !want_right_button )
01381   {
01382     management_popup();
01383   }
01384   else
01385   {
01386     clickPos = e->pos();
01387     if( toggleLocked -> isChecked() )
01388       passClick( e );
01389     if( !(onTop || managed))
01390       KWin::lowerWindow( winId() );
01391   }
01392 }
01393 
01394 void karamba::wheelEvent( QWheelEvent *e )
01395 {
01396   //qDebug("karamba::wheelEvent");
01397   passWheelClick( e );
01398 }
01399 
01400 void karamba::mouseReleaseEvent( QMouseEvent *e )
01401 {
01402   //qDebug("karamba::mouseReleaseEvent");
01403   clickPos = e->pos();
01404 }
01405 
01406 void karamba::mouseDoubleClickEvent( QMouseEvent *e )
01407 {
01408   //qDebug("karamba::mouseDoubleClickEvent");
01409   if( !toggleLocked -> isChecked() )
01410   {
01411     passClick( e );
01412   }
01413 }
01414 
01415 void karamba::keyPressEvent(QKeyEvent *e)
01416 {
01417   //qDebug("karamba::keyPressEvent");
01418   keyPressed(e->text(), 0);
01419 }
01420 
01421 void karamba::keyPressed(const QString& s, const Meter* meter)
01422 {
01423   if (pythonIface && pythonIface->isExtensionLoaded())
01424     pythonIface->keyPressed(this, meter, s);
01425 }
01426 
01427 void karamba::mouseMoveEvent( QMouseEvent *e )
01428 {
01429   //qDebug("karamba::mouseMoveEvent");
01430   if( e->state() !=  0 && e->state() < 16 && !toggleLocked -> isChecked() )
01431   {
01432     move( e->globalPos() - clickPos );
01433   }
01434   else
01435   {
01436     // Change cursor over ClickArea
01437     QObjectListIt it(*clickList);
01438     bool insideArea = false;
01439 
01440     while (it != 0)
01441     {
01442       insideArea = ((Meter*)(*it)) -> insideActiveArea(e -> x(), e ->y());
01443       if (insideArea)
01444       {
01445          break;
01446       }
01447       ++it;
01448     }
01449 
01450     if(insideArea)
01451     {
01452       if( cursor().shape() != PointingHandCursor )
01453         setCursor( PointingHandCursor );
01454     }
01455     else
01456     {
01457       if( cursor().shape() != ArrowCursor )
01458         setCursor( ArrowCursor );
01459     }
01460 
01461     QObjectListIt image_it( *imageList);        // iterate over image sensors
01462     while ( image_it != 0 )
01463     {
01464       ((ImageLabel*) *image_it)->rolloverImage(e);
01465       ++image_it;
01466     }
01467   }
01468 
01469   if (pythonIface && pythonIface->isExtensionLoaded())
01470   {
01471     int button = 0;
01472 
01473     //Modified by Ryan Nickell (p0z3r@mail.com) 03/16/2004
01474     // This will work now, but only when you move at least
01475     // one pixel in any direction with your mouse.
01476     //if( e->button() == Qt::LeftButton )
01477     if( e->state() == LeftButton)
01478       button = 1;
01479     //else if( e->button() == Qt::MidButton )
01480     else if( e->state() == MidButton )
01481       button = 2;
01482     //else if( e->button() == Qt::RightButton )
01483     else if( e->state() == RightButton )
01484       button = 3;
01485 
01486     pythonIface->widgetMouseMoved(this, e->x(), e->y(), button);
01487   }
01488 }
01489 
01490 void karamba::closeEvent ( QCloseEvent *  qc)
01491 {
01492   //qDebug("karamba::closeEvent");
01493   qc->accept();
01494   //  close(true);
01495   //  delete this;
01496 }
01497 
01498 void karamba::paintEvent ( QPaintEvent *e)
01499 {
01500   //kdDebug() << k_funcinfo << pm.size() << endl;
01501   if(pm.width() == 0)
01502     return;
01503   if( !(onTop || managed))
01504   {
01505     if( lowerTimer.elapsed() > 100 )
01506     {
01507       KWin::lowerWindow( winId() );
01508       lowerTimer.restart();
01509     }
01510   }
01511   QRect rect = e->rect();
01512   bitBlt(this,rect.topLeft(),&pm,rect,Qt::CopyROP);
01513 }
01514 
01515 void karamba::updateSensors()
01516 {
01517   //qDebug("karamba::updateSensors");
01518   QObjectListIt it( *sensorList ); // iterate over meters
01519   while ( it != 0 )
01520   {
01521     ((Sensor*) *it)->update();
01522     ++it;
01523   }
01524   QTimer::singleShot( 500, this, SLOT(step()) );
01525 }
01526 
01527 void karamba::updateBackground(KSharedPixmap* kpm)
01528 {
01529   //kdDebug() << k_funcinfo << pm.size() << endl;
01530   // if pm width == 0 this is the first time we come here and we should start
01531   // the theme. This is because we need the background before starting.
01532   //if(pm.width() == 0)
01533   if( !themeStarted )
01534   {
01535     themeStarted = true;
01536     start();
01537   }
01538   background = QPixmap(*kpm);
01539 
01540   QPixmap buffer = QPixmap(size());
01541 
01542   pm = QPixmap(size());
01543   buffer.fill(Qt::black);
01544 
01545   QObjectListIt it( *imageList ); // iterate over meters
01546   p.begin(&buffer);
01547   bitBlt(&buffer,0,0,&background,0,Qt::CopyROP);
01548 
01549   while ( it != 0 )
01550   {
01551     if (((ImageLabel*) *it)->background == 1)
01552     {
01553       ((ImageLabel*) *it)->mUpdate(&p, 1);
01554     }
01555     ++it;
01556   }
01557   p.end();
01558 
01559   bitBlt(&pm,0,0,&buffer,0,Qt::CopyROP);
01560   background = pm;
01561 
01562   QPixmap buffer2 = QPixmap(size());
01563 
01564   pm = QPixmap(size());
01565   buffer2.fill(Qt::black);
01566 
01567   QObjectListIt it2( *meterList ); // iterate over meters
01568   p.begin(&buffer2);
01569   bitBlt(&buffer2,0,0,&background,0,Qt::CopyROP);
01570 
01571   while ( it2 != 0 )
01572   {
01573     ((Meter*) *it2)->mUpdate(&p);
01574     ++it2;
01575   }
01576   p.end();
01577 
01578   bitBlt(&pm,0,0,&buffer2,0,Qt::CopyROP);
01579   if (systray != 0)
01580   {
01581     systray->updateBackgroundPixmap(buffer2);
01582   }
01583   repaint();
01584 }
01585 
01586 void karamba::currentDesktopChanged( int i )
01587 {
01588   //qDebug("karamba::currentDesktopChanged");
01589   kroot->repaint( true );
01590   if (pythonIface && pythonIface->isExtensionLoaded())
01591     pythonIface->desktopChanged(this, i);
01592 }
01593 
01594 void karamba::currentWallpaperChanged(int i )
01595 {
01596   //qDebug("karamba::currentWallpaperChanged");
01597   kroot->repaint( true );
01598   if (pythonIface && pythonIface->isExtensionLoaded())
01599     pythonIface->wallpaperChanged(this, i);
01600 }
01601 
01602 void karamba::externalStep()
01603 {
01604   //kdDebug() << k_funcinfo << pm.size() << endl;
01605   if (widgetUpdate)
01606   {
01607     QPixmap buffer = QPixmap(size());
01608 
01609     pm = QPixmap(size());
01610     buffer.fill(Qt::black);
01611 
01612     QObjectListIt it( *meterList ); // iterate over meters
01613     p.begin(&buffer);
01614     bitBlt(&buffer,0,0,&background,0,Qt::CopyROP);
01615 
01616     while ( it != 0 )
01617     {
01618       ((Meter*) *it)->mUpdate(&p);
01619       ++it;
01620     }
01621     p.end();
01622 
01623     bitBlt(&pm,0,0,&buffer,0,Qt::CopyROP);
01624     repaint();
01625   }
01626 }
01627 
01628 void karamba::step()
01629 {
01630   //kdDebug() << k_funcinfo << pm.size() << endl;
01631   if (widgetUpdate && haveUpdated)
01632   {
01633     pm = QPixmap(size());
01634     QPixmap buffer = QPixmap(size());
01635     buffer.fill(Qt::black);
01636 
01637     QObjectListIt it( *meterList ); // iterate over meters
01638     p.begin(&buffer);
01639 
01640     bitBlt(&buffer,0,0,&background,0,Qt::CopyROP);
01641 
01642     while (it != 0)
01643     {
01644       ((Meter*) *it)->mUpdate(&p);
01645       ++it;
01646     }
01647     p.end();
01648 
01649     bitBlt(&pm,0,0,&buffer,0,Qt::CopyROP);
01650     update();
01651   }
01652 
01653   if (pythonIface && pythonIface->isExtensionLoaded())
01654   {
01655     if (haveUpdated == 0)
01656       pythonIface->initWidget(this);
01657     else
01658       pythonIface->widgetUpdated(this);
01659   }
01660 
01661   if (haveUpdated == 0)
01662     haveUpdated = 1;
01663 }
01664 
01665 void karamba::widgetClosed()
01666 {
01667   //qDebug("karamba::widgetClosed");
01668   if (pythonIface && pythonIface->isExtensionLoaded())
01669     pythonIface->widgetClosed(this);
01670 }
01671 
01672 void karamba::slotToggleLocked()
01673 {
01674   //qDebug("karamba::slotToggleLocked");
01675   if(toggleLocked->isChecked())
01676   {
01677     toggleLocked->setIconSet(SmallIconSet("lock"));
01678   }
01679   else
01680   {
01681     toggleLocked->setIconSet(SmallIconSet("move"));
01682   }
01683 }
01684 
01685 void karamba::slotToggleFastTransforms()
01686 {
01687   //qDebug("karamba::slotToggleFastTransforms");
01688   //    bool fastTransforms = toggleFastTransforms -> isChecked();
01689   //    if (toggleFastTransforms -> isChecked())
01690   //    {
01691   //     toggleFastTransforms -> setIconSet(SmallIconSet("ok"));
01692   //    }
01693   //    else
01694   //    {
01695   //     QPixmap ok_disabled;
01696   //            toggleFastTransforms -> setIconSet(ok_disabled);
01697   //    }
01698   //config.setGroup("internal");
01699   //config.writeEntry("fastTransforms", toggleFastTransforms -> isChecked());
01700 }
01701 
01702 
01703 bool karamba::useSmoothTransforms()
01704 {
01705   //qDebug("karamba::useSmoothTransforms");
01706   return !toggleFastTransforms -> isChecked();
01707 }
01708 
01709 void karamba::writeConfigData()
01710 {
01711   //qDebug("karamba::writeConfigData");
01712   config -> setGroup("internal");
01713   config -> writeEntry("lockedPosition", toggleLocked -> isChecked() );
01714   config -> writeEntry("fastTransforms", toggleFastTransforms -> isChecked() );
01715   config -> writeEntry("desktop", desktop );
01716   config -> setGroup("theme");
01717   // Widget Position
01718   config -> writeEntry("widgetPosX", x());
01719   config -> writeEntry("widgetPosY", y());
01720   // Widget Size
01721   config -> writeEntry("widgetWidth", width());
01722   config -> writeEntry("widgetHeight", height());
01723 
01724   // write changes to DiskSensor
01725   config -> sync();
01726   //qWarning("Config File ~/.superkaramba/%s.rc written.",
01727   //         m_theme.name().ascii());
01728 }
01729 
01730 void karamba::slotToggleConfigOption(QString key, bool value)
01731 {
01732   //qDebug("karamba::slotToggleConfigOption");
01733   config -> setGroup("config menu");
01734   config -> writeEntry(key, value);
01735   passMenuOptionChanged(key, value);
01736 }
01737 
01738 void karamba::addMenuConfigOption(QString key, QString name)
01739 {
01740   //qDebug("karamba::addMenuConfigOption");
01741   kpop -> setItemEnabled(THEMECONF, true);
01742 
01743   SignalBridge* action = new SignalBridge(this, key, menuAccColl);
01744   KToggleAction* confItem = new KToggleAction (name, KShortcut::null(),
01745                                                action, SLOT(receive()),
01746                                                menuAccColl, key.ascii());
01747   confItem -> setName(key.ascii());
01748 
01749   menuAccColl -> insert(confItem);
01750 
01751   connect(action, SIGNAL( enabled(QString, bool) ),
01752           this, SLOT( slotToggleConfigOption(QString, bool) ));
01753 
01754   config -> setGroup("config menu");
01755   confItem -> setChecked(config -> readBoolEntry(key));
01756 
01757   confItem -> plug(themeConfMenu);
01758 
01759   numberOfConfMenuItems++;
01760 }
01761 
01762 bool karamba::setMenuConfigOption(QString key, bool value)
01763 {
01764   //qDebug("karamba::setMenuConfigOption");
01765   KToggleAction* menuAction = ((KToggleAction*)menuAccColl -> action(key.ascii()));
01766   if (menuAction == NULL)
01767   {
01768     qWarning("Menu action %s not found.", key.ascii());
01769     return false;
01770   }
01771   else
01772   {
01773     menuAction -> setChecked(value);
01774     return true;
01775   }
01776 }
01777 
01778 bool karamba::readMenuConfigOption(QString key)
01779 {
01780   //qDebug("karamba::readMenuConfigOption");
01781   KToggleAction* menuAction = ((KToggleAction*)menuAccColl -> action(key.ascii()));
01782   if (menuAction == NULL)
01783   {
01784     qWarning("Menu action %s not found.", key.ascii());
01785     return false;
01786   }
01787   else
01788   {
01789     return menuAction -> isChecked();
01790   }
01791 }
01792 
01793 void karamba::passMenuItemClicked(int id)
01794 {
01795   //qDebug("karamba::passMenuItemClicked");
01796   //Everything below is to call the python callback function
01797   if (pythonIface && pythonIface->isExtensionLoaded())
01798   {
01799     KPopupMenu* menu = 0;
01800     for(int i = 0; i < (int)menuList->count(); i++)
01801     {
01802       KPopupMenu* tmp;
01803       if(i==0)
01804       {
01805         tmp = (KPopupMenu*) menuList->first();
01806       }
01807       else
01808       {
01809         tmp = (KPopupMenu*) menuList->next();
01810       }
01811       if(tmp != 0)
01812       {
01813         if(tmp->isItemVisible(id))
01814         {
01815           menu = tmp;
01816           break;
01817         }
01818       }
01819     }
01820     pythonIface->menuItemClicked(this, menu, id);
01821   }
01822 }
01823 
01824 void karamba::activeTaskChanged(Task* t)
01825 {
01826   //qDebug("karamba::activeTaskChanged");
01827   //Everything below is to call the python callback function
01828   if (pythonIface && pythonIface->isExtensionLoaded())
01829     pythonIface->activeTaskChanged(this, t);
01830 }
01831 
01832 void karamba::taskAdded(Task* t)
01833 {
01834   //qDebug("karamba::taskAdded");
01835   //Everything below is to call the python callback function
01836   if (pythonIface && pythonIface->isExtensionLoaded())
01837     pythonIface->taskAdded(this, t);
01838 }
01839 
01840 void karamba::taskRemoved(Task* t)
01841 {
01842   //qDebug("karamba::taskRemoved");
01843   //Everything below is to call the python callback function
01844   if (pythonIface && pythonIface->isExtensionLoaded())
01845     pythonIface->taskRemoved(this, t);
01846 }
01847 
01848 void karamba::startupAdded(Startup* t)
01849 {
01850   //qDebug("karamba::startupAdded");
01851   //Everything below is to call the python callback function
01852   if (pythonIface && pythonIface->isExtensionLoaded())
01853     pythonIface->startupAdded(this, t);
01854 }
01855 
01856 void karamba::startupRemoved(Startup* t)
01857 {
01858   //qDebug("karamba::startupRemoved");
01859   //Everything below is to call the python callback function
01860   if (pythonIface && pythonIface->isExtensionLoaded())
01861     pythonIface->startupRemoved(this, t);
01862 }
01863 
01864 void  karamba::processExited (KProcess* proc)
01865 {
01866   //qDebug("karamba::processExited");
01867   if (pythonIface && pythonIface->isExtensionLoaded())
01868     pythonIface->commandFinished(this, (int)proc->pid());
01869 }
01870 
01871 void  karamba::receivedStdout (KProcess *proc, char *buffer, int)
01872 {
01873   //qDebug("karamba::receivedStdout");
01874   //Everything below is to call the python callback function
01875   if (pythonIface && pythonIface->isExtensionLoaded())
01876     pythonIface->commandOutput(this, (int)proc->pid(), buffer);
01877 }
01878 
01879 //For KDE session management
01880 void karamba::saveProperties(KConfig* config)
01881 {
01882   //qDebug("karamba::saveProperties");
01883   config->setGroup("session");
01884   config->writeEntry("theme", m_theme.file());
01885   writeConfigData();
01886 }
01887 
01888 //For KDE session management
01889 void karamba::readProperties(KConfig* config)
01890 {
01891   //qDebug("karamba::readProperties");
01892   config->setGroup("session");
01893   QString atheme = config->readEntry("theme");
01894 }
01895 
01896 //Register types of events that can be dragged on our widget
01897 void karamba::dragEnterEvent(QDragEnterEvent* event)
01898 {
01899   //qDebug("karamba::dragEnterEvent");
01900   event->accept(QTextDrag::canDecode(event));
01901 }
01902 
01903 //Handle the drop part of a drag and drop event.
01904 void karamba::dropEvent(QDropEvent* event)
01905 {
01906   //qDebug("karamba::dropEvent");
01907   QString text;
01908 
01909   if ( QTextDrag::decode(event, text) )
01910   {
01911     //Everything below is to call the python callback function
01912     if (pythonIface && pythonIface->isExtensionLoaded())
01913     {
01914       const QPoint &p = event->pos();
01915       pythonIface->itemDropped(this, text, p.x(), p.y());
01916     }
01917   }
01918 }
01919 
01920 void karamba::toDesktop(int id, int menuid)
01921 {
01922   //qDebug("karamba::toDesktop");
01923   int i;
01924 
01925   desktop = id;
01926   for (i=0; ; i++)
01927   {
01928     int mid = toDesktopMenu->idAt(i);
01929     if (mid == -1)
01930       break;
01931 
01932     toDesktopMenu->setItemChecked(mid, false);
01933   }
01934   toDesktopMenu->setItemChecked(menuid, true);
01935 
01936   if (desktop)
01937     info->setDesktop( desktop);
01938   else
01939     info->setDesktop( NETWinInfo::OnAllDesktops );
01940 }
01941 
01942 void karamba::systrayUpdated()
01943 {
01944   //qDebug("karamba::systrayUpdated");
01945   if (pythonIface && pythonIface->isExtensionLoaded())
01946     pythonIface->systrayUpdated(this);
01947 }
01948 
01949 void karamba::toggleWidgetUpdate( bool b)
01950 {
01951   //qDebug("karamba::toggleWidgetUpdate");
01952   if (pythonIface && pythonIface->isExtensionLoaded())
01953     widgetUpdate = b;
01954 }
01955 
01956 SignalBridge::SignalBridge(QObject* parent, QString name, KActionCollection* ac)
01957   : QObject(parent, name.ascii()), collection(ac)
01958 {
01959   setName(name.ascii());
01960 }
01961 
01962 void SignalBridge::receive()
01963 {
01964   emit enabled(name(), ((KToggleAction*)collection -> action(name())) ->
01965 isChecked());
01966 }
01967 
01968 DesktopChangeSlot::DesktopChangeSlot(QObject *parent, int id)
01969     : QObject(parent, "")
01970 {
01971   desktopid = id;
01972 }
01973 
01974 void DesktopChangeSlot::receive()
01975 {
01976   karamba *k = (karamba *)parent();
01977 
01978   // XXX - check type cast
01979 
01980   k->toDesktop(desktopid, menuid);
01981 }
01982 
01983 void DesktopChangeSlot::setMenuId(int id)
01984 {
01985   menuid = id;
01986 }
01987 
01988 int DesktopChangeSlot::menuId()
01989 {
01990   return menuid;
01991 }
01992 
01993 void karamba::showMenuExtension()
01994 {
01995   kglobal = new KPopupMenu(this);
01996 
01997   trayMenuToggleId = kglobal->insertItem(SmallIconSet("superkaramba"),
01998                                          i18n("Show System Tray Icon"), this,
01999                                          SLOT(slotToggleSystemTray()),
02000                                          CTRL+Key_S);
02001 
02002   trayMenuThemeId = kglobal->insertItem(SmallIconSet("knewstuff"),
02003                                         i18n("&Manage Themes..."), this,
02004                                         SLOT(slotShowTheme()), CTRL+Key_M);
02005 
02006   trayMenuQuitId = kglobal->insertItem(SmallIconSet("exit"),
02007                                        i18n("&Quit SuperKaramba"), this,
02008                                        SLOT(slotQuit()), CTRL+Key_Q);
02009 
02010   kglobal->polish();
02011 
02012   trayMenuSeperatorId = kpop->insertSeparator();
02013   kpop->insertItem("SuperKaramba", kglobal);
02014 }
02015 
02016 void karamba::hideMenuExtension()
02017 {
02018   if(kglobal)
02019   {
02020     kpop->removeItem(trayMenuSeperatorId);
02021     kglobal->removeItem(trayMenuToggleId);
02022     kglobal->removeItem(trayMenuThemeId);
02023     kglobal->removeItem(trayMenuQuitId);
02024 
02025     delete kglobal;
02026     kglobal = 0;
02027   }
02028 }
02029 
02030 void karamba::slotToggleSystemTray()
02031 {
02032   karambaApp->globalHideSysTray(false);
02033 }
02034 
02035 void karamba::slotQuit()
02036 {
02037   karambaApp->globalQuitSuperKaramba();
02038 }
02039 
02040 void karamba::slotShowTheme()
02041 {
02042   karambaApp->globalShowThemeDialog();
02043 }
02044 
02045 void karamba::setAlwaysOnTop(bool stay)
02046 {
02047     if(stay)
02048     {
02049         onTop = true;
02050         KWin::setState( winId(), NET::KeepAbove );
02051     }
02052     else
02053     {
02054         onTop = false;
02055         KWin::setState( winId(), NET::KeepBelow );
02056     }
02057 }
02058 
02059 #include "karamba.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys