1
/*****************************************************************************
2
* Copyright (C) 2009 Ben Cooksley <bcooksley@kde.org> *
3
* Copyright (C) 2009 by Mathias Soeken <msoeken@informatik.uni-bremen.de> *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, write to the *
17
* Free Software Foundation, Inc., *
18
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
19
*****************************************************************************/
21
#include "ModuleView.h"
22
#include "ExternalAppModule.h"
29
#include <QScrollArea>
30
#include <QVBoxLayout>
31
#include <QAbstractItemModel>
36
#include <KPageWidget>
37
#include <KPushButton>
38
#include <KAuthorized>
39
#include <KMessageBox>
40
#include <KCModuleInfo>
41
#include <KCModuleProxy>
42
#include <KStandardGuiItem>
43
#include <KDialogButtonBox>
44
#include <kauthaction.h>
48
class ModuleView::Private {
51
QMap<KPageWidgetItem*, KCModuleProxy*> mPages;
52
QMap<KPageWidgetItem*, KCModuleInfo*> mModules;
53
KPageWidget* mPageWidget;
55
KDialogButtonBox* mButtons;
58
KPushButton* mDefault;
60
bool pageChangeSupressed;
63
ModuleView::ModuleView( QWidget * parent )
67
// Configure a layout first
68
d->mLayout = new QVBoxLayout(this);
69
// Create the Page Widget
70
d->mPageWidget = new KPageWidget(this);
71
d->mPageWidget->layout()->setMargin(0);
72
d->mLayout->addWidget(d->mPageWidget);
74
d->mButtons = new KDialogButtonBox( this, Qt::Horizontal );
75
d->mLayout->addWidget(d->mButtons);
77
// Create the buttons in it
78
d->mApply = d->mButtons->addButton( KStandardGuiItem::apply(), QDialogButtonBox::ApplyRole );
79
d->mDefault = d->mButtons->addButton( KStandardGuiItem::defaults(), QDialogButtonBox::ResetRole );
80
d->mReset = d->mButtons->addButton( KStandardGuiItem::reset(), QDialogButtonBox::ResetRole );
81
d->mHelp = d->mButtons->addButton( KStandardGuiItem::help(), QDialogButtonBox::HelpRole );
82
// Set some more sensible tooltips
83
d->mReset->setToolTip( i18n("Reset all current changes to previous values") );
84
// Set Auto-Default mode ( KDE Bug #211187 )
85
d->mApply->setAutoDefault(true);
86
d->mDefault->setAutoDefault(true);
87
d->mReset->setAutoDefault(true);
88
d->mHelp->setAutoDefault(true);
89
// Prevent the buttons from being used
90
d->mApply->setEnabled(false);
91
d->mDefault->setEnabled(false);
92
d->mReset->setEnabled(false);
93
d->mHelp->setEnabled(false);
94
// Connect up the buttons
95
connect( d->mApply, SIGNAL(clicked()), this, SLOT(moduleSave()) );
96
connect( d->mReset, SIGNAL(clicked()), this, SLOT(moduleLoad()) );
97
connect( d->mHelp, SIGNAL(clicked()), this, SLOT(moduleHelp()) );
98
connect( d->mDefault, SIGNAL(clicked()), this, SLOT(moduleDefaults()) );
99
connect( d->mPageWidget, SIGNAL(currentPageChanged(KPageWidgetItem*, KPageWidgetItem*)),
100
this, SLOT(activeModuleChanged(KPageWidgetItem*, KPageWidgetItem*)) );
101
connect( this, SIGNAL(moduleChanged(bool)), this, SLOT(updateButtons()) );
104
ModuleView::~ModuleView()
109
KCModuleInfo * ModuleView::activeModule() const
111
return d->mModules.value( d->mPageWidget->currentPage() );
114
const KAboutData * ModuleView::aboutData() const
116
KCModuleProxy * activeModule = d->mPages.value( d->mPageWidget->currentPage() );
117
KAboutData * aboutData = 0;
119
aboutData = const_cast<KAboutData*>( activeModule->aboutData() );
122
aboutData->setProgramIconName( activeModule->moduleInfo().service()->icon() );
128
void ModuleView::loadModule( QModelIndex menuItem )
130
if ( !menuItem.isValid() ) {
134
QList<QModelIndex> indexes;
135
for ( int done = 0; menuItem.model()->rowCount( menuItem ) > done; done = 1 + done ) {
136
indexes << menuItem.model()->index( done, 0, menuItem );
138
if ( indexes.empty() ) {
142
foreach ( QModelIndex module, indexes ) {
143
MenuItem *menuItem = module.data( Qt::UserRole ).value<MenuItem*>();
144
addModule( &menuItem->item() );
146
// changing state is not needed here as the adding / changing of pages does it
149
void ModuleView::addModule( KCModuleInfo *module )
154
if( !module->service() ) {
155
kWarning() << "ModuleInfo has no associated KService" ;
158
if ( !KAuthorized::authorizeControlModule( module->service()->menuId() ) ) {
159
kWarning() << "Not authorised to load module" ;
162
if( module->service()->noDisplay() ) {
166
// Create the scroller
167
QScrollArea * moduleScroll = new QScrollArea( this );
168
// Prepare the scroll area
169
moduleScroll->setWidgetResizable( true );
170
moduleScroll->setFrameStyle( QFrame::NoFrame );
171
moduleScroll->viewport()->setAutoFillBackground( false );
173
KPageWidgetItem *page = new KPageWidgetItem( moduleScroll, module->moduleName() );
174
// Provide information to the users
176
if( module->service()->hasServiceType("SystemSettingsExternalApp") ) { // Is it an external app?
177
QWidget * externalWidget = new ExternalAppModule( this, module );
178
moduleScroll->setWidget( externalWidget );
179
} else { // It must be a normal module then
180
KCModuleProxy * moduleProxy = new KCModuleProxy( *module, moduleScroll );
181
moduleScroll->setWidget( moduleProxy );
182
moduleProxy->setAutoFillBackground( false );
183
connect( moduleProxy, SIGNAL(changed(bool)), this, SLOT(stateChanged()));
184
d->mPages.insert( page, moduleProxy );
187
d->mModules.insert( page, module );
188
updatePageIconHeader( page, true );
190
d->mPageWidget->addPage( page );
193
void ModuleView::updatePageIconHeader( KPageWidgetItem * page, bool light )
196
// Page is invalid. Probably means we have a race condition during closure of everyone so do nothing
200
KCModuleProxy * moduleProxy = d->mPages.value( page );
201
KCModuleInfo * moduleInfo = d->mModules.value( page );
204
// Seems like we have some form of a race condition going on here...
208
page->setHeader( moduleInfo->comment() );
209
page->setIcon( KIcon( moduleInfo->icon() ) );
214
if( moduleProxy && moduleProxy->realModule()->useRootOnlyMessage() ) {
215
page->setHeader( "<b>" + moduleInfo->comment() + "</b><br><i>" + moduleProxy->rootOnlyMessage() + "</i>" );
216
page->setIcon( KIcon( moduleInfo->icon(), 0, QStringList() << "dialog-warning" ) );
220
bool ModuleView::resolveChanges()
222
KCModuleProxy * currentProxy = d->mPages.value( d->mPageWidget->currentPage() );
223
return resolveChanges(currentProxy);
226
bool ModuleView::resolveChanges(KCModuleProxy * currentProxy)
228
if( !currentProxy || !currentProxy->changed() ) {
232
// Let the user decide
233
KGuiItem applyItem = KStandardGuiItem::apply();
234
applyItem.setIcon( KIcon(d->mApply->icon()) );
235
const int queryUser = KMessageBox::warningYesNoCancel(
237
i18n("The settings of the current module have changed.\n"
238
"Do you want to apply the changes or discard them?"),
239
i18n("Apply Settings"),
241
KStandardGuiItem::discard(),
242
KStandardGuiItem::cancel() );
245
case KMessageBox::Yes:
246
return moduleSave(currentProxy);
248
case KMessageBox::No:
249
currentProxy->load();
252
case KMessageBox::Cancel:
261
void ModuleView::closeModules()
263
d->pageChangeSupressed = true;
264
d->mApply->setAuthAction( 0 ); // Ensure KAuth knows that authentication is now pointless...
265
QMap<KPageWidgetItem*, KCModuleInfo*>::iterator page = d->mModules.begin();
266
QMap<KPageWidgetItem*, KCModuleInfo*>::iterator pageEnd = d->mModules.end();
267
for ( ; page != pageEnd; ++page ) {
268
d->mPageWidget->removePage( page.key() );
273
d->pageChangeSupressed = false;
276
bool ModuleView::moduleSave()
278
KCModuleProxy * moduleProxy = d->mPages.value( d->mPageWidget->currentPage() );
279
return moduleSave( moduleProxy );
282
bool ModuleView::moduleSave(KCModuleProxy *module)
292
void ModuleView::moduleLoad()
294
KCModuleProxy * activeModule = d->mPages.value( d->mPageWidget->currentPage() );
296
activeModule->load();
300
void ModuleView::moduleDefaults()
302
KCModuleProxy * activeModule = d->mPages.value( d->mPageWidget->currentPage() );
304
activeModule->defaults();
308
void ModuleView::moduleHelp()
310
KCModuleInfo * activeModule = d->mModules.value( d->mPageWidget->currentPage() );
311
if( !activeModule ) {
315
QString docPath = activeModule->docPath();
316
if( docPath.isEmpty() ) {
319
KUrl url( KUrl("help:/"), docPath );
320
QProcess::startDetached("khelpcenter", QStringList() << url.url());
323
void ModuleView::activeModuleChanged(KPageWidgetItem * current, KPageWidgetItem * previous)
325
d->mPageWidget->blockSignals(true);
326
d->mPageWidget->setCurrentPage(previous);
327
KCModuleProxy * previousModule = d->mPages.value(previous);
328
if( resolveChanges(previousModule) ) {
329
d->mPageWidget->setCurrentPage(current);
331
d->mPageWidget->blockSignals(false);
332
if( d->pageChangeSupressed ) {
335
// We need to get the state of the now active module
339
void ModuleView::stateChanged()
341
KCModuleProxy * activeModule = d->mPages.value( d->mPageWidget->currentPage() );
342
KAuth::Action * moduleAction = 0;
345
change = activeModule->changed();
347
disconnect( d->mApply, SIGNAL(authorized(KAuth::Action*)), this, SLOT(moduleSave()) );
348
disconnect( d->mApply, SIGNAL(clicked()), this, SLOT(moduleSave()) );
349
if( activeModule->realModule()->authAction() ) {
350
connect( d->mApply, SIGNAL(authorized(KAuth::Action*)), this, SLOT(moduleSave()) );
351
moduleAction = activeModule->realModule()->authAction();
353
connect( d->mApply, SIGNAL(clicked()), this, SLOT(moduleSave()) );
357
updatePageIconHeader( d->mPageWidget->currentPage() );
358
d->mApply->setAuthAction( moduleAction );
359
d->mApply->setEnabled( change );
360
d->mReset->setEnabled( change );
361
emit moduleChanged( change );
364
void ModuleView::keyPressEvent ( QKeyEvent * event )
366
if ( event->key() == Qt::Key_F1 && d->mHelp->isVisible() && d->mHelp->isEnabled()) {
367
d->mHelp->animateClick();
370
} else if ( event->key() == Qt::Key_Escape ) {
374
} else if ( event->key() == Qt::Key_F1 && event->modifiers() == Qt::ShiftModifier ) {
375
QWhatsThis::enterWhatsThisMode();
380
QWidget::keyPressEvent( event );
383
void ModuleView::updateButtons()
385
KCModuleProxy * activeModule = d->mPages.value( d->mPageWidget->currentPage() );
386
if( !activeModule ) {
390
const int buttons = activeModule->buttons();
392
d->mApply->setShown(buttons & KCModule::Apply );
393
d->mReset->setShown(buttons & KCModule::Apply );
395
d->mHelp->setEnabled(buttons & KCModule::Help );
396
d->mDefault->setEnabled(buttons & KCModule::Default );
399
#include "ModuleView.moc"