Merge lp:~verzegnassi-stefano/quick-memo/fix-1360869-1366076 into lp:quick-memo/trunk

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
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

PageHeadConfiguration is used to provided MultiSelection. (#1360869)
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

Subscribers

People subscribed via source and target branches

to all changes: