/******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2007 Rivo Laks 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, see . *********************************************************************/ #include "main.h" #include "advanced.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include K_PLUGIN_FACTORY(KWinCompositingConfigFactory, registerPlugin(); ) K_EXPORT_PLUGIN(KWinCompositingConfigFactory("kcmkwincompositing")) namespace KWin { ConfirmDialog::ConfirmDialog() : KTimerDialog(10000, KTimerDialog::CountDown, 0, "mainKTimerDialog", true, i18n("Confirm Desktop Effects Change"), KTimerDialog::Ok|KTimerDialog::Cancel, KTimerDialog::Cancel) { setButtonGuiItem( KDialog::Ok, KGuiItem( i18n( "&Accept Configuration" ), "dialog-ok" )); setButtonGuiItem( KDialog::Cancel, KGuiItem( i18n( "&Return to Previous Configuration" ), "dialog-cancel" )); QLabel *label = new QLabel( i18n( "Desktop effects settings have changed.\n" "Do you want to keep the new settings?\n" "They will be automatically reverted in 10 seconds." ), this ); label->setWordWrap( true ); setMainWidget( label ); } KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList &) : KCModule( KWinCompositingConfigFactory::componentData(), parent), mKWinConfig(KSharedConfig::openConfig("kwinrc")), m_showConfirmDialog (false) { KGlobal::locale()->insertCatalog( "kwin_effects" ); ui.setupUi(this); layout()->setMargin(0); ui.tabWidget->setCurrentIndex(0); ui.statusLabel->hide(); connect(ui.advancedOptions, SIGNAL(clicked()), this, SLOT(showAdvancedOptions())); connect(ui.useCompositing, SIGNAL(toggled(bool)), this, SLOT(compositingEnabled(bool))); connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); connect(ui.useCompositing, SIGNAL(toggled(bool)), this, SLOT(changed())); connect(ui.effectWinManagement, SIGNAL(toggled(bool)), this, SLOT(changed())); connect(ui.effectShadows, SIGNAL(toggled(bool)), this, SLOT(changed())); connect(ui.effectAnimations, SIGNAL(toggled(bool)), this, SLOT(changed())); connect(ui.effectSelector, SIGNAL(changed(bool)), this, SLOT(changed())); connect(ui.effectSelector, SIGNAL(configCommitted(const QByteArray&)), this, SLOT(reparseConfiguration(const QByteArray&))); // Open the temporary config file // Temporary conf file is used to syncronize effect checkboxes with effect // selector by loading/saving effects from/to temp config when active tab // changes. mTmpConfigFile.open(); mTmpConfig = KSharedConfig::openConfig(mTmpConfigFile.fileName()); if( CompositingPrefs::compositingPossible() ) { // Driver-specific config detection mDefaultPrefs.detect(); initEffectSelector(); // Load config load(); } else { ui.useCompositing->setEnabled(false); ui.useCompositing->setChecked(false); compositingEnabled(false); QString text = i18n("Compositing is not supported on your system."); text += "

"; text += CompositingPrefs::compositingNotPossibleReason(); ui.statusLabel->setText(text); ui.statusLabel->show(); } KAboutData *about = new KAboutData(I18N_NOOP("kcmkwincompositing"), 0, ki18n("KWin Desktop Effects Configuration Module"), 0, KLocalizedString(), KAboutData::License_GPL, ki18n("(c) 2007 Rivo Laks")); about->addAuthor(ki18n("Rivo Laks"), KLocalizedString(), "rivolaks@hot.ee"); setAboutData(about); } KWinCompositingConfig::~KWinCompositingConfig() { } void KWinCompositingConfig::reparseConfiguration(const QByteArray&conf) { KSettings::Dispatcher::reparseConfiguration(conf); } void KWinCompositingConfig::compositingEnabled(bool enabled) { ui.compositingOptionsContainer->setEnabled(enabled); ui.tabWidget->setTabEnabled(1, enabled); } void KWinCompositingConfig::showAdvancedOptions() { KWinAdvancedCompositingOptions* dialog = new KWinAdvancedCompositingOptions(this, mKWinConfig, &mDefaultPrefs); dialog->show(); } void KWinCompositingConfig::showConfirmDialog() { ConfirmDialog confirm; if(!confirm.exec()) { // Revert settings KConfigGroup config(mKWinConfig, "Compositing"); config.deleteGroup(); QMap::const_iterator it = mPreviousConfig.constBegin(); for(; it != mPreviousConfig.constEnd(); ++it) { if (it.value().isEmpty()) continue; config.writeEntry(it.key(), it.value()); } // Sync with KWin and reload configChanged(); load(); } } void KWinCompositingConfig::initEffectSelector() { // Find all .desktop files of the effects KService::List offers = KServiceTypeTrader::self()->query("KWin/Effect"); QList effectinfos = KPluginInfo::fromServices(offers); // Add them to the plugin selector ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Appearance"), "Appearance", mTmpConfig); ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Accessibility"), "Accessibility", mTmpConfig); ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Window Management"), "Window Management", mTmpConfig); ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Demos"), "Demos", mTmpConfig); ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Tests"), "Tests", mTmpConfig); ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Misc"), "Misc", mTmpConfig); } void KWinCompositingConfig::currentTabChanged(int tab) { if (tab == 0) { // General tab was activated saveEffectsTab(); loadGeneralTab(); } else { // Effects tab was activated saveGeneralTab(); loadEffectsTab(); } } void KWinCompositingConfig::loadGeneralTab() { KConfigGroup config(mKWinConfig, "Compositing"); ui.useCompositing->setChecked(config.readEntry("Enabled", mDefaultPrefs.enableCompositing())); // Load effect settings KConfigGroup effectconfig(mTmpConfig, "Plugins"); #define LOAD_EFFECT_CONFIG(effectname) effectconfig.readEntry("kwin4_effect_" effectname "Enabled", true) int winManagementEnabled = LOAD_EFFECT_CONFIG("presentwindows") + LOAD_EFFECT_CONFIG("boxswitch") + LOAD_EFFECT_CONFIG("desktopgrid") + LOAD_EFFECT_CONFIG("dialogparent"); if (winManagementEnabled > 0 && winManagementEnabled < 4) { ui.effectWinManagement->setTristate(true); ui.effectWinManagement->setCheckState(Qt::PartiallyChecked); } else ui.effectWinManagement->setChecked(winManagementEnabled); ui.effectShadows->setChecked(LOAD_EFFECT_CONFIG("shadow")); ui.effectAnimations->setChecked(LOAD_EFFECT_CONFIG("minimizeanimation")); #undef LOAD_EFFECT_CONFIG } void KWinCompositingConfig::loadEffectsTab() { ui.effectSelector->load(); } void KWinCompositingConfig::load() { mKWinConfig->reparseConfiguration(); // Copy Plugins group to temp config file QMap entries = mKWinConfig->entryMap("Plugins"); QMap::const_iterator it = entries.constBegin(); KConfigGroup tmpconfig(mTmpConfig, "Plugins"); tmpconfig.deleteGroup(); for(; it != entries.constEnd(); ++it) { tmpconfig.writeEntry(it.key(), it.value()); } loadGeneralTab(); loadEffectsTab(); emit changed( false ); } void KWinCompositingConfig::saveGeneralTab() { KConfigGroup config(mKWinConfig, "Compositing"); // Save current config. We'll use this for restoring in case something // goes wrong. mPreviousConfig = config.entryMap(); // Check if any critical settings that need confirmation have changed if(ui.useCompositing->isChecked() && ui.useCompositing->isChecked() != config.readEntry("Enabled", mDefaultPrefs.enableCompositing())) { m_showConfirmDialog = true; } config.writeEntry("Enabled", ui.useCompositing->isChecked()); // Save effects KConfigGroup effectconfig(mTmpConfig, "Plugins"); #define WRITE_EFFECT_CONFIG(effectname, widget) effectconfig.writeEntry("kwin4_effect_" effectname "Enabled", widget->isChecked()) if (ui.effectWinManagement->checkState() != Qt::PartiallyChecked) { WRITE_EFFECT_CONFIG("presentwindows", ui.effectWinManagement); WRITE_EFFECT_CONFIG("boxswitch", ui.effectWinManagement); WRITE_EFFECT_CONFIG("desktopgrid", ui.effectWinManagement); WRITE_EFFECT_CONFIG("dialogparent", ui.effectWinManagement); } WRITE_EFFECT_CONFIG("shadow", ui.effectShadows); // TODO: maybe also do some effect-specific configuration here, e.g. // enable/disable desktopgrid's animation according to this setting WRITE_EFFECT_CONFIG("minimizeanimation", ui.effectAnimations); #undef WRITE_EFFECT_CONFIG } void KWinCompositingConfig::saveEffectsTab() { ui.effectSelector->save(); } void KWinCompositingConfig::save() { // bah; tab content being dependent on the other is really bad; and // deprecated in the HIG for a reason. Its confusing! // Make sure we only call save on each tab once; as they are stateful due to the revert concept if (ui.tabWidget->currentIndex() == 0) { // general was active saveGeneralTab(); loadEffectsTab(); saveEffectsTab(); } else { // effects tab was active saveEffectsTab(); loadGeneralTab(); saveGeneralTab(); } // Copy Plugins group from temp config to real config QMap entries = mTmpConfig->entryMap("Plugins"); QMap::const_iterator it = entries.constBegin(); KConfigGroup realconfig(mKWinConfig, "Plugins"); realconfig.deleteGroup(); for(; it != entries.constEnd(); ++it) { realconfig.writeEntry(it.key(), it.value()); } emit changed( false ); configChanged(); if(m_showConfirmDialog) { m_showConfirmDialog = false; showConfirmDialog(); } } void KWinCompositingConfig::configChanged() { // Send signal to kwin mKWinConfig->sync(); // Send signal to all kwin instances QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reconfigure"); QDBusConnection::sessionBus().send(message); } void KWinCompositingConfig::defaults() { ui.useCompositing->setChecked(mDefaultPrefs.enableCompositing()); ui.effectWinManagement->setChecked(true); ui.effectShadows->setChecked(true); ui.effectAnimations->setChecked(true); ui.effectSelector->defaults(); } QString KWinCompositingConfig::quickHelp() const { return i18n("

Desktop Effects

"); } } // namespace #include "main.moc"