main.cpp 23.7 KB
Newer Older
1 2 3 4
/********************************************************************
 KWin - the KDE window manager
 This file is part of the KDE project.

5
Copyright (C) 2009 Martin Gräßlin <mgraesslin@kde.org>
6
Copyright (C) 2020 Cyril Rossi <cyril.rossi@enioka.com>
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

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 <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "main.h"
22
#include <effect_builtins.h>
23
#include <kwin_effects_interface.h>
24 25

// Qt
26
#include <QtDBus>
Thomas Lübking's avatar
Thomas Lübking committed
27
#include <QDesktopWidget>
28
#include <QDialogButtonBox>
29 30 31 32
#include <QHBoxLayout>
#include <QPushButton>
#include <QVBoxLayout>
#include <QSpacerItem>
33
#include <QStandardPaths>
Martin Flöser's avatar
Martin Flöser committed
34
#include <QPointer>
35 36 37 38

// KDE
#include <KActionCollection>
#include <KCModuleProxy>
39
#include <KGlobalAccel>
40
#include <KLocalizedString>
41
#include <KPluginFactory>
42
#include <KPluginTrader>
43 44 45
#include <KTitleWidget>
#include <KServiceTypeTrader>
#include <KShortcutsEditor>
46
#include <KNewStuff3/KNS3/DownloadDialog>
47
// Plasma
48 49
#include <KPackage/Package>
#include <KPackage/PackageLoader>
50 51

// own
Thomas Lübking's avatar
Thomas Lübking committed
52
#include "layoutpreview.h"
53 54 55
#include "kwintabboxsettings.h"
#include "kwinswitcheffectsettings.h"
#include "kwinpluginssettings.h"
56

57
K_PLUGIN_FACTORY(KWinTabBoxConfigFactory, registerPlugin<KWin::KWinTabBoxConfig>();)
58 59 60 61

namespace KWin
{

Thomas Lübking's avatar
Thomas Lübking committed
62 63
using namespace TabBox;

64 65 66 67 68
KWinTabBoxConfigForm::KWinTabBoxConfigForm(QWidget* parent)
    : QWidget(parent)
{
    setupUi(this);
}
69

70
KWinTabBoxConfig::KWinTabBoxConfig(QWidget* parent, const QVariantList& args)
Martin Flöser's avatar
Martin Flöser committed
71
    : KCModule(parent, args)
72
    , m_config(KSharedConfig::openConfig("kwinrc"))
73 74 75 76 77
    , m_tabBoxConfig(new TabBoxSettings(QStringLiteral("TabBox"), this))
    , m_tabBoxAlternativeConfig(new TabBoxSettings(QStringLiteral("TabBoxAlternative"), this))
    , m_coverSwitchConfig(new SwitchEffectSettings(QStringLiteral("Effect-CoverSwitch"), this))
    , m_flipSwitchConfig(new SwitchEffectSettings(QStringLiteral("Effect-FlipSwitch"), this))
    , m_pluginsConfig(new PluginsSettings(this))
78
{
79
    QTabWidget* tabWidget = new QTabWidget(this);
80 81 82 83
    m_primaryTabBoxUi = new KWinTabBoxConfigForm(tabWidget);
    m_alternativeTabBoxUi = new KWinTabBoxConfigForm(tabWidget);
    tabWidget->addTab(m_primaryTabBoxUi, i18n("Main"));
    tabWidget->addTab(m_alternativeTabBoxUi, i18n("Alternative"));
84 85 86 87 88 89 90 91 92

    QPushButton* ghnsButton = new QPushButton(QIcon::fromTheme(QStringLiteral("get-hot-new-stuff")), i18n("Get New Task Switchers..."));
    connect(ghnsButton, SIGNAL(clicked(bool)), SLOT(slotGHNS()));

    QHBoxLayout* buttonBar = new QHBoxLayout();
    QSpacerItem* buttonBarSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
    buttonBar->addItem(buttonBarSpacer);
    buttonBar->addWidget(ghnsButton);

93 94 95 96 97
    QVBoxLayout* layout = new QVBoxLayout(this);
    KTitleWidget* infoLabel = new KTitleWidget(tabWidget);
    infoLabel->setText(i18n("Focus policy settings limit the functionality of navigating through windows."),
                       KTitleWidget::InfoMessage);
    infoLabel->setPixmap(KTitleWidget::InfoMessage, KTitleWidget::ImageLeft);
Thomas Lübking's avatar
Thomas Lübking committed
98 99
    layout->addWidget(infoLabel,0);
    layout->addWidget(tabWidget,1);
100
    layout->addLayout(buttonBar);
Thomas Lübking's avatar
Thomas Lübking committed
101 102 103
    setLayout(layout);

#define ADD_SHORTCUT(_NAME_, _CUT_, _BTN_) \
104
    a = m_actionCollection->addAction(_NAME_);\
Thomas Lübking's avatar
Thomas Lübking committed
105 106 107
    a->setProperty("isConfigurationAction", true);\
    _BTN_->setProperty("shortcutAction", _NAME_);\
    a->setText(i18n(_NAME_));\
108
    KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>() << _CUT_); \
Thomas Lübking's avatar
Thomas Lübking committed
109
    connect(_BTN_, SIGNAL(keySequenceChanged(QKeySequence)), SLOT(shortcutChanged(QKeySequence)))
110

111
    // Shortcut config. The shortcut belongs to the component "kwin"!
112
    m_actionCollection = new KActionCollection(this, QStringLiteral("kwin"));
113
    m_actionCollection->setComponentDisplayName(i18n("KWin"));
114 115
    m_actionCollection->setConfigGroup("Navigation");
    m_actionCollection->setConfigGlobal(true);
116
    QAction* a;
Thomas Lübking's avatar
Thomas Lübking committed
117 118 119
    ADD_SHORTCUT("Walk Through Windows", Qt::ALT + Qt::Key_Tab, m_primaryTabBoxUi->scAll);
    ADD_SHORTCUT("Walk Through Windows (Reverse)", Qt::ALT + Qt::SHIFT + Qt::Key_Backtab,
                 m_primaryTabBoxUi->scAllReverse);
120 121
    ADD_SHORTCUT("Walk Through Windows Alternative", QKeySequence(), m_alternativeTabBoxUi->scAll);
    ADD_SHORTCUT("Walk Through Windows Alternative (Reverse)", QKeySequence(), m_alternativeTabBoxUi->scAllReverse);
Thomas Lübking's avatar
Thomas Lübking committed
122 123 124 125
    ADD_SHORTCUT("Walk Through Windows of Current Application", Qt::ALT + Qt::Key_QuoteLeft,
                 m_primaryTabBoxUi->scCurrent);
    ADD_SHORTCUT("Walk Through Windows of Current Application (Reverse)", Qt::ALT + Qt::Key_AsciiTilde,
                 m_primaryTabBoxUi->scCurrentReverse);
126 127
    ADD_SHORTCUT("Walk Through Windows of Current Application Alternative", QKeySequence(), m_alternativeTabBoxUi->scCurrent);
    ADD_SHORTCUT("Walk Through Windows of Current Application Alternative (Reverse)", QKeySequence(),
Thomas Lübking's avatar
Thomas Lübking committed
128 129
                 m_alternativeTabBoxUi->scCurrentReverse);
#undef ADD_SHORTCUT
130

131
    initLayoutLists();
Thomas Lübking's avatar
Thomas Lübking committed
132 133
    KWinTabBoxConfigForm *ui[2] = { m_primaryTabBoxUi, m_alternativeTabBoxUi };
    for (int i = 0; i < 2; ++i) {
Nick Shaforostoff's avatar
Nick Shaforostoff committed
134
        ui[i]->effectConfigButton->setIcon(QIcon::fromTheme(QStringLiteral("view-preview")));
135

Thomas Lübking's avatar
Thomas Lübking committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
        connect(ui[i]->highlightWindowCheck, SIGNAL(clicked(bool)), SLOT(changed()));
        connect(ui[i]->showTabBox, SIGNAL(clicked(bool)), SLOT(tabBoxToggled(bool)));
        connect(ui[i]->effectCombo, SIGNAL(currentIndexChanged(int)), SLOT(changed()));
        connect(ui[i]->effectCombo, SIGNAL(currentIndexChanged(int)), SLOT(effectSelectionChanged(int)));
        connect(ui[i]->effectConfigButton, SIGNAL(clicked(bool)), SLOT(configureEffectClicked()));

        connect(ui[i]->switchingModeCombo, SIGNAL(currentIndexChanged(int)), SLOT(changed()));
        connect(ui[i]->showDesktop, SIGNAL(clicked(bool)), SLOT(changed()));

        connect(ui[i]->filterDesktops, SIGNAL(clicked(bool)), SLOT(changed()));
        connect(ui[i]->currentDesktop, SIGNAL(clicked(bool)), SLOT(changed()));
        connect(ui[i]->otherDesktops, SIGNAL(clicked(bool)), SLOT(changed()));

        connect(ui[i]->filterActivities, SIGNAL(clicked(bool)), SLOT(changed()));
        connect(ui[i]->currentActivity, SIGNAL(clicked(bool)), SLOT(changed()));
        connect(ui[i]->otherActivities, SIGNAL(clicked(bool)), SLOT(changed()));

        connect(ui[i]->filterScreens, SIGNAL(clicked(bool)), SLOT(changed()));
154
        if (QApplication::screens().count() < 2) {
Thomas Lübking's avatar
Thomas Lübking committed
155 156 157 158 159 160
            ui[i]->filterScreens->hide();
            ui[i]->screenFilter->hide();
        } else {
            connect(ui[i]->currentScreen, SIGNAL(clicked(bool)), SLOT(changed()));
            connect(ui[i]->otherScreens, SIGNAL(clicked(bool)), SLOT(changed()));
        }
161

Thomas Lübking's avatar
Thomas Lübking committed
162 163 164 165 166
        connect(ui[i]->oneAppWindow, SIGNAL(clicked(bool)), SLOT(changed()));
        connect(ui[i]->filterMinimization, SIGNAL(clicked(bool)), SLOT(changed()));
        connect(ui[i]->visibleWindows, SIGNAL(clicked(bool)), SLOT(changed()));
        connect(ui[i]->hiddenWindows, SIGNAL(clicked(bool)), SLOT(changed()));
    }
167 168

    // check focus policy - we don't offer configs for unreasonable focus policies
169 170 171 172
    KConfigGroup config(m_config, "Windows");
    QString policy = config.readEntry("FocusPolicy", "ClickToFocus");
    if ((policy == "FocusUnderMouse") || (policy == "FocusStrictlyUnderMouse")) {
        tabWidget->setEnabled(false);
173
        infoLabel->show();
174
    } else {
175
        infoLabel->hide();
176
    }
177
}
178 179

KWinTabBoxConfig::~KWinTabBoxConfig()
180 181
{
}
182

183

184
static QList<KPackage::Package> availableLnFPackages()
185
{
186
    QList<KPackage::Package> packages;
187 188 189 190
    QStringList paths;
    const QStringList dataPaths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);

    for (const QString &path : dataPaths) {
Nick Shaforostoff's avatar
Nick Shaforostoff committed
191
        QDir dir(path + QLatin1String("/plasma/look-and-feel"));
192 193 194 195 196
        paths << dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
    }

    const auto &p = paths;
    for (const QString &path : p) {
197
        KPackage::Package pkg = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/LookAndFeel"));
198
        pkg.setPath(path);
199
        pkg.setFallbackPackage(KPackage::Package());
200 201 202 203 204 205 206 207 208 209 210 211 212
        if (!pkg.filePath("defaults").isEmpty()) {
            KSharedConfigPtr conf = KSharedConfig::openConfig(pkg.filePath("defaults"));
            KConfigGroup cg = KConfigGroup(conf, "kwinrc");
            cg = KConfigGroup(&cg, "WindowSwitcher");
            if (!cg.readEntry("LayoutName", QString()).isEmpty()) {
                packages << pkg;
            }
        }
    }

    return packages;
}

213 214 215
void KWinTabBoxConfig::initLayoutLists()
{
    // search the effect names
216 217
    QString coverswitch = BuiltInEffects::effectData(BuiltInEffect::CoverSwitch).displayName;
    QString flipswitch = BuiltInEffects::effectData(BuiltInEffect::FlipSwitch).displayName;
218

Marco Martin's avatar
Marco Martin committed
219
    QList<KPluginMetaData> offers = KPackage::PackageLoader::self()->listPackages("KWin/WindowSwitcher");
220
    QStringList layoutNames, layoutPlugins, layoutPaths;
221 222 223 224 225

    const auto lnfPackages = availableLnFPackages();
    for (const auto &package : lnfPackages) {
        const auto &metaData = package.metadata();
        layoutNames << metaData.name();
226
        layoutPlugins << metaData.pluginId();
227 228 229
        layoutPaths << package.filePath("windowswitcher", QStringLiteral("WindowSwitcher.qml"));
    }

Marco Martin's avatar
Marco Martin committed
230 231 232
    for (const auto &offer : offers) {
        const QString pluginName = offer.pluginId();
        if (offer.value("X-Plasma-API") != "declarativeappletscript") {
233 234
            continue;
        }
Marco Martin's avatar
Marco Martin committed
235 236
        //we don't have a proper servicetype
        if (offer.value("X-KWin-Exclude-Listing") == QStringLiteral("true")) {
237 238
            continue;
        }
Marco Martin's avatar
Marco Martin committed
239
        const QString scriptName = offer.value("X-Plasma-MainScript");
240
        const QString scriptFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation,
Nick Shaforostoff's avatar
Nick Shaforostoff committed
241
                                                          QLatin1String("kwin/tabbox/") + pluginName + QLatin1String("/contents/")
242
                                                          + scriptName);
243 244 245 246
        if (scriptFile.isNull()) {
            continue;
        }

Marco Martin's avatar
Marco Martin committed
247
        layoutNames << offer.name();
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
        layoutPlugins << pluginName;
        layoutPaths << scriptFile;
    }

    KWinTabBoxConfigForm *ui[2] = { m_primaryTabBoxUi, m_alternativeTabBoxUi };
    for (int i=0; i<2; ++i) {
        int index = ui[i]->effectCombo->currentIndex();
        QVariant data = ui[i]->effectCombo->itemData(index);
        ui[i]->effectCombo->clear();
        ui[i]->effectCombo->addItem(coverswitch);
        ui[i]->effectCombo->addItem(flipswitch);
        for (int j = 0; j < layoutNames.count(); ++j) {
            ui[i]->effectCombo->addItem(layoutNames[j], layoutPlugins[j]);
            ui[i]->effectCombo->setItemData(ui[i]->effectCombo->count() - 1, layoutPaths[j], Qt::UserRole+1);
        }
        if (data.isValid()) {
            ui[i]->effectCombo->setCurrentIndex(ui[i]->effectCombo->findData(data));
        } else if (index != -1) {
            ui[i]->effectCombo->setCurrentIndex(index);
        }
    }
}

271
void KWinTabBoxConfig::load()
272
{
273 274
    KCModule::load();

275 276
    m_tabBoxConfig->load();
    m_tabBoxAlternativeConfig->load();
Thomas Lübking's avatar
Thomas Lübking committed
277

278 279 280 281
    m_coverSwitchConfig->load();
    m_flipSwitchConfig->load();

    m_pluginsConfig->load();
Thomas Lübking's avatar
Thomas Lübking committed
282

283 284
    updateUiFromConfig(m_primaryTabBoxUi, m_tabBoxConfig);
    updateUiFromConfig(m_alternativeTabBoxUi , m_tabBoxAlternativeConfig);
Thomas Lübking's avatar
Thomas Lübking committed
285

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
    if (m_pluginsConfig->coverswitchEnabled()) {
        if (m_coverSwitchConfig->tabBox()) {
            m_primaryTabBoxUi->effectCombo->setCurrentIndex(CoverSwitch);
        }
        if (m_coverSwitchConfig->tabBoxAlternative()) {
            m_alternativeTabBoxUi->effectCombo->setCurrentIndex(CoverSwitch);
        }
    }
    if (m_pluginsConfig->flipswitchEnabled()) {
        if (m_flipSwitchConfig->tabBox()) {
            m_primaryTabBoxUi->effectCombo->setCurrentIndex(FlipSwitch);
        }
        if (m_flipSwitchConfig->tabBoxAlternative()) {
            m_alternativeTabBoxUi->effectCombo->setCurrentIndex(FlipSwitch);
        }
    }
Thomas Lübking's avatar
Thomas Lübking committed
302

303 304
    KWinTabBoxConfigForm* ui[2] = { m_primaryTabBoxUi, m_alternativeTabBoxUi };
    for (int i = 0; i < 2; ++i) {
Thomas Lübking's avatar
Thomas Lübking committed
305 306 307 308
        QString action;
#define LOAD_SHORTCUT(_BTN_)\
        action = ui[i]->_BTN_->property("shortcutAction").toString();\
        qDebug() << "load shortcut for " << action;\
309 310 311 312 313
        if (QAction *a = m_actionCollection->action(action)) { \
            auto shortcuts = KGlobalAccel::self()->shortcut(a); \
            if (!shortcuts.isEmpty()) \
                ui[i]->_BTN_->setKeySequence(shortcuts.first()); \
        }
Thomas Lübking's avatar
Thomas Lübking committed
314 315 316 317 318
        LOAD_SHORTCUT(scAll);
        LOAD_SHORTCUT(scAllReverse);
        LOAD_SHORTCUT(scCurrent);
        LOAD_SHORTCUT(scCurrentReverse);
#undef LOAD_SHORTCUT
319 320 321 322
    }
    emit changed(false);
}

323
void KWinTabBoxConfig::save()
324
{
325 326 327
    KCModule::save();

    // sync ui to config
328 329
    updateConfigFromUi(m_primaryTabBoxUi, m_tabBoxConfig);
    updateConfigFromUi(m_alternativeTabBoxUi, m_tabBoxAlternativeConfig);
330 331
    m_tabBoxConfig->save();
    m_tabBoxAlternativeConfig->save();
332 333

    // effects
334 335
    bool highlightWindows = m_primaryTabBoxUi->highlightWindowCheck->isChecked() ||
                            m_alternativeTabBoxUi->highlightWindowCheck->isChecked();
Thomas Lübking's avatar
Thomas Lübking committed
336 337 338 339 340 341 342 343
    const bool coverSwitch = m_primaryTabBoxUi->showTabBox->isChecked() &&
                             m_primaryTabBoxUi->effectCombo->currentIndex() == CoverSwitch;
    const bool flipSwitch = m_primaryTabBoxUi->showTabBox->isChecked() &&
                            m_primaryTabBoxUi->effectCombo->currentIndex() == FlipSwitch;
    const bool coverSwitchAlternative = m_alternativeTabBoxUi->showTabBox->isChecked() &&
                                        m_alternativeTabBoxUi->effectCombo->currentIndex() == CoverSwitch;
    const bool flipSwitchAlternative = m_alternativeTabBoxUi->showTabBox->isChecked() &&
                                       m_alternativeTabBoxUi->effectCombo->currentIndex() == FlipSwitch;
344

345
    // activate effects if not active
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
    if (coverSwitch || coverSwitchAlternative) {
        m_pluginsConfig->setCoverswitchEnabled(true);
    }
    if (flipSwitch || flipSwitchAlternative) {
        m_pluginsConfig->setFlipswitchEnabled(true);
    }
    if (highlightWindows) {
        m_pluginsConfig->setHighlightwindowEnabled(true);
    }
    m_pluginsConfig->save();

    m_coverSwitchConfig->setTabBox(coverSwitch);
    m_coverSwitchConfig->setTabBoxAlternative(coverSwitchAlternative);
    m_coverSwitchConfig->save();

    m_flipSwitchConfig->setTabBox(flipSwitch);
    m_flipSwitchConfig->setTabBoxAlternative(flipSwitchAlternative);
    m_flipSwitchConfig->save();
364 365

    // Reload KWin.
366 367
    QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig");
    QDBusConnection::sessionBus().send(message);
368 369 370 371 372 373
    // and reconfigure the effects
    OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"),
                                             QStringLiteral("/Effects"),
                                             QDBusConnection::sessionBus());
    interface.reconfigureEffect(BuiltInEffects::nameForEffect(BuiltInEffect::CoverSwitch));
    interface.reconfigureEffect(BuiltInEffects::nameForEffect(BuiltInEffect::FlipSwitch));
374

375 376
    emit changed(false);
}
377 378

void KWinTabBoxConfig::defaults()
379
{
380 381 382 383 384 385 386 387 388 389 390
    KCModule::defaults();

    m_tabBoxConfig->setDefaults();
    m_tabBoxAlternativeConfig->setDefaults();

    m_pluginsConfig->setDefaults();
    m_coverSwitchConfig->setDefaults();
    m_flipSwitchConfig->setDefaults();

    updateUiFromConfig(m_primaryTabBoxUi, m_tabBoxConfig);
    updateUiFromConfig(m_alternativeTabBoxUi, m_tabBoxAlternativeConfig);
391

Thomas Lübking's avatar
Thomas Lübking committed
392
    QString action;
393 394 395 396 397
    auto RESET_SHORTCUT = [this](KKeySequenceWidget *widget, const QKeySequence &sequence = QKeySequence()) {
        const QString action = widget->property("shortcutAction").toString();
        QAction *a = m_actionCollection->action(action);
        KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>() << sequence, KGlobalAccel::NoAutoloading);
    };
Thomas Lübking's avatar
Thomas Lübking committed
398 399
    RESET_SHORTCUT(m_primaryTabBoxUi->scAll, Qt::ALT + Qt::Key_Tab);
    RESET_SHORTCUT(m_primaryTabBoxUi->scAllReverse, Qt::ALT + Qt::SHIFT + Qt::Key_Backtab);
400 401
    RESET_SHORTCUT(m_alternativeTabBoxUi->scAll);
    RESET_SHORTCUT(m_alternativeTabBoxUi->scAllReverse);
Thomas Lübking's avatar
Thomas Lübking committed
402 403
    RESET_SHORTCUT(m_primaryTabBoxUi->scCurrent, Qt::ALT + Qt::Key_QuoteLeft);
    RESET_SHORTCUT(m_primaryTabBoxUi->scCurrentReverse, Qt::ALT + Qt::Key_AsciiTilde);
404 405
    RESET_SHORTCUT(m_alternativeTabBoxUi->scCurrent);
    RESET_SHORTCUT(m_alternativeTabBoxUi->scCurrentReverse);
Thomas Lübking's avatar
Thomas Lübking committed
406
    m_actionCollection->writeSettings();
407 408
    emit changed(true);
}
409

410
void KWinTabBoxConfig::updateUiFromConfig(KWinTabBoxConfigForm *ui, const KWin::TabBox::TabBoxSettings *config)
411
{
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
#define CONFIGURE(SETTING, MODE, IS, VALUE) ui->SETTING->setChecked(config->MODE##Mode() IS TabBoxConfig::VALUE)
    CONFIGURE(filterDesktops, desktop, !=, AllDesktopsClients);
    CONFIGURE(currentDesktop, desktop, ==, OnlyCurrentDesktopClients);
    CONFIGURE(otherDesktops, desktop, ==, ExcludeCurrentDesktopClients);
    CONFIGURE(filterActivities, activities, !=, AllActivitiesClients);
    CONFIGURE(currentActivity, activities, ==, OnlyCurrentActivityClients);
    CONFIGURE(otherActivities, activities, ==, ExcludeCurrentActivityClients);
    CONFIGURE(filterScreens, multiScreen, !=, IgnoreMultiScreen);
    CONFIGURE(currentScreen, multiScreen, ==, OnlyCurrentScreenClients);
    CONFIGURE(otherScreens, multiScreen, ==, ExcludeCurrentScreenClients);
    CONFIGURE(oneAppWindow, applications, ==, OneWindowPerApplication);
    CONFIGURE(filterMinimization, minimized, !=, IgnoreMinimizedStatus);
    CONFIGURE(visibleWindows, minimized, ==, ExcludeMinimizedClients);
    CONFIGURE(hiddenWindows, minimized, ==, OnlyMinimizedClients);

    ui->switchingModeCombo->setCurrentIndex(config->switchingMode());
428 429

    // check boxes
430 431 432
    ui->showTabBox->setChecked(config->showTabBox());
    ui->highlightWindowCheck->setChecked(config->highlightWindows());
    ui->effectCombo->setCurrentIndex(ui->effectCombo->findData(config->layoutName()));
Thomas Lübking's avatar
Thomas Lübking committed
433 434
    CONFIGURE(showDesktop, showDesktop, ==, ShowDesktopClient);
#undef CONFIGURE
435
}
436

437
void KWinTabBoxConfig::updateConfigFromUi(const KWin::KWinTabBoxConfigForm *ui, TabBoxSettings *config)
438
{
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
    if (ui->filterDesktops->isChecked()) {
        config->setDesktopMode(ui->currentDesktop->isChecked() ? TabBoxConfig::OnlyCurrentDesktopClients : TabBoxConfig::ExcludeCurrentDesktopClients);
    } else {
        config->setDesktopMode(TabBoxConfig::AllDesktopsClients);
    }
    if (ui->filterActivities->isChecked()) {
        config->setActivitiesMode(ui->currentActivity->isChecked() ? TabBoxConfig::OnlyCurrentActivityClients : TabBoxConfig::ExcludeCurrentActivityClients);
    } else {
        config->setActivitiesMode(TabBoxConfig::AllActivitiesClients);
    }
    if (ui->filterScreens->isChecked()) {
        config->setMultiScreenMode(ui->currentScreen->isChecked() ? TabBoxConfig::OnlyCurrentScreenClients : TabBoxConfig::ExcludeCurrentScreenClients);
    } else {
        config->setMultiScreenMode(TabBoxConfig::IgnoreMultiScreen);
    }
    config->setApplicationsMode(ui->oneAppWindow->isChecked() ? TabBoxConfig::OneWindowPerApplication : TabBoxConfig::AllWindowsAllApplications);
    if (ui->filterMinimization->isChecked()) {
        config->setMinimizedMode(ui->visibleWindows->isChecked() ? TabBoxConfig::ExcludeMinimizedClients : TabBoxConfig::OnlyMinimizedClients);
    } else {
        config->setMinimizedMode(TabBoxConfig::IgnoreMinimizedStatus);
    }

    config->setSwitchingMode(TabBoxConfig::ClientSwitchingMode(ui->switchingModeCombo->currentIndex()));

    config->setShowTabBox(ui->showTabBox->isChecked());
    config->setHighlightWindows(ui->highlightWindowCheck->isChecked());
Thomas Lübking's avatar
Thomas Lübking committed
465
    if (ui->effectCombo->currentIndex() >= Layout) {
466
        config->setLayoutName(ui->effectCombo->itemData(ui->effectCombo->currentIndex()).toString());
Thomas Lübking's avatar
Thomas Lübking committed
467
    }
468
    config->setShowDesktopMode(ui->showDesktop->isChecked() ? TabBoxConfig::ShowDesktopClient : TabBoxConfig::DoNotShowDesktopClient);
469
}
470

Thomas Lübking's avatar
Thomas Lübking committed
471 472
#define CHECK_CURRENT_TABBOX_UI \
    Q_ASSERT(sender());\
473
    KWinTabBoxConfigForm *ui = nullptr;\
Thomas Lübking's avatar
Thomas Lübking committed
474 475 476 477
    QObject *dad = sender();\
    while (!ui && (dad = dad->parent()))\
        ui = qobject_cast<KWinTabBoxConfigForm*>(dad);\
    Q_ASSERT(ui);
478

Thomas Lübking's avatar
Thomas Lübking committed
479
void KWinTabBoxConfig::effectSelectionChanged(int index)
480
{
Thomas Lübking's avatar
Thomas Lübking committed
481
    CHECK_CURRENT_TABBOX_UI
482
    ui->effectConfigButton->setIcon(QIcon::fromTheme(index < Layout ? "configure" : "view-preview"));
Thomas Lübking's avatar
Thomas Lübking committed
483
    if (!ui->showTabBox->isChecked())
484
        return;
Thomas Lübking's avatar
Thomas Lübking committed
485
    ui->highlightWindowCheck->setEnabled(index >= Layout);
486
}
487

488 489
void KWinTabBoxConfig::tabBoxToggled(bool on)
{
Thomas Lübking's avatar
Thomas Lübking committed
490 491 492
    CHECK_CURRENT_TABBOX_UI
    on = !on || ui->effectCombo->currentIndex() >= Layout;
    ui->highlightWindowCheck->setEnabled(on);
Aleix Pol Gonzalez's avatar
Aleix Pol Gonzalez committed
493
    markAsChanged();
494
}
495

Thomas Lübking's avatar
Thomas Lübking committed
496
void KWinTabBoxConfig::configureEffectClicked()
497
{
Thomas Lübking's avatar
Thomas Lübking committed
498 499 500 501
    CHECK_CURRENT_TABBOX_UI

    const int effect = ui->effectCombo->currentIndex();
    if (effect >= Layout) {
502 503
        // TODO: here we need to show the preview
        new LayoutPreview(ui->effectCombo->itemData(effect, Qt::UserRole+1).toString(), this);
504
    } else {
505 506
        QPointer<QDialog> configDialog = new QDialog(this);
        configDialog->setLayout(new QVBoxLayout);
Thomas Lübking's avatar
Thomas Lübking committed
507
        configDialog->setWindowTitle(ui->effectCombo->currentText());
508 509 510 511
        QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel|QDialogButtonBox::RestoreDefaults, configDialog);
        connect(buttonBox, SIGNAL(accepted()), configDialog, SLOT(accept()));
        connect(buttonBox, SIGNAL(rejected()), configDialog, SLOT(reject()));

512
        const QString name = BuiltInEffects::nameForEffect(effect == CoverSwitch ? BuiltInEffect::CoverSwitch : BuiltInEffect::FlipSwitch);
513

514
        KCModule *kcm = KPluginTrader::createInstanceFromQuery<KCModule>(QStringLiteral("kwin/effects/configs/"), QString(),
515
                                                                         QStringLiteral("'%1' in [X-KDE-ParentComponents]").arg(name),
516 517 518 519 520 521 522
                                                                        configDialog);
        if (!kcm) {
            delete configDialog;
            return;
        }

        connect(buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, kcm, &KCModule::defaults);
Thomas Lübking's avatar
Thomas Lübking committed
523 524 525 526

        QWidget *showWidget = new QWidget(configDialog);
        QVBoxLayout *layout = new QVBoxLayout;
        showWidget->setLayout(layout);
527
        layout->addWidget(kcm);
528 529
        configDialog->layout()->addWidget(showWidget);
        configDialog->layout()->addWidget(buttonBox);
Thomas Lübking's avatar
Thomas Lübking committed
530 531

        if (configDialog->exec() == QDialog::Accepted) {
532
            kcm->save();
Thomas Lübking's avatar
Thomas Lübking committed
533
        } else {
534
            kcm->load();
Thomas Lübking's avatar
Thomas Lübking committed
535 536
        }
        delete configDialog;
537
    }
538
}
539

Thomas Lübking's avatar
Thomas Lübking committed
540
void KWinTabBoxConfig::shortcutChanged(const QKeySequence &seq)
541
{
Thomas Lübking's avatar
Thomas Lübking committed
542 543 544 545 546
    QString action;
    if (sender())
        action = sender()->property("shortcutAction").toString();
    if (action.isEmpty())
        return;
547 548
    QAction *a = m_actionCollection->action(action);
    KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>() << seq, KGlobalAccel::NoAutoloading);
Thomas Lübking's avatar
Thomas Lübking committed
549
    m_actionCollection->writeSettings();
550
}
551

552 553 554
void KWinTabBoxConfig::slotGHNS()
{
    QPointer<KNS3::DownloadDialog> downloadDialog = new KNS3::DownloadDialog("kwinswitcher.knsrc", this);
555
    if (downloadDialog->exec() == QDialog::Accepted) {
556 557 558 559 560 561 562
        if (!downloadDialog->changedEntries().isEmpty()) {
            initLayoutLists();
        }
    }
    delete downloadDialog;
}

563
} // namespace
Martin Flöser's avatar
Martin Flöser committed
564 565

#include "main.moc"