File indexing completed on 2024-05-12 05:37:16
0001 /* 0002 SPDX-FileCopyrightText: 2009 Chani Armitage <chani@kde.org> 0003 SPDX-FileCopyrightText: 2018 Eike Hein <hein@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "switch.h" 0009 0010 #include "abstracttasksmodel.h" 0011 #include "activityinfo.h" 0012 #include "tasksmodel.h" 0013 #include "virtualdesktopinfo.h" 0014 0015 #include <KConfigGroup> 0016 #include <KPluginFactory> 0017 0018 #include <QAction> 0019 #include <QMenu> 0020 #include <QVariantMap> 0021 0022 using namespace TaskManager; 0023 0024 ActivityInfo *SwitchWindow::s_activityInfo = nullptr; 0025 TasksModel *SwitchWindow::s_tasksModel = nullptr; 0026 int SwitchWindow::s_instanceCount = 0; 0027 0028 SwitchWindow::SwitchWindow(QObject *parent, const QVariantList &args) 0029 : Plasma::ContainmentActions(parent, args) 0030 , m_mode(AllFlat) 0031 , m_virtualDesktopInfo(new VirtualDesktopInfo(this)) 0032 { 0033 ++s_instanceCount; 0034 0035 if (!s_activityInfo) { 0036 s_activityInfo = new ActivityInfo(); 0037 } 0038 0039 if (!s_tasksModel) { 0040 s_tasksModel = new TasksModel(); 0041 0042 s_tasksModel->setGroupMode(TasksModel::GroupDisabled); 0043 0044 s_tasksModel->setActivity(s_activityInfo->currentActivity()); 0045 s_tasksModel->setFilterByActivity(true); 0046 connect(s_activityInfo, &ActivityInfo::currentActivityChanged, this, []() { 0047 s_tasksModel->setActivity(s_activityInfo->currentActivity()); 0048 }); 0049 } 0050 } 0051 0052 SwitchWindow::~SwitchWindow() 0053 { 0054 --s_instanceCount; 0055 0056 if (!s_instanceCount) { 0057 delete s_activityInfo; 0058 s_activityInfo = nullptr; 0059 delete s_tasksModel; 0060 s_tasksModel = nullptr; 0061 } 0062 0063 qDeleteAll(m_actions); 0064 } 0065 0066 void SwitchWindow::restore(const KConfigGroup &config) 0067 { 0068 m_mode = (MenuMode)config.readEntry("mode", (int)AllFlat); 0069 } 0070 0071 QWidget *SwitchWindow::createConfigurationInterface(QWidget *parent) 0072 { 0073 QWidget *widget = new QWidget(parent); 0074 m_ui.setupUi(widget); 0075 widget->setWindowTitle(i18nc("plasma_containmentactions_switchwindow", "Configure Switch Window Plugin")); 0076 switch (m_mode) { 0077 case AllFlat: 0078 m_ui.flatButton->setChecked(true); 0079 break; 0080 case DesktopSubmenus: 0081 m_ui.subButton->setChecked(true); 0082 break; 0083 case CurrentDesktop: 0084 m_ui.curButton->setChecked(true); 0085 break; 0086 } 0087 return widget; 0088 } 0089 0090 void SwitchWindow::configurationAccepted() 0091 { 0092 if (m_ui.flatButton->isChecked()) { 0093 m_mode = AllFlat; 0094 } else if (m_ui.subButton->isChecked()) { 0095 m_mode = DesktopSubmenus; 0096 } else { 0097 m_mode = CurrentDesktop; 0098 } 0099 } 0100 0101 void SwitchWindow::save(KConfigGroup &config) 0102 { 0103 config.writeEntry("mode", (int)m_mode); 0104 } 0105 0106 void SwitchWindow::makeMenu() 0107 { 0108 qDeleteAll(m_actions); 0109 m_actions.clear(); 0110 0111 if (s_tasksModel->rowCount() == 0) { 0112 return; 0113 } 0114 0115 QMultiMap<QString, QAction *> desktops; 0116 QList<QAction *> allDesktops; 0117 0118 // Make all the window actions. 0119 for (int i = 0; i < s_tasksModel->rowCount(); ++i) { 0120 const QModelIndex &idx = s_tasksModel->index(i, 0); 0121 0122 if (!idx.data(AbstractTasksModel::IsWindow).toBool()) { 0123 continue; 0124 } 0125 0126 const QString &name = idx.data().toString(); 0127 0128 if (name.isEmpty()) { 0129 continue; 0130 } 0131 0132 QAction *action = new QAction(name, this); 0133 action->setIcon(idx.data(Qt::DecorationRole).value<QIcon>()); 0134 action->setData(idx.data(AbstractTasksModel::WinIdList).toList()); 0135 0136 const QStringList &desktopList = idx.data(AbstractTasksModel::VirtualDesktops).toStringList(); 0137 0138 for (const QString &desktop : desktopList) { 0139 desktops.insert(desktop, action); 0140 } 0141 0142 if (idx.data(AbstractTasksModel::IsOnAllVirtualDesktops).toBool()) { 0143 allDesktops << action; 0144 } 0145 0146 connect(action, &QAction::triggered, [=, this]() { 0147 switchTo(action); 0148 }); 0149 } 0150 0151 // Sort into menu(s). 0152 if (m_mode == CurrentDesktop) { 0153 const QString ¤tDesktop = m_virtualDesktopInfo->currentDesktop().toString(); 0154 0155 QAction *a = new QAction(i18nc("plasma_containmentactions_switchwindow", "Windows"), this); 0156 a->setSeparator(true); 0157 m_actions << a; 0158 m_actions << desktops.values(currentDesktop); 0159 m_actions << allDesktops; 0160 0161 } else { 0162 const QVariantList &desktopIds = m_virtualDesktopInfo->desktopIds(); 0163 const QStringList &desktopNames = m_virtualDesktopInfo->desktopNames(); 0164 0165 if (m_mode == AllFlat) { 0166 for (int i = 0; i < desktopIds.count(); ++i) { 0167 const QString &desktop = desktopIds.at(i).toString(); 0168 0169 if (desktops.contains(desktop)) { 0170 const QString &name = QStringLiteral("%1: %2").arg(QString::number(i + 1), desktopNames.at(i)); 0171 QAction *a = new QAction(name, this); 0172 a->setSeparator(true); 0173 m_actions << a; 0174 m_actions << desktops.values(desktop); 0175 } 0176 } 0177 0178 if (allDesktops.count()) { 0179 QAction *a = new QAction(i18nc("plasma_containmentactions_switchwindow", "All Desktops"), this); 0180 a->setSeparator(true); 0181 m_actions << a; 0182 m_actions << allDesktops; 0183 } 0184 } else { // Submenus. 0185 for (int i = 0; i < desktopIds.count(); ++i) { 0186 const QString &desktop = desktopIds.at(i).toString(); 0187 0188 if (desktops.contains(desktop)) { 0189 const QString &name = QStringLiteral("%1: %2").arg(QString::number(i + 1), desktopNames.at(i)); 0190 QMenu *subMenu = new QMenu(name); 0191 subMenu->addActions(desktops.values(desktop)); 0192 0193 QAction *a = new QAction(name, this); 0194 a->setMenu(subMenu); 0195 m_actions << a; 0196 } 0197 } 0198 0199 if (allDesktops.count()) { 0200 QMenu *subMenu = new QMenu(i18nc("plasma_containmentactions_switchwindow", "All Desktops")); 0201 subMenu->addActions(allDesktops); 0202 QAction *a = new QAction(i18nc("plasma_containmentactions_switchwindow", "All Desktops"), this); 0203 a->setMenu(subMenu); 0204 m_actions << a; 0205 } 0206 } 0207 } 0208 } 0209 0210 QList<QAction *> SwitchWindow::contextualActions() 0211 { 0212 makeMenu(); 0213 return m_actions; 0214 } 0215 0216 void SwitchWindow::switchTo(QAction *action) 0217 { 0218 const QVariantList &idList = action->data().toList(); 0219 0220 for (int i = 0; i < s_tasksModel->rowCount(); ++i) { 0221 const QModelIndex &idx = s_tasksModel->index(i, 0); 0222 0223 if (idList == idx.data(AbstractTasksModel::WinIdList).toList()) { 0224 s_tasksModel->requestActivate(idx); 0225 0226 return; 0227 } 0228 } 0229 } 0230 0231 void SwitchWindow::performNextAction() 0232 { 0233 doSwitch(true); 0234 } 0235 0236 void SwitchWindow::performPreviousAction() 0237 { 0238 doSwitch(false); 0239 } 0240 0241 void SwitchWindow::doSwitch(bool up) 0242 { 0243 const QModelIndex &activeTask = s_tasksModel->activeTask(); 0244 0245 if (!activeTask.isValid()) { 0246 return; 0247 } 0248 0249 if (up) { 0250 const QModelIndex &next = activeTask.sibling(activeTask.row() + 1, 0); 0251 0252 if (next.isValid()) { 0253 s_tasksModel->requestActivate(next); 0254 } else if (s_tasksModel->rowCount() > 1) { 0255 s_tasksModel->requestActivate(s_tasksModel->index(0, 0)); 0256 } 0257 } else { 0258 const QModelIndex &previous = activeTask.sibling(activeTask.row() - 1, 0); 0259 0260 if (previous.isValid()) { 0261 s_tasksModel->requestActivate(previous); 0262 } else if (s_tasksModel->rowCount() > 1) { 0263 s_tasksModel->requestActivate(s_tasksModel->index(s_tasksModel->rowCount() - 1, 0)); 0264 } 0265 } 0266 } 0267 0268 K_PLUGIN_CLASS_WITH_JSON(SwitchWindow, "plasma-containmentactions-switchwindow.json") 0269 0270 #include "switch.moc"