~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to ksysguard/gui/ksysguard.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    KSysGuard, the KDE System Guard
 
3
 
 
4
    Copyright (c) 2006 - 2008 John Tapsell <john.tapsell@kde.org>
 
5
    Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
 
6
 
 
7
    This program is free software; you can redistribute it and/or
 
8
    modify it under the terms of the GNU General Public
 
9
    License version 2 or at your option version 3 as published by
 
10
    the Free Software Foundation.
 
11
 
 
12
    This program is distributed in the hope that it will be useful,
 
13
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
    GNU General Public License for more details.
 
16
 
 
17
    You should have received a copy of the GNU General Public License
 
18
    along with this program; if not, write to the Free Software
 
19
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
20
 
 
21
    KSysGuard has been written with some source code and ideas from
 
22
    ktop (<1.0). Early versions of ktop have been written by Bernd
 
23
    Johannes Wuebben <wuebben@math.cornell.edu> and Nicolas Leclercq
 
24
    <nicknet@planete.net>.
 
25
 
 
26
*/
 
27
 
 
28
#include <assert.h>
 
29
#include <ctype.h>
 
30
#include <fcntl.h>
 
31
#include <stdio.h>
 
32
#include <stdlib.h>
 
33
#include <unistd.h>
 
34
 
 
35
#include <kaboutdata.h>
 
36
#include <kaction.h>
 
37
#include <kactioncollection.h>
 
38
#include <kapplication.h>
 
39
#include <kcmdlineargs.h>
 
40
#include <kdebug.h>
 
41
#include <kedittoolbar.h>
 
42
#include <kglobal.h>
 
43
#include <kglobalsettings.h>
 
44
#include <kicon.h>
 
45
#include <klocale.h>
 
46
#include <kmessagebox.h>
 
47
#include <ksgrd/SensorAgent.h>
 
48
#include <ksgrd/SensorManager.h>
 
49
#include <kstatusbar.h>
 
50
#include <kstandardaction.h>
 
51
#include <ktoggleaction.h>
 
52
#include <kurl.h>
 
53
#include <kwindowsystem.h>
 
54
#include <QSplitter>
 
55
 
 
56
#include <kdeversion.h>
 
57
#include "SensorBrowser.h"
 
58
#include "Workspace.h"
 
59
#include "WorkSheet.h"
 
60
#include "StyleEngine.h"
 
61
#include "HostConnector.h"
 
62
#include "ProcessController.h"
 
63
#include "ProcessTable.h"
 
64
#include "processui/ksysguardprocesslist.h"
 
65
 
 
66
#include "ksysguard.h"
 
67
 
 
68
 
 
69
ProcessController *sLocalProcessController = NULL;
 
70
 
 
71
//Comment out to stop ksysguard from forking.  Good for debugging
 
72
//#define FORK_KSYSGUARD
 
73
 
 
74
static const char Description[] = I18N_NOOP( "KDE System Monitor" );
 
75
TopLevel* topLevel;
 
76
 
 
77
TopLevel::TopLevel()
 
78
  : KXmlGuiWindow( NULL, Qt::WindowFlags(KDE_DEFAULT_WINDOWFLAGS) | Qt::WindowContextHelpButtonHint)
 
79
{
 
80
  QDBusConnection::sessionBus().registerObject("/", this, QDBusConnection::ExportScriptableSlots);
 
81
  mTimerId = -1;
 
82
 
 
83
  mSplitter = new QSplitter( this );
 
84
  mSplitter->setOrientation( Qt::Horizontal );
 
85
  mSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() );
 
86
  setCentralWidget( mSplitter );
 
87
 
 
88
  mSensorBrowser = 0;
 
89
 
 
90
  mWorkSpace = new Workspace( mSplitter );
 
91
  connect( mWorkSpace, SIGNAL( setCaption( const QString&) ),
 
92
           SLOT( setCaption( const QString&) ) );
 
93
  connect( mWorkSpace, SIGNAL( currentChanged( int ) ),
 
94
           SLOT( currentTabChanged( int ) ) );
 
95
 
 
96
  sLocalProcessController = new ProcessController( this, NULL);
 
97
  connect( sLocalProcessController, SIGNAL( processListChanged() ), this, SLOT( updateProcessCount()));
 
98
 
 
99
  /* Create the status bar. It displays some information about the
 
100
   * number of processes and the memory consumption of the local
 
101
   * host. */
 
102
  const int STATUSBAR_STRETCH=1;
 
103
 
 
104
  sbProcessCount = new QLabel();
 
105
  statusBar()->addWidget( sbProcessCount, STATUSBAR_STRETCH );
 
106
 
 
107
  sbCpuStat = new QLabel();
 
108
  statusBar()->addWidget( sbCpuStat, STATUSBAR_STRETCH );
 
109
 
 
110
  sbMemTotal = new QLabel();
 
111
  statusBar()->addWidget( sbMemTotal, STATUSBAR_STRETCH );
 
112
 
 
113
  sbSwapTotal = new QLabel();
 
114
  statusBar()->addWidget( sbSwapTotal, STATUSBAR_STRETCH );
 
115
 
 
116
  statusBar()->hide();
 
117
 
 
118
  // create actions for menu entries
 
119
  mRefreshTabAction = KStandardAction::redisplay(mWorkSpace,SLOT( refreshActiveWorksheet() ),actionCollection());
 
120
  mNewWorksheetAction = actionCollection()->addAction("new_worksheet");
 
121
  mNewWorksheetAction->setIcon(KIcon("tab-new"));
 
122
  connect(mNewWorksheetAction, SIGNAL(triggered(bool)), mWorkSpace, SLOT( newWorkSheet() ));
 
123
  mInsertWorksheetAction = actionCollection()->addAction("import_worksheet");
 
124
  mInsertWorksheetAction->setIcon(KIcon("document-open") );
 
125
  connect(mInsertWorksheetAction, SIGNAL(triggered(bool)), mWorkSpace, SLOT( importWorkSheet() ));
 
126
  mTabExportAction = actionCollection()->addAction( "export_worksheet" );
 
127
  mTabExportAction->setIcon( KIcon("document-save-as") );
 
128
  connect(mTabExportAction, SIGNAL(triggered(bool)), mWorkSpace, SLOT( exportWorkSheet() ));
 
129
  mTabRemoveAction = actionCollection()->addAction( "remove_worksheet" );
 
130
  mTabRemoveAction->setIcon( KIcon("tab-close") );
 
131
  connect(mTabRemoveAction, SIGNAL(triggered(bool)), mWorkSpace, SLOT( removeWorkSheet() ));
 
132
  mMonitorRemoteAction = actionCollection()->addAction( "connect_host" );
 
133
  mMonitorRemoteAction->setIcon( KIcon("network-connect") );
 
134
  connect(mMonitorRemoteAction, SIGNAL(triggered(bool)), SLOT( connectHost() ));
 
135
  //knewstuff2 action
 
136
  mHotNewWorksheetAction = actionCollection()->addAction( "get_new_worksheet" );
 
137
  mHotNewWorksheetAction->setIcon( KIcon("network-server") );
 
138
  connect(mHotNewWorksheetAction, SIGNAL(triggered(bool)), mWorkSpace, SLOT( getHotNewWorksheet() ));
 
139
  mHotNewWorksheetUploadAction = actionCollection()->addAction( "upload_worksheet" );
 
140
  mHotNewWorksheetUploadAction->setIcon( KIcon("network-server") );
 
141
  connect(mHotNewWorksheetUploadAction, SIGNAL(triggered(bool)), mWorkSpace, SLOT( uploadHotNewWorksheet() ));
 
142
 
 
143
  mQuitAction = NULL;
 
144
 
 
145
  mConfigureSheetAction = actionCollection()->addAction( "configure_sheet" );
 
146
  mConfigureSheetAction->setIcon( KIcon("configure") );
 
147
  connect(mConfigureSheetAction, SIGNAL(triggered(bool)), SLOT( configureCurrentSheet() ));
 
148
 
 
149
  retranslateUi();
 
150
}
 
151
 
 
152
void TopLevel::retranslateUi()
 
153
{
 
154
  setPlainCaption( i18n( "System Monitor" ) );
 
155
  mRefreshTabAction->setText(i18n("&Refresh Tab"));
 
156
  mNewWorksheetAction->setText(i18n( "&New Tab..." ));
 
157
  mInsertWorksheetAction->setText(i18n( "Import Tab Fr&om File..." ));
 
158
  mTabExportAction->setText( i18n( "Save Tab &As..." ) );
 
159
  mTabRemoveAction->setText( i18n( "&Close Tab" ) );
 
160
  mMonitorRemoteAction->setText( i18n( "Monitor &Remote Machine..." ) );
 
161
  mHotNewWorksheetAction->setText( i18n( "&Download New Tabs..." ) );
 
162
  mHotNewWorksheetUploadAction->setText( i18n( "&Upload Current Tab..." ) );
 
163
 
 
164
  mConfigureSheetAction->setText( i18n( "Tab &Properties" ) );
 
165
  if(mQuitAction) {
 
166
    KAction *tmpQuitAction = KStandardAction::quit( NULL, NULL, NULL );
 
167
    mQuitAction->setText(tmpQuitAction->text());
 
168
    mQuitAction->setWhatsThis(tmpQuitAction->whatsThis());
 
169
    mQuitAction->setToolTip(tmpQuitAction->toolTip());
 
170
    delete tmpQuitAction;
 
171
  } else
 
172
    mQuitAction = KStandardAction::quit( this, SLOT( close() ), actionCollection() );
 
173
}
 
174
 
 
175
void TopLevel::configureCurrentSheet() {
 
176
  mWorkSpace->configure();
 
177
  mRefreshTabAction->setVisible( mWorkSpace->currentWorkSheet()->updateInterval() == 0 );
 
178
}
 
179
void TopLevel::currentTabChanged(int index)
 
180
{
 
181
  QWidget *wdg = mWorkSpace->widget(index);
 
182
  WorkSheet *sheet = (WorkSheet *)(wdg);
 
183
  Q_ASSERT(sheet);
 
184
  bool locked = !sheet || sheet->isLocked();
 
185
  mTabRemoveAction->setVisible(!locked);
 
186
  mTabExportAction->setVisible(!locked);
 
187
  mHotNewWorksheetUploadAction->setVisible(!locked);
 
188
  mMonitorRemoteAction->setVisible(!locked);
 
189
 
 
190
  //only show refresh option is update interval is 0 (manual)
 
191
  mRefreshTabAction->setVisible( sheet->updateInterval() == 0 );
 
192
 
 
193
  if(!locked && !mSensorBrowser) {
 
194
    startSensorBrowserWidget();
 
195
  }
 
196
  if(mSensorBrowser) {
 
197
    if(mSensorBrowser->isVisible() && locked) //going from visible to not visible to save the state
 
198
      mSplitterSize = mSplitter->sizes();
 
199
    mSensorBrowser->setVisible(!locked);
 
200
 
 
201
  }
 
202
}
 
203
void TopLevel::startSensorBrowserWidget()
 
204
{
 
205
  if(mSensorBrowser) return;
 
206
  mSensorBrowser = new SensorBrowserWidget( 0, KSGRD::SensorMgr );
 
207
  mSplitter->insertWidget(2,mSensorBrowser);
 
208
  mSplitter->setSizes( mSplitterSize );
 
209
}
 
210
 
 
211
/*
 
212
 * DBUS Interface functions
 
213
 */
 
214
 
 
215
void TopLevel::showOnCurrentDesktop()
 
216
{
 
217
  KWindowSystem::setOnDesktop( winId(), KWindowSystem::currentDesktop() );
 
218
  kapp->updateUserTimestamp();
 
219
  KWindowSystem::forceActiveWindow( winId() );
 
220
}
 
221
 
 
222
void TopLevel::importWorkSheet( const QString &fileName )
 
223
{
 
224
  mWorkSpace->importWorkSheet( KUrl( fileName ) );
 
225
}
 
226
 
 
227
void TopLevel::removeWorkSheet( const QString &fileName )
 
228
{
 
229
  mWorkSpace->removeWorkSheet( fileName );
 
230
}
 
231
 
 
232
void TopLevel::getHotNewWorksheet()
 
233
{
 
234
  mWorkSpace->getHotNewWorksheet( );
 
235
}
 
236
 
 
237
QStringList TopLevel::listSensors( const QString &hostName )
 
238
{
 
239
  if(!mSensorBrowser) {
 
240
    setUpdatesEnabled(false);
 
241
    startSensorBrowserWidget();
 
242
    mSensorBrowser->setVisible(false);
 
243
    setUpdatesEnabled(true);
 
244
  }
 
245
  return mSensorBrowser->listSensors( hostName );
 
246
}
 
247
 
 
248
QStringList TopLevel::listHosts()
 
249
{
 
250
  if(!mSensorBrowser) {
 
251
    setUpdatesEnabled(false);
 
252
    startSensorBrowserWidget();
 
253
    mSensorBrowser->setVisible(false);
 
254
    setUpdatesEnabled(true);
 
255
  }
 
256
  return mSensorBrowser->listHosts();
 
257
}
 
258
 
 
259
void TopLevel::initStatusBar()
 
260
{
 
261
  KSGRD::SensorMgr->engage( "localhost", "", "ksysguardd" );
 
262
  /* Request info about the swap space size and the units it is
 
263
   * measured in.  The requested info will be received by
 
264
   * answerReceived(). */
 
265
  KSGRD::SensorMgr->sendRequest( "localhost", "mem/swap/used?",
 
266
                                 (KSGRD::SensorClient*)this, 7 );
 
267
 
 
268
  KToggleAction *sb = dynamic_cast<KToggleAction*>(action("options_show_statusbar"));
 
269
  if (sb)
 
270
     connect(sb, SIGNAL(toggled(bool)), this, SLOT(updateStatusBar()));
 
271
  setupGUI(QSize(800,600), ToolBar | Keys | StatusBar | Save | Create);
 
272
 
 
273
  updateStatusBar();
 
274
}
 
275
 
 
276
void TopLevel::updateStatusBar()
 
277
{
 
278
  if ( mTimerId == -1 )
 
279
    mTimerId = startTimer( 2000 );
 
280
 
 
281
  // call timerEvent to fill the status bar with real values
 
282
  timerEvent( 0 );
 
283
}
 
284
 
 
285
void TopLevel::connectHost()
 
286
{
 
287
  HostConnector hostConnector( this );
 
288
 
 
289
//  hostConnector.setHostNames( mHostList );
 
290
//  hostConnector.setCommands( mCommandList );
 
291
 
 
292
//  hostConnector.setCurrentHostName( "" );
 
293
 
 
294
  if ( !hostConnector.exec() )
 
295
    return;
 
296
 
 
297
//  mHostList = hostConnector.hostNames();
 
298
//  mCommandList = hostConnector.commands();
 
299
 
 
300
  QString shell = "";
 
301
  QString command = "";
 
302
  int port = -1;
 
303
 
 
304
  /* Check which radio button is selected and set parameters
 
305
   * appropriately. */
 
306
  if ( hostConnector.useSsh() )
 
307
    shell = "ssh";
 
308
  else if ( hostConnector.useRsh() )
 
309
    shell = "rsh";
 
310
  else if ( hostConnector.useDaemon() )
 
311
    port = hostConnector.port();
 
312
  else
 
313
    command = hostConnector.currentCommand();
 
314
 
 
315
  KSGRD::SensorMgr->engage( hostConnector.currentHostName(), shell, command, port );
 
316
}
 
317
 
 
318
void TopLevel::disconnectHost()
 
319
{
 
320
  if(mSensorBrowser)
 
321
    mSensorBrowser->disconnect();
 
322
}
 
323
 
 
324
bool TopLevel::event( QEvent *e )
 
325
{
 
326
  if ( e->type() == QEvent::User ) {
 
327
    /* Due to the asynchronous communication between ksysguard and its
 
328
     * back-ends, we sometimes need to show message boxes that were
 
329
     * triggered by objects that have died already. */
 
330
    KMessageBox::error( this, static_cast<KSGRD::SensorManager::MessageEvent*>(e)->message() );
 
331
 
 
332
    return true;
 
333
  }
 
334
 
 
335
  return KXmlGuiWindow::event( e );
 
336
}
 
337
 
 
338
void TopLevel::timerEvent( QTimerEvent* )
 
339
{
 
340
  if ( statusBar()->isVisibleTo( this ) ) {
 
341
    /* Request some info about the memory status. The requested
 
342
     * information will be received by answerReceived(). */
 
343
    KSGRD::SensorMgr->sendRequest( "localhost", "cpu/idle",
 
344
                                   (KSGRD::SensorClient*)this, 1 );
 
345
    KSGRD::SensorMgr->sendRequest( "localhost", "mem/physical/free",
 
346
                                   (KSGRD::SensorClient*)this, 2 );
 
347
    KSGRD::SensorMgr->sendRequest( "localhost", "mem/physical/used",
 
348
                                   (KSGRD::SensorClient*)this, 3 );
 
349
    KSGRD::SensorMgr->sendRequest( "localhost", "mem/physical/application",
 
350
                                   (KSGRD::SensorClient*)this, 4 );
 
351
    KSGRD::SensorMgr->sendRequest( "localhost", "mem/swap/free",
 
352
                                   (KSGRD::SensorClient*)this, 5 );
 
353
    KSGRD::SensorMgr->sendRequest( "localhost", "mem/swap/used",
 
354
                                   (KSGRD::SensorClient*)this, 6 );
 
355
  }
 
356
}
 
357
 
 
358
void TopLevel::updateProcessCount()  {
 
359
    QString s = i18np( "1 process" "\xc2\x9c" "1", "%1 processes" "\xc2\x9c" "%1", sLocalProcessController->processList()->visibleProcessesCount() );
 
360
    sbProcessCount->setText( s );
 
361
}
 
362
void TopLevel::changeEvent( QEvent * event )
 
363
{
 
364
  if (event->type() == QEvent::LanguageChange) {
 
365
    KSGRD::SensorMgr->retranslate();
 
366
    setUpdatesEnabled(false);
 
367
    setupGUI(ToolBar | Keys | StatusBar | Create);
 
368
    retranslateUi();
 
369
    setUpdatesEnabled(true);
 
370
  }
 
371
  KXmlGuiWindow::changeEvent(event);
 
372
}
 
373
 
 
374
bool TopLevel::queryClose()
 
375
{
 
376
  if ( !mWorkSpace->saveOnQuit() )
 
377
    return false;
 
378
 
 
379
  KConfigGroup cg( KGlobal::config(), "MainWindow" );
 
380
  saveProperties( cg );
 
381
  KGlobal::config()->sync();
 
382
 
 
383
  return true;
 
384
}
 
385
 
 
386
void TopLevel::readProperties( const KConfigGroup& cfg )
 
387
{
 
388
 
 
389
  /* we can ignore 'isMaximized' because we can't set the window
 
390
     maximized, so we save the coordinates instead */
 
391
//  if ( cfg.readEntry( "isMinimized" , false) == true )
 
392
//    showMinimized();
 
393
 
 
394
  mSplitterSize = cfg.readEntry( "SplitterSizeList",QList<int>() );
 
395
  if ( mSplitterSize.isEmpty() ) {
 
396
    // start with a 30/70 ratio
 
397
    mSplitterSize.append( 10 );
 
398
    mSplitterSize.append( 90 );
 
399
  }
 
400
 
 
401
  KSGRD::SensorMgr->readProperties( cfg );
 
402
  KSGRD::Style->readProperties( cfg );
 
403
 
 
404
  mWorkSpace->readProperties( cfg );
 
405
 
 
406
  QList<WorkSheet *> workSheets = mWorkSpace->getWorkSheets();
 
407
  for(int i = 0; i < sLocalProcessController->actions().size(); i++) {
 
408
    actionCollection()->addAction("processAction" + QString::number(i), sLocalProcessController->actions().at(i));
 
409
  }
 
410
}
 
411
 
 
412
void TopLevel::saveProperties( KConfigGroup& cfg )
 
413
{
 
414
  cfg.writeEntry( "isMinimized", isMinimized() );
 
415
 
 
416
  if(mSensorBrowser && mSensorBrowser->isVisible())
 
417
    cfg.writeEntry( "SplitterSizeList",  mSplitter->sizes());
 
418
  else if(mSplitterSize.size() == 2 && mSplitterSize.value(0) != 0 && mSplitterSize.value(1) != 0)
 
419
    cfg.writeEntry( "SplitterSizeList", mSplitterSize );
 
420
 
 
421
  KSGRD::Style->saveProperties( cfg );
 
422
  KSGRD::SensorMgr->saveProperties( cfg );
 
423
 
 
424
  saveMainWindowSettings( cfg );
 
425
  mWorkSpace->saveProperties( cfg );
 
426
}
 
427
 
 
428
void TopLevel::answerReceived( int id, const QList<QByteArray> &answerList )
 
429
{
 
430
  // we have received an answer from the daemon.
 
431
  QByteArray answer;
 
432
  if(!answerList.isEmpty()) answer = answerList[0];
 
433
  QString s;
 
434
  static QString unit;
 
435
  static qlonglong mFree = 0;
 
436
  static qlonglong mUsedApplication = 0;
 
437
  static qlonglong mUsedTotal = 0;
 
438
  static qlonglong sUsed = 0;
 
439
  static qlonglong sFree = 0;
 
440
 
 
441
  switch ( id ) {
 
442
    case 1:
 
443
      s = i18n( "CPU: %1%\xc2\x9c%1%", (int) (100 - answer.toFloat()) );
 
444
      sbCpuStat->setText( s );
 
445
      break;
 
446
 
 
447
    case 2:
 
448
      mFree = answer.toLongLong();
 
449
      break;
 
450
 
 
451
    case 3:
 
452
      mUsedTotal = answer.toLongLong();
 
453
      break;
 
454
 
 
455
    case 4:
 
456
      mUsedApplication = answer.toLongLong();
 
457
      //Use a multi-length string
 
458
      s = i18nc( "Arguments are formatted byte sizes (used/total)", "Memory: %1 / %2" "\xc2\x9c" "Mem: %1 / %2" "\xc2\x9c" "Mem: %1" "\xc2\x9c" "%1",
 
459
                 KGlobal::locale()->formatByteSize( mUsedApplication*1024),
 
460
                 KGlobal::locale()->formatByteSize( (mFree+mUsedTotal)*1024 ) );
 
461
      sbMemTotal->setText( s );
 
462
      break;
 
463
 
 
464
    case 5:
 
465
      sFree = answer.toLongLong();
 
466
      break;
 
467
 
 
468
    case 6:
 
469
      sUsed = answer.toLongLong();
 
470
      setSwapInfo( sUsed, sFree, unit );
 
471
      break;
 
472
 
 
473
    case 7: {
 
474
      KSGRD::SensorIntegerInfo info( answer );
 
475
      unit = KSGRD::SensorMgr->translateUnit( info.unit() );
 
476
      break;
 
477
    }
 
478
  }
 
479
}
 
480
 
 
481
void TopLevel::setSwapInfo( qlonglong used, qlonglong free, const QString & )
 
482
{
 
483
  QString msg;
 
484
  if ( used == 0 && free == 0 ) // no swap available
 
485
    msg = i18n( " No swap space available " );
 
486
  else {
 
487
    msg = i18nc( "Arguments are formatted byte sizes (used/total)", "Swap: %1 / %2" "\xc2\x9c" "Swap: %1" "\xc2\x9c" "%1" ,
 
488
                 KGlobal::locale()->formatByteSize( used*1024 ),
 
489
                 KGlobal::locale()->formatByteSize( (free+used)*1024) );
 
490
  }
 
491
 
 
492
  sbSwapTotal->setText( msg );
 
493
}
 
494
 
 
495
/*
 
496
 * Once upon a time...
 
497
 */
 
498
extern "C" KDE_EXPORT int kdemain( int argc, char** argv )
 
499
{
 
500
  // initpipe is used to keep the parent process around till the child
 
501
  // has registered with dbus
 
502
#ifdef FORK_KSYSGUARD
 
503
  int initpipe[ 2 ];
 
504
  pipe( initpipe );
 
505
  /* This forking will put ksysguard in it's own session not having a
 
506
   * controlling terminal attached to it. This prevents ssh from
 
507
   * using this terminal for password requests. Thus, you
 
508
   * need a ssh with ssh-askpass support to popup an X dialog to
 
509
   * enter the password. */
 
510
  pid_t pid;
 
511
  if ( ( pid = fork() ) < 0 )
 
512
    return -1;
 
513
  else
 
514
    if ( pid != 0 ) {
 
515
      close( initpipe[ 1 ] );
 
516
 
 
517
      // wait till init is complete
 
518
      char c;
 
519
      while( read( initpipe[ 0 ], &c, 1 ) < 0 );
 
520
 
 
521
      // then exit
 
522
      close( initpipe[ 0 ] );
 
523
      exit( 0 );
 
524
    }
 
525
 
 
526
  close( initpipe[ 0 ] );
 
527
  setsid();
 
528
#endif
 
529
 
 
530
  KAboutData aboutData( "ksysguard", 0, ki18n( "System Monitor" ),
 
531
                        KDE_VERSION_STRING, ki18n(Description), KAboutData::License_GPL,
 
532
                        ki18n( "(c) 1996-2008 The KDE System Monitor Developers" ) );
 
533
  aboutData.addAuthor( ki18n("John Tapsell"), ki18n("Current Maintainer"), "john.tapsell@kde.org" );
 
534
  aboutData.addAuthor( ki18n("Chris Schlaeger"), ki18n("Previous Maintainer"), "cs@kde.org" );
 
535
  aboutData.addAuthor( ki18n("Greg Martyn"), KLocalizedString(), "greg.martyn@gmail.com" );
 
536
  aboutData.addAuthor( ki18n("Tobias Koenig"), KLocalizedString(), "tokoe@kde.org" );
 
537
  aboutData.addAuthor( ki18n("Nicolas Leclercq"), KLocalizedString(), "nicknet@planete.net" );
 
538
  aboutData.addAuthor( ki18n("Alex Sanda"), KLocalizedString(), "alex@darkstart.ping.at" );
 
539
  aboutData.addAuthor( ki18n("Bernd Johannes Wuebben"), KLocalizedString(), "wuebben@math.cornell.edu" );
 
540
  aboutData.addAuthor( ki18n("Ralf Mueller"), KLocalizedString(), "rlaf@bj-ig.de" );
 
541
  aboutData.addAuthor( ki18n("Hamish Rodda"), KLocalizedString(), "rodda@kde.org" );
 
542
  aboutData.addAuthor( ki18n("Torsten Kasch"), ki18n( "Solaris Support\n"
 
543
                       "Parts derived (by permission) from the sunos5\n"
 
544
                       "module of William LeFebvre's \"top\" utility." ),
 
545
                       "tk@Genetik.Uni-Bielefeld.DE" );
 
546
  aboutData.setProgramIconName("utilities-system-monitor");
 
547
 
 
548
  KCmdLineArgs::init( argc, argv, &aboutData );
 
549
 
 
550
  KCmdLineOptions options;
 
551
  options.add("+[worksheet]", ki18n( "Optional worksheet files to load" ));
 
552
  KCmdLineArgs::addCmdLineOptions( options );
 
553
  // initialize KDE application
 
554
  KApplication *app = new KApplication;
 
555
 
 
556
  KSGRD::SensorMgr = new KSGRD::SensorManager();
 
557
  KSGRD::Style = new KSGRD::StyleEngine();
 
558
 
 
559
#ifdef FORK_KSYSGUARD
 
560
  char c = 0;
 
561
  write( initpipe[ 1 ], &c, 1 );
 
562
  close( initpipe[ 1 ] );
 
563
#endif
 
564
  topLevel = new TopLevel();
 
565
 
 
566
 
 
567
  // create top-level widget
 
568
  topLevel->readProperties( KConfigGroup( KGlobal::config(), "MainWindow" ) );
 
569
  // setup the statusbar, toolbar etc.
 
570
  // Note that this comes after creating the top-level widgets whcih also 
 
571
  // sets up the various QActions that the user may have added to the toolbar
 
572
  topLevel->initStatusBar();
 
573
 
 
574
  //There seems to be some serious bugs with the session restore code.  Disabling
 
575
//  if ( app->isSessionRestored() )
 
576
//    topLevel->restore( 1 );
 
577
 
 
578
  topLevel->show();
 
579
  KSGRD::SensorMgr->setBroadcaster( topLevel );  // SensorMgr uses a QPointer for toplevel, so it is okay if topLevel is deleted first
 
580
 
 
581
  // run the application
 
582
  int result = app->exec();
 
583
 
 
584
  delete app;
 
585
  delete KSGRD::SensorMgr;
 
586
  delete KSGRD::Style;
 
587
 
 
588
  return result;
 
589
}
 
590
 
 
591
#include "ksysguard.moc"