File indexing completed on 2024-11-10 04:56:52

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2009, 2011 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 // own
0010 #include "layoutpreview.h"
0011 
0012 #include <KApplicationTrader>
0013 #include <KConfigGroup>
0014 #include <KDesktopFile>
0015 #include <KLocalizedString>
0016 #include <QApplication>
0017 #include <QDebug>
0018 #include <QQmlContext>
0019 #include <QQmlEngine>
0020 #include <QScreen>
0021 #include <QStandardPaths>
0022 
0023 namespace KWin
0024 {
0025 namespace TabBox
0026 {
0027 
0028 LayoutPreview::LayoutPreview(const QString &path, bool showDesktopThumbnail, QObject *parent)
0029     : QObject(parent)
0030     , m_item(nullptr)
0031 {
0032     QQmlEngine *engine = new QQmlEngine(this);
0033     QQmlComponent *component = new QQmlComponent(engine, this);
0034     qmlRegisterType<WindowThumbnailItem>("org.kde.kwin", 3, 0, "WindowThumbnail");
0035     qmlRegisterType<SwitcherItem>("org.kde.kwin", 3, 0, "TabBoxSwitcher");
0036     qmlRegisterType<DesktopBackground>("org.kde.kwin", 3, 0, "DesktopBackground");
0037     qmlRegisterAnonymousType<QAbstractItemModel>("org.kde.kwin", 3);
0038     component->loadUrl(QUrl::fromLocalFile(path));
0039     if (component->isError()) {
0040         qDebug() << component->errorString();
0041     }
0042     QObject *item = component->create();
0043     auto findSwitcher = [item]() -> SwitcherItem * {
0044         if (!item) {
0045             return nullptr;
0046         }
0047         if (SwitcherItem *i = qobject_cast<SwitcherItem *>(item)) {
0048             return i;
0049         } else if (QQuickWindow *w = qobject_cast<QQuickWindow *>(item)) {
0050             return w->contentItem()->findChild<SwitcherItem *>();
0051         }
0052         return item->findChild<SwitcherItem *>();
0053     };
0054     if (SwitcherItem *switcher = findSwitcher()) {
0055         m_item = switcher;
0056         static_cast<ExampleClientModel *>(switcher->model())->showDesktopThumbnail(showDesktopThumbnail);
0057         switcher->setVisible(true);
0058     }
0059     auto findWindow = [item]() -> QQuickWindow * {
0060         if (!item) {
0061             return nullptr;
0062         }
0063         if (QQuickWindow *w = qobject_cast<QQuickWindow *>(item)) {
0064             return w;
0065         }
0066         return item->findChild<QQuickWindow *>();
0067     };
0068     if (QQuickWindow *w = findWindow()) {
0069         w->setKeyboardGrabEnabled(true);
0070         w->installEventFilter(this);
0071     }
0072 }
0073 
0074 LayoutPreview::~LayoutPreview()
0075 {
0076 }
0077 
0078 bool LayoutPreview::eventFilter(QObject *object, QEvent *event)
0079 {
0080     if (event->type() == QEvent::KeyPress) {
0081         QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
0082         if (keyEvent->key() == Qt::Key_Escape || keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Space) {
0083             object->deleteLater();
0084             deleteLater();
0085         }
0086         if (m_item && keyEvent->key() == Qt::Key_Tab) {
0087             m_item->incrementIndex();
0088         }
0089         if (m_item && keyEvent->key() == Qt::Key_Backtab) {
0090             m_item->decrementIndex();
0091         }
0092     } else if (event->type() == QEvent::FocusOut) {
0093         object->deleteLater();
0094         deleteLater();
0095     }
0096     return QObject::eventFilter(object, event);
0097 }
0098 
0099 ExampleClientModel::ExampleClientModel(QObject *parent)
0100     : QAbstractListModel(parent)
0101 {
0102     init();
0103 }
0104 
0105 ExampleClientModel::~ExampleClientModel()
0106 {
0107 }
0108 
0109 void ExampleClientModel::init()
0110 {
0111     if (const auto s = KApplicationTrader::preferredService(QStringLiteral("inode/directory"))) {
0112         m_thumbnails << ThumbnailInfo{WindowThumbnailItem::Dolphin, s->name(), s->icon()};
0113     }
0114     if (const auto s = KApplicationTrader::preferredService(QStringLiteral("text/html"))) {
0115         m_thumbnails << ThumbnailInfo{WindowThumbnailItem::Konqueror, s->name(), s->icon()};
0116     }
0117     if (const auto s = KApplicationTrader::preferredService(QStringLiteral("message/rfc822"))) {
0118         m_thumbnails << ThumbnailInfo{WindowThumbnailItem::KMail, s->name(), s->icon()};
0119     }
0120     if (const auto s = KService::serviceByDesktopName(QStringLiteral("kdesystemsettings"))) {
0121         m_thumbnails << ThumbnailInfo{WindowThumbnailItem::Systemsettings, s->name(), s->icon()};
0122     }
0123 }
0124 
0125 void ExampleClientModel::showDesktopThumbnail(bool showDesktop)
0126 {
0127     const ThumbnailInfo desktopThumbnail = ThumbnailInfo{WindowThumbnailItem::Desktop, i18n("Show Desktop"), QStringLiteral("desktop")};
0128     const int desktopIndex = m_thumbnails.indexOf(desktopThumbnail);
0129     if (showDesktop == (desktopIndex >= 0)) {
0130         return;
0131     }
0132 
0133     Q_EMIT beginResetModel();
0134     if (showDesktop) {
0135         m_thumbnails << desktopThumbnail;
0136     } else {
0137         m_thumbnails.removeAt(desktopIndex);
0138     }
0139     Q_EMIT endResetModel();
0140 }
0141 
0142 QVariant ExampleClientModel::data(const QModelIndex &index, int role) const
0143 {
0144     if (!index.isValid() || index.row() >= rowCount()) {
0145         return QVariant();
0146     }
0147 
0148     const ThumbnailInfo &item = m_thumbnails.at(index.row());
0149 
0150     switch (role) {
0151     case Qt::DisplayRole:
0152     case CaptionRole:
0153         return item.caption;
0154     case MinimizedRole:
0155         return false;
0156     case DesktopNameRole:
0157         return i18nc("An example Desktop Name", "Desktop 1");
0158     case IconRole:
0159         return item.icon;
0160     case WindowIdRole:
0161         return item.wId;
0162     case CloseableRole:
0163         return item.wId != WindowThumbnailItem::Desktop;
0164     }
0165     return QVariant();
0166 }
0167 
0168 QString ExampleClientModel::longestCaption() const
0169 {
0170     QString caption;
0171     for (const auto &item : m_thumbnails) {
0172         if (item.caption.size() > caption.size()) {
0173             caption = item.caption;
0174         }
0175     }
0176     return caption;
0177 }
0178 
0179 int ExampleClientModel::rowCount(const QModelIndex &parent) const
0180 {
0181     return m_thumbnails.size();
0182 }
0183 
0184 QHash<int, QByteArray> ExampleClientModel::roleNames() const
0185 {
0186     return {
0187         {CaptionRole, QByteArrayLiteral("caption")},
0188         {MinimizedRole, QByteArrayLiteral("minimized")},
0189         {DesktopNameRole, QByteArrayLiteral("desktopName")},
0190         {IconRole, QByteArrayLiteral("icon")},
0191         {WindowIdRole, QByteArrayLiteral("windowId")},
0192         {CloseableRole, QByteArrayLiteral("closeable")},
0193     };
0194 }
0195 
0196 SwitcherItem::SwitcherItem(QObject *parent)
0197     : QObject(parent)
0198     , m_model(new ExampleClientModel(this))
0199     , m_item(nullptr)
0200     , m_currentIndex(0)
0201     , m_visible(false)
0202 {
0203 }
0204 
0205 SwitcherItem::~SwitcherItem()
0206 {
0207 }
0208 
0209 void SwitcherItem::setVisible(bool visible)
0210 {
0211     if (m_visible == visible) {
0212         return;
0213     }
0214     m_visible = visible;
0215     Q_EMIT visibleChanged();
0216 }
0217 
0218 void SwitcherItem::setItem(QObject *item)
0219 {
0220     m_item = item;
0221     Q_EMIT itemChanged();
0222 }
0223 
0224 void SwitcherItem::setCurrentIndex(int index)
0225 {
0226     if (m_currentIndex == index) {
0227         return;
0228     }
0229     m_currentIndex = index;
0230     Q_EMIT currentIndexChanged(m_currentIndex);
0231 }
0232 
0233 QRect SwitcherItem::screenGeometry() const
0234 {
0235     const QScreen *primaryScreen = qApp->primaryScreen();
0236     return primaryScreen->geometry();
0237 }
0238 
0239 void SwitcherItem::incrementIndex()
0240 {
0241     setCurrentIndex((m_currentIndex + 1) % m_model->rowCount());
0242 }
0243 
0244 void SwitcherItem::decrementIndex()
0245 {
0246     int index = m_currentIndex - 1;
0247     if (index < 0) {
0248         index = m_model->rowCount() - 1;
0249     }
0250     setCurrentIndex(index);
0251 }
0252 
0253 DesktopBackground::DesktopBackground(QQuickItem *parent)
0254     : WindowThumbnailItem(parent)
0255 {
0256     setWId(WindowThumbnailItem::Desktop);
0257 
0258     connect(this, &QQuickItem::windowChanged, this, &DesktopBackground::stretchToScreen);
0259     stretchToScreen();
0260 };
0261 
0262 void DesktopBackground::stretchToScreen()
0263 {
0264     const QQuickWindow *w = window();
0265     if (!w) {
0266         return;
0267     }
0268     const QScreen *screen = w->screen();
0269     if (!screen) {
0270         return;
0271     }
0272     setImplicitSize(screen->size().width(), screen->size().height());
0273 };
0274 
0275 } // namespace KWin
0276 } // namespace TabBox
0277 
0278 #include "moc_layoutpreview.cpp"