Merge lp:~artmello/camera-app/camera-app-gridlines into lp:camera-app
- camera-app-gridlines
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~artmello/camera-app/camera-app-gridlines |
Merge into: | lp:camera-app |
Diff against target: |
273 lines (+98/-19) 4 files modified
OptionValueButton.qml (+3/-2) OptionsOverlay.qml (+15/-10) ViewFinderOverlay.qml (+53/-5) ViewFinderView.qml (+27/-2) |
To merge this branch: | bzr merge lp:~artmello/camera-app/camera-app-gridlines |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Florian Boucault (community) | Needs Fixing | ||
Review via email: mp+243092@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-12-02.
Commit message
Add gridlines to the viewfinder controlled by a new settings option
Description of the change
Add gridlines to the viewfinder controlled by a new settings option
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:427
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
ABORTED: http://
UNSTABLE: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 428. By Arthur Mello
-
Merged bottom edge UI fixes from lp:~fboucault/camera-app/sdcard
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:428
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Unmerged revisions
Preview Diff
1 | === modified file 'OptionValueButton.qml' | |||
2 | --- OptionValueButton.qml 2014-07-09 21:57:43 +0000 | |||
3 | +++ OptionValueButton.qml 2014-12-01 01:56:45 +0000 | |||
4 | @@ -47,14 +47,15 @@ | |||
5 | 47 | id: label | 47 | id: label |
6 | 48 | anchors { | 48 | anchors { |
7 | 49 | left: icon.name != "" ? icon.right : parent.left | 49 | left: icon.name != "" ? icon.right : parent.left |
9 | 50 | leftMargin: units.gu(2) | 50 | leftMargin: icon.name != "" ? units.gu(2) : icon.anchors.leftMargin |
10 | 51 | right: parent.right | 51 | right: parent.right |
12 | 52 | rightMargin: units.gu(2) | 52 | rightMargin: icon.anchors.leftMargin |
13 | 53 | verticalCenter: parent.verticalCenter | 53 | verticalCenter: parent.verticalCenter |
14 | 54 | } | 54 | } |
15 | 55 | 55 | ||
16 | 56 | color: "white" | 56 | color: "white" |
17 | 57 | opacity: optionValueButton.selected ? 1.0 : 0.5 | 57 | opacity: optionValueButton.selected ? 1.0 : 0.5 |
18 | 58 | elide: Text.ElideRight | ||
19 | 58 | } | 59 | } |
20 | 59 | 60 | ||
21 | 60 | Rectangle { | 61 | Rectangle { |
22 | 61 | 62 | ||
23 | === modified file 'OptionsOverlay.qml' | |||
24 | --- OptionsOverlay.qml 2014-09-05 12:04:54 +0000 | |||
25 | +++ OptionsOverlay.qml 2014-12-01 01:56:45 +0000 | |||
26 | @@ -21,12 +21,13 @@ | |||
27 | 21 | id: optionsOverlay | 21 | id: optionsOverlay |
28 | 22 | 22 | ||
29 | 23 | property list<ListModel> options | 23 | property list<ListModel> options |
30 | 24 | property bool valueSelectorOpened: optionValueSelector.caller != null | ||
31 | 24 | 25 | ||
32 | 25 | function closeValueSelector() { | 26 | function closeValueSelector() { |
33 | 26 | optionValueSelector.hide(); | 27 | optionValueSelector.hide(); |
34 | 27 | } | 28 | } |
35 | 28 | 29 | ||
37 | 29 | height: optionsGrid.height | 30 | height: optionsGrid.height + optionsGrid.rowSpacing |
38 | 30 | 31 | ||
39 | 31 | Grid { | 32 | Grid { |
40 | 32 | id: optionsGrid | 33 | id: optionsGrid |
41 | @@ -34,9 +35,7 @@ | |||
42 | 34 | horizontalCenter: parent.horizontalCenter | 35 | horizontalCenter: parent.horizontalCenter |
43 | 35 | } | 36 | } |
44 | 36 | 37 | ||
48 | 37 | columns: 3 | 38 | rowSpacing: units.gu(4) |
46 | 38 | columnSpacing: units.gu(9.5) | ||
47 | 39 | rowSpacing: units.gu(9.5) | ||
49 | 40 | 39 | ||
50 | 41 | Repeater { | 40 | Repeater { |
51 | 42 | model: optionsOverlay.options | 41 | model: optionsOverlay.options |
52 | @@ -44,6 +43,9 @@ | |||
53 | 44 | id: optionButton | 43 | id: optionButton |
54 | 45 | model: modelData | 44 | model: modelData |
55 | 46 | onClicked: optionValueSelector.toggle(model, optionButton) | 45 | onClicked: optionValueSelector.toggle(model, optionButton) |
56 | 46 | enabled: model.available && (!optionValueSelector.caller || optionValueSelector.caller == optionButton) | ||
57 | 47 | opacity: enabled ? 1.0 : 0.05 | ||
58 | 48 | Behavior on opacity {UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration}} | ||
59 | 47 | } | 49 | } |
60 | 48 | } | 50 | } |
61 | 49 | } | 51 | } |
62 | @@ -51,11 +53,9 @@ | |||
63 | 51 | Column { | 53 | Column { |
64 | 52 | id: optionValueSelector | 54 | id: optionValueSelector |
65 | 53 | objectName: "optionValueSelector" | 55 | objectName: "optionValueSelector" |
71 | 54 | anchors { | 56 | width: units.gu(16) |
72 | 55 | bottom: optionsGrid.top | 57 | |
73 | 56 | bottomMargin: units.gu(2) | 58 | property OptionButton caller |
69 | 57 | } | ||
70 | 58 | width: units.gu(12) | ||
74 | 59 | 59 | ||
75 | 60 | function toggle(model, callerButton) { | 60 | function toggle(model, callerButton) { |
76 | 61 | if (optionValueSelectorVisible && optionsRepeater.model === model) { | 61 | if (optionValueSelectorVisible && optionsRepeater.model === model) { |
77 | @@ -66,13 +66,15 @@ | |||
78 | 66 | } | 66 | } |
79 | 67 | 67 | ||
80 | 68 | function show(model, callerButton) { | 68 | function show(model, callerButton) { |
81 | 69 | optionValueSelector.caller = callerButton; | ||
82 | 70 | optionsRepeater.model = model; | ||
83 | 69 | alignWith(callerButton); | 71 | alignWith(callerButton); |
84 | 70 | optionsRepeater.model = model; | ||
85 | 71 | optionValueSelectorVisible = true; | 72 | optionValueSelectorVisible = true; |
86 | 72 | } | 73 | } |
87 | 73 | 74 | ||
88 | 74 | function hide() { | 75 | function hide() { |
89 | 75 | optionValueSelectorVisible = false; | 76 | optionValueSelectorVisible = false; |
90 | 77 | optionValueSelector.caller = null; | ||
91 | 76 | } | 78 | } |
92 | 77 | 79 | ||
93 | 78 | function alignWith(item) { | 80 | function alignWith(item) { |
94 | @@ -90,6 +92,9 @@ | |||
95 | 90 | } else { | 92 | } else { |
96 | 91 | x = centeredX; | 93 | x = centeredX; |
97 | 92 | } | 94 | } |
98 | 95 | |||
99 | 96 | // vertically position the options above the caller button | ||
100 | 97 | y = Qt.binding(function() { return optionsGrid.y + item.y - height - units.gu(2) }); | ||
101 | 93 | } | 98 | } |
102 | 94 | 99 | ||
103 | 95 | visible: opacity !== 0.0 | 100 | visible: opacity !== 0.0 |
104 | 96 | 101 | ||
105 | === modified file 'ViewFinderOverlay.qml' | |||
106 | --- ViewFinderOverlay.qml 2014-09-05 12:04:54 +0000 | |||
107 | +++ ViewFinderOverlay.qml 2014-12-01 01:56:45 +0000 | |||
108 | @@ -20,6 +20,7 @@ | |||
109 | 20 | import QtMultimedia 5.0 | 20 | import QtMultimedia 5.0 |
110 | 21 | import QtPositioning 5.2 | 21 | import QtPositioning 5.2 |
111 | 22 | import CameraApp 0.1 | 22 | import CameraApp 0.1 |
112 | 23 | import Qt.labs.settings 1.0 | ||
113 | 23 | 24 | ||
114 | 24 | Item { | 25 | Item { |
115 | 25 | id: viewFinderOverlay | 26 | id: viewFinderOverlay |
116 | @@ -34,15 +35,15 @@ | |||
117 | 34 | focusRing.show(); | 35 | focusRing.show(); |
118 | 35 | } | 36 | } |
119 | 36 | 37 | ||
121 | 37 | QtObject { | 38 | Settings { |
122 | 38 | id: settings | 39 | id: settings |
123 | 39 | 40 | ||
124 | 40 | property int flashMode: Camera.FlashAuto | 41 | property int flashMode: Camera.FlashAuto |
125 | 41 | property bool gpsEnabled: false | 42 | property bool gpsEnabled: false |
126 | 42 | property bool hdrEnabled: false | 43 | property bool hdrEnabled: false |
127 | 43 | property int videoFlashMode: Camera.FlashOff | 44 | property int videoFlashMode: Camera.FlashOff |
130 | 44 | 45 | property bool gridEnabled: false | |
131 | 45 | StateSaver.properties: "flashMode, gpsEnabled, hdrEnabled, videoFlashMode" | 46 | property int encodingQuality: 2 // QMultimedia.NormalQuality |
132 | 46 | } | 47 | } |
133 | 47 | 48 | ||
134 | 48 | Binding { | 49 | Binding { |
135 | @@ -65,6 +66,12 @@ | |||
136 | 65 | value: settings.hdrEnabled | 66 | value: settings.hdrEnabled |
137 | 66 | } | 67 | } |
138 | 67 | 68 | ||
139 | 69 | Binding { | ||
140 | 70 | target: gridlines | ||
141 | 71 | property: "visible" | ||
142 | 72 | value: settings.gridEnabled | ||
143 | 73 | } | ||
144 | 74 | |||
145 | 68 | Connections { | 75 | Connections { |
146 | 69 | target: camera.imageCapture | 76 | target: camera.imageCapture |
147 | 70 | onReadyChanged: { | 77 | onReadyChanged: { |
148 | @@ -77,10 +84,19 @@ | |||
149 | 77 | } | 84 | } |
150 | 78 | } | 85 | } |
151 | 79 | 86 | ||
152 | 87 | function optionsOverlayClose() { | ||
153 | 88 | print("optionsOverlayClose") | ||
154 | 89 | if (optionsOverlayLoader.item.valueSelectorOpened) { | ||
155 | 90 | optionsOverlayLoader.item.closeValueSelector(); | ||
156 | 91 | } else { | ||
157 | 92 | bottomEdge.close(); | ||
158 | 93 | } | ||
159 | 94 | } | ||
160 | 95 | |||
161 | 80 | MouseArea { | 96 | MouseArea { |
162 | 81 | id: bottomEdgeClose | 97 | id: bottomEdgeClose |
163 | 82 | anchors.fill: parent | 98 | anchors.fill: parent |
165 | 83 | onClicked: bottomEdge.close() | 99 | onClicked: optionsOverlayClose() |
166 | 84 | } | 100 | } |
167 | 85 | 101 | ||
168 | 86 | Panel { | 102 | Panel { |
169 | @@ -90,9 +106,19 @@ | |||
170 | 90 | left: parent.left | 106 | left: parent.left |
171 | 91 | bottom: parent.bottom | 107 | bottom: parent.bottom |
172 | 92 | } | 108 | } |
174 | 93 | height: units.gu(9) | 109 | height: optionsOverlayLoader.height |
175 | 94 | onOpenedChanged: optionsOverlayLoader.item.closeValueSelector() | 110 | onOpenedChanged: optionsOverlayLoader.item.closeValueSelector() |
176 | 95 | 111 | ||
177 | 112 | Item { | ||
178 | 113 | /* Use the 'trigger' feature of Panel so that tapping on the Panel | ||
179 | 114 | has the same effect as tapping outside of it (bottomEdgeClose) */ | ||
180 | 115 | id: clickReceiver | ||
181 | 116 | anchors.fill: parent | ||
182 | 117 | function trigger() { | ||
183 | 118 | optionsOverlayClose(); | ||
184 | 119 | } | ||
185 | 120 | } | ||
186 | 121 | |||
187 | 96 | property real progress: (bottomEdge.height - bottomEdge.position) / bottomEdge.height | 122 | property real progress: (bottomEdge.height - bottomEdge.position) / bottomEdge.height |
188 | 97 | property list<ListModel> options: [ | 123 | property list<ListModel> options: [ |
189 | 98 | ListModel { | 124 | ListModel { |
190 | @@ -187,6 +213,28 @@ | |||
191 | 187 | label: QT_TR_NOOP("Off") | 213 | label: QT_TR_NOOP("Off") |
192 | 188 | value: false | 214 | value: false |
193 | 189 | } | 215 | } |
194 | 216 | }, | ||
195 | 217 | ListModel { | ||
196 | 218 | id: gridOptionsModel | ||
197 | 219 | |||
198 | 220 | property string settingsProperty: "gridEnabled" | ||
199 | 221 | property string icon: "view-grid-symbolic" | ||
200 | 222 | property string label: "" | ||
201 | 223 | property bool isToggle: true | ||
202 | 224 | property int selectedIndex: bottomEdge.indexForValue(gridOptionsModel, settings.gridEnabled) | ||
203 | 225 | property bool available: true | ||
204 | 226 | property bool visible: true | ||
205 | 227 | |||
206 | 228 | ListElement { | ||
207 | 229 | icon: "" | ||
208 | 230 | label: QT_TR_NOOP("On") | ||
209 | 231 | value: true | ||
210 | 232 | } | ||
211 | 233 | ListElement { | ||
212 | 234 | icon: "" | ||
213 | 235 | label: QT_TR_NOOP("Off") | ||
214 | 236 | value: false | ||
215 | 237 | } | ||
216 | 190 | } | 238 | } |
217 | 191 | ] | 239 | ] |
218 | 192 | 240 | ||
219 | 193 | 241 | ||
220 | === modified file 'ViewFinderView.qml' | |||
221 | --- ViewFinderView.qml 2014-10-09 19:14:01 +0000 | |||
222 | +++ ViewFinderView.qml 2014-12-01 01:56:45 +0000 | |||
223 | @@ -132,7 +132,8 @@ | |||
224 | 132 | Item { | 132 | Item { |
225 | 133 | id: viewFinderSwitcher | 133 | id: viewFinderSwitcher |
226 | 134 | anchors.fill: parent | 134 | anchors.fill: parent |
228 | 135 | 135 | visible: !viewFinderSwitcherBlurred.visible | |
229 | 136 | |||
230 | 136 | ShaderEffectSource { | 137 | ShaderEffectSource { |
231 | 137 | id: viewFinderGrab | 138 | id: viewFinderGrab |
232 | 138 | live: false | 139 | live: false |
233 | @@ -247,6 +248,26 @@ | |||
234 | 247 | viewFinderWidth: viewFinder.width | 248 | viewFinderWidth: viewFinder.width |
235 | 248 | viewFinderOrientation: viewFinder.orientation | 249 | viewFinderOrientation: viewFinder.orientation |
236 | 249 | } | 250 | } |
237 | 251 | |||
238 | 252 | Grid { | ||
239 | 253 | id: gridlines | ||
240 | 254 | anchors.fill: parent | ||
241 | 255 | visible: false | ||
242 | 256 | columns: 3 | ||
243 | 257 | property int rows: 3 | ||
244 | 258 | |||
245 | 259 | Repeater { | ||
246 | 260 | model: gridlines.columns * gridlines.rows | ||
247 | 261 | |||
248 | 262 | Rectangle { | ||
249 | 263 | width: parent.width / gridlines.columns | ||
250 | 264 | height: parent.height / gridlines.rows | ||
251 | 265 | border.width: 1 | ||
252 | 266 | border.color: "gray" | ||
253 | 267 | color: "transparent" | ||
254 | 268 | } | ||
255 | 269 | } | ||
256 | 270 | } | ||
257 | 250 | } | 271 | } |
258 | 251 | 272 | ||
259 | 252 | Rectangle { | 273 | Rectangle { |
260 | @@ -274,8 +295,12 @@ | |||
261 | 274 | } | 295 | } |
262 | 275 | 296 | ||
263 | 276 | FastBlur { | 297 | FastBlur { |
264 | 298 | id: viewFinderSwitcherBlurred | ||
265 | 277 | anchors.fill: viewFinderSwitcher | 299 | anchors.fill: viewFinderSwitcher |
267 | 278 | radius: photoRollHint.visible ? 64 : viewFinderOverlay.revealProgress * 64 | 300 | property real finalRadius: 64 |
268 | 301 | property real finalOpacity: 0.7 | ||
269 | 302 | radius: photoRollHint.visible ? finalRadius : viewFinderOverlay.revealProgress * finalRadius | ||
270 | 303 | opacity: photoRollHint.visible ? finalOpacity : (1.0 - viewFinderOverlay.revealProgress) * finalOpacity + finalOpacity | ||
271 | 279 | source: radius !== 0 ? viewFinderSwitcher : null | 304 | source: radius !== 0 ? viewFinderSwitcher : null |
272 | 280 | visible: radius !== 0 | 305 | visible: radius !== 0 |
273 | 281 | } | 306 | } |
- making the grid of options 4 columns does not really solve the problem of too many options long term (especially with your other MR coming in); thankfully this was solved already in another branch's commit. I think we should merge the specific commit that fixes it: commit 428 from lp:~fboucault/camera-app/jpeg_quality symbolic" is not good enough. I asked Matthieu (tiheum) from design to provide a better one. gridEnabled ? gridlines.columns * gridlines.rows : 0" will do the trick
Merge command: bzr merge -c428 lp:~fboucault/camera-app/jpeg_quality
- icon "view-grid-
- visually the grid should not have lines around the picture, only the 4 lines inside it; these lines outside are not useful and they create a boxing feel to the UI
- no need to use a Binding object (I understand the consistency reason, but it won't work out for other settings)
- better to not instantiate the Rectangles at all when the grid is disabled; "Repeater.model: settings.
- using Rectangle.border to draw is slightly more expensive than using Rectangle.color