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