File indexing completed on 2024-04-28 05:36:51
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 <QGuiApplication> 0010 #include <QIcon> 0011 0012 OutputsModel::OutputsModel(Options o, QObject *parent) 0013 : QAbstractListModel(parent) 0014 { 0015 const auto screens = qGuiApp->screens(); 0016 0017 // Only show the full workspace if there's several outputs 0018 if (screens.count() > 1 && (o & WorkspaceIncluded)) { 0019 m_outputs << Output{Output::Workspace, nullptr, i18n("Full Workspace"), "Workspace", {}}; 0020 } 0021 0022 if (o & VirtualIncluded) { 0023 static quint64 i = 0; 0024 m_outputs << Output{Output::Virtual, nullptr, i18n("New Virtual Output"), QStringLiteral("Virtual%1").arg(i++), {}}; 0025 } 0026 0027 if (o & RegionIncluded) { 0028 m_outputs << Output{Output::Region, nullptr, i18n("Rectangular Region"), "Region", {}}; 0029 } 0030 0031 for (const auto screen : screens) { 0032 auto model = screen->model(); 0033 Output::OutputType type = Output::Unknown; 0034 0035 static const auto embedded = { 0036 QLatin1String("LVDS"), 0037 QLatin1String("IDP"), 0038 QLatin1String("EDP"), 0039 QLatin1String("LCD"), 0040 }; 0041 0042 for (const auto &prefix : embedded) { 0043 if (model.startsWith(prefix, Qt::CaseInsensitive)) { 0044 type = Output::OutputType::Laptop; 0045 model = i18n("Laptop screen"); 0046 break; 0047 } 0048 } 0049 0050 if (type == Output::OutputType::Unknown) { 0051 if (model.contains(QLatin1String("TV"))) { 0052 type = Output::OutputType::Television; 0053 } else { 0054 type = Output::OutputType::Monitor; 0055 } 0056 } 0057 0058 const QPoint pos = screen->geometry().topLeft(); 0059 m_outputs << Output(type, screen, model, QStringLiteral("%1x%2").arg(pos.x()).arg(pos.y()), screen->name()); 0060 } 0061 } 0062 0063 OutputsModel::~OutputsModel() = default; 0064 0065 int OutputsModel::rowCount(const QModelIndex &parent) const 0066 { 0067 return parent.isValid() ? 0 : m_outputs.count(); 0068 } 0069 0070 QHash<int, QByteArray> OutputsModel::roleNames() const 0071 { 0072 return QHash<int, QByteArray>{ 0073 {Qt::DisplayRole, "display"}, 0074 {Qt::DecorationRole, "decoration"}, 0075 {Qt::CheckStateRole, "checked"}, 0076 {ScreenRole, "screen"}, 0077 {NameRole, "name"}, 0078 }; 0079 } 0080 0081 QVariant OutputsModel::data(const QModelIndex &index, int role) const 0082 { 0083 if (!checkIndex(index, CheckIndexOption::IndexIsValid)) { 0084 return {}; 0085 } 0086 0087 const auto &output = m_outputs[index.row()]; 0088 switch (role) { 0089 case ScreenRole: 0090 return QVariant::fromValue(output.screen()); 0091 return 0; 0092 case NameRole: 0093 return output.name(); 0094 case Qt::DecorationRole: 0095 return QIcon::fromTheme(output.iconName()); 0096 case Qt::DisplayRole: 0097 return output.display(); 0098 case Qt::CheckStateRole: 0099 return m_selectedRows.contains(index.row()) ? Qt::Checked : Qt::Unchecked; 0100 } 0101 return {}; 0102 } 0103 0104 bool OutputsModel::setData(const QModelIndex &index, const QVariant &value, int role) 0105 { 0106 if (!checkIndex(index, CheckIndexOption::IndexIsValid) || role != Qt::CheckStateRole) { 0107 return false; 0108 } 0109 0110 if (index.data(Qt::CheckStateRole) == value) { 0111 return true; 0112 } 0113 0114 if (value == Qt::Checked) { 0115 m_selectedRows.insert(index.row()); 0116 } else { 0117 m_selectedRows.remove(index.row()); 0118 } 0119 Q_EMIT dataChanged(index, index, {role}); 0120 if (m_selectedRows.count() <= 1) { 0121 Q_EMIT hasSelectionChanged(); 0122 } 0123 return true; 0124 } 0125 0126 const Output &OutputsModel::outputAt(int row) const 0127 { 0128 return m_outputs[row]; 0129 } 0130 0131 void OutputsModel::clearSelection() 0132 { 0133 if (m_selectedRows.isEmpty()) 0134 return; 0135 0136 auto selected = m_selectedRows; 0137 m_selectedRows.clear(); 0138 for (int i = 0, c = rowCount({}); i < c; ++i) { 0139 if (selected.contains(i)) { 0140 const auto idx = index(i, 0); 0141 Q_EMIT dataChanged(idx, idx, {Qt::CheckStateRole}); 0142 } 0143 } 0144 Q_EMIT hasSelectionChanged(); 0145 } 0146 0147 QList<Output> OutputsModel::selectedOutputs() const 0148 { 0149 QList<Output> ret; 0150 ret.reserve(m_selectedRows.count()); 0151 for (auto x : std::as_const(m_selectedRows)) { 0152 ret << m_outputs[x]; 0153 } 0154 return ret; 0155 }