00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <assert.h>
00031 #include <qdir.h>
00032 #include <qfileinfo.h>
00033 #include <qlayout.h>
00034 #include <qwhatsthis.h>
00035 #include <qgroupbox.h>
00036 #include <qcheckbox.h>
00037 #include <qtabwidget.h>
00038 #include <qvbox.h>
00039 #include <qlabel.h>
00040 #include <qfile.h>
00041 #include <qslider.h>
00042
00043 #include <kapplication.h>
00044 #include <kcombobox.h>
00045 #include <kdebug.h>
00046 #include <kdesktopfile.h>
00047 #include <kstandarddirs.h>
00048 #include <kglobal.h>
00049 #include <klocale.h>
00050 #include <kdialog.h>
00051 #include <kgenericfactory.h>
00052 #include <kaboutdata.h>
00053 #include <dcopclient.h>
00054
00055 #include "kwindecoration.h"
00056 #include "preview.h"
00057 #include <kdecoration_plugins_p.h>
00058 #include <kdecorationfactory.h>
00059
00060
00061
00062 typedef KGenericFactory<KWinDecorationModule, QWidget> KWinDecoFactory;
00063 K_EXPORT_COMPONENT_FACTORY( kcm_kwindecoration, KWinDecoFactory("kcmkwindecoration") )
00064
00065 KWinDecorationModule::KWinDecorationModule(QWidget* parent, const char* name, const QStringList &)
00066 : DCOPObject("KWinClientDecoration"),
00067 KCModule(KWinDecoFactory::instance(), parent, name),
00068 kwinConfig("kwinrc"),
00069 pluginObject(0)
00070 {
00071 kwinConfig.setGroup("Style");
00072 plugins = new KDecorationPreviewPlugins( &kwinConfig );
00073
00074 QVBoxLayout* layout = new QVBoxLayout(this, 0, KDialog::spacingHint());
00075
00076
00077
00078
00079
00080 tabWidget = new QTabWidget( this );
00081 layout->addWidget( tabWidget );
00082
00083
00084 QWidget *pluginPage = new QWidget( tabWidget );
00085
00086 QVBoxLayout* pluginLayout = new QVBoxLayout(pluginPage, KDialog::marginHint(), KDialog::spacingHint());
00087
00088
00089 decorationList = new KComboBox( pluginPage );
00090 QString whatsThis = i18n("Select the window decoration. This is the look and feel of both "
00091 "the window borders and the window handle.");
00092 QWhatsThis::add(decorationList, whatsThis);
00093 pluginLayout->addWidget(decorationList);
00094
00095 QGroupBox *pluginSettingsGrp = new QGroupBox( i18n("Decoration Options"), pluginPage );
00096 pluginSettingsGrp->setColumnLayout( 0, Vertical );
00097 pluginSettingsGrp->setFlat( true );
00098 pluginSettingsGrp->layout()->setMargin( 0 );
00099 pluginSettingsGrp->layout()->setSpacing( KDialog::spacingHint() );
00100 pluginLayout->addWidget( pluginSettingsGrp );
00101
00102 pluginLayout->addStretch();
00103
00104
00105 lBorder = new QLabel (i18n("B&order size:"), pluginSettingsGrp);
00106 cBorder = new QComboBox(pluginSettingsGrp);
00107 lBorder->setBuddy(cBorder);
00108 QWhatsThis::add( cBorder, i18n( "Use this combobox to change the border size of the decoration." ));
00109 lBorder->hide();
00110 cBorder->hide();
00111 QHBoxLayout *borderSizeLayout = new QHBoxLayout(pluginSettingsGrp->layout() );
00112 borderSizeLayout->addWidget(lBorder);
00113 borderSizeLayout->addWidget(cBorder);
00114 borderSizeLayout->addStretch();
00115
00116 pluginConfigWidget = new QVBox(pluginSettingsGrp);
00117 pluginSettingsGrp->layout()->add( pluginConfigWidget );
00118
00119
00120 QWidget* buttonPage = new QWidget( tabWidget );
00121 QVBoxLayout* buttonLayout = new QVBoxLayout(buttonPage, KDialog::marginHint(), KDialog::spacingHint());
00122
00123 cbShowToolTips = new QCheckBox(
00124 i18n("&Show window button tooltips"), buttonPage );
00125 QWhatsThis::add( cbShowToolTips,
00126 i18n( "Enabling this checkbox will show window button tooltips. "
00127 "If this checkbox is off, no window button tooltips will be shown."));
00128
00129 cbUseCustomButtonPositions = new QCheckBox(
00130 i18n("Use custom titlebar button &positions"), buttonPage );
00131 QWhatsThis::add( cbUseCustomButtonPositions,
00132 i18n( "The appropriate settings can be found in the \"Buttons\" Tab; "
00133 "please note that this option is not available on all styles yet." ) );
00134
00135 buttonLayout->addWidget( cbShowToolTips );
00136 buttonLayout->addWidget( cbUseCustomButtonPositions );
00137
00138
00139 buttonPositionWidget = new ButtonPositionWidget(buttonPage, "button_position_widget");
00140 buttonPositionWidget->setDecorationFactory(plugins->factory() );
00141 QHBoxLayout* buttonControlLayout = new QHBoxLayout(buttonLayout);
00142 buttonControlLayout->addSpacing(20);
00143 buttonControlLayout->addWidget(buttonPositionWidget);
00144
00145
00146
00147 QVBoxLayout* previewLayout = new QVBoxLayout(layout, KDialog::spacingHint() );
00148 previewLayout->setMargin( KDialog::marginHint() );
00149
00150 preview = new KDecorationPreview( this );
00151 previewLayout->addWidget(preview);
00152
00153 preview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00154 tabWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
00155
00156
00157
00158 findDecorations();
00159 createDecorationList();
00160 readConfig( &kwinConfig );
00161 resetPlugin( &kwinConfig );
00162
00163 tabWidget->insertTab( pluginPage, i18n("&Window Decoration") );
00164 tabWidget->insertTab( buttonPage, i18n("&Buttons") );
00165
00166 connect( buttonPositionWidget, SIGNAL(changed()), this, SLOT(slotButtonsChanged()) );
00167 connect( buttonPositionWidget, SIGNAL(changed()), this, SLOT(slotSelectionChanged()) );
00168 connect( decorationList, SIGNAL(activated(const QString&)), SLOT(slotSelectionChanged()) );
00169 connect( decorationList, SIGNAL(activated(const QString&)),
00170 SLOT(slotChangeDecoration(const QString&)) );
00171 connect( cbUseCustomButtonPositions, SIGNAL(clicked()), SLOT(slotSelectionChanged()) );
00172 connect(cbUseCustomButtonPositions, SIGNAL(toggled(bool)), buttonPositionWidget, SLOT(setEnabled(bool)));
00173 connect(cbUseCustomButtonPositions, SIGNAL(toggled(bool)), this, SLOT(slotButtonsChanged()) );
00174 connect( cbShowToolTips, SIGNAL(clicked()), SLOT(slotSelectionChanged()) );
00175 connect( cBorder, SIGNAL( activated( int )), SLOT( slotBorderChanged( int )));
00176
00177
00178
00179 connectDCOPSignal("kwin", 0, "dcopResetAllClients()", "dcopUpdateClientList()", false);
00180
00181 KAboutData *about =
00182 new KAboutData(I18N_NOOP("kcmkwindecoration"),
00183 I18N_NOOP("Window Decoration Control Module"),
00184 0, 0, KAboutData::License_GPL,
00185 I18N_NOOP("(c) 2001 Karol Szwed"));
00186 about->addAuthor("Karol Szwed", 0, "gallium@kde.org");
00187 setAboutData(about);
00188 }
00189
00190
00191 KWinDecorationModule::~KWinDecorationModule()
00192 {
00193 delete preview;
00194 delete plugins;
00195 }
00196
00197
00198
00199
00200 void KWinDecorationModule::findDecorations()
00201 {
00202 QStringList dirList = KGlobal::dirs()->findDirs("data", "kwin");
00203 QStringList::ConstIterator it;
00204
00205 for (it = dirList.begin(); it != dirList.end(); it++)
00206 {
00207 QDir d(*it);
00208 if (d.exists())
00209 for (QFileInfoListIterator it(*d.entryInfoList()); it.current(); ++it)
00210 {
00211 QString filename(it.current()->absFilePath());
00212 if (KDesktopFile::isDesktopFile(filename))
00213 {
00214 KDesktopFile desktopFile(filename);
00215 QString libName = desktopFile.readEntry("X-KDE-Library");
00216
00217 if (!libName.isEmpty() && libName.startsWith( "kwin3_" ))
00218 {
00219 DecorationInfo di;
00220 di.name = desktopFile.readName();
00221 di.libraryName = libName;
00222 decorations.append( di );
00223 }
00224 }
00225 }
00226 }
00227 }
00228
00229
00230
00231 void KWinDecorationModule::createDecorationList()
00232 {
00233 QValueList<DecorationInfo>::ConstIterator it;
00234
00235
00236 QStringList decorationNames;
00237 decorationNames.append( i18n("KDE 2") );
00238 for (it = decorations.begin(); it != decorations.end(); ++it)
00239 {
00240 decorationNames.append((*it).name);
00241 }
00242 decorationNames.sort();
00243 decorationList->insertStringList(decorationNames);
00244 }
00245
00246
00247
00248 void KWinDecorationModule::slotChangeDecoration( const QString & text)
00249 {
00250 KConfig kwinConfig("kwinrc");
00251 kwinConfig.setGroup("Style");
00252
00253
00254 resetPlugin( &kwinConfig, text );
00255 }
00256
00257
00258
00259 void KWinDecorationModule::slotSelectionChanged()
00260 {
00261 emit KCModule::changed(true);
00262 }
00263
00264 static const char* const border_names[ KDecorationDefines::BordersCount ] =
00265 {
00266 I18N_NOOP( "Tiny" ),
00267 I18N_NOOP( "Normal" ),
00268 I18N_NOOP( "Large" ),
00269 I18N_NOOP( "Very Large" ),
00270 I18N_NOOP( "Huge" ),
00271 I18N_NOOP( "Very Huge" ),
00272 I18N_NOOP( "Oversized" )
00273 };
00274
00275 int KWinDecorationModule::borderSizeToIndex( BorderSize size, QValueList< BorderSize > sizes )
00276 {
00277 int pos = 0;
00278 for( QValueList< BorderSize >::ConstIterator it = sizes.begin();
00279 it != sizes.end();
00280 ++it, ++pos )
00281 if( size <= *it )
00282 break;
00283 return pos;
00284 }
00285
00286 KDecorationDefines::BorderSize KWinDecorationModule::indexToBorderSize( int index,
00287 QValueList< BorderSize > sizes )
00288 {
00289 QValueList< BorderSize >::ConstIterator it = sizes.begin();
00290 for(;
00291 it != sizes.end();
00292 ++it, --index )
00293 if( index == 0 )
00294 break;
00295 return *it;
00296 }
00297
00298 void KWinDecorationModule::slotBorderChanged( int size )
00299 {
00300 if( lBorder->isHidden())
00301 return;
00302 emit KCModule::changed( true );
00303 QValueList< BorderSize > sizes;
00304 if( plugins->factory() != NULL )
00305 sizes = plugins->factory()->borderSizes();
00306 assert( sizes.count() >= 2 );
00307 border_size = indexToBorderSize( size, sizes );
00308
00309
00310 preview->setTempBorderSize(plugins, border_size);
00311 }
00312
00313 void KWinDecorationModule::slotButtonsChanged()
00314 {
00315
00316 preview->setTempButtons(plugins, cbUseCustomButtonPositions->isChecked(), buttonPositionWidget->buttonsLeft(), buttonPositionWidget->buttonsRight() );
00317 }
00318
00319 QString KWinDecorationModule::decorationName( QString& libName )
00320 {
00321 QString decoName;
00322
00323 QValueList<DecorationInfo>::Iterator it;
00324 for( it = decorations.begin(); it != decorations.end(); ++it )
00325 if ( (*it).libraryName == libName )
00326 {
00327 decoName = (*it).name;
00328 break;
00329 }
00330
00331 return decoName;
00332 }
00333
00334
00335 QString KWinDecorationModule::decorationLibName( const QString& name )
00336 {
00337 QString libName;
00338
00339
00340
00341 QValueList<DecorationInfo>::Iterator it;
00342 for( it = decorations.begin(); it != decorations.end(); ++it )
00343 if ( (*it).name == name )
00344 {
00345 libName = (*it).libraryName;
00346 break;
00347 }
00348
00349 if (libName.isEmpty())
00350 libName = "kwin_default";
00351
00352 return libName;
00353 }
00354
00355
00356
00357
00358 void KWinDecorationModule::resetPlugin( KConfig* conf, const QString& currentDecoName )
00359 {
00360
00361
00362
00363 QString oldName = styleToConfigLib( oldLibraryName );
00364
00365 QString currentName;
00366 if (!currentDecoName.isEmpty())
00367 currentName = decorationLibName( currentDecoName );
00368 else
00369 currentName = currentLibraryName;
00370
00371 if( plugins->loadPlugin( currentName )
00372 && preview->recreateDecoration( plugins ))
00373 preview->enablePreview();
00374 else
00375 preview->disablePreview();
00376 plugins->destroyPreviousPlugin();
00377
00378 checkSupportedBorderSizes();
00379
00380
00381 buttonPositionWidget->setDecorationFactory(plugins->factory() );
00382
00383 currentName = styleToConfigLib( currentName );
00384
00385
00386 delete pluginObject;
00387 pluginObject = 0;
00388
00389
00390 KLibLoader* loader = KLibLoader::self();
00391
00392
00393 if (!oldLibraryName.isNull())
00394 loader->unloadLibrary( QFile::encodeName(oldName) );
00395
00396 KLibrary* library = loader->library( QFile::encodeName(currentName) );
00397 if (library != NULL)
00398 {
00399 void* alloc_ptr = library->symbol("allocate_config");
00400
00401 if (alloc_ptr != NULL)
00402 {
00403 allocatePlugin = (QObject* (*)(KConfig* conf, QWidget* parent))alloc_ptr;
00404 pluginObject = (QObject*)(allocatePlugin( conf, pluginConfigWidget ));
00405
00406
00407 connect( pluginObject, SIGNAL(changed()), this, SLOT(slotSelectionChanged()) );
00408 connect( this, SIGNAL(pluginLoad(KConfig*)), pluginObject, SLOT(load(KConfig*)) );
00409 connect( this, SIGNAL(pluginSave(KConfig*)), pluginObject, SLOT(save(KConfig*)) );
00410 connect( this, SIGNAL(pluginDefaults()), pluginObject, SLOT(defaults()) );
00411 pluginConfigWidget->show();
00412 return;
00413 }
00414 }
00415
00416 pluginConfigWidget->hide();
00417 }
00418
00419
00420
00421
00422 void KWinDecorationModule::readConfig( KConfig* conf )
00423 {
00424
00425
00426 cbShowToolTips->setChecked( conf->readBoolEntry("ShowToolTips", true ));
00427
00428
00429
00430
00431
00432 oldLibraryName = currentLibraryName;
00433 currentLibraryName = conf->readEntry("PluginLib",
00434 ((QPixmap::defaultDepth() > 8) ? "kwin_plastik" : "kwin_quartz"));
00435 QString decoName = decorationName( currentLibraryName );
00436
00437
00438 if (decoName.isEmpty())
00439 decoName = i18n("KDE 2");
00440
00441 int numDecos = decorationList->count();
00442 for (int i = 0; i < numDecos; ++i)
00443 {
00444 if (decorationList->text(i) == decoName)
00445 {
00446 decorationList->setCurrentItem(i);
00447 break;
00448 }
00449 }
00450
00451
00452
00453 bool customPositions = conf->readBoolEntry("CustomButtonPositions", false);
00454 cbUseCustomButtonPositions->setChecked( customPositions );
00455 buttonPositionWidget->setEnabled( customPositions );
00456
00457 buttonPositionWidget->setButtonsLeft( conf->readEntry("ButtonsOnLeft", "MS") );
00458
00459 buttonPositionWidget->setButtonsRight( conf->readEntry("ButtonsOnRight", "HIAX") );
00460
00461 int bsize = conf->readNumEntry( "BorderSize", BorderNormal );
00462 if( bsize >= BorderTiny && bsize < BordersCount )
00463 border_size = static_cast< BorderSize >( bsize );
00464 else
00465 border_size = BorderNormal;
00466 checkSupportedBorderSizes();
00467
00468 emit KCModule::changed(false);
00469 }
00470
00471
00472
00473 void KWinDecorationModule::writeConfig( KConfig* conf )
00474 {
00475 QString name = decorationList->currentText();
00476 QString libName = decorationLibName( name );
00477
00478 KConfig kwinConfig("kwinrc");
00479 kwinConfig.setGroup("Style");
00480
00481
00482 conf->writeEntry("PluginLib", libName);
00483 conf->writeEntry("CustomButtonPositions", cbUseCustomButtonPositions->isChecked());
00484 conf->writeEntry("ShowToolTips", cbShowToolTips->isChecked());
00485
00486
00487
00488 conf->writeEntry("ButtonsOnLeft", buttonPositionWidget->buttonsLeft() );
00489 conf->writeEntry("ButtonsOnRight", buttonPositionWidget->buttonsRight() );
00490 conf->writeEntry("BorderSize", border_size );
00491
00492 oldLibraryName = currentLibraryName;
00493 currentLibraryName = libName;
00494
00495
00496 emit KCModule::changed(false);
00497 }
00498
00499
00500 void KWinDecorationModule::dcopUpdateClientList()
00501 {
00502
00503
00504 KConfig kwinConfig("kwinrc");
00505 kwinConfig.setGroup("Style");
00506
00507 readConfig( &kwinConfig );
00508 resetPlugin( &kwinConfig );
00509 }
00510
00511
00512
00513 void KWinDecorationModule::load()
00514 {
00515 KConfig kwinConfig("kwinrc");
00516 kwinConfig.setGroup("Style");
00517
00518
00519 readConfig( &kwinConfig );
00520 resetPlugin( &kwinConfig );
00521 }
00522
00523
00524 void KWinDecorationModule::save()
00525 {
00526 KConfig kwinConfig("kwinrc");
00527 kwinConfig.setGroup("Style");
00528
00529 writeConfig( &kwinConfig );
00530 emit pluginSave( &kwinConfig );
00531
00532 kwinConfig.sync();
00533 resetKWin();
00534
00535 }
00536
00537
00538 void KWinDecorationModule::defaults()
00539 {
00540
00541 cbUseCustomButtonPositions->setChecked( false );
00542 buttonPositionWidget->setEnabled( false );
00543 cbShowToolTips->setChecked( true );
00544
00545
00546
00547
00548
00549 buttonPositionWidget->setButtonsLeft("MS");
00550 buttonPositionWidget->setButtonsRight("HIAX");
00551
00552 border_size = BorderNormal;
00553 checkSupportedBorderSizes();
00554
00555
00556 emit pluginDefaults();
00557 }
00558
00559 void KWinDecorationModule::checkSupportedBorderSizes()
00560 {
00561 QValueList< BorderSize > sizes;
00562 if( plugins->factory() != NULL )
00563 sizes = plugins->factory()->borderSizes();
00564 if( sizes.count() < 2 ) {
00565 lBorder->hide();
00566 cBorder->hide();
00567 } else {
00568 cBorder->clear();
00569 for (QValueList<BorderSize>::const_iterator it = sizes.begin(); it != sizes.end(); ++it) {
00570 BorderSize size = *it;
00571 cBorder->insertItem(i18n(border_names[size]), borderSizeToIndex(size,sizes) );
00572 }
00573 int pos = borderSizeToIndex( border_size, sizes );
00574 lBorder->show();
00575 cBorder->show();
00576 cBorder->setCurrentItem(pos);
00577 slotBorderChanged( pos );
00578 }
00579 }
00580
00581 QString KWinDecorationModule::styleToConfigLib( QString& styleLib )
00582 {
00583 if( styleLib.startsWith( "kwin3_" ))
00584 return "kwin_" + styleLib.mid( 6 ) + "_config";
00585 else
00586 return styleLib + "_config";
00587 }
00588
00589 QString KWinDecorationModule::quickHelp() const
00590 {
00591 return i18n( "<h1>Window Manager Decoration</h1>"
00592 "<p>This module allows you to choose the window border decorations, "
00593 "as well as titlebar button positions and custom decoration options.</p>"
00594 "To choose a theme for your window decoration click on its name and apply your choice by clicking the \"Apply\" button below."
00595 " If you do not want to apply your choice you can click the \"Reset\" button to discard your changes."
00596 "<p>You can configure each theme in the \"Configure [...]\" tab. There are different options specific for each theme.</p>"
00597 "<p>In \"General Options (if available)\" you can activate the \"Buttons\" tab by checking the \"Use custom titlebar button positions\" box."
00598 " In the \"Buttons\" tab you can change the positions of the buttons to your liking.</p>" );
00599 }
00600
00601
00602 void KWinDecorationModule::resetKWin()
00603 {
00604 bool ok = kapp->dcopClient()->send("kwin*", "KWinInterface",
00605 "reconfigure()", QByteArray());
00606 if (!ok)
00607 kdDebug() << "kcmkwindecoration: Could not reconfigure kwin" << endl;
00608 }
00609
00610 #include "kwindecoration.moc"
00611
00612
00613