diff --git a/common/control.cpp b/common/control.cpp index 26ee559..9340161 100644 --- a/common/control.cpp +++ b/common/control.cpp @@ -1,99 +1,128 @@ /******************************************************************** Copyright 2019 Roman Gilg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "control.h" #include "globals.h" #include #include #include +#include +#include + QString Control::s_dirName = QStringLiteral("control/"); QString Control::dirPath() { return Globals::dirPath() % s_dirName; } -QString Control::outputFilePath(const QString &hash) +Control::OutputRetention Control::getOutputRetention(const QString &outputId, const QMap &retentions) { - const QString dir = dirPath() % QStringLiteral("outputs/"); - if (!QDir().mkpath(dir)) { - return QString(); + if (retentions.contains(outputId)) { + return retentions[outputId]; } - return dir % hash; + // info for output not found + return OutputRetention::Undefined; } -QString Control::configFilePath(const QString &hash) +ControlConfig::ControlConfig(KScreen::ConfigPtr config) + : m_config(config) +{ +} + +QString ControlConfig::filePath(const QString &hash) { const QString dir = dirPath() % QStringLiteral("configs/"); if (!QDir().mkpath(dir)) { return QString(); } return dir % hash; } +QString ControlConfig::filePath() +{ + if (!m_config) { + return QString(); + } + return ControlConfig::filePath(m_config->connectedOutputsHash()); +} + Control::OutputRetention Control::convertVariantToOutputRetention(QVariant variant) { if (variant.canConvert()) { const auto retention = variant.toInt(); if (retention == (int)OutputRetention::Global) { return OutputRetention::Global; } if (retention == (int)OutputRetention::Individual) { return OutputRetention::Individual; } } return OutputRetention::Undefined; } -QMap Control::readInOutputRetentionValues(const QString &configId) +QMap ControlConfig::readInOutputRetentionValues() { -// qDebug() << "Looking for control file:" << configId; - QFile file(configFilePath(configId)); +// qDebug() << "Looking for control file:" << m_config->connectedOutputsHash(); + QFile file(filePath(m_config->connectedOutputsHash())); if (!file.open(QIODevice::ReadOnly)) { // TODO: have a logging category // qCDebug(KSCREEN_COMMON) << "Failed to open file" << file.fileName(); return QMap(); } QJsonDocument parser; const QVariantMap controlInfo = parser.fromJson(file.readAll()).toVariant().toMap(); const QVariantList outputsInfo = controlInfo[QStringLiteral("outputs")].toList(); QMap retentions; for (const auto variantInfo : outputsInfo) { const QVariantMap info = variantInfo.toMap(); // TODO: this does not yet consider the output name (i.e. connector). Necessary? const QString outputHash = info[QStringLiteral("id")].toString(); if (outputHash.isEmpty()) { continue; } retentions[outputHash] = convertVariantToOutputRetention(info[QStringLiteral("retention")]); } return retentions; } -Control::OutputRetention Control::getOutputRetention(const QString &outputId, const QMap &retentions) +ControlOutput::ControlOutput(KScreen::OutputPtr output) + : m_output(output) { - if (retentions.contains(outputId)) { - return retentions[outputId]; +} + +QString ControlOutput::filePath(const QString &hash) +{ + const QString dir = dirPath() % QStringLiteral("outputs/"); + if (!QDir().mkpath(dir)) { + return QString(); } - // info for output not found - return OutputRetention::Undefined; + return dir % hash; +} + +QString ControlOutput::filePath() +{ + if (!m_output) { + return QString(); + } + return ControlOutput::filePath(m_output->hash()); } diff --git a/common/control.h b/common/control.h index e77a069..e076d62 100644 --- a/common/control.h +++ b/common/control.h @@ -1,46 +1,75 @@ /******************************************************************** Copyright 2019 Roman Gilg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef COMMON_CONTROL_H #define COMMON_CONTROL_H #include #include class Control { public: enum class OutputRetention { Undefined = -1, Global = 0, Individual = 1, }; - static QMap readInOutputRetentionValues(const QString &configId); + virtual ~Control() = default; + static OutputRetention getOutputRetention(const QString &outputId, const QMap &retentions); - static QString configFilePath(const QString &hash); - static QString outputFilePath(const QString &hash); + virtual QString filePath() = 0; -private: +protected: static QString dirPath(); static OutputRetention convertVariantToOutputRetention(QVariant variant); +private: static QString s_dirName; }; +class ControlConfig : public Control +{ +public: + ControlConfig(KScreen::ConfigPtr config); + + QMap readInOutputRetentionValues(); + + QString filePath() override; + static QString filePath(const QString &hash); + +private: + KScreen::ConfigPtr m_config; +}; + +class ControlOutput : public Control +{ +public: + ControlOutput(KScreen::OutputPtr output); + + // TODO: scale auto value + + QString filePath() override; + static QString filePath(const QString &hash); + +private: + KScreen::OutputPtr m_output; +}; + #endif diff --git a/kded/config.cpp b/kded/config.cpp index 91cfb1c..eacf14d 100644 --- a/kded/config.cpp +++ b/kded/config.cpp @@ -1,224 +1,224 @@ /******************************************************************** Copyright 2012 Alejandro Fiestas Olivares Copyright 2019 Roman Gilg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "config.h" #include "output.h" #include "../common/globals.h" #include "../common/control.h" #include "kscreen_daemon_debug.h" #include "device.h" #include #include #include #include #include #include #include #include QString Config::s_fixedConfigFileName = QStringLiteral("fixed-config"); QString Config::s_configsDirName = QStringLiteral("" /*"configs/"*/); // TODO: KDE6 - move these files into the subfolder QString Config::configsDirPath() { return Globals::dirPath() % s_configsDirName; } Config::Config(KScreen::ConfigPtr config) : m_data(config) { } QString Config::filePath() { if (!QDir().mkpath(configsDirPath())) { return QString(); } return configsDirPath() % id(); } QString Config::id() const { if (!m_data) { return QString(); } return m_data->connectedOutputsHash(); } bool Config::fileExists() const { return (QFile::exists(configsDirPath() % id()) || QFile::exists(configsDirPath() % s_fixedConfigFileName)); } std::unique_ptr Config::readFile() { if (Device::self()->isLaptop() && !Device::self()->isLidClosed()) { // We may look for a config that has been set when the lid was closed, Bug: 353029 const QString lidOpenedFilePath(filePath() % QStringLiteral("_lidOpened")); const QFile srcFile(lidOpenedFilePath); if (srcFile.exists()) { QFile::remove(filePath()); if (QFile::copy(lidOpenedFilePath, filePath())) { QFile::remove(lidOpenedFilePath); qCDebug(KSCREEN_KDED) << "Restored lid opened config to" << id(); } } } return readFile(id()); } std::unique_ptr Config::readOpenLidFile() { const QString openLidFilePath = filePath() % QStringLiteral("_lidOpened"); auto config = readFile(openLidFilePath); QFile::remove(openLidFilePath); return config; } std::unique_ptr Config::readFile(const QString &fileName) { if (!m_data) { return nullptr; } auto config = std::unique_ptr(new Config(m_data->clone())); config->setValidityFlags(m_validityFlags); QFile file; if (QFile::exists(configsDirPath() % s_fixedConfigFileName)) { file.setFileName(configsDirPath() % s_fixedConfigFileName); qCDebug(KSCREEN_KDED) << "found a fixed config, will use " << file.fileName(); } else { file.setFileName(configsDirPath() % fileName); } if (!file.open(QIODevice::ReadOnly)) { qCDebug(KSCREEN_KDED) << "failed to open file" << file.fileName(); return nullptr; } QJsonDocument parser; QVariantList outputs = parser.fromJson(file.readAll()).toVariant().toList(); - Output::readInOutputs(config->data()->outputs(), outputs, Control::readInOutputRetentionValues(config->id())); + Output::readInOutputs(config->data()->outputs(), outputs, ControlConfig(config->data()).readInOutputRetentionValues()); QSize screenSize; for (const auto &output : config->data()->outputs()) { if (!output->isConnected() || !output->isEnabled()) { continue; } const QRect geom = output->geometry(); if (geom.x() + geom.width() > screenSize.width()) { screenSize.setWidth(geom.x() + geom.width()); } if (geom.y() + geom.height() > screenSize.height()) { screenSize.setHeight(geom.y() + geom.height()); } } config->data()->screen()->setCurrentSize(screenSize); if (!canBeApplied(config->data())) { return nullptr; } return config; } bool Config::canBeApplied() const { return canBeApplied(m_data); } bool Config::canBeApplied(KScreen::ConfigPtr config) const { #ifdef KDED_UNIT_TEST Q_UNUSED(config); return true; #else return KScreen::Config::canBeApplied(config, m_validityFlags); #endif } bool Config::writeFile() { return writeFile(filePath()); } bool Config::writeOpenLidFile() { return writeFile(filePath() % QStringLiteral("_lidOpened")); } bool Config::writeFile(const QString &filePath) { if (id().isEmpty()) { return false; } const KScreen::OutputList outputs = m_data->outputs(); - const auto retentions = Control::readInOutputRetentionValues(id()); + const auto retentions = ControlConfig(m_data).readInOutputRetentionValues(); QVariantList outputList; Q_FOREACH(const KScreen::OutputPtr &output, outputs) { QVariantMap info; if (!output->isConnected()) { continue; } if (!Output::writeGlobalPart(output, info)) { continue; } info[QStringLiteral("primary")] = output->isPrimary(); info[QStringLiteral("enabled")] = output->isEnabled(); QVariantMap pos; pos[QStringLiteral("x")] = output->pos().x(); pos[QStringLiteral("y")] = output->pos().y(); info[QStringLiteral("pos")] = pos; if (Control::getOutputRetention(output->hash(), retentions) != Control::OutputRetention::Individual) { // try to update global output data Output::writeGlobal(output); } outputList.append(info); } QFile file(filePath); if (!file.open(QIODevice::WriteOnly)) { qCWarning(KSCREEN_KDED) << "Failed to open config file for writing! " << file.errorString(); return false; } file.write(QJsonDocument::fromVariant(outputList).toJson()); qCDebug(KSCREEN_KDED) << "Config saved on: " << file.fileName(); return true; } void Config::log() { if (!m_data) { return; } const auto outputs = m_data->outputs(); for (const auto o : outputs) { if (o->isConnected()) { qCDebug(KSCREEN_KDED) << o; } } }