File indexing completed on 2024-04-28 16:55:45
0001 /* 0002 * SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "outputsmodel.h" 0008 #include <KLocalizedString> 0009 #include <QIcon> 0010 0011 OutputsModel::OutputsModel(Options o, QObject *parent) 0012 : QAbstractListModel(parent) 0013 { 0014 const auto outputs = WaylandIntegration::screens().values(); 0015 0016 // Only show the full workspace if there's several outputs 0017 if (outputs.count() > 1 && (o & WorkspaceIncluded)) { 0018 m_outputs << Output{WaylandIntegration::WaylandOutput::Workspace, 0, i18n("Full Workspace"), "Workspace", {}}; 0019 } 0020 if (o & VirtualIncluded) { 0021 static quint64 i = 0; 0022 m_outputs << Output{WaylandIntegration::WaylandOutput::Virtual, 0, i18n("New Virtual Output"), QStringLiteral("Virtual%1").arg(i++), {}}; 0023 } 0024 for (auto output : outputs) { 0025 QString display; 0026 switch (output.outputType()) { 0027 case WaylandIntegration::WaylandOutput::Laptop: 0028 display = i18n("Laptop screen"); 0029 break; 0030 default: 0031 display = output.model(); 0032 break; 0033 } 0034 const QPoint pos = output.globalPosition(); 0035 m_outputs 0036 << Output(output.outputType(), output.waylandOutputName(), display, QStringLiteral("%1x%2").arg(pos.x()).arg(pos.y()), output.output()->name()); 0037 } 0038 } 0039 0040 OutputsModel::~OutputsModel() = default; 0041 0042 int OutputsModel::rowCount(const QModelIndex &parent) const 0043 { 0044 return parent.isValid() ? 0 : m_outputs.count(); 0045 } 0046 0047 QHash<int, QByteArray> OutputsModel::roleNames() const 0048 { 0049 return QHash<int, QByteArray>{ 0050 {Qt::DisplayRole, "display"}, 0051 {Qt::DecorationRole, "decoration"}, 0052 {Qt::CheckStateRole, "checked"}, 0053 {OutputNameRole, "outputName"}, 0054 {NameRole, "name"}, 0055 }; 0056 } 0057 0058 QVariant OutputsModel::data(const QModelIndex &index, int role) const 0059 { 0060 if (!checkIndex(index, CheckIndexOption::IndexIsValid)) { 0061 return {}; 0062 } 0063 0064 const auto &output = m_outputs[index.row()]; 0065 switch (role) { 0066 case OutputNameRole: 0067 return output.waylandOutputName(); 0068 case NameRole: 0069 return output.name(); 0070 case Qt::DecorationRole: 0071 return QIcon::fromTheme(output.iconName()); 0072 case Qt::DisplayRole: 0073 return output.display(); 0074 case Qt::CheckStateRole: 0075 return m_selectedRows.contains(index.row()) ? Qt::Checked : Qt::Unchecked; 0076 } 0077 return {}; 0078 } 0079 0080 bool OutputsModel::setData(const QModelIndex &index, const QVariant &value, int role) 0081 { 0082 if (!checkIndex(index, CheckIndexOption::IndexIsValid) || role != Qt::CheckStateRole) { 0083 return false; 0084 } 0085 0086 if (index.data(Qt::CheckStateRole) == value) { 0087 return true; 0088 } 0089 0090 if (value == Qt::Checked) { 0091 m_selectedRows.insert(index.row()); 0092 } else { 0093 m_selectedRows.remove(index.row()); 0094 } 0095 Q_EMIT dataChanged(index, index, {role}); 0096 if (m_selectedRows.count() <= 1) { 0097 Q_EMIT hasSelectionChanged(); 0098 } 0099 return true; 0100 } 0101 0102 const Output &OutputsModel::outputAt(int row) const 0103 { 0104 return m_outputs[row]; 0105 } 0106 0107 void OutputsModel::clearSelection() 0108 { 0109 if (m_selectedRows.isEmpty()) 0110 return; 0111 0112 auto selected = m_selectedRows; 0113 m_selectedRows.clear(); 0114 for (int i = 0, c = rowCount({}); i < c; ++i) { 0115 if (selected.contains(i)) { 0116 const auto idx = index(i, 0); 0117 Q_EMIT dataChanged(idx, idx, {Qt::CheckStateRole}); 0118 } 0119 } 0120 Q_EMIT hasSelectionChanged(); 0121 } 0122 0123 QList<Output> OutputsModel::selectedOutputs() const 0124 { 0125 QList<Output> ret; 0126 ret.reserve(m_selectedRows.count()); 0127 for (auto x : qAsConst(m_selectedRows)) { 0128 ret << m_outputs[x]; 0129 } 0130 return ret; 0131 }