on 141bb7b help sign in
unity8/plugins/Utils/windowstatestorage.cpp
203 lines 7.0 kB history raw
1/*
2 * Copyright 2015-2016 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17#include "windowstatestorage.h"
19#include <QtConcurrent>
20#include <QDebug>
21#include <QSqlQuery>
22#include <QSqlError>
23#include <QSqlResult>
24#include <QRect>
25#include <unity/shell/application/ApplicationInfoInterface.h>
27QMutex WindowStateStorage::s_mutex;
29inline QString sanitiseString(QString string) {
30 return string.remove(QLatin1Char('\"'))
31 .remove(QLatin1Char('\''))
32 .remove(QLatin1Char('\\'));
35WindowStateStorage::WindowStateStorage(const QString& dbName, QObject *parent):
36 QObject(parent)
38 const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/unity8/");
39 m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"));
40 QDir dir;
41 dir.mkpath(dbPath);
42 if (dbName != nullptr) {
43 m_db.setDatabaseName(dbName);
44 } else {
45 m_db.setDatabaseName(dbPath + "windowstatestorage.sqlite");
46 }
47 initdb();
50WindowStateStorage::~WindowStateStorage()
52 m_db.close();
55void WindowStateStorage::saveState(const QString &windowId, WindowStateStorage::WindowState state)
57 const QString queryString = QStringLiteral("INSERT OR REPLACE INTO state (windowId, state) values ('%1', '%2');")
58 .arg(sanitiseString(windowId))
59 .arg((int)state);
61 saveValue(queryString);
64WindowStateStorage::WindowState WindowStateStorage::getState(const QString &windowId, WindowStateStorage::WindowState defaultValue) const
66 const QString queryString = QStringLiteral("SELECT state FROM state WHERE windowId = '%1';")
67 .arg(sanitiseString(windowId));
69 QSqlQuery query = getValue(queryString);
71 if (!query.first()) {
72 return defaultValue;
73 }
74 return (WindowState)query.value(QStringLiteral("state")).toInt();
77void WindowStateStorage::saveGeometry(const QString &windowId, const QRect &rect)
79 const QString queryString = QStringLiteral("INSERT OR REPLACE INTO geometry (windowId, x, y, width, height) values ('%1', '%2', '%3', '%4', '%5');")
80 .arg(sanitiseString(windowId))
81 .arg(rect.x())
82 .arg(rect.y())
83 .arg(rect.width())
84 .arg(rect.height());
86 saveValue(queryString);
89void WindowStateStorage::saveStage(const QString &appId, int stage)
91 const QString queryString = QStringLiteral("INSERT OR REPLACE INTO stage (appId, stage) values ('%1', '%2');")
92 .arg(sanitiseString(appId))
93 .arg(stage);
95 saveValue(queryString);
98int WindowStateStorage::getStage(const QString &appId, int defaultValue) const
100 const QString queryString = QStringLiteral("SELECT stage FROM stage WHERE appId = '%1';")
101 .arg(sanitiseString(appId));
103 QSqlQuery query = getValue(queryString);
105 if (!query.first()) {
106 return defaultValue;
107 }
108 return query.value("stage").toInt();
111QRect WindowStateStorage::getGeometry(const QString &windowId, const QRect &defaultValue) const
113 QString queryString = QStringLiteral("SELECT * FROM geometry WHERE windowId = '%1';")
114 .arg(sanitiseString(windowId));
116 QSqlQuery query = getValue(queryString);
118 if (!query.first()) {
119 return defaultValue;
120 }
122 const QRect result(query.value(QStringLiteral("x")).toInt(), query.value(QStringLiteral("y")).toInt(),
123 query.value(QStringLiteral("width")).toInt(), query.value(QStringLiteral("height")).toInt());
125 if (result.isValid()) {
126 return result;
127 }
129 return defaultValue;
132void WindowStateStorage::initdb()
134 m_db.open();
135 if (!m_db.open()) {
136 qWarning() << "Error opening state database:" << m_db.lastError().driverText() << m_db.lastError().databaseText();
137 return;
138 }
140 if (!m_db.tables().contains(QStringLiteral("geometry"))) {
141 QSqlQuery query;
142 query.exec(QStringLiteral("CREATE TABLE geometry(windowId TEXT UNIQUE, x INTEGER, y INTEGER, width INTEGER, height INTEGER);"));
143 }
145 if (!m_db.tables().contains(QStringLiteral("state"))) {
146 QSqlQuery query;
147 query.exec(QStringLiteral("CREATE TABLE state(windowId TEXT UNIQUE, state INTEGER);"));
148 }
150 if (!m_db.tables().contains(QStringLiteral("stage"))) {
151 QSqlQuery query;
152 query.exec(QStringLiteral("CREATE TABLE stage(appId TEXT UNIQUE, stage INTEGER);"));
153 }
156void WindowStateStorage::saveValue(const QString &queryString)
158 QMutexLocker mutexLocker(&s_mutex);
159 QSqlQuery query;
160 auto ok = query.exec(queryString);
161 if (!ok) {
162 qWarning() << "Error executing query" << queryString
163 << "Driver error:" << query.lastError().driverText()
164 << "Database error:" << query.lastError().databaseText();
165 }
168QSqlQuery WindowStateStorage::getValue(const QString &queryString) const
170 QMutexLocker l(&s_mutex);
171 QSqlQuery query;
173 bool ok = query.exec(queryString);
174 if (!ok) {
175 qWarning() << "Error retrieving database query:" << queryString
176 << "Driver error:" << query.lastError().driverText()
177 << "Database error:" << query.lastError().databaseText();
178 }
179 return query;
182Mir::State WindowStateStorage::toMirState(WindowState state) const
184 // assumes a single state (not an OR of several)
185 switch (state) {
186 case WindowStateMaximized: return Mir::MaximizedState;
187 case WindowStateMinimized: return Mir::MinimizedState;
188 case WindowStateFullscreen: return Mir::FullscreenState;
189 case WindowStateMaximizedLeft: return Mir::MaximizedLeftState;
190 case WindowStateMaximizedRight: return Mir::MaximizedRightState;
191 case WindowStateMaximizedHorizontally: return Mir::HorizMaximizedState;
192 case WindowStateMaximizedVertically: return Mir::VertMaximizedState;
193 case WindowStateMaximizedTopLeft: return Mir::MaximizedTopLeftState;
194 case WindowStateMaximizedTopRight: return Mir::MaximizedTopRightState;
195 case WindowStateMaximizedBottomLeft: return Mir::MaximizedBottomLeftState;
196 case WindowStateMaximizedBottomRight: return Mir::MaximizedBottomRightState;
198 case WindowStateNormal:
199 case WindowStateRestored:
200 default:
201 return Mir::RestoredState;
202 }