kresources
configpage.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of libkresources. 00003 00004 Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> 00005 Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> 00006 Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Library General Public 00010 License as published by the Free Software Foundation; either 00011 version 2 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Library General Public License for more details. 00017 00018 You should have received a copy of the GNU Library General Public License 00019 along with this library; see the file COPYING.LIB. If not, write to 00020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00021 Boston, MA 02110-1301, USA. 00022 */ 00036 #include "configpage.h" 00037 00038 #include <QtGui/QGroupBox> 00039 #include <QtGui/QLabel> 00040 #include <QtGui/QLayout> 00041 #include <QtGui/QTreeWidget> 00042 #include <QtGui/QTreeWidgetItem> 00043 00044 #include <kcombobox.h> 00045 #include <kdebug.h> 00046 #include <klocale.h> 00047 #include <kmessagebox.h> 00048 #include <kconfig.h> 00049 #include <kstandarddirs.h> 00050 #include <kurlrequester.h> 00051 #include <kdialogbuttonbox.h> 00052 #include <kservicetypetrader.h> 00053 #include <kinputdialog.h> 00054 #include <QtCore/QList> 00055 00056 #include "resource.h" 00057 #include "configdialog.h" 00058 00059 namespace KRES { 00060 00061 class ResourcePageInfo::Private 00062 { 00063 }; 00064 00065 ResourcePageInfo::ResourcePageInfo() : d( new KRES::ResourcePageInfo::Private ) 00066 { 00067 mManager = 0; 00068 mConfig = 0; 00069 } 00070 00071 ResourcePageInfo::~ResourcePageInfo() 00072 { 00073 //delete mManager; 00074 mManager = 0; 00075 //delete mConfig; 00076 mConfig = 0; 00077 delete d; 00078 } 00079 00080 class ConfigViewItem : public QTreeWidgetItem 00081 { 00082 public: 00083 ConfigViewItem( QTreeWidget *parent, Resource *resource ) : 00084 QTreeWidgetItem( parent ), mResource( resource ), mIsStandard( false ) 00085 { 00086 updateItem(); 00087 } 00088 00089 void setStandard( bool value ) 00090 { 00091 setText( 2, ( value ? i18nc( "yes, a standard resource", "Yes" ) : QString() ) ); 00092 mIsStandard = value; 00093 } 00094 00095 bool standard() const { return mIsStandard; } 00096 bool readOnly() const { return mResource->readOnly(); } 00097 00098 Resource *resource() { return mResource; } 00099 00100 void updateItem() 00101 { 00102 setCheckState( 0, mResource->isActive() ? Qt::Checked : Qt::Unchecked ); 00103 setText( 0, mResource->resourceName() ); 00104 setText( 1, mResource->type() ); 00105 setText( 2, mIsStandard ? i18nc( "yes, a standard resource", "Yes" ) : QString() ); 00106 } 00107 00108 bool isOn() 00109 { 00110 return checkState( 0 ) == Qt::Checked; 00111 } 00112 00113 private: 00114 Resource *mResource; 00115 bool mIsStandard; 00116 }; 00117 00118 class ConfigPage::Private 00119 { 00120 public: 00121 void loadManager( const QString &family, ConfigPage *page ); 00122 void saveResourceSettings( ConfigPage *page ); 00123 00124 Manager<Resource> *mCurrentManager; 00125 KConfig *mCurrentConfig; 00126 KConfigGroup *mConfigGroup; 00127 QString mFamily; 00128 QStringList mFamilyMap; 00129 QList<KSharedPtr<ResourcePageInfo> > mInfoMap; 00130 00131 KComboBox *mFamilyCombo; 00132 QTreeWidget *mListView; 00133 QPushButton *mAddButton; 00134 QPushButton *mRemoveButton; 00135 QPushButton *mEditButton; 00136 QPushButton *mStandardButton; 00137 00138 QTreeWidgetItem *mLastItem; 00139 }; 00140 00141 ConfigPage::ConfigPage( QWidget *parent ) 00142 : QWidget( parent ), d( new KRES::ConfigPage::Private ) 00143 { 00144 setWindowTitle( i18n( "Resource Configuration" ) ); 00145 00146 QVBoxLayout *mainLayout = new QVBoxLayout( this ); 00147 mainLayout->setMargin( 0 ); 00148 00149 QGroupBox *groupBox = new QGroupBox( i18n( "Resources" ), this ); 00150 QGridLayout *groupBoxLayout = new QGridLayout(); 00151 groupBox->setLayout( groupBoxLayout ); 00152 00153 d->mFamilyCombo = new KComboBox( false, groupBox ); 00154 groupBoxLayout->addWidget( d->mFamilyCombo, 0, 0, 1, 2 ); 00155 00156 d->mCurrentManager = 0; 00157 d->mCurrentConfig = 0; 00158 d->mListView = new QTreeWidget( groupBox ); 00159 d->mListView->setColumnCount( 3 ); 00160 QStringList headerLabels; 00161 headerLabels << i18nc( "@title:column resource name", "Name" ) 00162 << i18nc( "@title:column resource type", "Type" ) 00163 << i18nc( "@title:column a standard resource?", "Standard" ); 00164 d->mListView->setHeaderItem( new QTreeWidgetItem( headerLabels ) ); 00165 00166 groupBoxLayout->addWidget( d->mListView, 1, 0 ); 00167 connect( d->mListView, SIGNAL( itemDoubleClicked( QTreeWidgetItem *, int ) ), 00168 this, SLOT( slotEdit() ) ); 00169 00170 KDialogButtonBox *buttonBox = new KDialogButtonBox( groupBox, Qt::Vertical ); 00171 d->mAddButton = buttonBox->addButton( i18n( "&Add..." ), 00172 KDialogButtonBox::ActionRole, 00173 this, SLOT(slotAdd()) ); 00174 00175 d->mRemoveButton = buttonBox->addButton( i18n( "&Remove" ), 00176 KDialogButtonBox::ActionRole, 00177 this, SLOT(slotRemove()) ); 00178 d->mRemoveButton->setEnabled( false ); 00179 00180 d->mEditButton = buttonBox->addButton( i18n( "&Edit..." ), 00181 KDialogButtonBox::ActionRole, 00182 this, SLOT(slotEdit()) ); 00183 d->mEditButton->setEnabled( false ); 00184 00185 d->mStandardButton = buttonBox->addButton( i18n( "&Use as Standard" ), 00186 KDialogButtonBox::ActionRole, 00187 this, SLOT(slotStandard()) ); 00188 d->mStandardButton->setEnabled( false ); 00189 00190 buttonBox->layout(); 00191 groupBoxLayout->addWidget( buttonBox, 1, 1 ); 00192 00193 mainLayout->addWidget( groupBox ); 00194 00195 connect( d->mFamilyCombo, SIGNAL( activated( int ) ), 00196 SLOT( slotFamilyChanged( int ) ) ); 00197 connect( d->mListView, SIGNAL( itemSelectionChanged() ), 00198 SLOT( slotSelectionChanged() ) ); 00199 connect( d->mListView, SIGNAL( itemClicked( QTreeWidgetItem *, int ) ), 00200 SLOT( slotItemClicked( QTreeWidgetItem * ) ) ); 00201 00202 d->mLastItem = 0; 00203 00204 d->mConfigGroup = new KConfigGroup( new KConfig( "kcmkresourcesrc" ), "General" ); 00205 00206 load(); 00207 } 00208 00209 ConfigPage::~ConfigPage() 00210 { 00211 QList<KSharedPtr<ResourcePageInfo> >::Iterator it; 00212 for ( it = d->mInfoMap.begin(); it != d->mInfoMap.end(); ++it ) { 00213 (*it)->mManager->removeObserver( this ); 00214 } 00215 00216 d->mConfigGroup->writeEntry( "CurrentFamily", d->mFamilyCombo->currentIndex() ); 00217 delete d->mConfigGroup->config(); 00218 delete d->mConfigGroup; 00219 d->mConfigGroup = 0; 00220 delete d; 00221 } 00222 00223 void ConfigPage::load() 00224 { 00225 kDebug(); 00226 00227 d->mListView->clear(); 00228 d->mFamilyMap.clear(); 00229 d->mInfoMap.clear(); 00230 QStringList familyDisplayNames; 00231 00232 // KDE-3.3 compatibility code: get families from the plugins 00233 QStringList compatFamilyNames; 00234 const KService::List plugins = KServiceTypeTrader::self()->query( "KResources/Plugin" ); 00235 KService::List::ConstIterator it = plugins.begin(); 00236 KService::List::ConstIterator end = plugins.end(); 00237 for ( ; it != end; ++it ) { 00238 const QString family = (*it)->property( "X-KDE-ResourceFamily" ).toString(); 00239 if ( compatFamilyNames.indexOf( family ) == -1 ) { 00240 compatFamilyNames.append( family ); 00241 } 00242 } 00243 00244 const KService::List managers = KServiceTypeTrader::self()->query( "KResources/Manager" ); 00245 KService::List::ConstIterator m_it; 00246 for ( m_it = managers.begin(); m_it != managers.end(); ++m_it ) { 00247 QString displayName = (*m_it)->property( "Name" ).toString(); 00248 familyDisplayNames.append( displayName ); 00249 QString family = (*m_it)->property( "X-KDE-ResourceFamily" ).toString(); 00250 if ( !family.isEmpty() ) { 00251 compatFamilyNames.removeAll( family ); 00252 d->mFamilyMap.append( family ); 00253 d->loadManager( family, this ); 00254 } 00255 } 00256 00257 // Rest of the kde-3.3 compat code 00258 QStringList::ConstIterator cfit = compatFamilyNames.constBegin(); 00259 for ( ; cfit != compatFamilyNames.constEnd(); ++cfit ) { 00260 d->mFamilyMap.append( *cfit ); 00261 familyDisplayNames.append( *cfit ); 00262 d->loadManager( *cfit, this ); 00263 } 00264 00265 d->mCurrentManager = 0; 00266 00267 d->mFamilyCombo->clear(); 00268 d->mFamilyCombo->insertItems( 0, familyDisplayNames ); 00269 00270 int currentFamily = d->mConfigGroup->readEntry( "CurrentFamily", 0 ); 00271 d->mFamilyCombo->setCurrentIndex( currentFamily ); 00272 slotFamilyChanged( currentFamily ); 00273 emit changed( false ); 00274 } 00275 00276 void ConfigPage::Private::loadManager( const QString &family, ConfigPage *page ) 00277 { 00278 mCurrentManager = new Manager<Resource>( family ); 00279 if ( mCurrentManager ) { 00280 mCurrentManager->addObserver( page ); 00281 00282 ResourcePageInfo *info = new ResourcePageInfo; 00283 info->mManager = mCurrentManager; 00284 info->mConfig = new KConfig( KRES::ManagerImpl::defaultConfigFile( family ) ); 00285 info->mManager->readConfig( info->mConfig ); 00286 00287 mInfoMap.append( KSharedPtr<ResourcePageInfo>( info ) ); 00288 } 00289 } 00290 00291 void ConfigPage::save() 00292 { 00293 d->saveResourceSettings( this ); 00294 00295 QList<KSharedPtr<ResourcePageInfo> >::Iterator it; 00296 for ( it = d->mInfoMap.begin(); it != d->mInfoMap.end(); ++it ) { 00297 (*it)->mManager->writeConfig( (*it)->mConfig ); 00298 } 00299 00300 emit changed( false ); 00301 } 00302 00303 void ConfigPage::defaults() 00304 { 00305 } 00306 00307 void ConfigPage::slotFamilyChanged( int pos ) 00308 { 00309 if ( pos < 0 || pos >= (int)d->mFamilyMap.count() ) { 00310 return; 00311 } 00312 00313 d->saveResourceSettings( this ); 00314 00315 d->mFamily = d->mFamilyMap[ pos ]; 00316 00317 d->mCurrentManager = d->mInfoMap[ pos ]->mManager; 00318 d->mCurrentConfig = d->mInfoMap[ pos ]->mConfig; 00319 00320 if ( !d->mCurrentManager ) { 00321 kDebug() << "ERROR: cannot create ResourceManager<Resource>( mFamily )"; 00322 } 00323 00324 d->mListView->clear(); 00325 00326 if ( d->mCurrentManager->isEmpty() ) { 00327 defaults(); 00328 } 00329 00330 Resource *standardResource = d->mCurrentManager->standardResource(); 00331 00332 Manager<Resource>::Iterator it; 00333 for ( it = d->mCurrentManager->begin(); it != d->mCurrentManager->end(); ++it ) { 00334 ConfigViewItem *item = new ConfigViewItem( d->mListView, *it ); 00335 if ( *it == standardResource ) { 00336 item->setStandard( true ); 00337 } 00338 } 00339 00340 if ( d->mListView->topLevelItemCount() == 0 ) { 00341 defaults(); 00342 emit changed( true ); 00343 d->mCurrentManager->writeConfig( d->mCurrentConfig ); 00344 } else { 00345 if ( !standardResource ) { 00346 KMessageBox::sorry( this, i18n( "There is no standard resource. Please select one." ) ); 00347 } 00348 00349 emit changed( false ); 00350 } 00351 } 00352 00353 void ConfigPage::slotAdd() 00354 { 00355 if ( !d->mCurrentManager ) { 00356 return; 00357 } 00358 00359 QStringList types = d->mCurrentManager->resourceTypeNames(); 00360 QStringList descs = d->mCurrentManager->resourceTypeDescriptions(); 00361 bool ok = false; 00362 QString desc = KInputDialog::getItem( i18n( "Resource Configuration" ), 00363 i18n( "Please select type of the new resource:" ), descs, 00364 0, false, &ok, this ); 00365 if ( !ok ) { 00366 return; 00367 } 00368 00369 QString type = types[ descs.indexOf( desc ) ]; 00370 00371 // Create new resource 00372 Resource *resource = d->mCurrentManager->createResource( type ); 00373 if ( !resource ) { 00374 KMessageBox::error( 00375 this, i18n( "Unable to create resource of type '%1'.", type ) ); 00376 return; 00377 } 00378 00379 resource->setResourceName( type + "-resource" ); 00380 00381 ConfigDialog dlg( this, d->mFamily, resource ); 00382 00383 if ( dlg.exec() ) { //krazy:exclude=crashy 00384 d->mCurrentManager->add( resource ); 00385 00386 ConfigViewItem *item = new ConfigViewItem( d->mListView, resource ); 00387 00388 d->mLastItem = item; 00389 00390 // if there are only read-only resources we'll set this resource 00391 // as standard resource 00392 if ( !resource->readOnly() ) { 00393 bool onlyReadOnly = true; 00394 for ( int i = 0; i < d->mListView->topLevelItemCount(); ++i ) { 00395 ConfigViewItem *confIt = static_cast<ConfigViewItem*>( d->mListView->topLevelItem( i ) ); 00396 if ( !confIt->readOnly() && confIt != item ) { 00397 onlyReadOnly = false; 00398 } 00399 } 00400 00401 if ( onlyReadOnly ) { 00402 item->setStandard( true ); 00403 } 00404 } 00405 00406 emit changed( true ); 00407 } else { 00408 delete resource; 00409 resource = 0; 00410 } 00411 } 00412 00413 void ConfigPage::slotRemove() 00414 { 00415 if ( !d->mCurrentManager ) { 00416 return; 00417 } 00418 00419 QTreeWidgetItem *item = d->mListView->currentItem(); 00420 ConfigViewItem *confItem = static_cast<ConfigViewItem*>( item ); 00421 00422 if ( !confItem ) { 00423 return; 00424 } 00425 00426 if ( confItem->standard() ) { 00427 KMessageBox::sorry( this, 00428 i18n( "You cannot remove your standard resource. " 00429 "Please select a new standard resource first." ) ); 00430 return; 00431 } 00432 00433 d->mCurrentManager->remove( confItem->resource() ); 00434 00435 if ( item == d->mLastItem ) { 00436 d->mLastItem = 0; 00437 } 00438 00439 d->mListView->takeTopLevelItem( d->mListView->indexOfTopLevelItem( item ) ); 00440 delete item; 00441 00442 emit changed( true ); 00443 } 00444 00445 void ConfigPage::slotEdit() 00446 { 00447 if ( !d->mCurrentManager ) { 00448 return; 00449 } 00450 00451 QTreeWidgetItem *item = d->mListView->currentItem(); 00452 ConfigViewItem *configItem = static_cast<ConfigViewItem*>( item ); 00453 if ( !configItem ) { 00454 return; 00455 } 00456 00457 Resource *resource = configItem->resource(); 00458 00459 ConfigDialog dlg( this, d->mFamily, resource ); 00460 00461 if ( dlg.exec() ) { //krazy:exclude=crashy 00462 configItem->setText( 0, resource->resourceName() ); 00463 configItem->setText( 1, resource->type() ); 00464 00465 if ( configItem->standard() && configItem->readOnly() ) { 00466 KMessageBox::sorry( this, i18n( "You cannot use a read-only resource as standard." ) ); 00467 configItem->setStandard( false ); 00468 } 00469 00470 d->mCurrentManager->change( resource ); 00471 emit changed( true ); 00472 } 00473 } 00474 00475 void ConfigPage::slotStandard() 00476 { 00477 if ( !d->mCurrentManager ) { 00478 return; 00479 } 00480 00481 ConfigViewItem *item = static_cast<ConfigViewItem*>( d->mListView->currentItem() ); 00482 if ( !item ) { 00483 return; 00484 } 00485 00486 if ( item->readOnly() ) { 00487 KMessageBox::sorry( this, i18n( "You cannot use a read-only resource as standard." ) ); 00488 return; 00489 } 00490 00491 if ( !item->isOn() ) { 00492 KMessageBox::sorry( this, i18n( "You cannot use an inactive resource as standard." ) ); 00493 return; 00494 } 00495 00496 for ( int i = 0; i < d->mListView->topLevelItemCount(); ++i ) { 00497 ConfigViewItem *configItem = static_cast<ConfigViewItem*>( d->mListView->topLevelItem( i ) ); 00498 if ( configItem->standard() ) { 00499 configItem->setStandard( false ); 00500 } 00501 } 00502 00503 item->setStandard( true ); 00504 d->mCurrentManager->setStandardResource( item->resource() ); 00505 00506 emit changed( true ); 00507 } 00508 00509 void ConfigPage::slotSelectionChanged() 00510 { 00511 bool state = ( d->mListView->currentItem() != 0 ); 00512 00513 d->mRemoveButton->setEnabled( state ); 00514 d->mEditButton->setEnabled( state ); 00515 d->mStandardButton->setEnabled( state ); 00516 } 00517 00518 void ConfigPage::resourceAdded( Resource *resource ) 00519 { 00520 kDebug() << resource->resourceName(); 00521 00522 ConfigViewItem *item = new ConfigViewItem( d->mListView, resource ); 00523 00524 item->setCheckState( 0, resource->isActive()? Qt::Checked : Qt::Unchecked ); 00525 00526 d->mLastItem = item; 00527 00528 emit changed( true ); 00529 } 00530 00531 void ConfigPage::resourceModified( Resource *resource ) 00532 { 00533 kDebug() << resource->resourceName(); 00534 ConfigViewItem *item = findItem( resource ); 00535 if ( !item ) { 00536 return; 00537 } 00538 00539 // TODO: Reread resource config. Otherwise we won't see the modification. 00540 00541 item->updateItem(); 00542 } 00543 00544 void ConfigPage::resourceDeleted( Resource *resource ) 00545 { 00546 kDebug() << resource->resourceName(); 00547 00548 ConfigViewItem *item = findItem( resource ); 00549 if ( !item ) { 00550 return; 00551 } 00552 00553 delete item; 00554 } 00555 00556 ConfigViewItem *ConfigPage::findItem( Resource *resource ) 00557 { 00558 for ( int i = 0; i < d->mListView->topLevelItemCount(); ++i ) { 00559 ConfigViewItem *item = static_cast<ConfigViewItem *>( d->mListView->topLevelItem( i ) ); 00560 if ( item->resource() == resource ) { 00561 return item; 00562 } 00563 } 00564 return 0; 00565 } 00566 00567 void ConfigPage::slotItemClicked( QTreeWidgetItem *item ) 00568 { 00569 ConfigViewItem *configItem = static_cast<ConfigViewItem *>( item ); 00570 if ( !configItem ) { 00571 return; 00572 } 00573 00574 if ( configItem->standard() && !configItem->isOn() ) { 00575 KMessageBox::sorry( this, 00576 i18n( "You cannot deactivate the standard resource. " 00577 "Choose another standard resource first." ) ); 00578 configItem->setCheckState( 0, Qt::Checked ); 00579 return; 00580 } 00581 00582 if ( configItem->isOn() != configItem->resource()->isActive() ) { 00583 emit changed( true ); 00584 } 00585 } 00586 00587 void ConfigPage::Private::saveResourceSettings( ConfigPage *page ) 00588 { 00589 if ( mCurrentManager ) { 00590 for ( int i = 0; i < mListView->topLevelItemCount(); ++i ) { 00591 ConfigViewItem *configItem = static_cast<ConfigViewItem *>( mListView->topLevelItem( i ) ); 00592 // check if standard resource 00593 if ( configItem->standard() && !configItem->readOnly() && 00594 configItem->isOn() ) { 00595 mCurrentManager->setStandardResource( configItem->resource() ); 00596 } 00597 00598 // check if active or passive resource 00599 configItem->resource()->setActive( configItem->isOn() ); 00600 } 00601 mCurrentManager->writeConfig( mCurrentConfig ); 00602 00603 if ( !mCurrentManager->standardResource() ) { 00604 KMessageBox::sorry( page, 00605 i18n( "There is no valid standard resource. " 00606 "Please select one which is neither read-only nor inactive." ) ); 00607 } 00608 } 00609 } 00610 00611 } 00612 00613 #include "configpage.moc" 00614