Merge lp:~uriboni/messaging-app/stickers into lp:messaging-app
- stickers
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 491 |
Proposed branch: | lp:~uriboni/messaging-app/stickers |
Merge into: | lp:messaging-app |
Diff against target: |
1937 lines (+1685/-33) 22 files modified
.bzrignore (+37/-0) debian/control (+1/-0) debian/messaging-app.install (+1/-0) src/CMakeLists.txt (+3/-1) src/messagingapplication.cpp (+17/-0) src/qml/CMakeLists.txt (+1/-0) src/qml/Messages.qml (+55/-2) src/qml/Stickers/CMakeLists.txt (+4/-0) src/qml/Stickers/HistoryButton.qml (+35/-0) src/qml/Stickers/StickerDelegate.qml (+32/-0) src/qml/Stickers/StickerPackDelegate.qml (+53/-0) src/qml/Stickers/StickerPackModel.qml (+27/-0) src/qml/Stickers/StickerPacksModel.qml (+25/-0) src/qml/Stickers/StickersPicker.qml (+112/-0) src/qml/assets/face-smile-big-symbolic-2.svg (+182/-0) src/qml/assets/history.svg (+173/-0) src/qml/assets/input-keyboard-symbolic.svg (+221/-0) src/stickers-history-model.cpp (+307/-0) src/stickers-history-model.h (+91/-0) tests/qml/CMakeLists.txt (+42/-30) tests/qml/tst_QmlTests.cpp (+78/-0) tests/qml/tst_StickersHistoryModel.qml (+188/-0) |
To merge this branch: | bzr merge lp:~uriboni/messaging-app/stickers |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ubuntu Phablet Team | Pending | ||
Review via email: mp+277446@code.launchpad.net |
Commit message
Prototype implementation for stickers support.
Description of the change
Prototype implementation for stickers support.
At the moment only the sticker picker component is implemented (including the most frequently used stickers panel).
Actually sending the sticker chosen by the user is not implemented by this branch yet.
It is also unclear what stickers will be preinstalled, so at the moment the app reads stickers from the user data directory: ~/.local/
Each subdirectory is considered a "sticker pack" and the pack can contain any number of png, webm or gif files, preferrably with transparency.
Test sticke packs: http://
- 475. By Ugo Riboni
-
Remove debug code
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:475
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 476. By Ugo Riboni
-
Add stickers directory to cmake
- 477. By Ugo Riboni
-
The model is now a chronological list of the most recently used stickers
- 478. By Ugo Riboni
-
Add a limit property to the model to set the maximum size of the history
- 479. By Ugo Riboni
-
Fix .bzrignore to properly ignore test binaries, and remove mistakely added test binary
- 480. By Ugo Riboni
-
Add stickers qml dir to the list of installed files in debian
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:480
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 481. By Ugo Riboni
-
Fix interactions between OSK, stickers picker and the rest of the UI
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:481
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 482. By Ugo Riboni
-
Add missing debian dependecy
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:482
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:482
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:482
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === added file '.bzrignore' | |||
2 | --- .bzrignore 1970-01-01 00:00:00 +0000 | |||
3 | +++ .bzrignore 2015-11-16 14:15:20 +0000 | |||
4 | @@ -0,0 +1,37 @@ | |||
5 | 1 | *.qmlproject.user | ||
6 | 2 | CMakeCache.txt | ||
7 | 3 | CMakeFiles/ | ||
8 | 4 | CMakeLists.txt.user | ||
9 | 5 | cmake_install.cmake | ||
10 | 6 | cmake_uninstall.cmake | ||
11 | 7 | Makefile | ||
12 | 8 | install_manifest.txt | ||
13 | 9 | CTestTestfile.cmake | ||
14 | 10 | |||
15 | 11 | *.cbp | ||
16 | 12 | *.moc | ||
17 | 13 | moc_*.cpp | ||
18 | 14 | *_automoc.cpp | ||
19 | 15 | |||
20 | 16 | Testing | ||
21 | 17 | RE:tests/qml/tst_\w+Tests$ | ||
22 | 18 | po/*.gmo | ||
23 | 19 | po/src | ||
24 | 20 | |||
25 | 21 | config.h | ||
26 | 22 | src/messaging-app | ||
27 | 23 | src/messaging-app.desktop* | ||
28 | 24 | |||
29 | 25 | obj-* | ||
30 | 26 | debian/usr.bin.webbrowser-app | ||
31 | 27 | debian/files | ||
32 | 28 | debian/tmp/ | ||
33 | 29 | debian/qtdeclarative5-ubuntu-ui-extras-browser-plugin/ | ||
34 | 30 | debian/qtdeclarative5-ubuntu-web-plugin/ | ||
35 | 31 | debian/qtdeclarative5-ubuntu-web-plugin-doc/ | ||
36 | 32 | debian/messaging-app/ | ||
37 | 33 | debian/messaging-app-autopilot/ | ||
38 | 34 | debian/*.debhelper | ||
39 | 35 | debian/*.debhelper.log | ||
40 | 36 | debian/*.substvars | ||
41 | 37 | debian/stamp-* | ||
42 | 0 | 38 | ||
43 | === modified file 'debian/control' | |||
44 | --- debian/control 2015-09-11 14:25:57 +0000 | |||
45 | +++ debian/control 2015-11-16 14:15:20 +0000 | |||
46 | @@ -23,6 +23,7 @@ | |||
47 | 23 | qtdeclarative5-ubuntu-addressbook0.1, | 23 | qtdeclarative5-ubuntu-addressbook0.1, |
48 | 24 | qtdeclarative5-qtcontacts-plugin, | 24 | qtdeclarative5-qtcontacts-plugin, |
49 | 25 | qml-module-qt-labs-settings, | 25 | qml-module-qt-labs-settings, |
50 | 26 | qtdeclarative5-folderlistmodel-plugin, | ||
51 | 26 | qtpim5-dev, | 27 | qtpim5-dev, |
52 | 27 | xvfb, | 28 | xvfb, |
53 | 28 | Standards-Version: 3.9.4 | 29 | Standards-Version: 3.9.4 |
54 | 29 | 30 | ||
55 | === modified file 'debian/messaging-app.install' | |||
56 | --- debian/messaging-app.install 2014-08-11 22:22:59 +0000 | |||
57 | +++ debian/messaging-app.install 2015-11-16 14:15:20 +0000 | |||
58 | @@ -8,4 +8,5 @@ | |||
59 | 8 | usr/share/messaging-app/3rd_party | 8 | usr/share/messaging-app/3rd_party |
60 | 9 | usr/share/messaging-app/MMS/*.qml | 9 | usr/share/messaging-app/MMS/*.qml |
61 | 10 | usr/share/messaging-app/Dialogs/*.qml | 10 | usr/share/messaging-app/Dialogs/*.qml |
62 | 11 | usr/share/messaging-app/Stickers/*.qml | ||
63 | 11 | usr/bin/*messaging-app* | 12 | usr/bin/*messaging-app* |
64 | 12 | 13 | ||
65 | === modified file 'src/CMakeLists.txt' | |||
66 | --- src/CMakeLists.txt 2015-02-24 13:33:31 +0000 | |||
67 | +++ src/CMakeLists.txt 2015-11-16 14:15:20 +0000 | |||
68 | @@ -2,17 +2,19 @@ | |||
69 | 2 | 2 | ||
70 | 3 | set(messaging_app_HDRS | 3 | set(messaging_app_HDRS |
71 | 4 | messagingapplication.h | 4 | messagingapplication.h |
72 | 5 | stickers-history-model.h | ||
73 | 5 | ) | 6 | ) |
74 | 6 | 7 | ||
75 | 7 | set(messaging_app_SRCS | 8 | set(messaging_app_SRCS |
76 | 8 | messagingapplication.cpp | 9 | messagingapplication.cpp |
77 | 9 | main.cpp | 10 | main.cpp |
78 | 11 | stickers-history-model.cpp | ||
79 | 10 | ) | 12 | ) |
80 | 11 | 13 | ||
81 | 12 | add_executable(${MESSAGING_APP} | 14 | add_executable(${MESSAGING_APP} |
82 | 13 | ${messaging_app_SRCS} | 15 | ${messaging_app_SRCS} |
83 | 14 | ) | 16 | ) |
85 | 15 | qt5_use_modules(${MESSAGING_APP} Core DBus Gui Qml Quick Versit) | 17 | qt5_use_modules(${MESSAGING_APP} Core DBus Gui Qml Quick Versit Sql) |
86 | 16 | 18 | ||
87 | 17 | include_directories( | 19 | include_directories( |
88 | 18 | ${CMAKE_CURRENT_BINARY_DIR} | 20 | ${CMAKE_CURRENT_BINARY_DIR} |
89 | 19 | 21 | ||
90 | === modified file 'src/messagingapplication.cpp' | |||
91 | --- src/messagingapplication.cpp 2015-07-07 16:31:26 +0000 | |||
92 | +++ src/messagingapplication.cpp 2015-11-16 14:15:20 +0000 | |||
93 | @@ -17,6 +17,7 @@ | |||
94 | 17 | */ | 17 | */ |
95 | 18 | 18 | ||
96 | 19 | #include "messagingapplication.h" | 19 | #include "messagingapplication.h" |
97 | 20 | #include "stickers-history-model.h" | ||
98 | 20 | 21 | ||
99 | 21 | #include <libnotify/notify.h> | 22 | #include <libnotify/notify.h> |
100 | 22 | 23 | ||
101 | @@ -24,6 +25,7 @@ | |||
102 | 24 | #include <QUrl> | 25 | #include <QUrl> |
103 | 25 | #include <QUrlQuery> | 26 | #include <QUrlQuery> |
104 | 26 | #include <QDebug> | 27 | #include <QDebug> |
105 | 28 | #include <QDir> | ||
106 | 27 | #include <QStringList> | 29 | #include <QStringList> |
107 | 28 | #include <QQuickItem> | 30 | #include <QQuickItem> |
108 | 29 | #include <QQmlComponent> | 31 | #include <QQmlComponent> |
109 | @@ -36,6 +38,7 @@ | |||
110 | 36 | #include "config.h" | 38 | #include "config.h" |
111 | 37 | #include <QQmlEngine> | 39 | #include <QQmlEngine> |
112 | 38 | #include <QMimeDatabase> | 40 | #include <QMimeDatabase> |
113 | 41 | #include <QStandardPaths> | ||
114 | 39 | #include <QVersitReader> | 42 | #include <QVersitReader> |
115 | 40 | 43 | ||
116 | 41 | using namespace QtVersit; | 44 | using namespace QtVersit; |
117 | @@ -71,6 +74,13 @@ | |||
118 | 71 | setApplicationName("MessagingApp"); | 74 | setApplicationName("MessagingApp"); |
119 | 72 | } | 75 | } |
120 | 73 | 76 | ||
121 | 77 | static QObject* StickersHistoryModel_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) | ||
122 | 78 | { | ||
123 | 79 | Q_UNUSED(engine); | ||
124 | 80 | Q_UNUSED(scriptEngine); | ||
125 | 81 | return new StickersHistoryModel(); | ||
126 | 82 | } | ||
127 | 83 | |||
128 | 74 | bool MessagingApplication::setup() | 84 | bool MessagingApplication::setup() |
129 | 75 | { | 85 | { |
130 | 76 | installIconPath(); | 86 | installIconPath(); |
131 | @@ -149,6 +159,13 @@ | |||
132 | 149 | m_view->rootContext()->setContextProperty("QTCONTACTS_MANAGER_OVERRIDE", contactsBackend); | 159 | m_view->rootContext()->setContextProperty("QTCONTACTS_MANAGER_OVERRIDE", contactsBackend); |
133 | 150 | } | 160 | } |
134 | 151 | 161 | ||
135 | 162 | QDir dataLocation(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); | ||
136 | 163 | m_view->rootContext()->setContextProperty("dataLocation", dataLocation.absolutePath()); | ||
137 | 164 | dataLocation.mkpath("stickers"); | ||
138 | 165 | const char* uri = "messagingapp.private"; | ||
139 | 166 | qmlRegisterSingletonType<StickersHistoryModel>(uri, 0, 1, "StickersHistoryModel", StickersHistoryModel_singleton_factory); | ||
140 | 167 | |||
141 | 168 | |||
142 | 152 | // used by autopilot tests to load vcards during tests | 169 | // used by autopilot tests to load vcards during tests |
143 | 153 | QByteArray testData = qgetenv("QTCONTACTS_PRELOAD_VCARD"); | 170 | QByteArray testData = qgetenv("QTCONTACTS_PRELOAD_VCARD"); |
144 | 154 | m_view->rootContext()->setContextProperty("QTCONTACTS_PRELOAD_VCARD", testData); | 171 | m_view->rootContext()->setContextProperty("QTCONTACTS_PRELOAD_VCARD", testData); |
145 | 155 | 172 | ||
146 | === modified file 'src/qml/CMakeLists.txt' | |||
147 | --- src/qml/CMakeLists.txt 2014-08-11 22:22:59 +0000 | |||
148 | +++ src/qml/CMakeLists.txt 2015-11-16 14:15:20 +0000 | |||
149 | @@ -17,3 +17,4 @@ | |||
150 | 17 | 17 | ||
151 | 18 | add_subdirectory(MMS) | 18 | add_subdirectory(MMS) |
152 | 19 | add_subdirectory(Dialogs) | 19 | add_subdirectory(Dialogs) |
153 | 20 | add_subdirectory(Stickers) | ||
154 | 20 | 21 | ||
155 | === modified file 'src/qml/Messages.qml' | |||
156 | --- src/qml/Messages.qml 2015-11-12 17:33:30 +0000 | |||
157 | +++ src/qml/Messages.qml 2015-11-16 14:15:20 +0000 | |||
158 | @@ -26,6 +26,7 @@ | |||
159 | 26 | import Ubuntu.Telephony 0.1 | 26 | import Ubuntu.Telephony 0.1 |
160 | 27 | import Ubuntu.Contacts 0.1 | 27 | import Ubuntu.Contacts 0.1 |
161 | 28 | 28 | ||
162 | 29 | import "Stickers" | ||
163 | 29 | import "dateUtils.js" as DateUtils | 30 | import "dateUtils.js" as DateUtils |
164 | 30 | 31 | ||
165 | 31 | Page { | 32 | Page { |
166 | @@ -783,9 +784,26 @@ | |||
167 | 783 | } | 784 | } |
168 | 784 | } | 785 | } |
169 | 785 | 786 | ||
170 | 787 | StickersPicker { | ||
171 | 788 | id: stickersPicker | ||
172 | 789 | anchors.left: parent.left | ||
173 | 790 | anchors.right: parent.right | ||
174 | 791 | anchors.bottom: parent.bottom | ||
175 | 792 | height: keyboard.maximumHeight | ||
176 | 793 | visible: false | ||
177 | 794 | |||
178 | 795 | onStickerSelected: console.log(">>>>>>>>>>>> send:", path) | ||
179 | 796 | |||
180 | 797 | Connections { | ||
181 | 798 | target: Qt.inputMethod | ||
182 | 799 | onVisibleChanged: if (Qt.inputMethod.visible) stickersPicker.visible = false | ||
183 | 800 | } | ||
184 | 801 | } | ||
185 | 802 | |||
186 | 786 | Item { | 803 | Item { |
187 | 787 | id: bottomPanel | 804 | id: bottomPanel |
189 | 788 | anchors.bottom: isSearching ? parent.bottom : keyboard.top | 805 | anchors.bottom: isSearching ? parent.bottom : |
190 | 806 | (Qt.inputMethod.visible ? keyboard.top : stickersPicker.top) | ||
191 | 789 | anchors.left: parent.left | 807 | anchors.left: parent.left |
192 | 790 | anchors.right: parent.right | 808 | anchors.right: parent.right |
193 | 791 | height: selectionMode || (participants.length > 0 && !contactWatcher.interactive) ? 0 : textEntry.height + units.gu(2) | 809 | height: selectionMode || (participants.length > 0 && !contactWatcher.interactive) ? 0 : textEntry.height + units.gu(2) |
194 | @@ -826,6 +844,32 @@ | |||
195 | 826 | } | 844 | } |
196 | 827 | } | 845 | } |
197 | 828 | 846 | ||
198 | 847 | Icon { | ||
199 | 848 | id: stickersButton | ||
200 | 849 | objectName: "stickersButton" | ||
201 | 850 | anchors.left: attachButton.right | ||
202 | 851 | anchors.leftMargin: units.gu(2) | ||
203 | 852 | anchors.verticalCenter: sendButton.verticalCenter | ||
204 | 853 | height: units.gu(3) | ||
205 | 854 | width: units.gu(3) | ||
206 | 855 | color: "gray" | ||
207 | 856 | visible: messageTextArea.activeFocus || stickersPicker.visible | ||
208 | 857 | source: Qt.resolvedUrl("./assets/" + (Qt.inputMethod.visible ? | ||
209 | 858 | "face-smile-big-symbolic-2.svg" : | ||
210 | 859 | "input-keyboard-symbolic.svg")) | ||
211 | 860 | MouseArea { | ||
212 | 861 | anchors.fill: parent | ||
213 | 862 | onClicked: { | ||
214 | 863 | if (Qt.inputMethod.visible) { | ||
215 | 864 | messageTextArea.focus = false | ||
216 | 865 | stickersPicker.visible = true | ||
217 | 866 | } else { | ||
218 | 867 | messageTextArea.forceActiveFocus() | ||
219 | 868 | } | ||
220 | 869 | } | ||
221 | 870 | } | ||
222 | 871 | } | ||
223 | 872 | |||
224 | 829 | StyledItem { | 873 | StyledItem { |
225 | 830 | id: textEntry | 874 | id: textEntry |
226 | 831 | property alias text: messageTextArea.text | 875 | property alias text: messageTextArea.text |
227 | @@ -834,7 +878,7 @@ | |||
228 | 834 | style: Theme.createStyleComponent("TextAreaStyle.qml", textEntry) | 878 | style: Theme.createStyleComponent("TextAreaStyle.qml", textEntry) |
229 | 835 | anchors.bottomMargin: units.gu(1) | 879 | anchors.bottomMargin: units.gu(1) |
230 | 836 | anchors.bottom: parent.bottom | 880 | anchors.bottom: parent.bottom |
232 | 837 | anchors.left: attachButton.right | 881 | anchors.left: stickersButton.visible ? stickersButton.right : attachButton.right |
233 | 838 | anchors.leftMargin: units.gu(1) | 882 | anchors.leftMargin: units.gu(1) |
234 | 839 | anchors.right: sendButton.left | 883 | anchors.right: sendButton.left |
235 | 840 | anchors.rightMargin: units.gu(1) | 884 | anchors.rightMargin: units.gu(1) |
236 | @@ -1045,6 +1089,7 @@ | |||
237 | 1045 | font.pixelSize: FontUtils.sizeToPixels("medium") | 1089 | font.pixelSize: FontUtils.sizeToPixels("medium") |
238 | 1046 | color: "#5d5d5d" | 1090 | color: "#5d5d5d" |
239 | 1047 | text: messages.text | 1091 | text: messages.text |
240 | 1092 | onActiveFocusChanged: if (activeFocus) stickersPicker.visible = false | ||
241 | 1048 | } | 1093 | } |
242 | 1049 | 1094 | ||
243 | 1050 | /*InverseMouseArea { | 1095 | /*InverseMouseArea { |
244 | @@ -1125,6 +1170,14 @@ | |||
245 | 1125 | 1170 | ||
246 | 1126 | KeyboardRectangle { | 1171 | KeyboardRectangle { |
247 | 1127 | id: keyboard | 1172 | id: keyboard |
248 | 1173 | |||
249 | 1174 | // Workaround for not being able to know the keyboard rectangle size | ||
250 | 1175 | // before it has shown at least once: keep matching its height until it | ||
251 | 1176 | // has reached its maximum. | ||
252 | 1177 | property int maximumHeight: 0 | ||
253 | 1178 | onHeightChanged: { | ||
254 | 1179 | if (height > maximumHeight) maximumHeight = height | ||
255 | 1180 | } | ||
256 | 1128 | } | 1181 | } |
257 | 1129 | 1182 | ||
258 | 1130 | MessageInfoDialog { | 1183 | MessageInfoDialog { |
259 | 1131 | 1184 | ||
260 | === added directory 'src/qml/Stickers' | |||
261 | === added file 'src/qml/Stickers/CMakeLists.txt' | |||
262 | --- src/qml/Stickers/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
263 | +++ src/qml/Stickers/CMakeLists.txt 2015-11-16 14:15:20 +0000 | |||
264 | @@ -0,0 +1,4 @@ | |||
265 | 1 | file(GLOB STICKERS_QML_FILES *.qml) | ||
266 | 2 | |||
267 | 3 | add_custom_target(messaging_app_Stickers_QMlFiles ALL SOURCES ${STICKERS_QML_FILES}) | ||
268 | 4 | install(FILES ${STICKERS_QML_FILES} DESTINATION ${MESSAGING_APP_DIR}/Stickers) | ||
269 | 0 | 5 | ||
270 | === added file 'src/qml/Stickers/HistoryButton.qml' | |||
271 | --- src/qml/Stickers/HistoryButton.qml 1970-01-01 00:00:00 +0000 | |||
272 | +++ src/qml/Stickers/HistoryButton.qml 2015-11-16 14:15:20 +0000 | |||
273 | @@ -0,0 +1,35 @@ | |||
274 | 1 | /* | ||
275 | 2 | * Copyright 2015 Canonical Ltd. | ||
276 | 3 | * | ||
277 | 4 | * This file is part of messaging-app. | ||
278 | 5 | * | ||
279 | 6 | * messaging-app is free software; you can redistribute it and/or modify | ||
280 | 7 | * it under the terms of the GNU General Public License as published by | ||
281 | 8 | * the Free Software Foundation; version 3. | ||
282 | 9 | * | ||
283 | 10 | * messaging-app is distributed in the hope that it will be useful, | ||
284 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
285 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
286 | 13 | * GNU General Public License for more details. | ||
287 | 14 | * | ||
288 | 15 | * You should have received a copy of the GNU General Public License | ||
289 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
290 | 17 | */ | ||
291 | 18 | |||
292 | 19 | import QtQuick 2.3 | ||
293 | 20 | import Ubuntu.Components 1.3 | ||
294 | 21 | |||
295 | 22 | AbstractButton { | ||
296 | 23 | property bool selected | ||
297 | 24 | |||
298 | 25 | Rectangle { | ||
299 | 26 | anchors.fill: parent | ||
300 | 27 | color: selected ? "#f5f5f5" : "transparent" | ||
301 | 28 | } | ||
302 | 29 | |||
303 | 30 | Icon { | ||
304 | 31 | name: "history" | ||
305 | 32 | anchors.fill: parent | ||
306 | 33 | anchors.margins: units.gu(1.5) | ||
307 | 34 | } | ||
308 | 35 | } | ||
309 | 0 | 36 | ||
310 | === added file 'src/qml/Stickers/StickerDelegate.qml' | |||
311 | --- src/qml/Stickers/StickerDelegate.qml 1970-01-01 00:00:00 +0000 | |||
312 | +++ src/qml/Stickers/StickerDelegate.qml 2015-11-16 14:15:20 +0000 | |||
313 | @@ -0,0 +1,32 @@ | |||
314 | 1 | /* | ||
315 | 2 | * Copyright 2015 Canonical Ltd. | ||
316 | 3 | * | ||
317 | 4 | * This file is part of messaging-app. | ||
318 | 5 | * | ||
319 | 6 | * messaging-app is free software; you can redistribute it and/or modify | ||
320 | 7 | * it under the terms of the GNU General Public License as published by | ||
321 | 8 | * the Free Software Foundation; version 3. | ||
322 | 9 | * | ||
323 | 10 | * messaging-app is distributed in the hope that it will be useful, | ||
324 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
325 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
326 | 13 | * GNU General Public License for more details. | ||
327 | 14 | * | ||
328 | 15 | * You should have received a copy of the GNU General Public License | ||
329 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
330 | 17 | */ | ||
331 | 18 | |||
332 | 19 | import QtQuick 2.3 | ||
333 | 20 | import Ubuntu.Components 1.3 | ||
334 | 21 | |||
335 | 22 | AbstractButton { | ||
336 | 23 | property alias stickerSource: image.source | ||
337 | 24 | |||
338 | 25 | Image { | ||
339 | 26 | id: image | ||
340 | 27 | anchors.fill: parent | ||
341 | 28 | anchors.margins: units.gu(0.5) | ||
342 | 29 | fillMode: Image.PreserveAspectFit | ||
343 | 30 | smooth: true | ||
344 | 31 | } | ||
345 | 32 | } | ||
346 | 0 | 33 | ||
347 | === added file 'src/qml/Stickers/StickerPackDelegate.qml' | |||
348 | --- src/qml/Stickers/StickerPackDelegate.qml 1970-01-01 00:00:00 +0000 | |||
349 | +++ src/qml/Stickers/StickerPackDelegate.qml 2015-11-16 14:15:20 +0000 | |||
350 | @@ -0,0 +1,53 @@ | |||
351 | 1 | /* | ||
352 | 2 | * Copyright 2015 Canonical Ltd. | ||
353 | 3 | * | ||
354 | 4 | * This file is part of messaging-app. | ||
355 | 5 | * | ||
356 | 6 | * messaging-app is free software; you can redistribute it and/or modify | ||
357 | 7 | * it under the terms of the GNU General Public License as published by | ||
358 | 8 | * the Free Software Foundation; version 3. | ||
359 | 9 | * | ||
360 | 10 | * messaging-app is distributed in the hope that it will be useful, | ||
361 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
362 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
363 | 13 | * GNU General Public License for more details. | ||
364 | 14 | * | ||
365 | 15 | * You should have received a copy of the GNU General Public License | ||
366 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
367 | 17 | */ | ||
368 | 18 | |||
369 | 19 | import QtQuick 2.3 | ||
370 | 20 | import Qt.labs.folderlistmodel 2.1 | ||
371 | 21 | import Ubuntu.Components 1.3 | ||
372 | 22 | |||
373 | 23 | AbstractButton { | ||
374 | 24 | property alias path: stickers.folder | ||
375 | 25 | property string name | ||
376 | 26 | property bool selected | ||
377 | 27 | |||
378 | 28 | Rectangle { | ||
379 | 29 | anchors.fill: parent | ||
380 | 30 | color: selected ? "#f5f5f5" : "transparent" | ||
381 | 31 | } | ||
382 | 32 | |||
383 | 33 | Icon { | ||
384 | 34 | anchors.fill: parent | ||
385 | 35 | visible: stickers.count === 0 | ||
386 | 36 | name: "cancel" | ||
387 | 37 | } | ||
388 | 38 | |||
389 | 39 | Image { | ||
390 | 40 | visible: stickers.count > 0 | ||
391 | 41 | anchors.fill: parent | ||
392 | 42 | anchors.margins: units.gu(0.5) | ||
393 | 43 | fillMode: Image.PreserveAspectFit | ||
394 | 44 | smooth: true | ||
395 | 45 | source: visible ? stickers.get(0, "filePath") : "" | ||
396 | 46 | } | ||
397 | 47 | |||
398 | 48 | FolderListModel { | ||
399 | 49 | id: stickers | ||
400 | 50 | showDirs: false | ||
401 | 51 | nameFilters: ["*.png", "*.webm", "*.gif"] | ||
402 | 52 | } | ||
403 | 53 | } | ||
404 | 0 | 54 | ||
405 | === added file 'src/qml/Stickers/StickerPackModel.qml' | |||
406 | --- src/qml/Stickers/StickerPackModel.qml 1970-01-01 00:00:00 +0000 | |||
407 | +++ src/qml/Stickers/StickerPackModel.qml 2015-11-16 14:15:20 +0000 | |||
408 | @@ -0,0 +1,27 @@ | |||
409 | 1 | /* | ||
410 | 2 | * Copyright 2015 Canonical Ltd. | ||
411 | 3 | * | ||
412 | 4 | * This file is part of messaging-app. | ||
413 | 5 | * | ||
414 | 6 | * messaging-app is free software; you can redistribute it and/or modify | ||
415 | 7 | * it under the terms of the GNU General Public License as published by | ||
416 | 8 | * the Free Software Foundation; version 3. | ||
417 | 9 | * | ||
418 | 10 | * messaging-app is distributed in the hope that it will be useful, | ||
419 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
420 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
421 | 13 | * GNU General Public License for more details. | ||
422 | 14 | * | ||
423 | 15 | * You should have received a copy of the GNU General Public License | ||
424 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
425 | 17 | */ | ||
426 | 18 | |||
427 | 19 | import QtQuick 2.3 | ||
428 | 20 | import Qt.labs.folderlistmodel 2.1 | ||
429 | 21 | |||
430 | 22 | FolderListModel { | ||
431 | 23 | property string packName | ||
432 | 24 | folder: "%1/stickers/%2".arg(dataLocation).arg(packName) | ||
433 | 25 | showDirs: false | ||
434 | 26 | nameFilters: ["*.png", "*.webm", "*.gif"] | ||
435 | 27 | } | ||
436 | 0 | 28 | ||
437 | === added file 'src/qml/Stickers/StickerPacksModel.qml' | |||
438 | --- src/qml/Stickers/StickerPacksModel.qml 1970-01-01 00:00:00 +0000 | |||
439 | +++ src/qml/Stickers/StickerPacksModel.qml 2015-11-16 14:15:20 +0000 | |||
440 | @@ -0,0 +1,25 @@ | |||
441 | 1 | /* | ||
442 | 2 | * Copyright 2015 Canonical Ltd. | ||
443 | 3 | * | ||
444 | 4 | * This file is part of messaging-app. | ||
445 | 5 | * | ||
446 | 6 | * messaging-app is free software; you can redistribute it and/or modify | ||
447 | 7 | * it under the terms of the GNU General Public License as published by | ||
448 | 8 | * the Free Software Foundation; version 3. | ||
449 | 9 | * | ||
450 | 10 | * messaging-app is distributed in the hope that it will be useful, | ||
451 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
452 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
453 | 13 | * GNU General Public License for more details. | ||
454 | 14 | * | ||
455 | 15 | * You should have received a copy of the GNU General Public License | ||
456 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
457 | 17 | */ | ||
458 | 18 | |||
459 | 19 | import QtQuick 2.3 | ||
460 | 20 | import Qt.labs.folderlistmodel 2.1 | ||
461 | 21 | |||
462 | 22 | FolderListModel { | ||
463 | 23 | folder: dataLocation + "/stickers/" | ||
464 | 24 | showFiles: false | ||
465 | 25 | } | ||
466 | 0 | 26 | ||
467 | === added file 'src/qml/Stickers/StickersPicker.qml' | |||
468 | --- src/qml/Stickers/StickersPicker.qml 1970-01-01 00:00:00 +0000 | |||
469 | +++ src/qml/Stickers/StickersPicker.qml 2015-11-16 14:15:20 +0000 | |||
470 | @@ -0,0 +1,112 @@ | |||
471 | 1 | /* | ||
472 | 2 | * Copyright 2015 Canonical Ltd. | ||
473 | 3 | * | ||
474 | 4 | * This file is part of messaging-app. | ||
475 | 5 | * | ||
476 | 6 | * messaging-app is free software; you can redistribute it and/or modify | ||
477 | 7 | * it under the terms of the GNU General Public License as published by | ||
478 | 8 | * the Free Software Foundation; version 3. | ||
479 | 9 | * | ||
480 | 10 | * messaging-app is distributed in the hope that it will be useful, | ||
481 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
482 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
483 | 13 | * GNU General Public License for more details. | ||
484 | 14 | * | ||
485 | 15 | * You should have received a copy of the GNU General Public License | ||
486 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
487 | 17 | */ | ||
488 | 18 | |||
489 | 19 | import QtQuick 2.3 | ||
490 | 20 | import Ubuntu.Components 1.3 | ||
491 | 21 | import messagingapp.private 0.1 | ||
492 | 22 | |||
493 | 23 | FocusScope { | ||
494 | 24 | id: pickerRoot | ||
495 | 25 | signal stickerSelected(string path) | ||
496 | 26 | |||
497 | 27 | Component.onCompleted: { | ||
498 | 28 | StickersHistoryModel.databasePath = dataLocation + "/stickers/stickers.sqlite" | ||
499 | 29 | StickersHistoryModel.limit = 10 | ||
500 | 30 | } | ||
501 | 31 | |||
502 | 32 | ListView { | ||
503 | 33 | id: setsList | ||
504 | 34 | model: StickerPacksModel {} | ||
505 | 35 | orientation: ListView.Horizontal | ||
506 | 36 | anchors.left: parent.left | ||
507 | 37 | anchors.right: parent.right | ||
508 | 38 | anchors.top: parent.top | ||
509 | 39 | height: units.gu(6) | ||
510 | 40 | |||
511 | 41 | header: HistoryButton { | ||
512 | 42 | height: units.gu(6) | ||
513 | 43 | width: height | ||
514 | 44 | |||
515 | 45 | onTriggered: stickersGrid.model.packName = "" | ||
516 | 46 | selected: stickersGrid.model.packName === "" | ||
517 | 47 | } | ||
518 | 48 | delegate: StickerPackDelegate { | ||
519 | 49 | anchors.top: parent.top | ||
520 | 50 | anchors.bottom: parent.bottom | ||
521 | 51 | width: units.gu(6) | ||
522 | 52 | |||
523 | 53 | path: filePath | ||
524 | 54 | onTriggered: stickersGrid.model.packName = fileName | ||
525 | 55 | selected: stickersGrid.model.packName === fileName | ||
526 | 56 | } | ||
527 | 57 | } | ||
528 | 58 | |||
529 | 59 | Rectangle { | ||
530 | 60 | anchors.fill: stickersGrid | ||
531 | 61 | color: "#f5f5f5" | ||
532 | 62 | } | ||
533 | 63 | |||
534 | 64 | GridView { | ||
535 | 65 | id: stickersGrid | ||
536 | 66 | anchors.left: parent.left | ||
537 | 67 | anchors.right: parent.right | ||
538 | 68 | anchors.top: setsList.bottom | ||
539 | 69 | anchors.bottom: parent.bottom | ||
540 | 70 | clip: true | ||
541 | 71 | cellWidth: units.gu(10) | ||
542 | 72 | cellHeight: units.gu(10) | ||
543 | 73 | visible: stickersGrid.model.packName.length > 0 | ||
544 | 74 | |||
545 | 75 | model: StickerPackModel { } | ||
546 | 76 | delegate: StickerDelegate { | ||
547 | 77 | stickerSource: filePath | ||
548 | 78 | width: stickersGrid.cellWidth | ||
549 | 79 | height: stickersGrid.cellHeight | ||
550 | 80 | |||
551 | 81 | onTriggered: { | ||
552 | 82 | StickersHistoryModel.add("%1/%2".arg(stickersGrid.model.packName).arg(fileName)) | ||
553 | 83 | pickerRoot.stickerSelected(stickerSource) | ||
554 | 84 | } | ||
555 | 85 | } | ||
556 | 86 | } | ||
557 | 87 | |||
558 | 88 | GridView { | ||
559 | 89 | id: historyGrid | ||
560 | 90 | anchors.left: parent.left | ||
561 | 91 | anchors.right: parent.right | ||
562 | 92 | anchors.top: setsList.bottom | ||
563 | 93 | anchors.bottom: parent.bottom | ||
564 | 94 | clip: true | ||
565 | 95 | cellWidth: units.gu(10) | ||
566 | 96 | cellHeight: units.gu(10) | ||
567 | 97 | visible: stickersGrid.model.packName.length === 0 | ||
568 | 98 | |||
569 | 99 | model: StickersHistoryModel | ||
570 | 100 | |||
571 | 101 | delegate: StickerDelegate { | ||
572 | 102 | stickerSource: "%1/stickers/%2".arg(dataLocation).arg(sticker) | ||
573 | 103 | width: stickersGrid.cellWidth | ||
574 | 104 | height: stickersGrid.cellHeight | ||
575 | 105 | |||
576 | 106 | onTriggered: { | ||
577 | 107 | StickersHistoryModel.add(sticker) | ||
578 | 108 | pickerRoot.stickerSelected(stickerSource) | ||
579 | 109 | } | ||
580 | 110 | } | ||
581 | 111 | } | ||
582 | 112 | } | ||
583 | 0 | 113 | ||
584 | === added file 'src/qml/assets/face-smile-big-symbolic-2.svg' | |||
585 | --- src/qml/assets/face-smile-big-symbolic-2.svg 1970-01-01 00:00:00 +0000 | |||
586 | +++ src/qml/assets/face-smile-big-symbolic-2.svg 2015-11-16 14:15:20 +0000 | |||
587 | @@ -0,0 +1,182 @@ | |||
588 | 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
589 | 2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||
590 | 3 | |||
591 | 4 | <svg | ||
592 | 5 | xmlns:dc="http://purl.org/dc/elements/1.1/" | ||
593 | 6 | xmlns:cc="http://creativecommons.org/ns#" | ||
594 | 7 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||
595 | 8 | xmlns:svg="http://www.w3.org/2000/svg" | ||
596 | 9 | xmlns="http://www.w3.org/2000/svg" | ||
597 | 10 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||
598 | 11 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||
599 | 12 | width="96" | ||
600 | 13 | height="96" | ||
601 | 14 | id="svg4874" | ||
602 | 15 | version="1.1" | ||
603 | 16 | inkscape:version="0.91+devel r" | ||
604 | 17 | viewBox="0 0 96 96.000001" | ||
605 | 18 | sodipodi:docname="face-smile-big-symbolic.svg"> | ||
606 | 19 | <defs | ||
607 | 20 | id="defs4876" /> | ||
608 | 21 | <sodipodi:namedview | ||
609 | 22 | id="base" | ||
610 | 23 | pagecolor="#ffffff" | ||
611 | 24 | bordercolor="#666666" | ||
612 | 25 | borderopacity="1.0" | ||
613 | 26 | inkscape:pageopacity="0.0" | ||
614 | 27 | inkscape:pageshadow="2" | ||
615 | 28 | inkscape:zoom="2.8774396" | ||
616 | 29 | inkscape:cx="-93.086241" | ||
617 | 30 | inkscape:cy="47.64648" | ||
618 | 31 | inkscape:document-units="px" | ||
619 | 32 | inkscape:current-layer="g4780" | ||
620 | 33 | showgrid="true" | ||
621 | 34 | showborder="true" | ||
622 | 35 | fit-margin-top="0" | ||
623 | 36 | fit-margin-left="0" | ||
624 | 37 | fit-margin-right="0" | ||
625 | 38 | fit-margin-bottom="0" | ||
626 | 39 | inkscape:snap-bbox="true" | ||
627 | 40 | inkscape:bbox-paths="true" | ||
628 | 41 | inkscape:bbox-nodes="true" | ||
629 | 42 | inkscape:snap-bbox-edge-midpoints="true" | ||
630 | 43 | inkscape:snap-bbox-midpoints="true" | ||
631 | 44 | inkscape:object-paths="true" | ||
632 | 45 | inkscape:snap-intersection-paths="true" | ||
633 | 46 | inkscape:object-nodes="true" | ||
634 | 47 | inkscape:snap-smooth-nodes="true" | ||
635 | 48 | inkscape:snap-midpoints="true" | ||
636 | 49 | inkscape:snap-object-midpoints="true" | ||
637 | 50 | inkscape:snap-center="true" | ||
638 | 51 | showguides="true" | ||
639 | 52 | inkscape:guide-bbox="true"> | ||
640 | 53 | <inkscape:grid | ||
641 | 54 | type="xygrid" | ||
642 | 55 | id="grid5451" | ||
643 | 56 | empspacing="8" /> | ||
644 | 57 | <sodipodi:guide | ||
645 | 58 | orientation="1,0" | ||
646 | 59 | position="8,-8.0000001" | ||
647 | 60 | id="guide4063" /> | ||
648 | 61 | <sodipodi:guide | ||
649 | 62 | orientation="1,0" | ||
650 | 63 | position="4,-8.0000001" | ||
651 | 64 | id="guide4065" /> | ||
652 | 65 | <sodipodi:guide | ||
653 | 66 | orientation="0,1" | ||
654 | 67 | position="-8,88.000001" | ||
655 | 68 | id="guide4067" /> | ||
656 | 69 | <sodipodi:guide | ||
657 | 70 | orientation="0,1" | ||
658 | 71 | position="-8,92.000001" | ||
659 | 72 | id="guide4069" /> | ||
660 | 73 | <sodipodi:guide | ||
661 | 74 | orientation="0,1" | ||
662 | 75 | position="104,4" | ||
663 | 76 | id="guide4071" /> | ||
664 | 77 | <sodipodi:guide | ||
665 | 78 | orientation="0,1" | ||
666 | 79 | position="-5,8.0000001" | ||
667 | 80 | id="guide4073" /> | ||
668 | 81 | <sodipodi:guide | ||
669 | 82 | orientation="1,0" | ||
670 | 83 | position="92,-8.0000001" | ||
671 | 84 | id="guide4075" /> | ||
672 | 85 | <sodipodi:guide | ||
673 | 86 | orientation="1,0" | ||
674 | 87 | position="88,-8.0000001" | ||
675 | 88 | id="guide4077" /> | ||
676 | 89 | <sodipodi:guide | ||
677 | 90 | orientation="0,1" | ||
678 | 91 | position="-8,84.000001" | ||
679 | 92 | id="guide4074" /> | ||
680 | 93 | <sodipodi:guide | ||
681 | 94 | orientation="1,0" | ||
682 | 95 | position="12,-8.0000001" | ||
683 | 96 | id="guide4076" /> | ||
684 | 97 | <sodipodi:guide | ||
685 | 98 | orientation="0,1" | ||
686 | 99 | position="-5,12" | ||
687 | 100 | id="guide4078" /> | ||
688 | 101 | <sodipodi:guide | ||
689 | 102 | orientation="1,0" | ||
690 | 103 | position="84,-9.0000001" | ||
691 | 104 | id="guide4080" /> | ||
692 | 105 | <sodipodi:guide | ||
693 | 106 | position="48,-8.0000001" | ||
694 | 107 | orientation="1,0" | ||
695 | 108 | id="guide4170" /> | ||
696 | 109 | <sodipodi:guide | ||
697 | 110 | position="-8,48" | ||
698 | 111 | orientation="0,1" | ||
699 | 112 | id="guide4172" /> | ||
700 | 113 | </sodipodi:namedview> | ||
701 | 114 | <metadata | ||
702 | 115 | id="metadata4879"> | ||
703 | 116 | <rdf:RDF> | ||
704 | 117 | <cc:Work | ||
705 | 118 | rdf:about=""> | ||
706 | 119 | <dc:format>image/svg+xml</dc:format> | ||
707 | 120 | <dc:type | ||
708 | 121 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||
709 | 122 | <dc:title></dc:title> | ||
710 | 123 | </cc:Work> | ||
711 | 124 | </rdf:RDF> | ||
712 | 125 | </metadata> | ||
713 | 126 | <g | ||
714 | 127 | inkscape:label="Layer 1" | ||
715 | 128 | inkscape:groupmode="layer" | ||
716 | 129 | id="layer1" | ||
717 | 130 | transform="translate(67.857146,-78.50504)"> | ||
718 | 131 | <g | ||
719 | 132 | transform="matrix(0,-1,-1,0,373.50506,516.50504)" | ||
720 | 133 | id="g4845" | ||
721 | 134 | style="display:inline"> | ||
722 | 135 | <g | ||
723 | 136 | inkscape:export-ydpi="90" | ||
724 | 137 | inkscape:export-xdpi="90" | ||
725 | 138 | inkscape:export-filename="next01.png" | ||
726 | 139 | transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)" | ||
727 | 140 | id="g4778" | ||
728 | 141 | inkscape:label="Layer 1"> | ||
729 | 142 | <g | ||
730 | 143 | transform="matrix(-1,0,0,1,575.99999,611)" | ||
731 | 144 | id="g4780" | ||
732 | 145 | style="display:inline"> | ||
733 | 146 | <rect | ||
734 | 147 | style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate" | ||
735 | 148 | id="rect4782" | ||
736 | 149 | width="96.037987" | ||
737 | 150 | height="96" | ||
738 | 151 | x="-438.00244" | ||
739 | 152 | y="345.36221" | ||
740 | 153 | transform="scale(-1,1)" /> | ||
741 | 154 | <path | ||
742 | 155 | style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079107;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" | ||
743 | 156 | d="m 432,393.36133 c 0,23.17236 -18.83538,42 -42.01562,42 -23.18025,0 -42.01563,-18.82764 -42.01563,-42 0,-23.17236 18.83538,-42 42.01563,-42 23.18024,0 42.01562,18.82764 42.01562,42 z m -4.00195,0 c 0,-21.00932 -16.99476,-37.99805 -38.01367,-37.99805 -21.01892,0 -38.01563,16.98873 -38.01563,37.99805 0,21.00931 16.99671,37.99804 38.01563,37.99805 21.01891,0 38.01367,-16.98874 38.01367,-37.99805 z" | ||
744 | 157 | id="path4116" | ||
745 | 158 | inkscape:connector-curvature="0" /> | ||
746 | 159 | <path | ||
747 | 160 | style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:64.01265717;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" | ||
748 | 161 | d="m 404.99002,409.36281 1.50057,-8.00059 -13.50534,0 0,8.00059 z" | ||
749 | 162 | id="rect4175" | ||
750 | 163 | inkscape:connector-curvature="0" | ||
751 | 164 | sodipodi:nodetypes="ccccc" /> | ||
752 | 165 | <path | ||
753 | 166 | sodipodi:nodetypes="ccccc" | ||
754 | 167 | inkscape:connector-curvature="0" | ||
755 | 168 | id="path4178" | ||
756 | 169 | d="m 404.99002,385.36222 1.50057,-7.99941 -13.50534,0 0,7.99941 z" | ||
757 | 170 | style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:64.01265717;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /> | ||
758 | 171 | <path | ||
759 | 172 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:'Ubuntu, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#808080;fill-opacity:1;stroke:none;stroke-width:1.00019777px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | ||
760 | 173 | d="m 383.98169,414.37529 c -1.5268,-0.21155 -2.98748,-0.52576 -4.37873,-0.94375 -2.81692,-0.88674 -5.23617,-2.19676 -7.25967,-3.92985 -2.0236,-1.77325 -3.59002,-3.99099 -4.70116,-6.65098 -1.11104,-2.70036 -1.66756,-5.86393 -1.66756,-9.49118 0,-3.62725 0.55652,-6.77166 1.66756,-9.43164 1.11114,-2.70027 2.67756,-4.91499 4.70116,-6.64799 2.0235,-1.77334 4.44275,-3.0835 7.25967,-3.92986 1.39125,-0.4379 2.85193,-0.76678 4.37873,-0.98841 l 0,42.01366 z" | ||
761 | 174 | id="path4190" | ||
762 | 175 | inkscape:connector-curvature="0" | ||
763 | 176 | inkscape:transform-center-x="0.0068360001" | ||
764 | 177 | inkscape:transform-center-y="-9.0000001" /> | ||
765 | 178 | </g> | ||
766 | 179 | </g> | ||
767 | 180 | </g> | ||
768 | 181 | </g> | ||
769 | 182 | </svg> | ||
770 | 0 | 183 | ||
771 | === added file 'src/qml/assets/history.svg' | |||
772 | --- src/qml/assets/history.svg 1970-01-01 00:00:00 +0000 | |||
773 | +++ src/qml/assets/history.svg 2015-11-16 14:15:20 +0000 | |||
774 | @@ -0,0 +1,173 @@ | |||
775 | 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
776 | 2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||
777 | 3 | |||
778 | 4 | <svg | ||
779 | 5 | xmlns:dc="http://purl.org/dc/elements/1.1/" | ||
780 | 6 | xmlns:cc="http://creativecommons.org/ns#" | ||
781 | 7 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||
782 | 8 | xmlns:svg="http://www.w3.org/2000/svg" | ||
783 | 9 | xmlns="http://www.w3.org/2000/svg" | ||
784 | 10 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||
785 | 11 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||
786 | 12 | width="96" | ||
787 | 13 | height="96" | ||
788 | 14 | id="svg4874" | ||
789 | 15 | version="1.1" | ||
790 | 16 | inkscape:version="0.91+devel r" | ||
791 | 17 | viewBox="0 0 96 96.000001" | ||
792 | 18 | sodipodi:docname="history.svg"> | ||
793 | 19 | <defs | ||
794 | 20 | id="defs4876" /> | ||
795 | 21 | <sodipodi:namedview | ||
796 | 22 | id="base" | ||
797 | 23 | pagecolor="#ffffff" | ||
798 | 24 | bordercolor="#666666" | ||
799 | 25 | borderopacity="1.0" | ||
800 | 26 | inkscape:pageopacity="0.0" | ||
801 | 27 | inkscape:pageshadow="2" | ||
802 | 28 | inkscape:zoom="8.7812488" | ||
803 | 29 | inkscape:cx="12.412809" | ||
804 | 30 | inkscape:cy="56.142342" | ||
805 | 31 | inkscape:document-units="px" | ||
806 | 32 | inkscape:current-layer="g4780" | ||
807 | 33 | showgrid="true" | ||
808 | 34 | showborder="true" | ||
809 | 35 | fit-margin-top="0" | ||
810 | 36 | fit-margin-left="0" | ||
811 | 37 | fit-margin-right="0" | ||
812 | 38 | fit-margin-bottom="0" | ||
813 | 39 | inkscape:snap-bbox="true" | ||
814 | 40 | inkscape:bbox-paths="true" | ||
815 | 41 | inkscape:bbox-nodes="true" | ||
816 | 42 | inkscape:snap-bbox-edge-midpoints="true" | ||
817 | 43 | inkscape:snap-bbox-midpoints="true" | ||
818 | 44 | inkscape:object-paths="true" | ||
819 | 45 | inkscape:snap-intersection-paths="true" | ||
820 | 46 | inkscape:object-nodes="true" | ||
821 | 47 | inkscape:snap-smooth-nodes="true" | ||
822 | 48 | inkscape:snap-midpoints="true" | ||
823 | 49 | inkscape:snap-object-midpoints="true" | ||
824 | 50 | inkscape:snap-center="true" | ||
825 | 51 | showguides="true" | ||
826 | 52 | inkscape:guide-bbox="true"> | ||
827 | 53 | <inkscape:grid | ||
828 | 54 | type="xygrid" | ||
829 | 55 | id="grid5451" | ||
830 | 56 | empspacing="8" /> | ||
831 | 57 | <sodipodi:guide | ||
832 | 58 | orientation="1,0" | ||
833 | 59 | position="8,-8.0000001" | ||
834 | 60 | id="guide4063" /> | ||
835 | 61 | <sodipodi:guide | ||
836 | 62 | orientation="1,0" | ||
837 | 63 | position="4,-8.0000001" | ||
838 | 64 | id="guide4065" /> | ||
839 | 65 | <sodipodi:guide | ||
840 | 66 | orientation="0,1" | ||
841 | 67 | position="-8,88.000001" | ||
842 | 68 | id="guide4067" /> | ||
843 | 69 | <sodipodi:guide | ||
844 | 70 | orientation="0,1" | ||
845 | 71 | position="-8,92.000001" | ||
846 | 72 | id="guide4069" /> | ||
847 | 73 | <sodipodi:guide | ||
848 | 74 | orientation="0,1" | ||
849 | 75 | position="104,4" | ||
850 | 76 | id="guide4071" /> | ||
851 | 77 | <sodipodi:guide | ||
852 | 78 | orientation="0,1" | ||
853 | 79 | position="-5,8.0000001" | ||
854 | 80 | id="guide4073" /> | ||
855 | 81 | <sodipodi:guide | ||
856 | 82 | orientation="1,0" | ||
857 | 83 | position="92,-8.0000001" | ||
858 | 84 | id="guide4075" /> | ||
859 | 85 | <sodipodi:guide | ||
860 | 86 | orientation="1,0" | ||
861 | 87 | position="88,-8.0000001" | ||
862 | 88 | id="guide4077" /> | ||
863 | 89 | <sodipodi:guide | ||
864 | 90 | orientation="0,1" | ||
865 | 91 | position="-8,84.000001" | ||
866 | 92 | id="guide4074" /> | ||
867 | 93 | <sodipodi:guide | ||
868 | 94 | orientation="1,0" | ||
869 | 95 | position="12,-8.0000001" | ||
870 | 96 | id="guide4076" /> | ||
871 | 97 | <sodipodi:guide | ||
872 | 98 | orientation="0,1" | ||
873 | 99 | position="-5,12" | ||
874 | 100 | id="guide4078" /> | ||
875 | 101 | <sodipodi:guide | ||
876 | 102 | orientation="1,0" | ||
877 | 103 | position="84,-9.0000001" | ||
878 | 104 | id="guide4080" /> | ||
879 | 105 | <sodipodi:guide | ||
880 | 106 | position="48,-8.0000001" | ||
881 | 107 | orientation="1,0" | ||
882 | 108 | id="guide4170" /> | ||
883 | 109 | <sodipodi:guide | ||
884 | 110 | position="-8,48" | ||
885 | 111 | orientation="0,1" | ||
886 | 112 | id="guide4172" /> | ||
887 | 113 | </sodipodi:namedview> | ||
888 | 114 | <metadata | ||
889 | 115 | id="metadata4879"> | ||
890 | 116 | <rdf:RDF> | ||
891 | 117 | <cc:Work | ||
892 | 118 | rdf:about=""> | ||
893 | 119 | <dc:format>image/svg+xml</dc:format> | ||
894 | 120 | <dc:type | ||
895 | 121 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||
896 | 122 | <dc:title></dc:title> | ||
897 | 123 | </cc:Work> | ||
898 | 124 | </rdf:RDF> | ||
899 | 125 | </metadata> | ||
900 | 126 | <g | ||
901 | 127 | inkscape:label="Layer 1" | ||
902 | 128 | inkscape:groupmode="layer" | ||
903 | 129 | id="layer1" | ||
904 | 130 | transform="translate(67.857146,-78.50504)"> | ||
905 | 131 | <g | ||
906 | 132 | transform="matrix(0,-1,-1,0,373.50506,516.50504)" | ||
907 | 133 | id="g4845" | ||
908 | 134 | style="display:inline"> | ||
909 | 135 | <g | ||
910 | 136 | inkscape:export-ydpi="90" | ||
911 | 137 | inkscape:export-xdpi="90" | ||
912 | 138 | inkscape:export-filename="next01.png" | ||
913 | 139 | transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)" | ||
914 | 140 | id="g4778" | ||
915 | 141 | inkscape:label="Layer 1"> | ||
916 | 142 | <g | ||
917 | 143 | transform="matrix(-1,0,0,1,575.99999,611)" | ||
918 | 144 | id="g4780" | ||
919 | 145 | style="display:inline"> | ||
920 | 146 | <rect | ||
921 | 147 | style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate" | ||
922 | 148 | id="rect4782" | ||
923 | 149 | width="96.037987" | ||
924 | 150 | height="96" | ||
925 | 151 | x="-438.00244" | ||
926 | 152 | y="345.36221" | ||
927 | 153 | transform="scale(-1,1)" /> | ||
928 | 154 | <path | ||
929 | 155 | style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079107;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" | ||
930 | 156 | d="m 420.87891,421.82617 c -13.02519,14.12639 -34.00962,17.61704 -50.90821,8.4668 -16.89858,-9.15024 -25.43667,-28.62704 -20.71484,-47.25 4.72183,-18.62296 21.51014,-31.68164 40.72852,-31.68164 l 0,4.00195 c -17.40844,0 -32.5749,11.79684 -36.85157,28.66406 -4.27667,16.86723 3.43743,34.45783 18.74414,42.7461 15.30671,8.28827 34.26279,5.13698 46.06055,-7.65821 l 2.94141,2.71094 z" | ||
931 | 157 | id="path4116" | ||
932 | 158 | inkscape:connector-curvature="0" /> | ||
933 | 159 | <path | ||
934 | 160 | style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079107;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:8.00158199, 8.00158199;stroke-dashoffset:1.60031641;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" | ||
935 | 161 | d="m 431.99414,394.00977 -0.0137,0.42968 -3.99805,-0.13281 0.0137,-0.42187 0,-0.008 -0.006,-1.35937 0,-0.0254 -0.0527,-1.31446 -0.002,-0.0254 -0.10352,-1.36328 -0.002,-0.01 -0.16016,-1.41016 -0.20312,-1.34961 -0.004,-0.0215 -0.041,-0.21875 3.93164,-0.74414 0.0449,0.24023 0.0117,0.0723 0.2207,1.45703 0.01,0.0723 0.16602,1.45899 0.008,0.0742 0.11133,1.46093 0.006,0.0723 0.0586,1.46094 0,0.0723 0.006,1.45899 z m -1.11914,9.00195 -0.0156,0.0703 -0.36133,1.4082 -0.0195,0.0684 -0.41211,1.39453 -0.0215,0.0703 -0.46289,1.3789 -0.0234,0.0703 -0.51367,1.36328 -0.0273,0.0684 -0.5625,1.3457 -0.0293,0.0664 -0.17969,0.38867 -3.63281,-1.67774 0.15039,-0.32226 0.0137,-0.0312 0.54493,-1.30274 0.004,-0.0117 0.48242,-1.28516 0.004,-0.0117 0.42773,-1.27734 0.40039,-1.35938 0.3418,-1.33789 0.0469,-0.2168 3.9082,0.85352 z m -5.52344,-23.56055 -0.25,-0.63476 -0.0117,-0.0312 -0.54492,-1.24805 -0.0156,-0.0312 -0.60352,-1.25586 -0.0137,-0.0254 -0.68359,-1.29297 -0.002,-0.004 -0.6914,-1.19531 -0.0176,-0.0293 -0.64453,-1.02343 3.38672,-2.12891 0.68359,1.08789 0.0391,0.0625 0.74414,1.28906 0.0371,0.0664 0.69922,1.32227 0.0332,0.0664 0.6543,1.35547 0.0312,0.0684 0.60547,1.38477 0.0273,0.0703 0.26172,0.66601 z m -1.52929,38.8086 -0.0449,0.0605 -0.90625,1.18164 -0.0469,0.0566 -0.95313,1.15235 -0.0488,0.0566 -1.00196,1.12304 -0.0527,0.0547 -1.04883,1.08789 -2.88086,-2.77539 1.02344,-1.06054 0.92773,-1.03711 0.0234,-0.0274 0.88477,-1.0664 0.0215,-0.0274 0.86719,-1.13086 0.0176,-0.0234 0.1875,-0.26563 3.26171,2.31445 z m -6.66993,-51.46875 -0.68554,-0.68946 -0.0215,-0.0215 -0.99219,-0.92774 -0.0195,-0.0176 -0.98828,-0.85938 -0.0117,-0.01 -1.11132,-0.89648 -0.008,-0.008 -1.04687,-0.78516 -0.0176,-0.0117 -0.94922,-0.66015 2.28125,-3.28711 0.9668,0.67187 0.0586,0.043 1.16406,0.87109 0.0566,0.0449 1.13086,0.91406 0.0566,0.0469 1.09766,0.95508 0.0547,0.0488 1.06445,0.99609 0.0527,0.0508 0.70507,0.71093 z m -12.49609,-8.47852 -0.86523,-0.35547 -0.0176,-0.006 -1.32813,-0.49023 -0.0254,-0.01 -1.29101,-0.41992 -1.30469,-0.375 -0.0156,-0.004 -1.39843,-0.3457 -0.0156,-0.004 -1.02734,-0.21289 0.81445,-3.91601 1.10156,0.22851 0.0703,0.0156 1.43164,0.35351 0.0703,0.0195 1.41211,0.40429 0.0703,0.0215 1.39258,0.45508 0.0703,0.0254 1.3711,0.5039 0.0684,0.0274 0.9336,0.38281 z" | ||
936 | 162 | id="ellipse4178" | ||
937 | 163 | inkscape:connector-curvature="0" /> | ||
938 | 164 | <path | ||
939 | 165 | style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079107;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.5999999;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" | ||
940 | 166 | d="m 387.98242,367.36133 0,26.83008 20.5957,20.58593 2.82813,-2.83007 -19.42187,-19.41407 0,-25.17187 -4.00196,0 z" | ||
941 | 167 | id="path4180" | ||
942 | 168 | inkscape:connector-curvature="0" /> | ||
943 | 169 | </g> | ||
944 | 170 | </g> | ||
945 | 171 | </g> | ||
946 | 172 | </g> | ||
947 | 173 | </svg> | ||
948 | 0 | 174 | ||
949 | === added file 'src/qml/assets/input-keyboard-symbolic.svg' | |||
950 | --- src/qml/assets/input-keyboard-symbolic.svg 1970-01-01 00:00:00 +0000 | |||
951 | +++ src/qml/assets/input-keyboard-symbolic.svg 2015-11-16 14:15:20 +0000 | |||
952 | @@ -0,0 +1,221 @@ | |||
953 | 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
954 | 2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||
955 | 3 | |||
956 | 4 | <svg | ||
957 | 5 | xmlns:dc="http://purl.org/dc/elements/1.1/" | ||
958 | 6 | xmlns:cc="http://creativecommons.org/ns#" | ||
959 | 7 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||
960 | 8 | xmlns:svg="http://www.w3.org/2000/svg" | ||
961 | 9 | xmlns="http://www.w3.org/2000/svg" | ||
962 | 10 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||
963 | 11 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||
964 | 12 | width="96" | ||
965 | 13 | height="96" | ||
966 | 14 | id="svg4874" | ||
967 | 15 | version="1.1" | ||
968 | 16 | inkscape:version="0.91+devel r" | ||
969 | 17 | viewBox="0 0 96 96.000001" | ||
970 | 18 | sodipodi:docname="input-keyboard-symbolic.svg"> | ||
971 | 19 | <defs | ||
972 | 20 | id="defs4876" /> | ||
973 | 21 | <sodipodi:namedview | ||
974 | 22 | id="base" | ||
975 | 23 | pagecolor="#ffffff" | ||
976 | 24 | bordercolor="#666666" | ||
977 | 25 | borderopacity="1.0" | ||
978 | 26 | inkscape:pageopacity="0.0" | ||
979 | 27 | inkscape:pageshadow="2" | ||
980 | 28 | inkscape:zoom="7.0249992" | ||
981 | 29 | inkscape:cx="12.362986" | ||
982 | 30 | inkscape:cy="54.10675" | ||
983 | 31 | inkscape:document-units="px" | ||
984 | 32 | inkscape:current-layer="g4780" | ||
985 | 33 | showgrid="true" | ||
986 | 34 | showborder="true" | ||
987 | 35 | fit-margin-top="0" | ||
988 | 36 | fit-margin-left="0" | ||
989 | 37 | fit-margin-right="0" | ||
990 | 38 | fit-margin-bottom="0" | ||
991 | 39 | inkscape:snap-bbox="true" | ||
992 | 40 | inkscape:bbox-paths="true" | ||
993 | 41 | inkscape:bbox-nodes="true" | ||
994 | 42 | inkscape:snap-bbox-edge-midpoints="true" | ||
995 | 43 | inkscape:snap-bbox-midpoints="true" | ||
996 | 44 | inkscape:object-paths="true" | ||
997 | 45 | inkscape:snap-intersection-paths="true" | ||
998 | 46 | inkscape:object-nodes="true" | ||
999 | 47 | inkscape:snap-smooth-nodes="true" | ||
1000 | 48 | inkscape:snap-midpoints="true" | ||
1001 | 49 | inkscape:snap-object-midpoints="true" | ||
1002 | 50 | inkscape:snap-center="true" | ||
1003 | 51 | showguides="true" | ||
1004 | 52 | inkscape:guide-bbox="true" | ||
1005 | 53 | inkscape:snap-global="true"> | ||
1006 | 54 | <inkscape:grid | ||
1007 | 55 | type="xygrid" | ||
1008 | 56 | id="grid5451" | ||
1009 | 57 | empspacing="8" /> | ||
1010 | 58 | <sodipodi:guide | ||
1011 | 59 | orientation="1,0" | ||
1012 | 60 | position="8,-8.0000001" | ||
1013 | 61 | id="guide4063" /> | ||
1014 | 62 | <sodipodi:guide | ||
1015 | 63 | orientation="1,0" | ||
1016 | 64 | position="4,-8.0000001" | ||
1017 | 65 | id="guide4065" /> | ||
1018 | 66 | <sodipodi:guide | ||
1019 | 67 | orientation="0,1" | ||
1020 | 68 | position="-8,88.000001" | ||
1021 | 69 | id="guide4067" /> | ||
1022 | 70 | <sodipodi:guide | ||
1023 | 71 | orientation="0,1" | ||
1024 | 72 | position="-8,92.000001" | ||
1025 | 73 | id="guide4069" /> | ||
1026 | 74 | <sodipodi:guide | ||
1027 | 75 | orientation="0,1" | ||
1028 | 76 | position="104,4" | ||
1029 | 77 | id="guide4071" /> | ||
1030 | 78 | <sodipodi:guide | ||
1031 | 79 | orientation="0,1" | ||
1032 | 80 | position="-5,8.0000001" | ||
1033 | 81 | id="guide4073" /> | ||
1034 | 82 | <sodipodi:guide | ||
1035 | 83 | orientation="1,0" | ||
1036 | 84 | position="88,-8.0000001" | ||
1037 | 85 | id="guide4077" /> | ||
1038 | 86 | <sodipodi:guide | ||
1039 | 87 | orientation="0,1" | ||
1040 | 88 | position="-8,84.000001" | ||
1041 | 89 | id="guide4074" /> | ||
1042 | 90 | <sodipodi:guide | ||
1043 | 91 | orientation="1,0" | ||
1044 | 92 | position="12,-8.0000001" | ||
1045 | 93 | id="guide4076" /> | ||
1046 | 94 | <sodipodi:guide | ||
1047 | 95 | orientation="1,0" | ||
1048 | 96 | position="84,-8.0000001" | ||
1049 | 97 | id="guide4080" /> | ||
1050 | 98 | <sodipodi:guide | ||
1051 | 99 | position="48,-8.0000001" | ||
1052 | 100 | orientation="1,0" | ||
1053 | 101 | id="guide4170" /> | ||
1054 | 102 | <sodipodi:guide | ||
1055 | 103 | position="-8,48" | ||
1056 | 104 | orientation="0,1" | ||
1057 | 105 | id="guide4172" /> | ||
1058 | 106 | <sodipodi:guide | ||
1059 | 107 | position="92,-8.0000001" | ||
1060 | 108 | orientation="1,0" | ||
1061 | 109 | id="guide4760" /> | ||
1062 | 110 | </sodipodi:namedview> | ||
1063 | 111 | <metadata | ||
1064 | 112 | id="metadata4879"> | ||
1065 | 113 | <rdf:RDF> | ||
1066 | 114 | <cc:Work | ||
1067 | 115 | rdf:about=""> | ||
1068 | 116 | <dc:format>image/svg+xml</dc:format> | ||
1069 | 117 | <dc:type | ||
1070 | 118 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||
1071 | 119 | <dc:title></dc:title> | ||
1072 | 120 | </cc:Work> | ||
1073 | 121 | </rdf:RDF> | ||
1074 | 122 | </metadata> | ||
1075 | 123 | <g | ||
1076 | 124 | inkscape:label="Layer 1" | ||
1077 | 125 | inkscape:groupmode="layer" | ||
1078 | 126 | id="layer1" | ||
1079 | 127 | transform="translate(67.857146,-78.50504)"> | ||
1080 | 128 | <g | ||
1081 | 129 | transform="matrix(0,-1,-1,0,373.50506,516.50504)" | ||
1082 | 130 | id="g4845" | ||
1083 | 131 | style="display:inline"> | ||
1084 | 132 | <g | ||
1085 | 133 | inkscape:export-ydpi="90" | ||
1086 | 134 | inkscape:export-xdpi="90" | ||
1087 | 135 | inkscape:export-filename="next01.png" | ||
1088 | 136 | transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)" | ||
1089 | 137 | id="g4778" | ||
1090 | 138 | inkscape:label="Layer 1"> | ||
1091 | 139 | <g | ||
1092 | 140 | transform="matrix(-1,0,0,1,575.99999,611)" | ||
1093 | 141 | id="g4780" | ||
1094 | 142 | style="display:inline"> | ||
1095 | 143 | <rect | ||
1096 | 144 | style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate" | ||
1097 | 145 | id="rect4782" | ||
1098 | 146 | width="96.037987" | ||
1099 | 147 | height="96" | ||
1100 | 148 | x="-438.00244" | ||
1101 | 149 | y="345.36221" | ||
1102 | 150 | transform="scale(-1,1)" /> | ||
1103 | 151 | <path | ||
1104 | 152 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" | ||
1105 | 153 | d="m 407.99059,425.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1106 | 154 | id="path4321" | ||
1107 | 155 | inkscape:connector-curvature="0" /> | ||
1108 | 156 | <path | ||
1109 | 157 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" | ||
1110 | 158 | d="m 379.97952,411.36222 0,-36 -8.00318,0 0,36 8.00318,0 z" | ||
1111 | 159 | id="path4301" | ||
1112 | 160 | inkscape:connector-curvature="0" /> | ||
1113 | 161 | <path | ||
1114 | 162 | sodipodi:nodetypes="ccccccccc" | ||
1115 | 163 | inkscape:connector-curvature="0" | ||
1116 | 164 | id="path4297" | ||
1117 | 165 | d="m 371.97588,349.36261 c -10.00396,0 -9.8873,3.91306 -10.00396,14 l 0,59.99961 c 0.11666,10.08694 0,14 10.00396,14 l 36.01466,0 c 10.00396,0 9.8873,-3.91306 10.00396,-14 l 0,-59.99961 c -0.11666,-10.08694 0,-14 -10.00396,-14 z" | ||
1118 | 166 | style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#808080;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /> | ||
1119 | 167 | <path | ||
1120 | 168 | inkscape:connector-curvature="0" | ||
1121 | 169 | id="path4165" | ||
1122 | 170 | d="m 407.99059,411.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1123 | 171 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" /> | ||
1124 | 172 | <path | ||
1125 | 173 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" | ||
1126 | 174 | d="m 407.99059,397.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1127 | 175 | id="path4167" | ||
1128 | 176 | inkscape:connector-curvature="0" /> | ||
1129 | 177 | <path | ||
1130 | 178 | inkscape:connector-curvature="0" | ||
1131 | 179 | id="path4169" | ||
1132 | 180 | d="m 407.99059,383.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1133 | 181 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" /> | ||
1134 | 182 | <path | ||
1135 | 183 | inkscape:connector-curvature="0" | ||
1136 | 184 | id="path4171" | ||
1137 | 185 | d="m 393.98503,418.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1138 | 186 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" /> | ||
1139 | 187 | <path | ||
1140 | 188 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" | ||
1141 | 189 | d="m 393.98503,404.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1142 | 190 | id="path4173" | ||
1143 | 191 | inkscape:connector-curvature="0" /> | ||
1144 | 192 | <path | ||
1145 | 193 | inkscape:connector-curvature="0" | ||
1146 | 194 | id="path4175" | ||
1147 | 195 | d="m 393.98503,390.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1148 | 196 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" /> | ||
1149 | 197 | <path | ||
1150 | 198 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" | ||
1151 | 199 | d="m 393.98503,376.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1152 | 200 | id="path4177" | ||
1153 | 201 | inkscape:connector-curvature="0" /> | ||
1154 | 202 | <path | ||
1155 | 203 | inkscape:connector-curvature="0" | ||
1156 | 204 | id="path4179" | ||
1157 | 205 | d="m 379.97951,425.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1158 | 206 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" /> | ||
1159 | 207 | <path | ||
1160 | 208 | inkscape:connector-curvature="0" | ||
1161 | 209 | id="path4181" | ||
1162 | 210 | d="m 379.97947,369.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1163 | 211 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" /> | ||
1164 | 212 | <path | ||
1165 | 213 | style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none" | ||
1166 | 214 | d="m 407.99059,369.36222 0,-8.00001 -8.00317,0 0,8.00001 8.00317,0 z" | ||
1167 | 215 | id="path4185" | ||
1168 | 216 | inkscape:connector-curvature="0" /> | ||
1169 | 217 | </g> | ||
1170 | 218 | </g> | ||
1171 | 219 | </g> | ||
1172 | 220 | </g> | ||
1173 | 221 | </svg> | ||
1174 | 0 | 222 | ||
1175 | === added file 'src/stickers-history-model.cpp' | |||
1176 | --- src/stickers-history-model.cpp 1970-01-01 00:00:00 +0000 | |||
1177 | +++ src/stickers-history-model.cpp 2015-11-16 14:15:20 +0000 | |||
1178 | @@ -0,0 +1,307 @@ | |||
1179 | 1 | /* | ||
1180 | 2 | * Copyright 2015 Canonical Ltd. | ||
1181 | 3 | * | ||
1182 | 4 | * This file is part of messaging-app. | ||
1183 | 5 | * | ||
1184 | 6 | * messaging-app is free software; you can redistribute it and/or modify | ||
1185 | 7 | * it under the terms of the GNU General Public License as published by | ||
1186 | 8 | * the Free Software Foundation; version 3. | ||
1187 | 9 | * | ||
1188 | 10 | * messaging-app is distributed in the hope that it will be useful, | ||
1189 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1190 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1191 | 13 | * GNU General Public License for more details. | ||
1192 | 14 | * | ||
1193 | 15 | * You should have received a copy of the GNU General Public License | ||
1194 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1195 | 17 | */ | ||
1196 | 18 | |||
1197 | 19 | #include "stickers-history-model.h" | ||
1198 | 20 | |||
1199 | 21 | // Qt | ||
1200 | 22 | #include <QtCore/QDebug> | ||
1201 | 23 | #include <QtCore/QMutexLocker> | ||
1202 | 24 | #include <QtSql/QSqlQuery> | ||
1203 | 25 | #include <QtSql/QSqlError> | ||
1204 | 26 | |||
1205 | 27 | #define CONNECTION_NAME "messaging-app-stickers-history" | ||
1206 | 28 | |||
1207 | 29 | /*! | ||
1208 | 30 | \class StickersHistoryModel | ||
1209 | 31 | \brief List model that stores information about most recently used stickers | ||
1210 | 32 | |||
1211 | 33 | StickersHistoryModel is a list model that stores information about the most | ||
1212 | 34 | recently used stickers. | ||
1213 | 35 | Each sticker is simply identified by the sticker pack name plus the name of | ||
1214 | 36 | the sticker image file itself. | ||
1215 | 37 | Stickers are ordered by the time of last use, with the most recent first. | ||
1216 | 38 | By default the model stores a rolling list of the 10 most recently used | ||
1217 | 39 | stickers, though this number can be changed by setting the /a limit | ||
1218 | 40 | */ | ||
1219 | 41 | StickersHistoryModel::StickersHistoryModel(QObject* parent) | ||
1220 | 42 | : QAbstractListModel(parent), | ||
1221 | 43 | m_limit(10) | ||
1222 | 44 | { | ||
1223 | 45 | m_database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), CONNECTION_NAME); | ||
1224 | 46 | } | ||
1225 | 47 | |||
1226 | 48 | StickersHistoryModel::~StickersHistoryModel() | ||
1227 | 49 | { | ||
1228 | 50 | m_database.close(); | ||
1229 | 51 | m_database = QSqlDatabase(); | ||
1230 | 52 | QSqlDatabase::removeDatabase(CONNECTION_NAME); | ||
1231 | 53 | } | ||
1232 | 54 | |||
1233 | 55 | void StickersHistoryModel::resetDatabase(const QString& databaseName) | ||
1234 | 56 | { | ||
1235 | 57 | beginResetModel(); | ||
1236 | 58 | m_entries.clear(); | ||
1237 | 59 | m_database.close(); | ||
1238 | 60 | m_database.setDatabaseName(databaseName); | ||
1239 | 61 | m_database.open(); | ||
1240 | 62 | createOrAlterDatabaseSchema(); | ||
1241 | 63 | endResetModel(); | ||
1242 | 64 | populateFromDatabase(); | ||
1243 | 65 | } | ||
1244 | 66 | |||
1245 | 67 | void StickersHistoryModel::createOrAlterDatabaseSchema() | ||
1246 | 68 | { | ||
1247 | 69 | QMutexLocker ml(&m_dbMutex); | ||
1248 | 70 | QSqlQuery query(m_database); | ||
1249 | 71 | QString statement = QLatin1String("CREATE TABLE IF NOT EXISTS history " | ||
1250 | 72 | "(sticker VARCHAR, mostRecentUse DATETIME);"); | ||
1251 | 73 | query.prepare(statement); | ||
1252 | 74 | if (!query.exec()) { | ||
1253 | 75 | qWarning() << "Query failed" << query.lastError(); | ||
1254 | 76 | } | ||
1255 | 77 | } | ||
1256 | 78 | |||
1257 | 79 | void StickersHistoryModel::populateFromDatabase() | ||
1258 | 80 | { | ||
1259 | 81 | QSqlQuery query(m_database); | ||
1260 | 82 | QString statement = QLatin1String("SELECT sticker, mostRecentUse " | ||
1261 | 83 | "FROM history ORDER BY mostRecentUse DESC;"); | ||
1262 | 84 | query.prepare(statement); | ||
1263 | 85 | if (!query.exec()) { | ||
1264 | 86 | qWarning() << "Query failed" << query.lastError(); | ||
1265 | 87 | } | ||
1266 | 88 | |||
1267 | 89 | int count = 0; | ||
1268 | 90 | while (query.next()) { | ||
1269 | 91 | HistoryEntry entry; | ||
1270 | 92 | entry.sticker = query.value(0).toString(); | ||
1271 | 93 | entry.mostRecentUse = QDateTime::fromTime_t(query.value(1).toInt()); | ||
1272 | 94 | beginInsertRows(QModelIndex(), count, count); | ||
1273 | 95 | m_entries.append(entry); | ||
1274 | 96 | endInsertRows(); | ||
1275 | 97 | ++count; | ||
1276 | 98 | } | ||
1277 | 99 | } | ||
1278 | 100 | |||
1279 | 101 | QHash<int, QByteArray> StickersHistoryModel::roleNames() const | ||
1280 | 102 | { | ||
1281 | 103 | static QHash<int, QByteArray> roles; | ||
1282 | 104 | if (roles.isEmpty()) { | ||
1283 | 105 | roles[Sticker] = "sticker"; | ||
1284 | 106 | roles[MostRecentUse] = "mostRecentUse"; | ||
1285 | 107 | } | ||
1286 | 108 | return roles; | ||
1287 | 109 | } | ||
1288 | 110 | |||
1289 | 111 | int StickersHistoryModel::rowCount(const QModelIndex& parent) const | ||
1290 | 112 | { | ||
1291 | 113 | Q_UNUSED(parent); | ||
1292 | 114 | return m_entries.count(); | ||
1293 | 115 | } | ||
1294 | 116 | |||
1295 | 117 | QVariant StickersHistoryModel::data(const QModelIndex& index, int role) const | ||
1296 | 118 | { | ||
1297 | 119 | if (!index.isValid()) { | ||
1298 | 120 | return QVariant(); | ||
1299 | 121 | } | ||
1300 | 122 | const HistoryEntry& entry = m_entries.at(index.row()); | ||
1301 | 123 | switch (role) { | ||
1302 | 124 | case Sticker: | ||
1303 | 125 | return entry.sticker; | ||
1304 | 126 | case MostRecentUse: | ||
1305 | 127 | return entry.mostRecentUse; | ||
1306 | 128 | default: | ||
1307 | 129 | return QVariant(); | ||
1308 | 130 | } | ||
1309 | 131 | } | ||
1310 | 132 | |||
1311 | 133 | const QString StickersHistoryModel::databasePath() const | ||
1312 | 134 | { | ||
1313 | 135 | return m_database.databaseName(); | ||
1314 | 136 | } | ||
1315 | 137 | |||
1316 | 138 | int StickersHistoryModel::limit() const | ||
1317 | 139 | { | ||
1318 | 140 | return m_limit; | ||
1319 | 141 | } | ||
1320 | 142 | |||
1321 | 143 | void StickersHistoryModel::setLimit(int limit) | ||
1322 | 144 | { | ||
1323 | 145 | if (limit != m_limit) { | ||
1324 | 146 | m_limit = limit; | ||
1325 | 147 | Q_EMIT limitChanged(); | ||
1326 | 148 | removeExcessRows(); | ||
1327 | 149 | } | ||
1328 | 150 | } | ||
1329 | 151 | |||
1330 | 152 | void StickersHistoryModel::setDatabasePath(const QString& path) | ||
1331 | 153 | { | ||
1332 | 154 | if (path != databasePath()) { | ||
1333 | 155 | if (path.isEmpty()) { | ||
1334 | 156 | resetDatabase(":memory:"); | ||
1335 | 157 | } else { | ||
1336 | 158 | resetDatabase(path); | ||
1337 | 159 | } | ||
1338 | 160 | Q_EMIT databasePathChanged(); | ||
1339 | 161 | } | ||
1340 | 162 | } | ||
1341 | 163 | |||
1342 | 164 | int StickersHistoryModel::getEntryIndex(const QString& sticker) const | ||
1343 | 165 | { | ||
1344 | 166 | for (int i = 0; i < m_entries.count(); ++i) { | ||
1345 | 167 | if (m_entries.at(i).sticker == sticker) { | ||
1346 | 168 | return i; | ||
1347 | 169 | } | ||
1348 | 170 | } | ||
1349 | 171 | return -1; | ||
1350 | 172 | } | ||
1351 | 173 | |||
1352 | 174 | /*! | ||
1353 | 175 | Add an entry to the model. | ||
1354 | 176 | |||
1355 | 177 | If an entry for the same sticker already exists, it is updated and placed | ||
1356 | 178 | first in the model. Otherwise a new entry is created and added at the | ||
1357 | 179 | begining of the model. | ||
1358 | 180 | If the new row count exceeds the limit, excess rows are purged. | ||
1359 | 181 | */ | ||
1360 | 182 | void StickersHistoryModel::add(const QString& sticker) | ||
1361 | 183 | { | ||
1362 | 184 | if (sticker.isEmpty()) { | ||
1363 | 185 | return; | ||
1364 | 186 | } | ||
1365 | 187 | QDateTime now = QDateTime::currentDateTime(); | ||
1366 | 188 | int index = getEntryIndex(sticker); | ||
1367 | 189 | |||
1368 | 190 | if (index == -1) { | ||
1369 | 191 | HistoryEntry entry; | ||
1370 | 192 | entry.sticker = sticker; | ||
1371 | 193 | entry.mostRecentUse = now; | ||
1372 | 194 | beginInsertRows(QModelIndex(), 0, 0); | ||
1373 | 195 | m_entries.prepend(entry); | ||
1374 | 196 | endInsertRows(); | ||
1375 | 197 | insertNewEntryInDatabase(entry); | ||
1376 | 198 | Q_EMIT rowCountChanged(); | ||
1377 | 199 | removeExcessRows(); | ||
1378 | 200 | } else { | ||
1379 | 201 | HistoryEntry entry; | ||
1380 | 202 | if (index > 0) { | ||
1381 | 203 | beginMoveRows(QModelIndex(), index, index, QModelIndex(), 0); | ||
1382 | 204 | } | ||
1383 | 205 | entry = m_entries.takeAt(index); | ||
1384 | 206 | entry.mostRecentUse = now; | ||
1385 | 207 | m_entries.prepend(entry); | ||
1386 | 208 | if (index > 0) { | ||
1387 | 209 | endMoveRows(); | ||
1388 | 210 | } | ||
1389 | 211 | QVector<int> roles; | ||
1390 | 212 | roles << MostRecentUse; | ||
1391 | 213 | Q_EMIT dataChanged(this->index(0), this->index(0), roles); | ||
1392 | 214 | updateExistingEntryInDatabase(m_entries.first()); | ||
1393 | 215 | } | ||
1394 | 216 | } | ||
1395 | 217 | |||
1396 | 218 | void StickersHistoryModel::removeExcessRows() | ||
1397 | 219 | { | ||
1398 | 220 | if (m_limit < rowCount()) { | ||
1399 | 221 | beginRemoveRows(QModelIndex(), m_limit, rowCount() - 1); | ||
1400 | 222 | for (int i = rowCount() - 1; i >= m_limit; i--) { | ||
1401 | 223 | HistoryEntry item = m_entries.takeAt(i); | ||
1402 | 224 | removeEntryFromDatabase(item.sticker); | ||
1403 | 225 | } | ||
1404 | 226 | endRemoveRows(); | ||
1405 | 227 | Q_EMIT rowCountChanged(); | ||
1406 | 228 | } | ||
1407 | 229 | } | ||
1408 | 230 | |||
1409 | 231 | void StickersHistoryModel::insertNewEntryInDatabase(const HistoryEntry& entry) | ||
1410 | 232 | { | ||
1411 | 233 | QMutexLocker ml(&m_dbMutex); | ||
1412 | 234 | QSqlQuery query(m_database); | ||
1413 | 235 | static QString statement = QLatin1String("INSERT INTO history (sticker, mostRecentUse) " | ||
1414 | 236 | "VALUES (?, ?);"); | ||
1415 | 237 | query.prepare(statement); | ||
1416 | 238 | query.addBindValue(entry.sticker); | ||
1417 | 239 | query.addBindValue(entry.mostRecentUse.toTime_t()); | ||
1418 | 240 | |||
1419 | 241 | if (!query.exec()) { | ||
1420 | 242 | qWarning() << "Query failed" << query.lastError(); | ||
1421 | 243 | } | ||
1422 | 244 | } | ||
1423 | 245 | |||
1424 | 246 | void StickersHistoryModel::updateExistingEntryInDatabase(const HistoryEntry& entry) | ||
1425 | 247 | { | ||
1426 | 248 | QMutexLocker ml(&m_dbMutex); | ||
1427 | 249 | QSqlQuery query(m_database); | ||
1428 | 250 | static QString statement = QLatin1String("UPDATE history SET mostRecentUse=?" | ||
1429 | 251 | " WHERE sticker=?;"); | ||
1430 | 252 | query.prepare(statement); | ||
1431 | 253 | query.addBindValue(entry.mostRecentUse.toTime_t()); | ||
1432 | 254 | query.addBindValue(entry.sticker); | ||
1433 | 255 | if (!query.exec()) { | ||
1434 | 256 | qWarning() << "Query failed" << query.lastError(); | ||
1435 | 257 | } | ||
1436 | 258 | } | ||
1437 | 259 | |||
1438 | 260 | void StickersHistoryModel::removeEntryFromDatabase(const QString& sticker) | ||
1439 | 261 | { | ||
1440 | 262 | QMutexLocker ml(&m_dbMutex); | ||
1441 | 263 | QSqlQuery query(m_database); | ||
1442 | 264 | static QString statement = QLatin1String("DELETE FROM history WHERE sticker=?;"); | ||
1443 | 265 | query.prepare(statement); | ||
1444 | 266 | query.addBindValue(sticker); | ||
1445 | 267 | if (!query.exec()) { | ||
1446 | 268 | qWarning() << "Query failed" << query.lastError(); | ||
1447 | 269 | } | ||
1448 | 270 | } | ||
1449 | 271 | |||
1450 | 272 | void StickersHistoryModel::clearAll() | ||
1451 | 273 | { | ||
1452 | 274 | if (!m_entries.isEmpty()) { | ||
1453 | 275 | beginResetModel(); | ||
1454 | 276 | m_entries.clear(); | ||
1455 | 277 | endResetModel(); | ||
1456 | 278 | clearDatabase(); | ||
1457 | 279 | Q_EMIT rowCountChanged(); | ||
1458 | 280 | } | ||
1459 | 281 | } | ||
1460 | 282 | |||
1461 | 283 | void StickersHistoryModel::clearDatabase() | ||
1462 | 284 | { | ||
1463 | 285 | QMutexLocker ml(&m_dbMutex); | ||
1464 | 286 | QSqlQuery query(m_database); | ||
1465 | 287 | QString statement = QLatin1String("DELETE FROM history;"); | ||
1466 | 288 | query.prepare(statement); | ||
1467 | 289 | if (!query.exec()) { | ||
1468 | 290 | qWarning() << "Query failed" << query.lastError(); | ||
1469 | 291 | } | ||
1470 | 292 | } | ||
1471 | 293 | |||
1472 | 294 | QVariantMap StickersHistoryModel::get(int i) const | ||
1473 | 295 | { | ||
1474 | 296 | QVariantMap item; | ||
1475 | 297 | QHash<int, QByteArray> roles = roleNames(); | ||
1476 | 298 | |||
1477 | 299 | QModelIndex modelIndex = index(i, 0); | ||
1478 | 300 | if (modelIndex.isValid()) { | ||
1479 | 301 | Q_FOREACH(int role, roles.keys()) { | ||
1480 | 302 | QString roleName = QString::fromUtf8(roles.value(role)); | ||
1481 | 303 | item.insert(roleName, data(modelIndex, role)); | ||
1482 | 304 | } | ||
1483 | 305 | } | ||
1484 | 306 | return item; | ||
1485 | 307 | } | ||
1486 | 0 | 308 | ||
1487 | === added file 'src/stickers-history-model.h' | |||
1488 | --- src/stickers-history-model.h 1970-01-01 00:00:00 +0000 | |||
1489 | +++ src/stickers-history-model.h 2015-11-16 14:15:20 +0000 | |||
1490 | @@ -0,0 +1,91 @@ | |||
1491 | 1 | /* | ||
1492 | 2 | * Copyright 2015 Canonical Ltd. | ||
1493 | 3 | * | ||
1494 | 4 | * This file is part of messaging-app. | ||
1495 | 5 | * | ||
1496 | 6 | * messaging-app is free software; you can redistribute it and/or modify | ||
1497 | 7 | * it under the terms of the GNU General Public License as published by | ||
1498 | 8 | * the Free Software Foundation; version 3. | ||
1499 | 9 | * | ||
1500 | 10 | * messaging-app is distributed in the hope that it will be useful, | ||
1501 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1502 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1503 | 13 | * GNU General Public License for more details. | ||
1504 | 14 | * | ||
1505 | 15 | * You should have received a copy of the GNU General Public License | ||
1506 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1507 | 17 | */ | ||
1508 | 18 | |||
1509 | 19 | #ifndef __STICKERS_HISTORY_MODEL_H__ | ||
1510 | 20 | #define __STICKERS_HISTORY_MODEL_H__ | ||
1511 | 21 | |||
1512 | 22 | // Qt | ||
1513 | 23 | #include <QtCore/QAbstractListModel> | ||
1514 | 24 | #include <QtCore/QDateTime> | ||
1515 | 25 | #include <QtCore/QList> | ||
1516 | 26 | #include <QtCore/QMutex> | ||
1517 | 27 | #include <QtCore/QString> | ||
1518 | 28 | #include <QtSql/QSqlDatabase> | ||
1519 | 29 | |||
1520 | 30 | class StickersHistoryModel : public QAbstractListModel | ||
1521 | 31 | { | ||
1522 | 32 | Q_OBJECT | ||
1523 | 33 | |||
1524 | 34 | Q_PROPERTY(QString databasePath READ databasePath WRITE setDatabasePath NOTIFY databasePathChanged) | ||
1525 | 35 | Q_PROPERTY(int limit READ limit WRITE setLimit NOTIFY limitChanged) | ||
1526 | 36 | Q_PROPERTY(int count READ rowCount NOTIFY rowCountChanged) | ||
1527 | 37 | |||
1528 | 38 | Q_ENUMS(Roles) | ||
1529 | 39 | |||
1530 | 40 | public: | ||
1531 | 41 | StickersHistoryModel(QObject* parent=0); | ||
1532 | 42 | ~StickersHistoryModel(); | ||
1533 | 43 | |||
1534 | 44 | enum Roles { | ||
1535 | 45 | Sticker = Qt::UserRole + 1, | ||
1536 | 46 | MostRecentUse | ||
1537 | 47 | }; | ||
1538 | 48 | |||
1539 | 49 | // reimplemented from QAbstractListModel | ||
1540 | 50 | QHash<int, QByteArray> roleNames() const; | ||
1541 | 51 | int rowCount(const QModelIndex& parent=QModelIndex()) const; | ||
1542 | 52 | QVariant data(const QModelIndex& index, int role) const; | ||
1543 | 53 | |||
1544 | 54 | const QString databasePath() const; | ||
1545 | 55 | void setDatabasePath(const QString& path); | ||
1546 | 56 | int limit() const; | ||
1547 | 57 | void setLimit(int limit); | ||
1548 | 58 | |||
1549 | 59 | Q_INVOKABLE void add(const QString& sticker); | ||
1550 | 60 | Q_INVOKABLE void clearAll(); | ||
1551 | 61 | Q_INVOKABLE QVariantMap get(int index) const; | ||
1552 | 62 | |||
1553 | 63 | Q_SIGNALS: | ||
1554 | 64 | void databasePathChanged() const; | ||
1555 | 65 | void rowCountChanged() const; | ||
1556 | 66 | void limitChanged() const; | ||
1557 | 67 | |||
1558 | 68 | protected: | ||
1559 | 69 | struct HistoryEntry { | ||
1560 | 70 | QString sticker; | ||
1561 | 71 | QDateTime mostRecentUse; | ||
1562 | 72 | }; | ||
1563 | 73 | QList<HistoryEntry> m_entries; | ||
1564 | 74 | int getEntryIndex(const QString& sticker) const; | ||
1565 | 75 | void updateExistingEntryInDatabase(const HistoryEntry& entry); | ||
1566 | 76 | |||
1567 | 77 | private: | ||
1568 | 78 | QMutex m_dbMutex; | ||
1569 | 79 | QSqlDatabase m_database; | ||
1570 | 80 | int m_limit; | ||
1571 | 81 | |||
1572 | 82 | void resetDatabase(const QString& databaseName); | ||
1573 | 83 | void createOrAlterDatabaseSchema(); | ||
1574 | 84 | void populateFromDatabase(); | ||
1575 | 85 | void insertNewEntryInDatabase(const HistoryEntry& entry); | ||
1576 | 86 | void removeEntryFromDatabase(const QString& sticker); | ||
1577 | 87 | void clearDatabase(); | ||
1578 | 88 | void removeExcessRows(); | ||
1579 | 89 | }; | ||
1580 | 90 | |||
1581 | 91 | #endif // __STICKERS_HISTORY_MODEL_H__ | ||
1582 | 0 | 92 | ||
1583 | === modified file 'tests/qml/CMakeLists.txt' | |||
1584 | --- tests/qml/CMakeLists.txt 2015-08-13 18:34:55 +0000 | |||
1585 | +++ tests/qml/CMakeLists.txt 2015-11-16 14:15:20 +0000 | |||
1586 | @@ -1,33 +1,45 @@ | |||
1607 | 1 | find_program(QMLTESTRUNNER_BIN | 1 | find_package(Qt5Core REQUIRED) |
1608 | 2 | NAMES qmltestrunner | 2 | find_package(Qt5Gui REQUIRED) |
1609 | 3 | PATHS /usr/lib/*/qt5/bin | 3 | find_package(Qt5Network REQUIRED) |
1610 | 4 | NO_DEFAULT_PATH | 4 | find_package(Qt5Qml REQUIRED) |
1611 | 5 | ) | 5 | find_package(Qt5Quick REQUIRED) |
1612 | 6 | 6 | find_package(Qt5QuickTest REQUIRED) | |
1613 | 7 | find_program(XVFB_RUN_BIN | 7 | find_package(Qt5Sql REQUIRED) |
1614 | 8 | NAMES xvfb-run | 8 | |
1615 | 9 | ) | 9 | set(XVFB_COMMAND) |
1616 | 10 | 10 | find_program(XVFBRUN xvfb-run) | |
1617 | 11 | macro(DECLARE_QML_TEST TST_NAME TST_QML_FILE) | 11 | if(XVFBRUN) |
1618 | 12 | add_test(NAME ${TST_NAME} | 12 | set(XVFB_COMMAND ${XVFBRUN} -s "-screen 0 1024x768x24" -a) |
1599 | 13 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | ||
1600 | 14 | COMMAND ${XVFB_RUN_BIN} -a -s "-screen 0 1024x768x24" ${QMLTESTRUNNER_BIN} -import ${qml_BINARY_DIR} -input ${CMAKE_CURRENT_SOURCE_DIR}/${TST_QML_FILE} | ||
1601 | 15 | ) | ||
1602 | 16 | endmacro() | ||
1603 | 17 | |||
1604 | 18 | if(QMLTESTRUNNER_BIN AND XVFB_RUN_BIN) | ||
1605 | 19 | declare_qml_test("message_bubble" tst_MessageBubble.qml) | ||
1606 | 20 | declare_qml_test("messages_view" tst_MessagesView.qml) | ||
1619 | 21 | else() | 13 | else() |
1625 | 22 | if (NOT QMLTESTRUNNER_BIN) | 14 | message(WARNING "Cannot find xvfb-run.") |
1621 | 23 | message(WARNING "Qml tests disabled: qmltestrunner not found") | ||
1622 | 24 | else() | ||
1623 | 25 | message(WARNING "Qml tests disabled: xvfb-run not found") | ||
1624 | 26 | endif() | ||
1626 | 27 | endif() | 15 | endif() |
1627 | 28 | 16 | ||
1633 | 29 | set(QML_TST_FILES | 17 | set(CMAKE_AUTOMOC ON) |
1634 | 30 | tst_MessageBubble.qml | 18 | |
1635 | 31 | tst_MessagesView.qml | 19 | set(TEST tst_QmlTests) |
1636 | 32 | ) | 20 | set(SOURCES |
1637 | 33 | add_custom_target(tst_QmlFiles ALL SOURCES ${QML_TST_FILES}) | 21 | ${messaging-app_SOURCE_DIR}/src/stickers-history-model.cpp |
1638 | 22 | tst_QmlTests.cpp | ||
1639 | 23 | ) | ||
1640 | 24 | add_executable(${TEST} ${SOURCES}) | ||
1641 | 25 | include_directories( | ||
1642 | 26 | ${CMAKE_CURRENT_BINARY_DIR} | ||
1643 | 27 | ${CMAKE_CURRENT_SOURCE_DIR} | ||
1644 | 28 | ${messaging-app_SOURCE_DIR}/src/ | ||
1645 | 29 | ) | ||
1646 | 30 | target_link_libraries(${TEST} | ||
1647 | 31 | Qt5::Core | ||
1648 | 32 | Qt5::Gui | ||
1649 | 33 | Qt5::Network | ||
1650 | 34 | Qt5::Qml | ||
1651 | 35 | Qt5::Quick | ||
1652 | 36 | Qt5::QuickTest | ||
1653 | 37 | Qt5::Sql | ||
1654 | 38 | ) | ||
1655 | 39 | add_test(${TEST} ${XVFB_COMMAND} ${CMAKE_CURRENT_BINARY_DIR}/${TEST} | ||
1656 | 40 | -input ${CMAKE_CURRENT_SOURCE_DIR} | ||
1657 | 41 | -import ${CMAKE_BINARY_DIR}/src) | ||
1658 | 42 | |||
1659 | 43 | # make qml files visible in QtCreator | ||
1660 | 44 | file(GLOB_RECURSE NON_COMPILED_FILES *.qml) | ||
1661 | 45 | add_custom_target(NON_COMPILED_TARGET ALL SOURCES ${NON_COMPILED_FILES}) | ||
1662 | 34 | 46 | ||
1663 | === added file 'tests/qml/tst_QmlTests.cpp' | |||
1664 | --- tests/qml/tst_QmlTests.cpp 1970-01-01 00:00:00 +0000 | |||
1665 | +++ tests/qml/tst_QmlTests.cpp 2015-11-16 14:15:20 +0000 | |||
1666 | @@ -0,0 +1,78 @@ | |||
1667 | 1 | /* | ||
1668 | 2 | * Copyright 2015 Canonical Ltd. | ||
1669 | 3 | * | ||
1670 | 4 | * This file is part of messaging-app. | ||
1671 | 5 | * | ||
1672 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
1673 | 7 | * it under the terms of the GNU General Public License as published by | ||
1674 | 8 | * the Free Software Foundation; version 3. | ||
1675 | 9 | * | ||
1676 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
1677 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1678 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1679 | 13 | * GNU General Public License for more details. | ||
1680 | 14 | * | ||
1681 | 15 | * You should have received a copy of the GNU General Public License | ||
1682 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1683 | 17 | */ | ||
1684 | 18 | |||
1685 | 19 | // Qt | ||
1686 | 20 | #include <QtCore/QDir> | ||
1687 | 21 | #include <QtCore/QTemporaryDir> | ||
1688 | 22 | #include <QtCore/QObject> | ||
1689 | 23 | #include <QtCore/QString> | ||
1690 | 24 | #include <QtCore/QTemporaryDir> | ||
1691 | 25 | #include <QtQml/QtQml> | ||
1692 | 26 | #include <QtQuickTest/QtQuickTest> | ||
1693 | 27 | |||
1694 | 28 | // local | ||
1695 | 29 | #include "stickers-history-model.h" | ||
1696 | 30 | |||
1697 | 31 | static QObject* StickersHistoryModel_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) | ||
1698 | 32 | { | ||
1699 | 33 | Q_UNUSED(engine); | ||
1700 | 34 | Q_UNUSED(scriptEngine); | ||
1701 | 35 | return new StickersHistoryModel(); | ||
1702 | 36 | } | ||
1703 | 37 | |||
1704 | 38 | class TestContext : public QObject | ||
1705 | 39 | { | ||
1706 | 40 | Q_OBJECT | ||
1707 | 41 | |||
1708 | 42 | Q_PROPERTY(QString testDir READ testDir CONSTANT) | ||
1709 | 43 | |||
1710 | 44 | public: | ||
1711 | 45 | explicit TestContext(QObject* parent=0) | ||
1712 | 46 | : QObject(parent) | ||
1713 | 47 | { | ||
1714 | 48 | QDir dir(m_temporary.path()); | ||
1715 | 49 | dir.mkpath("stickers"); | ||
1716 | 50 | } | ||
1717 | 51 | |||
1718 | 52 | QString testDir() const | ||
1719 | 53 | { | ||
1720 | 54 | return m_temporary.path(); | ||
1721 | 55 | } | ||
1722 | 56 | |||
1723 | 57 | QTemporaryDir m_temporary; | ||
1724 | 58 | }; | ||
1725 | 59 | |||
1726 | 60 | static QObject* TestContext_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) | ||
1727 | 61 | { | ||
1728 | 62 | Q_UNUSED(engine); | ||
1729 | 63 | Q_UNUSED(scriptEngine); | ||
1730 | 64 | return new TestContext(); | ||
1731 | 65 | } | ||
1732 | 66 | |||
1733 | 67 | int main(int argc, char** argv) | ||
1734 | 68 | { | ||
1735 | 69 | const char* uri = "messagingapp.private"; | ||
1736 | 70 | qmlRegisterSingletonType<StickersHistoryModel>(uri, 0, 1, "StickersHistoryModel", StickersHistoryModel_singleton_factory); | ||
1737 | 71 | |||
1738 | 72 | const char* testUri = "messagingapptest.private"; | ||
1739 | 73 | qmlRegisterSingletonType<TestContext>(testUri, 0, 1, "TestContext", TestContext_singleton_factory); | ||
1740 | 74 | |||
1741 | 75 | return quick_test_main(argc, argv, "QmlTests", 0); | ||
1742 | 76 | } | ||
1743 | 77 | |||
1744 | 78 | #include "tst_QmlTests.moc" | ||
1745 | 0 | 79 | ||
1746 | === added file 'tests/qml/tst_StickersHistoryModel.qml' | |||
1747 | --- tests/qml/tst_StickersHistoryModel.qml 1970-01-01 00:00:00 +0000 | |||
1748 | +++ tests/qml/tst_StickersHistoryModel.qml 2015-11-16 14:15:20 +0000 | |||
1749 | @@ -0,0 +1,188 @@ | |||
1750 | 1 | /* | ||
1751 | 2 | * Copyright 2015 Canonical Ltd. | ||
1752 | 3 | * | ||
1753 | 4 | * This file is part of messaging-app. | ||
1754 | 5 | * | ||
1755 | 6 | * messaging-app is free software; you can redistribute it and/or modify | ||
1756 | 7 | * it under the terms of the GNU General Public License as published by | ||
1757 | 8 | * the Free Software Foundation; version 3. | ||
1758 | 9 | * | ||
1759 | 10 | * messaging-app is distributed in the hope that it will be useful, | ||
1760 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1761 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1762 | 13 | * GNU General Public License for more details. | ||
1763 | 14 | * | ||
1764 | 15 | * You should have received a copy of the GNU General Public License | ||
1765 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1766 | 17 | */ | ||
1767 | 18 | |||
1768 | 19 | import QtQuick 2.2 | ||
1769 | 20 | import QtTest 1.0 | ||
1770 | 21 | import Ubuntu.Components 1.3 | ||
1771 | 22 | import Ubuntu.Test 0.1 | ||
1772 | 23 | import messagingapp.private 0.1 | ||
1773 | 24 | import messagingapptest.private 0.1 | ||
1774 | 25 | |||
1775 | 26 | Item { | ||
1776 | 27 | id: root | ||
1777 | 28 | width: 1 | ||
1778 | 29 | height: 1 | ||
1779 | 30 | |||
1780 | 31 | property var model: StickersHistoryModel | ||
1781 | 32 | |||
1782 | 33 | SignalSpy { | ||
1783 | 34 | id: countSpy | ||
1784 | 35 | target: model | ||
1785 | 36 | signalName: "rowCountChanged" | ||
1786 | 37 | } | ||
1787 | 38 | |||
1788 | 39 | SignalSpy { | ||
1789 | 40 | id: rowsInsertedSpy | ||
1790 | 41 | target: model | ||
1791 | 42 | signalName: "rowsInserted" | ||
1792 | 43 | } | ||
1793 | 44 | |||
1794 | 45 | SignalSpy { | ||
1795 | 46 | id: rowsMovedSpy | ||
1796 | 47 | target: model | ||
1797 | 48 | signalName: "rowsMoved" | ||
1798 | 49 | } | ||
1799 | 50 | |||
1800 | 51 | SignalSpy { | ||
1801 | 52 | id: dataChangedSpy | ||
1802 | 53 | target: model | ||
1803 | 54 | signalName: "dataChanged" | ||
1804 | 55 | } | ||
1805 | 56 | |||
1806 | 57 | SignalSpy { | ||
1807 | 58 | id: rowsRemovedSpy | ||
1808 | 59 | target: model | ||
1809 | 60 | signalName: "rowsRemoved" | ||
1810 | 61 | } | ||
1811 | 62 | |||
1812 | 63 | UbuntuTestCase { | ||
1813 | 64 | id: test | ||
1814 | 65 | name: 'stickersHistoryModelTestCase' | ||
1815 | 66 | when: windowShown | ||
1816 | 67 | |||
1817 | 68 | function init() { | ||
1818 | 69 | model.databasePath = ":memory:" | ||
1819 | 70 | model.limit = 10 | ||
1820 | 71 | } | ||
1821 | 72 | |||
1822 | 73 | function cleanup() { | ||
1823 | 74 | model.databasePath = "" | ||
1824 | 75 | countSpy.clear() | ||
1825 | 76 | rowsInsertedSpy.clear() | ||
1826 | 77 | dataChangedSpy.clear() | ||
1827 | 78 | rowsMovedSpy.clear() | ||
1828 | 79 | rowsRemovedSpy.clear() | ||
1829 | 80 | } | ||
1830 | 81 | |||
1831 | 82 | function test_initiallyEmpty() { | ||
1832 | 83 | compare(model.count, 0) | ||
1833 | 84 | } | ||
1834 | 85 | |||
1835 | 86 | function test_addingEmptyOrInvalidDoesNothing() { | ||
1836 | 87 | model.add("") | ||
1837 | 88 | compare(model.count, 0) | ||
1838 | 89 | model.add(null) | ||
1839 | 90 | compare(model.count, 0) | ||
1840 | 91 | model.add(undefined) | ||
1841 | 92 | compare(model.count, 0) | ||
1842 | 93 | } | ||
1843 | 94 | |||
1844 | 95 | function test_add_new() { | ||
1845 | 96 | model.add("foo") | ||
1846 | 97 | compare(model.count, 1) | ||
1847 | 98 | compare(countSpy.count, 1) | ||
1848 | 99 | compare(rowsInsertedSpy.count, 1) | ||
1849 | 100 | compare(rowsInsertedSpy.signalArguments[0][1], 0) // first | ||
1850 | 101 | compare(rowsInsertedSpy.signalArguments[0][2], 0) // last | ||
1851 | 102 | |||
1852 | 103 | model.add("bar") | ||
1853 | 104 | compare(model.count, 2) | ||
1854 | 105 | compare(countSpy.count, 2) | ||
1855 | 106 | compare(rowsInsertedSpy.count, 2) | ||
1856 | 107 | compare(rowsInsertedSpy.signalArguments[0][1], 0) // first | ||
1857 | 108 | compare(rowsInsertedSpy.signalArguments[0][2], 0) // last | ||
1858 | 109 | } | ||
1859 | 110 | |||
1860 | 111 | function test_signals() { | ||
1861 | 112 | model.limit = 2 | ||
1862 | 113 | |||
1863 | 114 | model.add("a") | ||
1864 | 115 | compare(model.count, 1) | ||
1865 | 116 | compare(countSpy.count, 1) | ||
1866 | 117 | compare(rowsInsertedSpy.count, 1) | ||
1867 | 118 | compare(rowsInsertedSpy.signalArguments[0][1], 0) // first | ||
1868 | 119 | compare(rowsInsertedSpy.signalArguments[0][2], 0) // last | ||
1869 | 120 | |||
1870 | 121 | model.add("a") | ||
1871 | 122 | compare(dataChangedSpy.count, 1) | ||
1872 | 123 | |||
1873 | 124 | model.add("b") | ||
1874 | 125 | compare(model.count, 2) | ||
1875 | 126 | compare(countSpy.count, 2) | ||
1876 | 127 | compare(rowsInsertedSpy.count, 2) | ||
1877 | 128 | compare(rowsInsertedSpy.signalArguments[0][1], 0) // first | ||
1878 | 129 | compare(rowsInsertedSpy.signalArguments[0][2], 0) // last | ||
1879 | 130 | |||
1880 | 131 | model.add("a") | ||
1881 | 132 | compare(rowsMovedSpy.count, 1) | ||
1882 | 133 | compare(rowsMovedSpy.signalArguments[0][1], 1) // from first | ||
1883 | 134 | compare(rowsMovedSpy.signalArguments[0][2], 1) // from last | ||
1884 | 135 | compare(rowsMovedSpy.signalArguments[0][4], 0) // to | ||
1885 | 136 | compare(dataChangedSpy.count, 2) | ||
1886 | 137 | |||
1887 | 138 | model.add("c") | ||
1888 | 139 | compare(model.count, 2) | ||
1889 | 140 | compare(rowsRemovedSpy.count, 1) | ||
1890 | 141 | compare(rowsRemovedSpy.signalArguments[0][1], 2) // from | ||
1891 | 142 | compare(rowsRemovedSpy.signalArguments[0][2], 2) // to | ||
1892 | 143 | } | ||
1893 | 144 | |||
1894 | 145 | function test_get_and_order() { | ||
1895 | 146 | model.add("a") | ||
1896 | 147 | // datetimes have only millisecond precision, and we want to prevent | ||
1897 | 148 | // the two entries to have the same timestamp | ||
1898 | 149 | wait(100) | ||
1899 | 150 | model.add("b") | ||
1900 | 151 | |||
1901 | 152 | var a = model.get(1) | ||
1902 | 153 | verify(a !== null) | ||
1903 | 154 | compare(a.sticker, "a") | ||
1904 | 155 | |||
1905 | 156 | var b = model.get(0) | ||
1906 | 157 | verify(b !== null) | ||
1907 | 158 | compare(b.sticker, "b") | ||
1908 | 159 | |||
1909 | 160 | verify(b.mostRecentUse.toISOString() > a.mostRecentUse.toISOString()) | ||
1910 | 161 | |||
1911 | 162 | wait(100) | ||
1912 | 163 | model.add("a") | ||
1913 | 164 | |||
1914 | 165 | a = model.get(0) | ||
1915 | 166 | verify(a !== null) | ||
1916 | 167 | compare(a.sticker, "a") | ||
1917 | 168 | |||
1918 | 169 | b = model.get(1) | ||
1919 | 170 | verify(b !== null) | ||
1920 | 171 | compare(b.sticker, "b") | ||
1921 | 172 | |||
1922 | 173 | verify(a.mostRecentUse.toISOString() > b.mostRecentUse.toISOString()) | ||
1923 | 174 | } | ||
1924 | 175 | |||
1925 | 176 | function test_limit_change() { | ||
1926 | 177 | model.add("d") | ||
1927 | 178 | model.add("c") | ||
1928 | 179 | model.add("b") | ||
1929 | 180 | model.add("a") | ||
1930 | 181 | model.limit = 2 | ||
1931 | 182 | |||
1932 | 183 | compare(model.count, 2) | ||
1933 | 184 | compare(model.get(0).sticker, "a") | ||
1934 | 185 | compare(model.get(1).sticker, "b") | ||
1935 | 186 | } | ||
1936 | 187 | } | ||
1937 | 188 | } |
FAILED: Continuous integration, rev:475 /code.launchpad .net/~uriboni/ messaging- app/stickers/ +merge/ 277446/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http:// jenkins. qa.ubuntu. com/job/ messaging- app-ci/ 700/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 5144/console jenkins. qa.ubuntu. com/job/ messaging- app-vivid- i386-ci/ 213/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 5158/console
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/messaging- app-ci/ 700/rebuild
http://