You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
956 lines
35 KiB
956 lines
35 KiB
/*
|
|
This is the new twindecoration kcontrol module
|
|
|
|
Copyright (c) 2001
|
|
Karol Szwed <gallium@kde.org>
|
|
http://gallium.n3.net/
|
|
|
|
Supports new twin configuration plugins, and titlebar button position
|
|
modification via dnd interface.
|
|
|
|
Based on original "twintheme" (Window Borders)
|
|
Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
|
|
#include <tqdir.h>
|
|
#include <tqfileinfo.h>
|
|
#include <tqlayout.h>
|
|
#include <tqwhatsthis.h>
|
|
#include <tqgroupbox.h>
|
|
#include <tqcheckbox.h>
|
|
#include <tqtabwidget.h>
|
|
#include <tqvbox.h>
|
|
#include <tqlabel.h>
|
|
#include <tqfile.h>
|
|
#include <tqslider.h>
|
|
#include <tqspinbox.h>
|
|
|
|
#include <kapplication.h>
|
|
#include <kcolorbutton.h>
|
|
#include <kcombobox.h>
|
|
#include <kdebug.h>
|
|
#include <kdesktopfile.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kglobal.h>
|
|
#include <klocale.h>
|
|
#include <kdialog.h>
|
|
#include <kgenericfactory.h>
|
|
#include <kaboutdata.h>
|
|
#include <dcopclient.h>
|
|
|
|
#include "twindecoration.h"
|
|
#include "preview.h"
|
|
#include <kdecoration_plugins_p.h>
|
|
#include <kdecorationfactory.h>
|
|
|
|
// KCModule plugin interface
|
|
// =========================
|
|
typedef KGenericFactory<KWinDecorationModule, TQWidget> KWinDecoFactory;
|
|
K_EXPORT_COMPONENT_FACTORY( kcm_twindecoration, KWinDecoFactory("kcmtwindecoration") )
|
|
|
|
KWinDecorationModule::KWinDecorationModule(TQWidget* parent, const char* name, const TQStringList &)
|
|
: DCOPObject("KWinClientDecoration"),
|
|
KCModule(KWinDecoFactory::instance(), parent, name),
|
|
twinConfig("twinrc"),
|
|
pluginObject(0)
|
|
{
|
|
twinConfig.setGroup("Style");
|
|
plugins = new KDecorationPreviewPlugins( &twinConfig );
|
|
|
|
TQVBoxLayout* layout = new TQVBoxLayout(this, 0, KDialog::spacingHint());
|
|
|
|
// Save this for later...
|
|
// cbUseMiniWindows = new TQCheckBox( i18n( "Render mini &titlebars for all windows"), checkGroup );
|
|
// TQWhatsThis::add( cbUseMiniWindows, i18n( "Note that this option is not available on all styles yet!" ) );
|
|
|
|
tabWidget = new TQTabWidget( this );
|
|
layout->addWidget( tabWidget );
|
|
|
|
// Page 1 (General Options)
|
|
pluginPage = new TQWidget( tabWidget );
|
|
|
|
TQVBoxLayout* pluginLayout = new TQVBoxLayout(pluginPage, KDialog::marginHint(), KDialog::spacingHint());
|
|
|
|
// decoration chooser
|
|
decorationList = new KComboBox( pluginPage );
|
|
TQString whatsThis = i18n("Select the window decoration. This is the look and feel of both "
|
|
"the window borders and the window handle.");
|
|
TQWhatsThis::add(decorationList, whatsThis);
|
|
pluginLayout->addWidget(decorationList);
|
|
|
|
TQGroupBox *pluginSettingsGrp = new TQGroupBox( i18n("Decoration Options"), pluginPage );
|
|
pluginSettingsGrp->setColumnLayout( 0, Qt::Vertical );
|
|
pluginSettingsGrp->setFlat( true );
|
|
pluginSettingsGrp->layout()->setMargin( 0 );
|
|
pluginSettingsGrp->layout()->setSpacing( KDialog::spacingHint() );
|
|
pluginLayout->addWidget( pluginSettingsGrp );
|
|
|
|
pluginLayout->addStretch();
|
|
|
|
// Border size chooser
|
|
lBorder = new TQLabel (i18n("B&order size:"), pluginSettingsGrp);
|
|
cBorder = new TQComboBox(pluginSettingsGrp);
|
|
lBorder->setBuddy(cBorder);
|
|
TQWhatsThis::add( cBorder, i18n( "Use this combobox to change the border size of the decoration." ));
|
|
lBorder->hide();
|
|
cBorder->hide();
|
|
TQHBoxLayout *borderSizeLayout = new TQHBoxLayout(pluginSettingsGrp->layout() );
|
|
borderSizeLayout->addWidget(lBorder);
|
|
borderSizeLayout->addWidget(cBorder);
|
|
borderSizeLayout->addStretch();
|
|
|
|
pluginConfigWidget = new TQVBox(pluginSettingsGrp);
|
|
pluginSettingsGrp->layout()->add( pluginConfigWidget );
|
|
|
|
// Page 2 (Button Selector)
|
|
buttonPage = new TQWidget( tabWidget );
|
|
TQVBoxLayout* buttonLayout = new TQVBoxLayout(buttonPage, KDialog::marginHint(), KDialog::spacingHint());
|
|
|
|
cbShowToolTips = new TQCheckBox(
|
|
i18n("&Show window button tooltips"), buttonPage );
|
|
TQWhatsThis::add( cbShowToolTips,
|
|
i18n( "Enabling this checkbox will show window button tooltips. "
|
|
"If this checkbox is off, no window button tooltips will be shown."));
|
|
|
|
cbUseCustomButtonPositions = new TQCheckBox(
|
|
i18n("Use custom titlebar button &positions"), buttonPage );
|
|
TQWhatsThis::add( cbUseCustomButtonPositions,
|
|
i18n( "The appropriate settings can be found in the \"Buttons\" Tab; "
|
|
"please note that this option is not available on all styles yet." ) );
|
|
|
|
buttonLayout->addWidget( cbShowToolTips );
|
|
buttonLayout->addWidget( cbUseCustomButtonPositions );
|
|
|
|
// Add nifty dnd button modification widgets
|
|
buttonPositionWidget = new ButtonPositionWidget(buttonPage, "button_position_widget");
|
|
buttonPositionWidget->setDecorationFactory(plugins->factory() );
|
|
TQHBoxLayout* buttonControlLayout = new TQHBoxLayout(buttonLayout);
|
|
buttonControlLayout->addSpacing(20);
|
|
buttonControlLayout->addWidget(buttonPositionWidget);
|
|
// buttonLayout->addStretch();
|
|
|
|
// preview
|
|
TQVBoxLayout* previewLayout = new TQVBoxLayout(layout, KDialog::spacingHint() );
|
|
previewLayout->setMargin( KDialog::marginHint() );
|
|
|
|
disabledNotice = new TQLabel("<b>" + i18n("NOTICE") + "</b><br>" + i18n("A third party Window Manager has been selected for use with TDE.") + "<br>" + i18n("As a result, the built-in Window Manager configuration system will not function and has been disabled."), this);
|
|
previewLayout->addWidget(disabledNotice);
|
|
disabledNotice->hide();
|
|
|
|
preview = new KDecorationPreview( this );
|
|
previewLayout->addWidget(preview);
|
|
|
|
preview->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding);
|
|
tabWidget->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Maximum);
|
|
|
|
// Page 3 (Window Shadows)
|
|
TQHBox *inactiveShadowColourHBox, *shadowColourHBox;
|
|
TQHBox *inactiveShadowOpacityHBox, *shadowOpacityHBox;
|
|
TQHBox *inactiveShadowXOffsetHBox, *shadowXOffsetHBox;
|
|
TQHBox *inactiveShadowYOffsetHBox, *shadowYOffsetHBox;
|
|
TQHBox *inactiveShadowThicknessHBox, *shadowThicknessHBox;
|
|
TQLabel *inactiveShadowColourLabel, *shadowColourLabel;
|
|
TQLabel *inactiveShadowOpacityLabel, *shadowOpacityLabel;
|
|
TQLabel *inactiveShadowXOffsetLabel, *shadowXOffsetLabel;
|
|
TQLabel *inactiveShadowYOffsetLabel, *shadowYOffsetLabel;
|
|
TQLabel *inactiveShadowThicknessLabel, *shadowThicknessLabel;
|
|
|
|
shadowPage = new TQVBox(tabWidget);
|
|
shadowPage->setSpacing(KDialog::spacingHint());
|
|
shadowPage->setMargin(KDialog::marginHint());
|
|
|
|
cbWindowShadow = new TQCheckBox(
|
|
i18n("&Draw a drop shadow under windows"), shadowPage);
|
|
TQWhatsThis::add(cbWindowShadow,
|
|
i18n("Enabling this checkbox will allow you to choose a kind of "
|
|
"drop shadow to draw under each window."));
|
|
|
|
activeShadowSettings = new TQGroupBox(1, Qt::Horizontal,
|
|
i18n("Active Window Shadow"), shadowPage);
|
|
inactiveShadowSettings = new TQGroupBox(1, Qt::Horizontal,
|
|
i18n("Inactive Window Shadows"), shadowPage);
|
|
whichShadowSettings = new TQGroupBox(3, Qt::Horizontal,
|
|
i18n("Draw Shadow Under Normal Windows And..."), shadowPage);
|
|
|
|
cbShadowDocks = new TQCheckBox(i18n("Docks and &panels"),
|
|
whichShadowSettings);
|
|
connect(cbShadowDocks, TQT_SIGNAL(toggled(bool)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
cbShadowOverrides = new TQCheckBox(i18n("O&verride windows"),
|
|
whichShadowSettings);
|
|
connect(cbShadowOverrides, TQT_SIGNAL(toggled(bool)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
cbShadowTopMenus = new TQCheckBox(i18n("&Top menu"),
|
|
whichShadowSettings);
|
|
connect(cbShadowTopMenus, TQT_SIGNAL(toggled(bool)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
cbInactiveShadow = new TQCheckBox(
|
|
i18n("Draw shadow under &inactive windows"), inactiveShadowSettings);
|
|
connect(cbInactiveShadow, TQT_SIGNAL(toggled(bool)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
|
|
shadowColourHBox = new TQHBox(activeShadowSettings);
|
|
shadowColourHBox->setSpacing(KDialog::spacingHint());
|
|
shadowColourLabel = new TQLabel(i18n("Colour:"), shadowColourHBox);
|
|
shadowColourButton = new KColorButton(shadowColourHBox);
|
|
connect(shadowColourButton, TQT_SIGNAL(changed(const TQColor &)), TQT_SLOT(slotSelectionChanged()));
|
|
|
|
inactiveShadowColourHBox = new TQHBox(inactiveShadowSettings);
|
|
inactiveShadowColourHBox->setSpacing(KDialog::spacingHint());
|
|
inactiveShadowColourLabel = new TQLabel(i18n("Colour:"), inactiveShadowColourHBox);
|
|
inactiveShadowColourButton = new KColorButton(inactiveShadowColourHBox);
|
|
connect(inactiveShadowColourButton, TQT_SIGNAL(changed(const TQColor &)), TQT_SLOT(slotSelectionChanged()));
|
|
|
|
shadowOpacityHBox = new TQHBox(activeShadowSettings);
|
|
shadowOpacityHBox->setSpacing(KDialog::spacingHint());
|
|
shadowOpacityLabel = new TQLabel(i18n("Maximum opacity:"), shadowOpacityHBox);
|
|
shadowOpacitySlider = new TQSlider(1, 100, 10, 50, Qt::Horizontal,
|
|
shadowOpacityHBox);
|
|
shadowOpacitySlider->setTickmarks(TQSlider::Below);
|
|
shadowOpacitySlider->setTickInterval(10);
|
|
shadowOpacitySpinBox = new TQSpinBox(1, 100, 1, shadowOpacityHBox);
|
|
shadowOpacitySpinBox->setSuffix(" %");
|
|
connect(shadowOpacitySlider, TQT_SIGNAL(valueChanged(int)), shadowOpacitySpinBox,
|
|
TQT_SLOT(setValue(int)));
|
|
connect(shadowOpacitySpinBox, TQT_SIGNAL(valueChanged(int)), shadowOpacitySlider,
|
|
TQT_SLOT(setValue(int)));
|
|
connect(shadowOpacitySlider, TQT_SIGNAL(valueChanged(int)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
|
|
inactiveShadowOpacityHBox = new TQHBox(inactiveShadowSettings);
|
|
inactiveShadowOpacityHBox->setSpacing(KDialog::spacingHint());
|
|
inactiveShadowOpacityLabel = new TQLabel(i18n("Maximum opacity:"),
|
|
inactiveShadowOpacityHBox);
|
|
inactiveShadowOpacitySlider = new TQSlider(1, 100, 10, 50, Qt::Horizontal,
|
|
inactiveShadowOpacityHBox);
|
|
inactiveShadowOpacitySlider->setTickmarks(TQSlider::Below);
|
|
inactiveShadowOpacitySlider->setTickInterval(10);
|
|
inactiveShadowOpacitySpinBox = new TQSpinBox(1, 100, 1,
|
|
inactiveShadowOpacityHBox);
|
|
inactiveShadowOpacitySpinBox->setSuffix(" %");
|
|
connect(inactiveShadowOpacitySlider, TQT_SIGNAL(valueChanged(int)),
|
|
inactiveShadowOpacitySpinBox,
|
|
TQT_SLOT(setValue(int)));
|
|
connect(inactiveShadowOpacitySpinBox, TQT_SIGNAL(valueChanged(int)),
|
|
inactiveShadowOpacitySlider,
|
|
TQT_SLOT(setValue(int)));
|
|
connect(inactiveShadowOpacitySlider, TQT_SIGNAL(valueChanged(int)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
|
|
shadowXOffsetHBox = new TQHBox(activeShadowSettings);
|
|
shadowXOffsetHBox->setSpacing(KDialog::spacingHint());
|
|
shadowXOffsetLabel = new TQLabel(
|
|
i18n("Offset rightward (may be negative):"),
|
|
shadowXOffsetHBox);
|
|
shadowXOffsetSpinBox = new TQSpinBox(-1024, 1024, 1, shadowXOffsetHBox);
|
|
shadowXOffsetSpinBox->setSuffix(i18n(" pixels"));
|
|
connect(shadowXOffsetSpinBox, TQT_SIGNAL(valueChanged(int)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
|
|
inactiveShadowXOffsetHBox = new TQHBox(inactiveShadowSettings);
|
|
inactiveShadowXOffsetHBox->setSpacing(KDialog::spacingHint());
|
|
inactiveShadowXOffsetLabel = new TQLabel(
|
|
i18n("Offset rightward (may be negative):"),
|
|
inactiveShadowXOffsetHBox);
|
|
inactiveShadowXOffsetSpinBox = new TQSpinBox(-1024, 1024, 1,
|
|
inactiveShadowXOffsetHBox);
|
|
inactiveShadowXOffsetSpinBox->setSuffix(i18n(" pixels"));
|
|
connect(inactiveShadowXOffsetSpinBox, TQT_SIGNAL(valueChanged(int)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
|
|
shadowYOffsetHBox = new TQHBox(activeShadowSettings);
|
|
shadowYOffsetHBox->setSpacing(KDialog::spacingHint());
|
|
shadowYOffsetLabel = new TQLabel(
|
|
i18n("Offset downward (may be negative):"),
|
|
shadowYOffsetHBox);
|
|
shadowYOffsetSpinBox = new TQSpinBox(-1024, 1024, 1, shadowYOffsetHBox);
|
|
shadowYOffsetSpinBox->setSuffix(i18n(" pixels"));
|
|
connect(shadowYOffsetSpinBox, TQT_SIGNAL(valueChanged(int)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
|
|
inactiveShadowYOffsetHBox = new TQHBox(inactiveShadowSettings);
|
|
inactiveShadowYOffsetHBox->setSpacing(KDialog::spacingHint());
|
|
inactiveShadowYOffsetLabel = new TQLabel(
|
|
i18n("Offset downward (may be negative):"),
|
|
inactiveShadowYOffsetHBox);
|
|
inactiveShadowYOffsetSpinBox = new TQSpinBox(-1024, 1024, 1,
|
|
inactiveShadowYOffsetHBox);
|
|
inactiveShadowYOffsetSpinBox->setSuffix(i18n(" pixels"));
|
|
connect(inactiveShadowYOffsetSpinBox, TQT_SIGNAL(valueChanged(int)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
|
|
shadowThicknessHBox = new TQHBox(activeShadowSettings);
|
|
shadowThicknessHBox->setSpacing(KDialog::spacingHint());
|
|
shadowThicknessLabel = new TQLabel(
|
|
i18n("Thickness to either side of window:"),
|
|
shadowThicknessHBox);
|
|
shadowThicknessSpinBox = new TQSpinBox(1, 100, 1,
|
|
shadowThicknessHBox);
|
|
shadowThicknessSpinBox->setSuffix(i18n(" pixels"));
|
|
connect(shadowThicknessSpinBox, TQT_SIGNAL(valueChanged(int)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
|
|
inactiveShadowThicknessHBox = new TQHBox(inactiveShadowSettings);
|
|
inactiveShadowThicknessHBox->setSpacing(KDialog::spacingHint());
|
|
inactiveShadowThicknessLabel = new TQLabel(
|
|
i18n("Thickness to either side of window:"),
|
|
inactiveShadowThicknessHBox);
|
|
inactiveShadowThicknessSpinBox = new TQSpinBox(1, 100, 1,
|
|
inactiveShadowThicknessHBox);
|
|
inactiveShadowThicknessSpinBox->setSuffix(i18n(" pixels"));
|
|
connect(inactiveShadowThicknessSpinBox, TQT_SIGNAL(valueChanged(int)),
|
|
TQT_SLOT(slotSelectionChanged()));
|
|
|
|
// Page 4 (WM selector)
|
|
windowmanagerPage = new TQWidget( tabWidget );
|
|
|
|
TQVBoxLayout* windowmanagerLayout = new TQVBoxLayout(windowmanagerPage, KDialog::marginHint(), KDialog::spacingHint());
|
|
|
|
// WM chooser
|
|
thirdpartyWMList = new KComboBox( windowmanagerPage );
|
|
whatsThis = i18n("Select the window manager. Selecting a window manager "
|
|
"other than \"twin\" will require you to use a third party program for configuration and may increase the risk of system crashes or security problems.");
|
|
TQWhatsThis::add(thirdpartyWMList, whatsThis);
|
|
TQLabel* thirdpartyWMLabel = new TQLabel(i18n("Window Manager to use in your TDE session:"), windowmanagerPage);
|
|
windowmanagerLayout->addWidget(thirdpartyWMLabel);
|
|
windowmanagerLayout->addWidget(thirdpartyWMList);
|
|
thirdpartyWMArguments = new KLineEdit( windowmanagerPage );
|
|
whatsThis = i18n("Specify any command line arguments to be passed to the selected WM on startup. A common example is --replace");
|
|
TQWhatsThis::add(thirdpartyWMArguments, whatsThis);
|
|
TQLabel* thirdpartyWMArgumentsLabel = new TQLabel(i18n("Command line arguments to pass to the Window Manager (should remain blank unless needed):"), windowmanagerPage);
|
|
windowmanagerLayout->addWidget(thirdpartyWMArgumentsLabel);
|
|
windowmanagerLayout->addWidget(thirdpartyWMArguments);
|
|
|
|
windowmanagerLayout->addStretch();
|
|
|
|
// Load all installed decorations into memory
|
|
// Set up the decoration lists and other UI settings
|
|
findDecorations();
|
|
createDecorationList();
|
|
createThirdPartyWMList();
|
|
readConfig( &twinConfig );
|
|
resetPlugin( &twinConfig );
|
|
|
|
tabWidget->insertTab( pluginPage, i18n("&Window Decoration") );
|
|
tabWidget->insertTab( buttonPage, i18n("&Buttons") );
|
|
tabWidget->insertTab( shadowPage, i18n("&Shadows") );
|
|
tabWidget->insertTab( windowmanagerPage, i18n("&Window Manager") );
|
|
|
|
connect( buttonPositionWidget, TQT_SIGNAL(changed()), this, TQT_SLOT(slotButtonsChanged()) ); // update preview etc.
|
|
connect( buttonPositionWidget, TQT_SIGNAL(changed()), this, TQT_SLOT(slotSelectionChanged()) ); // emit changed()...
|
|
connect( decorationList, TQT_SIGNAL(activated(const TQString&)), TQT_SLOT(slotSelectionChanged()) );
|
|
connect( decorationList, TQT_SIGNAL(activated(const TQString&)),
|
|
TQT_SLOT(slotChangeDecoration(const TQString&)) );
|
|
connect( cbUseCustomButtonPositions, TQT_SIGNAL(clicked()), TQT_SLOT(slotSelectionChanged()) );
|
|
connect(cbUseCustomButtonPositions, TQT_SIGNAL(toggled(bool)), buttonPositionWidget, TQT_SLOT(setEnabled(bool)));
|
|
connect(cbUseCustomButtonPositions, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotButtonsChanged()) );
|
|
connect(cbWindowShadow, TQT_SIGNAL(toggled(bool)), activeShadowSettings, TQT_SLOT(setEnabled(bool)));
|
|
connect(cbWindowShadow, TQT_SIGNAL(toggled(bool)), inactiveShadowSettings, TQT_SLOT(setEnabled(bool)));
|
|
connect(cbWindowShadow, TQT_SIGNAL(toggled(bool)), whichShadowSettings, TQT_SLOT(setEnabled(bool)));
|
|
|
|
connect( cbShowToolTips, TQT_SIGNAL(clicked()), TQT_SLOT(slotSelectionChanged()) );
|
|
connect( cbWindowShadow, TQT_SIGNAL(clicked()), TQT_SLOT(slotSelectionChanged()) );
|
|
connect( cBorder, TQT_SIGNAL( activated( int )), TQT_SLOT( slotBorderChanged( int )));
|
|
// connect( cbUseMiniWindows, TQT_SIGNAL(clicked()), TQT_SLOT(slotSelectionChanged()) );
|
|
|
|
connect( thirdpartyWMList, TQT_SIGNAL(activated(const TQString&)), TQT_SLOT(slotSelectionChanged()) );
|
|
connect( thirdpartyWMArguments, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(slotSelectionChanged()) );
|
|
|
|
// Allow twin dcop signal to update our selection list
|
|
connectDCOPSignal("twin", 0, "dcopResetAllClients()", "dcopUpdateClientList()", false);
|
|
|
|
KAboutData *about =
|
|
new KAboutData(I18N_NOOP("kcmtwindecoration"),
|
|
I18N_NOOP("Window Decoration Control Module"),
|
|
0, 0, KAboutData::License_GPL,
|
|
I18N_NOOP("(c) 2001 Karol Szwed"));
|
|
about->addAuthor("Karol Szwed", 0, "gallium@kde.org");
|
|
setAboutData(about);
|
|
}
|
|
|
|
|
|
KWinDecorationModule::~KWinDecorationModule()
|
|
{
|
|
delete preview; // needs to be destroyed before plugins
|
|
delete plugins;
|
|
}
|
|
|
|
|
|
// Find all theme desktop files in all 'data' dirs owned by twin.
|
|
// And insert these into a DecorationInfo structure
|
|
void KWinDecorationModule::findDecorations()
|
|
{
|
|
TQStringList dirList = KGlobal::dirs()->findDirs("data", "twin");
|
|
TQStringList::ConstIterator it;
|
|
|
|
for (it = dirList.begin(); it != dirList.end(); it++)
|
|
{
|
|
TQDir d(*it);
|
|
if (d.exists())
|
|
for (TQFileInfoListIterator it(*d.entryInfoList()); it.current(); ++it)
|
|
{
|
|
TQString filename(it.current()->absFilePath());
|
|
if (KDesktopFile::isDesktopFile(filename))
|
|
{
|
|
KDesktopFile desktopFile(filename);
|
|
TQString libName = desktopFile.readEntry("X-KDE-Library");
|
|
|
|
if (!libName.isEmpty() && libName.startsWith( "twin3_" ))
|
|
{
|
|
DecorationInfo di;
|
|
di.name = desktopFile.readName();
|
|
di.libraryName = libName;
|
|
decorations.append( di );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Fills the decorationList with a list of available twin decorations
|
|
void KWinDecorationModule::createDecorationList()
|
|
{
|
|
TQValueList<DecorationInfo>::ConstIterator it;
|
|
|
|
// Sync with twin hardcoded KDE2 style which has no desktop item
|
|
TQStringList decorationNames;
|
|
decorationNames.append( i18n("KDE 2") );
|
|
for (it = decorations.begin(); it != decorations.end(); ++it)
|
|
{
|
|
decorationNames.append((*it).name);
|
|
}
|
|
decorationNames.sort();
|
|
decorationList->insertStringList(decorationNames);
|
|
}
|
|
|
|
|
|
// Fills the thirdpartyWMList with a list of available window managers
|
|
void KWinDecorationModule::createThirdPartyWMList()
|
|
{
|
|
TQStringList::Iterator it;
|
|
|
|
// FIXME
|
|
// This list SHOULD NOT be hard coded
|
|
// It should detect the available WMs through a standard mechanism of some sort
|
|
TQString wmExecutable;
|
|
TQStringList wmNames;
|
|
TQStringList wmAvailableNames;
|
|
wmNames << TQString("kwin ").append(i18n("(KDE4's window manager)")) << TQString("compiz ").append(i18n("(Compiz Effects Manager)")) << TQString("icewm ").append(i18n("(Simple, fast window manager)"));
|
|
wmNames.sort();
|
|
wmNames.prepend(TQString("twin ").append(i18n("(Default TDE window manager)")));
|
|
for (it = wmNames.begin(); it != wmNames.end(); ++it)
|
|
{
|
|
wmExecutable = *it;
|
|
int descStart = wmExecutable.find(" ");
|
|
if (descStart >= 0) {
|
|
wmExecutable.truncate(descStart);
|
|
}
|
|
if (KStandardDirs::findExe(wmExecutable) != TQString::null) {
|
|
wmAvailableNames.append(*it);
|
|
}
|
|
}
|
|
|
|
thirdpartyWMList->insertStringList(wmAvailableNames);
|
|
}
|
|
|
|
|
|
// Reset the decoration plugin to what the user just selected
|
|
void KWinDecorationModule::slotChangeDecoration( const TQString & text)
|
|
{
|
|
KConfig twinConfig("twinrc");
|
|
twinConfig.setGroup("Style");
|
|
|
|
// Let the user see config options for the currently selected decoration
|
|
resetPlugin( &twinConfig, text );
|
|
}
|
|
|
|
|
|
// This is the selection handler setting
|
|
void KWinDecorationModule::slotSelectionChanged()
|
|
{
|
|
emit KCModule::changed(true);
|
|
|
|
processEnabledDisabledTabs();
|
|
}
|
|
|
|
// Handle WM selection-related disable/enable of tabs
|
|
void KWinDecorationModule::processEnabledDisabledTabs()
|
|
{
|
|
TQString wmExecutableName = thirdpartyWMList->currentText();
|
|
int descStart = wmExecutableName.find(" ");
|
|
if (descStart >= 0) {
|
|
wmExecutableName.truncate(descStart);
|
|
}
|
|
if (wmExecutableName == "twin") {
|
|
pluginPage->setEnabled(true);
|
|
buttonPage->setEnabled(true);
|
|
shadowPage->setEnabled(true);
|
|
disabledNotice->hide();
|
|
preview->show();
|
|
}
|
|
else {
|
|
pluginPage->setEnabled(false);
|
|
buttonPage->setEnabled(false);
|
|
shadowPage->setEnabled(false);
|
|
disabledNotice->show();
|
|
preview->hide();
|
|
}
|
|
}
|
|
|
|
static const char* const border_names[ KDecorationDefines::BordersCount ] =
|
|
{
|
|
I18N_NOOP( "Tiny" ),
|
|
I18N_NOOP( "Normal" ),
|
|
I18N_NOOP( "Large" ),
|
|
I18N_NOOP( "Very Large" ),
|
|
I18N_NOOP( "Huge" ),
|
|
I18N_NOOP( "Very Huge" ),
|
|
I18N_NOOP( "Oversized" )
|
|
};
|
|
|
|
int KWinDecorationModule::borderSizeToIndex( BorderSize size, TQValueList< BorderSize > sizes )
|
|
{
|
|
int pos = 0;
|
|
for( TQValueList< BorderSize >::ConstIterator it = sizes.begin();
|
|
it != sizes.end();
|
|
++it, ++pos )
|
|
if( size <= *it )
|
|
break;
|
|
return pos;
|
|
}
|
|
|
|
KDecorationDefines::BorderSize KWinDecorationModule::indexToBorderSize( int index,
|
|
TQValueList< BorderSize > sizes )
|
|
{
|
|
TQValueList< BorderSize >::ConstIterator it = sizes.begin();
|
|
for(;
|
|
it != sizes.end();
|
|
++it, --index )
|
|
if( index == 0 )
|
|
break;
|
|
return *it;
|
|
}
|
|
|
|
void KWinDecorationModule::slotBorderChanged( int size )
|
|
{
|
|
if( lBorder->isHidden())
|
|
return;
|
|
emit KCModule::changed( true );
|
|
TQValueList< BorderSize > sizes;
|
|
if( plugins->factory() != NULL )
|
|
sizes = plugins->factory()->borderSizes();
|
|
assert( sizes.count() >= 2 );
|
|
border_size = indexToBorderSize( size, sizes );
|
|
|
|
// update preview
|
|
preview->setTempBorderSize(plugins, border_size);
|
|
}
|
|
|
|
void KWinDecorationModule::slotButtonsChanged()
|
|
{
|
|
// update preview
|
|
preview->setTempButtons(plugins, cbUseCustomButtonPositions->isChecked(), buttonPositionWidget->buttonsLeft(), buttonPositionWidget->buttonsRight() );
|
|
}
|
|
|
|
TQString KWinDecorationModule::decorationName( TQString& libName )
|
|
{
|
|
TQString decoName;
|
|
|
|
TQValueList<DecorationInfo>::Iterator it;
|
|
for( it = decorations.begin(); it != decorations.end(); ++it )
|
|
if ( (*it).libraryName == libName )
|
|
{
|
|
decoName = (*it).name;
|
|
break;
|
|
}
|
|
|
|
return decoName;
|
|
}
|
|
|
|
|
|
TQString KWinDecorationModule::decorationLibName( const TQString& name )
|
|
{
|
|
TQString libName;
|
|
|
|
// Find the corresponding library name to that of
|
|
// the current plugin name
|
|
TQValueList<DecorationInfo>::Iterator it;
|
|
for( it = decorations.begin(); it != decorations.end(); ++it )
|
|
if ( (*it).name == name )
|
|
{
|
|
libName = (*it).libraryName;
|
|
break;
|
|
}
|
|
|
|
if (libName.isEmpty())
|
|
libName = "twin_default"; // KDE 2
|
|
|
|
return libName;
|
|
}
|
|
|
|
|
|
// Loads/unloads and inserts the decoration config plugin into the
|
|
// pluginConfigWidget, allowing for dynamic configuration of decorations
|
|
void KWinDecorationModule::resetPlugin( KConfig* conf, const TQString& currentDecoName )
|
|
{
|
|
// Config names are "twin_icewm_config"
|
|
// for "twin3_icewm" twin client
|
|
|
|
TQString oldName = styleToConfigLib( oldLibraryName );
|
|
|
|
TQString currentName;
|
|
if (!currentDecoName.isEmpty())
|
|
currentName = decorationLibName( currentDecoName ); // Use what the user selected
|
|
else
|
|
currentName = currentLibraryName; // Use what was read from readConfig()
|
|
|
|
if( plugins->loadPlugin( currentName )
|
|
&& preview->recreateDecoration( plugins ))
|
|
preview->enablePreview();
|
|
else
|
|
preview->disablePreview();
|
|
plugins->destroyPreviousPlugin();
|
|
|
|
checkSupportedBorderSizes();
|
|
|
|
// inform buttonPositionWidget about the new factory...
|
|
buttonPositionWidget->setDecorationFactory(plugins->factory() );
|
|
|
|
currentName = styleToConfigLib( currentName );
|
|
|
|
// Delete old plugin widget if it exists
|
|
delete pluginObject;
|
|
pluginObject = 0;
|
|
|
|
// Use klibloader for library manipulation
|
|
KLibLoader* loader = KLibLoader::self();
|
|
|
|
// Free the old library if possible
|
|
if (!oldLibraryName.isNull())
|
|
loader->unloadLibrary( TQFile::encodeName(oldName) );
|
|
|
|
KLibrary* library = loader->library( TQFile::encodeName(currentName) );
|
|
if (library != NULL)
|
|
{
|
|
void* alloc_ptr = library->symbol("allocate_config");
|
|
|
|
if (alloc_ptr != NULL)
|
|
{
|
|
allocatePlugin = (TQObject* (*)(KConfig* conf, TQWidget* parent))alloc_ptr;
|
|
pluginObject = (TQObject*)(allocatePlugin( conf, pluginConfigWidget ));
|
|
|
|
// connect required signals and slots together...
|
|
connect( pluginObject, TQT_SIGNAL(changed()), this, TQT_SLOT(slotSelectionChanged()) );
|
|
connect( this, TQT_SIGNAL(pluginLoad(KConfig*)), pluginObject, TQT_SLOT(load(KConfig*)) );
|
|
connect( this, TQT_SIGNAL(pluginSave(KConfig*)), pluginObject, TQT_SLOT(save(KConfig*)) );
|
|
connect( this, TQT_SIGNAL(pluginDefaults()), pluginObject, TQT_SLOT(defaults()) );
|
|
pluginConfigWidget->show();
|
|
return;
|
|
}
|
|
}
|
|
|
|
pluginConfigWidget->hide();
|
|
}
|
|
|
|
|
|
// Reads the twin config settings, and sets all UI controls to those settings
|
|
// Updating the config plugin if required
|
|
void KWinDecorationModule::readConfig( KConfig* conf )
|
|
{
|
|
// General tab
|
|
// ============
|
|
cbShowToolTips->setChecked( conf->readBoolEntry("ShowToolTips", true ));
|
|
// cbUseMiniWindows->setChecked( conf->readBoolEntry("MiniWindowBorders", false));
|
|
|
|
// Find the corresponding decoration name to that of
|
|
// the current plugin library name
|
|
|
|
oldLibraryName = currentLibraryName;
|
|
currentLibraryName = conf->readEntry("PluginLib",
|
|
((TQPixmap::defaultDepth() > 8) ? "twin_plastik" : "twin_quartz"));
|
|
TQString decoName = decorationName( currentLibraryName );
|
|
|
|
// If we are using the "default" kde client, use the "default" entry.
|
|
if (decoName.isEmpty())
|
|
decoName = i18n("KDE 2");
|
|
|
|
int numDecos = decorationList->count();
|
|
for (int i = 0; i < numDecos; ++i)
|
|
{
|
|
if (decorationList->text(i) == decoName)
|
|
{
|
|
decorationList->setCurrentItem(i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Buttons tab
|
|
// ============
|
|
bool customPositions = conf->readBoolEntry("CustomButtonPositions", false);
|
|
cbUseCustomButtonPositions->setChecked( customPositions );
|
|
buttonPositionWidget->setEnabled( customPositions );
|
|
// Menu and onAllDesktops buttons are default on LHS
|
|
buttonPositionWidget->setButtonsLeft( conf->readEntry("ButtonsOnLeft", "MS") );
|
|
// Help, Minimize, Maximize and Close are default on RHS
|
|
buttonPositionWidget->setButtonsRight( conf->readEntry("ButtonsOnRight", "HIAX") );
|
|
|
|
int bsize = conf->readNumEntry( "BorderSize", BorderNormal );
|
|
if( bsize >= BorderTiny && bsize < BordersCount )
|
|
border_size = static_cast< BorderSize >( bsize );
|
|
else
|
|
border_size = BorderNormal;
|
|
checkSupportedBorderSizes();
|
|
|
|
// Shadows tab
|
|
// ===========
|
|
bool shadowEnabled = conf->readBoolEntry("ShadowEnabled", false);
|
|
cbWindowShadow->setChecked(shadowEnabled);
|
|
activeShadowSettings->setEnabled(shadowEnabled);
|
|
inactiveShadowSettings->setEnabled(shadowEnabled);
|
|
whichShadowSettings->setEnabled(shadowEnabled);
|
|
shadowColourButton->setColor(conf->readColorEntry("ShadowColour", &TQt::black));
|
|
shadowOpacitySlider->setValue((int)ceil(conf->readDoubleNumEntry("ShadowOpacity", 0.70) * 100));
|
|
shadowXOffsetSpinBox->setValue(conf->readNumEntry("ShadowXOffset", 0));
|
|
shadowYOffsetSpinBox->setValue(conf->readNumEntry("ShadowYOffset", 10));
|
|
cbShadowDocks->setChecked(conf->readBoolEntry("ShadowDocks", false));
|
|
cbShadowOverrides->setChecked(conf->readBoolEntry("ShadowOverrides", false));
|
|
cbShadowTopMenus->setChecked(conf->readBoolEntry("ShadowTopMenus", false));
|
|
shadowThicknessSpinBox->setValue(conf->readNumEntry("ShadowThickness", 10));
|
|
cbInactiveShadow->setChecked(conf->readBoolEntry("InactiveShadowEnabled", false));
|
|
inactiveShadowColourButton->setColor(conf->readColorEntry("InactiveShadowColour", &TQt::black));
|
|
inactiveShadowOpacitySlider->setValue((int)ceil(conf->readDoubleNumEntry("InactiveShadowOpacity", 0.70) * 100));
|
|
inactiveShadowXOffsetSpinBox->setValue(conf->readNumEntry("InactiveShadowXOffset", 0));
|
|
inactiveShadowYOffsetSpinBox->setValue(conf->readNumEntry("InactiveShadowYOffset", 5));
|
|
inactiveShadowThicknessSpinBox->setValue(conf->readNumEntry("InactiveShadowThickness", 5));
|
|
|
|
// Third party WM
|
|
// ==============
|
|
conf->setGroup("ThirdPartyWM");
|
|
TQString selectedWM = conf->readEntry("WMExecutable", "twin");
|
|
TQString wmArguments = conf->readEntry("WMAdditionalArguments", "");
|
|
|
|
bool found;
|
|
int swm;
|
|
for ( swm = 0; swm < thirdpartyWMList->count(); ++swm ) {
|
|
if ( thirdpartyWMList->text( swm ).startsWith(selectedWM + " ") ) {
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
thirdpartyWMList->setCurrentItem(swm);
|
|
thirdpartyWMArguments->setText(wmArguments);
|
|
|
|
processEnabledDisabledTabs();
|
|
|
|
emit KCModule::changed(false);
|
|
}
|
|
|
|
|
|
// Writes the selected user configuration to the twin config file
|
|
void KWinDecorationModule::writeConfig( KConfig* conf )
|
|
{
|
|
TQString name = decorationList->currentText();
|
|
TQString libName = decorationLibName( name );
|
|
|
|
KConfig twinConfig("twinrc");
|
|
twinConfig.setGroup("Style");
|
|
|
|
// General settings
|
|
conf->writeEntry("PluginLib", libName);
|
|
conf->writeEntry("CustomButtonPositions", cbUseCustomButtonPositions->isChecked());
|
|
conf->writeEntry("ShowToolTips", cbShowToolTips->isChecked());
|
|
// conf->writeEntry("MiniWindowBorders", cbUseMiniWindows->isChecked());
|
|
|
|
// Button settings
|
|
conf->writeEntry("ButtonsOnLeft", buttonPositionWidget->buttonsLeft() );
|
|
conf->writeEntry("ButtonsOnRight", buttonPositionWidget->buttonsRight() );
|
|
conf->writeEntry("BorderSize", border_size );
|
|
|
|
// Shadow settings
|
|
conf->writeEntry("ShadowEnabled", cbWindowShadow->isChecked());
|
|
conf->writeEntry("ShadowColour", shadowColourButton->color());
|
|
conf->writeEntry("ShadowOpacity", shadowOpacitySlider->value() / 100.0);
|
|
conf->writeEntry("ShadowXOffset", shadowXOffsetSpinBox->value());
|
|
conf->writeEntry("ShadowYOffset", shadowYOffsetSpinBox->value());
|
|
conf->writeEntry("ShadowThickness", shadowThicknessSpinBox->value());
|
|
conf->writeEntry("ShadowDocks", cbShadowDocks->isChecked());
|
|
conf->writeEntry("ShadowOverrides", cbShadowOverrides->isChecked());
|
|
conf->writeEntry("ShadowTopMenus", cbShadowTopMenus->isChecked());
|
|
conf->writeEntry("InactiveShadowEnabled", cbInactiveShadow->isChecked());
|
|
conf->writeEntry("InactiveShadowColour", inactiveShadowColourButton->color());
|
|
conf->writeEntry("InactiveShadowOpacity",
|
|
inactiveShadowOpacitySlider->value() / 100.0);
|
|
conf->writeEntry("InactiveShadowXOffset",
|
|
inactiveShadowXOffsetSpinBox->value());
|
|
conf->writeEntry("InactiveShadowYOffset",
|
|
inactiveShadowYOffsetSpinBox->value());
|
|
conf->writeEntry("InactiveShadowThickness",
|
|
inactiveShadowThicknessSpinBox->value());
|
|
|
|
conf->setGroup("ThirdPartyWM");
|
|
TQString wmExecutableName = thirdpartyWMList->currentText();
|
|
int descStart = wmExecutableName.find(" ");
|
|
if (descStart >= 0) {
|
|
wmExecutableName.truncate(descStart);
|
|
}
|
|
conf->writeEntry("WMExecutable", wmExecutableName);
|
|
conf->writeEntry("WMAdditionalArguments", thirdpartyWMArguments->text());
|
|
|
|
oldLibraryName = currentLibraryName;
|
|
currentLibraryName = libName;
|
|
|
|
// We saved, so tell kcmodule that there have been no new user changes made.
|
|
emit KCModule::changed(false);
|
|
}
|
|
|
|
|
|
void KWinDecorationModule::dcopUpdateClientList()
|
|
{
|
|
// Changes the current active ListBox item, and
|
|
// Loads a new plugin configuration tab if required.
|
|
KConfig twinConfig("twinrc");
|
|
twinConfig.setGroup("Style");
|
|
|
|
readConfig( &twinConfig );
|
|
resetPlugin( &twinConfig );
|
|
}
|
|
|
|
|
|
// Virutal functions required by KCModule
|
|
void KWinDecorationModule::load()
|
|
{
|
|
KConfig twinConfig("twinrc");
|
|
twinConfig.setGroup("Style");
|
|
|
|
// Reset by re-reading the config
|
|
readConfig( &twinConfig );
|
|
resetPlugin( &twinConfig );
|
|
}
|
|
|
|
|
|
void KWinDecorationModule::save()
|
|
{
|
|
KConfig twinConfig("twinrc");
|
|
twinConfig.setGroup("Style");
|
|
|
|
writeConfig( &twinConfig );
|
|
emit pluginSave( &twinConfig );
|
|
|
|
twinConfig.sync();
|
|
resetKWin();
|
|
// resetPlugin() will get called via the above DCOP function
|
|
}
|
|
|
|
|
|
void KWinDecorationModule::defaults()
|
|
{
|
|
// Set the KDE defaults
|
|
cbUseCustomButtonPositions->setChecked( false );
|
|
buttonPositionWidget->setEnabled( false );
|
|
cbShowToolTips->setChecked( true );
|
|
cbWindowShadow->setChecked( false );
|
|
// cbUseMiniWindows->setChecked( false);
|
|
// Don't set default for now
|
|
// decorationList->setSelected(
|
|
// decorationList->findItem( i18n("KDE 2") ), true ); // KDE classic client
|
|
|
|
buttonPositionWidget->setButtonsLeft("MS");
|
|
buttonPositionWidget->setButtonsRight("HIAX");
|
|
|
|
border_size = BorderNormal;
|
|
checkSupportedBorderSizes();
|
|
|
|
shadowColourButton->setColor(Qt::black);
|
|
shadowOpacitySlider->setValue(70);
|
|
shadowXOffsetSpinBox->setValue(0);
|
|
shadowYOffsetSpinBox->setValue(10);
|
|
shadowThicknessSpinBox->setValue(10);
|
|
cbShadowDocks->setChecked(false);
|
|
cbShadowOverrides->setChecked(false);
|
|
cbShadowTopMenus->setChecked(false);
|
|
cbInactiveShadow->setChecked(false);
|
|
inactiveShadowColourButton->setColor(Qt::black);
|
|
inactiveShadowOpacitySlider->setValue(70);
|
|
inactiveShadowXOffsetSpinBox->setValue(0);
|
|
inactiveShadowYOffsetSpinBox->setValue(5);
|
|
inactiveShadowThicknessSpinBox->setValue(5);
|
|
|
|
// Set plugin defaults
|
|
emit pluginDefaults();
|
|
}
|
|
|
|
void KWinDecorationModule::checkSupportedBorderSizes()
|
|
{
|
|
TQValueList< BorderSize > sizes;
|
|
if( plugins->factory() != NULL )
|
|
sizes = plugins->factory()->borderSizes();
|
|
if( sizes.count() < 2 ) {
|
|
lBorder->hide();
|
|
cBorder->hide();
|
|
} else {
|
|
cBorder->clear();
|
|
for (TQValueList<BorderSize>::const_iterator it = sizes.begin(); it != sizes.end(); ++it) {
|
|
BorderSize size = *it;
|
|
cBorder->insertItem(i18n(border_names[size]), borderSizeToIndex(size,sizes) );
|
|
}
|
|
int pos = borderSizeToIndex( border_size, sizes );
|
|
lBorder->show();
|
|
cBorder->show();
|
|
cBorder->setCurrentItem(pos);
|
|
slotBorderChanged( pos );
|
|
}
|
|
}
|
|
|
|
TQString KWinDecorationModule::styleToConfigLib( TQString& styleLib )
|
|
{
|
|
if( styleLib.startsWith( "twin3_" ))
|
|
return "twin_" + styleLib.mid( 6 ) + "_config";
|
|
else
|
|
return styleLib + "_config";
|
|
}
|
|
|
|
TQString KWinDecorationModule::quickHelp() const
|
|
{
|
|
return i18n( "<h1>Window Manager Decoration</h1>"
|
|
"<p>This module allows you to choose the window border decorations, "
|
|
"as well as titlebar button positions and custom decoration options.</p>"
|
|
"To choose a theme for your window decoration click on its name and apply your choice by clicking the \"Apply\" button below."
|
|
" If you do not want to apply your choice you can click the \"Reset\" button to discard your changes."
|
|
"<p>You can configure each theme in the \"Configure [...]\" tab. There are different options specific for each theme.</p>"
|
|
"<p>In \"General Options (if available)\" you can activate the \"Buttons\" tab by checking the \"Use custom titlebar button positions\" box."
|
|
" In the \"Buttons\" tab you can change the positions of the buttons to your liking.</p>" );
|
|
}
|
|
|
|
|
|
void KWinDecorationModule::resetKWin()
|
|
{
|
|
bool ok = kapp->dcopClient()->send("twin*", "KWinInterface",
|
|
"reconfigure()", TQByteArray());
|
|
if (!ok)
|
|
kdDebug() << "kcmtwindecoration: Could not reconfigure twin" << endl;
|
|
}
|
|
|
|
#include "twindecoration.moc"
|
|
// vim: ts=4
|
|
// kate: space-indent off; tab-width 4;
|
|
|