Changeset View
Changeset View
Standalone View
Standalone View
common/control.cpp
Show All 25 Lines | |||||
26 | 26 | | |||
27 | QString Control::s_dirName = QStringLiteral("control/"); | 27 | QString Control::s_dirName = QStringLiteral("control/"); | ||
28 | 28 | | |||
29 | QString Control::dirPath() | 29 | QString Control::dirPath() | ||
30 | { | 30 | { | ||
31 | return Globals::dirPath() % s_dirName; | 31 | return Globals::dirPath() % s_dirName; | ||
32 | } | 32 | } | ||
33 | 33 | | |||
34 | Control::OutputRetention Control::getOutputRetention(const QString &outputId, const QMap<QString, Control::OutputRetention> &retentions) | 34 | Control::OutputRetention Control::convertVariantToOutputRetention(QVariant variant) | ||
35 | { | 35 | { | ||
36 | if (retentions.contains(outputId)) { | 36 | if (variant.canConvert<int>()) { | ||
37 | return retentions[outputId]; | 37 | const auto retention = variant.toInt(); | ||
38 | if (retention == (int)OutputRetention::Global) { | ||||
39 | return OutputRetention::Global; | ||||
40 | } | ||||
41 | if (retention == (int)OutputRetention::Individual) { | ||||
42 | return OutputRetention::Individual; | ||||
43 | } | ||||
38 | } | 44 | } | ||
39 | // info for output not found | | |||
40 | return OutputRetention::Undefined; | 45 | return OutputRetention::Undefined; | ||
41 | } | 46 | } | ||
42 | 47 | | |||
43 | ControlConfig::ControlConfig(KScreen::ConfigPtr config) | 48 | ControlConfig::ControlConfig(KScreen::ConfigPtr config) | ||
44 | : m_config(config) | 49 | : m_config(config) | ||
45 | { | 50 | { | ||
51 | // qDebug() << "Looking for control file:" << config->connectedOutputsHash(); | ||||
52 | QFile file(filePath(config->connectedOutputsHash())); | ||||
53 | if (file.open(QIODevice::ReadOnly)) { | ||||
54 | QJsonDocument parser; | ||||
55 | m_info = parser.fromJson(file.readAll()).toVariant().toList(); | ||||
56 | } | ||||
57 | | ||||
58 | // TODO: use a file watcher in case of changes to the control file while | ||||
59 | // object exists? | ||||
60 | | ||||
61 | // As global outputs are indexed by a hash of their edid, which is not unique, | ||||
62 | // to be able to tell apart multiple identical outputs, these need special treatment | ||||
63 | { | ||||
64 | QStringList allIds; | ||||
65 | const auto outputs = config->outputs(); | ||||
66 | allIds.reserve(outputs.count()); | ||||
67 | for (const KScreen::OutputPtr &output : outputs) { | ||||
68 | const auto outputId = output->hash(); | ||||
69 | if (allIds.contains(outputId) && !m_duplicateOutputIds.contains(outputId)) { | ||||
70 | m_duplicateOutputIds << outputId; | ||||
71 | } | ||||
72 | allIds << outputId; | ||||
73 | } | ||||
74 | } | ||||
75 | | ||||
76 | // TODO: this is same in Output::readInOutputs of the daemon. Combine? | ||||
77 | | ||||
78 | // TODO: connect to outputs added/removed signals and reevaluate duplicate ids | ||||
79 | // in case of such a change while object exists? | ||||
46 | } | 80 | } | ||
47 | 81 | | |||
48 | QString ControlConfig::filePath(const QString &hash) | 82 | QString ControlConfig::filePath(const QString &hash) | ||
49 | { | 83 | { | ||
50 | const QString dir = dirPath() % QStringLiteral("configs/"); | 84 | const QString dir = dirPath() % QStringLiteral("configs/"); | ||
51 | if (!QDir().mkpath(dir)) { | 85 | if (!QDir().mkpath(dir)) { | ||
52 | return QString(); | 86 | return QString(); | ||
53 | } | 87 | } | ||
54 | return dir % hash; | 88 | return dir % hash; | ||
55 | } | 89 | } | ||
56 | 90 | | |||
57 | QString ControlConfig::filePath() | 91 | QString ControlConfig::filePath() | ||
58 | { | 92 | { | ||
59 | if (!m_config) { | 93 | if (!m_config) { | ||
60 | return QString(); | 94 | return QString(); | ||
61 | } | 95 | } | ||
62 | return ControlConfig::filePath(m_config->connectedOutputsHash()); | 96 | return ControlConfig::filePath(m_config->connectedOutputsHash()); | ||
63 | } | 97 | } | ||
64 | 98 | | |||
65 | Control::OutputRetention Control::convertVariantToOutputRetention(QVariant variant) | 99 | Control::OutputRetention ControlConfig::getOutputRetention(const KScreen::OutputPtr &output) const | ||
66 | { | 100 | { | ||
67 | if (variant.canConvert<int>()) { | 101 | return getOutputRetention(output->hash(), output->name()); | ||
68 | const auto retention = variant.toInt(); | | |||
69 | if (retention == (int)OutputRetention::Global) { | | |||
70 | return OutputRetention::Global; | | |||
71 | } | | |||
72 | if (retention == (int)OutputRetention::Individual) { | | |||
73 | return OutputRetention::Individual; | | |||
74 | } | | |||
75 | } | | |||
76 | return OutputRetention::Undefined; | | |||
77 | } | 102 | } | ||
78 | 103 | | |||
79 | QMap<QString, Control::OutputRetention> ControlConfig::readInOutputRetentionValues() | 104 | Control::OutputRetention ControlConfig::getOutputRetention(const QString &outputId, const QString &outputName) const | ||
80 | { | 105 | { | ||
81 | // qDebug() << "Looking for control file:" << m_config->connectedOutputsHash(); | 106 | for (const auto variantInfo : m_info) { | ||
82 | QFile file(filePath(m_config->connectedOutputsHash())); | | |||
83 | if (!file.open(QIODevice::ReadOnly)) { | | |||
84 | // TODO: have a logging category | | |||
85 | // qCDebug(KSCREEN_COMMON) << "Failed to open file" << file.fileName(); | | |||
86 | return QMap<QString, Control::OutputRetention>(); | | |||
87 | } | | |||
88 | | ||||
89 | QJsonDocument parser; | | |||
90 | const QVariantList outputsInfo = parser.fromJson(file.readAll()).toVariant().toList(); | | |||
91 | QMap<QString, Control::OutputRetention> retentions; | | |||
92 | | ||||
93 | for (const auto variantInfo : outputsInfo) { | | |||
94 | const QVariantMap info = variantInfo.toMap(); | 107 | const QVariantMap info = variantInfo.toMap(); | ||
95 | 108 | | |||
96 | // TODO: this does not yet consider the output name (i.e. connector). Necessary? | 109 | const QString outputIdInfo = info[QStringLiteral("id")].toString(); | ||
97 | const QString outputHash = info[QStringLiteral("id")].toString(); | 110 | if (outputIdInfo.isEmpty()) { | ||
98 | if (outputHash.isEmpty()) { | | |||
99 | continue; | 111 | continue; | ||
100 | } | 112 | } | ||
101 | retentions[outputHash] = convertVariantToOutputRetention(info[QStringLiteral("retention")]); | 113 | if (outputId != outputIdInfo) { | ||
114 | continue; | ||||
102 | } | 115 | } | ||
103 | 116 | | |||
104 | return retentions; | 117 | if (!outputName.isEmpty() && m_duplicateOutputIds.contains(outputId)) { | ||
118 | // We may have identical outputs connected, these will have the same id in the config | ||||
119 | // in order to find the right one, also check the output's name (usually the connector) | ||||
120 | const auto metadata = info[QStringLiteral("metadata")].toMap(); | ||||
121 | const auto outputNameInfo = metadata[QStringLiteral("name")].toString(); | ||||
122 | if (outputName != outputNameInfo) { | ||||
123 | // was a duplicate id, but info not for this output | ||||
124 | continue; | ||||
125 | } | ||||
126 | } | ||||
127 | return convertVariantToOutputRetention(info[QStringLiteral("retention")]); | ||||
128 | } | ||||
129 | // info for output not found | ||||
130 | return OutputRetention::Undefined; | ||||
105 | } | 131 | } | ||
106 | 132 | | |||
107 | ControlOutput::ControlOutput(KScreen::OutputPtr output) | 133 | ControlOutput::ControlOutput(KScreen::OutputPtr output) | ||
108 | : m_output(output) | 134 | : m_output(output) | ||
109 | { | 135 | { | ||
110 | } | 136 | } | ||
111 | 137 | | |||
112 | QString ControlOutput::filePath(const QString &hash) | 138 | QString ControlOutput::filePath(const QString &hash) | ||
Show All 15 Lines |