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