17 #include "windowstatestorage.h" 19 #include <QtConcurrent> 21 #include <QFutureSynchronizer> 26 #include <unity/shell/application/ApplicationInfoInterface.h> 28 QMutex WindowStateStorage::s_mutex;
30 inline QString sanitiseString(QString
string) {
31 return string.remove(QLatin1Char(
'\"'))
32 .remove(QLatin1Char(
'\''))
33 .remove(QLatin1Char(
'\\'));
36 WindowStateStorage::WindowStateStorage(QObject *parent):
39 QString dbPath = QDir::homePath() +
"/.cache/unity8/";
40 m_db = QSqlDatabase::addDatabase(QStringLiteral(
"QSQLITE"));
43 m_db.setDatabaseName(dbPath +
"windowstatestorage.sqlite");
47 WindowStateStorage::~WindowStateStorage()
49 QFutureSynchronizer<void> futureSync;
50 for (
int i = 0; i < m_asyncQueries.count(); ++i) {
51 futureSync.addFuture(m_asyncQueries[i]);
53 futureSync.waitForFinished();
57 void WindowStateStorage::saveState(
const QString &windowId, WindowStateStorage::WindowState state)
59 const QString queryString = QStringLiteral(
"INSERT OR REPLACE INTO state (windowId, state) values ('%1', '%2');")
60 .arg(sanitiseString(windowId))
63 saveValue(queryString);
66 WindowStateStorage::WindowState WindowStateStorage::getState(
const QString &windowId, WindowStateStorage::WindowState defaultValue)
const 68 const QString queryString = QStringLiteral(
"SELECT * FROM state WHERE windowId = '%1';")
69 .arg(sanitiseString(windowId));
71 QSqlQuery query = getValue(queryString);
76 return (WindowState)query.value(QStringLiteral(
"state")).toInt();
79 void WindowStateStorage::saveGeometry(
const QString &windowId,
const QRect &rect)
81 const QString queryString = QStringLiteral(
"INSERT OR REPLACE INTO geometry (windowId, x, y, width, height) values ('%1', '%2', '%3', '%4', '%5');")
82 .arg(sanitiseString(windowId))
88 saveValue(queryString);
91 void WindowStateStorage::saveStage(
const QString &appId,
int stage)
93 const QString queryString = QStringLiteral(
"INSERT OR REPLACE INTO stage (appId, stage) values ('%1', '%2');")
94 .arg(sanitiseString(appId))
97 saveValue(queryString);
100 int WindowStateStorage::getStage(
const QString &appId,
int defaultValue)
const 102 const QString queryString = QStringLiteral(
"SELECT * FROM stage WHERE appId = '%1';")
103 .arg(sanitiseString(appId));
105 QSqlQuery query = getValue(queryString);
107 if (!query.first()) {
110 return query.value(
"stage").toInt();
113 void WindowStateStorage::executeAsyncQuery(
const QString &queryString)
115 QMutexLocker l(&s_mutex);
118 bool ok = query.exec(queryString);
120 qWarning() <<
"Error executing query" << queryString
121 <<
"Driver error:" << query.lastError().driverText()
122 <<
"Database error:" << query.lastError().databaseText();
126 QRect WindowStateStorage::getGeometry(
const QString &windowId,
const QRect &defaultValue)
const 128 QString queryString = QStringLiteral(
"SELECT * FROM geometry WHERE windowId = '%1';")
129 .arg(sanitiseString(windowId));
131 QSqlQuery query = getValue(queryString);
133 if (!query.first()) {
136 return QRect(query.value(QStringLiteral(
"x")).toInt(), query.value(QStringLiteral(
"y")).toInt(),
137 query.value(QStringLiteral(
"width")).toInt(), query.value(QStringLiteral(
"height")).toInt());
140 void WindowStateStorage::initdb()
144 qWarning() <<
"Error opening state database:" << m_db.lastError().driverText() << m_db.lastError().databaseText();
148 if (!m_db.tables().contains(QStringLiteral(
"geometry"))) {
150 query.exec(QStringLiteral(
"CREATE TABLE geometry(windowId TEXT UNIQUE, x INTEGER, y INTEGER, width INTEGER, height INTEGER);"));
153 if (!m_db.tables().contains(QStringLiteral(
"state"))) {
155 query.exec(QStringLiteral(
"CREATE TABLE state(windowId TEXT UNIQUE, state INTEGER);"));
158 if (!m_db.tables().contains(QStringLiteral(
"stage"))) {
160 query.exec(QStringLiteral(
"CREATE TABLE stage(appId TEXT UNIQUE, stage INTEGER);"));
164 void WindowStateStorage::saveValue(
const QString &queryString)
166 QMutexLocker mutexLocker(&s_mutex);
168 QFuture<void> future = QtConcurrent::run(executeAsyncQuery, queryString);
169 m_asyncQueries.append(future);
171 QFutureWatcher<void> *futureWatcher =
new QFutureWatcher<void>();
172 futureWatcher->setFuture(future);
173 connect(futureWatcher, &QFutureWatcher<void>::finished,
175 [=](){ m_asyncQueries.removeAll(futureWatcher->future());
176 futureWatcher->deleteLater(); });
179 QSqlQuery WindowStateStorage::getValue(
const QString &queryString)
const 181 QMutexLocker l(&s_mutex);
184 bool ok = query.exec(queryString);
186 qWarning() <<
"Error retrieving database query:" << queryString
187 <<
"Driver error:" << query.lastError().driverText()
188 <<
"Database error:" << query.lastError().databaseText();