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