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
=== modified file 'components/AddMemo.qml'
--- components/AddMemo.qml 2014-08-29 03:30:43 +0000
+++ components/AddMemo.qml 2014-09-27 18:44:34 +0000
@@ -70,10 +70,7 @@
70 onTriggered: colorDialog.show()70 onTriggered: colorDialog.show()
71 }71 }
7272
73 tools: ToolbarItems {73 head.actions: [colorToolAction, saveMemo]
74 ToolbarButton { action: colorToolAction }
75 ToolbarButton { action: saveMemo }
76 }
7774
78 // Background75 // Background
79 Rectangle {76 Rectangle {
8077
=== modified file 'components/MainPage.qml'
--- components/MainPage.qml 2014-09-04 15:12:38 +0000
+++ components/MainPage.qml 2014-09-27 18:44:34 +0000
@@ -23,28 +23,9 @@
23PageWithBottomEdge {23PageWithBottomEdge {
24 id: mainPage24 id: mainPage
25 title: i18n.tr("Overview")25 title: i18n.tr("Overview")
26 flickable: useGridView ? null : viewLoader.item26 flickable: mainPage.state === "multiSelection" ? null
2727 : useGridView ? null
28 // TODO: Switch to PageHeads. Do it also for MultiSelectionHandler28 : viewLoader.item
29
30 Action {
31 id: openAbout
32 text: i18n.tr("About...")
33 iconName: "help"
34 onTriggered: pageStack.push(Qt.resolvedUrl("AboutPage.qml"))
35 }
36
37 Action {
38 id: switchView
39 text: useGridView ? i18n.tr("Switch to one-column list") : i18n.tr("Switch to grid")
40 iconName: useGridView ? "view-list-symbolic" : "view-grid-symbolic"
41 onTriggered: useGridView = !useGridView
42 }
43
44 tools: ToolbarItems {
45 ToolbarButton { action: openAbout }
46 ToolbarButton { action: switchView }
47 }
4829
49 // Used for switching from HorizontalFlowListView to ListView, and vice versa.30 // Used for switching from HorizontalFlowListView to ListView, and vice versa.
50 Loader {31 Loader {
@@ -115,7 +96,7 @@
115 width: (memoView.width * 0.5) - (memoView.spacing * 3)96 width: (memoView.width * 0.5) - (memoView.spacing * 3)
11697
117 onClicked: {98 onClicked: {
118 if (multiSelection.active) {99 if (mainPage.state === "multiSelection") {
119 selected = multiSelection.selectUnselectItem(model.index)100 selected = multiSelection.selectUnselectItem(model.index)
120 } else {101 } else {
121 /* Workaround: clear the pageStack before pushing memoPage.102 /* Workaround: clear the pageStack before pushing memoPage.
@@ -130,14 +111,14 @@
130 }111 }
131112
132 onPressAndHold: {113 onPressAndHold: {
133 if (!multiSelection.active) {114 if (mainPage.state !== "multiSelection") {
134 multiSelection.active = true115 mainPage.state = "multiSelection"
135 selected = multiSelection.selectUnselectItem(model.index)116 selected = multiSelection.selectUnselectItem(model.index)
136 }117 }
137 }118 }
138 Connections {119 Connections {
139 target: multiSelection120 target: mainPage
140 onActiveChanged: viewDelegate.selected = false121 onStateChanged: if (mainPage.state !== "multiSelection") viewDelegate.selected = false
141 }122 }
142 }123 }
143 }124 }
@@ -149,7 +130,13 @@
149130
150 ListView {131 ListView {
151 id: memoView132 id: memoView
152 anchors { fill: parent; margins: units.gu(2) }133 anchors {
134 fill: parent
135 margins: units.gu(2)
136 // Fix wrong topMargin when switching to multiSelection state.
137 topMargin: (mainPage.state === "multiSelection") ? (units.gu(2) - mainPage.header.height)
138 : units.gu(2)
139 }
153 clip: false140 clip: false
154141
155 spacing: units.gu(1)142 spacing: units.gu(1)
@@ -160,7 +147,7 @@
160 width: memoView.width147 width: memoView.width
161148
162 onClicked: {149 onClicked: {
163 if (multiSelection.active) {150 if (mainPage.state === "multiSelection") {
164 selected = multiSelection.selectUnselectItem(model.index)151 selected = multiSelection.selectUnselectItem(model.index)
165 } else {152 } else {
166 /* Workaround: clear the pageStack before pushing memoPage.153 /* Workaround: clear the pageStack before pushing memoPage.
@@ -175,21 +162,21 @@
175 }162 }
176163
177 onPressAndHold: {164 onPressAndHold: {
178 if (!multiSelection.active) {165 if (mainPage.state !== "multiSelection") {
179 multiSelection.active = true166 mainPage.state = "multiSelection"
180 selected = multiSelection.selectUnselectItem(model.index)167 selected = multiSelection.selectUnselectItem(model.index)
181 }168 }
182 }169 }
183 Connections {170 Connections {
184 target: multiSelection171 target: mainPage
185 onActiveChanged: viewDelegate.selected = false172 onStateChanged: if (mainPage.state !== "multiSelection") viewDelegate.selected = false
186 }173 }
187174
188 /* According to Qt-Project docs, "delegates are instantiated as needed and may be destroyed at any time".175 /* According to Qt-Project docs, "delegates are instantiated as needed and may be destroyed at any time".
189 We need to restore 'selected' property when this happens. (this issue does not affect FlowListView,176 We need to restore 'selected' property when this happens. (this issue does not affect FlowListView,
190 since Repeater does not destroy delegates). */177 since Repeater does not destroy delegates). */
191 Component.onCompleted: {178 Component.onCompleted: {
192 if (multiSelection.active) {179 if (mainPage.state === "multiSelection") {
193 for (var i=0; i<multiSelection.indexes.length; i++) {180 for (var i=0; i<multiSelection.indexes.length; i++) {
194 if (multiSelection.indexes[i] === index) {181 if (multiSelection.indexes[i] === index) {
195 selected = true182 selected = true
@@ -201,91 +188,101 @@
201 }188 }
202 }189 }
203190
204 // Used to manage multi-selection in ListViews191 state: "default"
205 MultiSelectionHandler {192 states: [
206 id: multiSelection193 PageHeadState {
207194 name: "default"
208 target: mainPage195 head: mainPage.head
209 title: (multiSelection.count == 1) ? i18n.tr("%1 item selected").arg(multiSelection.count)196 actions: [openAbout, switchView]
210 : i18n.tr("%1 items selected").arg(multiSelection.count)197 },
211 tools: ToolbarItems {198
212 back: ToolbarButton {199 // Used to manage multi-selection in ListViews
213 action: Action {200 MultiSelectionHandler {
214 text: i18n.tr("Cancel")201 id: multiSelection
215 iconName: "back"202
216 onTriggered: multiSelection.active = false203 name: "multiSelection"
217 }204 targetPage: mainPage
218 }205
219206 actions: [changeNoteColor, deleteMemo]
220 ToolbarButton {207 }
221 id: colorToolBtn208 ]
222 action: Action {209
223 text: i18n.tr("Change note color")210 // DEFAULT PAGEHEAD ACTIONS
224 iconSource: "../img/palette.svg"211 Action {
225 onTriggered: PopupUtils.open(colorNotePopover, colorToolBtn)212 id: openAbout
226 }213 text: i18n.tr("About...")
227 }214 iconName: "help"
228215 onTriggered: pageStack.push(Qt.resolvedUrl("AboutPage.qml"))
229 ToolbarButton {216 }
230 action: Action {217
231 id: deleteMemo218 Action {
232 text: i18n.tr("Delete note")219 id: switchView
233 iconName: "delete"220 text: useGridView ? i18n.tr("Switch to one-column list") : i18n.tr("Switch to grid")
234 onTriggered: {221 iconName: useGridView ? "view-list-symbolic" : "view-grid-symbolic"
235 PopupUtils.open(deleteDialog)222 onTriggered: useGridView = !useGridView
236 }223 }
237 }224
238 }225 // MULTISELECTIONHANDLER ACTIONS
239 }226 Action {
240227 id: changeNoteColor
241 onIndexAdded: console.log("Added index:", index)228 text: i18n.tr("Change note color")
242 onIndexRemoved: console.log("Index removed:", index)229 iconSource: "../img/palette.svg"
243230 onTriggered: PopupUtils.open(colorNotePopover)
244 Component {231 }
245 id: colorNotePopover232
246233 Action {
247 ColorDialog {234 id: deleteMemo
248 id: colorDialog235 text: i18n.tr("Delete note")
249 showTick: false236 iconName: "delete"
250 // A color not listed in 'colors' property, just to avoid that oldColor and selectedColor result the same.237 onTriggered: {
251 // TODO: If there's just a single element selected, we can import the right color of the memo.238 PopupUtils.open(deleteDialog)
252 selectedColor: "#ababab"239 }
253240 }
254 onColorPicked: {241
255 if (isChanged) {242 Component {
256 for (var i=0; i<multiSelection.indexes.length; i++) {243 id: colorNotePopover
257 notes.setNoteProperty(multiSelection.indexes[i], "color", selectedColor)244
258 }245 ColorDialog {
259 } else {246 id: colorDialog
260 console.log("Color not changed")247 showTick: false
261 }248 // A color not listed in 'colors' property, just to avoid that oldColor and selectedColor result the same.
262249 // TODO: If there's just a single element selected, we can import the right color of the memo.
263 multiSelection.active = false250 selectedColor: "#ababab"
264 PopupUtils.close(colorDialog)251
265 }252 onColorPicked: {
266 }253 if (isChanged) {
267 }254 for (var i=0; i<multiSelection.indexes.length; i++) {
268255 notes.setNoteProperty(multiSelection.indexes[i], "color", selectedColor)
269 Component {256 }
270 id: deleteDialog257 } else {
271 Dialog {258 console.log("Color not changed")
272 id: deleteDialogue259 }
273 title: i18n.tr("Delete note(s)")260
274 text: i18n.tr("Are you sure?")261 mainPage.state = "default"
275262 PopupUtils.close(colorDialog)
276 Button {263 }
277 text: i18n.tr("Cancel")264 }
278 gradient: UbuntuColors.greyGradient265 }
279 onClicked: PopupUtils.close(deleteDialogue)266
280 }267 Component {
281 Button {268 id: deleteDialog
282 text: i18n.tr("Delete")269 Dialog {
283 color: UbuntuColors.orange270 id: deleteDialogue
284 onClicked: {271 title: i18n.tr("Delete note(s)")
285 notes.deleteNotes(multiSelection.indexes)272 text: i18n.tr("Are you sure?")
286 multiSelection.active = false273
287 PopupUtils.close(deleteDialogue)274 Button {
288 }275 text: i18n.tr("Cancel")
276 gradient: UbuntuColors.greyGradient
277 onClicked: PopupUtils.close(deleteDialogue)
278 }
279 Button {
280 text: i18n.tr("Delete")
281 color: UbuntuColors.orange
282 onClicked: {
283 notes.deleteNotes(multiSelection.indexes)
284 mainPage.state = "default"
285 PopupUtils.close(deleteDialogue)
289 }286 }
290 }287 }
291 }288 }
@@ -293,4 +290,6 @@
293290
294 bottomEdgeTitle: i18n.tr("New memo")291 bottomEdgeTitle: i18n.tr("New memo")
295 bottomEdgePageComponent: AddMemo {}292 bottomEdgePageComponent: AddMemo {}
293 // Disable bottomEdge when MultiSelectionHandler is active
294 bottomEdgeEnabled: mainPage.state !== "multiSelection"
296}295}
297296
=== modified file 'components/MemoPage.qml'
--- components/MemoPage.qml 2014-08-29 03:30:43 +0000
+++ components/MemoPage.qml 2014-09-27 18:44:34 +0000
@@ -60,17 +60,10 @@
60 }60 }
6161
62 Action {62 Action {
63 id: addImage
64 text: i18n.tr("Add image")
65 iconName: "insert-image"
66 onTriggered: picsView.importImageFromContentHub()
67 }
68
69 Action {
70 id: colorToolAction63 id: colorToolAction
71 text: i18n.tr("Change note color")64 text: i18n.tr("Change note color")
72 iconSource: "../img/palette.svg"65 iconSource: "../img/palette.svg"
73 onTriggered: PopupUtils.open(colorNotePopover, colorToolBtn)66 onTriggered: PopupUtils.open(colorNotePopover)
74 }67 }
75 Component {68 Component {
76 id: colorNotePopover69 id: colorNotePopover
@@ -89,32 +82,26 @@
89 }82 }
90 }83 }
9184
92 tools: ToolbarItems {85 head.backAction: Action {
93 back: ToolbarButton {86 iconName: "back"
94 action: Action {87 onTriggered: {
95 iconName: "back"88 // Check if a saveNote request was made. If so, stop the timer and save before exiting the page.
96 onTriggered: {89 if (autoSaveTimer.running) {
97 // Check if a saveNote request was made. If so, stop the timer and save before exiting the page.90 console.log("It's ok. Saving the note before closing the page...")
98 if (autoSaveTimer.running) {91 autoSaveTimer.running = false
99 console.log("It's ok. Saving the note before closing the page...")92 saveNote()
100 autoSaveTimer.running = false93 }
101 saveNote()94
102 }95 pageStack.pop()
10396
104 pageStack.pop()97 /* Workaround: see MainPage.qml, comment for mainView.delegate.onClicked().
105
106 /* Workaround: see MainPage.qml, comment for mainView.delegate.onClicked().
107 We simply re-push in the stack what we removed earlier.*/98 We simply re-push in the stack what we removed earlier.*/
108 pageStack.push(mainPage)99 pageStack.push(mainPage)
109 }
110 }
111 }100 }
112
113 ToolbarButton { id: colorToolBtn; action: colorToolAction }
114 ToolbarButton { action: addImage }
115 ToolbarButton { action: deleteMemo }
116 }101 }
117102
103 head.actions: [colorToolAction, deleteMemo]
104
118 // Background105 // Background
119 Rectangle {106 Rectangle {
120 id: bg107 id: bg
121108
=== modified file 'components/MultiSelectionHandler.qml'
--- components/MultiSelectionHandler.qml 2014-08-31 22:11:24 +0000
+++ components/MultiSelectionHandler.qml 2014-09-27 18:44:34 +0000
@@ -18,58 +18,55 @@
18import QtQuick 2.018import QtQuick 2.0
19import Ubuntu.Components 1.119import Ubuntu.Components 1.1
2020
21Item {21PageHeadState {
22 id: rootItem22 id: rootItem
2323
24 property bool active: false
25
26 property Page target
27 property ToolbarItems tools
28 property string title24 property string title
2925
30 property var indexes: []26 property var indexes: []
31 property int count: rootItem.indexes.length27 property int count: rootItem.indexes.length
3228 property Page targetPage
33 QtObject {29
34 id: d30 head: targetPage.head
35 property ToolbarItems tools31
36 property string title32 backAction: Action {
37 }33 text: i18n.tr("Cancel")
3834 iconName: "back"
39 // Provide a visual feedback when active35 onTriggered: targetPage.state = "default"
40 Rectangle {36 }
41 id: headerBg37
42 parent: target.header38 contents: Item {
43 z: -1039 anchors.fill: parent
4440
45 width: target.width41 Connections {
46 height: target.header.height42 target: targetPage
47 color: "#19B6EE" // Cyan43 onStateChanged: {
48 visible: rootItem.active44 if (targetPage.state !== "multiSelection") {
49 }45 // Clean the model
5046 rootItem.indexes = []
51 onActiveChanged: {47 }
52 if(active) {48 }
53 // Copy current toolbar and title49 }
54 d.tools = target.tools50
55 d.title = target.title51 Label {
5652 fontSize: "x-large"
57 // Show new header53 text: (rootItem.count == 0) ? i18n.tr("No item selected")
58 target.tools = rootItem.tools54 : (rootItem.count == 1) ? i18n.tr("%1 item selected").arg(rootItem.count)
59 target.title = rootItem.title55 : i18n.tr("%1 items selected").arg(rootItem.count)
6056 anchors.verticalCenter: parent.verticalCenter
61 } else {57 }
62 target.tools = d.tools58
63 target.title = d.title59 // Provide a visual feedback when active
6460 Rectangle {
65 // Clean the model61 id: headerBg
66 rootItem.indexes = []62 parent: targetPage.header
67 }63 z: -10
68 }64
6965 width: targetPage.width
70 Connections {66 height: targetPage.header.height
71 target: rootItem.target67 color: "#19B6EE" // Cyan
72 onActiveChanged: rootItem.active = false68 visible: mainPage.state == "multiSelection"
69 }
73 }70 }
7471
75 signal indexAdded(var index)72 signal indexAdded(var index)
@@ -84,8 +81,6 @@
8481
85 // Update count and header82 // Update count and header
86 rootItem.count = rootItem.indexes.length83 rootItem.count = rootItem.indexes.length
87 target.tools = rootItem.tools
88 target.title = rootItem.title
8984
90 // Return false if the index is removed.85 // Return false if the index is removed.
91 rootItem.indexRemoved(index)86 rootItem.indexRemoved(index)
@@ -98,13 +93,10 @@
9893
99 // Update count94 // Update count
100 rootItem.count = rootItem.indexes.length95 rootItem.count = rootItem.indexes.length
101 target.tools = rootItem.tools
102 target.title = rootItem.title
10396
104 // Sort indexes, so they're processed ascending if requested. This simplify the code of the functions that use this array.97 // Sort indexes, so they're processed ascending if requested. This simplify the code of the functions that use this array.
105 indexes.sort(function(a,b) {return a-b})98 indexes.sort(function(a,b) {return a-b})
10699
107
108 // Return true if the index is added100 // Return true if the index is added
109 rootItem.indexAdded(index)101 rootItem.indexAdded(index)
110 return true102 return true

Subscribers

People subscribed via source and target branches

to all changes: