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"