You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
6.5 KiB
269 lines
6.5 KiB
/* |
|
KWin - the KDE window manager |
|
This file is part of the KDE project. |
|
|
|
SPDX-FileCopyrightText: 2009 Martin Gräßlin <mgraesslin@kde.org> |
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later |
|
*/ |
|
|
|
#include "clientmodel.h" |
|
#include "tabboxconfig.h" |
|
#include "window.h" |
|
|
|
#include <KLocalizedString> |
|
|
|
#include <QIcon> |
|
#include <QUuid> |
|
|
|
#include <cmath> |
|
|
|
namespace KWin |
|
{ |
|
namespace TabBox |
|
{ |
|
|
|
ClientModel::ClientModel(QObject *parent) |
|
: QAbstractItemModel(parent) |
|
{ |
|
} |
|
|
|
ClientModel::~ClientModel() |
|
{ |
|
} |
|
|
|
QVariant ClientModel::data(const QModelIndex &index, int role) const |
|
{ |
|
if (!index.isValid()) { |
|
return QVariant(); |
|
} |
|
|
|
if (m_clientList.isEmpty()) { |
|
return QVariant(); |
|
} |
|
|
|
int clientIndex = index.row(); |
|
if (clientIndex >= m_clientList.count()) { |
|
return QVariant(); |
|
} |
|
Window *client = m_clientList[clientIndex]; |
|
if (!client) { |
|
return QVariant(); |
|
} |
|
switch (role) { |
|
case Qt::DisplayRole: |
|
case CaptionRole: { |
|
if (client->isDesktop()) { |
|
return i18nc("Special entry in alt+tab list for minimizing all windows", |
|
"Show Desktop"); |
|
} |
|
return client->caption(); |
|
} |
|
case ClientRole: |
|
return QVariant::fromValue<void *>(client); |
|
case DesktopNameRole: { |
|
return tabBox->desktopName(client); |
|
} |
|
case WIdRole: |
|
return client->internalId(); |
|
case MinimizedRole: |
|
return client->isMinimized(); |
|
case CloseableRole: |
|
return client->isCloseable(); |
|
case IconRole: |
|
if (client->isDesktop()) { |
|
return QIcon::fromTheme(QStringLiteral("user-desktop")); |
|
} |
|
return client->icon(); |
|
default: |
|
return QVariant(); |
|
} |
|
} |
|
|
|
QString ClientModel::longestCaption() const |
|
{ |
|
QString caption; |
|
for (Window *window : std::as_const(m_clientList)) { |
|
if (window->caption().size() > caption.size()) { |
|
caption = window->caption(); |
|
} |
|
} |
|
return caption; |
|
} |
|
|
|
int ClientModel::columnCount(const QModelIndex &parent) const |
|
{ |
|
return 1; |
|
} |
|
|
|
int ClientModel::rowCount(const QModelIndex &parent) const |
|
{ |
|
if (parent.isValid()) { |
|
return 0; |
|
} |
|
return m_clientList.count(); |
|
} |
|
|
|
QModelIndex ClientModel::parent(const QModelIndex &child) const |
|
{ |
|
return QModelIndex(); |
|
} |
|
|
|
QModelIndex ClientModel::index(int row, int column, const QModelIndex &parent) const |
|
{ |
|
if (row < 0 || column != 0 || parent.isValid()) { |
|
return QModelIndex(); |
|
} |
|
int index = row * columnCount(); |
|
if (index >= m_clientList.count() && !m_clientList.isEmpty()) { |
|
return QModelIndex(); |
|
} |
|
return createIndex(row, 0); |
|
} |
|
|
|
QHash<int, QByteArray> ClientModel::roleNames() const |
|
{ |
|
return { |
|
{CaptionRole, QByteArrayLiteral("caption")}, |
|
{DesktopNameRole, QByteArrayLiteral("desktopName")}, |
|
{MinimizedRole, QByteArrayLiteral("minimized")}, |
|
{WIdRole, QByteArrayLiteral("windowId")}, |
|
{CloseableRole, QByteArrayLiteral("closeable")}, |
|
{IconRole, QByteArrayLiteral("icon")}, |
|
}; |
|
} |
|
|
|
QModelIndex ClientModel::index(Window *client) const |
|
{ |
|
const int index = m_clientList.indexOf(client); |
|
if (index == -1) { |
|
return QModelIndex(); |
|
} |
|
int row = index / columnCount(); |
|
int column = index % columnCount(); |
|
return createIndex(row, column); |
|
} |
|
|
|
void ClientModel::createFocusChainClientList(Window *start) |
|
{ |
|
auto c = start; |
|
if (!tabBox->isInFocusChain(c)) { |
|
Window *firstClient = tabBox->firstClientFocusChain(); |
|
if (firstClient) { |
|
c = firstClient; |
|
} |
|
} |
|
auto stop = c; |
|
do { |
|
Window *add = tabBox->clientToAddToList(c); |
|
if (add) { |
|
m_mutableClientList += add; |
|
} |
|
c = tabBox->nextClientFocusChain(c); |
|
} while (c && c != stop); |
|
} |
|
|
|
void ClientModel::createStackingOrderClientList(Window *start) |
|
{ |
|
// TODO: needs improvement |
|
const QList<Window *> stacking = tabBox->stackingOrder(); |
|
auto c = stacking.first(); |
|
auto stop = c; |
|
int index = 0; |
|
while (c) { |
|
Window *add = tabBox->clientToAddToList(c); |
|
if (add) { |
|
if (start == add) { |
|
m_mutableClientList.removeAll(add); |
|
m_mutableClientList.prepend(add); |
|
} else { |
|
m_mutableClientList += add; |
|
} |
|
} |
|
if (index >= stacking.size() - 1) { |
|
c = nullptr; |
|
} else { |
|
c = stacking[++index]; |
|
} |
|
|
|
if (c == stop) { |
|
break; |
|
} |
|
} |
|
} |
|
|
|
void ClientModel::createClientList(bool partialReset) |
|
{ |
|
auto start = tabBox->activeClient(); |
|
// TODO: new clients are not added at correct position |
|
if (partialReset && !m_mutableClientList.isEmpty()) { |
|
Window *firstClient = m_mutableClientList.constFirst(); |
|
if (!firstClient->isDeleted()) { |
|
start = firstClient; |
|
} |
|
} |
|
|
|
m_mutableClientList.clear(); |
|
|
|
switch (tabBox->config().clientSwitchingMode()) { |
|
case TabBoxConfig::FocusChainSwitching: { |
|
createFocusChainClientList(start); |
|
break; |
|
} |
|
case TabBoxConfig::StackingOrderSwitching: { |
|
createStackingOrderClientList(start); |
|
break; |
|
} |
|
} |
|
|
|
if (tabBox->config().orderMinimizedMode() == TabBoxConfig::GroupByMinimized) { |
|
// Put all non-minimized included clients first. |
|
std::stable_partition(m_mutableClientList.begin(), m_mutableClientList.end(), [](const auto &client) { |
|
return !client->isMinimized(); |
|
}); |
|
} |
|
|
|
if (!m_mutableClientList.isEmpty() |
|
&& tabBox->config().clientApplicationsMode() != TabBoxConfig::AllWindowsCurrentApplication |
|
&& tabBox->config().showDesktopMode() == TabBoxConfig::ShowDesktopClient) { |
|
Window *desktopClient = tabBox->desktopClient(); |
|
if (desktopClient) { |
|
m_mutableClientList.append(desktopClient); |
|
} |
|
} |
|
|
|
if (m_clientList == m_mutableClientList) { |
|
return; |
|
} |
|
|
|
beginResetModel(); |
|
m_clientList = m_mutableClientList; |
|
endResetModel(); |
|
} |
|
|
|
void ClientModel::close(int i) |
|
{ |
|
QModelIndex ind = index(i, 0); |
|
if (!ind.isValid()) { |
|
return; |
|
} |
|
Window *client = m_mutableClientList.at(i); |
|
if (client) { |
|
client->closeWindow(); |
|
} |
|
} |
|
|
|
void ClientModel::activate(int i) |
|
{ |
|
QModelIndex ind = index(i, 0); |
|
if (!ind.isValid()) { |
|
return; |
|
} |
|
tabBox->setCurrentIndex(ind); |
|
tabBox->activateAndClose(); |
|
} |
|
|
|
} // namespace Tabbox |
|
} // namespace KWin |
|
|
|
#include "moc_clientmodel.cpp"
|
|
|