add more spacing
[personal-kdebase.git] / workspace / ksysguard / gui / WorkSheet.cc
blobd24f1e983bdf6c1e377e153ddef96da30f3fb380
1 /*
2 KSysGuard, the KDE System Guard
4 Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public
8 License version 2 or at your option version 3 as published by
9 the Free Software Foundation.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <QClipboard>
23 #include <QCursor>
24 #include <QLayout>
25 #include <QTextStream>
26 #include <QGridLayout>
27 #include <QEvent>
28 #include <QDropEvent>
29 #include <QDragEnterEvent>
30 #include <QFile>
31 #include <QByteArray>
32 #include <QApplication>
34 #include <kdebug.h>
35 #include <klocale.h>
36 #include <kmessagebox.h>
37 #include <kmenu.h>
39 #include <SensorManager.h>
41 #include "DancingBars.h"
42 #include "DummyDisplay.h"
43 #include "FancyPlotter.h"
44 #include "ListView.h"
45 #include "LogFile.h"
46 #include "MultiMeter.h"
47 #include "ProcessController.h"
48 #include "SensorLogger.h"
49 #include "WorkSheet.h"
50 #include "WorkSheetSettings.h"
52 WorkSheet::WorkSheet( QWidget *parent )
53 : QWidget( parent )
55 mGridLayout = 0;
56 mRows = mColumns = 0;
57 mDisplayList = 0;
58 mFileName = "";
59 mLocalProcessController = NULL;
60 setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
61 setAcceptDrops( true );
64 WorkSheet::WorkSheet( uint rows, uint columns, float interval, QWidget* parent )
65 : QWidget( parent)
67 mRows = mColumns = 0;
68 mGridLayout = 0;
69 mDisplayList = 0;
70 setUpdateInterval( interval );
71 mFileName = "";
73 createGrid( rows, columns );
75 // Initialize worksheet with dummy displays.
76 for ( uint r = 0; r < mRows; ++r )
77 for ( uint c = 0; c < mColumns; ++c )
78 replaceDisplay( r, c );
80 mGridLayout->activate();
82 setAcceptDrops( true );
85 WorkSheet::~WorkSheet()
87 for ( int r = 0; r < mRows; ++r ) {
88 for ( int c = 0; c < mColumns; ++c )
89 delete mDisplayList[ r ][ c ];
90 delete mDisplayList[ r ];
92 delete [] mDisplayList;
95 bool WorkSheet::load( const QString &fileName )
97 QFile file( fileName );
98 if ( !file.open( QIODevice::ReadOnly ) ) {
99 KMessageBox::sorry( this, i18n( "Cannot open the file %1." , fileName ) );
100 return false;
103 QDomDocument doc;
105 // Read in file and check for a valid XML header.
106 if ( !doc.setContent( &file) ) {
107 KMessageBox::sorry( this, i18n( "The file %1 does not contain valid XML." ,
108 fileName ) );
109 return false;
112 // Check for proper document type.
113 if ( doc.doctype().name() != "KSysGuardWorkSheet" ) {
114 KMessageBox::sorry( this, i18n( "The file %1 does not contain a valid worksheet "
115 "definition, which must have a document type 'KSysGuardWorkSheet'.",
116 fileName ) );
117 return false;
120 // Check for proper size.
121 QDomElement element = doc.documentElement();
122 float interval = element.attribute( "interval", "0.5" ).toFloat();
123 if( interval <0.01 || interval > 100000 ) //make sure the interval is fairly sane
124 interval = 0.5;
126 setUpdateInterval(interval);
128 mTitle = element.attribute( "title");
129 mTranslatedTitle = mTitle.isEmpty() ? "" : i18n(mTitle.toUtf8());
130 bool ok;
131 mSharedSettings.locked = element.attribute( "locked" ).toUInt( &ok );
132 if(!ok) mSharedSettings.locked = false;
134 bool rowsOk, columnsOk;
135 uint rows = element.attribute( "rows" ).toUInt( &rowsOk );
136 uint columns = element.attribute( "columns" ).toUInt( &columnsOk );
137 if ( !( rowsOk && columnsOk ) ) {
138 KMessageBox::sorry( this, i18n("The file %1 has an invalid worksheet size.",
139 fileName ) );
140 return false;
143 createGrid( rows, columns );
145 int i;
146 /* Load lists of hosts that are needed for the work sheet and try
147 * to establish a connection. */
148 QDomNodeList dnList = element.elementsByTagName( "host" );
149 for ( i = 0; i < dnList.count(); ++i ) {
150 QDomElement element = dnList.item( i ).toElement();
151 bool ok;
152 int port = element.attribute( "port" ).toInt( &ok );
153 if ( !ok )
154 port = -1;
155 KSGRD::SensorMgr->engage( element.attribute( "name" ),
156 element.attribute( "shell" ),
157 element.attribute( "command" ), port );
159 //if no hosts are specified, at least connect to localhost
160 if(dnList.count() == 0)
161 KSGRD::SensorMgr->engage( "localhost", "", "ksysguardd", -1);
163 // Load the displays and place them into the work sheet.
164 dnList = element.elementsByTagName( "display" );
165 for ( i = 0; i < dnList.count(); ++i ) {
166 QDomElement element = dnList.item( i ).toElement();
167 uint row = element.attribute( "row" ).toUInt();
168 uint column = element.attribute( "column" ).toUInt();
169 if ( row >= mRows || column >= mColumns) {
170 kDebug(1215) << "Row or Column out of range (" << row << ", "
171 << column << ")" << endl;
172 return false;
174 replaceDisplay( row, column, element );
177 // Fill empty cells with dummy displays
178 for ( uint r = 0; r < mRows; ++r )
179 for ( uint c = 0; c < mColumns; ++c )
180 if ( !mDisplayList[ r ][ c ] )
181 replaceDisplay( r, c );
183 return true;
186 bool WorkSheet::save( const QString &fileName )
188 return exportWorkSheet(fileName);
191 bool WorkSheet::exportWorkSheet( const QString &fileName )
193 QDomDocument doc( "KSysGuardWorkSheet" );
194 doc.appendChild( doc.createProcessingInstruction(
195 "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
197 // save work sheet information
198 QDomElement ws = doc.createElement( "WorkSheet" );
199 doc.appendChild( ws );
200 ws.setAttribute( "title", mTitle );
201 ws.setAttribute( "locked", mSharedSettings.locked?"1":"0" );
202 ws.setAttribute( "interval", updateInterval() );
203 ws.setAttribute( "rows", mRows );
204 ws.setAttribute( "columns", mColumns );
206 QStringList hosts;
207 collectHosts( hosts );
209 // save host information (name, shell, etc.)
210 QStringList::Iterator it;
211 for ( it = hosts.begin(); it != hosts.end(); ++it ) {
212 QString shell, command;
213 int port;
215 if ( KSGRD::SensorMgr->hostInfo( *it, shell, command, port ) ) {
216 QDomElement host = doc.createElement( "host" );
217 ws.appendChild( host );
218 host.setAttribute( "name", *it );
219 host.setAttribute( "shell", shell );
220 host.setAttribute( "command", command );
221 host.setAttribute( "port", port );
225 for ( uint r = 0; r < mRows; ++r )
226 for (uint c = 0; c < mColumns; ++c )
227 if ( QByteArray("DummyDisplay") != mDisplayList[ r ][ c ]->metaObject()->className()) {
228 KSGRD::SensorDisplay* display = (KSGRD::SensorDisplay*)mDisplayList[ r ][ c ];
229 QDomElement element = doc.createElement( "display" );
230 ws.appendChild( element );
231 element.setAttribute( "row", r );
232 element.setAttribute( "column", c );
233 element.setAttribute( "class", display->metaObject()->className() );
235 display->saveSettings( doc, element );
238 QFile file( fileName );
239 if ( !file.open( QIODevice::WriteOnly ) ) {
240 KMessageBox::sorry( this, i18n( "Cannot save file %1" , fileName ) );
241 return false;
244 QTextStream s( &file );
245 s.setCodec( "UTF-8" );
246 s << doc;
247 file.close();
249 return true;
252 void WorkSheet::cut()
254 if ( !currentDisplay() || currentDisplay()->metaObject()->className() == QByteArray("DummyDisplay" ) )
255 return;
257 QClipboard* clip = QApplication::clipboard();
259 clip->setText( currentDisplayAsXML() );
261 removeDisplay( currentDisplay() );
264 void WorkSheet::copy()
266 if ( !currentDisplay() || currentDisplay()->metaObject()->className() == QByteArray( "DummyDisplay" ) )
267 return;
269 QClipboard* clip = QApplication::clipboard();
271 clip->setText( currentDisplayAsXML() );
274 void WorkSheet::paste()
276 uint row, column;
277 if ( !currentDisplay( &row, &column ) )
278 return;
280 QClipboard* clip = QApplication::clipboard();
282 QDomDocument doc;
283 /* Get text from clipboard and check for a valid XML header and
284 * proper document type. */
285 if ( !doc.setContent( clip->text() ) || doc.doctype().name() != "KSysGuardDisplay" ) {
286 KMessageBox::sorry( this, i18n("The clipboard does not contain a valid display "
287 "description." ) );
288 return;
291 QDomElement element = doc.documentElement();
292 replaceDisplay( row, column, element );
295 void WorkSheet::setFileName( const QString &fileName )
297 mFileName = fileName;
300 QString WorkSheet::fileName() const
302 return mFileName;
305 void WorkSheet::setTitle( const QString &title )
307 mTitle = title;
308 mTranslatedTitle = mTitle.isEmpty() ? "" : i18n(mTitle.toUtf8());
309 emit titleChanged(this);
312 QString WorkSheet::translatedTitle() const {
313 return mTranslatedTitle;
316 QString WorkSheet::title() const {
317 return mTitle;
320 KSGRD::SensorDisplay *WorkSheet::addDisplay( const QString &hostName,
321 const QString &sensorName,
322 const QString &sensorType,
323 const QString& sensorDescr,
324 uint row, uint column )
327 /* If the by 'row' and 'column' specified display is a QGroupBox dummy
328 * display we replace the widget. Otherwise we just try to add
329 * the new sensor to an existing display. */
330 if ( mDisplayList[ row ][ column ]->metaObject()->className() == QByteArray( "DummyDisplay" ) ) {
331 KSGRD::SensorDisplay* newDisplay = 0;
332 /* If the sensor type is supported by more than one display
333 * type we popup a menu so the user can select what display is
334 * wanted. */
335 if ( sensorType == "integer" || sensorType == "float" ) {
336 KMenu pm;
337 pm.addTitle( i18n( "Select Display Type" ) );
338 QAction *a1 = pm.addAction( i18n( "&Line graph" ) );
339 QAction *a2 = pm.addAction( i18n( "&Digital display" ) );
340 QAction *a3 = pm.addAction( i18n( "&Bar graph" ) );
341 QAction *a4 = pm.addAction( i18n( "Log to a &file" ) );
342 QAction *execed = pm.exec( QCursor::pos() );
343 if (execed == a1) {
344 newDisplay = new FancyPlotter( this, sensorDescr, &mSharedSettings );
346 else if (execed == a2) {
347 newDisplay = new MultiMeter( this, sensorDescr, &mSharedSettings);
349 else if (execed == a3) {
350 newDisplay = new DancingBars( this, sensorDescr, &mSharedSettings);
352 else if (execed == a4) {
353 newDisplay = new SensorLogger( this, sensorDescr, &mSharedSettings);
355 else {
356 return 0;
358 } else if ( sensorType == "listview" ) {
359 newDisplay = new ListView( this, sensorDescr, &mSharedSettings);
361 else if ( sensorType == "logfile" ) {
362 newDisplay = new LogFile( this, sensorDescr, &mSharedSettings );
364 else if ( sensorType == "sensorlogger" ) {
365 newDisplay = new SensorLogger( this, sensorDescr, &mSharedSettings );
367 else if ( sensorType == "table" ) {
368 if(!mLocalProcessController && (hostName.isEmpty() || hostName == "localhost")) {
369 mLocalProcessController = new ProcessController( this, sensorDescr, &mSharedSettings);
370 newDisplay = mLocalProcessController;
371 } else
372 newDisplay = new ProcessController( this, sensorDescr, &mSharedSettings);
374 else {
375 kDebug(1215) << "Unknown sensor type: " << sensorType;
376 return 0;
379 newDisplay->applyStyle();
381 connect(&mTimer, SIGNAL( timeout()), newDisplay, SLOT( timerTick()));
382 replaceDisplay( row, column, newDisplay );
385 mDisplayList[ row ][ column ]->addSensor( hostName, sensorName, sensorType, sensorDescr );
387 return ((KSGRD::SensorDisplay*)mDisplayList[ row ][ column ] );
390 void WorkSheet::settings()
392 WorkSheetSettings dlg( this, mSharedSettings.locked );
393 dlg.setSheetTitle( mTranslatedTitle );
394 dlg.setInterval( updateInterval() );
396 if(!mSharedSettings.locked) {
397 dlg.setRows( mRows );
398 dlg.setColumns( mColumns );
401 if ( dlg.exec() ) {
402 setUpdateInterval( dlg.interval() );
404 if (!mSharedSettings.locked)
405 resizeGrid( dlg.rows(), dlg.columns() );
407 if(mTranslatedTitle != dlg.sheetTitle()) { //Title has changed
408 if(mRows == 1 && mColumns ==1) {
409 mDisplayList[ 0 ][ 0 ]->setTitle(dlg.sheetTitle());
410 } else {
411 setTitle(dlg.sheetTitle());
417 void WorkSheet::showPopupMenu( KSGRD::SensorDisplay *display )
419 display->configureSettings();
422 void WorkSheet::applyStyle()
424 for ( uint r = 0; r < mRows; ++r )
425 for (uint c = 0; c < mColumns; ++c )
426 mDisplayList[ r ][ c ]->applyStyle();
429 void WorkSheet::dragEnterEvent( QDragEnterEvent* event)
431 if ( !event->mimeData()->hasFormat("application/x-ksysguard") )
432 return;
433 event->accept();
435 void WorkSheet::dragMoveEvent( QDragMoveEvent *event )
438 /* Find the sensor display that is supposed to get the drop
439 * event and replace or add sensor. */
440 const QPoint globalPos = mapToGlobal( event->pos() );
441 for ( uint r = 0; r < mRows; ++r ) {
442 for ( uint c = 0; c < mColumns; ++c ) {
443 const QSize displaySize = mDisplayList[ r ][ c ]->size();
445 const QPoint displayPoint( displaySize.width(), displaySize.height() );
447 const QRect widgetRect = QRect( mDisplayList[ r ][ c ]->mapToGlobal( QPoint( 0, 0 ) ),
448 mDisplayList[ r ][ c ]->mapToGlobal( displayPoint ) );
451 if ( widgetRect.contains( globalPos ) ) {
452 QByteArray widgetType = mDisplayList[ r ][ c ]->metaObject()->className();
453 if(widgetType == "MultiMeter" || widgetType == "ProcessController" || widgetType == "table")
454 event->ignore(widgetRect);
455 else if(widgetType != "Dumm")
456 event->accept(widgetRect);
457 return;
463 void WorkSheet::dropEvent( QDropEvent *event )
465 if ( !event->mimeData()->hasFormat("application/x-ksysguard") )
466 return;
468 const QString dragObject = QString::fromUtf8(event->mimeData()->data("application/x-ksysguard"));
470 // The host name, sensor name and type are separated by a ' '.
471 QStringList parts = dragObject.split( ' ');
473 QString hostName = parts[ 0 ];
474 QString sensorName = parts[ 1 ];
475 QString sensorType = parts[ 2 ];
476 QString sensorDescr = parts[ 3 ];
478 if ( hostName.isEmpty() || sensorName.isEmpty() || sensorType.isEmpty() )
479 return;
481 /* Find the sensor display that is supposed to get the drop
482 * event and replace or add sensor. */
483 const QPoint globalPos = mapToGlobal( event->pos() );
484 for ( uint r = 0; r < mRows; ++r ) {
485 for ( uint c = 0; c < mColumns; ++c ) {
486 const QSize displaySize = mDisplayList[ r ][ c ]->size();
488 const QPoint displayPoint( displaySize.width(), displaySize.height() );
490 const QRect widgetRect = QRect( mDisplayList[ r ][ c ]->mapToGlobal( QPoint( 0, 0 ) ),
491 mDisplayList[ r ][ c ]->mapToGlobal( displayPoint ) );
494 if ( widgetRect.contains( globalPos ) ) {
495 addDisplay( hostName, sensorName, sensorType, sensorDescr, r, c );
496 return;
502 QSize WorkSheet::sizeHint() const
504 return QSize( 800,600 );
507 bool WorkSheet::event( QEvent *e )
509 if ( e->type() == QEvent::User ) {
510 // SensorDisplays send out this event if they want to be removed.
511 if ( KMessageBox::warningContinueCancel( this, i18n( "Do you really want to delete the display?" ),
512 i18n("Delete Display"), KStandardGuiItem::del() )
513 == KMessageBox::Continue ) {
514 KSGRD::SensorDisplay::DeleteEvent *event = static_cast<KSGRD::SensorDisplay::DeleteEvent*>( e );
515 removeDisplay( event->display() );
517 return true;
521 return QWidget::event( e );
524 bool WorkSheet::replaceDisplay( uint row, uint column, QDomElement& element )
526 QString classType = element.attribute( "class" );
527 KSGRD::SensorDisplay* newDisplay = 0;
530 if ( classType == "FancyPlotter" ) {
531 newDisplay = new FancyPlotter( 0, i18n("Dummy"), &mSharedSettings );
533 else if ( classType == "MultiMeter" )
534 newDisplay = new MultiMeter( 0, i18n("Dummy"), &mSharedSettings );
535 else if ( classType == "DancingBars" )
536 newDisplay = new DancingBars( 0, i18n("Dummy"), &mSharedSettings );
537 else if ( classType == "ListView" )
538 newDisplay = new ListView( 0, i18n("Dummy"), &mSharedSettings );
539 else if ( classType == "LogFile" )
540 newDisplay = new LogFile( 0, i18n("Dummy"), &mSharedSettings );
541 else if ( classType == "SensorLogger" )
542 newDisplay = new SensorLogger( 0, i18n("Dummy"), &mSharedSettings );
543 else if ( classType == "ProcessController" ) {
544 if(!mLocalProcessController) {
545 kDebug() << "Found process controller";
546 mLocalProcessController = new ProcessController( 0, i18n("Dummy"), &mSharedSettings);
547 newDisplay = mLocalProcessController;
549 } else {
550 kDebug(1215) << "Unknown class " << classType;
551 return false;
554 connect(&mTimer, SIGNAL( timeout()), newDisplay, SLOT( timerTick()));
556 // load display specific settings
557 if ( !newDisplay->restoreSettings( element ) )
558 return false;
560 replaceDisplay( row, column, newDisplay );
562 return true;
566 void WorkSheet::replaceDisplay( uint row, uint column, KSGRD::SensorDisplay* newDisplay )
568 // remove the old display && sensor frame at this location
569 if ( mDisplayList[ row ][ column ] ) {
570 if(mDisplayList[ row ][ column ] == mLocalProcessController)
571 mLocalProcessController = NULL;
572 if ( qstrcmp( mDisplayList[ row ][ column ]->parent()->metaObject()->className(), "SensorFrame" ) == 0 ) {
573 delete mDisplayList[ row ][ column ]->parent(); // destroys the child (display) as well
574 } else {
575 delete mDisplayList[ row ][ column ];
579 // insert new display
580 if ( !newDisplay ) {
581 newDisplay = new DummyDisplay( this, &mSharedSettings );
582 mDisplayList[ row ][ column ] = newDisplay;
583 } else {
584 mDisplayList[ row ][ column ] = newDisplay;
585 connect( newDisplay, SIGNAL( showPopupMenu( KSGRD::SensorDisplay* ) ),
586 SLOT( showPopupMenu( KSGRD::SensorDisplay* ) ) );
587 newDisplay->setDeleteNotifier( this );
590 mGridLayout->addWidget( mDisplayList[ row ][ column ], row, column );
591 if(mRows == 1 && mColumns == 1) { //if there's only item, the tab's title should be the widget's title
592 connect( newDisplay, SIGNAL(titleChanged(const QString&)), SLOT(setTitle(const QString&)));
593 setTitle(newDisplay->title());
595 if ( isVisible() ) {
596 mDisplayList[ row ][ column ]->show();
600 void WorkSheet::removeDisplay( KSGRD::SensorDisplay *display )
602 if ( !display )
603 return;
605 if(display == mLocalProcessController)
606 mLocalProcessController = NULL;
608 for ( uint r = 0; r < mRows; ++r )
609 for ( uint c = 0; c < mColumns; ++c )
610 if ( mDisplayList[ r ][ c ] == display ) {
611 replaceDisplay( r, c );
612 return;
616 void WorkSheet::collectHosts( QStringList &list )
618 for ( uint r = 0; r < mRows; ++r )
619 for ( uint c = 0; c < mColumns; ++c )
620 if ( mDisplayList[ r ][ c ]->metaObject()->className() != QByteArray( "DummyDisplay" ) )
621 ((KSGRD::SensorDisplay*)mDisplayList[ r ][ c ])->hosts( list );
624 void WorkSheet::createGrid( uint rows, uint columns )
626 mRows = rows;
627 mColumns = columns;
629 // create grid layout with specified dimensions
630 mGridLayout = new QGridLayout( this );
631 mGridLayout->setSpacing( 5 );
633 mDisplayList = new KSGRD::SensorDisplay**[ mRows ];
634 for ( uint r = 0; r < mRows; ++r ) {
635 mDisplayList[ r ] = new KSGRD::SensorDisplay*[ mColumns ];
636 for ( uint c = 0; c < mColumns; ++c )
637 mDisplayList[ r ][ c ] = 0;
640 /* set stretch factors for rows and columns */
641 for ( uint r = 0; r < mRows; ++r )
642 mGridLayout->setRowStretch( r, 100 );
643 for ( uint c = 0; c < mColumns; ++c )
644 mGridLayout->setColumnStretch( c, 100 );
647 void WorkSheet::resizeGrid( uint newRows, uint newColumns )
649 uint r, c;
651 /* Create new array for display pointers */
652 KSGRD::SensorDisplay*** newDisplayList = new KSGRD::SensorDisplay**[ newRows ];
653 for ( r = 0; r < newRows; ++r ) {
654 newDisplayList[ r ] = new KSGRD::SensorDisplay*[ newColumns ];
655 for ( c = 0; c < newColumns; ++c ) {
656 if ( c < mColumns && r < mRows )
657 newDisplayList[ r ][ c ] = mDisplayList[ r ][ c ];
658 else
659 newDisplayList[ r ][ c ] = 0;
663 /* remove obsolete displays */
664 for ( r = 0; r < mRows; ++r ) {
665 for ( c = 0; c < mColumns; ++c )
666 if ( r >= newRows || c >= newColumns )
667 delete mDisplayList[ r ][ c ];
668 delete mDisplayList[ r ];
670 delete [] mDisplayList;
672 /* now we make the new display the regular one */
673 mDisplayList = newDisplayList;
675 /* create new displays */
676 for ( r = 0; r < newRows; ++r )
677 for ( c = 0; c < newColumns; ++c )
678 if ( r >= mRows || c >= mColumns )
679 replaceDisplay( r, c );
681 /* set stretch factors for new rows and columns (if any) */
682 for ( r = mRows; r < newRows; ++r )
683 mGridLayout->setRowStretch( r, 100 );
684 for ( c = mColumns; c < newColumns; ++c )
685 mGridLayout->setColumnStretch( c, 100 );
687 /* Obviously Qt does not shrink the size of the QGridLayout
688 * automatically. So we simply force the rows and columns that
689 * are no longer used to have a stretch factor of 0 and hence be
690 * invisible. */
691 for ( r = newRows; r < mRows; ++r )
692 mGridLayout->setRowStretch( r, 0 );
693 for ( c = newColumns; c < mColumns; ++c )
694 mGridLayout->setColumnStretch( c, 0 );
696 mRows = newRows;
697 mColumns = newColumns;
699 fixTabOrder();
701 mGridLayout->activate();
704 KSGRD::SensorDisplay *WorkSheet::currentDisplay( uint *row, uint *column )
706 for ( uint r = 0 ; r < mRows; ++r )
707 for ( uint c = 0 ; c < mColumns; ++c )
708 if ( mDisplayList[ r ][ c ]->hasFocus() ) {
709 if ( row )
710 *row = r;
711 if ( column )
712 *column = c;
713 return ( mDisplayList[ r ][ c ] );
716 return 0;
719 void WorkSheet::fixTabOrder()
721 for ( uint r = 0; r < mRows; ++r )
722 for ( uint c = 0; c < mColumns; ++c ) {
723 if ( c + 1 < mColumns )
724 setTabOrder( mDisplayList[ r ][ c ], mDisplayList[ r ][ c + 1 ] );
725 else if ( r + 1 < mRows )
726 setTabOrder( mDisplayList[ r ][ c ], mDisplayList[ r + 1 ][ 0 ] );
730 QString WorkSheet::currentDisplayAsXML()
732 KSGRD::SensorDisplay* display = currentDisplay();
733 if ( !display )
734 return QString();
736 /* We create an XML description of the current display. */
737 QDomDocument doc( "KSysGuardDisplay" );
738 doc.appendChild( doc.createProcessingInstruction(
739 "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
741 QDomElement element = doc.createElement( "display" );
742 doc.appendChild( element );
743 element.setAttribute( "class", display->metaObject()->className() );
744 display->saveSettings( doc, element );
746 return doc.toString();
749 void WorkSheet::changeEvent( QEvent * event ) {
750 if (event->type() == QEvent::LanguageChange) {
751 setTitle(mTitle); //retranslate
755 void WorkSheet::setUpdateInterval( float secs)
757 if(secs == 0)
758 mTimer.stop();
759 else {
760 mTimer.setInterval(secs*1000);
761 mTimer.start();
764 float WorkSheet::updateInterval() const
766 if(mTimer.isActive())
767 return mTimer.interval()/1000.0;
768 else
769 return 0;
772 #include "WorkSheet.moc"