Merge lp:~verzegnassi-stefano/quick-memo/fix-1360869-1366076 into lp:quick-memo/trunk
- fix-1360869-1366076
- Merge into 0.3
Proposed by
Stefano Verzegnassi
Status: | Merged | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 39 | ||||||||||||||||
Proposed branch: | lp:~verzegnassi-stefano/quick-memo/fix-1360869-1366076 | ||||||||||||||||
Merge into: | lp:quick-memo/trunk | ||||||||||||||||
Diff against target: |
525 lines (+179/-204) 4 files modified
components/AddMemo.qml (+1/-4) components/MainPage.qml (+118/-119) components/MemoPage.qml (+17/-30) components/MultiSelectionHandler.qml (+43/-51) |
||||||||||||||||
To merge this branch: | bzr merge lp:~verzegnassi-stefano/quick-memo/fix-1360869-1366076 | ||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stefano Verzegnassi | Approve | ||
Review via email: mp+236235@code.launchpad.net |
Commit message
Transition to new header API and minor UX fixes
Description of the change
PageHeadConfigu
Minor UX fixes (bottomEdge and Header behaviour). (#1366069 and #1366076)
Remove "Add image" menu option from MemoPage. (#1374148)
To post a comment you must log in.
Revision history for this message
Stefano Verzegnassi (verzegnassi-stefano) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'components/AddMemo.qml' |
2 | --- components/AddMemo.qml 2014-08-29 03:30:43 +0000 |
3 | +++ components/AddMemo.qml 2014-09-27 18:44:34 +0000 |
4 | @@ -70,10 +70,7 @@ |
5 | onTriggered: colorDialog.show() |
6 | } |
7 | |
8 | - tools: ToolbarItems { |
9 | - ToolbarButton { action: colorToolAction } |
10 | - ToolbarButton { action: saveMemo } |
11 | - } |
12 | + head.actions: [colorToolAction, saveMemo] |
13 | |
14 | // Background |
15 | Rectangle { |
16 | |
17 | === modified file 'components/MainPage.qml' |
18 | --- components/MainPage.qml 2014-09-04 15:12:38 +0000 |
19 | +++ components/MainPage.qml 2014-09-27 18:44:34 +0000 |
20 | @@ -23,28 +23,9 @@ |
21 | PageWithBottomEdge { |
22 | id: mainPage |
23 | title: i18n.tr("Overview") |
24 | - flickable: useGridView ? null : viewLoader.item |
25 | - |
26 | - // TODO: Switch to PageHeads. Do it also for MultiSelectionHandler |
27 | - |
28 | - Action { |
29 | - id: openAbout |
30 | - text: i18n.tr("About...") |
31 | - iconName: "help" |
32 | - onTriggered: pageStack.push(Qt.resolvedUrl("AboutPage.qml")) |
33 | - } |
34 | - |
35 | - Action { |
36 | - id: switchView |
37 | - text: useGridView ? i18n.tr("Switch to one-column list") : i18n.tr("Switch to grid") |
38 | - iconName: useGridView ? "view-list-symbolic" : "view-grid-symbolic" |
39 | - onTriggered: useGridView = !useGridView |
40 | - } |
41 | - |
42 | - tools: ToolbarItems { |
43 | - ToolbarButton { action: openAbout } |
44 | - ToolbarButton { action: switchView } |
45 | - } |
46 | + flickable: mainPage.state === "multiSelection" ? null |
47 | + : useGridView ? null |
48 | + : viewLoader.item |
49 | |
50 | // Used for switching from HorizontalFlowListView to ListView, and vice versa. |
51 | Loader { |
52 | @@ -115,7 +96,7 @@ |
53 | width: (memoView.width * 0.5) - (memoView.spacing * 3) |
54 | |
55 | onClicked: { |
56 | - if (multiSelection.active) { |
57 | + if (mainPage.state === "multiSelection") { |
58 | selected = multiSelection.selectUnselectItem(model.index) |
59 | } else { |
60 | /* Workaround: clear the pageStack before pushing memoPage. |
61 | @@ -130,14 +111,14 @@ |
62 | } |
63 | |
64 | onPressAndHold: { |
65 | - if (!multiSelection.active) { |
66 | - multiSelection.active = true |
67 | + if (mainPage.state !== "multiSelection") { |
68 | + mainPage.state = "multiSelection" |
69 | selected = multiSelection.selectUnselectItem(model.index) |
70 | } |
71 | } |
72 | Connections { |
73 | - target: multiSelection |
74 | - onActiveChanged: viewDelegate.selected = false |
75 | + target: mainPage |
76 | + onStateChanged: if (mainPage.state !== "multiSelection") viewDelegate.selected = false |
77 | } |
78 | } |
79 | } |
80 | @@ -149,7 +130,13 @@ |
81 | |
82 | ListView { |
83 | id: memoView |
84 | - anchors { fill: parent; margins: units.gu(2) } |
85 | + anchors { |
86 | + fill: parent |
87 | + margins: units.gu(2) |
88 | + // Fix wrong topMargin when switching to multiSelection state. |
89 | + topMargin: (mainPage.state === "multiSelection") ? (units.gu(2) - mainPage.header.height) |
90 | + : units.gu(2) |
91 | + } |
92 | clip: false |
93 | |
94 | spacing: units.gu(1) |
95 | @@ -160,7 +147,7 @@ |
96 | width: memoView.width |
97 | |
98 | onClicked: { |
99 | - if (multiSelection.active) { |
100 | + if (mainPage.state === "multiSelection") { |
101 | selected = multiSelection.selectUnselectItem(model.index) |
102 | } else { |
103 | /* Workaround: clear the pageStack before pushing memoPage. |
104 | @@ -175,21 +162,21 @@ |
105 | } |
106 | |
107 | onPressAndHold: { |
108 | - if (!multiSelection.active) { |
109 | - multiSelection.active = true |
110 | + if (mainPage.state !== "multiSelection") { |
111 | + mainPage.state = "multiSelection" |
112 | selected = multiSelection.selectUnselectItem(model.index) |
113 | } |
114 | } |
115 | Connections { |
116 | - target: multiSelection |
117 | - onActiveChanged: viewDelegate.selected = false |
118 | + target: mainPage |
119 | + onStateChanged: if (mainPage.state !== "multiSelection") viewDelegate.selected = false |
120 | } |
121 | |
122 | /* According to Qt-Project docs, "delegates are instantiated as needed and may be destroyed at any time". |
123 | We need to restore 'selected' property when this happens. (this issue does not affect FlowListView, |
124 | since Repeater does not destroy delegates). */ |
125 | Component.onCompleted: { |
126 | - if (multiSelection.active) { |
127 | + if (mainPage.state === "multiSelection") { |
128 | for (var i=0; i<multiSelection.indexes.length; i++) { |
129 | if (multiSelection.indexes[i] === index) { |
130 | selected = true |
131 | @@ -201,91 +188,101 @@ |
132 | } |
133 | } |
134 | |
135 | - // Used to manage multi-selection in ListViews |
136 | - MultiSelectionHandler { |
137 | - id: multiSelection |
138 | - |
139 | - target: mainPage |
140 | - title: (multiSelection.count == 1) ? i18n.tr("%1 item selected").arg(multiSelection.count) |
141 | - : i18n.tr("%1 items selected").arg(multiSelection.count) |
142 | - tools: ToolbarItems { |
143 | - back: ToolbarButton { |
144 | - action: Action { |
145 | - text: i18n.tr("Cancel") |
146 | - iconName: "back" |
147 | - onTriggered: multiSelection.active = false |
148 | - } |
149 | - } |
150 | - |
151 | - ToolbarButton { |
152 | - id: colorToolBtn |
153 | - action: Action { |
154 | - text: i18n.tr("Change note color") |
155 | - iconSource: "../img/palette.svg" |
156 | - onTriggered: PopupUtils.open(colorNotePopover, colorToolBtn) |
157 | - } |
158 | - } |
159 | - |
160 | - ToolbarButton { |
161 | - action: Action { |
162 | - id: deleteMemo |
163 | - text: i18n.tr("Delete note") |
164 | - iconName: "delete" |
165 | - onTriggered: { |
166 | - PopupUtils.open(deleteDialog) |
167 | - } |
168 | - } |
169 | - } |
170 | - } |
171 | - |
172 | - onIndexAdded: console.log("Added index:", index) |
173 | - onIndexRemoved: console.log("Index removed:", index) |
174 | - |
175 | - Component { |
176 | - id: colorNotePopover |
177 | - |
178 | - ColorDialog { |
179 | - id: colorDialog |
180 | - showTick: false |
181 | - // A color not listed in 'colors' property, just to avoid that oldColor and selectedColor result the same. |
182 | - // TODO: If there's just a single element selected, we can import the right color of the memo. |
183 | - selectedColor: "#ababab" |
184 | - |
185 | - onColorPicked: { |
186 | - if (isChanged) { |
187 | - for (var i=0; i<multiSelection.indexes.length; i++) { |
188 | - notes.setNoteProperty(multiSelection.indexes[i], "color", selectedColor) |
189 | - } |
190 | - } else { |
191 | - console.log("Color not changed") |
192 | - } |
193 | - |
194 | - multiSelection.active = false |
195 | - PopupUtils.close(colorDialog) |
196 | - } |
197 | - } |
198 | - } |
199 | - |
200 | - Component { |
201 | - id: deleteDialog |
202 | - Dialog { |
203 | - id: deleteDialogue |
204 | - title: i18n.tr("Delete note(s)") |
205 | - text: i18n.tr("Are you sure?") |
206 | - |
207 | - Button { |
208 | - text: i18n.tr("Cancel") |
209 | - gradient: UbuntuColors.greyGradient |
210 | - onClicked: PopupUtils.close(deleteDialogue) |
211 | - } |
212 | - Button { |
213 | - text: i18n.tr("Delete") |
214 | - color: UbuntuColors.orange |
215 | - onClicked: { |
216 | - notes.deleteNotes(multiSelection.indexes) |
217 | - multiSelection.active = false |
218 | - PopupUtils.close(deleteDialogue) |
219 | - } |
220 | + state: "default" |
221 | + states: [ |
222 | + PageHeadState { |
223 | + name: "default" |
224 | + head: mainPage.head |
225 | + actions: [openAbout, switchView] |
226 | + }, |
227 | + |
228 | + // Used to manage multi-selection in ListViews |
229 | + MultiSelectionHandler { |
230 | + id: multiSelection |
231 | + |
232 | + name: "multiSelection" |
233 | + targetPage: mainPage |
234 | + |
235 | + actions: [changeNoteColor, deleteMemo] |
236 | + } |
237 | + ] |
238 | + |
239 | + // DEFAULT PAGEHEAD ACTIONS |
240 | + Action { |
241 | + id: openAbout |
242 | + text: i18n.tr("About...") |
243 | + iconName: "help" |
244 | + onTriggered: pageStack.push(Qt.resolvedUrl("AboutPage.qml")) |
245 | + } |
246 | + |
247 | + Action { |
248 | + id: switchView |
249 | + text: useGridView ? i18n.tr("Switch to one-column list") : i18n.tr("Switch to grid") |
250 | + iconName: useGridView ? "view-list-symbolic" : "view-grid-symbolic" |
251 | + onTriggered: useGridView = !useGridView |
252 | + } |
253 | + |
254 | + // MULTISELECTIONHANDLER ACTIONS |
255 | + Action { |
256 | + id: changeNoteColor |
257 | + text: i18n.tr("Change note color") |
258 | + iconSource: "../img/palette.svg" |
259 | + onTriggered: PopupUtils.open(colorNotePopover) |
260 | + } |
261 | + |
262 | + Action { |
263 | + id: deleteMemo |
264 | + text: i18n.tr("Delete note") |
265 | + iconName: "delete" |
266 | + onTriggered: { |
267 | + PopupUtils.open(deleteDialog) |
268 | + } |
269 | + } |
270 | + |
271 | + Component { |
272 | + id: colorNotePopover |
273 | + |
274 | + ColorDialog { |
275 | + id: colorDialog |
276 | + showTick: false |
277 | + // A color not listed in 'colors' property, just to avoid that oldColor and selectedColor result the same. |
278 | + // TODO: If there's just a single element selected, we can import the right color of the memo. |
279 | + selectedColor: "#ababab" |
280 | + |
281 | + onColorPicked: { |
282 | + if (isChanged) { |
283 | + for (var i=0; i<multiSelection.indexes.length; i++) { |
284 | + notes.setNoteProperty(multiSelection.indexes[i], "color", selectedColor) |
285 | + } |
286 | + } else { |
287 | + console.log("Color not changed") |
288 | + } |
289 | + |
290 | + mainPage.state = "default" |
291 | + PopupUtils.close(colorDialog) |
292 | + } |
293 | + } |
294 | + } |
295 | + |
296 | + Component { |
297 | + id: deleteDialog |
298 | + Dialog { |
299 | + id: deleteDialogue |
300 | + title: i18n.tr("Delete note(s)") |
301 | + text: i18n.tr("Are you sure?") |
302 | + |
303 | + Button { |
304 | + text: i18n.tr("Cancel") |
305 | + gradient: UbuntuColors.greyGradient |
306 | + onClicked: PopupUtils.close(deleteDialogue) |
307 | + } |
308 | + Button { |
309 | + text: i18n.tr("Delete") |
310 | + color: UbuntuColors.orange |
311 | + onClicked: { |
312 | + notes.deleteNotes(multiSelection.indexes) |
313 | + mainPage.state = "default" |
314 | + PopupUtils.close(deleteDialogue) |
315 | } |
316 | } |
317 | } |
318 | @@ -293,4 +290,6 @@ |
319 | |
320 | bottomEdgeTitle: i18n.tr("New memo") |
321 | bottomEdgePageComponent: AddMemo {} |
322 | + // Disable bottomEdge when MultiSelectionHandler is active |
323 | + bottomEdgeEnabled: mainPage.state !== "multiSelection" |
324 | } |
325 | |
326 | === modified file 'components/MemoPage.qml' |
327 | --- components/MemoPage.qml 2014-08-29 03:30:43 +0000 |
328 | +++ components/MemoPage.qml 2014-09-27 18:44:34 +0000 |
329 | @@ -60,17 +60,10 @@ |
330 | } |
331 | |
332 | Action { |
333 | - id: addImage |
334 | - text: i18n.tr("Add image") |
335 | - iconName: "insert-image" |
336 | - onTriggered: picsView.importImageFromContentHub() |
337 | - } |
338 | - |
339 | - Action { |
340 | id: colorToolAction |
341 | text: i18n.tr("Change note color") |
342 | iconSource: "../img/palette.svg" |
343 | - onTriggered: PopupUtils.open(colorNotePopover, colorToolBtn) |
344 | + onTriggered: PopupUtils.open(colorNotePopover) |
345 | } |
346 | Component { |
347 | id: colorNotePopover |
348 | @@ -89,32 +82,26 @@ |
349 | } |
350 | } |
351 | |
352 | - tools: ToolbarItems { |
353 | - back: ToolbarButton { |
354 | - action: Action { |
355 | - iconName: "back" |
356 | - onTriggered: { |
357 | - // Check if a saveNote request was made. If so, stop the timer and save before exiting the page. |
358 | - if (autoSaveTimer.running) { |
359 | - console.log("It's ok. Saving the note before closing the page...") |
360 | - autoSaveTimer.running = false |
361 | - saveNote() |
362 | - } |
363 | - |
364 | - pageStack.pop() |
365 | - |
366 | - /* Workaround: see MainPage.qml, comment for mainView.delegate.onClicked(). |
367 | + head.backAction: Action { |
368 | + iconName: "back" |
369 | + onTriggered: { |
370 | + // Check if a saveNote request was made. If so, stop the timer and save before exiting the page. |
371 | + if (autoSaveTimer.running) { |
372 | + console.log("It's ok. Saving the note before closing the page...") |
373 | + autoSaveTimer.running = false |
374 | + saveNote() |
375 | + } |
376 | + |
377 | + pageStack.pop() |
378 | + |
379 | + /* Workaround: see MainPage.qml, comment for mainView.delegate.onClicked(). |
380 | We simply re-push in the stack what we removed earlier.*/ |
381 | - pageStack.push(mainPage) |
382 | - } |
383 | - } |
384 | + pageStack.push(mainPage) |
385 | } |
386 | - |
387 | - ToolbarButton { id: colorToolBtn; action: colorToolAction } |
388 | - ToolbarButton { action: addImage } |
389 | - ToolbarButton { action: deleteMemo } |
390 | } |
391 | |
392 | + head.actions: [colorToolAction, deleteMemo] |
393 | + |
394 | // Background |
395 | Rectangle { |
396 | id: bg |
397 | |
398 | === modified file 'components/MultiSelectionHandler.qml' |
399 | --- components/MultiSelectionHandler.qml 2014-08-31 22:11:24 +0000 |
400 | +++ components/MultiSelectionHandler.qml 2014-09-27 18:44:34 +0000 |
401 | @@ -18,58 +18,55 @@ |
402 | import QtQuick 2.0 |
403 | import Ubuntu.Components 1.1 |
404 | |
405 | -Item { |
406 | +PageHeadState { |
407 | id: rootItem |
408 | |
409 | - property bool active: false |
410 | - |
411 | - property Page target |
412 | - property ToolbarItems tools |
413 | property string title |
414 | |
415 | property var indexes: [] |
416 | property int count: rootItem.indexes.length |
417 | - |
418 | - QtObject { |
419 | - id: d |
420 | - property ToolbarItems tools |
421 | - property string title |
422 | - } |
423 | - |
424 | - // Provide a visual feedback when active |
425 | - Rectangle { |
426 | - id: headerBg |
427 | - parent: target.header |
428 | - z: -10 |
429 | - |
430 | - width: target.width |
431 | - height: target.header.height |
432 | - color: "#19B6EE" // Cyan |
433 | - visible: rootItem.active |
434 | - } |
435 | - |
436 | - onActiveChanged: { |
437 | - if(active) { |
438 | - // Copy current toolbar and title |
439 | - d.tools = target.tools |
440 | - d.title = target.title |
441 | - |
442 | - // Show new header |
443 | - target.tools = rootItem.tools |
444 | - target.title = rootItem.title |
445 | - |
446 | - } else { |
447 | - target.tools = d.tools |
448 | - target.title = d.title |
449 | - |
450 | - // Clean the model |
451 | - rootItem.indexes = [] |
452 | - } |
453 | - } |
454 | - |
455 | - Connections { |
456 | - target: rootItem.target |
457 | - onActiveChanged: rootItem.active = false |
458 | + property Page targetPage |
459 | + |
460 | + head: targetPage.head |
461 | + |
462 | + backAction: Action { |
463 | + text: i18n.tr("Cancel") |
464 | + iconName: "back" |
465 | + onTriggered: targetPage.state = "default" |
466 | + } |
467 | + |
468 | + contents: Item { |
469 | + anchors.fill: parent |
470 | + |
471 | + Connections { |
472 | + target: targetPage |
473 | + onStateChanged: { |
474 | + if (targetPage.state !== "multiSelection") { |
475 | + // Clean the model |
476 | + rootItem.indexes = [] |
477 | + } |
478 | + } |
479 | + } |
480 | + |
481 | + Label { |
482 | + fontSize: "x-large" |
483 | + text: (rootItem.count == 0) ? i18n.tr("No item selected") |
484 | + : (rootItem.count == 1) ? i18n.tr("%1 item selected").arg(rootItem.count) |
485 | + : i18n.tr("%1 items selected").arg(rootItem.count) |
486 | + anchors.verticalCenter: parent.verticalCenter |
487 | + } |
488 | + |
489 | + // Provide a visual feedback when active |
490 | + Rectangle { |
491 | + id: headerBg |
492 | + parent: targetPage.header |
493 | + z: -10 |
494 | + |
495 | + width: targetPage.width |
496 | + height: targetPage.header.height |
497 | + color: "#19B6EE" // Cyan |
498 | + visible: mainPage.state == "multiSelection" |
499 | + } |
500 | } |
501 | |
502 | signal indexAdded(var index) |
503 | @@ -84,8 +81,6 @@ |
504 | |
505 | // Update count and header |
506 | rootItem.count = rootItem.indexes.length |
507 | - target.tools = rootItem.tools |
508 | - target.title = rootItem.title |
509 | |
510 | // Return false if the index is removed. |
511 | rootItem.indexRemoved(index) |
512 | @@ -98,13 +93,10 @@ |
513 | |
514 | // Update count |
515 | rootItem.count = rootItem.indexes.length |
516 | - target.tools = rootItem.tools |
517 | - target.title = rootItem.title |
518 | |
519 | // Sort indexes, so they're processed ascending if requested. This simplify the code of the functions that use this array. |
520 | indexes.sort(function(a,b) {return a-b}) |
521 | |
522 | - |
523 | // Return true if the index is added |
524 | rootItem.indexAdded(index) |
525 | return true |