summaryrefslogtreecommitdiffstats
path: root/ksysguard/gui/ksysguard.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ksysguard/gui/ksysguard.cpp')
-rw-r--r--ksysguard/gui/ksysguard.cpp650
1 files changed, 650 insertions, 0 deletions
diff --git a/ksysguard/gui/ksysguard.cpp b/ksysguard/gui/ksysguard.cpp
new file mode 100644
index 000000000..937c5fdd1
--- /dev/null
+++ b/ksysguard/gui/ksysguard.cpp
@@ -0,0 +1,650 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger
+ <cs@kde.org>. Please do not commit any changes without consulting
+ me first. Thanks!
+
+ KSysGuard has been written with some source code and ideas from
+ ktop (<1.0). Early versions of ktop have been written by Bernd
+ Johannes Wuebben <wuebben@math.cornell.edu> and Nicolas Leclercq
+ <nicknet@planete.net>.
+
+*/
+
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <tdeaboutdata.h>
+#include <tdeaction.h>
+#include <tdeapplication.h>
+#include <tdecmdlineargs.h>
+#include <kdebug.h>
+#include <kedittoolbar.h>
+#include <tdeglobal.h>
+#include <tdeglobalsettings.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <ksgrd/SensorAgent.h>
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+#include <kstandarddirs.h>
+#include <kstatusbar.h>
+#include <kstdaction.h>
+#include <twin.h>
+#include <twinmodule.h>
+#include <dnssd/remoteservice.h>
+
+
+#include "../version.h"
+#include "SensorBrowser.h"
+#include "Workspace.h"
+
+#include "ksysguard.h"
+
+static const char Description[] = I18N_NOOP( "TDE system guard" );
+TopLevel* topLevel;
+
+/**
+ This is the constructor for the main widget. It sets up the menu and the
+ TaskMan widget.
+ */
+TopLevel::TopLevel( const char *name )
+ : TDEMainWindow( 0, name ), DCOPObject( "KSysGuardIface" )
+{
+ setPlainCaption( i18n( "KSysGuard" ) );
+ mDontSaveSession = false;
+ mTimerId = -1;
+
+ mSplitter = new TQSplitter( this );
+ mSplitter->setOrientation( Qt::Horizontal );
+ mSplitter->setOpaqueResize( TDEGlobalSettings::opaqueResize() );
+ setCentralWidget( mSplitter );
+
+ mSensorBrowser = new SensorBrowser( mSplitter, KSGRD::SensorMgr );
+
+ mServiceBrowser = new DNSSD::ServiceBrowser("_ksysguard._tcp", 0, true);
+ connect(mServiceBrowser,TQT_SIGNAL(serviceAdded(DNSSD::RemoteService::Ptr)),this,
+ TQT_SLOT(serviceAdded(DNSSD::RemoteService::Ptr)));
+
+ mWorkSpace = new Workspace( mSplitter );
+ connect( mWorkSpace, TQT_SIGNAL( announceRecentURL( const KURL& ) ),
+ TQT_SLOT( registerRecentURL( const KURL& ) ) );
+ connect( mWorkSpace, TQT_SIGNAL( setCaption( const TQString&, bool ) ),
+ TQT_SLOT( setCaption( const TQString&, bool ) ) );
+ connect( KSGRD::Style, TQT_SIGNAL( applyStyleToWorksheet() ), mWorkSpace,
+ TQT_SLOT( applyStyle() ) );
+
+ /* Create the status bar. It displays some information about the
+ * number of processes and the memory consumption of the local
+ * host. */
+ statusBar()->insertFixedItem( i18n( "88888 Processes" ), 0 );
+ statusBar()->insertFixedItem( i18n( "Memory: 88888888888 kB used, "
+ "88888888888 kB free" ), 1 );
+ statusBar()->insertFixedItem( i18n( "Swap: 888888888 kB used, "
+ "888888888 kB free" ), 2 );
+ statusBar()->hide();
+
+ // create actions for menue entries
+ new TDEAction( i18n( "&New Worksheet..." ), "tab_new", 0, TQT_TQOBJECT(mWorkSpace),
+ TQT_SLOT( newWorkSheet() ), actionCollection(), "new_worksheet" );
+
+ new TDEAction( i18n( "Import Worksheet..." ), "document-open", 0, TQT_TQOBJECT(mWorkSpace),
+ TQT_SLOT( loadWorkSheet() ), actionCollection(), "import_worksheet" );
+
+ mActionOpenRecent = new TDERecentFilesAction( i18n( "&Import Recent Worksheet" ),"document-open", 0,
+ TQT_TQOBJECT(mWorkSpace), TQT_SLOT( loadWorkSheet( const KURL& ) ), actionCollection(), "recent_import_worksheet" );
+
+ new TDEAction( i18n( "&Remove Worksheet" ), "tab_remove", 0, TQT_TQOBJECT(mWorkSpace),
+ TQT_SLOT( deleteWorkSheet() ), actionCollection(), "remove_worksheet" );
+
+ new TDEAction( i18n( "&Export Worksheet..." ), "document-save-as", 0, TQT_TQOBJECT(mWorkSpace),
+ TQT_SLOT( saveWorkSheetAs() ), actionCollection(), "export_worksheet" );
+
+ KStdAction::quit( TQT_TQOBJECT(this), TQT_SLOT( close() ), actionCollection() );
+
+ new TDEAction( i18n( "C&onnect Host..." ), "connect_established", 0, TQT_TQOBJECT(this),
+ TQT_SLOT( connectHost() ), actionCollection(), "connect_host" );
+ new TDEAction( i18n( "D&isconnect Host" ), "connect_no", 0, TQT_TQOBJECT(this),
+ TQT_SLOT( disconnectHost() ), actionCollection(), "disconnect_host" );
+
+// KStdAction::cut( mWorkSpace, TQT_SLOT( cut() ), actionCollection() );
+// KStdAction::copy( mWorkSpace, TQT_SLOT( copy() ), actionCollection() );
+// KStdAction::paste( mWorkSpace, TQT_SLOT( paste() ), actionCollection() );
+ new TDEAction( i18n( "&Worksheet Properties" ), "configure", 0, TQT_TQOBJECT(mWorkSpace),
+ TQT_SLOT( configure() ), actionCollection(), "configure_sheet" );
+
+ new TDEAction( i18n( "Load Standard Sheets" ), "document-revert",
+ 0, TQT_TQOBJECT(this), TQT_SLOT( resetWorkSheets() ),
+ actionCollection(), "revert_all_worksheets" );
+
+ new TDEAction( i18n( "Configure &Style..." ), "colorize", 0, TQT_TQOBJECT(this),
+ TQT_SLOT( editStyle() ), actionCollection(), "configure_style" );
+
+ // TODO remove resize and fix so sizeHints() determines default size.
+ if (!initialGeometrySet())
+ resize( 640, 480 );
+ setupGUI(ToolBar | Keys | StatusBar | Create);
+ setAutoSaveSettings();
+}
+
+
+/*
+ * DCOP Interface functions
+ */
+void TopLevel::resetWorkSheets()
+{
+ if ( KMessageBox::warningContinueCancel( this,
+ i18n( "Do you really want to restore the default worksheets?" ),
+ i18n( "Reset All Worksheets" ),
+ i18n("Reset"),
+ "AskResetWorkSheets") == KMessageBox::Cancel )
+ return;
+
+ mWorkSpace->removeAllWorkSheets();
+
+ TDEStandardDirs* kstd = TDEGlobal::dirs();
+ kstd->addResourceType( "data", "share/apps/ksysguard" );
+
+ TQString workDir = kstd->saveLocation( "data", "ksysguard" );
+
+ TQString file = kstd->findResource( "data", "SystemLoad.sgrd" );
+ TQString newFile = workDir + "/" + i18n( "System Load" ) + ".sgrd";
+ if ( !file.isEmpty() )
+ mWorkSpace->restoreWorkSheet( file, newFile );
+
+ file = kstd->findResource( "data", "ProcessTable.sgrd" );
+ newFile = workDir + "/" + i18n( "Process Table" ) + ".sgrd";
+ if ( !file.isEmpty() )
+ mWorkSpace->restoreWorkSheet( file, newFile );
+}
+
+void TopLevel::showProcesses()
+{
+ mWorkSpace->showProcesses();
+}
+
+void TopLevel::showOnCurrentDesktop()
+{
+ KWin::setOnDesktop( winId(), KWin::currentDesktop() );
+ kapp->updateUserTimestamp();
+ KWin::forceActiveWindow( winId() );
+}
+
+void TopLevel::loadWorkSheet( const TQString &fileName )
+{
+ mWorkSpace->loadWorkSheet( KURL( fileName ) );
+}
+
+void TopLevel::removeWorkSheet( const TQString &fileName )
+{
+ mWorkSpace->deleteWorkSheet( fileName );
+}
+
+TQStringList TopLevel::listSensors( const TQString &hostName )
+{
+ return mSensorBrowser->listSensors( hostName );
+}
+
+TQStringList TopLevel::listHosts()
+{
+ return mSensorBrowser->listHosts();
+}
+
+TQString TopLevel::readIntegerSensor( const TQString &sensorLocator )
+{
+ TQString host = sensorLocator.left( sensorLocator.find( ':' ) );
+ TQString sensor = sensorLocator.right( sensorLocator.length() -
+ sensorLocator.find( ':' ) - 1 );
+
+ DCOPClientTransaction *dcopTransaction = kapp->dcopClient()->beginTransaction();
+ mDCopFIFO.prepend( dcopTransaction );
+
+ KSGRD::SensorMgr->engage( host, "", "ksysguardd" );
+ KSGRD::SensorMgr->sendRequest( host, sensor, (KSGRD::SensorClient*)this, 133 );
+
+ return TQString::null;
+}
+
+TQStringList TopLevel::readListSensor( const TQString& sensorLocator )
+{
+ TQStringList retval;
+
+ TQString host = sensorLocator.left( sensorLocator.find( ':' ) );
+ TQString sensor = sensorLocator.right( sensorLocator.length() -
+ sensorLocator.find( ':' ) - 1 );
+
+ DCOPClientTransaction *dcopTransaction = kapp->dcopClient()->beginTransaction();
+ mDCopFIFO.prepend( dcopTransaction );
+
+ KSGRD::SensorMgr->engage( host, "", "ksysguardd" );
+ KSGRD::SensorMgr->sendRequest( host, sensor, (KSGRD::SensorClient*)this, 134 );
+
+ return retval;
+}
+/*
+ * End of DCOP Interface section
+ */
+
+void TopLevel::serviceAdded(DNSSD::RemoteService::Ptr srv)
+{
+ KSGRD::SensorMgr->engage( srv->hostName(), "", "", srv->port() );
+}
+
+void TopLevel::registerRecentURL( const KURL &url )
+{
+ mActionOpenRecent->addURL( url );
+}
+
+void TopLevel::beATaskManager()
+{
+ mWorkSpace->showProcesses();
+
+ // Avoid displaying splitter widget
+ mSensorBrowser->hide();
+
+ // No toolbar and status bar in taskmanager mode.
+ toolBar( "mainToolBar" )->hide();
+
+ mDontSaveSession = true;
+
+ stateChanged( "showProcessState" );
+}
+
+void TopLevel::showRequestedSheets()
+{
+ toolBar( "mainToolBar" )->hide();
+
+ TQValueList<int> sizes;
+ sizes.append( 0 );
+ sizes.append( 100 );
+ mSplitter->setSizes( sizes );
+}
+
+void TopLevel::initStatusBar()
+{
+ KSGRD::SensorMgr->engage( "localhost", "", "ksysguardd" );
+ /* Request info about the swap space size and the units it is
+ * measured in. The requested info will be received by
+ * answerReceived(). */
+ KSGRD::SensorMgr->sendRequest( "localhost", "mem/swap/used?",
+ (KSGRD::SensorClient*)this, 5 );
+ updateStatusBar();
+ mServiceBrowser->startBrowse();
+
+ TDEToggleAction *sb = dynamic_cast<TDEToggleAction*>(action("options_show_statusbar"));
+ if (sb)
+ connect(sb, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(updateStatusBar()));
+}
+
+void TopLevel::updateStatusBar()
+{
+ if ( mTimerId == -1 )
+ mTimerId = startTimer( 2000 );
+
+ // call timerEvent to fill the status bar with real values
+ timerEvent( 0 );
+}
+
+void TopLevel::connectHost()
+{
+ KSGRD::SensorMgr->engageHost( "" );
+}
+
+void TopLevel::disconnectHost()
+{
+ mSensorBrowser->disconnect();
+}
+
+void TopLevel::editToolbars()
+{
+ saveMainWindowSettings( kapp->config() );
+ KEditToolbar dlg( actionCollection() );
+ connect( &dlg, TQT_SIGNAL( newToolbarConfig() ), this,
+ TQT_SLOT( slotNewToolbarConfig() ) );
+
+ dlg.exec();
+}
+
+void TopLevel::slotNewToolbarConfig()
+{
+ createGUI();
+ applyMainWindowSettings( kapp->config() );
+}
+
+void TopLevel::editStyle()
+{
+ KSGRD::Style->configure();
+}
+
+void TopLevel::customEvent( TQCustomEvent *e )
+{
+ if ( e->type() == TQEvent::User ) {
+ /* Due to the asynchronous communication between ksysguard and its
+ * back-ends, we sometimes need to show message boxes that were
+ * triggered by objects that have died already. */
+ KMessageBox::error( this, *((TQString*)e->data()) );
+ delete (TQString*)e->data();
+ }
+}
+
+void TopLevel::timerEvent( TQTimerEvent* )
+{
+ if ( statusBar()->isVisibleTo( this ) ) {
+ /* Request some info about the memory status. The requested
+ * information will be received by answerReceived(). */
+ KSGRD::SensorMgr->sendRequest( "localhost", "pscount",
+ (KSGRD::SensorClient*)this, 0 );
+ KSGRD::SensorMgr->sendRequest( "localhost", "mem/physical/free",
+ (KSGRD::SensorClient*)this, 1 );
+ KSGRD::SensorMgr->sendRequest( "localhost", "mem/physical/used",
+ (KSGRD::SensorClient*)this, 2 );
+ KSGRD::SensorMgr->sendRequest( "localhost", "mem/swap/free",
+ (KSGRD::SensorClient*)this, 3 );
+ KSGRD::SensorMgr->sendRequest( "localhost", "mem/swap/used",
+ (KSGRD::SensorClient*)this, 4 );
+ }
+}
+
+bool TopLevel::queryClose()
+{
+ if ( !mDontSaveSession ) {
+ if ( !mWorkSpace->saveOnQuit() )
+ return false;
+
+ saveProperties( kapp->config() );
+ kapp->config()->sync();
+ }
+
+ return true;
+}
+
+void TopLevel::readProperties( TDEConfig *cfg )
+{
+ /* we can ignore 'isMaximized' because we can't set the window
+ maximized, so we save the coordinates instead */
+ if ( cfg->readBoolEntry( "isMinimized" ) == true )
+ showMinimized();
+
+ TQValueList<int> sizes = cfg->readIntListEntry( "SplitterSizeList" );
+ if ( sizes.isEmpty() ) {
+ // start with a 30/70 ratio
+ sizes.append( 30 );
+ sizes.append( 70 );
+ }
+ mSplitter->setSizes( sizes );
+
+ KSGRD::SensorMgr->readProperties( cfg );
+ KSGRD::Style->readProperties( cfg );
+
+ mWorkSpace->readProperties( cfg );
+
+ mActionOpenRecent->loadEntries( cfg );
+
+ applyMainWindowSettings( cfg );
+}
+
+void TopLevel::saveProperties( TDEConfig *cfg )
+{
+ mActionOpenRecent->saveEntries( cfg );
+
+ cfg->writeEntry( "isMinimized", isMinimized() );
+ cfg->writeEntry( "SplitterSizeList", mSplitter->sizes() );
+
+ KSGRD::Style->saveProperties( cfg );
+ KSGRD::SensorMgr->saveProperties( cfg );
+
+ saveMainWindowSettings( cfg );
+ mWorkSpace->saveProperties( cfg );
+}
+
+void TopLevel::answerReceived( int id, const TQString &answer )
+{
+ TQString s;
+ static TQString unit;
+ static long mUsed = 0;
+ static long mFree = 0;
+ static long sUsed = 0;
+ static long sFree = 0;
+
+ switch ( id ) {
+ case 0:
+ // yes, I know there is never 1 process, but that's the way
+ // singular vs. plural works :/
+ //
+ // To use pluralForms, though, you need to convert to
+ // an integer, not use the TQString straight.
+ s = i18n( "1 Process", "%n Processes", answer.toInt() );
+ statusBar()->changeItem( s, 0 );
+ break;
+
+ case 1:
+ mFree = answer.toLong();
+ break;
+
+ case 2:
+ mUsed = answer.toLong();
+ s = i18n( "Memory: %1 %2 used, %3 %4 free" )
+ .arg( TDEGlobal::locale()->formatNumber( mUsed, 0 ) ).arg( unit )
+ .arg( TDEGlobal::locale()->formatNumber( mFree, 0 ) ).arg( unit );
+ statusBar()->changeItem( s, 1 );
+ break;
+
+ case 3:
+ sFree = answer.toLong();
+ setSwapInfo( sUsed, sFree, unit );
+ break;
+
+ case 4:
+ sUsed = answer.toLong();
+ setSwapInfo( sUsed, sFree, unit );
+ break;
+
+ case 5: {
+ KSGRD::SensorIntegerInfo info( answer );
+ unit = KSGRD::SensorMgr->translateUnit( info.unit() );
+ }
+
+ case 133: {
+ TQCString replyType = "TQString";
+ TQByteArray replyData;
+ TQDataStream reply( replyData, IO_WriteOnly );
+ reply << answer;
+
+ DCOPClientTransaction *dcopTransaction = mDCopFIFO.last();
+ kapp->dcopClient()->endTransaction( dcopTransaction, replyType, replyData );
+ mDCopFIFO.removeLast();
+ break;
+ }
+
+ case 134: {
+ TQStringList resultList;
+ TQCString replyType = "TQStringList";
+ TQByteArray replyData;
+ TQDataStream reply( replyData, IO_WriteOnly );
+
+ KSGRD::SensorTokenizer lines( answer, '\n' );
+
+ for ( unsigned int i = 0; i < lines.count(); i++ )
+ resultList.append( lines[ i ] );
+
+ reply << resultList;
+
+ DCOPClientTransaction *dcopTransaction = mDCopFIFO.last();
+ kapp->dcopClient()->endTransaction( dcopTransaction, replyType, replyData );
+ mDCopFIFO.removeLast();
+ break;
+ }
+ }
+}
+
+void TopLevel::setSwapInfo( long used, long free, const TQString &unit )
+{
+ TQString msg;
+ if ( used == 0 && free == 0 ) // no swap available
+ msg = i18n( "No swap space available" );
+ else {
+ msg = i18n( "Swap: %1 %2 used, %3 %4 free" )
+ .arg( TDEGlobal::locale()->formatNumber( used, 0 ) ).arg( unit )
+ .arg( TDEGlobal::locale()->formatNumber( free, 0 ) ).arg( unit );
+ }
+
+ statusBar()->changeItem( msg, 2 );
+}
+
+static const TDECmdLineOptions options[] = {
+ { "showprocesses", I18N_NOOP( "Show only process list of local host" ), 0 },
+ { "+[worksheet]", I18N_NOOP( "Optional worksheet files to load" ), 0 },
+ TDECmdLineLastOption
+};
+
+/*
+ * Once upon a time...
+ */
+int main( int argc, char** argv )
+{
+ // initpipe is used to keep the parent process around till the child
+ // has registered with dcop.
+ int initpipe[ 2 ];
+ pipe( initpipe );
+
+ /* This forking will put ksysguard in it's on session not having a
+ * controlling terminal attached to it. This prevents ssh from
+ * using this terminal for password requests. Unfortunately you
+ * now need a ssh with ssh-askpass support to popup an X dialog to
+ * enter the password. Currently only the original ssh provides this
+ * but not open-ssh. */
+
+ pid_t pid;
+ if ( ( pid = fork() ) < 0 )
+ return -1;
+ else
+ if ( pid != 0 ) {
+ close( initpipe[ 1 ] );
+
+ // wait till init is complete
+ char c;
+ while( read( initpipe[ 0 ], &c, 1 ) < 0 );
+
+ // then exit
+ close( initpipe[ 0 ] );
+ exit( 0 );
+ }
+
+ close( initpipe[ 0 ] );
+ setsid();
+
+ TDEAboutData aboutData( "ksysguard", I18N_NOOP( "KSysGuard" ),
+ KSYSGUARD_VERSION, Description, TDEAboutData::License_GPL,
+ I18N_NOOP( "(c) 1996-2002 The KSysGuard Developers" ) );
+ aboutData.addAuthor( "Chris Schlaeger", "Current Maintainer", "cs@kde.org" );
+ aboutData.addAuthor( "Tobias Koenig", 0, "tokoe@kde.org" );
+ aboutData.addAuthor( "Nicolas Leclercq", 0, "nicknet@planete.net" );
+ aboutData.addAuthor( "Alex Sanda", 0, "alex@darkstart.ping.at" );
+ aboutData.addAuthor( "Bernd Johannes Wuebben", 0, "wuebben@math.cornell.edu" );
+ aboutData.addAuthor( "Ralf Mueller", 0, "rlaf@bj-ig.de" );
+ aboutData.addAuthor( "Hamish Rodda", 0, "rodda@kde.org" );
+ aboutData.addAuthor( "Torsten Kasch", I18N_NOOP( "Solaris Support\n"
+ "Parts derived (by permission) from the sunos5\n"
+ "module of William LeFebvre's \"top\" utility." ),
+ "tk@Genetik.Uni-Bielefeld.DE" );
+
+ TDECmdLineArgs::init( argc, argv, &aboutData );
+ TDECmdLineArgs::addCmdLineOptions( options );
+
+ TDEApplication::disableAutoDcopRegistration();
+ // initialize KDE application
+ TDEApplication *app = new TDEApplication;
+
+ KSGRD::SensorMgr = new KSGRD::SensorManager();
+ KSGRD::Style = new KSGRD::StyleEngine();
+
+ TDECmdLineArgs* args = TDECmdLineArgs::parsedArgs();
+
+ int result = 0;
+
+ if ( args->isSet( "showprocesses" ) ) {
+ /* To avoid having multiple instances of ksysguard in
+ * taskmanager mode we check if another taskmanager is running
+ * already. If so, we terminate this one immediately. */
+ if ( app->dcopClient()->registerAs( "ksysguard_taskmanager", false ) ==
+ "ksysguard_taskmanager" ) {
+ // We have registered with DCOP, our parent can exit now.
+ char c = 0;
+ write( initpipe[ 1 ], &c, 1 );
+ close( initpipe[ 1 ] );
+
+ topLevel = new TopLevel( "KSysGuard" );
+ topLevel->beATaskManager();
+ topLevel->initStatusBar();
+ topLevel->show();
+ KSGRD::SensorMgr->setBroadcaster( topLevel );
+
+ // run the application
+ result = app->exec();
+ } else {
+ TQByteArray data;
+ app->dcopClient()->send( "ksysguard_taskmanager", "KSysGuardIface",
+ "showOnCurrentDesktop()", data );
+ }
+ } else {
+ app->dcopClient()->registerAs( "ksysguard" );
+ app->dcopClient()->setDefaultObject( "KSysGuardIface" );
+
+ // We have registered with DCOP, our parent can exit now.
+ char c = 0;
+ write( initpipe[ 1 ], &c, 1 );
+ close( initpipe[ 1 ] );
+
+ topLevel = new TopLevel( "KSysGuard" );
+
+ // create top-level widget
+ if ( args->count() > 0 ) {
+ /* The user has specified a list of worksheets to load. In this
+ * case we do not restore any previous settings but load all the
+ * requested worksheets. */
+ topLevel->showRequestedSheets();
+ for ( int i = 0; i < args->count(); ++i )
+ topLevel->loadWorkSheet( args->arg( i ) );
+ } else {
+ if ( app->isRestored() )
+ topLevel->restore( 1 );
+ else
+ topLevel->readProperties( app->config() );
+ }
+
+ topLevel->initStatusBar();
+ topLevel->show();
+ KSGRD::SensorMgr->setBroadcaster( topLevel );
+
+ // run the application
+ result = app->exec();
+ }
+
+ delete KSGRD::Style;
+ delete KSGRD::SensorMgr;
+ delete app;
+
+ return result;
+}
+
+#include "ksysguard.moc"