diff --git a/kcmkwin/kwintabbox/CMakeLists.txt b/kcmkwin/kwintabbox/CMakeLists.txt index 4f7245acc7..6aa6c6a0f0 100644 --- a/kcmkwin/kwintabbox/CMakeLists.txt +++ b/kcmkwin/kwintabbox/CMakeLists.txt @@ -8,11 +8,7 @@ set(kcm_kwintabbox_PART_SRCS main.cpp layoutpreview.cpp thumbnailitem.cpp - ${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/tabbox/clientmodel.cpp - ${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/tabbox/declarative.cpp - ${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/tabbox/desktopmodel.cpp ${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/tabbox/tabboxconfig.cpp - ${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/tabbox/tabboxhandler.cpp ) kde4_add_ui_files( kcm_kwintabbox_PART_SRCS main.ui ) @@ -21,17 +17,11 @@ add_library(kcm_kwintabbox MODULE ${kcm_kwintabbox_PART_SRCS}) target_link_libraries(kcm_kwintabbox Qt5::Quick - Qt5::X11Extras KF5::KCMUtils KF5::Completion - KF5::Declarative KF5::GlobalAccel KF5::I18n - KF5::IconThemes KF5::Service - KF5::WindowSystem - KF5::Plasma - KF5::XmlGui KF5::NewStuff ${XCB_XCB_LIBRARY}) @@ -40,6 +30,5 @@ install(TARGETS kcm_kwintabbox DESTINATION ${PLUGIN_INSTALL_DIR} ) ########### install files ############### install( FILES kwintabbox.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) -install( FILES qml/main.qml DESTINATION ${DATA_INSTALL_DIR}/kwin/kcm_kwintabbox) install( FILES thumbnails/konqueror.png thumbnails/kmail.png thumbnails/systemsettings.png thumbnails/dolphin.png DESTINATION ${DATA_INSTALL_DIR}/kwin/kcm_kwintabbox) install( FILES kwinswitcher.knsrc DESTINATION ${CONFIG_INSTALL_DIR} ) diff --git a/kcmkwin/kwintabbox/layoutpreview.cpp b/kcmkwin/kwintabbox/layoutpreview.cpp index 4cff8734dd..0e100b0e89 100644 --- a/kcmkwin/kwintabbox/layoutpreview.cpp +++ b/kcmkwin/kwintabbox/layoutpreview.cpp @@ -20,12 +20,13 @@ along with this program. If not, see . // own #include "layoutpreview.h" #include "thumbnailitem.h" +#include +#include +#include #include #include #include #include -#include -#include #include #include @@ -34,65 +35,77 @@ namespace KWin namespace TabBox { -LayoutPreview::LayoutPreview(QWindow *parent) - : QQuickView(parent) +LayoutPreview::LayoutPreview(const QString &path, QObject *parent) + : QObject(parent) + , m_item(nullptr) { - setColor(Qt::white); - setMinimumSize(QSize(480, 300)); - setResizeMode(QQuickView::SizeRootObjectToView); - foreach (const QString &importPath, QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "kwin/tabbox", QStandardPaths::LocateDirectory)) { - engine()->addImportPath(importPath); + QQmlEngine *engine = new QQmlEngine(this); + QQmlComponent *component = new QQmlComponent(engine, this); + qmlRegisterType("org.kde.kwin", 2, 0, "ThumbnailItem"); + qmlRegisterType("org.kde.kwin", 2, 0, "Switcher"); + component->loadUrl(QUrl::fromLocalFile(path)); + QObject *item = component->create(); + auto findSwitcher = [item]() -> SwitcherItem* { + if (!item) { + return nullptr; + } + if (SwitcherItem *i = qobject_cast(item)) { + return i; + } else if (QQuickWindow *w = qobject_cast(item)) { + return w->contentItem()->findChild(); + } + return item->findChild(); + }; + if (SwitcherItem *switcher = findSwitcher()) { + m_item = switcher; + switcher->setVisible(true); + } + auto findWindow = [item]() -> QQuickWindow* { + if (!item) { + return nullptr; + } + if (QQuickWindow *w = qobject_cast(item)) { + return w; + } + return item->findChild(); + }; + if (QQuickWindow *w = findWindow()) { + w->setKeyboardGrabEnabled(true); + w->setMouseGrabEnabled(true); + w->installEventFilter(this); } - ExampleClientModel *model = new ExampleClientModel(this); - engine()->addImageProvider(QLatin1String("client"), new TabBoxImageProvider(model)); - qmlRegisterType("org.kde.kwin", 0, 1, "ThumbnailItem"); - rootContext()->setContextProperty("clientModel", model); - rootContext()->setContextProperty("sourcePath", QString()); - rootContext()->setContextProperty("name", QString()); - setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kwin/kcm_kwintabbox/main.qml"))); } LayoutPreview::~LayoutPreview() { } -void LayoutPreview::setLayout(const QString &path, const QString &name) -{ - rootContext()->setContextProperty("sourcePath", path); - rootContext()->setContextProperty("name", name); -} - -TabBoxImageProvider::TabBoxImageProvider(QAbstractListModel* model) - : QQuickImageProvider(QQuickImageProvider::Pixmap) - , m_model(model) -{ -} - -QPixmap TabBoxImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) +bool LayoutPreview::eventFilter(QObject *object, QEvent *event) { - bool ok = false; - QStringList parts = id.split('/'); - const int index = parts.first().toInt(&ok); - if (!ok) { - return QQuickImageProvider::requestPixmap(id, size, requestedSize); - } - QSize s(32, 32); - if (requestedSize.isValid()) { - s = requestedSize; - } - *size = s; - QPixmap icon(QIcon::fromTheme(m_model->data(m_model->index(index), Qt::UserRole+3).toString()).pixmap(s)); - if (parts.size() > 2) { - KIconEffect *effect = KIconLoader::global()->iconEffect(); - KIconLoader::States state = KIconLoader::DefaultState; - if (parts.at(2) == QLatin1String("selected")) { - state = KIconLoader::ActiveState; - } else if (parts.at(2) == QLatin1String("disabled")) { - state = KIconLoader::DisabledState; + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = dynamic_cast(event); + if (keyEvent->key() == Qt::Key_Escape || + keyEvent->key() == Qt::Key_Return || + keyEvent->key() == Qt::Key_Enter || + keyEvent->key() == Qt::Key_Space) { + object->deleteLater(); + deleteLater(); + } + if (m_item && keyEvent->key() == Qt::Key_Tab) { + m_item->incrementIndex(); + } + if (m_item && keyEvent->key() == Qt::Key_Backtab) { + m_item->decrementIndex(); + } + } else if (event->type() == QEvent::MouseButtonPress) { + if (QWindow *w = qobject_cast(object)) { + if (!w->geometry().contains(static_cast(event)->globalPos())) { + object->deleteLater(); + deleteLater(); + } } - icon = effect->apply(icon, KIconLoader::Desktop, state); } - return icon; + return QObject::eventFilter(object, event); } ExampleClientModel::ExampleClientModel (QObject* parent) @@ -161,6 +174,62 @@ int ExampleClientModel::rowCount(const QModelIndex &parent) const return m_nameList.size(); } +SwitcherItem::SwitcherItem(QObject *parent) + : QObject(parent) + , m_model(new ExampleClientModel(this)) + , m_item(nullptr) + , m_currentIndex(0) + , m_visible(false) +{ +} + +SwitcherItem::~SwitcherItem() +{ +} + +void SwitcherItem::setVisible(bool visible) +{ + if (m_visible == visible) { + return; + } + m_visible = visible; + emit visibleChanged(); +} + +void SwitcherItem::setItem(QObject *item) +{ + m_item = item; + emit itemChanged(); +} + +void SwitcherItem::setCurrentIndex(int index) +{ + if (m_currentIndex == index) { + return; + } + m_currentIndex = index; + emit currentIndexChanged(m_currentIndex); +} + +QRect SwitcherItem::screenGeometry() const +{ + return qApp->desktop()->screenGeometry(qApp->desktop()->primaryScreen()); +} + +void SwitcherItem::incrementIndex() +{ + setCurrentIndex((m_currentIndex + 1) % m_model->rowCount()); +} + +void SwitcherItem::decrementIndex() +{ + int index = m_currentIndex -1; + if (index < 0) { + index = m_model->rowCount() -1; + } + setCurrentIndex(index); +} + } // namespace KWin } // namespace TabBox diff --git a/kcmkwin/kwintabbox/layoutpreview.h b/kcmkwin/kwintabbox/layoutpreview.h index 6839b94aa0..7db9a07e9f 100644 --- a/kcmkwin/kwintabbox/layoutpreview.h +++ b/kcmkwin/kwintabbox/layoutpreview.h @@ -22,7 +22,7 @@ along with this program. If not, see . #include #include -#include +#include namespace KWin { @@ -30,23 +30,18 @@ namespace KWin namespace TabBox { -class LayoutPreview : public QQuickView +class SwitcherItem; + +class LayoutPreview : public QObject { Q_OBJECT public: - explicit LayoutPreview(QWindow *parent = nullptr); + explicit LayoutPreview(const QString &path, QObject *parent = nullptr); virtual ~LayoutPreview(); - void setLayout(const QString &path, const QString &name); -}; - -class TabBoxImageProvider : public QQuickImageProvider -{ -public: - explicit TabBoxImageProvider(QAbstractListModel *model); - virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize); + virtual bool eventFilter(QObject *object, QEvent *event) override; private: - QAbstractListModel *m_model; + SwitcherItem *m_item; }; class ExampleClientModel : public QAbstractListModel @@ -64,6 +59,79 @@ private: QStringList m_nameList; }; + +class SwitcherItem : public QObject +{ + Q_OBJECT + Q_PROPERTY(QAbstractItemModel *model READ model NOTIFY modelChanged) + Q_PROPERTY(QRect screenGeometry READ screenGeometry NOTIFY screenGeometryChanged) + Q_PROPERTY(bool visible READ isVisible NOTIFY visibleChanged) + Q_PROPERTY(bool allDesktops READ isAllDesktops NOTIFY allDesktopsChanged) + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + + /** + * The main QML item that will be displayed in the Dialog + */ + Q_PROPERTY(QObject *item READ item WRITE setItem NOTIFY itemChanged) + + Q_CLASSINFO("DefaultProperty", "item") +public: + SwitcherItem(QObject *parent = nullptr); + virtual ~SwitcherItem(); + + QAbstractItemModel *model() const; + QRect screenGeometry() const; + bool isVisible() const; + bool isAllDesktops() const; + int currentIndex() const; + void setCurrentIndex(int index); + QObject *item() const; + void setItem(QObject *item); + + void setVisible(bool visible); + void incrementIndex(); + void decrementIndex(); + +Q_SIGNALS: + void visibleChanged(); + void currentIndexChanged(int index); + void modelChanged(); + void allDesktopsChanged(); + void screenGeometryChanged(); + void itemChanged(); + +private: + QAbstractItemModel *m_model; + QObject *m_item; + int m_currentIndex; + bool m_visible; +}; + +inline QAbstractItemModel *SwitcherItem::model() const +{ + return m_model; +} + +inline bool SwitcherItem::isVisible() const +{ + return m_visible; +} + +inline bool SwitcherItem::isAllDesktops() const +{ + return true; +} + +inline int SwitcherItem::currentIndex() const +{ + return m_currentIndex; +} + +inline QObject *SwitcherItem::item() const +{ + return m_item; +} + } // namespace TabBox } // namespace KWin diff --git a/kcmkwin/kwintabbox/main.cpp b/kcmkwin/kwintabbox/main.cpp index 819c4dac70..5bda6887e0 100644 --- a/kcmkwin/kwintabbox/main.cpp +++ b/kcmkwin/kwintabbox/main.cpp @@ -61,7 +61,6 @@ KWinTabBoxConfigForm::KWinTabBoxConfigForm(QWidget* parent) KWinTabBoxConfig::KWinTabBoxConfig(QWidget* parent, const QVariantList& args) : KCModule(parent, args) , m_config(KSharedConfig::openConfig("kwinrc")) - , m_layoutPreview(NULL) { QTabWidget* tabWidget = new QTabWidget(this); m_primaryTabBoxUi = new KWinTabBoxConfigForm(tabWidget); @@ -475,12 +474,6 @@ void KWinTabBoxConfig::effectSelectionChanged(int index) if (!ui->showTabBox->isChecked()) return; ui->highlightWindowCheck->setEnabled(index >= Layout); - if (m_layoutPreview && m_layoutPreview->isVisible()) { - if (index < Layout) - m_layoutPreview->hide(); - else - m_layoutPreview->setLayout(ui->effectCombo->itemData(index, Qt::UserRole+1).toString(), ui->effectCombo->itemText(index)); - } } void KWinTabBoxConfig::tabBoxToggled(bool on) { @@ -496,13 +489,8 @@ void KWinTabBoxConfig::configureEffectClicked() const int effect = ui->effectCombo->currentIndex(); if (effect >= Layout) { - if (!m_layoutPreview) { - m_layoutPreview = new LayoutPreview(); - m_layoutPreview->setTitle(i18n("Tabbox layout preview")); - m_layoutPreview->setFlags(Qt::Dialog); - } - m_layoutPreview->setLayout(ui->effectCombo->itemData(effect, Qt::UserRole+1).toString(), ui->effectCombo->itemText(effect)); - m_layoutPreview->show(); + // TODO: here we need to show the preview + new LayoutPreview(ui->effectCombo->itemData(effect, Qt::UserRole+1).toString(), this); } else { QPointer configDialog = new QDialog(this); configDialog->setLayout(new QVBoxLayout); diff --git a/kcmkwin/kwintabbox/main.h b/kcmkwin/kwintabbox/main.h index 3344d00e0b..f8b5ac257d 100644 --- a/kcmkwin/kwintabbox/main.h +++ b/kcmkwin/kwintabbox/main.h @@ -35,7 +35,6 @@ namespace KWin namespace TabBox { -class LayoutPreview; } @@ -87,7 +86,6 @@ private: KShortcutsEditor* m_editor; TabBox::TabBoxConfig m_tabBoxConfig; TabBox::TabBoxConfig m_tabBoxAlternativeConfig; - TabBox::LayoutPreview *m_layoutPreview; bool effectEnabled(const QString& effect, const KConfigGroup& cfg) const; }; diff --git a/kcmkwin/kwintabbox/qml/main.qml b/kcmkwin/kwintabbox/qml/main.qml deleted file mode 100644 index 911e81a749..0000000000 --- a/kcmkwin/kwintabbox/qml/main.qml +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - -Copyright (C) 2011 Martin Gräßlin - -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 . -*********************************************************************/ -import QtQuick 2.0 - -Item { - id : preview - Loader { - property int screenWidth : preview.width - property int screenHeight : preview.height - property bool allDesktops: true - width: preview.width - height: preview.height - textElement.height - source: sourcePath - anchors.centerIn: parent - onLoaded: { - if (item.allDesktops != undefined) { - item.allDesktops = allDesktops; - } - if (item.setModel) { - item.setModel(clientModel); - } - if (item.screenWidth != undefined) { - item.screenWidth = screenWidth; - } - if (item.screenHeight != undefined) { - item.screenHeight = screenHeight; - } - item.width = preview.width; - item.height = preview.height - textElement.height; - } - } - Text { - id: textElement - font.bold: true - text: name - anchors { - horizontalCenter: parent.horizontalCenter - bottom: parent.bottom - } - visible: true - } -}