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 }