/* This file is part of libkresources. Copyright (c) 2002 Tobias Koenig Copyright (c) 2002 Jan-Pascal van Best Copyright (c) 2003 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** @file This file is part of the KDE resource framework and defines the ConfigPage class. @brief A resource configuration page. @author Tobias Koenig @author Jan-Pascal van Best @author Cornelius Schumacher */ #include "configpage.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "resource.h" #include "configdialog.h" namespace KRES { class ResourcePageInfo::Private { }; ResourcePageInfo::ResourcePageInfo() : d( new KRES::ResourcePageInfo::Private ) { mManager = 0; mConfig = 0; } ResourcePageInfo::~ResourcePageInfo() { //delete mManager; mManager = 0; //delete mConfig; mConfig = 0; delete d; } class ConfigViewItem : public QTreeWidgetItem { public: ConfigViewItem( QTreeWidget *parent, Resource *resource ) : QTreeWidgetItem( parent ), mResource( resource ), mIsStandard( false ) { updateItem(); } void setStandard( bool value ) { setText( 2, ( value ? i18nc( "yes, a standard resource", "Yes" ) : QString() ) ); mIsStandard = value; } bool standard() const { return mIsStandard; } bool readOnly() const { return mResource->readOnly(); } Resource *resource() { return mResource; } void updateItem() { setCheckState( 0, mResource->isActive() ? Qt::Checked : Qt::Unchecked ); setText( 0, mResource->resourceName() ); setText( 1, mResource->type() ); setText( 2, mIsStandard ? i18nc( "yes, a standard resource", "Yes" ) : QString() ); } bool isOn() { return checkState( 0 ) == Qt::Checked; } private: Resource *mResource; bool mIsStandard; }; class ConfigPage::Private { public: void loadManager( const QString &family, ConfigPage *page ); void saveResourceSettings( ConfigPage *page ); Manager *mCurrentManager; KConfig *mCurrentConfig; KConfigGroup *mConfigGroup; QString mFamily; QStringList mFamilyMap; QList > mInfoMap; KComboBox *mFamilyCombo; QTreeWidget *mListView; QPushButton *mAddButton; QPushButton *mRemoveButton; QPushButton *mEditButton; QPushButton *mStandardButton; QTreeWidgetItem *mLastItem; }; ConfigPage::ConfigPage( QWidget *parent ) : QWidget( parent ), d( new KRES::ConfigPage::Private ) { setWindowTitle( i18n( "Resource Configuration" ) ); QVBoxLayout *mainLayout = new QVBoxLayout( this ); mainLayout->setMargin( 0 ); QGroupBox *groupBox = new QGroupBox( i18n( "Resources" ), this ); QGridLayout *groupBoxLayout = new QGridLayout(); groupBox->setLayout( groupBoxLayout ); d->mFamilyCombo = new KComboBox( false, groupBox ); groupBoxLayout->addWidget( d->mFamilyCombo, 0, 0, 1, 2 ); d->mCurrentManager = 0; d->mCurrentConfig = 0; d->mListView = new QTreeWidget( groupBox ); d->mListView->setColumnCount( 3 ); QStringList headerLabels; headerLabels << i18nc( "@title:column resource name", "Name" ) << i18nc( "@title:column resource type", "Type" ) << i18nc( "@title:column a standard resource?", "Standard" ); d->mListView->setHeaderItem( new QTreeWidgetItem( headerLabels ) ); groupBoxLayout->addWidget( d->mListView, 1, 0 ); connect( d->mListView, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotEdit()) ); KDialogButtonBox *buttonBox = new KDialogButtonBox( groupBox, Qt::Vertical ); d->mAddButton = buttonBox->addButton( i18n( "&Add..." ), KDialogButtonBox::ActionRole, this, SLOT(slotAdd()) ); d->mRemoveButton = buttonBox->addButton( i18n( "&Remove" ), KDialogButtonBox::ActionRole, this, SLOT(slotRemove()) ); d->mRemoveButton->setEnabled( false ); d->mEditButton = buttonBox->addButton( i18n( "&Edit..." ), KDialogButtonBox::ActionRole, this, SLOT(slotEdit()) ); d->mEditButton->setEnabled( false ); d->mStandardButton = buttonBox->addButton( i18n( "&Use as Standard" ), KDialogButtonBox::ActionRole, this, SLOT(slotStandard()) ); d->mStandardButton->setEnabled( false ); buttonBox->layout(); groupBoxLayout->addWidget( buttonBox, 1, 1 ); mainLayout->addWidget( groupBox ); connect( d->mFamilyCombo, SIGNAL(activated(int)), SLOT(slotFamilyChanged(int)) ); connect( d->mListView, SIGNAL(itemSelectionChanged()), SLOT(slotSelectionChanged()) ); connect( d->mListView, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SLOT(slotItemClicked(QTreeWidgetItem*)) ); d->mLastItem = 0; d->mConfigGroup = new KConfigGroup( new KConfig( QLatin1String("kcmkresourcesrc") ), "General" ); load(); } ConfigPage::~ConfigPage() { QList >::Iterator it; for ( it = d->mInfoMap.begin(); it != d->mInfoMap.end(); ++it ) { ( *it )->mManager->removeObserver( this ); } d->mConfigGroup->writeEntry( "CurrentFamily", d->mFamilyCombo->currentIndex() ); delete d->mConfigGroup->config(); delete d->mConfigGroup; d->mConfigGroup = 0; delete d; } void ConfigPage::load() { kDebug(); d->mListView->clear(); d->mFamilyMap.clear(); d->mInfoMap.clear(); QStringList familyDisplayNames; // KDE-3.3 compatibility code: get families from the plugins QStringList compatFamilyNames; const KService::List plugins = KServiceTypeTrader::self()->query( QLatin1String("KResources/Plugin") ); KService::List::ConstIterator it = plugins.begin(); KService::List::ConstIterator end = plugins.end(); for ( ; it != end; ++it ) { const QString family = ( *it )->property( QLatin1String("X-KDE-ResourceFamily") ).toString(); if ( compatFamilyNames.indexOf( family ) == -1 ) { compatFamilyNames.append( family ); } } const KService::List managers = KServiceTypeTrader::self()->query( QLatin1String("KResources/Manager") ); KService::List::ConstIterator m_it; for ( m_it = managers.begin(); m_it != managers.end(); ++m_it ) { QString displayName = ( *m_it )->property( QLatin1String("Name") ).toString(); familyDisplayNames.append( displayName ); QString family = ( *m_it )->property( QLatin1String("X-KDE-ResourceFamily") ).toString(); if ( !family.isEmpty() ) { compatFamilyNames.removeAll( family ); d->mFamilyMap.append( family ); kDebug() << "Loading manager for family " << family; d->loadManager( family, this ); kDebug() << "Manager for family " << family << " loaded."; } } // Rest of the kde-3.3 compat code QStringList::ConstIterator cfit = compatFamilyNames.constBegin(); for ( ; cfit != compatFamilyNames.constEnd(); ++cfit ) { d->mFamilyMap.append( *cfit ); familyDisplayNames.append( *cfit ); d->loadManager( *cfit, this ); } d->mCurrentManager = 0; d->mFamilyCombo->clear(); d->mFamilyCombo->insertItems( 0, familyDisplayNames ); int currentFamily = d->mConfigGroup->readEntry( "CurrentFamily", 0 ); d->mFamilyCombo->setCurrentIndex( currentFamily ); slotFamilyChanged( currentFamily ); emit changed( false ); } void ConfigPage::Private::loadManager( const QString &family, ConfigPage *page ) { mCurrentManager = new Manager( family ); if ( mCurrentManager ) { mCurrentManager->addObserver( page ); ResourcePageInfo *info = new ResourcePageInfo; info->mManager = mCurrentManager; info->mConfig = new KConfig( KRES::ManagerImpl::defaultConfigFile( family ) ); info->mManager->readConfig( info->mConfig ); mInfoMap.append( KSharedPtr( info ) ); } } void ConfigPage::save() { d->saveResourceSettings( this ); QList >::Iterator it; for ( it = d->mInfoMap.begin(); it != d->mInfoMap.end(); ++it ) { ( *it )->mManager->writeConfig( ( *it )->mConfig ); } emit changed( false ); } void ConfigPage::defaults() { } void ConfigPage::slotFamilyChanged( int pos ) { if ( pos < 0 || pos >= (int)d->mFamilyMap.count() ) { return; } d->saveResourceSettings( this ); d->mFamily = d->mFamilyMap[ pos ]; d->mCurrentManager = d->mInfoMap[ pos ]->mManager; d->mCurrentConfig = d->mInfoMap[ pos ]->mConfig; if ( !d->mCurrentManager ) { kDebug() << "ERROR: cannot create ResourceManager( mFamily )"; } d->mListView->clear(); if ( d->mCurrentManager->isEmpty() ) { defaults(); } Resource *standardResource = d->mCurrentManager->standardResource(); Manager::Iterator it; for ( it = d->mCurrentManager->begin(); it != d->mCurrentManager->end(); ++it ) { ConfigViewItem *item = new ConfigViewItem( d->mListView, *it ); if ( *it == standardResource ) { item->setStandard( true ); } } if ( d->mListView->topLevelItemCount() == 0 ) { defaults(); emit changed( true ); d->mCurrentManager->writeConfig( d->mCurrentConfig ); } else { if ( !standardResource ) { KMessageBox::sorry( this, i18n( "There is no standard resource. Please select one." ) ); } emit changed( false ); } } void ConfigPage::slotAdd() { if ( !d->mCurrentManager ) { return; } QStringList types = d->mCurrentManager->resourceTypeNames(); QStringList descs = d->mCurrentManager->resourceTypeDescriptions(); bool ok = false; QString desc = KInputDialog::getItem( i18n( "Resource Configuration" ), i18n( "Please select type of the new resource:" ), descs, 0, false, &ok, this ); if ( !ok ) { return; } QString type = types[ descs.indexOf( desc ) ]; // Create new resource Resource *resource = d->mCurrentManager->createResource( type ); if ( !resource ) { KMessageBox::error( this, i18n( "Unable to create resource of type '%1'.", type ) ); return; } resource->setResourceName( type + QLatin1String("-resource") ); ConfigDialog dlg( this, d->mFamily, resource ); if ( dlg.exec() ) { //krazy:exclude=crashy d->mCurrentManager->add( resource ); ConfigViewItem *item = new ConfigViewItem( d->mListView, resource ); d->mLastItem = item; // if there are only read-only resources we'll set this resource // as standard resource if ( !resource->readOnly() ) { bool onlyReadOnly = true; for ( int i = 0; i < d->mListView->topLevelItemCount(); ++i ) { ConfigViewItem *confIt = static_cast( d->mListView->topLevelItem( i ) ); if ( !confIt->readOnly() && confIt != item ) { onlyReadOnly = false; } } if ( onlyReadOnly ) { item->setStandard( true ); } } emit changed( true ); } else { delete resource; resource = 0; } } void ConfigPage::slotRemove() { if ( !d->mCurrentManager ) { return; } QTreeWidgetItem *item = d->mListView->currentItem(); ConfigViewItem *confItem = static_cast( item ); if ( !confItem ) { return; } if ( confItem->standard() ) { KMessageBox::sorry( this, i18n( "You cannot remove your standard resource. " "Please select a new standard resource first." ) ); return; } d->mCurrentManager->remove( confItem->resource() ); if ( item == d->mLastItem ) { d->mLastItem = 0; } d->mListView->takeTopLevelItem( d->mListView->indexOfTopLevelItem( item ) ); delete item; emit changed( true ); } void ConfigPage::slotEdit() { if ( !d->mCurrentManager ) { return; } QTreeWidgetItem *item = d->mListView->currentItem(); ConfigViewItem *configItem = static_cast( item ); if ( !configItem ) { return; } Resource *resource = configItem->resource(); ConfigDialog dlg( this, d->mFamily, resource ); if ( dlg.exec() ) { //krazy:exclude=crashy configItem->setText( 0, resource->resourceName() ); configItem->setText( 1, resource->type() ); if ( configItem->standard() && configItem->readOnly() ) { KMessageBox::sorry( this, i18n( "You cannot use a read-only resource as standard." ) ); configItem->setStandard( false ); } d->mCurrentManager->change( resource ); emit changed( true ); } } void ConfigPage::slotStandard() { if ( !d->mCurrentManager ) { return; } ConfigViewItem *item = static_cast( d->mListView->currentItem() ); if ( !item ) { return; } if ( item->readOnly() ) { KMessageBox::sorry( this, i18n( "You cannot use a read-only resource as standard." ) ); return; } if ( !item->isOn() ) { KMessageBox::sorry( this, i18n( "You cannot use an inactive resource as standard." ) ); return; } for ( int i = 0; i < d->mListView->topLevelItemCount(); ++i ) { ConfigViewItem *configItem = static_cast( d->mListView->topLevelItem( i ) ); if ( configItem->standard() ) { configItem->setStandard( false ); } } item->setStandard( true ); d->mCurrentManager->setStandardResource( item->resource() ); emit changed( true ); } void ConfigPage::slotSelectionChanged() { bool state = ( d->mListView->currentItem() != 0 ); d->mRemoveButton->setEnabled( state ); d->mEditButton->setEnabled( state ); d->mStandardButton->setEnabled( state ); } void ConfigPage::resourceAdded( Resource *resource ) { kDebug() << resource->resourceName(); ConfigViewItem *item = new ConfigViewItem( d->mListView, resource ); item->setCheckState( 0, resource->isActive()? Qt::Checked : Qt::Unchecked ); d->mLastItem = item; emit changed( true ); } void ConfigPage::resourceModified( Resource *resource ) { kDebug() << resource->resourceName(); ConfigViewItem *item = findItem( resource ); if ( !item ) { return; } // TODO: Reread resource config. Otherwise we won't see the modification. item->updateItem(); } void ConfigPage::resourceDeleted( Resource *resource ) { kDebug() << resource->resourceName(); ConfigViewItem *item = findItem( resource ); if ( !item ) { return; } delete item; } ConfigViewItem *ConfigPage::findItem( Resource *resource ) { for ( int i = 0; i < d->mListView->topLevelItemCount(); ++i ) { ConfigViewItem *item = static_cast( d->mListView->topLevelItem( i ) ); if ( item->resource() == resource ) { return item; } } return 0; } void ConfigPage::slotItemClicked( QTreeWidgetItem *item ) { ConfigViewItem *configItem = static_cast( item ); if ( !configItem ) { return; } if ( configItem->standard() && !configItem->isOn() ) { KMessageBox::sorry( this, i18n( "You cannot deactivate the standard resource. " "Choose another standard resource first." ) ); configItem->setCheckState( 0, Qt::Checked ); return; } if ( configItem->isOn() != configItem->resource()->isActive() ) { emit changed( true ); } } void ConfigPage::Private::saveResourceSettings( ConfigPage *page ) { if ( mCurrentManager ) { for ( int i = 0; i < mListView->topLevelItemCount(); ++i ) { ConfigViewItem *configItem = static_cast( mListView->topLevelItem( i ) ); // check if standard resource if ( configItem->standard() && !configItem->readOnly() && configItem->isOn() ) { mCurrentManager->setStandardResource( configItem->resource() ); } // check if active or passive resource configItem->resource()->setActive( configItem->isOn() ); } mCurrentManager->writeConfig( mCurrentConfig ); if ( !mCurrentManager->standardResource() ) { KMessageBox::sorry( page, i18n( "There is no valid standard resource. " "Please select one which is neither read-only nor inactive." ) ); } } } }