• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • superkaramba
 

superkaramba

  • superkaramba
  • src
karamba.cpp
1 /*
2  * Copyright (C) 2003-2004 Adam Geitgey <adam@rootnode.org>
3  * Copyright (C) 2003 Hans Karlsson <karlsson.h@home.se>
4  * Copyright (C) 2004,2005 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
5  * Copyright (c) 2005 Ryan Nickell <p0z3r@earthlink.net>
6  *
7  * This file is part of SuperKaramba.
8  *
9  * SuperKaramba is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * SuperKaramba is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with SuperKaramba; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  ****************************************************************************/
23 
24 #include "karamba_python.h"
25 #include "dcopinterface_stub.h"
26 #include "richtextlabel.h"
27 #include "karamba.h"
28 #include "karambaapp.h"
29 #include "themesdlg.h"
30 #include "lineparser.h"
31 #include "themelocale.h"
32 #include "superkarambasettings.h"
33 
34 #include <kdebug.h>
35 #include <tdemessagebox.h>
36 #include <krun.h>
37 #include <tdelocale.h>
38 #include <twin.h>
39 #include <tdeversion.h>
40 #include <kdirwatch.h>
41 
42 #include <tdeparts/componentfactory.h>
43 #include <tdeparts/part.h>
44 
45 #include <tqdir.h>
46 #include <tqwidgetlist.h>
47 
48 // Menu IDs
49 #define EDITSCRIPT 1
50 #define THEMECONF 2
51 
52 karamba::karamba(TQString fn, TQString name, bool reloading, int instance,
53  bool sub_theme):
54  TQWidget(0,"karamba", TQt::WGroupLeader | WStyle_Customize |
55  WRepaintNoErase| WStyle_NoBorder | WDestructiveClose ),
56  meterList(0), imageList(0), clickList(0), kpop(0), widgetMask(0),
57  config(0), kWinModule(0), tempUnit('C'), m_instance(instance),
58  sensorList(0), timeList(0),
59  themeConfMenu(0), toDesktopMenu(0), kglobal(0), clickPos(0, 0), accColl(0),
60  menuAccColl(0), toggleLocked(0), pythonIface(0), defaultTextField(0),
61  trayMenuSeperatorId(-1), trayMenuQuitId(-1), trayMenuToggleId(-1),
62  trayMenuThemeId(-1),
63  m_sysTimer(NULL)
64 {
65  themeStarted = false;
66  want_right_button = false;
67  want_meter_wheel_event = false;
68  prettyName = name;
69  m_sub_theme = sub_theme;
70 
71  KURL url;
72 
73  if(fn.find('/') == -1)
74  url.setFileName(fn);
75  else
76  url = fn;
77  if(!m_theme.set(url))
78  {
79  setFixedSize(0, 0);
80  TQTimer::singleShot(100, this, TQ_SLOT(killWidget()));
81  return;
82  }
83  // Add self to list of open themes
84  // This also updates instance number
85  karambaApp->addKaramba(this, reloading);
86 
87  if(prettyName.isEmpty())
88  prettyName = TQString("%1 - %2").arg(m_theme.name()).arg(m_instance);
89 
90  kdDebug() << "Starting theme: " << m_theme.name()
91  << " pretty name: " << prettyName << endl;
92  TQString qName = "karamba - " + prettyName;
93  setName(qName.ascii());
94 
95  KDirWatch *dirWatch = KDirWatch::self();
96  connect(dirWatch, TQ_SIGNAL( dirty( const TQString & ) ),
97  TQ_SLOT( slotFileChanged( const TQString & ) ) );
98 
99  if(!dirWatch->contains(m_theme.file()))
100  dirWatch->addFile(m_theme.file());
101 
102  if(!m_theme.isZipTheme() && m_theme.pythonModuleExists())
103  {
104  TQString pythonFile = m_theme.path() + "/" + m_theme.pythonModule() + ".py";
105  if(!dirWatch->contains(pythonFile))
106  dirWatch->addFile(pythonFile);
107  }
108 
109  widgetUpdate = true;
110 
111  // Creates TDEConfig Object
112  TQString instanceString;
113  if(m_instance > 1)
114  instanceString = TQString("-%1").arg(m_instance);
115  TQString cfg = TQDir::home().absPath() + "/.superkaramba/"
116  + m_theme.id() + instanceString + ".rc";
117  kdDebug() << cfg << endl;
118  TQFile themeConfigFile(cfg);
119  // Tests if config file Exists
120  if (!TQFileInfo(themeConfigFile).exists())
121  {
122  // Create config file
123  themeConfigFile.open(IO_ReadWrite);
124  themeConfigFile.close();
125  }
126 
127  config = new TDEConfig(cfg, false, false);
128  config -> sync();
129  config -> setGroup("internal");
130 
131  m_reloading = reloading;
132  if(m_theme.pythonModuleExists())
133  {
134  kdDebug() << "Loading python module: " << m_theme.pythonModule() << endl;
135  TQTimer::singleShot(0, this, TQ_SLOT(initPythonInterface()));
136  }
137 
138  widgetMask = 0;
139  info = new NETWinInfo( tqt_xdisplay(), winId(), tqt_xrootwin(), NET::WMState );
140 
141  // could be replaced with TaskManager
142  kWinModule = new KWinModule();
143  desktop = 0;
144 
145  connect( kWinModule,TQ_SIGNAL(currentDesktopChanged(int)), this,
146  TQ_SLOT(currentDesktopChanged(int)) );
147  connect( tdeApp, TQ_SIGNAL(backgroundChanged(int)), this,
148  TQ_SLOT(currentWallpaperChanged(int)));
149 
150  // Setup of the Task Manager Callbacks
151  connect(&taskManager, TQ_SIGNAL(activeTaskChanged(Task*)), this,
152  TQ_SLOT(activeTaskChanged(Task*)) );
153  connect(&taskManager, TQ_SIGNAL(taskAdded(Task*)), this,
154  TQ_SLOT(taskAdded(Task*)) );
155  connect(&taskManager, TQ_SIGNAL(taskRemoved(Task*)), this,
156  TQ_SLOT(taskRemoved(Task*)) );
157  connect(&taskManager, TQ_SIGNAL(startupAdded(Startup*)), this,
158  TQ_SLOT(startupAdded(Startup*)) );
159  connect(&taskManager, TQ_SIGNAL(startupRemoved(Startup*)), this,
160  TQ_SLOT(startupRemoved(Startup*)) );
161 
162  themeConfMenu = new TDEPopupMenu( this);
163  themeConfMenu -> setCheckable(true);
164 
165  /* XXX - need to be able to delete all these DesktopChangeSlot objects */
166  DesktopChangeSlot *dslot;
167 
168  int mid;
169 
170  toDesktopMenu = new TDEPopupMenu (this);
171  toDesktopMenu -> setCheckable(true);
172  mid = toDesktopMenu -> insertItem (i18n("&All Desktops"),
173  dslot = new DesktopChangeSlot(this,0),
174  TQ_SLOT(receive()));
175  dslot->setMenuId(mid);
176 
177  toDesktopMenu -> insertSeparator();
178  for (int ndesktop=1; ndesktop <= kWinModule->numberOfDesktops(); ndesktop++)
179  {
180  TQString name = i18n("Desktop &");
181  name += ('0' + ndesktop);
182 
183  mid = toDesktopMenu -> insertItem (name,
184  dslot = new DesktopChangeSlot(this, ndesktop), TQ_SLOT(receive()));
185  dslot->setMenuId(mid);
186  }
187 
188 
189  kpop = new TDEPopupMenu( this );
190  kpop -> setCheckable(true);
191 
192  accColl = new TDEActionCollection( this );
193  menuAccColl = new TDEActionCollection( this );
194 
195  kpop->insertItem( SmallIconSet("reload"),i18n("Update"), this,
196  TQ_SLOT(updateSensors()), Key_F5 );
197  toggleLocked = new TDEToggleAction ( i18n("Toggle &Locked Position"),
198  SmallIconSet("locked"),
199  CTRL+Key_L, this,
200  TQ_SLOT( slotToggleLocked() ),
201  accColl, "Locked position" );
202  accColl->insert(toggleLocked);
203  toggleLocked -> setChecked(true);
204 
205  toggleLocked->plug(kpop);
206 
207  toggleFastTransforms = new TDEToggleAction(i18n("Use &Fast Image Scaling"),
208  CTRL+Key_F, this,
209  TQ_SLOT( slotToggleFastTransforms() ),
210  accColl, "Fast transformations");
211 
212  accColl->insert(toggleFastTransforms);
213  toggleFastTransforms -> setChecked(true);
214 
215  toggleFastTransforms -> plug(kpop);
216 
217  kpop->insertSeparator();
218 
219  kpop->insertItem(i18n("Configure &Theme"), themeConfMenu, THEMECONF);
220  kpop->setItemEnabled(THEMECONF, false);
221  kpop->insertItem(i18n("To Des&ktop"), toDesktopMenu);
222 
223  kpop->insertItem( SmallIconSet("reload3"),i18n("&Reload Theme"),this,
224  TQ_SLOT(reloadConfig()), CTRL+Key_R );
225  kpop->insertItem( SmallIconSet("window-close"),i18n("&Close This Theme"), this,
226  TQ_SLOT(killWidget()), CTRL+Key_C );
227 
228  if(!SuperKarambaSettings::showSysTray())
229  showMenuExtension();
230 
231  kpop->polish();
232 
233  numberOfConfMenuItems = 0;
234 
235  systray = 0;
236  foundKaramba = false;
237  onTop = false;
238  managed = false;
239  fixedPosition = false;
240  defaultTextField = new TextField();
241 
242  meterList = new TQObjectList();
243  meterList->setAutoDelete( true );
244  sensorList = new TQObjectList();
245  sensorList->setAutoDelete( true );
246  clickList = new TQObjectList();
247  timeList = new TQObjectList();
248  imageList = new TQObjectList();
249  menuList = new TQObjectList();
250  menuList->setAutoDelete( true );
251 
252  client = tdeApp->dcopClient();
253  if (!client->isAttached())
254  client->attach();
255  appId = client->registerAs(tqApp->name());
256 
257 
258  setBackgroundMode( NoBackground);
259  if( !(onTop || managed))
260  KWin::lowerWindow( winId() );
261 
262  if( !parseConfig() )
263  {
264  setFixedSize(0,0);
265  TQTimer::singleShot( 100, this, TQ_SLOT(killWidget()) );
266  tqWarning("Could not read config file.");
267  }
268  else
269  {
270  kroot = new KarambaRootPixmap((TQWidget*)this);
271  kroot->start();
272  }
273 
274  // Karamba specific Config Entries
275  bool locked = toggleLocked->isChecked();
276  locked = config->readBoolEntry("lockedPosition", locked);
277  toggleLocked->setChecked(locked);
278  slotToggleLocked();
279 
280  if (!config -> readBoolEntry("fastTransforms", true))
281  {
282  toggleFastTransforms -> setChecked(false);
283  slotToggleFastTransforms();
284  }
285 
286  desktop = config -> readNumEntry("desktop", desktop);
287  if (desktop > kWinModule->numberOfDesktops())
288  {
289  desktop = 0;
290  }
291 
292  if (desktop)
293  {
294  info->setDesktop( desktop );
295  }
296  else
297  info->setDesktop( NETWinInfo::OnAllDesktops);
298 
299  // Read Themespecific Config Entries
300  config -> setGroup("theme");
301  if (config -> hasKey("widgetPosX") && config -> hasKey("widgetPosY"))
302  {
303  int xpos = config -> readNumEntry("widgetPosX");
304  int ypos = config -> readNumEntry("widgetPosY");
305 
306  if (xpos < 0)
307  xpos = 0;
308  if (ypos < 0)
309  ypos = 0;
310  move(xpos, ypos);
311  }
312 
313  haveUpdated = false;
314  this->setMouseTracking(true);
315 
316 
317  setFocusPolicy(TQWidget::StrongFocus);
318 }
319 
320 karamba::~karamba()
321 {
322  //tqDebug("karamba::~karamba");
323  //Remove self from list of open themes
324  karambaApp->deleteKaramba(this, m_reloading);
325 
326  widgetClosed();
327  if(m_theme.isValid())
328  writeConfigData();
329 
330  delete config;
331 
332  if(meterList != 0)
333  {
334  meterList->clear();
335  delete meterList;
336  }
337 
338  if( sensorList != 0 )
339  {
340  sensorList->clear();
341  delete sensorList;
342  }
343 
344  if( imageList != 0 )
345  {
346  imageList->clear();
347  delete imageList;
348  }
349 
350  if( clickList != 0 )
351  {
352  clickList->clear();
353  delete clickList;
354  }
355 
356  if( timeList != 0 )
357  {
358  timeList->clear();
359  delete timeList;
360  }
361 
362  delete toggleLocked;
363  delete accColl;
364  delete menuAccColl;
365  delete themeConfMenu;
366  delete kpop;
367  delete widgetMask;
368  delete kWinModule;
369  delete defaultTextField;
370  if (pythonIface != NULL)
371  delete pythonIface;
372 }
373 
374 bool karamba::parseConfig()
375 {
376  //tqDebug("karamba::parseConfig");
377  bool passive = true;
378 
379  if(m_theme.open())
380  {
381  TQValueStack<TQPoint> offsetStack;
382  LineParser lineParser;
383  int x=0;
384  int y=0;
385  int w=0;
386  int h=0;
387 
388  offsetStack.push(TQPoint(0,0));
389 
390  while(m_theme.nextLine(lineParser))
391  {
392  x = lineParser.getInt("X") + offsetStack.top().x();
393  y = lineParser.getInt("Y") + offsetStack.top().y();
394  w = lineParser.getInt("W");
395  h = lineParser.getInt("H");
396 
397  if(lineParser.meter() == "KARAMBA" && !foundKaramba )
398  {
399  //tqDebug("karamba found");
400  toggleLocked->setChecked(lineParser.getBoolean("LOCKED"));
401  slotToggleLocked();
402 
403  x = ( x < 0 ) ? 0:x;
404  y = ( y < 0 ) ? 0:y;
405 
406  if( w == 0 || h == 0)
407  {
408  w = 300;
409  h = 300;
410  }
411  setFixedSize(w,h);
412 
413  if(lineParser.getBoolean("RIGHT"))
414  {
415  TQDesktopWidget *d = TQApplication::desktop();
416  x = d->width() - w;
417  }
418  else if(lineParser.getBoolean("LEFT"))
419  {
420  x = 0;
421  }
422 
423  if(lineParser.getBoolean("BOTTOM"))
424  {
425  TQDesktopWidget *d = TQApplication::desktop();
426  y = d->height() - h;
427  }
428  else if(lineParser.getBoolean("TOP"))
429  {
430  y = 0;
431  }
432 
433  move(x,y);
434  //pm = TQPixmap(size());
435 
436  if(lineParser.getBoolean("ONTOP"))
437  {
438  onTop = true;
439  KWin::setState( winId(), NET::StaysOnTop );
440  }
441 
442  if(lineParser.getBoolean("MANAGED"))
443  {
444  managed = true;
445  reparent(0, TQt::WType_Dialog | WStyle_Customize | WStyle_NormalBorder
446  | WRepaintNoErase | WDestructiveClose, pos());
447  }
448  else
449  {
450  info->setState( NETWinInfo::SkipTaskbar
451  | NETWinInfo::SkipPager,NETWinInfo::SkipTaskbar
452  | NETWinInfo::SkipPager );
453  if (onTop)
454  {
455  KWin::setState( winId(), NET::StaysOnTop );
456 
457  }
458  }
459 
460  if (lineParser.getBoolean("ONALLDESKTOPS"))
461  {
462  desktop = 200; // ugly
463  }
464 
465 
466  bool dfound=false;
467  //int desktop = lineParser.getInt("DESKTOP", line, dfound);
468  if (dfound)
469  {
470  info->setDesktop( dfound );
471  }
472  if(lineParser.getBoolean("TOPBAR"))
473  {
474  move(x,0);
475  KWin::setStrut( winId(), 0, 0, h, 0 );
476  toggleLocked->setChecked( true );
477  slotToggleLocked();
478  toggleLocked->setEnabled(false);
479  }
480 
481  if(lineParser.getBoolean("BOTTOMBAR"))
482  {
483  int dh = TQApplication::desktop()->height();
484  move( x, dh - h );
485  KWin::setStrut( winId(), 0, 0, 0, h );
486  toggleLocked->setChecked( true );
487  slotToggleLocked();
488  toggleLocked->setEnabled(false);
489  }
490 
491  if(lineParser.getBoolean("RIGHTBAR"))
492  {
493  int dw = TQApplication::desktop()->width();
494  move( dw - w, y );
495  KWin::setStrut( winId(), 0, w, 0, 0 );
496  toggleLocked->setChecked( true );
497  slotToggleLocked();
498  toggleLocked->setEnabled(false);
499  }
500 
501  if(lineParser.getBoolean("LEFTBAR"))
502  {
503  move( 0, y );
504  KWin::setStrut( winId(), w, 0, 0, 0 );
505  toggleLocked->setChecked( true );
506  slotToggleLocked();
507  toggleLocked->setEnabled(false);
508  }
509 
510  TQString path = lineParser.getString("MASK");
511 
512  TQFileInfo info(path);
513  TQString absPath;
514  TQBitmap bmMask;
515  TQByteArray ba;
516  if( info.isRelative() )
517  {
518  absPath.setAscii(m_theme.path().ascii());
519  absPath.append(path.ascii());
520  ba = m_theme.readThemeFile(path);
521  }
522  else
523  {
524  absPath.setAscii(path.ascii());
525  ba = m_theme.readThemeFile(info.fileName());
526  }
527  if(m_theme.isZipTheme())
528  {
529  bmMask.loadFromData(ba);
530  }
531  else
532  {
533  bmMask.load(absPath);
534  }
535  setMask(bmMask);
536 
537  m_interval = lineParser.getInt("INTERVAL");
538  m_interval = (m_interval == 0) ? 1000 : m_interval;
539 
540  TQString temp = lineParser.getString("TEMPUNIT", "C").upper();
541  tempUnit = temp.ascii()[0];
542  foundKaramba = true;
543  }
544 
545  if(lineParser.meter() == "THEME")
546  {
547  TQString path = lineParser.getString("PATH");
548  TQFileInfo info(path);
549  if( info.isRelative())
550  path = m_theme.path() +"/" + path;
551  (new karamba( path, TQString() ))->show();
552  }
553 
554  if(lineParser.meter() == "<GROUP>")
555  {
556  int offsetX = offsetStack.top().x();
557  int offsetY = offsetStack.top().y();
558  offsetStack.push( TQPoint( offsetX + lineParser.getInt("X"),
559  offsetY + lineParser.getInt("Y")));
560  }
561 
562  if(lineParser.meter() == "</GROUP>")
563  {
564  offsetStack.pop();
565  }
566 
567  if(lineParser.meter() == "CLICKAREA")
568  {
569  if( !hasMouseTracking() )
570  setMouseTracking(true);
571  ClickArea *tmp = new ClickArea(this, x, y, w, h );
572  tmp->setOnClick(lineParser.getString("ONCLICK"));
573 
574  setSensor(lineParser, (Meter*)tmp);
575  clickList->append( tmp );
576  if( lineParser.getBoolean("PREVIEW"))
577  meterList->append( tmp );
578  }
579 
580  // program sensor without a meter
581  if(lineParser.meter() == "SENSOR=PROGRAM")
582  {
583  setSensor(lineParser, 0 );
584  }
585 
586  if(lineParser.meter() == "IMAGE")
587  {
588  TQString file = lineParser.getString("PATH");
589  TQString file_roll = lineParser.getString("PATHROLL");
590  int xon = lineParser.getInt("XROLL");
591  int yon = lineParser.getInt("YROLL");
592  TQString tiptext = lineParser.getString("TOOLTIP");
593  TQString name = lineParser.getString("NAME");
594  bool bg = lineParser.getBoolean("BACKGROUND");
595  xon = ( xon <= 0 ) ? x:xon;
596  yon = ( yon <= 0 ) ? y:yon;
597 
598  ImageLabel *tmp = new ImageLabel(this, x, y, 0, 0);
599  tmp->setValue(file);
600  if(!file_roll.isEmpty())
601  tmp->parseImages(file, file_roll, x,y, xon, yon);
602  tmp->setBackground(bg);
603  if (!name.isEmpty())
604  tmp->setName(name.ascii());
605  if (!tiptext.isEmpty())
606  tmp->setTooltip(tiptext);
607 
608  connect(tmp, TQ_SIGNAL(pixmapLoaded()), this, TQ_SLOT(externalStep()));
609  setSensor(lineParser, (Meter*) tmp );
610  meterList->append (tmp );
611  imageList->append (tmp );
612  }
613 
614  if(lineParser.meter() == "DEFAULTFONT" )
615  {
616  delete defaultTextField;
617  defaultTextField = new TextField( );
618 
619  defaultTextField->setColor(lineParser.getColor("COLOR",
620  TQColor("black")));
621  defaultTextField->setBGColor(lineParser.getColor("BGCOLOR",
622  TQColor("white")));
623  defaultTextField->setFont(lineParser.getString("FONT", "Helvetica"));
624  defaultTextField->setFontSize(lineParser.getInt("FONTSIZE", 12));
625  defaultTextField->setAlignment(lineParser.getString("ALIGN",
626  "LEFT"));
627  defaultTextField->setFixedPitch(lineParser.getBoolean("FIXEDPITCH",
628  false));
629  defaultTextField->setShadow(lineParser.getInt("SHADOW", 0));
630  }
631 
632  if(lineParser.meter() == "TEXT" ||
633  lineParser.meter() == "CLICKMAP" ||
634  lineParser.meter() == "RICHTEXT" ||
635  lineParser.meter() == "INPUT")
636  {
637  TextField defTxt;
638 
639  if(defaultTextField)
640  defTxt = *defaultTextField;
641 
642  TextField* tmpText = new TextField();
643 
644  tmpText->setColor(lineParser.getColor("COLOR", defTxt.getColor()));
645  tmpText->setBGColor(lineParser.getColor("BGCOLOR",
646  defTxt.getBGColor()));
647  tmpText->setFont(lineParser.getString("FONT", defTxt.getFont()));
648  tmpText->setFontSize(lineParser.getInt("FONTSIZE",
649  defTxt.getFontSize()));
650  tmpText->setAlignment(lineParser.getString("ALIGN",
651  defTxt.getAlignmentAsString()));
652  tmpText->setFixedPitch(lineParser.getInt("FIXEDPITCH",
653  defTxt.getFixedPitch()));
654 
655  tmpText->setShadow(lineParser.getInt("SHADOW", defTxt.getShadow()));
656 
657  // ////////////////////////////////////////////////////
658  // Now handle the specifics
659  if(lineParser.meter() == "TEXT")
660  {
661 
662  TextLabel *tmp = new TextLabel(this, x, y, w, h );
663  tmp->setTextProps(tmpText);
664  tmp->setValue(
665  m_theme.locale()->translate(lineParser.getString("VALUE")));
666 
667  TQString name = lineParser.getString("NAME");
668  if (!name.isEmpty())
669  tmp->setName(name.ascii());
670 
671  setSensor(lineParser, (Meter*)tmp);
672  meterList->append ( tmp );
673  }
674 
675  if(lineParser.meter() == "CLICKMAP")
676  {
677  if( !hasMouseTracking() )
678  setMouseTracking(true);
679  ClickMap *tmp = new ClickMap(this, x, y, w, h);
680  tmp->setTextProps( tmpText );
681 
682  setSensor(lineParser, (Meter*)tmp);
683  // set all params
684  clickList -> append(tmp);
685  meterList->append( tmp );
686 
687  }
688 
689  if(lineParser.meter() == "RICHTEXT")
690  {
691  RichTextLabel *tmp = new RichTextLabel(this, x, y, w, h);
692 
693  bool dUl = lineParser.getBoolean("UNDERLINE");
694 
695  tmp->setText(
696  m_theme.locale()->translate(lineParser.getString("VALUE").ascii()), dUl);
697  tmp->setTextProps( tmpText );
698  tmp->setWidth(w);
699  tmp->setHeight(h);
700 
701  TQString name = lineParser.getString("NAME");
702  if (!name.isEmpty())
703  tmp->setName(name.ascii());
704 
705  setSensor(lineParser, (Meter*)tmp);
706  clickList -> append(tmp);
707  meterList->append ( tmp );
708  }
709 
710  if(lineParser.meter() == "INPUT")
711  {
712  Input *tmp = new Input(this, x, y, w, h);
713 
714  TQString name = lineParser.getString("NAME");
715  if (!name.isEmpty())
716  tmp->setName(name.ascii());
717 
718  tmp->setTextProps(tmpText);
719  tmp->setValue(
720  m_theme.locale()->translate(lineParser.getString("VALUE").ascii()));
721 
722  meterList->append(tmp);
723  passive = false;
724  }
725  }
726 
727  if(lineParser.meter() == "BAR")
728  {
729  Bar *tmp = new Bar(this, x, y, w, h );
730  tmp->setImage(lineParser.getString("PATH").ascii());
731  tmp->setVertical(lineParser.getBoolean("VERTICAL"));
732  tmp->setMax(lineParser.getInt("MAX", 100));
733  tmp->setMin(lineParser.getInt("MIN", 0));
734  tmp->setValue(lineParser.getInt("VALUE"));
735  TQString name = lineParser.getString("NAME");
736  if (!name.isEmpty())
737  tmp->setName(name.ascii());
738  setSensor(lineParser, (Meter*)tmp );
739  meterList->append ( tmp );
740  }
741 
742  if(lineParser.meter() == "GRAPH")
743  {
744  int points = lineParser.getInt("POINTS");
745 
746  Graph *tmp = new Graph(this, x, y, w, h, points);
747  tmp->setMax(lineParser.getInt("MAX", 100));
748  tmp->setMin(lineParser.getInt("MIN", 0));
749  TQString name = lineParser.getString("NAME");
750  if (!name.isEmpty())
751  tmp->setName(name.ascii());
752 
753  tmp->setColor(lineParser.getColor("COLOR"));
754 
755  setSensor(lineParser, (Graph*)tmp);
756  meterList->append ( tmp );
757  }
758  }
759 
760  if(passive && !managed)
761  {
762  // Matthew Kay: set window type to "dock"
763  // (plays better with taskbar themes this way)
764  KWin::setType(winId(), NET::Dock);
765  #if defined(TDE_MAKE_VERSION)
766  #if TDE_VERSION >= TDE_MAKE_VERSION(3,1,9)
767  //KDE 3.2 addition for the always on top issues
768  KWin::setState(winId(), NET::KeepBelow);
769  #endif
770  #endif
771  }
772 
773  m_theme.close();
774  }
775  //tqDebug("parseConfig ok: %d", foundKaramba);
776  if( !foundKaramba )
777  {
778  // interval = initKaramba( "", 0, 0, 0, 0 );
779  // this->close(true);
780  //delete this;
781  return false;
782  }
783  else
784  {
785  return true;
786  }
787 }
788 
789 void karamba::start()
790 {
791  m_sysTimer = new TQTimer(this);
792 
793  connect(m_sysTimer, TQ_SIGNAL(timeout()), TQ_SLOT(step()));
794 
795  m_sysTimer->start(m_interval);
796 
797  //Start the widget running
798  TQTimer::singleShot( 0, this, TQ_SLOT(step()) );
799 
800  if( !(onTop || managed) )
801  lowerTimer.start();
802 }
803 
804 void karamba::makeActive()
805 {
806  KWin::setType(winId(), NET::Normal);
807 
808  #if defined(TDE_MAKE_VERSION)
809  #if TDE_VERSION >= TDE_MAKE_VERSION(3,1,9)
810  //KDE 3.2 addition for the always on top issues
811  KWin::setState(winId(), NET::Modal);
812  #endif
813  #endif
814 }
815 
816 void karamba::makePassive()
817 {
818  if(managed)
819  return;
820 
821  TQObject *meter;
822  for (meter = meterList->first(); meter; meter = meterList->next())
823  {
824  if((meter)->isA("Input"))
825  return;
826  }
827 
828  // Matthew Kay: set window type to "dock" (plays better with taskbar themes
829  // this way)
830  KWin::setType(winId(), NET::Dock);
831  #if defined(TDE_MAKE_VERSION)
832  #if TDE_VERSION >= TDE_MAKE_VERSION(3,1,9)
833  //KDE 3.2 addition for the always on top issues
834  KWin::setState(winId(), NET::KeepBelow);
835  #endif
836  #endif
837 }
838 
839 void karamba::popupNotify(int)
840 {
841  //tqDebug("karamba::popupNotify");
842 }
843 
844 void karamba::reloadConfig()
845 {
846  //tqDebug("karamba::reloadConfig: %s", m_theme.file().ascii());
847  writeConfigData();
848  if(m_theme.exists())
849  {
850  TQFileInfo fileInfo( m_theme.file() );
851  (new karamba(m_theme.file(), fileInfo.baseName(), true, m_instance))->show();
852  }
853  closeTheme(true);
854 }
855 
856 void karamba::closeTheme(bool reloading)
857 {
858  m_reloading = reloading;
859  close();
860 }
861 
862 void karamba::killWidget()
863 {
864  closeTheme();
865 }
866 
867 void karamba::initPythonInterface()
868 {
869  pythonIface = new KarambaPython(m_theme, m_reloading);
870 }
871 
872 void karamba::editConfig()
873 {
874  //tqDebug("karamba::editConfig");
875  TQFileInfo fileInfo( m_theme.file() );
876  TQString path;
877 
878  if( fileInfo.isRelative() )
879  {
880  path = m_theme.path() + "/" + m_theme.file();
881  }
882  else
883  {
884  path = m_theme.file();
885  }
886 
887  KRun::runURL( KURL( path ), "text/plain" );
888 }
889 
890 void karamba::editScript()
891 {
892  //tqDebug("karamba::editScript");
893  TQFileInfo fileInfo( m_theme.file() );
894  TQString path;
895 
896  if( fileInfo.isRelative() )
897  {
898  path = m_theme.path() + "/" + m_theme.name() + ".py";
899  }
900  else
901  {
902  path = TQFileInfo(m_theme.file()).dirPath() + "/" + m_theme.name() + ".py";
903  }
904  KRun::runURL( KURL( path ), "text/plain" );
905 }
906 
907 TQString karamba::findSensorFromMap(Sensor* sensor)
908 {
909  //tqDebug("karamba::findSensorFromMap");
910  TQMap<TQString,Sensor*>::ConstIterator it;
911  TQMap<TQString,Sensor*>::ConstIterator end( sensorMap.end() );
912  for ( it = sensorMap.begin(); it != end; ++it )
913  {
914  if (it.data() == sensor)
915  return it.key();
916  }
917  return "";
918 }
919 
920 Sensor* karamba::findSensorFromList(Meter* meter)
921 {
922  //tqDebug("karamba::findSensorFromList");
923  TQObjectListIt it( *sensorList ); // iterate over meters
924 
925  while ( it != 0 )
926  {
927  if (((Sensor*) *it)->hasMeter(meter))
928  return ((Sensor*)*it);
929  ++it;
930  }
931  return NULL;
932 }
933 
934 TQString karamba::getSensor(Meter* meter)
935 {
936  //tqDebug("karamba::getSensor");
937  TQString s;
938  Sensor* sensor = findSensorFromList(meter);
939  if (sensor)
940  s = findSensorFromMap(sensor);
941  return s;
942 }
943 
944 void karamba::deleteMeterFromSensors(Meter* meter)
945 {
946  //tqDebug("karamba::deleteMeterFromSensors");
947  Sensor* sensor = findSensorFromList(meter);
948 
949  if (sensor)
950  {
951  sensor->deleteMeter(meter);
952  if (sensor->isEmpty())
953  {
954  TQString s = findSensorFromMap(sensor);
955  sensorMap.erase(s);
956  sensorList->removeRef(sensor);
957  }
958  }
959 }
960 
961 void karamba::setSensor(const LineParser& lineParser, Meter* meter)
962 {
963  //tqDebug("karamba::setSensor");
964  Sensor* sensor = 0;
965 
966  deleteMeterFromSensors(meter);
967 
968  TQString sens = lineParser.getString("SENSOR").upper();
969 
970  if( sens == "CPU" )
971  {
972  TQString cpuNbr = lineParser.getString("CPU");
973  sensor = sensorMap["CPU"+cpuNbr];
974  if (sensor == 0)
975  {
976  int interval = lineParser.getInt("INTERVAL");
977  interval = (interval == 0)?1000:interval;
978  sensor = ( sensorMap["CPU"+cpuNbr] = new CPUSensor( cpuNbr, interval ) );
979  sensorList->append( sensor );
980  }
981  SensorParams *sp = new SensorParams(meter);
982  sp->addParam("FORMAT",
983  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
984  sp->addParam("DECIMALS",lineParser.getString("DECIMALS"));
985 
986  sensor->addMeter(sp);
987  sensor->setMaxValue(sp);
988 
989  }
990 
991  if (sens == "GPU")
992  {
993  TQString gpuId = lineParser.getString("GPU");
994  TQString gpuDriver = lineParser.getString("DRIVER");
995  TQString sensorId = TQString("GPU_%1_%2").arg(gpuDriver, gpuId);
996  sensor = sensorMap[sensorId];
997  if (sensor == 0)
998  {
999  int interval = lineParser.getInt("INTERVAL");
1000  interval = (interval == 0) ? 1000 : interval;
1001  sensor = (sensorMap[sensorId] = new GPUSensor(gpuDriver, gpuId, interval));
1002  sensorList->append(sensor);
1003  }
1004 
1005  SensorParams *sp = new SensorParams(meter);
1006  sp->addParam("FORMAT", m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
1007  sensor->addMeter(sp);
1008  sensor->setMaxValue(sp);
1009  }
1010 
1011  if( sens == "MEMORY" )
1012  {
1013  sensor = sensorMap["MEMORY"];
1014  if (sensor == 0)
1015  {
1016  int interval = lineParser.getInt("INTERVAL");
1017  interval = (interval == 0)?3000:interval;
1018  sensor = ( sensorMap["MEMORY"] = new MemSensor( interval ) );
1019  sensorList->append( sensor );
1020  }
1021  SensorParams *sp = new SensorParams(meter);
1022  sp->addParam("FORMAT",
1023  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
1024 
1025  sensor->addMeter(sp);
1026  sensor->setMaxValue(sp);
1027  }
1028 
1029 
1030  if( sens == "DISK" )
1031  {
1032  sensor = sensorMap["DISK"];
1033  if (sensor == 0)
1034  {
1035  int interval = lineParser.getInt("INTERVAL");
1036  interval = (interval == 0)?5000:interval;
1037  sensor = ( sensorMap["DISK"] = new DiskSensor( interval ) );
1038  connect( sensor, TQ_SIGNAL(initComplete()), this, TQ_SLOT(externalStep()) );
1039  sensorList->append( sensor );
1040  }
1041  // meter->setMax( ((DiskSensor*)sensor)->getTotalSpace(mntPt)/1024 );
1042  SensorParams *sp = new SensorParams(meter);
1043  TQString mntPt = lineParser.getString("MOUNTPOINT");
1044  if( mntPt.isEmpty() )
1045  {
1046  mntPt = "/";
1047  }
1048  // remove any trailing '/' from mount points in the .theme config, our
1049  // mntMap doesn't like trailing '/'s for matching in DiskSensor
1050  if( mntPt.length() > 1 && mntPt.endsWith("/") )
1051  {
1052  mntPt.remove( mntPt.length()-1, 1 );
1053  }
1054  sp->addParam("MOUNTPOINT",mntPt);
1055  sp->addParam("FORMAT",
1056  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
1057  sensor->addMeter(sp);
1058  sensor->setMaxValue(sp);
1059  }
1060 
1061  if( sens == "NETWORK")
1062  {
1063  int interval = lineParser.getInt("INTERVAL");
1064  interval = (interval == 0)?2000:interval;
1065  TQString device = lineParser.getString("DEVICE");
1066  sensor = sensorMap["NETWORK"+device];
1067  if (sensor == 0)
1068  {
1069  sensor = ( sensorMap["NETWORK"+device] =
1070  new NetworkSensor(device, interval));
1071  sensorList->append( sensor );
1072  }
1073  SensorParams *sp = new SensorParams(meter);
1074  sp->addParam("FORMAT",
1075  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
1076  sp->addParam("DECIMALS", lineParser.getString("DECIMALS"));
1077  sensor->addMeter(sp);
1078  }
1079 
1080  if( sens == "UPTIME" )
1081  {
1082  sensor = sensorMap["UPTIME"];
1083  if (sensor == 0)
1084  {
1085  int interval = lineParser.getInt("INTERVAL");
1086  interval = (interval == 0)?60000:interval;
1087  sensor = ( sensorMap["UPTIME"] = new UptimeSensor( interval ));
1088  sensorList->append( sensor );
1089 
1090  }
1091  SensorParams *sp = new SensorParams(meter);
1092  sp->addParam("FORMAT",
1093  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
1094  sensor->addMeter(sp);
1095  }
1096 
1097  if( sens == "SENSOR" )
1098  {
1099  sensor = sensorMap["SENSOR"];
1100  if (sensor == 0)
1101  {
1102  int interval = lineParser.getInt("INTERVAL");
1103  interval = (interval == 0)?30000:interval;
1104  sensor = (sensorMap["SENSOR"] = new SensorSensor(interval, tempUnit));
1105  sensorList->append( sensor );
1106  }
1107  SensorParams *sp = new SensorParams(meter);
1108  sp->addParam("FORMAT",
1109  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
1110  sp->addParam("TYPE", lineParser.getString("TYPE"));
1111  sensor->addMeter(sp);
1112  }
1113 
1114 
1115  if( sens == "TEXTFILE" )
1116  {
1117  TQString path = lineParser.getString("PATH");
1118  bool rdf = lineParser.getBoolean("RDF");
1119  sensor = sensorMap["TEXTFILE"+path];
1120  if (sensor == 0)
1121  {
1122  int interval = lineParser.getInt("INTERVAL");
1123  interval = ( interval == 0 )?60000:interval;
1124  TQString encoding = lineParser.getString("ENCODING");
1125 
1126  sensor = ( sensorMap["TEXTFILE"+path] =
1127  new TextFileSensor( path, rdf, interval, encoding ) );
1128  sensorList->append( sensor );
1129  }
1130  SensorParams *sp = new SensorParams(meter);
1131  sp->addParam("LINE",TQString::number(lineParser.getInt("LINE")));
1132  sensor->addMeter(sp);
1133  }
1134 
1135 
1136  if( sens == "TIME")
1137  {
1138  sensor = sensorMap["DATE"];
1139  if (sensor == 0)
1140  {
1141  int interval = lineParser.getInt("INTERVAL");
1142  interval = (interval == 0)?60000:interval;
1143  sensor = ( sensorMap["DATE"] = new DateSensor( interval ) );
1144  sensorList->append( sensor );
1145  timeList->append( sensor );
1146  }
1147  SensorParams *sp = new SensorParams(meter);
1148  sp->addParam("FORMAT",
1149  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
1150  sp->addParam("CALWIDTH",lineParser.getString("CALWIDTH"));
1151  sp->addParam("CALHEIGHT",lineParser.getString("CALHEIGHT"));
1152  sensor->addMeter(sp);
1153  }
1154 
1155 #ifdef HAVE_XMMS
1156 
1157  if( sens == "XMMS" )
1158  {
1159  sensor = sensorMap["XMMS"];
1160  if (sensor == 0)
1161  {
1162  int interval = lineParser.getInt("INTERVAL");
1163  interval = (interval == 0)?1000:interval;
1164  TQString encoding = lineParser.getString("ENCODING");
1165 
1166  sensor = ( sensorMap["XMMS"] = new XMMSSensor( interval, encoding ) );
1167  sensorList->append( sensor );
1168  }
1169  SensorParams *sp = new SensorParams(meter);
1170  sp->addParam("FORMAT",
1171  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
1172  sensor->addMeter(sp);
1173  sensor->setMaxValue(sp);
1174  }
1175 #endif // HAVE_XMMS
1176 
1177 
1178  if( sens == "NOATUN" )
1179  {
1180  sensor = sensorMap["NOATUN"];
1181  if (sensor == 0)
1182  {
1183  int interval = lineParser.getInt("INTERVAL");
1184  interval = (interval == 0)?1000:interval;
1185  sensor = ( sensorMap["NOATUN"] = new NoatunSensor( interval, client ) );
1186  sensorList->append( sensor );
1187  }
1188  SensorParams *sp = new SensorParams(meter);
1189  sp->addParam("FORMAT",
1190  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
1191  sensor->addMeter(sp);
1192  sensor->setMaxValue(sp);
1193  }
1194 
1195  if( sens == "PROGRAM")
1196  {
1197  TQString progName = lineParser.getString("PROGRAM");
1198  sensor = sensorMap["PROGRAM"+progName];
1199  if (sensor == 0)
1200  {
1201  int interval = lineParser.getInt("INTERVAL");
1202  interval = (interval == 0)?3600000:interval;
1203  TQString encoding = lineParser.getString("ENCODING");
1204 
1205  sensor = (sensorMap["PROGRAM"+progName] =
1206  new ProgramSensor( progName, interval, encoding ) );
1207  sensorList->append( sensor );
1208  }
1209  SensorParams *sp = new SensorParams(meter);
1210  sp->addParam( "LINE", TQString::number(lineParser.getInt("LINE")));
1211  sp->addParam( "THEMAPATH", m_theme.path() );
1212  sensor->addMeter(sp);
1213  }
1214 
1215  if( sens == "RSS" )
1216  {
1217  TQString source = lineParser.getString("SOURCE");
1218  TQString format =
1219  m_theme.locale()->translate(lineParser.getString("FORMAT").ascii());
1220 
1221  sensor = sensorMap["RSS"+source];
1222  if (sensor == 0)
1223  {
1224  int interval = lineParser.getInt( "INTERVAL");
1225  interval = ( interval == 0 )?60000:interval;
1226  TQString encoding = lineParser.getString("ENCODING");
1227 
1228  sensor = ( sensorMap["RSS"+source] =
1229  new RssSensor( source, interval, format, encoding ) );
1230  sensorList->append( sensor );
1231  }
1232  SensorParams *sp = new SensorParams(meter);
1233  sp->addParam("SOURCE",lineParser.getString("SOURCE"));
1234  sensor->addMeter(sp);
1235  }
1236 
1237  if (sensor != 0)
1238  {
1239  TQTimer::singleShot( 0, sensor, TQ_SLOT(update()) );
1240  sensor->start();
1241  }
1242 }
1243 
1244 void karamba::slotFileChanged( const TQString & file)
1245 {
1246  //kdDebug() << "fileChanged: " << file << endl;
1247 
1248  TQString pythonFile = m_theme.path() + "/" + m_theme.pythonModule() + ".py";
1249 
1250  if(file == m_theme.file() || file == pythonFile)
1251  reloadConfig();
1252 }
1253 
1254 void karamba::passMenuOptionChanged(TQString key, bool value)
1255 {
1256  //Everything below is to call the python callback function
1257  if (pythonIface && pythonIface->isExtensionLoaded())
1258  pythonIface->menuOptionChanged(this, key, value);
1259 }
1260 
1261 void karamba::setIncomingData(TQString theme, TQString obj)
1262 {
1263  KarambaApplication* app = (KarambaApplication*)tqApp;
1264 
1265  kdDebug() << "karamba::setIncomingData " << theme << obj << endl;
1266  //TQByteArray data;
1267  //TQDataStream dataStream( data, IO_WriteOnly );
1268  //dataStream << theme;
1269  //dataStream << txt;
1270 
1271  //tdeApp->dcopClient()->send( app->dcopClient()->appId(), "KarambaIface", "themeNotify(TQString,TQString)", data );
1272 
1273  DCOPClient *c = tdeApp->dcopClient();
1274  if (!c->isAttached())
1275  c->attach();
1276 
1277  if(app->dcopStub())
1278  app->dcopStub()->setIncomingData(theme, obj);
1279 }
1280 
1281 void karamba::callTheme(TQString theme, TQString txt)
1282 {
1283  KarambaApplication* app = (KarambaApplication*)tqApp;
1284  kdDebug() << "karamba::callTheme " << theme << txt << endl;
1285  //tqWarning("karamba::callTheme");
1286  //TQByteArray data;
1287  //TQDataStream dataStream( data, IO_WriteOnly );
1288  //dataStream << theme;
1289  //dataStream << txt;
1290 
1291  //tdeApp->dcopClient()->send( app->dcopClient()->appId(), "KarambaIface", "themeNotify(TQString,TQString)", data );
1292 
1293  DCOPClient *c = tdeApp->dcopClient();
1294  if (!c->isAttached())
1295  c->attach();
1296 
1297  if(app->dcopStub())
1298  app->dcopStub()->themeNotify(theme, txt);
1299 }
1300 
1301 void karamba::themeNotify(TQString theme, TQString txt)
1302 {
1303  kdDebug() << "karamba::themeNotify" << theme << txt << endl;
1304  if (pythonIface->isExtensionLoaded())
1305  {
1306  pythonIface->themeNotify(this, theme.ascii(), txt.ascii());
1307  }
1308 }
1309 
1310 void karamba::meterClicked(TQMouseEvent* e, Meter* meter)
1311 {
1312  //tqWarning("karamba::meterClicked");
1313  if (pythonIface && pythonIface->isExtensionLoaded() && haveUpdated)
1314  {
1315  int button = 0;
1316 
1317  if( e->button() == TQt::LeftButton )
1318  button = 1;
1319  else if( e->button() == TQt::MidButton )
1320  button = 2;
1321  else if( e->button() == TQt::RightButton )
1322  button = 3;
1323 
1324  if (RichTextLabel* richText = dynamic_cast<RichTextLabel*>(meter))
1325  {
1326  pythonIface->meterClicked(this, richText->anchorAt(e->x(), e->y()),
1327  button);
1328  }
1329  else
1330  {
1331  pythonIface->meterClicked(this, meter, button);
1332  }
1333  }
1334 }
1335 
1336 void karamba::changeInterval(int interval)
1337 {
1338  if (m_sysTimer != NULL)
1339  m_sysTimer->changeInterval(interval);
1340 }
1341 
1342 void karamba::passClick(TQMouseEvent *e)
1343 {
1344  //tqDebug("karamba::passClick");
1345  TQObjectListIt it2( *timeList ); // iterate over meters
1346  while ( it2 != 0 )
1347  {
1348  (( DateSensor* ) *it2)->toggleCalendar( e );
1349  ++it2;
1350  }
1351 
1352 
1353  // We create a temporary click list here because original
1354  // can change during the loop (infinite loop Bug 994359)
1355  TQObjectList clickListTmp(*clickList);
1356  TQObjectListIt it(clickListTmp);
1357  while (it != 0)
1358  {
1359  Meter* meter = (Meter*)(*it);
1360  // Check if meter is still in list
1361  if (clickList->containsRef(meter) && meter->click(e))
1362  {
1363  // callback
1364  meterClicked(e, meter);
1365  }
1366  ++it;
1367  }
1368 
1369  //Everything below is to call the python callback function
1370  if (pythonIface && pythonIface->isExtensionLoaded() && haveUpdated)
1371  {
1372  int button = 0;
1373 
1374  if( e->button() == TQt::LeftButton )
1375  button = 1;
1376  else if( e->button() == TQt::MidButton )
1377  button = 2;
1378  else if( e->button() == TQt::RightButton )
1379  button = 3;
1380 
1381  pythonIface->widgetClicked(this, e->x(), e->y(), button);
1382  }
1383 }
1384 
1385 void karamba::passWheelClick( TQWheelEvent *e )
1386 {
1387  //tqDebug("karamba::passWheelClick");
1388  //Everything below is to call the python callback function
1389  if (pythonIface && pythonIface->isExtensionLoaded() && haveUpdated)
1390  {
1391  int button = 0;
1392 
1393  if( e->delta() > 0 )
1394  button = 4;
1395  else
1396  button = 5;
1397 
1398  // We create a temporary click list here because original
1399  // can change during the loop (infinite loop Bug 994359)
1400  if (want_meter_wheel_event)
1401  {
1402  TQObjectList clickListTmp(*clickList);
1403  TQObjectListIt it(clickListTmp);
1404 
1405  TQMouseEvent fakeEvent(TQEvent::MouseButtonPress, e->pos(), e->globalPos(), button, e->state());
1406 
1407  while (it != 0)
1408  {
1409  Meter* meter = (Meter*)(*it);
1410  // Check if meter is still in list
1411  if (clickList->containsRef(meter) && meter->click(&fakeEvent))
1412  {
1413  if (RichTextLabel* richText = dynamic_cast<RichTextLabel*>(meter))
1414  {
1415  pythonIface->meterClicked(this, richText->anchorAt(fakeEvent.x(), fakeEvent.y()),
1416  button);
1417  }
1418  else
1419  {
1420  pythonIface->meterClicked(this, meter, button);
1421  }
1422  }
1423  ++it;
1424  }
1425  }
1426 
1427  pythonIface->widgetClicked(this, e->x(), e->y(), button);
1428  }
1429 }
1430 
1431 void karamba::management_popup( void )
1432 {
1433  kpop->popup(TQCursor::pos());
1434 }
1435 
1436 void karamba::mousePressEvent( TQMouseEvent *e )
1437 {
1438  //tqDebug("karamba::mousePressEvent");
1439  if( e->button() == TQt::RightButton && !want_right_button )
1440  {
1441  management_popup();
1442  }
1443  else
1444  {
1445  clickPos = e->pos();
1446  if( toggleLocked -> isChecked() )
1447  passClick( e );
1448  if( !(onTop || managed))
1449  KWin::lowerWindow( winId() );
1450  }
1451 }
1452 
1453 void karamba::wheelEvent( TQWheelEvent *e )
1454 {
1455  //tqDebug("karamba::wheelEvent");
1456  passWheelClick( e );
1457 }
1458 
1459 void karamba::mouseReleaseEvent( TQMouseEvent *e )
1460 {
1461  //tqDebug("karamba::mouseReleaseEvent");
1462  clickPos = e->pos();
1463 }
1464 
1465 void karamba::mouseDoubleClickEvent( TQMouseEvent *e )
1466 {
1467  //tqDebug("karamba::mouseDoubleClickEvent");
1468  if( !toggleLocked -> isChecked() )
1469  {
1470  passClick( e );
1471  }
1472 }
1473 
1474 void karamba::keyPressEvent(TQKeyEvent *e)
1475 {
1476  //tqDebug("karamba::keyPressEvent");
1477  keyPressed(e->text(), 0);
1478 }
1479 
1480 void karamba::keyPressed(const TQString& s, const Meter* meter)
1481 {
1482  if (pythonIface && pythonIface->isExtensionLoaded())
1483  pythonIface->keyPressed(this, meter, s);
1484 }
1485 
1486 void karamba::mouseMoveEvent( TQMouseEvent *e )
1487 {
1488  //tqDebug("karamba::mouseMoveEvent");
1489  if( e->state() != 0 && e->state() < 16 && !toggleLocked -> isChecked() )
1490  {
1491  move( e->globalPos() - clickPos );
1492  }
1493  else
1494  {
1495  // Change cursor over ClickArea
1496  TQObjectListIt it(*clickList);
1497  bool insideArea = false;
1498 
1499  while (it != 0)
1500  {
1501  insideArea = ((Meter*)(*it)) -> insideActiveArea(e -> x(), e ->y());
1502  if (insideArea)
1503  {
1504  break;
1505  }
1506  ++it;
1507  }
1508 
1509  if(insideArea)
1510  {
1511  if( cursor().shape() != PointingHandCursor )
1512  setCursor( PointingHandCursor );
1513  }
1514  else
1515  {
1516  if( cursor().shape() != ArrowCursor )
1517  setCursor( ArrowCursor );
1518  }
1519 
1520  TQObjectListIt image_it( *imageList); // iterate over image sensors
1521  while ( image_it != 0 )
1522  {
1523  ((ImageLabel*) *image_it)->rolloverImage(e);
1524  ++image_it;
1525  }
1526  }
1527 
1528  if (pythonIface && pythonIface->isExtensionLoaded())
1529  {
1530  int button = 0;
1531 
1532  //Modified by Ryan Nickell (p0z3r@mail.com) 03/16/2004
1533  // This will work now, but only when you move at least
1534  // one pixel in any direction with your mouse.
1535  //if( e->button() == TQt::LeftButton )
1536  if( e->state() == TQt::LeftButton)
1537  button = 1;
1538  //else if( e->button() == TQt::MidButton )
1539  else if( e->state() == TQt::MidButton )
1540  button = 2;
1541  //else if( e->button() == TQt::RightButton )
1542  else if( e->state() == TQt::RightButton )
1543  button = 3;
1544 
1545  pythonIface->widgetMouseMoved(this, e->x(), e->y(), button);
1546  }
1547 }
1548 
1549 void karamba::closeEvent ( TQCloseEvent * qc)
1550 {
1551  //tqDebug("karamba::closeEvent");
1552  qc->accept();
1553  // close(true);
1554  // delete this;
1555 }
1556 
1557 void karamba::paintEvent ( TQPaintEvent *e)
1558 {
1559  //kdDebug() << k_funcinfo << pm.size() << endl;
1560  if(pm.width() == 0)
1561  return;
1562  if( !(onTop || managed))
1563  {
1564  if( lowerTimer.elapsed() > 100 )
1565  {
1566  KWin::lowerWindow( winId() );
1567  lowerTimer.restart();
1568  }
1569  }
1570  TQRect rect = e->rect();
1571  bitBlt(this,rect.topLeft(),&pm,rect,TQt::CopyROP);
1572 }
1573 
1574 void karamba::updateSensors()
1575 {
1576  //tqDebug("karamba::updateSensors");
1577  TQObjectListIt it( *sensorList ); // iterate over meters
1578  while ( it != 0 )
1579  {
1580  ((Sensor*) *it)->update();
1581  ++it;
1582  }
1583  TQTimer::singleShot( 500, this, TQ_SLOT(step()) );
1584 }
1585 
1586 void karamba::updateBackground(TDESharedPixmap* kpm)
1587 {
1588  //kdDebug() << k_funcinfo << pm.size() << endl;
1589  // if pm width == 0 this is the first time we come here and we should start
1590  // the theme. This is because we need the background before starting.
1591  //if(pm.width() == 0)
1592  if( !themeStarted )
1593  {
1594  themeStarted = true;
1595  start();
1596  }
1597  background = TQPixmap(*kpm);
1598 
1599  TQPixmap buffer = TQPixmap(size());
1600 
1601  pm = TQPixmap(size());
1602  buffer.fill(TQt::black);
1603 
1604  TQObjectListIt it( *imageList ); // iterate over meters
1605  p.begin(&buffer);
1606  bitBlt(&buffer,0,0,&background,0,TQt::CopyROP);
1607 
1608  while ( it != 0 )
1609  {
1610  if (((ImageLabel*) *it)->background == 1)
1611  {
1612  ((ImageLabel*) *it)->mUpdate(&p, 1);
1613  }
1614  ++it;
1615  }
1616  p.end();
1617 
1618  bitBlt(&pm,0,0,&buffer,0,TQt::CopyROP);
1619  background = pm;
1620 
1621  TQPixmap buffer2 = TQPixmap(size());
1622 
1623  pm = TQPixmap(size());
1624  buffer2.fill(TQt::black);
1625 
1626  TQObjectListIt it2( *meterList ); // iterate over meters
1627  p.begin(&buffer2);
1628  bitBlt(&buffer2,0,0,&background,0,TQt::CopyROP);
1629 
1630  while ( it2 != 0 )
1631  {
1632  ((Meter*) *it2)->mUpdate(&p);
1633  ++it2;
1634  }
1635  p.end();
1636 
1637  bitBlt(&pm,0,0,&buffer2,0,TQt::CopyROP);
1638  if (systray != 0)
1639  {
1640  systray->updateBackgroundPixmap(buffer2);
1641  }
1642  repaint();
1643 }
1644 
1645 void karamba::currentDesktopChanged( int i )
1646 {
1647  //tqDebug("karamba::currentDesktopChanged");
1648  kroot->repaint( true );
1649  if (pythonIface && pythonIface->isExtensionLoaded())
1650  pythonIface->desktopChanged(this, i);
1651 }
1652 
1653 void karamba::currentWallpaperChanged(int i )
1654 {
1655  //tqDebug("karamba::currentWallpaperChanged");
1656  kroot->repaint( true );
1657  if (pythonIface && pythonIface->isExtensionLoaded())
1658  pythonIface->wallpaperChanged(this, i);
1659 }
1660 
1661 void karamba::externalStep()
1662 {
1663  //kdDebug() << k_funcinfo << pm.size() << endl;
1664  if (widgetUpdate)
1665  {
1666  TQPixmap buffer = TQPixmap(size());
1667 
1668  pm = TQPixmap(size());
1669  buffer.fill(TQt::black);
1670 
1671  TQObjectListIt it( *meterList ); // iterate over meters
1672  p.begin(&buffer);
1673  bitBlt(&buffer,0,0,&background,0,TQt::CopyROP);
1674 
1675  while ( it != 0 )
1676  {
1677  ((Meter*) *it)->mUpdate(&p);
1678  ++it;
1679  }
1680  p.end();
1681 
1682  bitBlt(&pm,0,0,&buffer,0,TQt::CopyROP);
1683  repaint();
1684  }
1685 }
1686 
1687 void karamba::step()
1688 {
1689  //kdDebug() << k_funcinfo << pm.size() << endl;
1690  if (widgetUpdate && haveUpdated)
1691  {
1692  pm = TQPixmap(size());
1693  TQPixmap buffer = TQPixmap(size());
1694  buffer.fill(TQt::black);
1695 
1696  TQObjectListIt it( *meterList ); // iterate over meters
1697  p.begin(&buffer);
1698 
1699  bitBlt(&buffer,0,0,&background,0,TQt::CopyROP);
1700 
1701  while (it != 0)
1702  {
1703  ((Meter*) *it)->mUpdate(&p);
1704  ++it;
1705  }
1706  p.end();
1707 
1708  bitBlt(&pm,0,0,&buffer,0,TQt::CopyROP);
1709  update();
1710  }
1711 
1712  if (pythonIface && pythonIface->isExtensionLoaded())
1713  {
1714  if (!haveUpdated)
1715  pythonIface->initWidget(this);
1716  else
1717  pythonIface->widgetUpdated(this);
1718  }
1719 
1720  haveUpdated = true;
1721 }
1722 
1723 void karamba::widgetClosed()
1724 {
1725  //tqDebug("karamba::widgetClosed");
1726  if (pythonIface && pythonIface->isExtensionLoaded())
1727  pythonIface->widgetClosed(this);
1728 }
1729 
1730 void karamba::slotToggleLocked()
1731 {
1732  //tqDebug("karamba::slotToggleLocked");
1733  if(toggleLocked->isChecked())
1734  {
1735  toggleLocked->setIconSet(SmallIconSet("system-lock-screen"));
1736  }
1737  else
1738  {
1739  toggleLocked->setIconSet(SmallIconSet("move"));
1740  }
1741 }
1742 
1743 void karamba::slotToggleFastTransforms()
1744 {
1745  //tqDebug("karamba::slotToggleFastTransforms");
1746  // bool fastTransforms = toggleFastTransforms -> isChecked();
1747  // if (toggleFastTransforms -> isChecked())
1748  // {
1749  // toggleFastTransforms -> setIconSet(SmallIconSet("ok"));
1750  // }
1751  // else
1752  // {
1753  // TQPixmap ok_disabled;
1754  // toggleFastTransforms -> setIconSet(ok_disabled);
1755  // }
1756  //config.setGroup("internal");
1757  //config.writeEntry("fastTransforms", toggleFastTransforms -> isChecked());
1758 }
1759 
1760 
1761 bool karamba::useSmoothTransforms()
1762 {
1763  //tqDebug("karamba::useSmoothTransforms");
1764  return !toggleFastTransforms -> isChecked();
1765 }
1766 
1767 void karamba::writeConfigData()
1768 {
1769  //tqDebug("karamba::writeConfigData");
1770  config -> setGroup("internal");
1771  config -> writeEntry("lockedPosition", toggleLocked -> isChecked() );
1772  config -> writeEntry("fastTransforms", toggleFastTransforms -> isChecked() );
1773  config -> writeEntry("desktop", desktop );
1774  config -> setGroup("theme");
1775  // Widget Position
1776  config -> writeEntry("widgetPosX", x());
1777  config -> writeEntry("widgetPosY", y());
1778  // Widget Size
1779  config -> writeEntry("widgetWidth", width());
1780  config -> writeEntry("widgetHeight", height());
1781 
1782  // write changes to DiskSensor
1783  config -> sync();
1784  //tqWarning("Config File ~/.superkaramba/%s.rc written.",
1785  // m_theme.name().ascii());
1786 }
1787 
1788 void karamba::slotToggleConfigOption(TQString key, bool value)
1789 {
1790  //tqDebug("karamba::slotToggleConfigOption");
1791  config -> setGroup("config menu");
1792  config -> writeEntry(key, value);
1793  passMenuOptionChanged(key, value);
1794 }
1795 
1796 void karamba::addMenuConfigOption(TQString key, TQString name)
1797 {
1798  //tqDebug("karamba::addMenuConfigOption");
1799  kpop -> setItemEnabled(THEMECONF, true);
1800 
1801  SignalBridge* action = new SignalBridge(this, key, menuAccColl);
1802  TDEToggleAction* confItem = new TDEToggleAction (name, TDEShortcut::null(),
1803  action, TQ_SLOT(receive()),
1804  menuAccColl, key.ascii());
1805  confItem -> setName(key.ascii());
1806 
1807  menuAccColl -> insert(confItem);
1808 
1809  connect(action, TQ_SIGNAL( enabled(TQString, bool) ),
1810  this, TQ_SLOT( slotToggleConfigOption(TQString, bool) ));
1811 
1812  config -> setGroup("config menu");
1813  confItem -> setChecked(config -> readBoolEntry(key));
1814 
1815  confItem -> plug(themeConfMenu);
1816 
1817  numberOfConfMenuItems++;
1818 }
1819 
1820 bool karamba::setMenuConfigOption(TQString key, bool value)
1821 {
1822  //tqDebug("karamba::setMenuConfigOption");
1823  TDEToggleAction* menuAction = ((TDEToggleAction*)menuAccColl -> action(key.ascii()));
1824  if (menuAction == NULL)
1825  {
1826  tqWarning("Menu action %s not found.", key.ascii());
1827  return false;
1828  }
1829  else
1830  {
1831  menuAction -> setChecked(value);
1832  return true;
1833  }
1834 }
1835 
1836 bool karamba::readMenuConfigOption(TQString key)
1837 {
1838  //tqDebug("karamba::readMenuConfigOption");
1839  TDEToggleAction* menuAction = ((TDEToggleAction*)menuAccColl -> action(key.ascii()));
1840  if (menuAction == NULL)
1841  {
1842  tqWarning("Menu action %s not found.", key.ascii());
1843  return false;
1844  }
1845  else
1846  {
1847  return menuAction -> isChecked();
1848  }
1849 }
1850 
1851 void karamba::passMenuItemClicked(int id)
1852 {
1853  //tqDebug("karamba::passMenuItemClicked");
1854  //Everything below is to call the python callback function
1855  if (pythonIface && pythonIface->isExtensionLoaded())
1856  {
1857  TDEPopupMenu* menu = 0;
1858  for(int i = 0; i < (int)menuList->count(); i++)
1859  {
1860  TDEPopupMenu* tmp;
1861  if(i==0)
1862  {
1863  tmp = (TDEPopupMenu*) menuList->first();
1864  }
1865  else
1866  {
1867  tmp = (TDEPopupMenu*) menuList->next();
1868  }
1869  if(tmp != 0)
1870  {
1871  if(tmp->isItemVisible(id))
1872  {
1873  menu = tmp;
1874  break;
1875  }
1876  }
1877  }
1878  pythonIface->menuItemClicked(this, menu, id);
1879  }
1880 }
1881 
1882 void karamba::activeTaskChanged(Task* t)
1883 {
1884  //tqDebug("karamba::activeTaskChanged");
1885  //Everything below is to call the python callback function
1886  if (pythonIface && pythonIface->isExtensionLoaded())
1887  pythonIface->activeTaskChanged(this, t);
1888 }
1889 
1890 void karamba::taskAdded(Task* t)
1891 {
1892  //tqDebug("karamba::taskAdded");
1893  //Everything below is to call the python callback function
1894  if (pythonIface && pythonIface->isExtensionLoaded())
1895  pythonIface->taskAdded(this, t);
1896 }
1897 
1898 void karamba::taskRemoved(Task* t)
1899 {
1900  //tqDebug("karamba::taskRemoved");
1901  //Everything below is to call the python callback function
1902  if (pythonIface && pythonIface->isExtensionLoaded())
1903  pythonIface->taskRemoved(this, t);
1904 }
1905 
1906 void karamba::startupAdded(Startup* t)
1907 {
1908  //tqDebug("karamba::startupAdded");
1909  //Everything below is to call the python callback function
1910  if (pythonIface && pythonIface->isExtensionLoaded())
1911  pythonIface->startupAdded(this, t);
1912 }
1913 
1914 void karamba::startupRemoved(Startup* t)
1915 {
1916  //tqDebug("karamba::startupRemoved");
1917  //Everything below is to call the python callback function
1918  if (pythonIface && pythonIface->isExtensionLoaded())
1919  pythonIface->startupRemoved(this, t);
1920 }
1921 
1922 void karamba::processExited (TDEProcess* proc)
1923 {
1924  //tqDebug("karamba::processExited");
1925  if (pythonIface && pythonIface->isExtensionLoaded())
1926  pythonIface->commandFinished(this, (int)proc->pid());
1927 }
1928 
1929 void karamba::receivedStdout (TDEProcess *proc, char *buffer, int)
1930 {
1931  //tqDebug("karamba::receivedStdout");
1932  //Everything below is to call the python callback function
1933  if (pythonIface && pythonIface->isExtensionLoaded())
1934  pythonIface->commandOutput(this, (int)proc->pid(), buffer);
1935 }
1936 
1937 //For KDE session management
1938 void karamba::saveProperties(TDEConfig* config)
1939 {
1940  //tqDebug("karamba::saveProperties");
1941  config->setGroup("session");
1942  config->writeEntry("theme", m_theme.file());
1943  writeConfigData();
1944 }
1945 
1946 //For KDE session management
1947 void karamba::readProperties(TDEConfig* config)
1948 {
1949  //tqDebug("karamba::readProperties");
1950  config->setGroup("session");
1951  TQString atheme = config->readEntry("theme");
1952 }
1953 
1954 //Register types of events that can be dragged on our widget
1955 void karamba::dragEnterEvent(TQDragEnterEvent* event)
1956 {
1957  //tqDebug("karamba::dragEnterEvent");
1958  event->accept(TQTextDrag::canDecode(event));
1959 }
1960 
1961 //Handle the drop part of a drag and drop event.
1962 void karamba::dropEvent(TQDropEvent* event)
1963 {
1964  //tqDebug("karamba::dropEvent");
1965  TQString text;
1966 
1967  if ( TQTextDrag::decode(event, text) )
1968  {
1969  //Everything below is to call the python callback function
1970  if (pythonIface && pythonIface->isExtensionLoaded())
1971  {
1972  const TQPoint &p = event->pos();
1973  pythonIface->itemDropped(this, text, p.x(), p.y());
1974  }
1975  }
1976 }
1977 
1978 void karamba::toDesktop(int id, int menuid)
1979 {
1980  //tqDebug("karamba::toDesktop");
1981  int i;
1982 
1983  desktop = id;
1984  for (i=0; ; i++)
1985  {
1986  int mid = toDesktopMenu->idAt(i);
1987  if (mid == -1)
1988  break;
1989 
1990  toDesktopMenu->setItemChecked(mid, false);
1991  }
1992  toDesktopMenu->setItemChecked(menuid, true);
1993 
1994  if (desktop)
1995  info->setDesktop( desktop);
1996  else
1997  info->setDesktop( NETWinInfo::OnAllDesktops );
1998 }
1999 
2000 void karamba::systrayUpdated()
2001 {
2002  //tqDebug("karamba::systrayUpdated");
2003  if (pythonIface && pythonIface->isExtensionLoaded())
2004  pythonIface->systrayUpdated(this);
2005 }
2006 
2007 void karamba::toggleWidgetUpdate( bool b)
2008 {
2009  //tqDebug("karamba::toggleWidgetUpdate");
2010  if (pythonIface && pythonIface->isExtensionLoaded())
2011  widgetUpdate = b;
2012 }
2013 
2014 SignalBridge::SignalBridge(TQObject* parent, TQString name, TDEActionCollection* ac)
2015  : TQObject(parent, name.ascii()), collection(ac)
2016 {
2017  setName(name.ascii());
2018 }
2019 
2020 void SignalBridge::receive()
2021 {
2022  emit enabled(name(), ((TDEToggleAction*)collection -> action(name())) ->
2023 isChecked());
2024 }
2025 
2026 DesktopChangeSlot::DesktopChangeSlot(TQObject *parent, int id)
2027  : TQObject(parent, "")
2028 {
2029  desktopid = id;
2030 }
2031 
2032 void DesktopChangeSlot::receive()
2033 {
2034  karamba *k = (karamba *)parent();
2035 
2036  // XXX - check type cast
2037 
2038  k->toDesktop(desktopid, menuid);
2039 }
2040 
2041 void DesktopChangeSlot::setMenuId(int id)
2042 {
2043  menuid = id;
2044 }
2045 
2046 int DesktopChangeSlot::menuId()
2047 {
2048  return menuid;
2049 }
2050 
2051 void karamba::showMenuExtension()
2052 {
2053  kglobal = new TDEPopupMenu(this);
2054 
2055  trayMenuToggleId = kglobal->insertItem(SmallIconSet("superkaramba"),
2056  i18n("Show System Tray Icon"), this,
2057  TQ_SLOT(slotToggleSystemTray()),
2058  CTRL+Key_S);
2059 
2060  trayMenuThemeId = kglobal->insertItem(SmallIconSet("knewstuff"),
2061  i18n("&Manage Themes..."), this,
2062  TQ_SLOT(slotShowTheme()), CTRL+Key_M);
2063 
2064  trayMenuQuitId = kglobal->insertItem(SmallIconSet("system-log-out"),
2065  i18n("&Quit SuperKaramba"), this,
2066  TQ_SLOT(slotQuit()), CTRL+Key_Q);
2067 
2068  kglobal->polish();
2069 
2070  trayMenuSeperatorId = kpop->insertSeparator();
2071  kpop->insertItem("SuperKaramba", kglobal);
2072 }
2073 
2074 void karamba::hideMenuExtension()
2075 {
2076  if(kglobal)
2077  {
2078  kpop->removeItem(trayMenuSeperatorId);
2079  kglobal->removeItem(trayMenuToggleId);
2080  kglobal->removeItem(trayMenuThemeId);
2081  kglobal->removeItem(trayMenuQuitId);
2082 
2083  delete kglobal;
2084  kglobal = 0;
2085  }
2086 }
2087 
2088 void karamba::slotToggleSystemTray()
2089 {
2090  karambaApp->globalHideSysTray(false);
2091 }
2092 
2093 void karamba::slotQuit()
2094 {
2095  karambaApp->globalQuitSuperKaramba();
2096 }
2097 
2098 void karamba::slotShowTheme()
2099 {
2100  karambaApp->globalShowThemeDialog();
2101 }
2102 
2103 void karamba::setAlwaysOnTop(bool stay)
2104 {
2105  if(stay)
2106  {
2107  onTop = true;
2108  KWin::setState( winId(), NET::KeepAbove );
2109  }
2110  else
2111  {
2112  onTop = false;
2113  KWin::setState( winId(), NET::KeepBelow );
2114  }
2115 }
2116 
2117 #include "karamba.moc"
Startup
Represents a task which is in the process of starting.
Definition: taskmanager.h:376
SignalBridge
SignalBridge is an ungulate that lives in the forests of wild Wisconsin.
Definition: karamba.h:349
SensorParams
Hans Karlsson.
Definition: sensorparams.h:31
SensorSensor
Hans Karlsson.
Definition: sensorsensor.h:20
LineParser
Definition: lineparser.h:33
KarambaRootPixmap
Definition: karambarootpixmap.h:22
ClickArea
Hans Karlsson.
Definition: clickarea.h:40
TextFileSensor
Hans Karlsson.
Definition: textfilesensor.h:36
ClickMap
Ralph M.
Definition: clickmap.h:23
NoatunSensor
Definition: noatunsensor.h:23
Task
A dynamic interface to a task (main window).
Definition: taskmanager.h:49
TextField
Ralph M.
Definition: textfield.h:21
RssSensor
Ralph M.
Definition: rsssensor.h:22

superkaramba

Skip menu "superkaramba"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

superkaramba

Skip menu "superkaramba"
  • kcalc
  •   knumber
  • superkaramba
Generated for superkaramba by doxygen 1.8.13
This website is maintained by Timothy Pearson.