on xenial help sign in
merge prereq
6d88404Michael Zanetti
debian/control−2
@@ -37,7 +37,6 @@ Build-Depends: cmake,
37 python:any (>= 2.7),
37 python:any (>= 2.7),
38 qml-module-qt-labs-folderlistmodel,
38 qml-module-qt-labs-folderlistmodel,
39 qml-module-qtquick-layouts,
39 qml-module-qtquick-layouts,
40− qml-module-qtquick-localstorage,
41 qml-module-qtquick-xmllistmodel,
40 qml-module-qtquick-xmllistmodel,
42 qml-module-qtquick2,
41 qml-module-qtquick2,
43 qml-module-qttest,
42 qml-module-qttest,
@@ -90,7 +89,6 @@ Depends: gsettings-desktop-schemas,
90 libglib2.0-bin,
89 libglib2.0-bin,
91 qmenumodel-qml (>= 0.2.9),
90 qmenumodel-qml (>= 0.2.9),
92 qml-module-qt-labs-folderlistmodel,
91 qml-module-qt-labs-folderlistmodel,
93− qml-module-qtquick-localstorage,
94 qml-module-qtquick-xmllistmodel,
92 qml-module-qtquick-xmllistmodel,
95 qtdeclarative5-gsettings1.0,
93 qtdeclarative5-gsettings1.0,
96 qtdeclarative5-qtmir-plugin (>= 0.4.4),
94 qtdeclarative5-qtmir-plugin (>= 0.4.4),
plugins/Utils/CMakeLists.txt+2−1
@@ -18,6 +18,7 @@ set(QMLPLUGIN_SRC
18 unitymenumodelpaths.cpp
18 unitymenumodelpaths.cpp
19 windowkeysfilter.cpp
19 windowkeysfilter.cpp
20 easingcurve.cpp
20 easingcurve.cpp
21+ windowstatestorage.cpp
21 plugin.cpp
22 plugin.cpp
22 )
23 )
23
24
@@ -33,6 +34,6 @@ target_link_libraries(Utils-qml ${GIO_LDFLAGS})
33# files directly in targets.
34# files directly in targets.
34set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
35set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
35
36
36−qt5_use_modules(Utils-qml Qml Quick DBus Network Gui)
37+qt5_use_modules(Utils-qml Qml Quick DBus Network Gui Sql Concurrent)
37
38
38add_unity8_plugin(Utils 0.1 Utils TARGETS Utils-qml)
39add_unity8_plugin(Utils 0.1 Utils TARGETS Utils-qml)
plugins/Utils/plugin.cpp+9
@@ -33,6 +33,14 @@
33#include "unitymenumodelpaths.h"
33#include "unitymenumodelpaths.h"
34#include "windowkeysfilter.h"
34#include "windowkeysfilter.h"
35#include "easingcurve.h"
35#include "easingcurve.h"
36+#include "windowstatestorage.h"
37+
38+static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
39+{
40+ Q_UNUSED(engine)
41+ Q_UNUSED(scriptEngine)
42+ return new WindowStateStorage();
43+}
36
44
37void UtilsPlugin::registerTypes(const char *uri)
45void UtilsPlugin::registerTypes(const char *uri)
38{
46{
@@ -46,6 +54,7 @@ void UtilsPlugin::registerTypes(const char *uri)
46 qmlRegisterType<GDateTimeFormatter>(uri, 0, 1, "GDateTimeFormatter");
54 qmlRegisterType<GDateTimeFormatter>(uri, 0, 1, "GDateTimeFormatter");
47 qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
55 qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
48 qmlRegisterType<RelativeTimeFormatter>(uri, 0, 1, "RelativeTimeFormatter");
56 qmlRegisterType<RelativeTimeFormatter>(uri, 0, 1, "RelativeTimeFormatter");
57+ qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
49}
58}
50
59
51void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
60void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
plugins/Utils/windowstatestorage.cppnew file+96
@@ -0,0 +1,96 @@
1+/*
2+ * Copyright 2015 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+ */
16+
17+#include "windowstatestorage.h"
18+
19+#include <QtConcurrent>
20+#include <QDebug>
21+#include <QSqlQuery>
22+#include <QSqlError>
23+#include <QSqlResult>
24+#include <QRect>
25+
26+QMutex WindowStateStorage::s_mutex;
27+
28+WindowStateStorage::WindowStateStorage(QObject *parent):
29+ QObject(parent)
30+{
31+ QString dbPath = QDir::homePath() + "/.cache/unity8/";
32+ m_db = QSqlDatabase::addDatabase("QSQLITE");
33+ QDir dir;
34+ dir.mkpath(dbPath);
35+ m_db.setDatabaseName(dbPath + "windowstatestorage.sqlite");
36+ initdb();
37+}
38+
39+void WindowStateStorage::saveGeometry(const QString &windowId, const QRect &rect)
40+{
41+ QString queryString = QString("INSERT OR REPLACE INTO geometry (windowId, x, y, width, height) values ('%1', '%2', '%3', '%4', '%5');")
42+ .arg(windowId)
43+ .arg(rect.x())
44+ .arg(rect.y())
45+ .arg(rect.width())
46+ .arg(rect.height());
47+
48+ QtConcurrent::run(executeAsyncQuery, queryString);
49+}
50+
51+void WindowStateStorage::executeAsyncQuery(const QString &queryString)
52+{
53+ QMutexLocker l(&s_mutex);
54+ QSqlQuery query;
55+
56+ bool ok = query.exec(queryString);
57+ if (!ok) {
58+ qWarning() << "Error executing query" << queryString
59+ << "Driver error:" << query.lastError().driverText()
60+ << "Database error:" << query.lastError().databaseText();
61+ }
62+}
63+
64+QRect WindowStateStorage::getGeometry(const QString &windowId, const QRect &defaultValue)
65+{
66+ QMutexLocker l(&s_mutex);
67+ QString queryString = QString("SELECT * FROM geometry WHERE windowId = '%1';")
68+ .arg(windowId);
69+ QSqlQuery query;
70+
71+ bool ok = query.exec(queryString);
72+ if (!ok) {
73+ qWarning() << "Error retrieving window state for" << windowId
74+ << "Driver error:" << query.lastError().driverText()
75+ << "Database error:" << query.lastError().databaseText();
76+ return defaultValue;
77+ }
78+ if (!query.first()) {
79+ return defaultValue;
80+ }
81+ return QRect(query.value("x").toInt(), query.value("y").toInt(), query.value("width").toInt(), query.value("height").toInt());
82+}
83+
84+void WindowStateStorage::initdb()
85+{
86+ m_db.open();
87+ if (!m_db.open()) {
88+ qWarning() << "Error opening state database:" << m_db.lastError().driverText() << m_db.lastError().databaseText();
89+ return;
90+ }
91+
92+ if (!m_db.tables().contains("geometry")) {
93+ QSqlQuery query;
94+ query.exec("CREATE TABLE geometry(windowId TEXT UNIQUE, x INTEGER, y INTEGER, width INTEGER, height INTEGER);");
95+ }
96+}
plugins/Utils/windowstatestorage.hnew file+38
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright 2015 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+ */
16+
17+#include <QObject>
18+#include <QSqlDatabase>
19+#include <QMutex>
20+
21+class WindowStateStorage: public QObject
22+{
23+ Q_OBJECT
24+public:
25+ WindowStateStorage(QObject *parent = 0);
26+
27+ Q_INVOKABLE void saveGeometry(const QString &windowId, const QRect &rect);
28+ Q_INVOKABLE QRect getGeometry(const QString &windowId, const QRect &defaultValue);
29+
30+private:
31+ void initdb();
32+
33+ static void executeAsyncQuery(const QString &queryString);
34+ static QMutex s_mutex;
35+
36+ // NB: This is accessed from threads. Make sure to mutex it.
37+ QSqlDatabase m_db;
38+};
qml/Components/WindowStateStorage/WindowStateStorage.qmldeleted−63
@@ -1,63 +0,0 @@
1−/*
2− * Copyright (C) 2015 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−pragma Singleton
18−import QtQuick 2.2
19−import QtQuick.LocalStorage 2.0
20−
21−QtObject {
22−
23− property var priv: QtObject {
24− property var db: null
25−
26− function openDB() {
27− if (db !== null) return;
28−
29− db = LocalStorage.openDatabaseSync("unity8", "0.1", "", 100000);
30− try {
31− db.transaction(function(tx) {
32− tx.executeSql('CREATE TABLE IF NOT EXISTS windowproperties(windowId TEXT UNIQUE, x INTEGER, y INTEGER, width INTEGER, height INTEGER)');
33− });
34− } catch (err) {
35− console.log("Error creating table in database: " + err);
36− };
37− }
38− }
39−
40− function saveState(windowId, x, y, width, height) {
41− priv.openDB();
42− priv.db.transaction( function(tx){
43− tx.executeSql('INSERT OR REPLACE INTO windowproperties VALUES(?, ?, ?, ?, ?)', [windowId, x, y, width, height]);
44− });
45− }
46−
47− function getState(windowId) {
48− priv.openDB();
49− var res = new Object();
50− priv.db.transaction(function(tx) {
51− var rs = tx.executeSql('SELECT x, y, width, height FROM windowproperties WHERE windowId=?;', [windowId]);
52− if (rs.rows.length === 0) {
53− res = undefined;
54− } else {
55− res.x = rs.rows.item(0).x
56− res.y = rs.rows.item(0).y
57− res.width = rs.rows.item(0).width
58− res.height = rs.rows.item(0).height
59− }
60− });
61− return res;
62− }
63−}
qml/Components/WindowStateStorage/qmldirdeleted−1
@@ -1 +0,0 @@
1−singleton WindowStateStorage 1.0 WindowStateStorage.qml
qml/Stages/WindowMoveResizeArea.qml+3−3
@@ -18,7 +18,7 @@
18
18
19import QtQuick 2.3
19import QtQuick 2.3
20import Ubuntu.Components 1.1
20import Ubuntu.Components 1.1
21−import "../Components/WindowStateStorage"
21+import Utils 0.1
22
22
23MouseArea {
23MouseArea {
24 id: root
24 id: root
@@ -50,7 +50,7 @@ MouseArea {
50 }
50 }
51
51
52 Component.onCompleted: {
52 Component.onCompleted: {
53− var windowState = WindowStateStorage.getState(root.windowId)
53+ var windowState = WindowStateStorage.getGeometry(root.windowId, Qt.rect(target.x, target.y, target.width, target.height))
54 if (windowState !== undefined) {
54 if (windowState !== undefined) {
55 target.x = windowState.x
55 target.x = windowState.x
56 target.y = windowState.y
56 target.y = windowState.y
@@ -106,6 +106,6 @@ MouseArea {
106 }
106 }
107
107
108 onReleased: {
108 onReleased: {
109− WindowStateStorage.saveState(root.windowId,target.x, target.y, target.width, target.height)
109+ WindowStateStorage.saveGeometry(root.windowId, Qt.rect(target.x, target.y, target.width, target.height))
110 }
110 }
111}
111}
tests/qmltests/Stages/tst_WindowMoveResizeArea.qml+15−2
@@ -34,11 +34,14 @@ Item {
34 Component {
34 Component {
35 id: fakeWindowComponent
35 id: fakeWindowComponent
36
36
37− Rectangle {
37+ Item {
38 id: fakeWindow
38 id: fakeWindow
39− color: "khaki"
40 property alias minWidth: moveResizeArea.minWidth
39 property alias minWidth: moveResizeArea.minWidth
41 property alias minHeight: moveResizeArea.minHeight
40 property alias minHeight: moveResizeArea.minHeight
41+ x: units.gu(20)
42+ y: units.gu(20)
43+ height: units.gu(20)
44+ width: units.gu(20)
42
45
43 WindowMoveResizeArea {
46 WindowMoveResizeArea {
44 id: moveResizeArea
47 id: moveResizeArea
@@ -48,6 +51,16 @@ Item {
48 minHeight: units.gu(10)
51 minHeight: units.gu(10)
49 windowId: "test-window-id"
52 windowId: "test-window-id"
50 }
53 }
54+
55+ Rectangle {
56+ anchors.fill: moveResizeArea
57+ color: "red"
58+ }
59+
60+ Rectangle {
61+ anchors.fill: fakeWindow
62+ color: "blue"
63+ }
51 }
64 }
52 }
65 }
53
66