Merge lp:~verzegnassi-stefano/quick-memo/10-misc-refactoring into lp:quick-memo
- 10-misc-refactoring
- Merge into 0.4
Proposed by
Stefano Verzegnassi
on 2015-04-26
Status: | Merged |
---|---|
Approved by: | Stefano Verzegnassi on 2015-04-26 |
Approved revision: | 69 |
Merged at revision: | 64 |
Proposed branch: | lp:~verzegnassi-stefano/quick-memo/10-misc-refactoring |
Merge into: | lp:quick-memo |
Diff against target: |
6833 lines (+3352/-3035) (has conflicts) 46 files modified
CMakeLists.txt (+15/-6) app/CMakeLists.txt (+0/-15) app/common/ColorDialog.qml (+168/-0) app/common/NoteModel.qml (+119/-0) app/common/NoteTextArea.qml (+59/-0) app/common/NoteTextField.qml (+53/-0) app/common/PageBackground.qml (+25/-0) app/common/PageWithBottomEdge.qml (+407/-0) app/common/Toaster.qml (+81/-0) app/common/dateHelper.js (+23/-0) app/components/AboutPage.qml (+0/-206) app/components/CMakeLists.txt (+0/-7) app/components/ColorDialog.qml (+0/-168) app/components/Delegate.qml (+0/-291) app/components/EditMemoPage.qml (+0/-328) app/components/HorizontalFlowListView.qml (+0/-78) app/components/IconButton.qml (+0/-45) app/components/ImageViewer.qml (+0/-130) app/components/ListManager.qml (+0/-311) app/components/ListViewDelegate.qml (+0/-299) app/components/MultiSelectionHandler.qml (+0/-106) app/components/NoteModel.qml (+0/-119) app/components/NoteTextArea.qml (+0/-59) app/components/NoteTextField.qml (+0/-53) app/components/PageBackground.qml (+0/-25) app/components/PageWithBottomEdge.qml (+0/-407) app/components/PictureButton.qml (+0/-40) app/components/PicturesManager.qml (+0/-162) app/components/Toaster.qml (+0/-81) app/components/dateHelper.js (+0/-23) app/editPage/ListManager.qml (+313/-0) app/editPage/PictureButton.qml (+40/-0) app/editPage/PicturesManager.qml (+162/-0) app/main.qml (+5/-18) app/mainPage/Delegate.qml (+291/-0) app/mainPage/HorizontalFlowListView.qml (+78/-0) app/mainPage/ListViewDelegate.qml (+299/-0) app/mainPage/MultiSelectionHandler.qml (+106/-0) app/ubuntucomponents/CMakeLists.txt (+0/-7) app/ui/AboutPage.qml (+206/-0) app/ui/EditMemoPage.qml (+328/-0) app/ui/ImageViewer.qml (+130/-0) app/ui/MainPage.qml (+308/-0) app_info.json.in (+0/-3) po/CMakeLists.txt (+2/-2) po/quick-memo.pot (+134/-46) Conflict: can't delete app/components because it is not empty. Not deleting. Conflict because app/components is not versioned, but has versioned children. Versioned directory. Contents conflict in app/components/MainPage.qml Text conflict in po/quick-memo.pot |
To merge this branch: | bzr merge lp:~verzegnassi-stefano/quick-memo/10-misc-refactoring |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stefano Verzegnassi | Pending | ||
Review via email:
|
Commit message
General refactoring of the project:
- changed folder structures
- cleaning up the project
Description of the change
General refactoring of the project:
- changed folder structures
- cleaning up the project
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2015-04-13 20:26:48 +0000 |
3 | +++ CMakeLists.txt 2015-04-26 16:57:43 +0000 |
4 | @@ -43,6 +43,7 @@ |
5 | set(APP_NAME quick-memo) |
6 | set(APP_DIR "app") |
7 | set(MAIN_QML "main.qml") |
8 | +set(DESKTOP_FILE "quick-memo.desktop") |
9 | set(ICON "graphics/quick-memo.png") |
10 | |
11 | # Set install paths |
12 | @@ -64,6 +65,8 @@ |
13 | configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/manifest.json) |
14 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json |
15 | DESTINATION ${CMAKE_INSTALL_PREFIX}) |
16 | +configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/app_info.json) |
17 | +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/app_info.json DESTINATION ${DATA_DIR}) |
18 | |
19 | install(DIRECTORY "app/graphics" DESTINATION ${DATA_DIR}) |
20 | install(FILES "quick-memo.apparmor" DESTINATION ${DATA_DIR}) |
21 | @@ -71,12 +74,18 @@ |
22 | install(FILES "COPYING.LGPL-3" DESTINATION ${DATA_DIR}) |
23 | install(FILES "copyright" DESTINATION ${DATA_DIR}) |
24 | |
25 | -# Configure app_info.json |
26 | -configure_file(app_info.json.in ${CMAKE_CURRENT_BINARY_DIR}/app_info.json) |
27 | -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/app_info.json DESTINATION ${DATA_DIR}) |
28 | - |
29 | -add_subdirectory(app) |
30 | -#add_subdirectory(backend) |
31 | +# "App" subdirectory |
32 | +configure_file(${DESKTOP_FILE_NAME}.in ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE_NAME}.in) |
33 | +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE} DESTINATION ${DESKTOP_DIR}) |
34 | + |
35 | +file(GLOB_RECURSE QML_JS_FILES *.qml *.js) |
36 | +add_custom_target(quick-memo_QMlFiles ALL |
37 | + SOURCES ${QML_JS_FILES} |
38 | + COMMAND cp -r ${CMAKE_CURRENT_SOURCE_DIR}/app ${CMAKE_CURRENT_BINARY_DIR} |
39 | + DEPENDS ${QMLFILES} |
40 | +) |
41 | +install(DIRECTORY app DESTINATION ${DATA_DIR}) |
42 | + |
43 | add_subdirectory(po) |
44 | |
45 | add_custom_target("autopilot" chmod +x ${CMAKE_SOURCE_DIR}/app/tests/autopilot/run |
46 | |
47 | === removed file 'app/CMakeLists.txt' |
48 | --- app/CMakeLists.txt 2014-11-03 00:21:23 +0000 |
49 | +++ app/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
50 | @@ -1,15 +0,0 @@ |
51 | -file(GLOB QML_JS_FILES *.qml *.js) |
52 | - |
53 | -# make the files visible on qtcreator |
54 | -add_custom_target(quick-memo_QMlFiles ALL SOURCES ${QML_JS_FILES}) |
55 | - |
56 | -#substitute variables in the desktop file |
57 | -set(DESKTOP_FILE "quick-memo.desktop") |
58 | -configure_file(${DESKTOP_FILE_NAME}.in ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE_NAME}.in) |
59 | - |
60 | -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE} DESTINATION ${DESKTOP_DIR}) |
61 | -install(FILES ${QML_JS_FILES} DESTINATION ${APP_DIR}) |
62 | - |
63 | -add_subdirectory(components) |
64 | -add_subdirectory(ubuntucomponents) |
65 | - |
66 | |
67 | === added directory 'app/common' |
68 | === added file 'app/common/ColorDialog.qml' |
69 | --- app/common/ColorDialog.qml 1970-01-01 00:00:00 +0000 |
70 | +++ app/common/ColorDialog.qml 2015-04-26 16:57:43 +0000 |
71 | @@ -0,0 +1,168 @@ |
72 | +/* |
73 | + This file is part of quick-memo |
74 | + Copyright (C) 2014 Stefano Verzegnassi |
75 | + |
76 | + This program is free software: you can redistribute it and/or modify |
77 | + it under the terms of the GNU General Public License 3 as published by |
78 | + the Free Software Foundation. |
79 | + |
80 | + This program is distributed in the hope that it will be useful, |
81 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
82 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
83 | + GNU General Public License for more details. |
84 | + |
85 | + You should have received a copy of the GNU General Public License |
86 | + along with this program. If not, see http://www.gnu.org/licenses/. |
87 | +*/ |
88 | + |
89 | +import QtQuick 2.0 |
90 | +import Ubuntu.Components 1.1 |
91 | +import Ubuntu.Components.Popups 1.0 |
92 | + |
93 | +Dialog { |
94 | + id: rootItem |
95 | + |
96 | + title: i18n.tr("Pick a color") |
97 | + |
98 | + property var colors: ["#fdfdfd", "#e9674d", "#f0a250", "#eec34f", "#aea79f", "#95c253", "#8bbee2", "#e46f8e"] |
99 | + property color selectedColor: colors[0] |
100 | + |
101 | + property bool showTick: true |
102 | + property bool askConfirmation: false |
103 | + |
104 | + signal colorPicked(bool isChanged) |
105 | + |
106 | + onSelectedColorChanged: view.setCurrentColor() |
107 | + Component.onCompleted: internal.oldColor = rootItem.selectedColor |
108 | + |
109 | + QtObject { |
110 | + id: internal |
111 | + |
112 | + property color oldColor |
113 | + } |
114 | + |
115 | + Grid { |
116 | + id: grid |
117 | + width: parent.width |
118 | + |
119 | + columns: (width / cellWidth).toFixed(0) |
120 | + |
121 | + property int cellHeight: units.gu(5) |
122 | + property int cellWidth: units.gu(5) |
123 | + |
124 | + Repeater { |
125 | + id: view |
126 | + |
127 | + width: parent.width |
128 | + |
129 | + Component.onCompleted: setCurrentColor() |
130 | + |
131 | + function setCurrentColor() { |
132 | + if (rootItem.colors) { |
133 | + for (var i=0; i<rootItem.colors.length; i++) { |
134 | + if (rootItem.colors[i] == rootItem.selectedColor) { |
135 | + view.currentIndex = i |
136 | + } |
137 | + } |
138 | + } |
139 | + } |
140 | + |
141 | + model: rootItem.colors |
142 | + |
143 | + property int currentIndex: 0 |
144 | + |
145 | + delegate: AbstractButton { |
146 | + id: delegate |
147 | + |
148 | + height: grid.cellHeight |
149 | + width: grid.cellWidth |
150 | + |
151 | + onClicked: { |
152 | + view.currentIndex = model.index |
153 | + |
154 | + if (!rootItem.askConfirmation) { |
155 | + rootItem.selectedColor = rootItem.colors[view.currentIndex] |
156 | + |
157 | + console.log ("Old color:", internal.oldColor, "New color:", rootItem.selectedColor) |
158 | + if (internal.oldColor == rootItem.selectedColor) { |
159 | + rootItem.colorPicked(false) |
160 | + } else { |
161 | + rootItem.colorPicked(true) |
162 | + } |
163 | + |
164 | + rootItem.hide() |
165 | + } |
166 | + } |
167 | + |
168 | + UbuntuShape { |
169 | + anchors { fill: parent; margins: units.gu(0.5)} |
170 | + color: modelData |
171 | + clip: true |
172 | + |
173 | + Icon { |
174 | + id: tick |
175 | + anchors { fill: parent; margins: units.gu(0.5) } |
176 | + name: "tick" |
177 | + visible: view.currentIndex == model.index && rootItem.showTick |
178 | + color: getColor() |
179 | + |
180 | + function getColor() { |
181 | + return Qt.rgba(1 - parseInt(modelData.substr(1,2), 16) / 255, 1 - parseInt(modelData.substr(3,2), 16) / 255, 1 - parseInt(modelData.substr(5,2), 16) / 255) |
182 | + } |
183 | + } |
184 | + } |
185 | + } |
186 | + } |
187 | + } |
188 | + |
189 | + Column { |
190 | + width: parent.width |
191 | + spacing: units.gu(2) |
192 | + |
193 | + Loader { |
194 | + width: parent.width |
195 | + sourceComponent: if (askConfirmation) return confirmationButtons |
196 | + |
197 | + Component { |
198 | + id: confirmationButtons |
199 | + Button { |
200 | + width: parent.width |
201 | + text: i18n.tr("OK") |
202 | + color: UbuntuColors.orange |
203 | + |
204 | + onClicked: { |
205 | + rootItem.selectedColor = rootItem.colors[view.currentIndex] |
206 | + |
207 | + console.log ("Old color:", internal.oldColor, "New color:", rootItem.selectedColor) |
208 | + if (internal.oldColor == rootItem.selectedColor) { |
209 | + rootItem.colorPicked(false) |
210 | + } else { |
211 | + rootItem.colorPicked(true) |
212 | + } |
213 | + |
214 | + rootItem.hide() |
215 | + } |
216 | + } |
217 | + } |
218 | + } |
219 | + |
220 | + Button { |
221 | + width: parent.width |
222 | + text: i18n.tr("Cancel") |
223 | + |
224 | + onClicked: { |
225 | + rootItem.hide() |
226 | + |
227 | + for (var i=0; i<rootItem.colors.length; i++) { |
228 | + if (rootItem.colors[i] == internal.oldColor) { |
229 | + view.currentIndex = i |
230 | + } |
231 | + } |
232 | + rootItem.selectedColor = internal.oldColor |
233 | + } |
234 | + } |
235 | + } |
236 | + |
237 | + |
238 | + |
239 | +} |
240 | |
241 | === added file 'app/common/NoteModel.qml' |
242 | --- app/common/NoteModel.qml 1970-01-01 00:00:00 +0000 |
243 | +++ app/common/NoteModel.qml 2015-04-26 16:57:43 +0000 |
244 | @@ -0,0 +1,119 @@ |
245 | +/* |
246 | + This file is part of quick-memo |
247 | + Copyright (C) 2014 Stefano Verzegnassi |
248 | + |
249 | + This program is free software: you can redistribute it and/or modify |
250 | + it under the terms of the GNU General Public License 3 as published by |
251 | + the Free Software Foundation. |
252 | + |
253 | + This program is distributed in the hope that it will be useful, |
254 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
255 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
256 | + GNU General Public License for more details. |
257 | + |
258 | + You should have received a copy of the GNU General Public License |
259 | + along with this program. If not, see http://www.gnu.org/licenses/. |
260 | +*/ |
261 | + |
262 | +import QtQuick 2.0 |
263 | +import U1db 1.0 as U1db |
264 | +import Ubuntu.Components 1.1 |
265 | + |
266 | +Item { |
267 | + id: rootItem |
268 | + property alias model: model |
269 | + |
270 | + signal initialized() |
271 | + |
272 | + // *** functions |
273 | + function addNote(noteTitle, noteText, noteColor, noteList, notePictures) { |
274 | + // Get the current date |
275 | + var dateString = new Date().valueOf() |
276 | + |
277 | + db.putDoc(JSON.stringify({memos: {title: noteTitle, text: noteText, color: noteColor, date: dateString, list: noteList, pictures: notePictures}})) |
278 | + } |
279 | + |
280 | + // Function used for changing a single value of the note |
281 | + function setNoteProperty(index, field, value) { |
282 | + var obj = JSON.parse(JSON.stringify(model.get(index))) |
283 | + |
284 | + // Edit the required property |
285 | + switch(field) { |
286 | + case "title": |
287 | + obj.contents.title = value |
288 | + break |
289 | + case "text": |
290 | + obj.contents.text = value |
291 | + break |
292 | + case "color": |
293 | + // The char '#' from the hex color is not correctly parse by JSON. We add an empty string, so that it works well. |
294 | + obj.contents.color = "" + value |
295 | + break |
296 | + case "list": |
297 | + obj.contents.list = value |
298 | + break |
299 | + case "pictures": |
300 | + obj.contents.pictures = value |
301 | + } |
302 | + |
303 | + // Get the current date and update the time of the last update |
304 | + obj.contents.date = new Date().valueOf() |
305 | + |
306 | + db.putDoc(JSON.stringify({memos: obj.contents}), obj.docId) |
307 | + } |
308 | + |
309 | + // Function used for rewriting the whole content of the note. json variant is a JSON object. |
310 | + function editNote(index, json) { |
311 | + var obj = json |
312 | + |
313 | + // Get the current date and update the time of the last update |
314 | + obj.contents.date = new Date().valueOf() |
315 | + |
316 | + console.log(JSON.stringify({memos: obj.contents})) |
317 | + db.putDoc(JSON.stringify({memos: obj.contents}), obj.docId) |
318 | + } |
319 | + |
320 | + |
321 | + function deleteNote(index) { |
322 | + db.deleteDoc(model.get(index).docId) |
323 | + } |
324 | + |
325 | + function deleteNotes(indexes) { |
326 | + var deletedItemNumber = 0; |
327 | + for (var i=0; i<indexes.length; i++) { |
328 | + db.deleteDoc(model.get(indexes[i] - deletedItemNumber).docId) |
329 | + deletedItemNumber++ |
330 | + } |
331 | + } |
332 | + |
333 | + // *** U1db database |
334 | + U1db.Database { |
335 | + id: db |
336 | + path: "quick-memo" |
337 | + Component.onCompleted: { |
338 | + // TODO: Delete pictures that are not used by the notes at startup. |
339 | + rootItem.initialized() |
340 | + } |
341 | + } |
342 | + |
343 | + // TODO: More queries, more pages, a more powerful app. |
344 | + // TODO: Search feature. Use "filter" from SortFilterModel? |
345 | + SortFilterModel { |
346 | + id: model |
347 | + sort { |
348 | + property: "date" |
349 | + order: Qt.DescendingOrder |
350 | + } |
351 | + |
352 | + model: U1db.Query { |
353 | + id: query |
354 | + index: U1db.Index { |
355 | + database: db |
356 | + expression: ["memos.docId", "memos.title", "memos.text", "memos.color", "memos.date", "memos.list", "memos.pictures"] |
357 | + } |
358 | + query: ["*", "*", "*", "*", "*", "*", "*"] |
359 | + } |
360 | + } |
361 | + |
362 | + |
363 | +} |
364 | |
365 | === added file 'app/common/NoteTextArea.qml' |
366 | --- app/common/NoteTextArea.qml 1970-01-01 00:00:00 +0000 |
367 | +++ app/common/NoteTextArea.qml 2015-04-26 16:57:43 +0000 |
368 | @@ -0,0 +1,59 @@ |
369 | +/* |
370 | + This file is part of quick-memo |
371 | + Copyright (C) 2014 Stefano Verzegnassi |
372 | + |
373 | + This program is free software: you can redistribute it and/or modify |
374 | + it under the terms of the GNU General Public License 3 as published by |
375 | + the Free Software Foundation. |
376 | + |
377 | + This program is distributed in the hope that it will be useful, |
378 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
379 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
380 | + GNU General Public License for more details. |
381 | + |
382 | + You should have received a copy of the GNU General Public License |
383 | + along with this program. If not, see http://www.gnu.org/licenses/. |
384 | +*/ |
385 | + |
386 | +import QtQuick 2.0 |
387 | +import Ubuntu.Components 1.1 |
388 | +import Ubuntu.Components.Themes.Ambiance 0.1 |
389 | + |
390 | +TextArea { |
391 | + id: rootItem |
392 | + width: parent.width |
393 | + |
394 | + autoSize: true |
395 | + maximumLineCount: 0 |
396 | + |
397 | + // Prevent data loss |
398 | + inputMethodHints: Qt.ImhNoPredictiveText |
399 | + |
400 | + opacity: 1.0 |
401 | + |
402 | + signal focusLost() |
403 | + signal textReallyChanged |
404 | + |
405 | + property string __oldText: "" |
406 | + onTextChanged: { |
407 | + //WORKAROUND: textChanged seems to be emitted also when TextArea has the activeFocus (and text does not change). |
408 | + if (__oldText !== text) { |
409 | + rootItem.textReallyChanged() |
410 | + __oldText = text; |
411 | + } |
412 | + } |
413 | + |
414 | + InverseMouseArea { |
415 | + visible: parent.activeFocus |
416 | + anchors.fill: parent |
417 | + onClicked: { |
418 | + rootItem.focusLost() |
419 | + mouse.accepted = false |
420 | + } |
421 | + } |
422 | + |
423 | + style: TextAreaStyle { |
424 | + frameSpacing: 0 |
425 | + background: Item { anchors.fill: parent } |
426 | + } |
427 | +} |
428 | |
429 | === added file 'app/common/NoteTextField.qml' |
430 | --- app/common/NoteTextField.qml 1970-01-01 00:00:00 +0000 |
431 | +++ app/common/NoteTextField.qml 2015-04-26 16:57:43 +0000 |
432 | @@ -0,0 +1,53 @@ |
433 | +/* |
434 | + This file is part of quick-memo |
435 | + Copyright (C) 2014 Stefano Verzegnassi |
436 | + |
437 | + This program is free software: you can redistribute it and/or modify |
438 | + it under the terms of the GNU General Public License 3 as published by |
439 | + the Free Software Foundation. |
440 | + |
441 | + This program is distributed in the hope that it will be useful, |
442 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
443 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
444 | + GNU General Public License for more details. |
445 | + |
446 | + You should have received a copy of the GNU General Public License |
447 | + along with this program. If not, see http://www.gnu.org/licenses/. |
448 | +*/ |
449 | + |
450 | +import QtQuick 2.0 |
451 | +import Ubuntu.Components 1.1 |
452 | +import Ubuntu.Components.Themes.Ambiance 0.1 |
453 | + |
454 | +import "../ubuntucomponents" as UbuntuComponents |
455 | + |
456 | +// WORKAROUND: We need a 'custom' version of TextField in wait of LP:1376510 to be fixed. |
457 | +// FIXME: Some issue with InputHandler (e.g. Keys.Down or Keys.PgDown) but we don't care it, since at the moment the main focus is not desktop. |
458 | +UbuntuComponents.TextField { |
459 | + id: textArea |
460 | + width: parent.width - (checkBox.width + (parent.spacing * 2)) |
461 | + |
462 | + // Dynamic height: units.gu(3) = implicitHeight - (frameSpacing * 2) |
463 | + height: (contentHeight > units.gu(3)) ? contentHeight : units.gu(3) |
464 | + |
465 | + wrapMode: TextInput.Wrap |
466 | + |
467 | + // Prevent data loss |
468 | + inputMethodHints: Qt.ImhNoPredictiveText |
469 | + |
470 | + signal focusLost() |
471 | + signal focusReceived() |
472 | + |
473 | + onActiveFocusChanged: { |
474 | + if (activeFocus) { |
475 | + focusReceived() |
476 | + } else { |
477 | + focusLost() |
478 | + } |
479 | + } |
480 | + |
481 | + style: TextFieldStyle { |
482 | + frameSpacing: 0 |
483 | + background: Item { anchors.fill: parent } |
484 | + } |
485 | +} |
486 | |
487 | === added file 'app/common/PageBackground.qml' |
488 | --- app/common/PageBackground.qml 1970-01-01 00:00:00 +0000 |
489 | +++ app/common/PageBackground.qml 2015-04-26 16:57:43 +0000 |
490 | @@ -0,0 +1,25 @@ |
491 | +import QtQuick 2.0 |
492 | + |
493 | +// Background |
494 | +Rectangle { |
495 | + id: bg |
496 | + anchors.fill: parent |
497 | + z: -10; opacity: 0.5 |
498 | + |
499 | + property bool __parentPageAboutToBeClosed: false |
500 | + |
501 | + /* MainView clips its content, so that it does not overlap the header. |
502 | + We need to bypass this, using another Rectangle that specifically overlap the header. */ |
503 | + Rectangle { |
504 | + parent: root.header |
505 | + z: -10; opacity: 0.5 |
506 | + |
507 | + width: root.width |
508 | + height: root.header.height |
509 | + color: bg.color |
510 | + |
511 | + // FIXME: Header background should progressively change opacity to 0.0 when the BottomEdge page is dismissed. |
512 | + visible: !bg.__parentPageAboutToBeClosed |
513 | + } |
514 | +} |
515 | + |
516 | |
517 | === added file 'app/common/PageWithBottomEdge.qml' |
518 | --- app/common/PageWithBottomEdge.qml 1970-01-01 00:00:00 +0000 |
519 | +++ app/common/PageWithBottomEdge.qml 2015-04-26 16:57:43 +0000 |
520 | @@ -0,0 +1,407 @@ |
521 | +/* |
522 | + * Copyright (C) 2014 Canonical, Ltd. |
523 | + * |
524 | + * This program is free software; you can redistribute it and/or modify |
525 | + * it under the terms of the GNU General Public License as published by |
526 | + * the Free Software Foundation; version 3. |
527 | + * |
528 | + * This program is distributed in the hope that it will be useful, |
529 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
530 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
531 | + * GNU General Public License for more details. |
532 | + * |
533 | + * You should have received a copy of the GNU General Public License |
534 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
535 | + */ |
536 | + |
537 | +/* |
538 | + Example: |
539 | + |
540 | + MainView { |
541 | + objectName: "mainView" |
542 | + |
543 | + applicationName: "com.ubuntu.developer.boiko.bottomedge" |
544 | + |
545 | + width: units.gu(100) |
546 | + height: units.gu(75) |
547 | + |
548 | + Component { |
549 | + id: pageComponent |
550 | + |
551 | + PageWithBottomEdge { |
552 | + id: mainPage |
553 | + title: i18n.tr("Main Page") |
554 | + |
555 | + Rectangle { |
556 | + anchors.fill: parent |
557 | + color: "white" |
558 | + } |
559 | + |
560 | + bottomEdgePageComponent: Page { |
561 | + title: "Contents" |
562 | + anchors.fill: parent |
563 | + //anchors.topMargin: contentsPage.flickable.contentY |
564 | + |
565 | + ListView { |
566 | + anchors.fill: parent |
567 | + model: 50 |
568 | + delegate: ListItems.Standard { |
569 | + text: "One Content Item: " + index |
570 | + } |
571 | + } |
572 | + } |
573 | + bottomEdgeTitle: i18n.tr("Bottom edge action") |
574 | + } |
575 | + } |
576 | + |
577 | + PageStack { |
578 | + id: stack |
579 | + Component.onCompleted: stack.push(pageComponent) |
580 | + } |
581 | + } |
582 | + |
583 | +*/ |
584 | + |
585 | +import QtQuick 2.2 |
586 | +import Ubuntu.Components 1.1 |
587 | + |
588 | +Page { |
589 | + id: page |
590 | + |
591 | + property alias bottomEdgePageComponent: edgeLoader.sourceComponent |
592 | + property alias bottomEdgePageSource: edgeLoader.source |
593 | + property alias bottomEdgeTitle: tipLabel.text |
594 | + property bool bottomEdgeEnabled: true |
595 | + property int bottomEdgeExpandThreshold: page.height * 0.2 |
596 | + property int bottomEdgeExposedArea: bottomEdge.state !== "expanded" ? (page.height - bottomEdge.y - bottomEdge.tipHeight) : _areaWhenExpanded |
597 | + property bool reloadBottomEdgePage: true |
598 | + |
599 | + readonly property alias bottomEdgePage: edgeLoader.item |
600 | + readonly property bool isReady: ((bottomEdge.y === 0) && bottomEdgePageLoaded && edgeLoader.item.active) |
601 | + readonly property bool isCollapsed: (bottomEdge.y === page.height) |
602 | + readonly property bool bottomEdgePageLoaded: (edgeLoader.status == Loader.Ready) |
603 | + |
604 | + property bool _showEdgePageWhenReady: false |
605 | + property int _areaWhenExpanded: 0 |
606 | + |
607 | + signal bottomEdgeReleased() |
608 | + signal bottomEdgeDismissed() |
609 | + |
610 | + |
611 | + function showBottomEdgePage(source, properties) |
612 | + { |
613 | + edgeLoader.setSource(source, properties) |
614 | + _showEdgePageWhenReady = true |
615 | + } |
616 | + |
617 | + function setBottomEdgePage(source, properties) |
618 | + { |
619 | + edgeLoader.setSource(source, properties) |
620 | + } |
621 | + |
622 | + function _pushPage() |
623 | + { |
624 | + if (edgeLoader.status === Loader.Ready) { |
625 | + edgeLoader.item.active = true |
626 | + page.pageStack.push(edgeLoader.item) |
627 | + if (edgeLoader.item.flickable) { |
628 | + edgeLoader.item.flickable.contentY = -page.header.height |
629 | + edgeLoader.item.flickable.returnToBounds() |
630 | + } |
631 | + if (edgeLoader.item.ready) |
632 | + edgeLoader.item.ready() |
633 | + } |
634 | + } |
635 | + |
636 | + |
637 | + Component.onCompleted: { |
638 | + // avoid a binding on the expanded height value |
639 | + var expandedHeight = height; |
640 | + _areaWhenExpanded = expandedHeight; |
641 | + } |
642 | + |
643 | + onActiveChanged: { |
644 | + if (active) { |
645 | + bottomEdge.state = "collapsed" |
646 | + } |
647 | + } |
648 | + |
649 | + onBottomEdgePageLoadedChanged: { |
650 | + if (_showEdgePageWhenReady && bottomEdgePageLoaded) { |
651 | + bottomEdge.state = "expanded" |
652 | + _showEdgePageWhenReady = false |
653 | + } |
654 | + } |
655 | + |
656 | + Rectangle { |
657 | + id: bgVisual |
658 | + |
659 | + color: "black" |
660 | + anchors.fill: page |
661 | + opacity: 0.7 * ((page.height - bottomEdge.y) / page.height) |
662 | + z: 1 |
663 | + } |
664 | + |
665 | + UbuntuShape { |
666 | + id: tip |
667 | + objectName: "bottomEdgeTip" |
668 | + |
669 | + property bool hidden: (activeFocus === false) || ((bottomEdge.y - units.gu(1)) < tip.y) |
670 | + |
671 | + enabled: mouseArea.enabled |
672 | + visible: page.bottomEdgeEnabled |
673 | + anchors { |
674 | + bottom: parent.bottom |
675 | + horizontalCenter: bottomEdge.horizontalCenter |
676 | + bottomMargin: hidden ? - height + units.gu(1) : -units.gu(1) |
677 | + Behavior on bottomMargin { |
678 | + SequentialAnimation { |
679 | + // wait some msecs in case of the focus change again, to avoid flickering |
680 | + PauseAnimation { |
681 | + duration: 300 |
682 | + } |
683 | + UbuntuNumberAnimation { |
684 | + duration: UbuntuAnimation.SnapDuration |
685 | + } |
686 | + } |
687 | + } |
688 | + } |
689 | + |
690 | + z: 1 |
691 | + width: tipLabel.paintedWidth + units.gu(6) |
692 | + height: bottomEdge.tipHeight + units.gu(1) |
693 | + color: Theme.palette.normal.overlay |
694 | + Label { |
695 | + id: tipLabel |
696 | + |
697 | + anchors { |
698 | + top: parent.top |
699 | + left: parent.left |
700 | + right: parent.right |
701 | + } |
702 | + height: bottomEdge.tipHeight |
703 | + verticalAlignment: Text.AlignVCenter |
704 | + horizontalAlignment: Text.AlignHCenter |
705 | + opacity: tip.hidden ? 0.0 : 1.0 |
706 | + Behavior on opacity { |
707 | + UbuntuNumberAnimation { |
708 | + duration: UbuntuAnimation.SnapDuration |
709 | + } |
710 | + } |
711 | + } |
712 | + } |
713 | + |
714 | + Rectangle { |
715 | + id: shadow |
716 | + |
717 | + anchors { |
718 | + left: parent.left |
719 | + right: parent.right |
720 | + bottom: parent.bottom |
721 | + } |
722 | + height: units.gu(1) |
723 | + z: 1 |
724 | + opacity: 0.0 |
725 | + gradient: Gradient { |
726 | + GradientStop { position: 0.0; color: "transparent" } |
727 | + GradientStop { position: 1.0; color: Qt.rgba(0, 0, 0, 0.2) } |
728 | + } |
729 | + } |
730 | + |
731 | + MouseArea { |
732 | + id: mouseArea |
733 | + |
734 | + property real previousY: -1 |
735 | + property string dragDirection: "None" |
736 | + |
737 | + preventStealing: true |
738 | + drag { |
739 | + axis: Drag.YAxis |
740 | + target: bottomEdge |
741 | + minimumY: bottomEdge.pageStartY |
742 | + maximumY: page.height |
743 | + } |
744 | + enabled: edgeLoader.status == Loader.Ready |
745 | + visible: page.bottomEdgeEnabled |
746 | + |
747 | + anchors { |
748 | + left: parent.left |
749 | + right: parent.right |
750 | + bottom: parent.bottom |
751 | + |
752 | + } |
753 | + height: bottomEdge.tipHeight |
754 | + z: 1 |
755 | + |
756 | + onReleased: { |
757 | + page.bottomEdgeReleased() |
758 | + if ((dragDirection === "BottomToTop") && |
759 | + bottomEdge.y < (page.height - bottomEdgeExpandThreshold - bottomEdge.tipHeight)) { |
760 | + bottomEdge.state = "expanded" |
761 | + } else { |
762 | + bottomEdge.state = "collapsed" |
763 | + } |
764 | + previousY = -1 |
765 | + dragDirection = "None" |
766 | + } |
767 | + |
768 | + onPressed: { |
769 | + previousY = mouse.y |
770 | + tip.forceActiveFocus() |
771 | + } |
772 | + |
773 | + onMouseYChanged: { |
774 | + var yOffset = previousY - mouseY |
775 | + // skip if was a small move |
776 | + if (Math.abs(yOffset) <= units.gu(2)) { |
777 | + return |
778 | + } |
779 | + previousY = mouseY |
780 | + dragDirection = yOffset > 0 ? "BottomToTop" : "TopToBottom" |
781 | + } |
782 | + } |
783 | + |
784 | + Rectangle { |
785 | + id: bottomEdge |
786 | + objectName: "bottomEdge" |
787 | + |
788 | + readonly property int tipHeight: units.gu(3) |
789 | + readonly property int pageStartY: 0 |
790 | + |
791 | + z: 1 |
792 | + color: Theme.palette.normal.background |
793 | + clip: true |
794 | + anchors { |
795 | + left: parent.left |
796 | + right: parent.right |
797 | + } |
798 | + height: page.height |
799 | + y: height |
800 | + visible: !page.isCollapsed |
801 | + state: "collapsed" |
802 | + states: [ |
803 | + State { |
804 | + name: "collapsed" |
805 | + PropertyChanges { |
806 | + target: bottomEdge |
807 | + y: bottomEdge.height |
808 | + } |
809 | + }, |
810 | + State { |
811 | + name: "expanded" |
812 | + PropertyChanges { |
813 | + target: bottomEdge |
814 | + y: bottomEdge.pageStartY |
815 | + } |
816 | + }, |
817 | + State { |
818 | + name: "floating" |
819 | + when: mouseArea.drag.active |
820 | + PropertyChanges { |
821 | + target: shadow |
822 | + opacity: 1.0 |
823 | + } |
824 | + } |
825 | + ] |
826 | + |
827 | + transitions: [ |
828 | + Transition { |
829 | + to: "expanded" |
830 | + SequentialAnimation { |
831 | + alwaysRunToEnd: true |
832 | + |
833 | + SmoothedAnimation { |
834 | + target: bottomEdge |
835 | + property: "y" |
836 | + duration: UbuntuAnimation.FastDuration |
837 | + easing.type: Easing.Linear |
838 | + } |
839 | + SmoothedAnimation { |
840 | + target: edgeLoader |
841 | + property: "anchors.topMargin" |
842 | + to: - units.gu(4) |
843 | + duration: UbuntuAnimation.FastDuration |
844 | + easing.type: Easing.Linear |
845 | + } |
846 | + SmoothedAnimation { |
847 | + target: edgeLoader |
848 | + property: "anchors.topMargin" |
849 | + to: 0 |
850 | + duration: UbuntuAnimation.FastDuration |
851 | + easing: UbuntuAnimation.StandardEasing |
852 | + } |
853 | + ScriptAction { |
854 | + script: page._pushPage() |
855 | + } |
856 | + } |
857 | + }, |
858 | + Transition { |
859 | + from: "expanded" |
860 | + to: "collapsed" |
861 | + SequentialAnimation { |
862 | + alwaysRunToEnd: true |
863 | + |
864 | + ScriptAction { |
865 | + script: { |
866 | + Qt.inputMethod.hide() |
867 | + edgeLoader.item.parent = edgeLoader |
868 | + edgeLoader.item.anchors.fill = edgeLoader |
869 | + edgeLoader.item.active = false |
870 | + } |
871 | + } |
872 | + SmoothedAnimation { |
873 | + target: bottomEdge |
874 | + property: "y" |
875 | + duration: UbuntuAnimation.SlowDuration |
876 | + } |
877 | + ScriptAction { |
878 | + script: { |
879 | + // destroy current bottom page |
880 | + if (page.reloadBottomEdgePage) { |
881 | + edgeLoader.active = false |
882 | + // tip will receive focus on page active true |
883 | + } else { |
884 | + tip.forceActiveFocus() |
885 | + } |
886 | + |
887 | + // notify |
888 | + page.bottomEdgeDismissed() |
889 | + |
890 | + edgeLoader.active = true |
891 | + } |
892 | + } |
893 | + } |
894 | + }, |
895 | + Transition { |
896 | + from: "floating" |
897 | + to: "collapsed" |
898 | + SmoothedAnimation { |
899 | + target: bottomEdge |
900 | + property: "y" |
901 | + duration: UbuntuAnimation.FastDuration |
902 | + } |
903 | + } |
904 | + ] |
905 | + |
906 | + Loader { |
907 | + id: edgeLoader |
908 | + |
909 | + asynchronous: true |
910 | + anchors.fill: parent |
911 | + //WORKAROUND: The SDK move the page contents down to allocate space for the header we need to avoid that during the page dragging |
912 | + Binding { |
913 | + target: edgeLoader.status === Loader.Ready ? edgeLoader : null |
914 | + property: "anchors.topMargin" |
915 | + value: edgeLoader.item && edgeLoader.item.flickable ? edgeLoader.item.flickable.contentY : 0 |
916 | + when: !page.isReady |
917 | + } |
918 | + |
919 | + onLoaded: { |
920 | + tip.forceActiveFocus() |
921 | + if (page.isReady && edgeLoader.item.active !== true) { |
922 | + page._pushPage() |
923 | + } |
924 | + } |
925 | + } |
926 | + } |
927 | +} |
928 | |
929 | === added file 'app/common/Toaster.qml' |
930 | --- app/common/Toaster.qml 1970-01-01 00:00:00 +0000 |
931 | +++ app/common/Toaster.qml 2015-04-26 16:57:43 +0000 |
932 | @@ -0,0 +1,81 @@ |
933 | +/* |
934 | + This file is part of quick-memo |
935 | + Copyright (C) 2014 Stefano Verzegnassi |
936 | + |
937 | + This program is free software: you can redistribute it and/or modify |
938 | + it under the terms of the GNU General Public License 3 as published by |
939 | + the Free Software Foundation. |
940 | + |
941 | + This program is distributed in the hope that it will be useful, |
942 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
943 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
944 | + GNU General Public License for more details. |
945 | + |
946 | + You should have received a copy of the GNU General Public License |
947 | + along with this program. If not, see http://www.gnu.org/licenses/. |
948 | +*/ |
949 | + |
950 | +import QtQuick 2.0 |
951 | +import Ubuntu.Components 1.1 |
952 | + |
953 | +Rectangle { |
954 | + id: rootItem |
955 | + |
956 | + property alias text: label.text |
957 | + |
958 | + width: parent.width |
959 | + height: units.gu(8) |
960 | + |
961 | + color: "#131313" |
962 | + opacity: 0.85 |
963 | + |
964 | + anchors { |
965 | + horizontalCenter: parent.horizontalCenter |
966 | + bottom: parent.bottom; bottomMargin: - height |
967 | + } |
968 | + |
969 | + Label { |
970 | + id: label |
971 | + anchors.centerIn: parent |
972 | + |
973 | + font.weight: Font.DemiBold |
974 | + color: "white" |
975 | + } |
976 | + |
977 | + MouseArea { |
978 | + anchors.fill: parent |
979 | + |
980 | + onClicked: { |
981 | + showAnimation.stop() |
982 | + destroyAnimation.restart() |
983 | + } |
984 | + } |
985 | + |
986 | + Rectangle { |
987 | + anchors { |
988 | + bottom: parent.bottom |
989 | + left: parent.left |
990 | + right: parent.right |
991 | + } |
992 | + |
993 | + height: units.dp(2) |
994 | + color: UbuntuColors.orange |
995 | + } |
996 | + |
997 | + SequentialAnimation { |
998 | + id: showAnimation |
999 | + running: true |
1000 | + |
1001 | + NumberAnimation { target: rootItem; property: "anchors.bottomMargin"; to: 0; duration: 300 } |
1002 | + PauseAnimation { duration: 2000 } |
1003 | + ScriptAction { script: destroyAnimation.restart() } |
1004 | + } |
1005 | + |
1006 | + SequentialAnimation { |
1007 | + id: destroyAnimation |
1008 | + |
1009 | + NumberAnimation { target: rootItem; property: "opacity"; to: 0; duration: 500 } |
1010 | + ScriptAction { script: rootItem.destroy() } |
1011 | + } |
1012 | +} |
1013 | + |
1014 | |
1015 | === added file 'app/common/dateHelper.js' |
1016 | --- app/common/dateHelper.js 1970-01-01 00:00:00 +0000 |
1017 | +++ app/common/dateHelper.js 2015-04-26 16:57:43 +0000 |
1018 | @@ -0,0 +1,23 @@ |
1019 | +/* |
1020 | + This file is part of quick-memo |
1021 | + Copyright (C) 2014 Stefano Verzegnassi |
1022 | + |
1023 | + This program is free software: you can redistribute it and/or modify |
1024 | + it under the terms of the GNU General Public License 3 as published by |
1025 | + the Free Software Foundation. |
1026 | + |
1027 | + This program is distributed in the hope that it will be useful, |
1028 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
1029 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1030 | + GNU General Public License for more details. |
1031 | + |
1032 | + You should have received a copy of the GNU General Public License |
1033 | + along with this program. If not, see http://www.gnu.org/licenses/. |
1034 | +*/ |
1035 | + |
1036 | +function parseDate(value) { |
1037 | + var d = new Date(); |
1038 | + d.setTime(value) |
1039 | + |
1040 | + return d |
1041 | +} |
1042 | |
1043 | === removed file 'app/components/AboutPage.qml' |
1044 | --- app/components/AboutPage.qml 2015-01-17 20:25:00 +0000 |
1045 | +++ app/components/AboutPage.qml 1970-01-01 00:00:00 +0000 |
1046 | @@ -1,206 +0,0 @@ |
1047 | -/* |
1048 | - This file is part of quick-memo |
1049 | - Copyright (C) 2014-2015 Stefano Verzegnassi |
1050 | - |
1051 | - This program is free software: you can redistribute it and/or modify |
1052 | - it under the terms of the GNU General Public License 3 as published by |
1053 | - the Free Software Foundation. |
1054 | - |
1055 | - This program is distributed in the hope that it will be useful, |
1056 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
1057 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1058 | - GNU General Public License for more details. |
1059 | - |
1060 | - You should have received a copy of the GNU General Public License |
1061 | - along with this program. If not, see http://www.gnu.org/licenses/. |
1062 | -*/ |
1063 | - |
1064 | -import QtQuick 2.0 |
1065 | -import Ubuntu.Components 1.1 |
1066 | -import Ubuntu.Components.ListItems 1.0 as ListItem |
1067 | -import Ubuntu.Components.Popups 1.0 |
1068 | - |
1069 | -Page { |
1070 | - id: aboutPage |
1071 | - |
1072 | - title: i18n.tr("About") |
1073 | - head.sections.model: [i18n.tr("About"), i18n.tr("Credits"), i18n.tr("Copyright")] |
1074 | - |
1075 | - property string version |
1076 | - |
1077 | - Loader { |
1078 | - id: view |
1079 | - |
1080 | - anchors { |
1081 | - fill: parent |
1082 | - margins: units.gu(2) |
1083 | - } |
1084 | - |
1085 | - sourceComponent: { |
1086 | - if (aboutPage.head.sections.selectedIndex == 0) |
1087 | - return aboutSection |
1088 | - |
1089 | - if (aboutPage.head.sections.selectedIndex == 1) |
1090 | - return creditSection |
1091 | - |
1092 | - if (aboutPage.head.sections.selectedIndex == 2) |
1093 | - return copyrightSection |
1094 | - } |
1095 | - } |
1096 | - |
1097 | - // ABOUT SECTION |
1098 | - Component { |
1099 | - id: aboutSection |
1100 | - Column { |
1101 | - anchors.centerIn: parent |
1102 | - width: root.width > units.gu(50) ? units.gu(50) : parent.width |
1103 | - spacing: units.gu(4) |
1104 | - |
1105 | - UbuntuShape { |
1106 | - id: logo |
1107 | - |
1108 | - width: root.width > units.gu(50) ? units.gu(25) : parent.width / 2 |
1109 | - height: width |
1110 | - radius: "medium" |
1111 | - |
1112 | - image: Image { |
1113 | - source: "../../graphics/quick-memo.png" |
1114 | - } |
1115 | - |
1116 | - anchors.horizontalCenter: parent.horizontalCenter |
1117 | - } |
1118 | - |
1119 | - Column { |
1120 | - width: parent.width |
1121 | - |
1122 | - Label { |
1123 | - fontSize: "x-large" |
1124 | - font.weight: Font.DemiBold |
1125 | - text: "Quick Memo" |
1126 | - |
1127 | - anchors.horizontalCenter: parent.horizontalCenter |
1128 | - } |
1129 | - |
1130 | - Label { |
1131 | - // TRANSLATORS: Version of the software (e.g. "Version 0.3.51") |
1132 | - text: i18n.tr("Version ") + aboutPage.version |
1133 | - |
1134 | - anchors.horizontalCenter: parent.horizontalCenter |
1135 | - |
1136 | - Component.onCompleted: { |
1137 | - // Extract version info from manifest.json |
1138 | - var doc = new XMLHttpRequest(); |
1139 | - var json_string; |
1140 | - doc.onreadystatechange = function() { |
1141 | - if (doc.readyState == XMLHttpRequest.DONE) { |
1142 | - json_string = doc.responseText; |
1143 | - |
1144 | - if (json_string) { |
1145 | - var obj = JSON.parse(json_string) |
1146 | - aboutPage.version = obj.version |
1147 | - } else { |
1148 | - /* TRANSLATORS: This is shown where it's impossible to get |
1149 | - the version number (e.g. "Version UNKNOWN") */ |
1150 | - aboutPage.version = i18n.tr("UNKNOWN") |
1151 | - } |
1152 | - } |
1153 | - } |
1154 | - doc.open("get", Qt.resolvedUrl("../../app_info.json")); |
1155 | - |
1156 | - doc.setRequestHeader("Content-Encoding", "UTF-8"); |
1157 | - doc.send(); |
1158 | - } |
1159 | - } |
1160 | - } |
1161 | - |
1162 | - Column { |
1163 | - width: parent.width |
1164 | - |
1165 | - Label { |
1166 | - text: "(C) 2014-2015 Stefano Verzegnassi" |
1167 | - anchors.horizontalCenter: parent.horizontalCenter |
1168 | - } |
1169 | - |
1170 | - Label { |
1171 | - fontSize: "small" |
1172 | - text: i18n.tr("Released under the terms of the GNU GPL v3") |
1173 | - |
1174 | - anchors.horizontalCenter: parent.horizontalCenter |
1175 | - } |
1176 | - } |
1177 | - |
1178 | - Column { |
1179 | - width: parent.width |
1180 | - spacing: units.gu(2) |
1181 | - |
1182 | - Label { |
1183 | - fontSize: "small" |
1184 | - text: i18n.tr("Source code available on ") + "<a href=\"https://launchpad.net/quick-memo\">launchpad.net</a>" |
1185 | - |
1186 | - anchors.horizontalCenter: parent.horizontalCenter |
1187 | - |
1188 | - onLinkActivated: Qt.openUrlExternally(link) |
1189 | - } |
1190 | - } |
1191 | - } |
1192 | - } // END ABOUT SECTION |
1193 | - |
1194 | - // CREDITS SECTION |
1195 | - Component { |
1196 | - id: creditSection |
1197 | - |
1198 | - Column { |
1199 | - anchors.fill: parent |
1200 | - width: root.width > units.gu(50) ? units.gu(50) : parent.width |
1201 | - |
1202 | - ListItem.Header { |
1203 | - text: i18n.tr("A big thanks to:") |
1204 | - } |
1205 | - |
1206 | - ListItem.Subtitled { |
1207 | - text: "Nekhelesh Ramananthan" |
1208 | - subText: "Code contribution" |
1209 | - } |
1210 | - |
1211 | - ListItem.Subtitled { |
1212 | - text: "Renato Araujo Oliveira Filho" |
1213 | - subText: "Code contribution" |
1214 | - } |
1215 | - } |
1216 | - } // END CREDIT SECTION |
1217 | - |
1218 | - // COPYRIGHT SECTION |
1219 | - Component { |
1220 | - id: copyrightSection |
1221 | - |
1222 | - Flickable { |
1223 | - anchors.fill: parent |
1224 | - |
1225 | - clip: true |
1226 | - contentHeight: copyrightText.height |
1227 | - |
1228 | - // Indipendent GU flickable speed workaround |
1229 | - flickDeceleration: 1500 * units.gridUnit / 8 |
1230 | - maximumFlickVelocity: 2500 * units.gridUnit / 8 |
1231 | - |
1232 | - Label { |
1233 | - id: copyrightText |
1234 | - wrapMode: Text.WordWrap |
1235 | - width: parent.width |
1236 | - fontSize: "x-small" |
1237 | - |
1238 | - Component.onCompleted: { |
1239 | - var doc = new XMLHttpRequest(); |
1240 | - doc.onreadystatechange = function() { |
1241 | - if (doc.readyState == XMLHttpRequest.DONE) { |
1242 | - text = doc.responseText; |
1243 | - } |
1244 | - } |
1245 | - doc.open("get", Qt.resolvedUrl("../../copyright")); |
1246 | - doc.setRequestHeader("Content-Encoding", "UTF-8"); |
1247 | - doc.send(); |
1248 | - } |
1249 | - } |
1250 | - } |
1251 | - } |
1252 | -} |
1253 | |
1254 | === removed file 'app/components/CMakeLists.txt' |
1255 | --- app/components/CMakeLists.txt 2014-11-03 00:21:23 +0000 |
1256 | +++ app/components/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1257 | @@ -1,7 +0,0 @@ |
1258 | -file(GLOB COMPONENTS_QML_JS_FILES *.qml *.js) |
1259 | - |
1260 | -# make the files visible in the qtcreator tree |
1261 | -add_custom_target(quick-memo_components_QMlFiles ALL SOURCES ${COMPONENTS_QML_JS_FILES}) |
1262 | - |
1263 | -install(FILES ${COMPONENTS_QML_JS_FILES} DESTINATION ${APP_DIR}/components) |
1264 | - |
1265 | |
1266 | === removed file 'app/components/ColorDialog.qml' |
1267 | --- app/components/ColorDialog.qml 2014-09-02 00:16:08 +0000 |
1268 | +++ app/components/ColorDialog.qml 1970-01-01 00:00:00 +0000 |
1269 | @@ -1,168 +0,0 @@ |
1270 | -/* |
1271 | - This file is part of quick-memo |
1272 | - Copyright (C) 2014 Stefano Verzegnassi |
1273 | - |
1274 | - This program is free software: you can redistribute it and/or modify |
1275 | - it under the terms of the GNU General Public License 3 as published by |
1276 | - the Free Software Foundation. |
1277 | - |
1278 | - This program is distributed in the hope that it will be useful, |
1279 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
1280 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1281 | - GNU General Public License for more details. |
1282 | - |
1283 | - You should have received a copy of the GNU General Public License |
1284 | - along with this program. If not, see http://www.gnu.org/licenses/. |
1285 | -*/ |
1286 | - |
1287 | -import QtQuick 2.0 |
1288 | -import Ubuntu.Components 1.1 |
1289 | -import Ubuntu.Components.Popups 1.0 |
1290 | - |
1291 | -Dialog { |
1292 | - id: rootItem |
1293 | - |
1294 | - title: i18n.tr("Pick a color") |
1295 | - |
1296 | - property var colors: ["#fdfdfd", "#e9674d", "#f0a250", "#eec34f", "#aea79f", "#95c253", "#8bbee2", "#e46f8e"] |
1297 | - property color selectedColor: colors[0] |
1298 | - |
1299 | - property bool showTick: true |
1300 | - property bool askConfirmation: false |
1301 | - |
1302 | - signal colorPicked(bool isChanged) |
1303 | - |
1304 | - onSelectedColorChanged: view.setCurrentColor() |
1305 | - Component.onCompleted: internal.oldColor = rootItem.selectedColor |
1306 | - |
1307 | - QtObject { |
1308 | - id: internal |
1309 | - |
1310 | - property color oldColor |
1311 | - } |
1312 | - |
1313 | - Grid { |
1314 | - id: grid |
1315 | - width: parent.width |
1316 | - |
1317 | - columns: (width / cellWidth).toFixed(0) |
1318 | - |
1319 | - property int cellHeight: units.gu(5) |
1320 | - property int cellWidth: units.gu(5) |
1321 | - |
1322 | - Repeater { |
1323 | - id: view |
1324 | - |
1325 | - width: parent.width |
1326 | - |
1327 | - Component.onCompleted: setCurrentColor() |
1328 | - |
1329 | - function setCurrentColor() { |
1330 | - if (rootItem.colors) { |
1331 | - for (var i=0; i<rootItem.colors.length; i++) { |
1332 | - if (rootItem.colors[i] == rootItem.selectedColor) { |
1333 | - view.currentIndex = i |
1334 | - } |
1335 | - } |
1336 | - } |
1337 | - } |
1338 | - |
1339 | - model: rootItem.colors |
1340 | - |
1341 | - property int currentIndex: 0 |
1342 | - |
1343 | - delegate: AbstractButton { |
1344 | - id: delegate |
1345 | - |
1346 | - height: grid.cellHeight |
1347 | - width: grid.cellWidth |
1348 | - |
1349 | - onClicked: { |
1350 | - view.currentIndex = model.index |
1351 | - |
1352 | - if (!rootItem.askConfirmation) { |
1353 | - rootItem.selectedColor = rootItem.colors[view.currentIndex] |
1354 | - |
1355 | - console.log ("Old color:", internal.oldColor, "New color:", rootItem.selectedColor) |
1356 | - if (internal.oldColor == rootItem.selectedColor) { |
1357 | - rootItem.colorPicked(false) |
1358 | - } else { |
1359 | - rootItem.colorPicked(true) |
1360 | - } |
1361 | - |
1362 | - rootItem.hide() |
1363 | - } |
1364 | - } |
1365 | - |
1366 | - UbuntuShape { |
1367 | - anchors { fill: parent; margins: units.gu(0.5)} |
1368 | - color: modelData |
1369 | - clip: true |
1370 | - |
1371 | - Icon { |
1372 | - id: tick |
1373 | - anchors { fill: parent; margins: units.gu(0.5) } |
1374 | - name: "tick" |
1375 | - visible: view.currentIndex == model.index && rootItem.showTick |
1376 | - color: getColor() |
1377 | - |
1378 | - function getColor() { |
1379 | - return Qt.rgba(1 - parseInt(modelData.substr(1,2), 16) / 255, 1 - parseInt(modelData.substr(3,2), 16) / 255, 1 - parseInt(modelData.substr(5,2), 16) / 255) |
1380 | - } |
1381 | - } |
1382 | - } |
1383 | - } |
1384 | - } |
1385 | - } |
1386 | - |
1387 | - Column { |
1388 | - width: parent.width |
1389 | - spacing: units.gu(2) |
1390 | - |
1391 | - Loader { |
1392 | - width: parent.width |
1393 | - sourceComponent: if (askConfirmation) return confirmationButtons |
1394 | - |
1395 | - Component { |
1396 | - id: confirmationButtons |
1397 | - Button { |
1398 | - width: parent.width |
1399 | - text: i18n.tr("OK") |
1400 | - color: UbuntuColors.orange |
1401 | - |
1402 | - onClicked: { |
1403 | - rootItem.selectedColor = rootItem.colors[view.currentIndex] |
1404 | - |
1405 | - console.log ("Old color:", internal.oldColor, "New color:", rootItem.selectedColor) |
1406 | - if (internal.oldColor == rootItem.selectedColor) { |
1407 | - rootItem.colorPicked(false) |
1408 | - } else { |
1409 | - rootItem.colorPicked(true) |
1410 | - } |
1411 | - |
1412 | - rootItem.hide() |
1413 | - } |
1414 | - } |
1415 | - } |
1416 | - } |
1417 | - |
1418 | - Button { |
1419 | - width: parent.width |
1420 | - text: i18n.tr("Cancel") |
1421 | - |
1422 | - onClicked: { |
1423 | - rootItem.hide() |
1424 | - |
1425 | - for (var i=0; i<rootItem.colors.length; i++) { |
1426 | - if (rootItem.colors[i] == internal.oldColor) { |
1427 | - view.currentIndex = i |
1428 | - } |
1429 | - } |
1430 | - rootItem.selectedColor = internal.oldColor |
1431 | - } |
1432 | - } |
1433 | - } |
1434 | - |
1435 | - |
1436 | - |
1437 | -} |
1438 | |
1439 | === removed file 'app/components/Delegate.qml' |
1440 | --- app/components/Delegate.qml 2014-11-06 05:09:59 +0000 |
1441 | +++ app/components/Delegate.qml 1970-01-01 00:00:00 +0000 |
1442 | @@ -1,291 +0,0 @@ |
1443 | -/* |
1444 | - This file is part of quick-memo |
1445 | - Copyright (C) 2014 Stefano Verzegnassi |
1446 | - |
1447 | - This program is free software: you can redistribute it and/or modify |
1448 | - it under the terms of the GNU General Public License 3 as published by |
1449 | - the Free Software Foundation. |
1450 | - |
1451 | - This program is distributed in the hope that it will be useful, |
1452 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
1453 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1454 | - GNU General Public License for more details. |
1455 | - |
1456 | - You should have received a copy of the GNU General Public License |
1457 | - along with this program. If not, see http://www.gnu.org/licenses/. |
1458 | -*/ |
1459 | - |
1460 | -import QtQuick 2.0 |
1461 | -import Ubuntu.Components 1.1 |
1462 | -import Ubuntu.Thumbnailer 0.1 |
1463 | -import "dateHelper.js" as DateHelper |
1464 | - |
1465 | -AbstractButton { |
1466 | - id: rootItem |
1467 | - |
1468 | - height: layout.height + layout.anchors.topMargin |
1469 | - width: parent.width |
1470 | - |
1471 | - property bool selected: false |
1472 | - property int maxListDelegatesNumber: 3 |
1473 | - |
1474 | - // RGB channels from 'shape.color' are in [0; 1] range. |
1475 | - property color foregroundColor: ((shape.color.r * 0.30 + shape.color.g * 0.59 + shape.color.b * 0.11) > 0.5) ? UbuntuColors.darkGrey : "#F3F3E7" |
1476 | - |
1477 | - UbuntuShape { |
1478 | - id: shape |
1479 | - anchors.fill: parent |
1480 | - |
1481 | - // Add 70% opacity |
1482 | - color: contents.color.toString().replace("#", "#B3") |
1483 | - |
1484 | - radius: "medium" |
1485 | - |
1486 | - Column { |
1487 | - id: layout |
1488 | - anchors { top: parent.top; left: parent.left; right: parent.right; topMargin: units.gu(2) } |
1489 | - |
1490 | - Column { |
1491 | - id: column |
1492 | - width: parent.width - (spacing * 2) |
1493 | - x: spacing |
1494 | - spacing: units.gu(2) |
1495 | - |
1496 | - Loader { |
1497 | - width: parent.width |
1498 | - sourceComponent: (contents.title == "") ? undefined : titleComponent |
1499 | - |
1500 | - Component { |
1501 | - id: titleComponent |
1502 | - |
1503 | - Label { |
1504 | - width: parent.width |
1505 | - fontSize: "large" |
1506 | - font.weight: Font.Bold |
1507 | - text: contents.title |
1508 | - elide: Text.ElideRight |
1509 | - maximumLineCount: 2 |
1510 | - wrapMode: Text.WrapAnywhere |
1511 | - color: rootItem.foregroundColor |
1512 | - } |
1513 | - } |
1514 | - |
1515 | - } |
1516 | - |
1517 | - Loader { |
1518 | - width: parent.width |
1519 | - sourceComponent: (contents.text == "") ? undefined : textComponent |
1520 | - |
1521 | - Component { |
1522 | - id: textComponent |
1523 | - |
1524 | - Label { |
1525 | - width: parent.width |
1526 | - text: contents.text |
1527 | - wrapMode: Text.WrapAnywhere |
1528 | - elide: Text.ElideRight |
1529 | - maximumLineCount: 5 |
1530 | - color: rootItem.foregroundColor |
1531 | - } |
1532 | - } |
1533 | - } |
1534 | - } |
1535 | - |
1536 | - // A spacer item |
1537 | - Item { |
1538 | - width: parent.width |
1539 | - height: units.gu(2) |
1540 | - visible: picsRepeater.count > 0 |
1541 | - } |
1542 | - |
1543 | - Item { |
1544 | - id: picsItem |
1545 | - width: parent.width |
1546 | - height: picFlow.height |
1547 | - |
1548 | - // TODO: As for listDelegates, limit pics to a number of 9 |
1549 | - Flow { |
1550 | - id: picFlow |
1551 | - width: parent.width |
1552 | - |
1553 | - Repeater { |
1554 | - id: picsRepeater |
1555 | - |
1556 | - model: contents.pictures |
1557 | - |
1558 | - delegate: Image { |
1559 | - id: img |
1560 | - width: parent.width |
1561 | - fillMode: Image.PreserveAspectCrop |
1562 | - source: "image://thumbnailer/" + Qt.resolvedUrl(contents.pictures[index].url) |
1563 | - |
1564 | - Connections { |
1565 | - target: picsRepeater |
1566 | - onItemAdded: calculateSize(index) |
1567 | - onItemRemoved: calculateSize(index) |
1568 | - } |
1569 | - |
1570 | - Connections { |
1571 | - target: picFlow |
1572 | - onWidthChanged: calculateSize(index) |
1573 | - } |
1574 | - |
1575 | - Component.onCompleted: calculateSize(index) |
1576 | - |
1577 | - function calculateSize(index) { |
1578 | - var n = picsRepeater.count |
1579 | - var i = n % 3 |
1580 | - var m = Math.floor(n / 3) |
1581 | - |
1582 | - height = units.gu(6) |
1583 | - |
1584 | - // Need to be hardcoded because of an issue. |
1585 | - // FIXME: Think it requires a better solution |
1586 | - var picFlowRealWidth = ((root.width - units.gu(4)) * 0.5) - units.gu(1) |
1587 | - |
1588 | - switch(i) { |
1589 | - case 0: |
1590 | - width = picFlowRealWidth / 3 |
1591 | - return |
1592 | - case 1: |
1593 | - if (index == 0) { |
1594 | - width = picFlowRealWidth |
1595 | - return |
1596 | - } else { |
1597 | - width = picFlowRealWidth / 3 |
1598 | - return |
1599 | - } |
1600 | - case 2: |
1601 | - if (index <= 1) { |
1602 | - width = picFlowRealWidth / 2 |
1603 | - return |
1604 | - } else { |
1605 | - width = picFlowRealWidth / 3 |
1606 | - return |
1607 | - } |
1608 | - } |
1609 | - } |
1610 | - } |
1611 | - } |
1612 | - |
1613 | - Component.onCompleted: picsRepeater.model = contents.pictures |
1614 | - } |
1615 | - } |
1616 | - |
1617 | - Loader { |
1618 | - id: listLoader |
1619 | - width: parent.width |
1620 | - sourceComponent: (contents.list[0]) ? listComponent : null |
1621 | - |
1622 | - Component { |
1623 | - id: listComponent |
1624 | - |
1625 | - Column { |
1626 | - width: parent.width |
1627 | - |
1628 | - // A spacer item |
1629 | - Item { |
1630 | - width: parent.width |
1631 | - height: units.gu(1) |
1632 | - } |
1633 | - |
1634 | - Repeater { |
1635 | - id: listRepeater |
1636 | - width: parent.width |
1637 | - |
1638 | - model: contents.list |
1639 | - |
1640 | - delegate: Loader { |
1641 | - width: parent.width |
1642 | - sourceComponent: model.index < 4 ? listDelegate : null |
1643 | - |
1644 | - Component { |
1645 | - id: listDelegate |
1646 | - |
1647 | - Row { |
1648 | - id: rootItem |
1649 | - spacing: units.gu(1) |
1650 | - width: parent.width |
1651 | - height: Math.max(checkBox.height, textArea.height) |
1652 | - |
1653 | - Item { |
1654 | - id: checkBox |
1655 | - width: parent.width |
1656 | - height: units.gu(4) |
1657 | - |
1658 | - property bool checked: contents.list[index].checked |
1659 | - |
1660 | - Icon { |
1661 | - id: tick |
1662 | - anchors { |
1663 | - left: parent.left; leftMargin: units.gu(2.25); |
1664 | - top: parent.top; topMargin: units.gu(0.35) |
1665 | - } |
1666 | - width: (source == "../../graphics/select.svg") ? units.gu(2.25) : units.gu(1.5) |
1667 | - height: (source == "../../graphics/select.svg") ? units.gu(2) : units.gu(1.5) |
1668 | - |
1669 | - source: checkBox.checked ? "../../graphics/select.svg" : "../../graphics/unselect.svg" |
1670 | - visible: model.index !== 3 |
1671 | - color: foregroundColor |
1672 | - } |
1673 | - |
1674 | - Label { |
1675 | - id: textArea |
1676 | - anchors { left: tick.right; right: parent.right; margins: units.gu(1) } |
1677 | - |
1678 | - font.strikeout: checkBox.checked |
1679 | - text: (model.index == 3) ? ". . ." : contents.list[index].text |
1680 | - elide: Text.ElideRight |
1681 | - maximumLineCount: 2 |
1682 | - wrapMode: Text.WrapAnywhere |
1683 | - color: foregroundColor |
1684 | - } |
1685 | - } |
1686 | - } |
1687 | - } |
1688 | - } |
1689 | - } |
1690 | - |
1691 | - Component.onCompleted: listRepeater.model = contents.list |
1692 | - } |
1693 | - } |
1694 | - } |
1695 | - |
1696 | - // A spacer item |
1697 | - Item { |
1698 | - width: parent.width |
1699 | - height: units.gu(2) |
1700 | - } |
1701 | - |
1702 | - Item { |
1703 | - id: date |
1704 | - width: parent.width |
1705 | - height: units.gu(4) |
1706 | - |
1707 | - Label { |
1708 | - anchors { right: parent.right; verticalCenter: parent.verticalCenter; margins: units.gu(2) } |
1709 | - text: Qt.formatDateTime(DateHelper.parseDate(contents.date), "d MMM yyyy, hh:mm") |
1710 | - fontSize: "small" |
1711 | - color: rootItem.foregroundColor |
1712 | - } |
1713 | - } |
1714 | - } |
1715 | - } |
1716 | - |
1717 | - // Visual feedback when pressed. Not listed in official documentation, still useful. |
1718 | - onPressedChanged: { |
1719 | - if (pressed) |
1720 | - shape.borderSource = "radius_pressed.sci" |
1721 | - else |
1722 | - shape.borderSource = "radius_idle.sci" |
1723 | - } |
1724 | - |
1725 | - // Visual feedback when selected. |
1726 | - onSelectedChanged: { |
1727 | - if (selected) { |
1728 | - shape.color = Qt.darker(contents.color) |
1729 | - } else { |
1730 | - shape.color = contents.color.toString().replace("#", "#B3") |
1731 | - } |
1732 | - } |
1733 | -} |
1734 | |
1735 | === removed file 'app/components/EditMemoPage.qml' |
1736 | --- app/components/EditMemoPage.qml 2015-01-17 20:30:56 +0000 |
1737 | +++ app/components/EditMemoPage.qml 1970-01-01 00:00:00 +0000 |
1738 | @@ -1,328 +0,0 @@ |
1739 | -/* |
1740 | - This file is part of quick-memo |
1741 | - Copyright (C) 2014-2015 Stefano Verzegnassi |
1742 | - |
1743 | - This program is free software: you can redistribute it and/or modify |
1744 | - it under the terms of the GNU General Public License 3 as published by |
1745 | - the Free Software Foundation. |
1746 | - |
1747 | - This program is distributed in the hope that it will be useful, |
1748 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
1749 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1750 | - GNU General Public License for more details. |
1751 | - |
1752 | - You should have received a copy of the GNU General Public License |
1753 | - along with this program. If not, see http://www.gnu.org/licenses/. |
1754 | -*/ |
1755 | - |
1756 | -import QtQuick 2.0 |
1757 | -import Ubuntu.Components 1.1 |
1758 | -import Ubuntu.Keyboard 0.1 |
1759 | -import Ubuntu.Components.Popups 1.0 |
1760 | -import Ubuntu.Components.ListItems 1.0 as ListItem |
1761 | - |
1762 | -import "dateHelper.js" as DateHelper |
1763 | - |
1764 | -Page { |
1765 | - id: memoPage |
1766 | - title: editMemo ? i18n.tr("Details") : i18n.tr("Add a new memo") |
1767 | - |
1768 | - /* This page has two modes: NewMemo and EditMemo. |
1769 | - Following properties are used to load the right mode. |
1770 | - */ |
1771 | - property bool editMemo: false |
1772 | - property int index |
1773 | - |
1774 | - property bool canSave: (title.text != "") || (desc.text != "") || (listManager.model.count > 0) || (picsView.model.count > 0) |
1775 | - property bool contentChanged: false |
1776 | - |
1777 | - // Load an existent memo if required |
1778 | - Component.onCompleted: { if (editMemo) loadNote() } |
1779 | - |
1780 | - head.backAction: editMemo ? backEditMemo : backNewMemo |
1781 | - head.actions: [colorToolAction, deleteMemo, saveMemo] |
1782 | - |
1783 | - // Background |
1784 | - PageBackground { id: bg } |
1785 | - |
1786 | - // flickable property needs to be explicitly set, to avoid a binding loop for memoPage.height |
1787 | - flickable: flickable |
1788 | - Flickable { |
1789 | - id: flickable |
1790 | - anchors.fill: parent |
1791 | - |
1792 | - // Indipendent GU flickable speed workaround |
1793 | - flickDeceleration: 1500 * units.gridUnit / 8 |
1794 | - maximumFlickVelocity: 2500 * units.gridUnit / 8 |
1795 | - |
1796 | - // Could this be an SDK-related issue? |
1797 | - contentHeight: layout.height + root.header.height |
1798 | - interactive: contentHeight > height |
1799 | - |
1800 | - Column { |
1801 | - id: layout |
1802 | - anchors { left: parent.left; right: parent.right } |
1803 | - spacing: units.gu(1) |
1804 | - |
1805 | - // Spacing |
1806 | - Item { width: parent.width; height: units.gu(1) } |
1807 | - |
1808 | - NoteTextField { |
1809 | - id: title |
1810 | - x: units.gu(2); width: parent.width - units.gu(4) |
1811 | - |
1812 | - font.weight: Font.Bold |
1813 | - font.pixelSize: FontUtils.sizeToPixels("large") |
1814 | - |
1815 | - placeholderText: i18n.tr("No title") |
1816 | - onFocusLost: flickable.forceActiveFocus() |
1817 | - |
1818 | - // Ubuntu Keyboard |
1819 | - /* TRANSLATORS: This is a custom text for the "enter" key of |
1820 | - the on-screen keyboard (max 4 char, so it's not elided) */ |
1821 | - InputMethod.extensions: { "enterKeyText": i18n.tr("Next") } |
1822 | - Keys.onReturnPressed: desc.forceActiveFocus() |
1823 | - } |
1824 | - |
1825 | - NoteTextArea { |
1826 | - id: desc |
1827 | - x: units.gu(2); width: parent.width - units.gu(4) |
1828 | - |
1829 | - placeholderText: i18n.tr("No description") |
1830 | - onFocusLost: flickable.forceActiveFocus() |
1831 | - } |
1832 | - |
1833 | - ListManager { |
1834 | - id: listManager |
1835 | - |
1836 | - width: parent.width |
1837 | - flickable: flickable |
1838 | - } |
1839 | - |
1840 | - PicturesManager { id: picsView; width: parent.width } |
1841 | - |
1842 | - Label { |
1843 | - id: updateLabel |
1844 | - anchors { right: parent.right; rightMargin: units.gu(2) } |
1845 | - |
1846 | - fontSize: "x-small" |
1847 | - visible: editMemo |
1848 | - |
1849 | - function refresh() { |
1850 | - updateLabel.text = i18n.tr("Last update: %1").arg(Qt.formatDateTime(DateHelper.parseDate(notes.model.get(index).contents.date), "d MMM yyyy, hh:mm:ss")) |
1851 | - } |
1852 | - } |
1853 | - } |
1854 | - } |
1855 | - |
1856 | - // Used for auto saving while editing fields |
1857 | - Timer { |
1858 | - id: autoSaveTimer |
1859 | - interval: 1000 // Is this a good timing? |
1860 | - |
1861 | - onTriggered: { |
1862 | - if (!canSave) { // Change timer inteval if can't save? |
1863 | - deleteDialog.emptyMemo = true; |
1864 | - deleteDialog.show(); |
1865 | - } else { |
1866 | - console.log("autoSaveTimer triggered... updating the note!") |
1867 | - saveNote() |
1868 | - } |
1869 | - } |
1870 | - } |
1871 | - |
1872 | - function loadNote() { |
1873 | - var memoObj = notes.model.get(index) |
1874 | - |
1875 | - title.text = memoObj.contents.title |
1876 | - desc.text = memoObj.contents.text |
1877 | - bg.color = memoObj.contents.color |
1878 | - |
1879 | - // Append list items provided by NoteModel |
1880 | - listManager.model.clear() |
1881 | - for (var i=0; i<memoObj.contents.list.length; i++) { |
1882 | - listManager.model.append(JSON.parse(JSON.stringify(memoObj.contents.list[i]))) |
1883 | - } |
1884 | - |
1885 | - // Append pictures items provided by NoteModel |
1886 | - picsView.model.clear() |
1887 | - for (var i=0; i<memoObj.contents.pictures.length; i++) { |
1888 | - picsView.model.append(JSON.parse(JSON.stringify(memoObj.contents.pictures[i]))) |
1889 | - } |
1890 | - |
1891 | - // Connect signals for auto-saving |
1892 | - title.textChanged.connect(updateNote) |
1893 | - desc.textReallyChanged.connect(updateNote) |
1894 | - listManager.listChanged.connect(updateNote) |
1895 | - picsView.picsModelChanged.connect(updateNote) |
1896 | - bg.colorChanged.connect(updateNote) |
1897 | - |
1898 | - updateLabel.refresh() |
1899 | - } |
1900 | - |
1901 | - function updateNote() { |
1902 | - autoSaveTimer.restart() |
1903 | - } |
1904 | - |
1905 | - function saveNote() { |
1906 | - var obj = JSON.parse(JSON.stringify(notes.model.get(index))) |
1907 | - |
1908 | - obj.contents.title = title.text |
1909 | - obj.contents.text = desc.text |
1910 | - // The char '#' from the hex color is not correctly parse by JSON. We add an empty string, so that it works well. |
1911 | - obj.contents.color = "" + bg.color |
1912 | - obj.contents.list = listManager.exportModel() |
1913 | - obj.contents.pictures = picsView.exportModel() |
1914 | - |
1915 | - notes.editNote(memoPage.index, obj) |
1916 | - updateLabel.refresh() |
1917 | - |
1918 | - memoPage.contentChanged = true; |
1919 | - } |
1920 | - |
1921 | - function addNote() { |
1922 | - notes.addNote(title.text, |
1923 | - desc.text, |
1924 | - "" + bg.color, // The char '#' from the hex color is not correctly parse by JSON. We add an empty string, so that it works well. |
1925 | - listManager.exportModel(), |
1926 | - picsView.exportModel()) |
1927 | - pageStack.pop() |
1928 | - |
1929 | - root.showNotification(i18n.tr("Memo saved!")) |
1930 | - } |
1931 | - |
1932 | - // *** ACTIONS *** |
1933 | - Action { |
1934 | - id: saveMemo |
1935 | - text: i18n.tr("Save") |
1936 | - iconName: "ok" |
1937 | - onTriggered: addNote() |
1938 | - |
1939 | - visible: !editMemo |
1940 | - enabled: canSave |
1941 | - } |
1942 | - Action { |
1943 | - id: deleteMemo |
1944 | - text: i18n.tr("Delete memo") |
1945 | - iconName: "delete" |
1946 | - onTriggered: deleteDialog.show() |
1947 | - visible: editMemo |
1948 | - } |
1949 | - Action { |
1950 | - id: colorToolAction |
1951 | - text: i18n.tr("Change memo color") |
1952 | - iconSource: "../../graphics/palette.svg" |
1953 | - onTriggered: PopupUtils.open(colorNotePopover) |
1954 | - } |
1955 | - |
1956 | - // *** BACK ACTIONS *** |
1957 | - Action { |
1958 | - id: backEditMemo |
1959 | - iconName: "back" |
1960 | - onTriggered: { |
1961 | - if (!canSave) { |
1962 | - deleteDialog.emptyMemo = true; |
1963 | - deleteDialog.show(); |
1964 | - } else { |
1965 | - // Check if a saveNote request was made. If so, stop the timer and save before exiting the page. |
1966 | - if (autoSaveTimer.running) { |
1967 | - console.log("It's ok. Saving the note before closing the page...") |
1968 | - autoSaveTimer.running = false |
1969 | - saveNote() |
1970 | - } |
1971 | - pageStack.pop() |
1972 | - |
1973 | - /* Workaround: see MainPage.qml, comment for mainView.delegate.onClicked(). |
1974 | - We simply re-push in the stack what we removed earlier.*/ |
1975 | - pageStack.push(mainPage) |
1976 | - |
1977 | - if (memoPage.contentChanged) |
1978 | - root.showNotification(i18n.tr("Memo updated!")) |
1979 | - } |
1980 | - } |
1981 | - } |
1982 | - |
1983 | - Action { |
1984 | - id: backNewMemo |
1985 | - iconName: "close" |
1986 | - onTriggered: { |
1987 | - if (canSave) |
1988 | - PopupUtils.open(dataLosingOnBackDialog) |
1989 | - else { |
1990 | - // Just a pop() because this is called only when the page is loaded through bottomEdge. |
1991 | - pageStack.pop() |
1992 | - |
1993 | - root.showNotification(i18n.tr("Memo aborted!")) |
1994 | - } |
1995 | - } |
1996 | - } |
1997 | - |
1998 | - // *** DIALOGS *** |
1999 | - Dialog { |
2000 | - id: deleteDialog |
2001 | - |
2002 | - property bool emptyMemo: false |
2003 | - |
2004 | - title: emptyMemo ? i18n.tr("Empty memo") : i18n.tr("Delete memo") |
2005 | - text: emptyMemo ? i18n.tr("This memo has no content.") : i18n.tr("Are you sure?") |
2006 | - |
2007 | - Button { |
2008 | - text: i18n.tr("Cancel") |
2009 | - gradient: UbuntuColors.greyGradient |
2010 | - onClicked: deleteDialog.hide() |
2011 | - visible: !emptyMemo |
2012 | - } |
2013 | - Button { |
2014 | - text: i18n.tr("Delete") |
2015 | - color: UbuntuColors.orange |
2016 | - onClicked: { |
2017 | - deleteDialog.hide() |
2018 | - pageStack.pop(); |
2019 | - pageStack.push(mainPage) |
2020 | - notes.deleteNote(index) |
2021 | - |
2022 | - root.showNotification(i18n.tr("Memo deleted!")) |
2023 | - } |
2024 | - } |
2025 | - } |
2026 | - |
2027 | - Component { |
2028 | - id: dataLosingOnBackDialog |
2029 | - Dialog { |
2030 | - id: dataLosingOnBackDialogue |
2031 | - |
2032 | - title: i18n.tr("Discard changes?") |
2033 | - text: i18n.tr("Your memo will be PERMANENTLY lost.") |
2034 | - |
2035 | - Button { |
2036 | - text: i18n.tr("Cancel") |
2037 | - gradient: UbuntuColors.greyGradient |
2038 | - onClicked: PopupUtils.close(dataLosingOnBackDialogue) |
2039 | - } |
2040 | - Button { |
2041 | - text: i18n.tr("Go back!") |
2042 | - color: UbuntuColors.orange |
2043 | - onClicked: { |
2044 | - PopupUtils.close(dataLosingOnBackDialogue) |
2045 | - pageStack.pop(); |
2046 | - } |
2047 | - } |
2048 | - } |
2049 | - } |
2050 | - |
2051 | - Component { |
2052 | - id: colorNotePopover |
2053 | - |
2054 | - ColorDialog { |
2055 | - id: colorDialog |
2056 | - |
2057 | - selectedColor: bg.color |
2058 | - onColorPicked: { |
2059 | - if (isChanged) |
2060 | - bg.color = selectedColor |
2061 | - |
2062 | - PopupUtils.close(colorDialog) |
2063 | - } |
2064 | - } |
2065 | - } |
2066 | -} |
2067 | |
2068 | === removed file 'app/components/HorizontalFlowListView.qml' |
2069 | --- app/components/HorizontalFlowListView.qml 2014-10-04 18:40:51 +0000 |
2070 | +++ app/components/HorizontalFlowListView.qml 1970-01-01 00:00:00 +0000 |
2071 | @@ -1,78 +0,0 @@ |
2072 | -/* |
2073 | - * Copyright 2012 Ruediger Gad |
2074 | - * Copyright 2014 Stefano Verzegnassi <stefano92.100@gmail.com> |
2075 | - * |
2076 | - * This file is part of FlowListView. |
2077 | - * |
2078 | - * FlowListView is free software: you can redistribute it and/or modify |
2079 | - * it under the terms of the GNU Lesser General Public License (LGPL) |
2080 | - * as published by the Free Software Foundation, either version 3 of the |
2081 | - * License, or (at your option) any later version. |
2082 | - * |
2083 | - * FlowListView is distributed in the hope that it will be useful, |
2084 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2085 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2086 | - * GNU General Public License for more details. |
2087 | - * |
2088 | - * You should have received a copy of the GNU Lesser General Public License |
2089 | - * along with FlowListView. If not, see <http://www.gnu.org/licenses/>. |
2090 | - * |
2091 | - */ |
2092 | - |
2093 | -// A derivative version of FlowListView.qml |
2094 | -import QtQuick 2.0 |
2095 | -import Ubuntu.Components 1.1 |
2096 | - |
2097 | -Flickable { |
2098 | - id: flowListView |
2099 | - |
2100 | - contentWidth: flow.childrenRect.width |
2101 | - |
2102 | - property alias count: repeater.count |
2103 | - property int currentIndex: -1 |
2104 | - property variant currentItem; |
2105 | - property alias delegate: repeater.delegate |
2106 | - property alias model: repeater.model |
2107 | - |
2108 | - property alias spacing: flow.spacing |
2109 | - |
2110 | - property alias add: flow.add |
2111 | - property alias populate: flow.populate |
2112 | - property alias move: flow.move |
2113 | - |
2114 | - // Indipendent GU flickable speed workaround |
2115 | - flickDeceleration: 1500 * units.gridUnit / 8 |
2116 | - maximumFlickVelocity: 2500 * units.gridUnit / 8 |
2117 | - |
2118 | - onCurrentIndexChanged: { |
2119 | - currentItem = repeater.itemAt(currentIndex) |
2120 | - } |
2121 | - |
2122 | - Flow { |
2123 | - id: flow |
2124 | - |
2125 | - height: parent.height |
2126 | - flow: Flow.TopToBottom |
2127 | - |
2128 | - Item { width: units.gu(1); height: parent.height } |
2129 | - |
2130 | - Repeater { |
2131 | - id: repeater |
2132 | - |
2133 | - onCountChanged: { |
2134 | - if (flowListView.currentIndex === -1 && count > 0) { |
2135 | - flowListView.currentIndex = 0 |
2136 | - return |
2137 | - } |
2138 | - if (flowListView.currentIndex >= count) { |
2139 | - flowListView.currentIndex = count - 1 |
2140 | - return |
2141 | - } |
2142 | - |
2143 | - flowListView.currentIndex = -1 |
2144 | - } |
2145 | - } |
2146 | - |
2147 | - Item { width: units.gu(1); height: parent.height } |
2148 | - } |
2149 | -} |
2150 | |
2151 | === removed file 'app/components/IconButton.qml' |
2152 | --- app/components/IconButton.qml 2014-08-24 18:35:14 +0000 |
2153 | +++ app/components/IconButton.qml 1970-01-01 00:00:00 +0000 |
2154 | @@ -1,45 +0,0 @@ |
2155 | -/* |
2156 | - This file is part of quick-memo |
2157 | - Copyright (C) 2014 Stefano Verzegnassi |
2158 | - |
2159 | - This program is free software: you can redistribute it and/or modify |
2160 | - it under the terms of the GNU General Public License 3 as published by |
2161 | - the Free Software Foundation. |
2162 | - |
2163 | - This program is distributed in the hope that it will be useful, |
2164 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
2165 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2166 | - GNU General Public License for more details. |
2167 | - |
2168 | - You should have received a copy of the GNU General Public License |
2169 | - along with this program. If not, see http://www.gnu.org/licenses/. |
2170 | -*/ |
2171 | - |
2172 | -import QtQuick 2.0 |
2173 | -import Ubuntu.Components 1.1 |
2174 | -import QtGraphicalEffects 1.0 |
2175 | - |
2176 | -AbstractButton { |
2177 | - id: rootItem |
2178 | - height: units.gu(4) |
2179 | - width: height |
2180 | - |
2181 | - property alias source: image.name |
2182 | - |
2183 | - Icon { |
2184 | - id: image |
2185 | - anchors.fill: parent |
2186 | - visible: false |
2187 | - } |
2188 | - |
2189 | - ColorOverlay { |
2190 | - id: co |
2191 | - anchors { fill: image; margins: units.gu(0.5) } |
2192 | - source: image |
2193 | - color: rootItem.pressed ? UbuntuColors.orange : Theme.palette.selected.backgroundText |
2194 | - |
2195 | - Behavior on color { |
2196 | - ColorAnimation { duration: UbuntuAnimation.SnapDuration } |
2197 | - } |
2198 | - } |
2199 | -} |
2200 | |
2201 | === removed file 'app/components/ImageViewer.qml' |
2202 | --- app/components/ImageViewer.qml 2014-10-04 18:40:51 +0000 |
2203 | +++ app/components/ImageViewer.qml 1970-01-01 00:00:00 +0000 |
2204 | @@ -1,130 +0,0 @@ |
2205 | -/* |
2206 | - This file is part of quick-memo |
2207 | - Copyright (C) 2014 Stefano Verzegnassi |
2208 | - |
2209 | - This program is free software: you can redistribute it and/or modify |
2210 | - it under the terms of the GNU General Public License 3 as published by |
2211 | - the Free Software Foundation. |
2212 | - |
2213 | - This program is distributed in the hope that it will be useful, |
2214 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
2215 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2216 | - GNU General Public License for more details. |
2217 | - |
2218 | - You should have received a copy of the GNU General Public License |
2219 | - along with this program. If not, see http://www.gnu.org/licenses/. |
2220 | -*/ |
2221 | - |
2222 | -import QtQuick 2.0 |
2223 | -import Ubuntu.Components 1.1 |
2224 | -// Following are used by the custom header |
2225 | -import Ubuntu.Components.ListItems 1.0 as ListItem |
2226 | -import QtGraphicalEffects 1.0 |
2227 | - |
2228 | -Page { |
2229 | - id: imageViewer |
2230 | - |
2231 | - property alias source: image.source |
2232 | - |
2233 | - // Don't use Ubuntu header. Use a custom one. |
2234 | - Item { |
2235 | - id: header |
2236 | - |
2237 | - anchors { left: parent.left; top: parent.top; right: parent.right } |
2238 | - height: units.gu(6) |
2239 | - |
2240 | - Rectangle { |
2241 | - anchors.fill: parent |
2242 | - color: "black" |
2243 | - opacity: 0.3 |
2244 | - |
2245 | - ListItem.Divider { |
2246 | - anchors { left: parent.left; right: parent.right; bottom: parent.bottom } |
2247 | - } |
2248 | - } |
2249 | - |
2250 | - AbstractButton { |
2251 | - id: backButton |
2252 | - anchors { left: parent.left; top: parent.top; bottom: parent.bottom; leftMargin: units.gu(2); } |
2253 | - width: backImg.width + title.width + title.anchors.margins |
2254 | - |
2255 | - onClicked: pageStack.pop() |
2256 | - |
2257 | - Icon { |
2258 | - id: backImg |
2259 | - anchors { left: parent.left; verticalCenter: parent.verticalCenter } |
2260 | - height: units.gu(2) |
2261 | - width: height |
2262 | - visible: false |
2263 | - name: "back" |
2264 | - } |
2265 | - |
2266 | - ColorOverlay { |
2267 | - id: co |
2268 | - anchors.fill: backImg |
2269 | - source: backImg |
2270 | - color: backButton.pressed ? UbuntuColors.orange : "white" |
2271 | - Behavior on color { |
2272 | - ColorAnimation { duration: UbuntuAnimation.SnapDuration } |
2273 | - } |
2274 | - } |
2275 | - |
2276 | - Label { |
2277 | - id: title |
2278 | - anchors { left: co.right; verticalCenter: parent.verticalCenter; margins: units.gu(1) } |
2279 | - text: i18n.tr("Back") |
2280 | - |
2281 | - fontSize: "large" |
2282 | - font.weight: Font.DemiBold |
2283 | - color: backButton.pressed ? UbuntuColors.orange : "white" |
2284 | - |
2285 | - Behavior on color { |
2286 | - ColorAnimation { duration: UbuntuAnimation.SnapDuration } |
2287 | - } |
2288 | - } |
2289 | - } |
2290 | - } |
2291 | - |
2292 | - Rectangle { |
2293 | - anchors.fill: parent |
2294 | - color: "black" |
2295 | - z:-10 |
2296 | - } |
2297 | - |
2298 | - Flickable { |
2299 | - id: flickable |
2300 | - anchors { left: parent.left; top: header.bottom; right: parent.right; bottom: parent.bottom } |
2301 | - |
2302 | - contentWidth: Math.max(container.width, width) |
2303 | - contentHeight: Math.max(container.height, height) |
2304 | - |
2305 | - // Indipendent GU flickable speed workaround |
2306 | - flickDeceleration: 1500 * units.gridUnit / 8 |
2307 | - maximumFlickVelocity: 2500 * units.gridUnit / 8 |
2308 | - |
2309 | - Item { |
2310 | - id: container |
2311 | - anchors.centerIn: parent |
2312 | - width: image.paintedWidth * image.scale |
2313 | - height: image.paintedHeight * image.scale |
2314 | - |
2315 | - Image { |
2316 | - id: image |
2317 | - anchors.centerIn: parent |
2318 | - width: flickable.width |
2319 | - height: flickable.height |
2320 | - fillMode: Image.PreserveAspectFit |
2321 | - } |
2322 | - } |
2323 | - |
2324 | - PinchArea { |
2325 | - anchors.fill: parent |
2326 | - pinch.target: image |
2327 | - pinch.minimumScale: 1.0 |
2328 | - pinch.maximumScale: 5.0 |
2329 | - } |
2330 | - |
2331 | - // Go below the custom header |
2332 | - z: -1 |
2333 | - } |
2334 | -} |
2335 | |
2336 | === removed file 'app/components/ListManager.qml' |
2337 | --- app/components/ListManager.qml 2015-01-07 18:27:48 +0000 |
2338 | +++ app/components/ListManager.qml 1970-01-01 00:00:00 +0000 |
2339 | @@ -1,311 +0,0 @@ |
2340 | -/* |
2341 | - This file is part of quick-memo |
2342 | - Copyright (C) 2014 Stefano Verzegnassi |
2343 | - |
2344 | - This program is free software: you can redistribute it and/or modify |
2345 | - it under the terms of the GNU General Public License 3 as published by |
2346 | - the Free Software Foundation. |
2347 | - |
2348 | - This program is distributed in the hope that it will be useful, |
2349 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
2350 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2351 | - GNU General Public License for more details. |
2352 | - |
2353 | - You should have received a copy of the GNU General Public License |
2354 | - along with this program. If not, see http://www.gnu.org/licenses/. |
2355 | -*/ |
2356 | - |
2357 | -import QtQuick 2.0 |
2358 | -import Ubuntu.Components 1.1 |
2359 | -import Ubuntu.Keyboard 0.1 |
2360 | -import Ubuntu.Components.ListItems 1.0 as ListItem |
2361 | - |
2362 | -Column { |
2363 | - id: rootItem |
2364 | - |
2365 | - width: parent.width |
2366 | - spacing: units.gu(0.25) |
2367 | - |
2368 | - property Flickable flickable |
2369 | - property alias model: repeater.model |
2370 | - property alias delegate: repeater.delegate |
2371 | - property alias footer: footerLoader.sourceComponent |
2372 | - readonly property bool focusOnLastItem: (model.focusedIndex === -1) || (model.focusedIndex === (model.count - 1)) |
2373 | - |
2374 | - signal listChanged() |
2375 | - |
2376 | - ListItem.Header { |
2377 | - text: i18n.tr("List:") |
2378 | - } |
2379 | - |
2380 | - Repeater { |
2381 | - id: repeater |
2382 | - width: parent.width |
2383 | - |
2384 | - model: ListModel { |
2385 | - id: dataModel |
2386 | - |
2387 | - property int focusedIndex: -1 |
2388 | - } |
2389 | - |
2390 | - delegate: delegate |
2391 | - } |
2392 | - |
2393 | - // TODO: When user adds an element in the list, the new element should gain focus. |
2394 | - Loader { |
2395 | - id: footerLoader |
2396 | - width: parent.width |
2397 | - |
2398 | - sourceComponent: ListItem.Empty { |
2399 | - width: parent.width |
2400 | - opacity: enabled ? 1.0 : 0.5 |
2401 | - showDivider: false |
2402 | - |
2403 | - enabled: { |
2404 | - if (rootItem.model.count > 0) { |
2405 | - if (rootItem.model.get(rootItem.model.count - 1).text !== "") { |
2406 | - return true |
2407 | - } else { |
2408 | - return false |
2409 | - } |
2410 | - } else { |
2411 | - return true |
2412 | - } |
2413 | - } |
2414 | - |
2415 | - Row { |
2416 | - spacing: units.gu(2) |
2417 | - anchors { |
2418 | - left: parent.left; leftMargin: units.gu(2); |
2419 | - right: parent.right; |
2420 | - verticalCenter: parent.verticalCenter |
2421 | - } |
2422 | - |
2423 | - Item { |
2424 | - id: addListBtnImage |
2425 | - implicitWidth: units.gu(4.25) |
2426 | - implicitHeight: units.gu(4) |
2427 | - |
2428 | - Icon { |
2429 | - anchors { fill: parent; margins: units.gu(0.5) } |
2430 | - name: "add" |
2431 | - } |
2432 | - } |
2433 | - |
2434 | - Label { |
2435 | - id: addListBtnLabel |
2436 | - // TRANSLATORS: Text of a button used for add an item in the To-do list. |
2437 | - text: i18n.tr("Add item") |
2438 | - anchors.verticalCenter: addListBtnImage.verticalCenter |
2439 | - } |
2440 | - } |
2441 | - |
2442 | - onClicked: { |
2443 | - rootItem.addItem({"checked": false, "text": ""}) |
2444 | - // Here we don't send listChanged signal, since it is an empty item that should not be saved |
2445 | - } |
2446 | - } |
2447 | - } |
2448 | - |
2449 | - |
2450 | - function exportModel() { |
2451 | - var list = [] |
2452 | - |
2453 | - if (rootItem.model.count > 0 && rootItem.model.get(0).text !== "") { |
2454 | - for (var i=0; i<rootItem.model.count; i++) { |
2455 | - if (i != rootItem.model.count && rootItem.model.get(i).text != "") { |
2456 | - list[i] = rootItem.model.get(i) |
2457 | - } |
2458 | - } |
2459 | - } |
2460 | - |
2461 | - return list |
2462 | - } |
2463 | - |
2464 | - function addItem(args) { |
2465 | - rootItem.model.append(args) |
2466 | - var newItem = repeater.itemAt(repeater.count - 1) |
2467 | - newItem.textArea.forceActiveFocus() |
2468 | - autoScrollAnimation.makeMeVisible(newItem) |
2469 | - } |
2470 | - |
2471 | - SequentialAnimation { |
2472 | - id: autoScrollAnimation |
2473 | - |
2474 | - property var targetItem: null |
2475 | - alwaysRunToEnd: true |
2476 | - |
2477 | - // wait item be moved to correct place |
2478 | - PauseAnimation { |
2479 | - duration: 100 |
2480 | - } |
2481 | - // scroll to new item position |
2482 | - ScriptAction { |
2483 | - script: { |
2484 | - if (autoScrollAnimation.targetItem) { |
2485 | - autoScrollAnimation.makeMeVisibleImpl(autoScrollAnimation.targetItem) |
2486 | - autoScrollAnimation.targetItem = null |
2487 | - } |
2488 | - } |
2489 | - } |
2490 | - |
2491 | - function makeMeVisible(newItem) { |
2492 | - autoScrollAnimation.targetItem = newItem |
2493 | - autoScrollAnimation.restart() |
2494 | - } |
2495 | - |
2496 | - function makeMeVisibleImpl(newItem) { |
2497 | - if (!newItem) { |
2498 | - return |
2499 | - } |
2500 | - |
2501 | - var positionY = rootItem.y + repeater.y + newItem.y |
2502 | - |
2503 | - // check if the item is already visible |
2504 | - var bottomY = flickable.contentY + flickable.height |
2505 | - var itemBottom = positionY + (newItem.height *3) // margin |
2506 | - if (positionY >= flickable.contentY && itemBottom <= bottomY) { |
2507 | - return; |
2508 | - } |
2509 | - |
2510 | - // if it is not, try to scroll and make it visible |
2511 | - var targetY = itemBottom - flickable.height |
2512 | - if (targetY >= 0 && positionY) { |
2513 | - flickable.contentY = targetY |
2514 | - } else if (positionY < flickable.contentY) { |
2515 | - // if it is hidden at the top, also show it |
2516 | - flickable.contentY = positionY |
2517 | - } |
2518 | - flickable.returnToBounds() |
2519 | - } |
2520 | - } |
2521 | - |
2522 | - |
2523 | - // *** DELEGATE *** |
2524 | - Component { |
2525 | - id: delegate |
2526 | - |
2527 | - ListItem.Empty { |
2528 | - id: item |
2529 | - width: parent ? parent.width : undefined |
2530 | - height: (layoutDelegate.height > item.__height) ? layoutDelegate.height : item.__height |
2531 | - |
2532 | - showDivider: false |
2533 | - |
2534 | - property alias textArea: textArea |
2535 | - |
2536 | - Rectangle { |
2537 | - anchors.fill: parent |
2538 | - opacity: 0.1 |
2539 | - visible: textArea.activeFocus |
2540 | - color: "black" |
2541 | - } |
2542 | - |
2543 | - backgroundIndicator: Rectangle { |
2544 | - anchors.fill: parent |
2545 | - color: "red" |
2546 | - |
2547 | - Icon { |
2548 | - anchors.centerIn: parent |
2549 | - name: "delete" |
2550 | - color: Theme.palette.selected.field |
2551 | - height: units.gu(3) |
2552 | - width: units.gu(3) |
2553 | - } |
2554 | - } |
2555 | - |
2556 | - // ListItem is removable for all items, except the first when the text field is empty. |
2557 | - //confirmRemoval: true |
2558 | - removable: rootItem.model.count > 1 || (rootItem.model.get(0).text !== "") |
2559 | - confirmRemoval: true |
2560 | - onItemRemoved: { |
2561 | - // Send the signal before removing the item. This avoids a ReferenceError. |
2562 | - rootItem.listChanged() |
2563 | - rootItem.model.remove(model.index) |
2564 | - } |
2565 | - |
2566 | - Row { |
2567 | - id: layoutDelegate |
2568 | - |
2569 | - anchors { |
2570 | - left: parent.left |
2571 | - right: parent.right |
2572 | - margins: units.gu(2) |
2573 | - verticalCenter: parent.verticalCenter |
2574 | - } |
2575 | - |
2576 | - spacing: units.gu(1) |
2577 | - height: Math.max(checkBox.height, textArea.height) |
2578 | - |
2579 | - CheckBox { |
2580 | - id: checkBox |
2581 | - |
2582 | - checked: model.checked |
2583 | - onCheckedChanged: layoutDelegate.updateModel() |
2584 | - |
2585 | - style: Item { |
2586 | - implicitWidth: units.gu(4.25) |
2587 | - implicitHeight: units.gu(4) |
2588 | - |
2589 | - Image { |
2590 | - anchors { fill: parent; margins: units.gu(0.5) } |
2591 | - |
2592 | - source: checkBox.checked ? "../../graphics/select.svg" : "../../graphics/unselect.svg" |
2593 | - } |
2594 | - } |
2595 | - } |
2596 | - |
2597 | - NoteTextField { |
2598 | - id: textArea |
2599 | - |
2600 | - width: parent.width - (checkBox.width + (parent.spacing * 2)) |
2601 | - anchors.verticalCenter: parent.verticalCenter |
2602 | - |
2603 | - font.strikeout: checkBox.checked |
2604 | - |
2605 | - onFocusReceived: { |
2606 | - rootItem.model.focusedIndex = model.index |
2607 | - } |
2608 | - |
2609 | - text: model.text |
2610 | - onTextChanged: { |
2611 | - layoutDelegate.updateModel() |
2612 | - |
2613 | - /* This requires some test. No problem when TextField is used, but it seems to break dataModel when |
2614 | - TextArea is used. Could be related to NoteTextArea.qml, line 39.*/ |
2615 | - if (text === "") { |
2616 | - rootItem.model.remove(model.index) |
2617 | - } |
2618 | - } |
2619 | - |
2620 | - //hasClearButton: false |
2621 | - focus: true |
2622 | - |
2623 | - // Ubuntu Keyboard |
2624 | - // TODO: Disable Enter key if model.text is empty. |
2625 | - InputMethod.extensions: { |
2626 | - "enterKeyText": rootItem.focusOnLastItem ? i18n.tr("Add") : i18n.tr("Next") |
2627 | - } |
2628 | - |
2629 | - Keys.onReturnPressed: { |
2630 | - if (rootItem.focusOnLastItem && (model.text !== "")) { |
2631 | - // Create a new item. |
2632 | - rootItem.addItem({"checked": false, "text": ""}) |
2633 | - } else if (!rootItem.focusOnLastItem) { |
2634 | - var nextItem = repeater.itemAt(model.index + 1) |
2635 | - if (nextItem) { |
2636 | - nextItem.textArea.forceActiveFocus() |
2637 | - autoScrollAnimation.makeMeVisible(nextItem) |
2638 | - } |
2639 | - } |
2640 | - } |
2641 | - } |
2642 | - |
2643 | - function updateModel() { |
2644 | - rootItem.model.set(model.index, {"checked": checkBox.checked, "text": textArea.text}) |
2645 | - rootItem.listChanged() |
2646 | - } |
2647 | - } |
2648 | - } |
2649 | - } |
2650 | -} |
2651 | |
2652 | === removed file 'app/components/ListViewDelegate.qml' |
2653 | --- app/components/ListViewDelegate.qml 2014-11-06 05:09:59 +0000 |
2654 | +++ app/components/ListViewDelegate.qml 1970-01-01 00:00:00 +0000 |
2655 | @@ -1,299 +0,0 @@ |
2656 | -/* |
2657 | - This file is part of quick-memo |
2658 | - Copyright (C) 2014 Stefano Verzegnassi |
2659 | - |
2660 | - This program is free software: you can redistribute it and/or modify |
2661 | - it under the terms of the GNU General Public License 3 as published by |
2662 | - the Free Software Foundation. |
2663 | - |
2664 | - This program is distributed in the hope that it will be useful, |
2665 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
2666 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2667 | - GNU General Public License for more details. |
2668 | - |
2669 | - You should have received a copy of the GNU General Public License |
2670 | - along with this program. If not, see http://www.gnu.org/licenses/. |
2671 | -*/ |
2672 | - |
2673 | -import QtQuick 2.0 |
2674 | -import Ubuntu.Components 1.1 |
2675 | -import Ubuntu.Thumbnailer 0.1 |
2676 | -import "dateHelper.js" as DateHelper |
2677 | - |
2678 | -AbstractButton { |
2679 | - id: rootItem |
2680 | - |
2681 | - height: layout.height + layout.anchors.topMargin |
2682 | - width: parent.width |
2683 | - |
2684 | - property bool selected: false |
2685 | - property int maxListDelegatesNumber: 3 |
2686 | - |
2687 | - // RGB channels from 'shape.color' are in [0; 1] range. |
2688 | - property color foregroundColor: ((shape.color.r * 0.30 + shape.color.g * 0.59 + shape.color.b * 0.11) > 0.5) ? UbuntuColors.darkGrey : "#F3F3E7" |
2689 | - |
2690 | - UbuntuShape { |
2691 | - id: shape |
2692 | - anchors.fill: parent |
2693 | - |
2694 | - // Add 70% opacity |
2695 | - color: contents.color.toString().replace("#", "#B3") |
2696 | - |
2697 | - radius: "medium" |
2698 | - |
2699 | - Column { |
2700 | - id: layout |
2701 | - anchors { top: parent.top; left: parent.left; right: parent.right; topMargin: units.gu(2) } |
2702 | - |
2703 | - Loader { |
2704 | - x: units.gu(2) |
2705 | - width: parent.width - x |
2706 | - sourceComponent: (contents.title == "") ? undefined : titleComponent |
2707 | - |
2708 | - Component { |
2709 | - id: titleComponent |
2710 | - |
2711 | - Label { |
2712 | - width: parent.width |
2713 | - fontSize: "large" |
2714 | - font.weight: Font.Bold |
2715 | - text: contents.title |
2716 | - elide: Text.ElideRight |
2717 | - maximumLineCount: 2 |
2718 | - wrapMode: Text.WrapAnywhere |
2719 | - color: rootItem.foregroundColor |
2720 | - } |
2721 | - } |
2722 | - } |
2723 | - |
2724 | - // A spacer item |
2725 | - Item { |
2726 | - width: parent.width |
2727 | - height: units.gu(1) |
2728 | - } |
2729 | - |
2730 | - Item { |
2731 | - x: (column1.width > 0) ? units.gu(2) : 0 |
2732 | - width: parent.width - units.gu(4) |
2733 | - height: Math.max(column1.height, column2.height) |
2734 | - |
2735 | - Column { |
2736 | - id: column1 |
2737 | - anchors { left: parent.left; top: parent.top } |
2738 | - width: ((contents.text == "") && (picsRepeater.count == 0)) ? 0 |
2739 | - : (listRepeater.count > 0) ? (parent.width * 0.5) |
2740 | - : parent.width |
2741 | - spacing: units.gu(2) |
2742 | - |
2743 | - Loader { |
2744 | - width: parent.width |
2745 | - sourceComponent: (contents.text == "") ? undefined : textComponent |
2746 | - |
2747 | - Component { |
2748 | - id: textComponent |
2749 | - |
2750 | - Label { |
2751 | - width: parent.width |
2752 | - text: contents.text |
2753 | - wrapMode: Text.WrapAnywhere |
2754 | - elide: Text.ElideRight |
2755 | - maximumLineCount: 5 |
2756 | - color: rootItem.foregroundColor |
2757 | - } |
2758 | - } |
2759 | - } |
2760 | - |
2761 | - Item { |
2762 | - id: picsItem |
2763 | - width: parent.width |
2764 | - height: picFlow.height |
2765 | - |
2766 | - // TODO: As for listDelegates, limit pics to a number of 9 |
2767 | - Flow { |
2768 | - id: picFlow |
2769 | - width: parent.width |
2770 | - |
2771 | - Repeater { |
2772 | - id: picsRepeater |
2773 | - |
2774 | - model: contents.pictures |
2775 | - |
2776 | - delegate: Image { |
2777 | - id: img |
2778 | - width: parent.width |
2779 | - fillMode: Image.PreserveAspectCrop |
2780 | - source: "image://thumbnailer/" + Qt.resolvedUrl(contents.pictures[index].url) |
2781 | - |
2782 | - Connections { |
2783 | - target: picsRepeater |
2784 | - onItemAdded: calculateSize(index) |
2785 | - onItemRemoved: calculateSize(index) |
2786 | - } |
2787 | - |
2788 | - Connections { |
2789 | - target: picFlow |
2790 | - onWidthChanged: calculateSize(index) |
2791 | - } |
2792 | - |
2793 | - Component.onCompleted: calculateSize(index) |
2794 | - |
2795 | - function calculateSize(index) { |
2796 | - var n = picsRepeater.count |
2797 | - var i = n % 3 |
2798 | - var m = Math.floor(n / 3) |
2799 | - |
2800 | - height = units.gu(6) |
2801 | - |
2802 | - // Need to be hardcoded because of an issue. |
2803 | - // FIXME: Think it requires a better solution |
2804 | - var picFlowRealWidth = column1.width - units.gu(1) |
2805 | - |
2806 | - switch(i) { |
2807 | - case 0: |
2808 | - width = picFlowRealWidth / 3 |
2809 | - return |
2810 | - case 1: |
2811 | - if (index == 0) { |
2812 | - width = picFlowRealWidth |
2813 | - return |
2814 | - } else { |
2815 | - width = picFlowRealWidth / 3 |
2816 | - return |
2817 | - } |
2818 | - case 2: |
2819 | - if (index <= 1) { |
2820 | - width = picFlowRealWidth / 2 |
2821 | - return |
2822 | - } else { |
2823 | - width = picFlowRealWidth / 3 |
2824 | - return |
2825 | - } |
2826 | - } |
2827 | - } |
2828 | - } |
2829 | - } |
2830 | - |
2831 | - Component.onCompleted: picsRepeater.model = contents.pictures |
2832 | - } |
2833 | - } |
2834 | - } |
2835 | - |
2836 | - Loader { |
2837 | - anchors { right: column2.left; top: parent.top; bottom: parent.bottom; rightMargin: -units.gu(1) } |
2838 | - sourceComponent: ((column2.width > 0) && (column1.width > 0)) ? divider : null |
2839 | - width: 1 |
2840 | - |
2841 | - Component { |
2842 | - id: divider |
2843 | - Rectangle { |
2844 | - anchors.fill: parent |
2845 | - color: foregroundColor |
2846 | - opacity: 0.3 |
2847 | - } |
2848 | - } |
2849 | - } |
2850 | - |
2851 | - Column { |
2852 | - id: column2 |
2853 | - anchors { left: column1.right; top: parent.top } |
2854 | - width: (listRepeater.count > 0) ? ((contents.text == "") && (picsRepeater.count == 0)) ? parent.width |
2855 | - : (parent.width * 0.5) |
2856 | - : 0 |
2857 | - |
2858 | - Repeater { |
2859 | - id: listRepeater |
2860 | - width: parent.width |
2861 | - |
2862 | - model: contents.list |
2863 | - |
2864 | - delegate: Loader { |
2865 | - width: parent.width |
2866 | - sourceComponent: model.index < 4 ? listDelegate : null |
2867 | - |
2868 | - Component { |
2869 | - id: listDelegate |
2870 | - |
2871 | - Row { |
2872 | - id: rootItem |
2873 | - spacing: units.gu(1) |
2874 | - width: parent.width |
2875 | - height: Math.max(checkBox.height, textArea.height) |
2876 | - |
2877 | - Item { |
2878 | - id: checkBox |
2879 | - width: parent.width |
2880 | - height: units.gu(4) |
2881 | - |
2882 | - property bool checked: contents.list[index].checked |
2883 | - |
2884 | - Icon { |
2885 | - id: tick |
2886 | - anchors { |
2887 | - left: parent.left; leftMargin: units.gu(2.25); |
2888 | - top: parent.top; topMargin: units.gu(0.35) |
2889 | - } |
2890 | - width: (source == "../../graphics/select.svg") ? units.gu(2.25) : units.gu(1.5) |
2891 | - height: (source == "../../graphics/select.svg") ? units.gu(2) : units.gu(1.5) |
2892 | - |
2893 | - source: checkBox.checked ? "../../graphics/select.svg" : "../../graphics/unselect.svg" |
2894 | - visible: model.index !== 3 |
2895 | - color: foregroundColor |
2896 | - } |
2897 | - |
2898 | - Label { |
2899 | - id: textArea |
2900 | - anchors { left: tick.right; right: parent.right; margins: units.gu(1) } |
2901 | - |
2902 | - font.strikeout: checkBox.checked |
2903 | - text: (model.index == 3) ? ". . ." : contents.list[index].text |
2904 | - elide: Text.ElideRight |
2905 | - maximumLineCount: 2 |
2906 | - wrapMode: Text.WrapAnywhere |
2907 | - color: foregroundColor |
2908 | - } |
2909 | - } |
2910 | - } |
2911 | - } |
2912 | - } |
2913 | - } |
2914 | - } |
2915 | - } |
2916 | - |
2917 | - // A spacer item |
2918 | - Item { |
2919 | - width: parent.width |
2920 | - height: units.gu(1) |
2921 | - } |
2922 | - |
2923 | - Item { |
2924 | - id: date |
2925 | - width: parent.width |
2926 | - height: units.gu(4) |
2927 | - |
2928 | - Label { |
2929 | - anchors { right: parent.right; verticalCenter: parent.verticalCenter; margins: units.gu(2) } |
2930 | - text: Qt.formatDateTime(DateHelper.parseDate(contents.date), "d MMM yyyy, hh:mm") |
2931 | - fontSize: "small" |
2932 | - color: rootItem.foregroundColor |
2933 | - } |
2934 | - } |
2935 | - } |
2936 | - } |
2937 | - |
2938 | - // Visual feedback when pressed. Not listed in official documentation, still useful. |
2939 | - onPressedChanged: { |
2940 | - if (pressed) |
2941 | - shape.borderSource = "radius_pressed.sci" |
2942 | - else |
2943 | - shape.borderSource = "radius_idle.sci" |
2944 | - } |
2945 | - |
2946 | - // Visual feedback when selected. |
2947 | - onSelectedChanged: { |
2948 | - if (selected) { |
2949 | - shape.color = Qt.darker(contents.color) |
2950 | - } else { |
2951 | - shape.color = contents.color.toString().replace("#", "#B3") |
2952 | - } |
2953 | - } |
2954 | -} |
2955 | |
2956 | === renamed file 'app/components/MainPage.qml' => 'app/components/MainPage.qml.THIS' |
2957 | === removed file 'app/components/MultiSelectionHandler.qml' |
2958 | --- app/components/MultiSelectionHandler.qml 2014-11-03 00:21:23 +0000 |
2959 | +++ app/components/MultiSelectionHandler.qml 1970-01-01 00:00:00 +0000 |
2960 | @@ -1,106 +0,0 @@ |
2961 | -/* |
2962 | - This file is part of quick-memo |
2963 | - Copyright (C) 2014 Stefano Verzegnassi |
2964 | - |
2965 | - This program is free software: you can redistribute it and/or modify |
2966 | - it under the terms of the GNU General Public License 3 as published by |
2967 | - the Free Software Foundation. |
2968 | - |
2969 | - This program is distributed in the hope that it will be useful, |
2970 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
2971 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2972 | - GNU General Public License for more details. |
2973 | - |
2974 | - You should have received a copy of the GNU General Public License |
2975 | - along with this program. If not, see http://www.gnu.org/licenses/. |
2976 | -*/ |
2977 | - |
2978 | -import QtQuick 2.0 |
2979 | -import Ubuntu.Components 1.1 |
2980 | - |
2981 | -PageHeadState { |
2982 | - id: rootItem |
2983 | - |
2984 | - property string title |
2985 | - |
2986 | - property var indexes: [] |
2987 | - property int count: rootItem.indexes.length |
2988 | - property Page targetPage |
2989 | - |
2990 | - head: targetPage.head |
2991 | - |
2992 | - backAction: Action { |
2993 | - text: i18n.tr("Cancel") |
2994 | - iconName: "back" |
2995 | - onTriggered: targetPage.state = "default" |
2996 | - } |
2997 | - |
2998 | - contents: Item { |
2999 | - anchors.fill: parent |
3000 | - |
3001 | - Connections { |
3002 | - target: targetPage |
3003 | - onStateChanged: { |
3004 | - if (targetPage.state !== "multiSelection") { |
3005 | - // Clean the model |
3006 | - rootItem.indexes = [] |
3007 | - } |
3008 | - } |
3009 | - } |
3010 | - |
3011 | - Label { |
3012 | - fontSize: "x-large" |
3013 | - |
3014 | - // See LP:1184810 |
3015 | - text: (rootItem.count == 0) ? i18n.tr("No item selected") |
3016 | - : i18n.tr("%1 item selected", "%1 items selected", rootItem.count).arg(rootItem.count) |
3017 | - |
3018 | - anchors.verticalCenter: parent.verticalCenter |
3019 | - } |
3020 | - |
3021 | - // Provide a visual feedback when active |
3022 | - Rectangle { |
3023 | - id: headerBg |
3024 | - parent: targetPage.header |
3025 | - z: -10 |
3026 | - |
3027 | - width: targetPage.width |
3028 | - height: targetPage.header.height |
3029 | - color: "#19B6EE" // Cyan |
3030 | - visible: mainPage.state == "multiSelection" |
3031 | - } |
3032 | - } |
3033 | - |
3034 | - signal indexAdded(var index) |
3035 | - signal indexRemoved(var index) |
3036 | - |
3037 | - function selectUnselectItem(index) { |
3038 | - for (var i=0; i<rootItem.indexes.length; i++) { |
3039 | - // Search for index in the model |
3040 | - if (rootItem.indexes[i] === index) { |
3041 | - // That means it's already in, so remove it. |
3042 | - rootItem.indexes.splice(i, 1); |
3043 | - |
3044 | - // Update count and header |
3045 | - rootItem.count = rootItem.indexes.length |
3046 | - |
3047 | - // Return false if the index is removed. |
3048 | - rootItem.indexRemoved(index) |
3049 | - return false |
3050 | - } |
3051 | - } |
3052 | - |
3053 | - // Otherwise, the item is not in the model, so add it. |
3054 | - rootItem.indexes.push(index) |
3055 | - |
3056 | - // Update count |
3057 | - rootItem.count = rootItem.indexes.length |
3058 | - |
3059 | - // Sort indexes, so that it's easier to use the indexes we collect. |
3060 | - indexes.sort(function(a,b) {return a-b}) |
3061 | - |
3062 | - // Return true if the index is added |
3063 | - rootItem.indexAdded(index) |
3064 | - return true |
3065 | - } |
3066 | -} |
3067 | |
3068 | === removed file 'app/components/NoteModel.qml' |
3069 | --- app/components/NoteModel.qml 2014-08-21 20:09:02 +0000 |
3070 | +++ app/components/NoteModel.qml 1970-01-01 00:00:00 +0000 |
3071 | @@ -1,119 +0,0 @@ |
3072 | -/* |
3073 | - This file is part of quick-memo |
3074 | - Copyright (C) 2014 Stefano Verzegnassi |
3075 | - |
3076 | - This program is free software: you can redistribute it and/or modify |
3077 | - it under the terms of the GNU General Public License 3 as published by |
3078 | - the Free Software Foundation. |
3079 | - |
3080 | - This program is distributed in the hope that it will be useful, |
3081 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
3082 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3083 | - GNU General Public License for more details. |
3084 | - |
3085 | - You should have received a copy of the GNU General Public License |
3086 | - along with this program. If not, see http://www.gnu.org/licenses/. |
3087 | -*/ |
3088 | - |
3089 | -import QtQuick 2.0 |
3090 | -import U1db 1.0 as U1db |
3091 | -import Ubuntu.Components 1.1 |
3092 | - |
3093 | -Item { |
3094 | - id: rootItem |
3095 | - property alias model: model |
3096 | - |
3097 | - signal initialized() |
3098 | - |
3099 | - // *** functions |
3100 | - function addNote(noteTitle, noteText, noteColor, noteList, notePictures) { |
3101 | - // Get the current date |
3102 | - var dateString = new Date().valueOf() |
3103 | - |
3104 | - db.putDoc(JSON.stringify({memos: {title: noteTitle, text: noteText, color: noteColor, date: dateString, list: noteList, pictures: notePictures}})) |
3105 | - } |
3106 | - |
3107 | - // Function used for changing a single value of the note |
3108 | - function setNoteProperty(index, field, value) { |
3109 | - var obj = JSON.parse(JSON.stringify(model.get(index))) |
3110 | - |
3111 | - // Edit the required property |
3112 | - switch(field) { |
3113 | - case "title": |
3114 | - obj.contents.title = value |
3115 | - break |
3116 | - case "text": |
3117 | - obj.contents.text = value |
3118 | - break |
3119 | - case "color": |
3120 | - // The char '#' from the hex color is not correctly parse by JSON. We add an empty string, so that it works well. |
3121 | - obj.contents.color = "" + value |
3122 | - break |
3123 | - case "list": |
3124 | - obj.contents.list = value |
3125 | - break |
3126 | - case "pictures": |
3127 | - obj.contents.pictures = value |
3128 | - } |
3129 | - |
3130 | - // Get the current date and update the time of the last update |
3131 | - obj.contents.date = new Date().valueOf() |
3132 | - |
3133 | - db.putDoc(JSON.stringify({memos: obj.contents}), obj.docId) |
3134 | - } |
3135 | - |
3136 | - // Function used for rewriting the whole content of the note. json variant is a JSON object. |
3137 | - function editNote(index, json) { |
3138 | - var obj = json |
3139 | - |
3140 | - // Get the current date and update the time of the last update |
3141 | - obj.contents.date = new Date().valueOf() |
3142 | - |
3143 | - console.log(JSON.stringify({memos: obj.contents})) |
3144 | - db.putDoc(JSON.stringify({memos: obj.contents}), obj.docId) |
3145 | - } |
3146 | - |
3147 | - |
3148 | - function deleteNote(index) { |
3149 | - db.deleteDoc(model.get(index).docId) |
3150 | - } |
3151 | - |
3152 | - function deleteNotes(indexes) { |
3153 | - var deletedItemNumber = 0; |
3154 | - for (var i=0; i<indexes.length; i++) { |
3155 | - db.deleteDoc(model.get(indexes[i] - deletedItemNumber).docId) |
3156 | - deletedItemNumber++ |
3157 | - } |
3158 | - } |
3159 | - |
3160 | - // *** U1db database |
3161 | - U1db.Database { |
3162 | - id: db |
3163 | - path: "quick-memo" |
3164 | - Component.onCompleted: { |
3165 | - // TODO: Delete pictures that are not used by the notes at startup. |
3166 | - rootItem.initialized() |
3167 | - } |
3168 | - } |
3169 | - |
3170 | - // TODO: More queries, more pages, a more powerful app. |
3171 | - // TODO: Search feature. Use "filter" from SortFilterModel? |
3172 | - SortFilterModel { |
3173 | - id: model |
3174 | - sort { |
3175 | - property: "date" |
3176 | - order: Qt.DescendingOrder |
3177 | - } |
3178 | - |
3179 | - model: U1db.Query { |
3180 | - id: query |
3181 | - index: U1db.Index { |
3182 | - database: db |
3183 | - expression: ["memos.docId", "memos.title", "memos.text", "memos.color", "memos.date", "memos.list", "memos.pictures"] |
3184 | - } |
3185 | - query: ["*", "*", "*", "*", "*", "*", "*"] |
3186 | - } |
3187 | - } |
3188 | - |
3189 | - |
3190 | -} |
3191 | |
3192 | === removed file 'app/components/NoteTextArea.qml' |
3193 | --- app/components/NoteTextArea.qml 2014-10-04 00:46:31 +0000 |
3194 | +++ app/components/NoteTextArea.qml 1970-01-01 00:00:00 +0000 |
3195 | @@ -1,59 +0,0 @@ |
3196 | -/* |
3197 | - This file is part of quick-memo |
3198 | - Copyright (C) 2014 Stefano Verzegnassi |
3199 | - |
3200 | - This program is free software: you can redistribute it and/or modify |
3201 | - it under the terms of the GNU General Public License 3 as published by |
3202 | - the Free Software Foundation. |
3203 | - |
3204 | - This program is distributed in the hope that it will be useful, |
3205 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
3206 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3207 | - GNU General Public License for more details. |
3208 | - |
3209 | - You should have received a copy of the GNU General Public License |
3210 | - along with this program. If not, see http://www.gnu.org/licenses/. |
3211 | -*/ |
3212 | - |
3213 | -import QtQuick 2.0 |
3214 | -import Ubuntu.Components 1.1 |
3215 | -import Ubuntu.Components.Themes.Ambiance 0.1 |
3216 | - |
3217 | -TextArea { |
3218 | - id: rootItem |
3219 | - width: parent.width |
3220 | - |
3221 | - autoSize: true |
3222 | - maximumLineCount: 0 |
3223 | - |
3224 | - // Prevent data loss |
3225 | - inputMethodHints: Qt.ImhNoPredictiveText |
3226 | - |
3227 | - opacity: 1.0 |
3228 | - |
3229 | - signal focusLost() |
3230 | - signal textReallyChanged |
3231 | - |
3232 | - property string __oldText: "" |
3233 | - onTextChanged: { |
3234 | - //WORKAROUND: textChanged seems to be emitted also when TextArea has the activeFocus (and text does not change). |
3235 | - if (__oldText !== text) { |
3236 | - rootItem.textReallyChanged() |
3237 | - __oldText = text; |
3238 | - } |
3239 | - } |
3240 | - |
3241 | - InverseMouseArea { |
3242 | - visible: parent.activeFocus |
3243 | - anchors.fill: parent |
3244 | - onClicked: { |
3245 | - rootItem.focusLost() |
3246 | - mouse.accepted = false |
3247 | - } |
3248 | - } |
3249 | - |
3250 | - style: TextAreaStyle { |
3251 | - frameSpacing: 0 |
3252 | - background: Item { anchors.fill: parent } |
3253 | - } |
3254 | -} |
3255 | |
3256 | === removed file 'app/components/NoteTextField.qml' |
3257 | --- app/components/NoteTextField.qml 2015-01-07 18:27:48 +0000 |
3258 | +++ app/components/NoteTextField.qml 1970-01-01 00:00:00 +0000 |
3259 | @@ -1,53 +0,0 @@ |
3260 | -/* |
3261 | - This file is part of quick-memo |
3262 | - Copyright (C) 2014 Stefano Verzegnassi |
3263 | - |
3264 | - This program is free software: you can redistribute it and/or modify |
3265 | - it under the terms of the GNU General Public License 3 as published by |
3266 | - the Free Software Foundation. |
3267 | - |
3268 | - This program is distributed in the hope that it will be useful, |
3269 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
3270 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3271 | - GNU General Public License for more details. |
3272 | - |
3273 | - You should have received a copy of the GNU General Public License |
3274 | - along with this program. If not, see http://www.gnu.org/licenses/. |
3275 | -*/ |
3276 | - |
3277 | -import QtQuick 2.0 |
3278 | -import Ubuntu.Components 1.1 |
3279 | -import Ubuntu.Components.Themes.Ambiance 0.1 |
3280 | - |
3281 | -import "../ubuntucomponents" as UbuntuComponents |
3282 | - |
3283 | -// WORKAROUND: We need a 'custom' version of TextField in wait of LP:1376510 to be fixed. |
3284 | -// FIXME: Some issue with InputHandler (e.g. Keys.Down or Keys.PgDown) but we don't care it, since at the moment the main focus is not desktop. |
3285 | -UbuntuComponents.TextField { |
3286 | - id: textArea |
3287 | - width: parent.width - (checkBox.width + (parent.spacing * 2)) |
3288 | - |
3289 | - // Dynamic height: units.gu(3) = implicitHeight - (frameSpacing * 2) |
3290 | - height: (contentHeight > units.gu(3)) ? contentHeight : units.gu(3) |
3291 | - |
3292 | - wrapMode: TextInput.Wrap |
3293 | - |
3294 | - // Prevent data loss |
3295 | - inputMethodHints: Qt.ImhNoPredictiveText |
3296 | - |
3297 | - signal focusLost() |
3298 | - signal focusReceived() |
3299 | - |
3300 | - onActiveFocusChanged: { |
3301 | - if (activeFocus) { |
3302 | - focusReceived() |
3303 | - } else { |
3304 | - focusLost() |
3305 | - } |
3306 | - } |
3307 | - |
3308 | - style: TextFieldStyle { |
3309 | - frameSpacing: 0 |
3310 | - background: Item { anchors.fill: parent } |
3311 | - } |
3312 | -} |
3313 | |
3314 | === removed file 'app/components/PageBackground.qml' |
3315 | --- app/components/PageBackground.qml 2014-09-28 23:58:26 +0000 |
3316 | +++ app/components/PageBackground.qml 1970-01-01 00:00:00 +0000 |
3317 | @@ -1,25 +0,0 @@ |
3318 | -import QtQuick 2.0 |
3319 | - |
3320 | -// Background |
3321 | -Rectangle { |
3322 | - id: bg |
3323 | - anchors.fill: parent |
3324 | - z: -10; opacity: 0.5 |
3325 | - |
3326 | - property bool __parentPageAboutToBeClosed: false |
3327 | - |
3328 | - /* MainView clips its content, so that it does not overlap the header. |
3329 | - We need to bypass this, using another Rectangle that specifically overlap the header. */ |
3330 | - Rectangle { |
3331 | - parent: root.header |
3332 | - z: -10; opacity: 0.5 |
3333 | - |
3334 | - width: root.width |
3335 | - height: root.header.height |
3336 | - color: bg.color |
3337 | - |
3338 | - // FIXME: Header background should progressively change opacity to 0.0 when the BottomEdge page is dismissed. |
3339 | - visible: !bg.__parentPageAboutToBeClosed |
3340 | - } |
3341 | -} |
3342 | - |
3343 | |
3344 | === removed file 'app/components/PageWithBottomEdge.qml' |
3345 | --- app/components/PageWithBottomEdge.qml 2014-10-21 16:01:52 +0000 |
3346 | +++ app/components/PageWithBottomEdge.qml 1970-01-01 00:00:00 +0000 |
3347 | @@ -1,407 +0,0 @@ |
3348 | -/* |
3349 | - * Copyright (C) 2014 Canonical, Ltd. |
3350 | - * |
3351 | - * This program is free software; you can redistribute it and/or modify |
3352 | - * it under the terms of the GNU General Public License as published by |
3353 | - * the Free Software Foundation; version 3. |
3354 | - * |
3355 | - * This program is distributed in the hope that it will be useful, |
3356 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3357 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3358 | - * GNU General Public License for more details. |
3359 | - * |
3360 | - * You should have received a copy of the GNU General Public License |
3361 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3362 | - */ |
3363 | - |
3364 | -/* |
3365 | - Example: |
3366 | - |
3367 | - MainView { |
3368 | - objectName: "mainView" |
3369 | - |
3370 | - applicationName: "com.ubuntu.developer.boiko.bottomedge" |
3371 | - |
3372 | - width: units.gu(100) |
3373 | - height: units.gu(75) |
3374 | - |
3375 | - Component { |
3376 | - id: pageComponent |
3377 | - |
3378 | - PageWithBottomEdge { |
3379 | - id: mainPage |
3380 | - title: i18n.tr("Main Page") |
3381 | - |
3382 | - Rectangle { |
3383 | - anchors.fill: parent |
3384 | - color: "white" |
3385 | - } |
3386 | - |
3387 | - bottomEdgePageComponent: Page { |
3388 | - title: "Contents" |
3389 | - anchors.fill: parent |
3390 | - //anchors.topMargin: contentsPage.flickable.contentY |
3391 | - |
3392 | - ListView { |
3393 | - anchors.fill: parent |
3394 | - model: 50 |
3395 | - delegate: ListItems.Standard { |
3396 | - text: "One Content Item: " + index |
3397 | - } |
3398 | - } |
3399 | - } |
3400 | - bottomEdgeTitle: i18n.tr("Bottom edge action") |
3401 | - } |
3402 | - } |
3403 | - |
3404 | - PageStack { |
3405 | - id: stack |
3406 | - Component.onCompleted: stack.push(pageComponent) |
3407 | - } |
3408 | - } |
3409 | - |
3410 | -*/ |
3411 | - |
3412 | -import QtQuick 2.2 |
3413 | -import Ubuntu.Components 1.1 |
3414 | - |
3415 | -Page { |
3416 | - id: page |
3417 | - |
3418 | - property alias bottomEdgePageComponent: edgeLoader.sourceComponent |
3419 | - property alias bottomEdgePageSource: edgeLoader.source |
3420 | - property alias bottomEdgeTitle: tipLabel.text |
3421 | - property bool bottomEdgeEnabled: true |
3422 | - property int bottomEdgeExpandThreshold: page.height * 0.2 |
3423 | - property int bottomEdgeExposedArea: bottomEdge.state !== "expanded" ? (page.height - bottomEdge.y - bottomEdge.tipHeight) : _areaWhenExpanded |
3424 | - property bool reloadBottomEdgePage: true |
3425 | - |
3426 | - readonly property alias bottomEdgePage: edgeLoader.item |
3427 | - readonly property bool isReady: ((bottomEdge.y === 0) && bottomEdgePageLoaded && edgeLoader.item.active) |
3428 | - readonly property bool isCollapsed: (bottomEdge.y === page.height) |
3429 | - readonly property bool bottomEdgePageLoaded: (edgeLoader.status == Loader.Ready) |
3430 | - |
3431 | - property bool _showEdgePageWhenReady: false |
3432 | - property int _areaWhenExpanded: 0 |
3433 | - |
3434 | - signal bottomEdgeReleased() |
3435 | - signal bottomEdgeDismissed() |
3436 | - |
3437 | - |
3438 | - function showBottomEdgePage(source, properties) |
3439 | - { |
3440 | - edgeLoader.setSource(source, properties) |
3441 | - _showEdgePageWhenReady = true |
3442 | - } |
3443 | - |
3444 | - function setBottomEdgePage(source, properties) |
3445 | - { |
3446 | - edgeLoader.setSource(source, properties) |
3447 | - } |
3448 | - |
3449 | - function _pushPage() |
3450 | - { |
3451 | - if (edgeLoader.status === Loader.Ready) { |
3452 | - edgeLoader.item.active = true |
3453 | - page.pageStack.push(edgeLoader.item) |
3454 | - if (edgeLoader.item.flickable) { |
3455 | - edgeLoader.item.flickable.contentY = -page.header.height |
3456 | - edgeLoader.item.flickable.returnToBounds() |
3457 | - } |
3458 | - if (edgeLoader.item.ready) |
3459 | - edgeLoader.item.ready() |
3460 | - } |
3461 | - } |
3462 | - |
3463 | - |
3464 | - Component.onCompleted: { |
3465 | - // avoid a binding on the expanded height value |
3466 | - var expandedHeight = height; |
3467 | - _areaWhenExpanded = expandedHeight; |
3468 | - } |
3469 | - |
3470 | - onActiveChanged: { |
3471 | - if (active) { |
3472 | - bottomEdge.state = "collapsed" |
3473 | - } |
3474 | - } |
3475 | - |
3476 | - onBottomEdgePageLoadedChanged: { |
3477 | - if (_showEdgePageWhenReady && bottomEdgePageLoaded) { |
3478 | - bottomEdge.state = "expanded" |
3479 | - _showEdgePageWhenReady = false |
3480 | - } |
3481 | - } |
3482 | - |
3483 | - Rectangle { |
3484 | - id: bgVisual |
3485 | - |
3486 | - color: "black" |
3487 | - anchors.fill: page |
3488 | - opacity: 0.7 * ((page.height - bottomEdge.y) / page.height) |
3489 | - z: 1 |
3490 | - } |
3491 | - |
3492 | - UbuntuShape { |
3493 | - id: tip |
3494 | - objectName: "bottomEdgeTip" |
3495 | - |
3496 | - property bool hidden: (activeFocus === false) || ((bottomEdge.y - units.gu(1)) < tip.y) |
3497 | - |
3498 | - enabled: mouseArea.enabled |
3499 | - visible: page.bottomEdgeEnabled |
3500 | - anchors { |
3501 | - bottom: parent.bottom |
3502 | - horizontalCenter: bottomEdge.horizontalCenter |
3503 | - bottomMargin: hidden ? - height + units.gu(1) : -units.gu(1) |
3504 | - Behavior on bottomMargin { |
3505 | - SequentialAnimation { |
3506 | - // wait some msecs in case of the focus change again, to avoid flickering |
3507 | - PauseAnimation { |
3508 | - duration: 300 |
3509 | - } |
3510 | - UbuntuNumberAnimation { |
3511 | - duration: UbuntuAnimation.SnapDuration |
3512 | - } |
3513 | - } |
3514 | - } |
3515 | - } |
3516 | - |
3517 | - z: 1 |
3518 | - width: tipLabel.paintedWidth + units.gu(6) |
3519 | - height: bottomEdge.tipHeight + units.gu(1) |
3520 | - color: Theme.palette.normal.overlay |
3521 | - Label { |
3522 | - id: tipLabel |
3523 | - |
3524 | - anchors { |
3525 | - top: parent.top |
3526 | - left: parent.left |
3527 | - right: parent.right |
3528 | - } |
3529 | - height: bottomEdge.tipHeight |
3530 | - verticalAlignment: Text.AlignVCenter |
3531 | - horizontalAlignment: Text.AlignHCenter |
3532 | - opacity: tip.hidden ? 0.0 : 1.0 |
3533 | - Behavior on opacity { |
3534 | - UbuntuNumberAnimation { |
3535 | - duration: UbuntuAnimation.SnapDuration |
3536 | - } |
3537 | - } |
3538 | - } |
3539 | - } |
3540 | - |
3541 | - Rectangle { |
3542 | - id: shadow |
3543 | - |
3544 | - anchors { |
3545 | - left: parent.left |
3546 | - right: parent.right |
3547 | - bottom: parent.bottom |
3548 | - } |
3549 | - height: units.gu(1) |
3550 | - z: 1 |
3551 | - opacity: 0.0 |
3552 | - gradient: Gradient { |
3553 | - GradientStop { position: 0.0; color: "transparent" } |
3554 | - GradientStop { position: 1.0; color: Qt.rgba(0, 0, 0, 0.2) } |
3555 | - } |
3556 | - } |
3557 | - |
3558 | - MouseArea { |
3559 | - id: mouseArea |
3560 | - |
3561 | - property real previousY: -1 |
3562 | - property string dragDirection: "None" |
3563 | - |
3564 | - preventStealing: true |
3565 | - drag { |
3566 | - axis: Drag.YAxis |
3567 | - target: bottomEdge |
3568 | - minimumY: bottomEdge.pageStartY |
3569 | - maximumY: page.height |
3570 | - } |
3571 | - enabled: edgeLoader.status == Loader.Ready |
3572 | - visible: page.bottomEdgeEnabled |
3573 | - |
3574 | - anchors { |
3575 | - left: parent.left |
3576 | - right: parent.right |
3577 | - bottom: parent.bottom |
3578 | - |
3579 | - } |
3580 | - height: bottomEdge.tipHeight |
3581 | - z: 1 |
3582 | - |
3583 | - onReleased: { |
3584 | - page.bottomEdgeReleased() |
3585 | - if ((dragDirection === "BottomToTop") && |
3586 | - bottomEdge.y < (page.height - bottomEdgeExpandThreshold - bottomEdge.tipHeight)) { |
3587 | - bottomEdge.state = "expanded" |
3588 | - } else { |
3589 | - bottomEdge.state = "collapsed" |
3590 | - } |
3591 | - previousY = -1 |
3592 | - dragDirection = "None" |
3593 | - } |
3594 | - |
3595 | - onPressed: { |
3596 | - previousY = mouse.y |
3597 | - tip.forceActiveFocus() |
3598 | - } |
3599 | - |
3600 | - onMouseYChanged: { |
3601 | - var yOffset = previousY - mouseY |
3602 | - // skip if was a small move |
3603 | - if (Math.abs(yOffset) <= units.gu(2)) { |
3604 | - return |
3605 | - } |
3606 | - previousY = mouseY |
3607 | - dragDirection = yOffset > 0 ? "BottomToTop" : "TopToBottom" |
3608 | - } |
3609 | - } |
3610 | - |
3611 | - Rectangle { |
3612 | - id: bottomEdge |
3613 | - objectName: "bottomEdge" |
3614 | - |
3615 | - readonly property int tipHeight: units.gu(3) |
3616 | - readonly property int pageStartY: 0 |
3617 | - |
3618 | - z: 1 |
3619 | - color: Theme.palette.normal.background |
3620 | - clip: true |
3621 | - anchors { |
3622 | - left: parent.left |
3623 | - right: parent.right |
3624 | - } |
3625 | - height: page.height |
3626 | - y: height |
3627 | - visible: !page.isCollapsed |
3628 | - state: "collapsed" |
3629 | - states: [ |
3630 | - State { |
3631 | - name: "collapsed" |
3632 | - PropertyChanges { |
3633 | - target: bottomEdge |
3634 | - y: bottomEdge.height |
3635 | - } |
3636 | - }, |
3637 | - State { |
3638 | - name: "expanded" |
3639 | - PropertyChanges { |
3640 | - target: bottomEdge |
3641 | - y: bottomEdge.pageStartY |
3642 | - } |
3643 | - }, |
3644 | - State { |
3645 | - name: "floating" |
3646 | - when: mouseArea.drag.active |
3647 | - PropertyChanges { |
3648 | - target: shadow |
3649 | - opacity: 1.0 |
3650 | - } |
3651 | - } |
3652 | - ] |
3653 | - |
3654 | - transitions: [ |
3655 | - Transition { |
3656 | - to: "expanded" |
3657 | - SequentialAnimation { |
3658 | - alwaysRunToEnd: true |
3659 | - |
3660 | - SmoothedAnimation { |
3661 | - target: bottomEdge |
3662 | - property: "y" |
3663 | - duration: UbuntuAnimation.FastDuration |
3664 | - easing.type: Easing.Linear |
3665 | - } |
3666 | - SmoothedAnimation { |
3667 | - target: edgeLoader |
3668 | - property: "anchors.topMargin" |
3669 | - to: - units.gu(4) |
3670 | - duration: UbuntuAnimation.FastDuration |
3671 | - easing.type: Easing.Linear |
3672 | - } |
3673 | - SmoothedAnimation { |
3674 | - target: edgeLoader |
3675 | - property: "anchors.topMargin" |
3676 | - to: 0 |
3677 | - duration: UbuntuAnimation.FastDuration |
3678 | - easing: UbuntuAnimation.StandardEasing |
3679 | - } |
3680 | - ScriptAction { |
3681 | - script: page._pushPage() |
3682 | - } |
3683 | - } |
3684 | - }, |
3685 | - Transition { |
3686 | - from: "expanded" |
3687 | - to: "collapsed" |
3688 | - SequentialAnimation { |
3689 | - alwaysRunToEnd: true |
3690 | - |
3691 | - ScriptAction { |
3692 | - script: { |
3693 | - Qt.inputMethod.hide() |
3694 | - edgeLoader.item.parent = edgeLoader |
3695 | - edgeLoader.item.anchors.fill = edgeLoader |
3696 | - edgeLoader.item.active = false |
3697 | - } |
3698 | - } |
3699 | - SmoothedAnimation { |
3700 | - target: bottomEdge |
3701 | - property: "y" |
3702 | - duration: UbuntuAnimation.SlowDuration |
3703 | - } |
3704 | - ScriptAction { |
3705 | - script: { |
3706 | - // destroy current bottom page |
3707 | - if (page.reloadBottomEdgePage) { |
3708 | - edgeLoader.active = false |
3709 | - // tip will receive focus on page active true |
3710 | - } else { |
3711 | - tip.forceActiveFocus() |
3712 | - } |
3713 | - |
3714 | - // notify |
3715 | - page.bottomEdgeDismissed() |
3716 | - |
3717 | - edgeLoader.active = true |
3718 | - } |
3719 | - } |
3720 | - } |
3721 | - }, |
3722 | - Transition { |
3723 | - from: "floating" |
3724 | - to: "collapsed" |
3725 | - SmoothedAnimation { |
3726 | - target: bottomEdge |
3727 | - property: "y" |
3728 | - duration: UbuntuAnimation.FastDuration |
3729 | - } |
3730 | - } |
3731 | - ] |
3732 | - |
3733 | - Loader { |
3734 | - id: edgeLoader |
3735 | - |
3736 | - asynchronous: true |
3737 | - anchors.fill: parent |
3738 | - //WORKAROUND: The SDK move the page contents down to allocate space for the header we need to avoid that during the page dragging |
3739 | - Binding { |
3740 | - target: edgeLoader.status === Loader.Ready ? edgeLoader : null |
3741 | - property: "anchors.topMargin" |
3742 | - value: edgeLoader.item && edgeLoader.item.flickable ? edgeLoader.item.flickable.contentY : 0 |
3743 | - when: !page.isReady |
3744 | - } |
3745 | - |
3746 | - onLoaded: { |
3747 | - tip.forceActiveFocus() |
3748 | - if (page.isReady && edgeLoader.item.active !== true) { |
3749 | - page._pushPage() |
3750 | - } |
3751 | - } |
3752 | - } |
3753 | - } |
3754 | -} |
3755 | |
3756 | === removed file 'app/components/PictureButton.qml' |
3757 | --- app/components/PictureButton.qml 2014-10-04 17:44:08 +0000 |
3758 | +++ app/components/PictureButton.qml 1970-01-01 00:00:00 +0000 |
3759 | @@ -1,40 +0,0 @@ |
3760 | -/* |
3761 | - This file is part of quick-memo |
3762 | - Copyright (C) 2014 Stefano Verzegnassi |
3763 | - |
3764 | - This program is free software: you can redistribute it and/or modify |
3765 | - it under the terms of the GNU General Public License 3 as published by |
3766 | - the Free Software Foundation. |
3767 | - |
3768 | - This program is distributed in the hope that it will be useful, |
3769 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
3770 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3771 | - GNU General Public License for more details. |
3772 | - |
3773 | - You should have received a copy of the GNU General Public License |
3774 | - along with this program. If not, see http://www.gnu.org/licenses/. |
3775 | -*/ |
3776 | - |
3777 | -import QtQuick 2.0 |
3778 | -import Ubuntu.Components 1.1 |
3779 | - |
3780 | -AbstractButton { |
3781 | - id: rootItem |
3782 | - width: units.gu(8) |
3783 | - height: units.gu(8) |
3784 | - |
3785 | - property alias image: shape.image |
3786 | - default property alias contentsItem: shape.data |
3787 | - |
3788 | - onPressedChanged: { |
3789 | - if (pressed) |
3790 | - shape.borderSource = "radius_pressed.sci" |
3791 | - else |
3792 | - shape.borderSource = "radius_idle.sci" |
3793 | - } |
3794 | - |
3795 | - UbuntuShape { |
3796 | - id: shape |
3797 | - anchors.fill: parent |
3798 | - } |
3799 | -} |
3800 | |
3801 | === removed file 'app/components/PicturesManager.qml' |
3802 | --- app/components/PicturesManager.qml 2014-10-21 18:21:13 +0000 |
3803 | +++ app/components/PicturesManager.qml 1970-01-01 00:00:00 +0000 |
3804 | @@ -1,162 +0,0 @@ |
3805 | -/* |
3806 | - This file is part of quick-memo |
3807 | - Copyright (C) 2014 Stefano Verzegnassi |
3808 | - |
3809 | - This program is free software: you can redistribute it and/or modify |
3810 | - it under the terms of the GNU General Public License 3 as published by |
3811 | - the Free Software Foundation. |
3812 | - |
3813 | - This program is distributed in the hope that it will be useful, |
3814 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
3815 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3816 | - GNU General Public License for more details. |
3817 | - |
3818 | - You should have received a copy of the GNU General Public License |
3819 | - along with this program. If not, see http://www.gnu.org/licenses/. |
3820 | -*/ |
3821 | - |
3822 | -import QtQuick 2.0 |
3823 | -import Ubuntu.Components 1.1 |
3824 | -import Ubuntu.Thumbnailer 0.1 |
3825 | -import Ubuntu.Content 0.1 |
3826 | -import Ubuntu.Components.Popups 1.0 |
3827 | -import Ubuntu.Components.ListItems 1.0 as ListItem |
3828 | - |
3829 | -Item { |
3830 | - id: rootItem |
3831 | - |
3832 | - property alias model: repeater.model |
3833 | - |
3834 | - width: parent.width |
3835 | - height: childrenRect.height |
3836 | - |
3837 | - signal picsModelChanged() |
3838 | - |
3839 | - function exportModel() { |
3840 | - var list = [] |
3841 | - for (var i=0; i<picModel.count; i++) { |
3842 | - list[i] = picModel.get(i) |
3843 | - } |
3844 | - |
3845 | - return list |
3846 | - } |
3847 | - |
3848 | - ListItem.Header { id: header; text: i18n.tr("Related pictures:") } |
3849 | - |
3850 | - Flow { |
3851 | - id: flow |
3852 | - |
3853 | - anchors { |
3854 | - top: header.bottom; topMargin: units.gu(1) |
3855 | - left: parent.left |
3856 | - right: parent.right |
3857 | - margins: units.gu(2) |
3858 | - } |
3859 | - spacing: units.gu(2) |
3860 | - |
3861 | - Repeater { |
3862 | - id: repeater |
3863 | - |
3864 | - model: ListModel { id: picModel; onRowsRemoved: rootItem.picsModelChanged() } |
3865 | - delegate: PictureButton { |
3866 | - image: Image { |
3867 | - source: "image://thumbnailer/" + Qt.resolvedUrl(model.url) |
3868 | - fillMode: Image.PreserveAspectCrop |
3869 | - } |
3870 | - |
3871 | - //TODO: Add right click support |
3872 | - onClicked: pageStack.push(Qt.resolvedUrl("./ImageViewer.qml"), {source: Qt.resolvedUrl(model.url)}) |
3873 | - onPressAndHold: PopupUtils.open(pictureMenuPopover, this, {index: model.index}) |
3874 | - } |
3875 | - } |
3876 | - |
3877 | - PictureButton { |
3878 | - Icon { |
3879 | - anchors.centerIn: parent |
3880 | - height: parent.height / 2 |
3881 | - width: height |
3882 | - name: "add" |
3883 | - } |
3884 | - |
3885 | - onClicked: rootItem.importImageFromContentHub() |
3886 | - } |
3887 | - } |
3888 | - |
3889 | - // *** CONTENT HANDLER *** |
3890 | - //This should be probably moved in main.qml |
3891 | - property var activeTransfer |
3892 | - |
3893 | - function importImageFromContentHub() { |
3894 | - pageStack.push(picker) |
3895 | - } |
3896 | - |
3897 | - Page { |
3898 | - id: picker |
3899 | - visible: false |
3900 | - |
3901 | - ContentPeerPicker { |
3902 | - visible: parent.visible |
3903 | - |
3904 | - contentType: ContentType.Pictures |
3905 | - handler: ContentHandler.Source |
3906 | - |
3907 | - onPeerSelected: { |
3908 | - rootItem.activeTransfer = peer.request(appStore); |
3909 | - pageStack.pop(); |
3910 | - } |
3911 | - |
3912 | - onCancelPressed: { |
3913 | - pageStack.pop(); |
3914 | - } |
3915 | - } |
3916 | - } |
3917 | - |
3918 | - ContentTransferHint { |
3919 | - id: transferHint |
3920 | - anchors.fill: parent |
3921 | - activeTransfer: rootItem.activeTransfer |
3922 | - } |
3923 | - |
3924 | - ContentStore { |
3925 | - id: appStore |
3926 | - scope: ContentScope.App |
3927 | - } |
3928 | - |
3929 | - Connections { |
3930 | - target: rootItem.activeTransfer ? rootItem.activeTransfer : null |
3931 | - onStateChanged: { |
3932 | - if (rootItem.activeTransfer.state === ContentTransfer.Charged) { |
3933 | - for (var i=0; i<rootItem.activeTransfer.items.length; i++) { |
3934 | - picModel.append({url: rootItem.activeTransfer.items[i].url.toString().replace("file://", "")}) |
3935 | - console.log("CONTENT IMPORTED:", rootItem.activeTransfer.items[i].url.toString().replace("file://", "")) |
3936 | - rootItem.picsModelChanged() |
3937 | - } |
3938 | - } |
3939 | - } |
3940 | - } |
3941 | - |
3942 | - // *** PICTURE POPOVER *** |
3943 | - Component { |
3944 | - id: pictureMenuPopover |
3945 | - ActionSelectionPopover { |
3946 | - id: popover |
3947 | - property int index |
3948 | - |
3949 | - actions: ActionList { |
3950 | - Action { |
3951 | - text: i18n.tr("Remove picture from selection") |
3952 | - onTriggered: { |
3953 | - PopupUtils.close(popover) |
3954 | - rootItem.model.remove(popover.index) |
3955 | - } |
3956 | - } |
3957 | - } |
3958 | - |
3959 | - delegate: ListItem.Standard { |
3960 | - // ForegroundColor is not correctly set |
3961 | - __foregroundColor: Theme.palette.normal.overlayText |
3962 | - showDivider: false |
3963 | - } |
3964 | - } |
3965 | - } |
3966 | -} |
3967 | |
3968 | === removed file 'app/components/Toaster.qml' |
3969 | --- app/components/Toaster.qml 2014-10-22 12:43:11 +0000 |
3970 | +++ app/components/Toaster.qml 1970-01-01 00:00:00 +0000 |
3971 | @@ -1,81 +0,0 @@ |
3972 | -/* |
3973 | - This file is part of quick-memo |
3974 | - Copyright (C) 2014 Stefano Verzegnassi |
3975 | - |
3976 | - This program is free software: you can redistribute it and/or modify |
3977 | - it under the terms of the GNU General Public License 3 as published by |
3978 | - the Free Software Foundation. |
3979 | - |
3980 | - This program is distributed in the hope that it will be useful, |
3981 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
3982 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3983 | - GNU General Public License for more details. |
3984 | - |
3985 | - You should have received a copy of the GNU General Public License |
3986 | - along with this program. If not, see http://www.gnu.org/licenses/. |
3987 | -*/ |
3988 | - |
3989 | -import QtQuick 2.0 |
3990 | -import Ubuntu.Components 1.1 |
3991 | - |
3992 | -Rectangle { |
3993 | - id: rootItem |
3994 | - |
3995 | - property alias text: label.text |
3996 | - |
3997 | - width: parent.width |
3998 | - height: units.gu(8) |
3999 | - |
4000 | - color: "#131313" |
4001 | - opacity: 0.85 |
4002 | - |
4003 | - anchors { |
4004 | - horizontalCenter: parent.horizontalCenter |
4005 | - bottom: parent.bottom; bottomMargin: - height |
4006 | - } |
4007 | - |
4008 | - Label { |
4009 | - id: label |
4010 | - anchors.centerIn: parent |
4011 | - |
4012 | - font.weight: Font.DemiBold |
4013 | - color: "white" |
4014 | - } |
4015 | - |
4016 | - MouseArea { |
4017 | - anchors.fill: parent |
4018 | - |
4019 | - onClicked: { |
4020 | - showAnimation.stop() |
4021 | - destroyAnimation.restart() |
4022 | - } |
4023 | - } |
4024 | - |
4025 | - Rectangle { |
4026 | - anchors { |
4027 | - bottom: parent.bottom |
4028 | - left: parent.left |
4029 | - right: parent.right |
4030 | - } |
4031 | - |
4032 | - height: units.dp(2) |
4033 | - color: UbuntuColors.orange |
4034 | - } |
4035 | - |
4036 | - SequentialAnimation { |
4037 | - id: showAnimation |
4038 | - running: true |
4039 | - |
4040 | - NumberAnimation { target: rootItem; property: "anchors.bottomMargin"; to: 0; duration: 300 } |
4041 | - PauseAnimation { duration: 2000 } |
4042 | - ScriptAction { script: destroyAnimation.restart() } |
4043 | - } |
4044 | - |
4045 | - SequentialAnimation { |
4046 | - id: destroyAnimation |
4047 | - |
4048 | - NumberAnimation { target: rootItem; property: "opacity"; to: 0; duration: 500 } |
4049 | - ScriptAction { script: rootItem.destroy() } |
4050 | - } |
4051 | -} |
4052 | - |
4053 | |
4054 | === removed file 'app/components/dateHelper.js' |
4055 | --- app/components/dateHelper.js 2014-08-04 17:05:04 +0000 |
4056 | +++ app/components/dateHelper.js 1970-01-01 00:00:00 +0000 |
4057 | @@ -1,23 +0,0 @@ |
4058 | -/* |
4059 | - This file is part of quick-memo |
4060 | - Copyright (C) 2014 Stefano Verzegnassi |
4061 | - |
4062 | - This program is free software: you can redistribute it and/or modify |
4063 | - it under the terms of the GNU General Public License 3 as published by |
4064 | - the Free Software Foundation. |
4065 | - |
4066 | - This program is distributed in the hope that it will be useful, |
4067 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
4068 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4069 | - GNU General Public License for more details. |
4070 | - |
4071 | - You should have received a copy of the GNU General Public License |
4072 | - along with this program. If not, see http://www.gnu.org/licenses/. |
4073 | -*/ |
4074 | - |
4075 | -function parseDate(value) { |
4076 | - var d = new Date(); |
4077 | - d.setTime(value) |
4078 | - |
4079 | - return d |
4080 | -} |
4081 | |
4082 | === added directory 'app/editPage' |
4083 | === added file 'app/editPage/ListManager.qml' |
4084 | --- app/editPage/ListManager.qml 1970-01-01 00:00:00 +0000 |
4085 | +++ app/editPage/ListManager.qml 2015-04-26 16:57:43 +0000 |
4086 | @@ -0,0 +1,313 @@ |
4087 | +/* |
4088 | + This file is part of quick-memo |
4089 | + Copyright (C) 2014, 2015 Stefano Verzegnassi |
4090 | + |
4091 | + This program is free software: you can redistribute it and/or modify |
4092 | + it under the terms of the GNU General Public License 3 as published by |
4093 | + the Free Software Foundation. |
4094 | + |
4095 | + This program is distributed in the hope that it will be useful, |
4096 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
4097 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4098 | + GNU General Public License for more details. |
4099 | + |
4100 | + You should have received a copy of the GNU General Public License |
4101 | + along with this program. If not, see http://www.gnu.org/licenses/. |
4102 | +*/ |
4103 | + |
4104 | +import QtQuick 2.0 |
4105 | +import Ubuntu.Components 1.1 |
4106 | +import Ubuntu.Keyboard 0.1 |
4107 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
4108 | + |
4109 | +import "../common" |
4110 | + |
4111 | +Column { |
4112 | + id: rootItem |
4113 | + |
4114 | + width: parent.width |
4115 | + spacing: units.gu(0.25) |
4116 | + |
4117 | + property Flickable flickable |
4118 | + property alias model: repeater.model |
4119 | + property alias delegate: repeater.delegate |
4120 | + property alias footer: footerLoader.sourceComponent |
4121 | + readonly property bool focusOnLastItem: (model.focusedIndex === -1) || (model.focusedIndex === (model.count - 1)) |
4122 | + |
4123 | + signal listChanged() |
4124 | + |
4125 | + ListItem.Header { |
4126 | + text: i18n.tr("List:") |
4127 | + } |
4128 | + |
4129 | + Repeater { |
4130 | + id: repeater |
4131 | + width: parent.width |
4132 | + |
4133 | + model: ListModel { |
4134 | + id: dataModel |
4135 | + |
4136 | + property int focusedIndex: -1 |
4137 | + } |
4138 | + |
4139 | + delegate: delegate |
4140 | + } |
4141 | + |
4142 | + // TODO: When user adds an element in the list, the new element should gain focus. |
4143 | + Loader { |
4144 | + id: footerLoader |
4145 | + width: parent.width |
4146 | + |
4147 | + sourceComponent: ListItem.Empty { |
4148 | + width: parent.width |
4149 | + opacity: enabled ? 1.0 : 0.5 |
4150 | + showDivider: false |
4151 | + |
4152 | + enabled: { |
4153 | + if (rootItem.model.count > 0) { |
4154 | + if (rootItem.model.get(rootItem.model.count - 1).text !== "") { |
4155 | + return true |
4156 | + } else { |
4157 | + return false |
4158 | + } |
4159 | + } else { |
4160 | + return true |
4161 | + } |
4162 | + } |
4163 | + |
4164 | + Row { |
4165 | + spacing: units.gu(2) |
4166 | + anchors { |
4167 | + left: parent.left; leftMargin: units.gu(2); |
4168 | + right: parent.right; |
4169 | + verticalCenter: parent.verticalCenter |
4170 | + } |
4171 | + |
4172 | + Item { |
4173 | + id: addListBtnImage |
4174 | + implicitWidth: units.gu(4.25) |
4175 | + implicitHeight: units.gu(4) |
4176 | + |
4177 | + Icon { |
4178 | + anchors { fill: parent; margins: units.gu(0.5) } |
4179 | + name: "add" |
4180 | + } |
4181 | + } |
4182 | + |
4183 | + Label { |
4184 | + id: addListBtnLabel |
4185 | + // TRANSLATORS: Text of a button used for add an item in the To-do list. |
4186 | + text: i18n.tr("Add item") |
4187 | + anchors.verticalCenter: addListBtnImage.verticalCenter |
4188 | + } |
4189 | + } |
4190 | + |
4191 | + onClicked: { |
4192 | + rootItem.addItem({"checked": false, "text": ""}) |
4193 | + // Here we don't send listChanged signal, since it is an empty item that should not be saved |
4194 | + } |
4195 | + } |
4196 | + } |
4197 | + |
4198 | + |
4199 | + function exportModel() { |
4200 | + var list = [] |
4201 | + |
4202 | + if (rootItem.model.count > 0 && rootItem.model.get(0).text !== "") { |
4203 | + for (var i=0; i<rootItem.model.count; i++) { |
4204 | + if (i != rootItem.model.count && rootItem.model.get(i).text != "") { |
4205 | + list[i] = rootItem.model.get(i) |
4206 | + } |
4207 | + } |
4208 | + } |
4209 | + |
4210 | + return list |
4211 | + } |
4212 | + |
4213 | + function addItem(args) { |
4214 | + rootItem.model.append(args) |
4215 | + var newItem = repeater.itemAt(repeater.count - 1) |
4216 | + newItem.textArea.forceActiveFocus() |
4217 | + autoScrollAnimation.makeMeVisible(newItem) |
4218 | + } |
4219 | + |
4220 | + SequentialAnimation { |
4221 | + id: autoScrollAnimation |
4222 | + |
4223 | + property var targetItem: null |
4224 | + alwaysRunToEnd: true |
4225 | + |
4226 | + // wait item be moved to correct place |
4227 | + PauseAnimation { |
4228 | + duration: 100 |
4229 | + } |
4230 | + // scroll to new item position |
4231 | + ScriptAction { |
4232 | + script: { |
4233 | + if (autoScrollAnimation.targetItem) { |
4234 | + autoScrollAnimation.makeMeVisibleImpl(autoScrollAnimation.targetItem) |
4235 | + autoScrollAnimation.targetItem = null |
4236 | + } |
4237 | + } |
4238 | + } |
4239 | + |
4240 | + function makeMeVisible(newItem) { |
4241 | + autoScrollAnimation.targetItem = newItem |
4242 | + autoScrollAnimation.restart() |
4243 | + } |
4244 | + |
4245 | + function makeMeVisibleImpl(newItem) { |
4246 | + if (!newItem) { |
4247 | + return |
4248 | + } |
4249 | + |
4250 | + var positionY = rootItem.y + repeater.y + newItem.y |
4251 | + |
4252 | + // check if the item is already visible |
4253 | + var bottomY = flickable.contentY + flickable.height |
4254 | + var itemBottom = positionY + (newItem.height *3) // margin |
4255 | + if (positionY >= flickable.contentY && itemBottom <= bottomY) { |
4256 | + return; |
4257 | + } |
4258 | + |
4259 | + // if it is not, try to scroll and make it visible |
4260 | + var targetY = itemBottom - flickable.height |
4261 | + if (targetY >= 0 && positionY) { |
4262 | + flickable.contentY = targetY |
4263 | + } else if (positionY < flickable.contentY) { |
4264 | + // if it is hidden at the top, also show it |
4265 | + flickable.contentY = positionY |
4266 | + } |
4267 | + flickable.returnToBounds() |
4268 | + } |
4269 | + } |
4270 | + |
4271 | + |
4272 | + // *** DELEGATE *** |
4273 | + Component { |
4274 | + id: delegate |
4275 | + |
4276 | + ListItem.Empty { |
4277 | + id: item |
4278 | + width: parent ? parent.width : undefined |
4279 | + height: (layoutDelegate.height > item.__height) ? layoutDelegate.height : item.__height |
4280 | + |
4281 | + showDivider: false |
4282 | + |
4283 | + property alias textArea: textArea |
4284 | + |
4285 | + Rectangle { |
4286 | + anchors.fill: parent |
4287 | + opacity: 0.1 |
4288 | + visible: textArea.activeFocus |
4289 | + color: "black" |
4290 | + } |
4291 | + |
4292 | + backgroundIndicator: Rectangle { |
4293 | + anchors.fill: parent |
4294 | + color: "red" |
4295 | + |
4296 | + Icon { |
4297 | + anchors.centerIn: parent |
4298 | + name: "delete" |
4299 | + color: Theme.palette.selected.field |
4300 | + height: units.gu(3) |
4301 | + width: units.gu(3) |
4302 | + } |
4303 | + } |
4304 | + |
4305 | + // ListItem is removable for all items, except the first when the text field is empty. |
4306 | + //confirmRemoval: true |
4307 | + removable: rootItem.model.count > 1 || (rootItem.model.get(0).text !== "") |
4308 | + confirmRemoval: true |
4309 | + onItemRemoved: { |
4310 | + // Send the signal before removing the item. This avoids a ReferenceError. |
4311 | + rootItem.listChanged() |
4312 | + rootItem.model.remove(model.index) |
4313 | + } |
4314 | + |
4315 | + Row { |
4316 | + id: layoutDelegate |
4317 | + |
4318 | + anchors { |
4319 | + left: parent.left |
4320 | + right: parent.right |
4321 | + margins: units.gu(2) |
4322 | + verticalCenter: parent.verticalCenter |
4323 | + } |
4324 | + |
4325 | + spacing: units.gu(1) |
4326 | + height: Math.max(checkBox.height, textArea.height) |
4327 | + |
4328 | + CheckBox { |
4329 | + id: checkBox |
4330 | + |
4331 | + checked: model.checked |
4332 | + onCheckedChanged: layoutDelegate.updateModel() |
4333 | + |
4334 | + style: Item { |
4335 | + implicitWidth: units.gu(4.25) |
4336 | + implicitHeight: units.gu(4) |
4337 | + |
4338 | + Image { |
4339 | + anchors { fill: parent; margins: units.gu(0.5) } |
4340 | + |
4341 | + source: checkBox.checked ? "../../graphics/select.svg" : "../../graphics/unselect.svg" |
4342 | + } |
4343 | + } |
4344 | + } |
4345 | + |
4346 | + NoteTextField { |
4347 | + id: textArea |
4348 | + |
4349 | + width: parent.width - (checkBox.width + (parent.spacing * 2)) |
4350 | + anchors.verticalCenter: parent.verticalCenter |
4351 | + |
4352 | + font.strikeout: checkBox.checked |
4353 | + |
4354 | + onFocusReceived: { |
4355 | + rootItem.model.focusedIndex = model.index |
4356 | + } |
4357 | + |
4358 | + text: model.text |
4359 | + onTextChanged: { |
4360 | + layoutDelegate.updateModel() |
4361 | + |
4362 | + /* This requires some test. No problem when TextField is used, but it seems to break dataModel when |
4363 | + TextArea is used. Could be related to NoteTextArea.qml, line 39.*/ |
4364 | + if (text === "") { |
4365 | + rootItem.model.remove(model.index) |
4366 | + } |
4367 | + } |
4368 | + |
4369 | + //hasClearButton: false |
4370 | + focus: true |
4371 | + |
4372 | + // Ubuntu Keyboard |
4373 | + // TODO: Disable Enter key if model.text is empty. |
4374 | + InputMethod.extensions: { |
4375 | + "enterKeyText": rootItem.focusOnLastItem ? i18n.tr("Add") : i18n.tr("Next") |
4376 | + } |
4377 | + |
4378 | + Keys.onReturnPressed: { |
4379 | + if (rootItem.focusOnLastItem && (model.text !== "")) { |
4380 | + // Create a new item. |
4381 | + rootItem.addItem({"checked": false, "text": ""}) |
4382 | + } else if (!rootItem.focusOnLastItem) { |
4383 | + var nextItem = repeater.itemAt(model.index + 1) |
4384 | + if (nextItem) { |
4385 | + nextItem.textArea.forceActiveFocus() |
4386 | + autoScrollAnimation.makeMeVisible(nextItem) |
4387 | + } |
4388 | + } |
4389 | + } |
4390 | + } |
4391 | + |
4392 | + function updateModel() { |
4393 | + rootItem.model.set(model.index, {"checked": checkBox.checked, "text": textArea.text}) |
4394 | + rootItem.listChanged() |
4395 | + } |
4396 | + } |
4397 | + } |
4398 | + } |
4399 | +} |
4400 | |
4401 | === added file 'app/editPage/PictureButton.qml' |
4402 | --- app/editPage/PictureButton.qml 1970-01-01 00:00:00 +0000 |
4403 | +++ app/editPage/PictureButton.qml 2015-04-26 16:57:43 +0000 |
4404 | @@ -0,0 +1,40 @@ |
4405 | +/* |
4406 | + This file is part of quick-memo |
4407 | + Copyright (C) 2014 Stefano Verzegnassi |
4408 | + |
4409 | + This program is free software: you can redistribute it and/or modify |
4410 | + it under the terms of the GNU General Public License 3 as published by |
4411 | + the Free Software Foundation. |
4412 | + |
4413 | + This program is distributed in the hope that it will be useful, |
4414 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
4415 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4416 | + GNU General Public License for more details. |
4417 | + |
4418 | + You should have received a copy of the GNU General Public License |
4419 | + along with this program. If not, see http://www.gnu.org/licenses/. |
4420 | +*/ |
4421 | + |
4422 | +import QtQuick 2.0 |
4423 | +import Ubuntu.Components 1.1 |
4424 | + |
4425 | +AbstractButton { |
4426 | + id: rootItem |
4427 | + width: units.gu(8) |
4428 | + height: units.gu(8) |
4429 | + |
4430 | + property alias image: shape.image |
4431 | + default property alias contentsItem: shape.data |
4432 | + |
4433 | + onPressedChanged: { |
4434 | + if (pressed) |
4435 | + shape.borderSource = "radius_pressed.sci" |
4436 | + else |
4437 | + shape.borderSource = "radius_idle.sci" |
4438 | + } |
4439 | + |
4440 | + UbuntuShape { |
4441 | + id: shape |
4442 | + anchors.fill: parent |
4443 | + } |
4444 | +} |
4445 | |
4446 | === added file 'app/editPage/PicturesManager.qml' |
4447 | --- app/editPage/PicturesManager.qml 1970-01-01 00:00:00 +0000 |
4448 | +++ app/editPage/PicturesManager.qml 2015-04-26 16:57:43 +0000 |
4449 | @@ -0,0 +1,162 @@ |
4450 | +/* |
4451 | + This file is part of quick-memo |
4452 | + Copyright (C) 2014, 2015 Stefano Verzegnassi |
4453 | + |
4454 | + This program is free software: you can redistribute it and/or modify |
4455 | + it under the terms of the GNU General Public License 3 as published by |
4456 | + the Free Software Foundation. |
4457 | + |
4458 | + This program is distributed in the hope that it will be useful, |
4459 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
4460 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4461 | + GNU General Public License for more details. |
4462 | + |
4463 | + You should have received a copy of the GNU General Public License |
4464 | + along with this program. If not, see http://www.gnu.org/licenses/. |
4465 | +*/ |
4466 | + |
4467 | +import QtQuick 2.0 |
4468 | +import Ubuntu.Components 1.1 |
4469 | +import Ubuntu.Thumbnailer 0.1 |
4470 | +import Ubuntu.Content 0.1 |
4471 | +import Ubuntu.Components.Popups 1.0 |
4472 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
4473 | + |
4474 | +Item { |
4475 | + id: rootItem |
4476 | + |
4477 | + property alias model: repeater.model |
4478 | + |
4479 | + width: parent.width |
4480 | + height: childrenRect.height |
4481 | + |
4482 | + signal picsModelChanged() |
4483 | + |
4484 | + function exportModel() { |
4485 | + var list = [] |
4486 | + for (var i=0; i<picModel.count; i++) { |
4487 | + list[i] = picModel.get(i) |
4488 | + } |
4489 | + |
4490 | + return list |
4491 | + } |
4492 | + |
4493 | + ListItem.Header { id: header; text: i18n.tr("Related pictures:") } |
4494 | + |
4495 | + Flow { |
4496 | + id: flow |
4497 | + |
4498 | + anchors { |
4499 | + top: header.bottom; topMargin: units.gu(1) |
4500 | + left: parent.left |
4501 | + right: parent.right |
4502 | + margins: units.gu(2) |
4503 | + } |
4504 | + spacing: units.gu(2) |
4505 | + |
4506 | + Repeater { |
4507 | + id: repeater |
4508 | + |
4509 | + model: ListModel { id: picModel; onRowsRemoved: rootItem.picsModelChanged() } |
4510 | + delegate: PictureButton { |
4511 | + image: Image { |
4512 | + source: "image://thumbnailer/" + Qt.resolvedUrl(model.url) |
4513 | + fillMode: Image.PreserveAspectCrop |
4514 | + } |
4515 | + |
4516 | + //TODO: Add right click support |
4517 | + onClicked: pageStack.push(Qt.resolvedUrl("../ui/ImageViewer.qml"), {source: Qt.resolvedUrl(model.url)}) |
4518 | + onPressAndHold: PopupUtils.open(pictureMenuPopover, this, {index: model.index}) |
4519 | + } |
4520 | + } |
4521 | + |
4522 | + PictureButton { |
4523 | + Icon { |
4524 | + anchors.centerIn: parent |
4525 | + height: parent.height / 2 |
4526 | + width: height |
4527 | + name: "add" |
4528 | + } |
4529 | + |
4530 | + onClicked: rootItem.importImageFromContentHub() |
4531 | + } |
4532 | + } |
4533 | + |
4534 | + // *** CONTENT HANDLER *** |
4535 | + //This should be probably moved in main.qml |
4536 | + property var activeTransfer |
4537 | + |
4538 | + function importImageFromContentHub() { |
4539 | + pageStack.push(picker) |
4540 | + } |
4541 | + |
4542 | + Page { |
4543 | + id: picker |
4544 | + visible: false |
4545 | + |
4546 | + ContentPeerPicker { |
4547 | + visible: parent.visible |
4548 | + |
4549 | + contentType: ContentType.Pictures |
4550 | + handler: ContentHandler.Source |
4551 | + |
4552 | + onPeerSelected: { |
4553 | + rootItem.activeTransfer = peer.request(appStore); |
4554 | + pageStack.pop(); |
4555 | + } |
4556 | + |
4557 | + onCancelPressed: { |
4558 | + pageStack.pop(); |
4559 | + } |
4560 | + } |
4561 | + } |
4562 | + |
4563 | + ContentTransferHint { |
4564 | + id: transferHint |
4565 | + anchors.fill: parent |
4566 | + activeTransfer: rootItem.activeTransfer |
4567 | + } |
4568 | + |
4569 | + ContentStore { |
4570 | + id: appStore |
4571 | + scope: ContentScope.App |
4572 | + } |
4573 | + |
4574 | + Connections { |
4575 | + target: rootItem.activeTransfer ? rootItem.activeTransfer : null |
4576 | + onStateChanged: { |
4577 | + if (rootItem.activeTransfer.state === ContentTransfer.Charged) { |
4578 | + for (var i=0; i<rootItem.activeTransfer.items.length; i++) { |
4579 | + picModel.append({url: rootItem.activeTransfer.items[i].url.toString().replace("file://", "")}) |
4580 | + console.log("CONTENT IMPORTED:", rootItem.activeTransfer.items[i].url.toString().replace("file://", "")) |
4581 | + rootItem.picsModelChanged() |
4582 | + } |
4583 | + } |
4584 | + } |
4585 | + } |
4586 | + |
4587 | + // *** PICTURE POPOVER *** |
4588 | + Component { |
4589 | + id: pictureMenuPopover |
4590 | + ActionSelectionPopover { |
4591 | + id: popover |
4592 | + property int index |
4593 | + |
4594 | + actions: ActionList { |
4595 | + Action { |
4596 | + text: i18n.tr("Remove picture from selection") |
4597 | + onTriggered: { |
4598 | + PopupUtils.close(popover) |
4599 | + rootItem.model.remove(popover.index) |
4600 | + } |
4601 | + } |
4602 | + } |
4603 | + |
4604 | + delegate: ListItem.Standard { |
4605 | + // ForegroundColor is not correctly set |
4606 | + __foregroundColor: Theme.palette.normal.overlayText |
4607 | + showDivider: false |
4608 | + } |
4609 | + } |
4610 | + } |
4611 | +} |
4612 | |
4613 | === modified file 'app/main.qml' |
4614 | --- app/main.qml 2014-10-21 16:01:52 +0000 |
4615 | +++ app/main.qml 2015-04-26 16:57:43 +0000 |
4616 | @@ -1,6 +1,6 @@ |
4617 | /* |
4618 | This file is part of quick-memo |
4619 | - Copyright (C) 2014 Stefano Verzegnassi |
4620 | + Copyright (C) 2014, 2015 Stefano Verzegnassi |
4621 | |
4622 | This program is free software: you can redistribute it and/or modify |
4623 | it under the terms of the GNU General Public License 3 as published by |
4624 | @@ -18,7 +18,7 @@ |
4625 | import QtQuick 2.0 |
4626 | import Ubuntu.Components 1.1 |
4627 | import Qt.labs.settings 1.0 |
4628 | -import "components" |
4629 | +import "common" |
4630 | |
4631 | MainView { |
4632 | id: root |
4633 | @@ -42,28 +42,15 @@ |
4634 | } |
4635 | |
4636 | // This is where we manage the pages of the application. |
4637 | - PageStack { |
4638 | - id: pageStack |
4639 | - |
4640 | - Component { |
4641 | - id: mainPage |
4642 | - MainPage {} |
4643 | - } |
4644 | - |
4645 | - Component { |
4646 | - id: memoPage |
4647 | - EditMemoPage {} |
4648 | - } |
4649 | - } |
4650 | + PageStack { id: pageStack } |
4651 | |
4652 | NoteModel { |
4653 | id: notes |
4654 | - onInitialized: pageStack.push(mainPage) |
4655 | + onInitialized: pageStack.push(Qt.resolvedUrl("./ui/MainPage.qml")) |
4656 | } |
4657 | |
4658 | - |
4659 | function showNotification(text) { |
4660 | - var component = Qt.createComponent("components/Toaster.qml") |
4661 | + var component = Qt.createComponent("./common/Toaster.qml") |
4662 | var toast = component.createObject(root, {"text" : text}); |
4663 | } |
4664 | |
4665 | |
4666 | === added directory 'app/mainPage' |
4667 | === added file 'app/mainPage/Delegate.qml' |
4668 | --- app/mainPage/Delegate.qml 1970-01-01 00:00:00 +0000 |
4669 | +++ app/mainPage/Delegate.qml 2015-04-26 16:57:43 +0000 |
4670 | @@ -0,0 +1,291 @@ |
4671 | +/* |
4672 | + This file is part of quick-memo |
4673 | + Copyright (C) 2014, 2015 Stefano Verzegnassi |
4674 | + |
4675 | + This program is free software: you can redistribute it and/or modify |
4676 | + it under the terms of the GNU General Public License 3 as published by |
4677 | + the Free Software Foundation. |
4678 | + |
4679 | + This program is distributed in the hope that it will be useful, |
4680 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
4681 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4682 | + GNU General Public License for more details. |
4683 | + |
4684 | + You should have received a copy of the GNU General Public License |
4685 | + along with this program. If not, see http://www.gnu.org/licenses/. |
4686 | +*/ |
4687 | + |
4688 | +import QtQuick 2.0 |
4689 | +import Ubuntu.Components 1.1 |
4690 | +import Ubuntu.Thumbnailer 0.1 |
4691 | +import "../common/dateHelper.js" as DateHelper |
4692 | + |
4693 | +AbstractButton { |
4694 | + id: rootItem |
4695 | + |
4696 | + height: layout.height + layout.anchors.topMargin |
4697 | + width: parent.width |
4698 | + |
4699 | + property bool selected: false |
4700 | + property int maxListDelegatesNumber: 3 |
4701 | + |
4702 | + // RGB channels from 'shape.color' are in [0; 1] range. |
4703 | + property color foregroundColor: ((shape.color.r * 0.30 + shape.color.g * 0.59 + shape.color.b * 0.11) > 0.5) ? UbuntuColors.darkGrey : "#F3F3E7" |
4704 | + |
4705 | + UbuntuShape { |
4706 | + id: shape |
4707 | + anchors.fill: parent |
4708 | + |
4709 | + // Add 70% opacity |
4710 | + color: contents.color.toString().replace("#", "#B3") |
4711 | + |
4712 | + radius: "medium" |
4713 | + |
4714 | + Column { |
4715 | + id: layout |
4716 | + anchors { top: parent.top; left: parent.left; right: parent.right; topMargin: units.gu(2) } |
4717 | + |
4718 | + Column { |
4719 | + id: column |
4720 | + width: parent.width - (spacing * 2) |
4721 | + x: spacing |
4722 | + spacing: units.gu(2) |
4723 | + |
4724 | + Loader { |
4725 | + width: parent.width |
4726 | + sourceComponent: (contents.title == "") ? undefined : titleComponent |
4727 | + |
4728 | + Component { |
4729 | + id: titleComponent |
4730 | + |
4731 | + Label { |
4732 | + width: parent.width |
4733 | + fontSize: "large" |
4734 | + font.weight: Font.Bold |
4735 | + text: contents.title |
4736 | + elide: Text.ElideRight |
4737 | + maximumLineCount: 2 |
4738 | + wrapMode: Text.WrapAnywhere |
4739 | + color: rootItem.foregroundColor |
4740 | + } |
4741 | + } |
4742 | + |
4743 | + } |
4744 | + |
4745 | + Loader { |
4746 | + width: parent.width |
4747 | + sourceComponent: (contents.text == "") ? undefined : textComponent |
4748 | + |
4749 | + Component { |
4750 | + id: textComponent |
4751 | + |
4752 | + Label { |
4753 | + width: parent.width |
4754 | + text: contents.text |
4755 | + wrapMode: Text.WrapAnywhere |
4756 | + elide: Text.ElideRight |
4757 | + maximumLineCount: 5 |
4758 | + color: rootItem.foregroundColor |
4759 | + } |
4760 | + } |
4761 | + } |
4762 | + } |
4763 | + |
4764 | + // A spacer item |
4765 | + Item { |
4766 | + width: parent.width |
4767 | + height: units.gu(2) |
4768 | + visible: picsRepeater.count > 0 |
4769 | + } |
4770 | + |
4771 | + Item { |
4772 | + id: picsItem |
4773 | + width: parent.width |
4774 | + height: picFlow.height |
4775 | + |
4776 | + // TODO: As for listDelegates, limit pics to a number of 9 |
4777 | + Flow { |
4778 | + id: picFlow |
4779 | + width: parent.width |
4780 | + |
4781 | + Repeater { |
4782 | + id: picsRepeater |
4783 | + |
4784 | + model: contents.pictures |
4785 | + |
4786 | + delegate: Image { |
4787 | + id: img |
4788 | + width: parent.width |
4789 | + fillMode: Image.PreserveAspectCrop |
4790 | + source: "image://thumbnailer/" + Qt.resolvedUrl(contents.pictures[index].url) |
4791 | + |
4792 | + Connections { |
4793 | + target: picsRepeater |
4794 | + onItemAdded: calculateSize(index) |
4795 | + onItemRemoved: calculateSize(index) |
4796 | + } |
4797 | + |
4798 | + Connections { |
4799 | + target: picFlow |
4800 | + onWidthChanged: calculateSize(index) |
4801 | + } |
4802 | + |
4803 | + Component.onCompleted: calculateSize(index) |
4804 | + |
4805 | + function calculateSize(index) { |
4806 | + var n = picsRepeater.count |
4807 | + var i = n % 3 |
4808 | + var m = Math.floor(n / 3) |
4809 | + |
4810 | + height = units.gu(6) |
4811 | + |
4812 | + // Need to be hardcoded because of an issue. |
4813 | + // FIXME: Think it requires a better solution |
4814 | + var picFlowRealWidth = ((root.width - units.gu(4)) * 0.5) - units.gu(1) |
4815 | + |
4816 | + switch(i) { |
4817 | + case 0: |
4818 | + width = picFlowRealWidth / 3 |
4819 | + return |
4820 | + case 1: |
4821 | + if (index == 0) { |
4822 | + width = picFlowRealWidth |
4823 | + return |
4824 | + } else { |
4825 | + width = picFlowRealWidth / 3 |
4826 | + return |
4827 | + } |
4828 | + case 2: |
4829 | + if (index <= 1) { |
4830 | + width = picFlowRealWidth / 2 |
4831 | + return |
4832 | + } else { |
4833 | + width = picFlowRealWidth / 3 |
4834 | + return |
4835 | + } |
4836 | + } |
4837 | + } |
4838 | + } |
4839 | + } |
4840 | + |
4841 | + Component.onCompleted: picsRepeater.model = contents.pictures |
4842 | + } |
4843 | + } |
4844 | + |
4845 | + Loader { |
4846 | + id: listLoader |
4847 | + width: parent.width |
4848 | + sourceComponent: (contents.list[0]) ? listComponent : null |
4849 | + |
4850 | + Component { |
4851 | + id: listComponent |
4852 | + |
4853 | + Column { |
4854 | + width: parent.width |
4855 | + |
4856 | + // A spacer item |
4857 | + Item { |
4858 | + width: parent.width |
4859 | + height: units.gu(1) |
4860 | + } |
4861 | + |
4862 | + Repeater { |
4863 | + id: listRepeater |
4864 | + width: parent.width |
4865 | + |
4866 | + model: contents.list |
4867 | + |
4868 | + delegate: Loader { |
4869 | + width: parent.width |
4870 | + sourceComponent: model.index < 4 ? listDelegate : null |
4871 | + |
4872 | + Component { |
4873 | + id: listDelegate |
4874 | + |
4875 | + Row { |
4876 | + id: rootItem |
4877 | + spacing: units.gu(1) |
4878 | + width: parent.width |
4879 | + height: Math.max(checkBox.height, textArea.height) |
4880 | + |
4881 | + Item { |
4882 | + id: checkBox |
4883 | + width: parent.width |
4884 | + height: units.gu(4) |
4885 | + |
4886 | + property bool checked: contents.list[index].checked |
4887 | + |
4888 | + Icon { |
4889 | + id: tick |
4890 | + anchors { |
4891 | + left: parent.left; leftMargin: units.gu(2.25); |
4892 | + top: parent.top; topMargin: units.gu(0.35) |
4893 | + } |
4894 | + width: (source == "../../graphics/select.svg") ? units.gu(2.25) : units.gu(1.5) |
4895 | + height: (source == "../../graphics/select.svg") ? units.gu(2) : units.gu(1.5) |
4896 | + |
4897 | + source: checkBox.checked ? "../../graphics/select.svg" : "../../graphics/unselect.svg" |
4898 | + visible: model.index !== 3 |
4899 | + color: foregroundColor |
4900 | + } |
4901 | + |
4902 | + Label { |
4903 | + id: textArea |
4904 | + anchors { left: tick.right; right: parent.right; margins: units.gu(1) } |
4905 | + |
4906 | + font.strikeout: checkBox.checked |
4907 | + text: (model.index == 3) ? ". . ." : contents.list[index].text |
4908 | + elide: Text.ElideRight |
4909 | + maximumLineCount: 2 |
4910 | + wrapMode: Text.WrapAnywhere |
4911 | + color: foregroundColor |
4912 | + } |
4913 | + } |
4914 | + } |
4915 | + } |
4916 | + } |
4917 | + } |
4918 | + |
4919 | + Component.onCompleted: listRepeater.model = contents.list |
4920 | + } |
4921 | + } |
4922 | + } |
4923 | + |
4924 | + // A spacer item |
4925 | + Item { |
4926 | + width: parent.width |
4927 | + height: units.gu(2) |
4928 | + } |
4929 | + |
4930 | + Item { |
4931 | + id: date |
4932 | + width: parent.width |
4933 | + height: units.gu(4) |
4934 | + |
4935 | + Label { |
4936 | + anchors { right: parent.right; verticalCenter: parent.verticalCenter; margins: units.gu(2) } |
4937 | + text: Qt.formatDateTime(DateHelper.parseDate(contents.date), "d MMM yyyy, hh:mm") |
4938 | + fontSize: "small" |
4939 | + color: rootItem.foregroundColor |
4940 | + } |
4941 | + } |
4942 | + } |
4943 | + } |
4944 | + |
4945 | + // Visual feedback when pressed. Not listed in official documentation, still useful. |
4946 | + onPressedChanged: { |
4947 | + if (pressed) |
4948 | + shape.borderSource = "radius_pressed.sci" |
4949 | + else |
4950 | + shape.borderSource = "radius_idle.sci" |
4951 | + } |
4952 | + |
4953 | + // Visual feedback when selected. |
4954 | + onSelectedChanged: { |
4955 | + if (selected) { |
4956 | + shape.color = Qt.darker(contents.color) |
4957 | + } else { |
4958 | + shape.color = contents.color.toString().replace("#", "#B3") |
4959 | + } |
4960 | + } |
4961 | +} |
4962 | |
4963 | === added file 'app/mainPage/HorizontalFlowListView.qml' |
4964 | --- app/mainPage/HorizontalFlowListView.qml 1970-01-01 00:00:00 +0000 |
4965 | +++ app/mainPage/HorizontalFlowListView.qml 2015-04-26 16:57:43 +0000 |
4966 | @@ -0,0 +1,78 @@ |
4967 | +/* |
4968 | + * Copyright 2012 Ruediger Gad |
4969 | + * Copyright 2014 Stefano Verzegnassi <stefano92.100@gmail.com> |
4970 | + * |
4971 | + * This file is part of FlowListView. |
4972 | + * |
4973 | + * FlowListView is free software: you can redistribute it and/or modify |
4974 | + * it under the terms of the GNU Lesser General Public License (LGPL) |
4975 | + * as published by the Free Software Foundation, either version 3 of the |
4976 | + * License, or (at your option) any later version. |
4977 | + * |
4978 | + * FlowListView is distributed in the hope that it will be useful, |
4979 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4980 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4981 | + * GNU General Public License for more details. |
4982 | + * |
4983 | + * You should have received a copy of the GNU Lesser General Public License |
4984 | + * along with FlowListView. If not, see <http://www.gnu.org/licenses/>. |
4985 | + * |
4986 | + */ |
4987 | + |
4988 | +// A derivative version of FlowListView.qml |
4989 | +import QtQuick 2.0 |
4990 | +import Ubuntu.Components 1.1 |
4991 | + |
4992 | +Flickable { |
4993 | + id: flowListView |
4994 | + |
4995 | + contentWidth: flow.childrenRect.width |
4996 | + |
4997 | + property alias count: repeater.count |
4998 | + property int currentIndex: -1 |
4999 | + property variant currentItem; |
5000 | + property alias delegate: repeater.delegate |
The diff has been truncated for viewing.