Lomiri
DisplayConfigurationStorage.cpp
1 /*
2  * Copyright (C) 2017 Canonical Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include "DisplayConfigurationStorage.h"
18 
19 #include <QFile>
20 #include <QStandardPaths>
21 #include <QJsonObject>
22 #include <QJsonDocument>
23 
24 namespace {
25 
26 #ifndef USE_MIROIL
27 namespace miroil = miral;
28 #endif
29 
30 inline QString stringFromEdid(const miroil::Edid& edid)
31 {
32  QString str;
33  str += QString::fromStdString(edid.vendor);
34  str += QString("%1%2").arg(edid.product_code).arg(edid.serial_number);
35 
36  for (int i = 0; i < 4; i++) {
37  str += QString::fromStdString(edid.descriptors[i].string_value());
38  }
39  return str;
40 }
41 
42 }
43 
44 DisplayConfigurationStorage::DisplayConfigurationStorage()
45 {
46 }
47 
48 void DisplayConfigurationStorage::save(const miroil::DisplayId &displayId, const miroil::DisplayConfigurationOptions &options)
49 {
50  const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/lomiri/");
51  QFile f(dbPath + stringFromEdid(displayId.edid) + ".edid");
52 
53  QJsonObject json;
54  if (options.used.is_set()) json.insert("used", options.used.value());
55  if (options.clone_output_index.is_set()) json.insert("clone_output_index", static_cast<int>(options.clone_output_index.value()));
56  if (options.mode.is_set()) {
57  auto const& mode = options.mode.value();
58 
59  QString sz(QString("%1x%2").arg(mode.size.width.as_int()).arg(mode.size.height.as_int()));
60  QJsonObject jsonMode({
61  {"size", sz},
62  {"refresh_rate", mode.refresh_rate }
63  });
64  json.insert("mode", jsonMode);
65  }
66  if (options.orientation.is_set()) json.insert("orientation", static_cast<int>(options.orientation.value()));
67  if (options.form_factor.is_set()) json.insert("form_factor", static_cast<int>(options.form_factor.value()));
68  if (options.scale.is_set()) json.insert("scale", options.scale.value());
69 
70  if (f.open(QIODevice::WriteOnly)) {
71  QJsonDocument saveDoc(json);
72  f.write(saveDoc.toJson());
73  }
74 }
75 
76 bool DisplayConfigurationStorage::load(const miroil::DisplayId &displayId, miroil::DisplayConfigurationOptions &options) const
77 {
78  const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/lomiri/");
79  QFile f(dbPath + stringFromEdid(displayId.edid) + ".edid");
80 
81  if (f.open(QIODevice::ReadOnly)) {
82  QByteArray saveData = f.readAll();
83  QJsonDocument loadDoc(QJsonDocument::fromJson(saveData));
84 
85  QJsonObject json(loadDoc.object());
86  if (json.contains("used")) options.used = json["used"].toBool();
87  if (json.contains("clone_output_index")) options.clone_output_index = json["clone_output_index"].toInt();
88  if (json.contains("mode")) {
89  QJsonObject jsonMode = json["mode"].toObject();
90 
91  if (jsonMode.contains("size") && jsonMode.contains("refresh_rate")) {
92  QString sz(jsonMode["size"].toString());
93 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
94  QStringList geo = sz.split("x", Qt::SkipEmptyParts);
95 #else
96  QStringList geo = sz.split("x", QString::SkipEmptyParts);
97 #endif
98  if (geo.count() == 2) {
99  miroil::DisplayConfigurationOptions::DisplayMode mode;
100  mode.size = mir::geometry::Size(geo[0].toInt(), geo[1].toInt());
101  mode.refresh_rate = jsonMode["refresh_rate"].toDouble();
102  options.mode = mode;
103  }
104  }
105  }
106  if (json.contains("orientation")) options.orientation = static_cast<MirOrientation>(json["orientation"].toInt());
107  if (json.contains("form_factor")) options.form_factor = static_cast<MirFormFactor>(json["form_factor"].toInt());
108  if (json.contains("scale")) options.scale = json["form_factor"].toDouble();
109 
110  return true;
111  }
112 
113  return false;
114 }