You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
464 lines
13 KiB
464 lines
13 KiB
15 years ago
|
/*
|
||
|
KSysGuard, the KDE System Guard
|
||
|
|
||
|
Copyright (c) 1999 - 2002 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!
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include <qlineedit.h>
|
||
|
#include <qspinbox.h>
|
||
|
#include <qwhatsthis.h>
|
||
|
|
||
|
#include <kdebug.h>
|
||
|
#include <kfiledialog.h>
|
||
|
#include <kio/netaccess.h>
|
||
|
#include <klocale.h>
|
||
|
#include <kmessagebox.h>
|
||
|
#include <kstandarddirs.h>
|
||
|
#include <kaccelmanager.h>
|
||
|
|
||
|
#include "WorkSheet.h"
|
||
|
#include "WorkSheetSettings.h"
|
||
|
#include "ProcessController.h"
|
||
|
|
||
|
#include "Workspace.h"
|
||
|
|
||
|
Workspace::Workspace( QWidget* parent, const char* name )
|
||
|
: QTabWidget( parent, name )
|
||
|
{
|
||
|
KAcceleratorManager::setNoAccel(this);
|
||
|
|
||
|
mSheetList.setAutoDelete( true );
|
||
|
mAutoSave = true;
|
||
|
|
||
|
connect( this, SIGNAL( currentChanged( QWidget* ) ),
|
||
|
SLOT( updateCaption( QWidget* ) ) );
|
||
|
|
||
|
QWhatsThis::add( this, i18n( "This is your work space. It holds your worksheets. You need "
|
||
|
"to create a new worksheet (Menu File->New) before "
|
||
|
"you can drag sensors here." ) );
|
||
|
}
|
||
|
|
||
|
Workspace::~Workspace()
|
||
|
{
|
||
|
/* This workaround is necessary to prevent a crash when the last
|
||
|
* page is not the current page. It seems like the the signal/slot
|
||
|
* administration data is already deleted but slots are still
|
||
|
* being triggered. TODO: I need to ask the Trolls about this. */
|
||
|
|
||
|
disconnect( this, SIGNAL( currentChanged( QWidget* ) ), this,
|
||
|
SLOT( updateCaption( QWidget* ) ) );
|
||
|
}
|
||
|
|
||
|
void Workspace::saveProperties( KConfig *cfg )
|
||
|
{
|
||
|
cfg->writePathEntry( "WorkDir", mWorkDir );
|
||
|
cfg->writeEntry( "CurrentSheet", tabLabel( currentPage() ) );
|
||
|
|
||
|
QPtrListIterator<WorkSheet> it( mSheetList);
|
||
|
|
||
|
QStringList list;
|
||
|
for ( int i = 0; it.current(); ++it, ++i )
|
||
|
if ( !(*it)->fileName().isEmpty() )
|
||
|
list.append( (*it)->fileName() );
|
||
|
|
||
|
cfg->writePathEntry( "Sheets", list );
|
||
|
}
|
||
|
|
||
|
void Workspace::readProperties( KConfig *cfg )
|
||
|
{
|
||
|
QString currentSheet;
|
||
|
|
||
|
mWorkDir = cfg->readPathEntry( "WorkDir" );
|
||
|
|
||
|
if ( mWorkDir.isEmpty() ) {
|
||
|
/* If workDir is not specified in the config file, it's
|
||
|
* probably the first time the user has started KSysGuard. We
|
||
|
* then "restore" a special default configuration. */
|
||
|
KStandardDirs* kstd = KGlobal::dirs();
|
||
|
kstd->addResourceType( "data", "share/apps/ksysguard" );
|
||
|
|
||
|
mWorkDir = kstd->saveLocation( "data", "ksysguard" );
|
||
|
|
||
|
QString origFile = kstd->findResource( "data", "SystemLoad.sgrd" );
|
||
|
QString newFile = mWorkDir + "/" + i18n( "System Load" ) + ".sgrd";
|
||
|
if ( !origFile.isEmpty() )
|
||
|
restoreWorkSheet( origFile, newFile );
|
||
|
|
||
|
origFile = kstd->findResource( "data", "ProcessTable.sgrd" );
|
||
|
newFile = mWorkDir + "/" + i18n( "Process Table" ) + ".sgrd";
|
||
|
if ( !origFile.isEmpty() )
|
||
|
restoreWorkSheet( origFile, newFile );
|
||
|
|
||
|
currentSheet = i18n( "System Load" );
|
||
|
} else {
|
||
|
currentSheet = cfg->readEntry( "CurrentSheet" );
|
||
|
QStringList list = cfg->readPathListEntry( "Sheets" );
|
||
|
for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
|
||
|
restoreWorkSheet( *it );
|
||
|
}
|
||
|
|
||
|
// Determine visible sheet.
|
||
|
QPtrListIterator<WorkSheet> it( mSheetList );
|
||
|
for ( ; it.current(); ++it )
|
||
|
if ( currentSheet == tabLabel(*it) ) {
|
||
|
showPage( *it );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Workspace::newWorkSheet()
|
||
|
{
|
||
|
/* Find a name of the form "Sheet %d" that is not yet used by any
|
||
|
* of the existing worksheets. */
|
||
|
QString sheetName;
|
||
|
bool found;
|
||
|
|
||
|
int i = 1;
|
||
|
do {
|
||
|
sheetName = i18n( "Sheet %1" ).arg( i++ );
|
||
|
QPtrListIterator<WorkSheet> it( mSheetList );
|
||
|
found = false;
|
||
|
for ( ; it.current() && !found; ++it )
|
||
|
if ( tabLabel(*it) == sheetName )
|
||
|
found = true;
|
||
|
} while ( found );
|
||
|
|
||
|
WorkSheetSettings dlg( this );
|
||
|
dlg.setSheetTitle( sheetName );
|
||
|
if ( dlg.exec() ) {
|
||
|
WorkSheet* sheet = new WorkSheet( dlg.rows(), dlg.columns(), dlg.interval(), this );
|
||
|
sheet->setTitle( dlg.sheetTitle() );
|
||
|
insertTab( sheet, dlg.sheetTitle() );
|
||
|
mSheetList.append( sheet );
|
||
|
showPage( sheet );
|
||
|
connect( sheet, SIGNAL( sheetModified( QWidget* ) ),
|
||
|
SLOT( updateCaption( QWidget* ) ) );
|
||
|
connect( sheet, SIGNAL( titleChanged( QWidget* ) ),
|
||
|
SLOT( updateSheetTitle( QWidget* ) ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool Workspace::saveOnQuit()
|
||
|
{
|
||
|
QPtrListIterator<WorkSheet> it( mSheetList );
|
||
|
for ( ; it.current(); ++it )
|
||
|
if ( (*it)->modified() ) {
|
||
|
if ( !mAutoSave || (*it)->fileName().isEmpty() ) {
|
||
|
int res = KMessageBox::warningYesNoCancel( this,
|
||
|
i18n( "The worksheet '%1' contains unsaved data.\n"
|
||
|
"Do you want to save the worksheet?")
|
||
|
.arg( tabLabel( *it ) ), QString::null, KStdGuiItem::save(), KStdGuiItem::discard() );
|
||
|
if ( res == KMessageBox::Yes )
|
||
|
saveWorkSheet( *it );
|
||
|
else if ( res == KMessageBox::Cancel )
|
||
|
return false; // abort quit
|
||
|
} else
|
||
|
saveWorkSheet(*it);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void Workspace::loadWorkSheet()
|
||
|
{
|
||
|
KFileDialog dlg( 0, i18n( "*.sgrd|Sensor Files" ), this,
|
||
|
"LoadFileDialog", true );
|
||
|
|
||
|
KURL url = dlg.getOpenURL( mWorkDir, "*.sgrd", 0, i18n( "Select Worksheet to Load" ) );
|
||
|
|
||
|
loadWorkSheet( url );
|
||
|
}
|
||
|
|
||
|
void Workspace::loadWorkSheet( const KURL &url )
|
||
|
{
|
||
|
if ( url.isEmpty() )
|
||
|
return;
|
||
|
|
||
|
/* It's probably not worth the effort to make this really network
|
||
|
* transparent. Unless s/o beats me up I use this pseudo transparent
|
||
|
* code. */
|
||
|
QString tmpFile;
|
||
|
KIO::NetAccess::download( url, tmpFile, this );
|
||
|
mWorkDir = tmpFile.left( tmpFile.findRev( '/' ) );
|
||
|
|
||
|
// Load sheet from file.
|
||
|
if ( !restoreWorkSheet( tmpFile ) )
|
||
|
return;
|
||
|
|
||
|
/* If we have loaded a non-local file we clear the file name so that
|
||
|
* the users is prompted for a new name for saving the file. */
|
||
|
KURL tmpFileUrl;
|
||
|
tmpFileUrl.setPath( tmpFile );
|
||
|
if ( tmpFileUrl != url.url() )
|
||
|
mSheetList.last()->setFileName( QString::null );
|
||
|
KIO::NetAccess::removeTempFile( tmpFile );
|
||
|
|
||
|
emit announceRecentURL( KURL( url ) );
|
||
|
}
|
||
|
|
||
|
void Workspace::saveWorkSheet()
|
||
|
{
|
||
|
saveWorkSheet( (WorkSheet*)currentPage() );
|
||
|
}
|
||
|
|
||
|
void Workspace::saveWorkSheetAs()
|
||
|
{
|
||
|
saveWorkSheetAs( (WorkSheet*)currentPage() );
|
||
|
}
|
||
|
|
||
|
void Workspace::saveWorkSheet( WorkSheet *sheet )
|
||
|
{
|
||
|
if ( !sheet ) {
|
||
|
KMessageBox::sorry( this, i18n( "You do not have a worksheet that could be saved." ) );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
QString fileName = sheet->fileName();
|
||
|
if ( fileName.isEmpty() ) {
|
||
|
KFileDialog dlg( 0, i18n( "*.sgrd|Sensor Files" ), this,
|
||
|
"LoadFileDialog", true );
|
||
|
fileName = dlg.getSaveFileName( mWorkDir + "/" + tabLabel( sheet ) +
|
||
|
".sgrd", "*.sgrd", 0,
|
||
|
i18n( "Save Current Worksheet As" ) );
|
||
|
if ( fileName.isEmpty() )
|
||
|
return;
|
||
|
|
||
|
mWorkDir = fileName.left( fileName.findRev( '/' ) );
|
||
|
|
||
|
// extract filename without path
|
||
|
QString baseName = fileName.right( fileName.length() - fileName.findRev( '/' ) - 1 );
|
||
|
|
||
|
// chop off extension (usually '.sgrd')
|
||
|
baseName = baseName.left( baseName.findRev( '.' ) );
|
||
|
changeTab( sheet, baseName );
|
||
|
}
|
||
|
|
||
|
/* If we cannot save the file is probably write protected. So we need
|
||
|
* to ask the user for a new name. */
|
||
|
if ( !sheet->save( fileName ) ) {
|
||
|
saveWorkSheetAs( sheet );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Add file to recent documents menue. */
|
||
|
KURL url;
|
||
|
url.setPath( fileName );
|
||
|
emit announceRecentURL( url );
|
||
|
}
|
||
|
|
||
|
void Workspace::saveWorkSheetAs( WorkSheet *sheet )
|
||
|
{
|
||
|
if ( !sheet ) {
|
||
|
KMessageBox::sorry( this, i18n( "You do not have a worksheet that could be saved." ) );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
QString fileName;
|
||
|
do {
|
||
|
KFileDialog dlg( 0, "*.sgrd", this, "LoadFileDialog", true );
|
||
|
fileName = dlg.getSaveFileName( mWorkDir + "/" + tabLabel( currentPage() ) +
|
||
|
".sgrd", "*.sgrd" );
|
||
|
if ( fileName.isEmpty() )
|
||
|
return;
|
||
|
|
||
|
mWorkDir = fileName.left( fileName.findRev( '/' ) );
|
||
|
|
||
|
// extract filename without path
|
||
|
QString baseName = fileName.right( fileName.length() - fileName.findRev( '/' ) - 1 );
|
||
|
|
||
|
// chop off extension (usually '.sgrd')
|
||
|
baseName = baseName.left( baseName.findRev( '.' ) );
|
||
|
changeTab( sheet, baseName );
|
||
|
} while ( !sheet->save( fileName ) );
|
||
|
|
||
|
/* Add file to recent documents menue. */
|
||
|
KURL url;
|
||
|
url.setPath( fileName );
|
||
|
emit announceRecentURL( url );
|
||
|
}
|
||
|
|
||
|
void Workspace::deleteWorkSheet()
|
||
|
{
|
||
|
WorkSheet *current = (WorkSheet*)currentPage();
|
||
|
|
||
|
if ( current ) {
|
||
|
if ( current->modified() ) {
|
||
|
if ( !mAutoSave || current->fileName().isEmpty() ) {
|
||
|
int res = KMessageBox::warningYesNoCancel( this,
|
||
|
i18n( "The worksheet '%1' contains unsaved data.\n"
|
||
|
"Do you want to save the worksheet?" )
|
||
|
.arg( tabLabel( current ) ), QString::null, KStdGuiItem::save(), KStdGuiItem::discard() );
|
||
|
if ( res == KMessageBox::Cancel )
|
||
|
return;
|
||
|
|
||
|
if ( res == KMessageBox::Yes )
|
||
|
saveWorkSheet( current );
|
||
|
} else
|
||
|
saveWorkSheet( current );
|
||
|
}
|
||
|
|
||
|
removePage( current );
|
||
|
mSheetList.remove( current );
|
||
|
} else {
|
||
|
QString msg = i18n( "There are no worksheets that could be deleted." );
|
||
|
KMessageBox::error( this, msg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Workspace::removeAllWorkSheets()
|
||
|
{
|
||
|
WorkSheet *sheet;
|
||
|
while ( ( sheet = (WorkSheet*)currentPage() ) != 0 ) {
|
||
|
removePage( sheet );
|
||
|
mSheetList.remove( sheet );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Workspace::deleteWorkSheet( const QString &fileName )
|
||
|
{
|
||
|
QPtrListIterator<WorkSheet> it( mSheetList );
|
||
|
for ( ; it.current(); ++it )
|
||
|
if ( (*it)->fileName() == fileName ) {
|
||
|
removePage( *it );
|
||
|
mSheetList.remove( *it );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WorkSheet *Workspace::restoreWorkSheet( const QString &fileName, const QString &newName )
|
||
|
{
|
||
|
/* We might want to save the worksheet under a different name later. This
|
||
|
* name can be specified by newName. If newName is empty we use the
|
||
|
* original name to save the work sheet. */
|
||
|
QString tmpStr;
|
||
|
if ( newName.isEmpty() )
|
||
|
tmpStr = fileName;
|
||
|
else
|
||
|
tmpStr = newName;
|
||
|
|
||
|
// extract filename without path
|
||
|
QString baseName = tmpStr.right( tmpStr.length() - tmpStr.findRev( '/' ) - 1 );
|
||
|
|
||
|
// chop off extension (usually '.sgrd')
|
||
|
baseName = baseName.left( baseName.findRev( '.' ) );
|
||
|
|
||
|
WorkSheet *sheet = new WorkSheet( this );
|
||
|
sheet->setTitle( baseName );
|
||
|
insertTab( sheet, baseName );
|
||
|
showPage( sheet );
|
||
|
|
||
|
if ( !sheet->load( fileName ) ) {
|
||
|
delete sheet;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
mSheetList.append( sheet );
|
||
|
connect( sheet, SIGNAL( sheetModified( QWidget* ) ),
|
||
|
SLOT( updateCaption( QWidget* ) ) );
|
||
|
|
||
|
/* Force the file name to be the new name. This also sets the modified
|
||
|
* flag, so that the file will get saved on exit. */
|
||
|
if ( !newName.isEmpty() )
|
||
|
sheet->setFileName( newName );
|
||
|
|
||
|
return sheet;
|
||
|
}
|
||
|
|
||
|
void Workspace::cut()
|
||
|
{
|
||
|
WorkSheet *current = (WorkSheet*)currentPage();
|
||
|
|
||
|
if ( current )
|
||
|
current->cut();
|
||
|
}
|
||
|
|
||
|
void Workspace::copy()
|
||
|
{
|
||
|
WorkSheet *current = (WorkSheet*)currentPage();
|
||
|
|
||
|
if ( current )
|
||
|
current->copy();
|
||
|
}
|
||
|
|
||
|
void Workspace::paste()
|
||
|
{
|
||
|
WorkSheet *current = (WorkSheet*)currentPage();
|
||
|
|
||
|
if ( current )
|
||
|
current->paste();
|
||
|
}
|
||
|
|
||
|
void Workspace::configure()
|
||
|
{
|
||
|
WorkSheet *current = (WorkSheet*)currentPage();
|
||
|
|
||
|
if ( !current )
|
||
|
return;
|
||
|
|
||
|
current->settings();
|
||
|
}
|
||
|
|
||
|
void Workspace::updateCaption( QWidget* wdg )
|
||
|
{
|
||
|
if ( wdg )
|
||
|
emit setCaption( tabLabel( wdg ), ((WorkSheet*)wdg)->modified() );
|
||
|
else
|
||
|
emit setCaption( QString::null, false );
|
||
|
|
||
|
for ( WorkSheet* s = mSheetList.first(); s != 0; s = mSheetList.next() )
|
||
|
((WorkSheet*)s)->setIsOnTop( s == wdg );
|
||
|
}
|
||
|
|
||
|
void Workspace::updateSheetTitle( QWidget* wdg )
|
||
|
{
|
||
|
if ( wdg )
|
||
|
changeTab( wdg, static_cast<WorkSheet*>( wdg )->title() );
|
||
|
}
|
||
|
|
||
|
void Workspace::applyStyle()
|
||
|
{
|
||
|
if ( currentPage() )
|
||
|
((WorkSheet*)currentPage())->applyStyle();
|
||
|
}
|
||
|
|
||
|
void Workspace::showProcesses()
|
||
|
{
|
||
|
KStandardDirs* kstd = KGlobal::dirs();
|
||
|
kstd->addResourceType( "data", "share/apps/ksysguard" );
|
||
|
|
||
|
QString file = kstd->findResource( "data", "ProcessTable.sgrd" );
|
||
|
if ( file.isEmpty() ) {
|
||
|
KMessageBox::error( this, i18n( "Cannot find file ProcessTable.sgrd." ) );
|
||
|
return;
|
||
|
}
|
||
|
WorkSheet *processSheet = restoreWorkSheet( file );
|
||
|
if(!processSheet) return;
|
||
|
|
||
|
//Set the focus of the search line. This is nasty I know, but I don't know how better to do this :(
|
||
|
KSGRD::SensorDisplay *processSensor = processSheet->display( 0,0 );
|
||
|
if(!processSensor || !processSensor->isA("ProcessController")) return;
|
||
|
ProcessController *controller = dynamic_cast<ProcessController *>(processSensor);
|
||
|
if(!controller) return;
|
||
|
controller->setSearchFocus();
|
||
|
|
||
|
}
|
||
|
|
||
|
#include "Workspace.moc"
|