Merge lp:~f-riccardo87/ubuntu-calculator-app/new-formula-structure into lp:~ubuntu-calculator-dev/ubuntu-calculator-app/old_trunk
- new-formula-structure
- Merge into old_trunk
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Gustavo Pichorim Boiko | ||||||||
Approved revision: | 48 | ||||||||
Merged at revision: | 47 | ||||||||
Proposed branch: | lp:~f-riccardo87/ubuntu-calculator-app/new-formula-structure | ||||||||
Merge into: | lp:~ubuntu-calculator-dev/ubuntu-calculator-app/old_trunk | ||||||||
Diff against target: |
589 lines (+284/-172) 8 files modified
Simple/CalcKeyboard.qml (+4/-4) Simple/CalcLabel.qml (+7/-0) Simple/Screen.qml (+1/-0) Simple/SimplePage.qml (+34/-143) formula.js (+133/-0) tests/autopilot/ubuntu_calculator_app/emulators/simple_page.py (+12/-0) tests/autopilot/ubuntu_calculator_app/tests/__init__.py (+12/-12) tests/autopilot/ubuntu_calculator_app/tests/test_simple_page.py (+81/-13) |
||||||||
To merge this branch: | bzr merge lp:~f-riccardo87/ubuntu-calculator-app/new-formula-structure | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gustavo Pichorim Boiko (community) | Approve | ||
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Riccardo Ferrazzo (community) | Abstain | ||
Review via email: mp+158100@code.launchpad.net |
Commit message
New formula implementation
Description of the change
Operations on the formula moved to a specific javascript class within another file.
Implementation of every preexisting function to use the new formula implementation.
C button now works as expected.
Some bugs corrected
- 47. By Riccardo Ferrazzo
-
comments added
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:47
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Riccardo Ferrazzo (f-riccardo87) wrote : | # |
> 108 + if(last.type === CALC.T_NUMBER || last.type ===
> CALC.T_
> 109 + screenFormula[
> last.value.
> 110 + } else {
> 111 + screenFormula.
> last.value.
>
> Would you mind adding a comment in the code explaining what is the use case
> being handle here? It will make it easier to understand and avoid wrong
> changes in the future.
Fixed!
Riccardo Ferrazzo (f-riccardo87) : | # |
Riccardo Ferrazzo (f-riccardo87) : | # |
Riccardo Ferrazzo (f-riccardo87) wrote : | # |
Excuse me, i maded some mistakes with my smartphone browser
- 48. By Riccardo Ferrazzo
-
merged autopilot tests
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:48
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Gustavo Pichorim Boiko (boiko) wrote : | # |
Looks good now!
Preview Diff
1 | === modified file 'Simple/CalcKeyboard.qml' | |||
2 | --- Simple/CalcKeyboard.qml 2013-04-07 11:18:00 +0000 | |||
3 | +++ Simple/CalcKeyboard.qml 2013-04-12 09:09:27 +0000 | |||
4 | @@ -33,7 +33,7 @@ | |||
5 | 33 | y: 0 | 33 | y: 0 |
6 | 34 | text: "C" | 34 | text: "C" |
7 | 35 | onClicked: { | 35 | onClicked: { |
9 | 36 | pop(); | 36 | formulaPop(); |
10 | 37 | } | 37 | } |
11 | 38 | } | 38 | } |
12 | 39 | 39 | ||
13 | @@ -50,14 +50,14 @@ | |||
14 | 50 | x: (calcGridUnit*11)*2 | 50 | x: (calcGridUnit*11)*2 |
15 | 51 | y: 0 | 51 | y: 0 |
16 | 52 | text: "÷" | 52 | text: "÷" |
18 | 53 | onClicked: formulaPush(text) | 53 | onClicked: formulaPush("/") |
19 | 54 | } | 54 | } |
20 | 55 | 55 | ||
21 | 56 | KeyboardButton { | 56 | KeyboardButton { |
22 | 57 | x: (calcGridUnit*11)*3 | 57 | x: (calcGridUnit*11)*3 |
23 | 58 | y: 0 | 58 | y: 0 |
24 | 59 | text: "×" | 59 | text: "×" |
26 | 60 | onClicked: formulaPush(text) | 60 | onClicked: formulaPush("*") |
27 | 61 | } | 61 | } |
28 | 62 | 62 | ||
29 | 63 | KeyboardButton { | 63 | KeyboardButton { |
30 | @@ -85,7 +85,7 @@ | |||
31 | 85 | x: (calcGridUnit*11)*3 | 85 | x: (calcGridUnit*11)*3 |
32 | 86 | y: (calcGridUnit*8) | 86 | y: (calcGridUnit*8) |
33 | 87 | text: "−" | 87 | text: "−" |
35 | 88 | onClicked: formulaPush(text) | 88 | onClicked: formulaPush('-') |
36 | 89 | } | 89 | } |
37 | 90 | 90 | ||
38 | 91 | KeyboardButton { | 91 | KeyboardButton { |
39 | 92 | 92 | ||
40 | === modified file 'Simple/CalcLabel.qml' | |||
41 | --- Simple/CalcLabel.qml 2013-03-19 17:52:36 +0000 | |||
42 | +++ Simple/CalcLabel.qml 2013-04-12 09:09:27 +0000 | |||
43 | @@ -14,6 +14,7 @@ | |||
44 | 14 | property string labelText: "" | 14 | property string labelText: "" |
45 | 15 | property int numbersHeight: units.gu(4) | 15 | property int numbersHeight: units.gu(4) |
46 | 16 | property string numbersColor: '#757373' | 16 | property string numbersColor: '#757373' |
47 | 17 | property bool isLast: false | ||
48 | 17 | 18 | ||
49 | 18 | Row{ | 19 | Row{ |
50 | 19 | id: row | 20 | id: row |
51 | @@ -39,6 +40,12 @@ | |||
52 | 39 | } | 40 | } |
53 | 40 | Label { | 41 | Label { |
54 | 41 | id: formulaLabel | 42 | id: formulaLabel |
55 | 43 | |||
56 | 44 | // this property is used by autopilot tests to find the correct item | ||
57 | 45 | // FIXME: implement it in a better way | ||
58 | 46 | property bool isLast: root.isLast | ||
59 | 47 | |||
60 | 48 | objectName: "formulaLabel" | ||
61 | 42 | width: units.gu(25) | 49 | width: units.gu(25) |
62 | 43 | color: numbersColor | 50 | color: numbersColor |
63 | 44 | anchors.bottom: parent.bottom | 51 | anchors.bottom: parent.bottom |
64 | 45 | 52 | ||
65 | === modified file 'Simple/Screen.qml' | |||
66 | --- Simple/Screen.qml 2013-03-20 16:28:57 +0000 | |||
67 | +++ Simple/Screen.qml 2013-04-12 09:09:27 +0000 | |||
68 | @@ -77,6 +77,7 @@ | |||
69 | 77 | operation: _operation | 77 | operation: _operation |
70 | 78 | numbersColor: (isLastItem && index === repeater.model.count-1) ? "#dd4814" : "#757373" | 78 | numbersColor: (isLastItem && index === repeater.model.count-1) ? "#dd4814" : "#757373" |
71 | 79 | numbersHeight: (isLastItem && index === repeater.model.count-1) ? units.gu(7) : units.gu(4) | 79 | numbersHeight: (isLastItem && index === repeater.model.count-1) ? units.gu(7) : units.gu(4) |
72 | 80 | isLast: (isLastItem && index === repeater.model.count-1) | ||
73 | 80 | 81 | ||
74 | 81 | onLabelTextChanged: { | 82 | onLabelTextChanged: { |
75 | 82 | root.labelTextUpdated(index, labelText) | 83 | root.labelTextUpdated(index, labelText) |
76 | 83 | 84 | ||
77 | === modified file 'Simple/SimplePage.qml' | |||
78 | --- Simple/SimplePage.qml 2013-04-06 08:47:15 +0000 | |||
79 | +++ Simple/SimplePage.qml 2013-04-12 09:09:27 +0000 | |||
80 | @@ -1,168 +1,59 @@ | |||
81 | 1 | import QtQuick 2.0 | 1 | import QtQuick 2.0 |
82 | 2 | import Ubuntu.Components 0.1 | 2 | import Ubuntu.Components 0.1 |
83 | 3 | import "../engine.js" as CALC | 3 | import "../engine.js" as CALC |
85 | 4 | //TODO: check for unneeded scanner initializations | 4 | import "../formula.js" as F |
86 | 5 | 5 | ||
87 | 6 | Page { | 6 | Page { |
88 | 7 | 7 | ||
91 | 8 | property var context: new CALC.Context; | 8 | property var formula: new F.Formula() |
90 | 9 | property var scanner: new CALC.Scanner(engineFormula.join(''), context); | ||
92 | 10 | property var screenFormula: [{_text:'', _operation: '', _number:''}] | 9 | property var screenFormula: [{_text:'', _operation: '', _number:''}] |
93 | 11 | property var engineFormula: [''] | ||
94 | 12 | 10 | ||
95 | 13 | function formulaPush(visual) { | 11 | function formulaPush(visual) { |
96 | 14 | var engine; | ||
97 | 15 | switch(visual){ | ||
98 | 16 | case '÷': | ||
99 | 17 | engine = '/'; | ||
100 | 18 | break; | ||
101 | 19 | case '×': | ||
102 | 20 | engine = '*'; | ||
103 | 21 | break; | ||
104 | 22 | case '−': | ||
105 | 23 | engine = '-'; | ||
106 | 24 | break; | ||
107 | 25 | default: | ||
108 | 26 | engine = visual; | ||
109 | 27 | } | ||
110 | 28 | if(screenFormula.length === 0){ | ||
111 | 29 | screenFormula.push({_text:'', _operation: '', _number:''}); | ||
112 | 30 | } | ||
113 | 31 | if(engineFormula.length === 0){ | ||
114 | 32 | engineFormula.push(''); | ||
115 | 33 | } | ||
116 | 34 | if(screenFormula[screenFormula.length-1]._operation === "=") return; | ||
117 | 35 | try{ | 12 | try{ |
121 | 36 | var n_scanner = new CALC.Scanner(engineFormula.join('') + engine, context); | 13 | var last = formula.push(visual); |
122 | 37 | } catch(exception) { | 14 | } catch(exception){ |
120 | 38 | console.log("errore",exception) | ||
123 | 39 | return; | 15 | return; |
124 | 40 | } | 16 | } |
145 | 41 | if(n_scanner.tokens.length > 1){ | 17 | |
146 | 42 | switch(n_scanner.tokens.last().type){ | 18 | //if the element to add is a number or an unary operator it is added to the current line |
147 | 43 | case CALC.T_PLUS: | 19 | //otherwise the element is a binary operator and it needs to be added to a new line |
148 | 44 | case CALC.T_MINUS: | 20 | if(last.type === CALC.T_NUMBER || last.type === CALC.T_UNARY_MINUS){ |
149 | 45 | case CALC.T_DIV: | 21 | screenFormula[screenFormula.length - 1]._number += last.value.toString(); |
150 | 46 | case CALC.T_TIMES: | 22 | } else { |
151 | 47 | if(n_scanner.tokens[n_scanner.tokens.length-2].type & CALC.T_OPERATOR) return; | 23 | screenFormula.push({_text:'', _operation: last.value.toString(), _number: ''}) |
132 | 48 | scanner = n_scanner; | ||
133 | 49 | screenFormula.push({_text:'', _operation: '', _number:''}); | ||
134 | 50 | screenFormula[screenFormula.length-1]._operation = visual; | ||
135 | 51 | engineFormula.push(''); | ||
136 | 52 | engineFormula[engineFormula.length-1] += engine; | ||
137 | 53 | formulaView.currentOperatorsChanged(); | ||
138 | 54 | return; | ||
139 | 55 | case CALC.T_UNARY_PLUS: | ||
140 | 56 | case CALC.T_UNARY_MINUS: | ||
141 | 57 | if(n_scanner.tokens[n_scanner.tokens.length-2].type === CALC.T_UNARY_MINUS || | ||
142 | 58 | n_scanner.tokens[n_scanner.tokens.length-2].type === CALC.T_UNARY_PLUS ) return; | ||
143 | 59 | break; | ||
144 | 60 | } | ||
152 | 61 | } | 24 | } |
153 | 62 | scanner = n_scanner; | ||
154 | 63 | screenFormula[screenFormula.length-1]._number += visual; | ||
155 | 64 | engineFormula[engineFormula.length-1] += engine; | ||
156 | 65 | formulaView.currentOperatorsChanged(); | 25 | formulaView.currentOperatorsChanged(); |
157 | 66 | } | 26 | } |
158 | 67 | 27 | ||
159 | 68 | function changeSign(){ | 28 | function changeSign(){ |
163 | 69 | if(screenFormula[screenFormula.length-1]._operation === "=") return; | 29 | formula.changeSign(); |
164 | 70 | var prev_tokens = []; | 30 | formulaView.currentOperatorsChanged(); |
165 | 71 | var add_minus = true; | 31 | } |
166 | 32 | |||
167 | 33 | function calculate() { | ||
168 | 34 | try{ | ||
169 | 35 | var result = formula.calculate(); | ||
170 | 36 | } catch(exception) { | ||
171 | 37 | formulaPop(); | ||
172 | 38 | calculate(); | ||
173 | 39 | } | ||
174 | 40 | screenFormula.push({_text:'', _operation: '=', _number: result.toString()}); | ||
175 | 41 | formulaView.currentOperatorsChanged(); | ||
176 | 42 | } | ||
177 | 43 | |||
178 | 44 | function formulaPop(){ | ||
179 | 45 | if(screenFormula.length <= 1){ | ||
180 | 46 | clear(); | ||
181 | 47 | return; | ||
182 | 48 | } | ||
183 | 49 | formula.pop(); | ||
184 | 72 | screenFormula.pop(); | 50 | screenFormula.pop(); |
185 | 73 | engineFormula.pop(); | ||
186 | 74 | if(scanner.tokens.length === 0){ | ||
187 | 75 | prev_tokens.push(new CALC.Token('-', CALC.T_UNARY_MINUS)); | ||
188 | 76 | } | ||
189 | 77 | while(scanner.tokens.length > 0 ){ | ||
190 | 78 | var last = scanner.tokens.pop(); | ||
191 | 79 | if(last.type & CALC.T_OPERATOR && | ||
192 | 80 | last.type !== CALC.T_UNARY_MINUS && | ||
193 | 81 | last.type !== CALC.T_UNARY_PLUS ){ | ||
194 | 82 | if(add_minus){ | ||
195 | 83 | prev_tokens.push(new CALC.Token('-', CALC.T_UNARY_MINUS)); | ||
196 | 84 | } | ||
197 | 85 | prev_tokens.push(last); | ||
198 | 86 | break; | ||
199 | 87 | } | ||
200 | 88 | if(last.type === CALC.T_UNARY_MINUS){ | ||
201 | 89 | add_minus = false; | ||
202 | 90 | continue; | ||
203 | 91 | } | ||
204 | 92 | prev_tokens.push(last); | ||
205 | 93 | if(scanner.tokens.length === 0 && add_minus){ | ||
206 | 94 | prev_tokens.push(new CALC.Token('-', CALC.T_UNARY_MINUS)); | ||
207 | 95 | } | ||
208 | 96 | } | ||
209 | 97 | while(prev_tokens.length > 0){ | ||
210 | 98 | var last = prev_tokens.pop(); | ||
211 | 99 | var visual; | ||
212 | 100 | switch(last.type){ | ||
213 | 101 | case CALC.T_TIMES: | ||
214 | 102 | visual = '×'; | ||
215 | 103 | break; | ||
216 | 104 | case CALC.T_DIV: | ||
217 | 105 | visual = '÷'; | ||
218 | 106 | break; | ||
219 | 107 | case CALC.T_MINUS: | ||
220 | 108 | visual = "−"; | ||
221 | 109 | break; | ||
222 | 110 | default: | ||
223 | 111 | visual = last.value.toString(); | ||
224 | 112 | } | ||
225 | 113 | formulaPush(visual); | ||
226 | 114 | } | ||
227 | 115 | formulaView.currentOperatorsChanged(); | ||
228 | 116 | } | ||
229 | 117 | |||
230 | 118 | function calculate() { | ||
231 | 119 | if(screenFormula[screenFormula.length-1]._operation === "="){ | ||
232 | 120 | var lastOperation = engineFormula.pop(); | ||
233 | 121 | var previousResult = screenFormula[screenFormula.length-1]._number | ||
234 | 122 | engineFormula = [previousResult, lastOperation]; | ||
235 | 123 | } | ||
236 | 124 | try{ | ||
237 | 125 | scanner = new CALC.Scanner(engineFormula.join(""), context); | ||
238 | 126 | var result = new CALC.Parser(scanner).reduce(context); | ||
239 | 127 | if (result === Number.POSITIVE_INFINITY) | ||
240 | 128 | result = '∞'; | ||
241 | 129 | else if (result === Number.NEGATIVE_INFINITY) | ||
242 | 130 | result = '-∞'; | ||
243 | 131 | } catch(exception) { | ||
244 | 132 | if(exception instanceof CALC.DivisionByZeroError){ | ||
245 | 133 | result = "division by zero error"; | ||
246 | 134 | } else{ | ||
247 | 135 | screenFormula.pop(); | ||
248 | 136 | engineFormula.pop(); | ||
249 | 137 | scanner = new CALC.Scanner(engineFormula.join(''), context); | ||
250 | 138 | calculate(); | ||
251 | 139 | return; | ||
252 | 140 | } | ||
253 | 141 | } | ||
254 | 142 | screenFormula.push({_text:'', _operation: '=', _number:result.toString()}); | ||
255 | 143 | formulaView.currentOperatorsChanged(); | ||
256 | 144 | } | ||
257 | 145 | |||
258 | 146 | function pop(){ | ||
259 | 147 | if(screenFormula.length === 0) return; | ||
260 | 148 | var lastRow = screenFormula.pop(); | ||
261 | 149 | formulaView.currentOperatorsChanged(); | ||
262 | 150 | if(screenFormula[screenFormula.length-1]._operation === "=") return; | ||
263 | 151 | var oldFormula = screenFormula; | ||
264 | 152 | clear(); | ||
265 | 153 | for(var i = 0; i<oldFormula.length; i++){ | ||
266 | 154 | if(oldFormula[i]._operation !== '') | ||
267 | 155 | formulaPush(oldFormula[i]._operation); | ||
268 | 156 | formulaPush(oldFormula[i]._number); | ||
269 | 157 | screenFormula[screenFormula.length-1]._text = oldFormula[i]._text; | ||
270 | 158 | } | ||
271 | 159 | formulaView.currentOperatorsChanged(); | 51 | formulaView.currentOperatorsChanged(); |
272 | 160 | } | 52 | } |
273 | 161 | 53 | ||
274 | 162 | function clear(){ | 54 | function clear(){ |
275 | 163 | screenFormula = [{_text:'', _operation: '', _number:''}]; | 55 | screenFormula = [{_text:'', _operation: '', _number:''}]; |
278 | 164 | engineFormula = ['']; | 56 | formula = new F.Formula(); |
277 | 165 | scanner = new CALC.Scanner(engineFormula.join(''), context); | ||
279 | 166 | formulaView.currentOperatorsChanged(); | 57 | formulaView.currentOperatorsChanged(); |
280 | 167 | } | 58 | } |
281 | 168 | 59 | ||
282 | @@ -173,7 +64,7 @@ | |||
283 | 173 | return; | 64 | return; |
284 | 174 | } | 65 | } |
285 | 175 | if(temp.tokens.length === 1 && temp.tokens.last().type === CALC.T_NUMBER){ | 66 | if(temp.tokens.length === 1 && temp.tokens.last().type === CALC.T_NUMBER){ |
287 | 176 | formulaPush(numberToAdd, numberToAdd); | 67 | formulaPush(numberToAdd); |
288 | 177 | } | 68 | } |
289 | 178 | } | 69 | } |
290 | 179 | 70 | ||
291 | 180 | 71 | ||
292 | === added file 'formula.js' | |||
293 | --- formula.js 1970-01-01 00:00:00 +0000 | |||
294 | +++ formula.js 2013-04-12 09:09:27 +0000 | |||
295 | @@ -0,0 +1,133 @@ | |||
296 | 1 | Qt.include("engine.js"); | ||
297 | 2 | |||
298 | 3 | var context = new Context; | ||
299 | 4 | |||
300 | 5 | function Formula() { | ||
301 | 6 | var previous = new Token(0, T_NUMBER); | ||
302 | 7 | var formula = ''; | ||
303 | 8 | var results = []; | ||
304 | 9 | var lookupTbl = { | ||
305 | 10 | '-': '−', | ||
306 | 11 | '/': '÷', | ||
307 | 12 | '*': '×' | ||
308 | 13 | }; | ||
309 | 14 | |||
310 | 15 | var _calculate = function(func){ | ||
311 | 16 | try{ | ||
312 | 17 | var result = parse(func, context); | ||
313 | 18 | if (result === Number.POSITIVE_INFINITY) | ||
314 | 19 | result = '∞'; | ||
315 | 20 | else if (result === Number.NEGATIVE_INFINITY) | ||
316 | 21 | result = '-∞'; | ||
317 | 22 | }catch(exception){ | ||
318 | 23 | if(exception instanceof DivisionByZeroError){ | ||
319 | 24 | result = "division by zero error"; | ||
320 | 25 | } else{ | ||
321 | 26 | throw new SyntaxError("malformed calculation"); | ||
322 | 27 | } | ||
323 | 28 | } | ||
324 | 29 | return result; | ||
325 | 30 | } | ||
326 | 31 | |||
327 | 32 | this.push = function(digit){ | ||
328 | 33 | if(results.length > 0) throw new SyntaxError("cannot push"); | ||
329 | 34 | var last = (new Scanner(previous.value.toString()+digit, context)).tokens.pop(); | ||
330 | 35 | switch(last.type){ | ||
331 | 36 | case T_PLUS: | ||
332 | 37 | case T_MINUS: | ||
333 | 38 | case T_DIV: | ||
334 | 39 | case T_TIMES: | ||
335 | 40 | if(previous.type & T_OPERATOR) return; | ||
336 | 41 | break; | ||
337 | 42 | case T_UNARY_PLUS: | ||
338 | 43 | case T_UNARY_MINUS: | ||
339 | 44 | if(previous.type === T_UNARY_MINUS || previous.type === T_UNARY_PLUS ) return; | ||
340 | 45 | break; | ||
341 | 46 | } | ||
342 | 47 | formula += digit; | ||
343 | 48 | previous = last; | ||
344 | 49 | var ret = {value: '', type: last.type}; | ||
345 | 50 | if(lookupTbl[digit] !== undefined){ | ||
346 | 51 | ret.value = lookupTbl[digit]; | ||
347 | 52 | } else { | ||
348 | 53 | ret.value = digit; | ||
349 | 54 | } | ||
350 | 55 | return ret; | ||
351 | 56 | }; | ||
352 | 57 | |||
353 | 58 | this.pop = function(){ | ||
354 | 59 | if(results.length > 0){ | ||
355 | 60 | results.pop(); | ||
356 | 61 | return; | ||
357 | 62 | } | ||
358 | 63 | var scannedFormula = new Scanner(formula, context); | ||
359 | 64 | var last = {type:T_NUMBER}; | ||
360 | 65 | var removeSize = 0; | ||
361 | 66 | while(scannedFormula.tokens.length > 0 && (last.type === T_NUMBER || last.type === T_UNARY_PLUS || last.type === T_UNARY_MINUS)){ | ||
362 | 67 | last = scannedFormula.tokens.pop(); | ||
363 | 68 | removeSize += last.value.toString().length | ||
364 | 69 | } | ||
365 | 70 | formula = formula.substring(0, formula.length - removeSize); | ||
366 | 71 | previous = scannedFormula.tokens.pop(); | ||
367 | 72 | }; | ||
368 | 73 | |||
369 | 74 | this.calculate = function(){ | ||
370 | 75 | var result; | ||
371 | 76 | var previousSize = previous.value.toString().length; | ||
372 | 77 | if(formula.length <= previousSize) return; | ||
373 | 78 | if(results.length > 0){ | ||
374 | 79 | var scannedFormula = new Scanner(formula, context); | ||
375 | 80 | var last = scannedFormula.tokens.pop(); | ||
376 | 81 | var newFormula = last.value.toString(); | ||
377 | 82 | while(last.type !== T_PLUS && | ||
378 | 83 | last.type !== T_MINUS && | ||
379 | 84 | last.type !== T_DIV && | ||
380 | 85 | last.type !== T_TIMES ){ | ||
381 | 86 | last = scannedFormula.tokens.pop(); | ||
382 | 87 | newFormula = last.value.toString() + newFormula; | ||
383 | 88 | } | ||
384 | 89 | result = _calculate(results[results.length-1]+newFormula); | ||
385 | 90 | } else { | ||
386 | 91 | result = _calculate(formula); | ||
387 | 92 | } | ||
388 | 93 | results.push(result.toString()); | ||
389 | 94 | return result; | ||
390 | 95 | } | ||
391 | 96 | |||
392 | 97 | this.changeSign = function(){ | ||
393 | 98 | if(results.length > 0) throw new SyntaxError("cannot edit formula"); | ||
394 | 99 | switch(previous.type){ | ||
395 | 100 | case T_PLUS: | ||
396 | 101 | case T_MINUS: | ||
397 | 102 | case T_DIV: | ||
398 | 103 | case T_TIMES: | ||
399 | 104 | formulaPush("-"); | ||
400 | 105 | break; | ||
401 | 106 | default: | ||
402 | 107 | var scannedFormula = new Scanner(formula, context); | ||
403 | 108 | var last = {type: undefined}; | ||
404 | 109 | var toAdd = []; | ||
405 | 110 | var addMinus = true; | ||
406 | 111 | while(scannedFormula.tokens.length > 0 && last.type !== T_PLUS && | ||
407 | 112 | last.type !== T_MINUS && | ||
408 | 113 | last.type !== T_DIV && | ||
409 | 114 | last.type !== T_TIMES ){ | ||
410 | 115 | last = scannedFormula.tokens.pop(); | ||
411 | 116 | if(last.type !== T_UNARY_MINUS && last.type !== T_UNARY_PLUS){ | ||
412 | 117 | toAdd.push(last); | ||
413 | 118 | } else { | ||
414 | 119 | if(last.type === T_UNARY_MINUS) | ||
415 | 120 | addMinus = false; | ||
416 | 121 | } | ||
417 | 122 | } | ||
418 | 123 | formulaPop(); | ||
419 | 124 | while(toAdd.length > 0){ | ||
420 | 125 | var el = toAdd.pop() | ||
421 | 126 | formulaPush(el.value.toString()); | ||
422 | 127 | if((el.type & T_OPERATOR) && addMinus){ | ||
423 | 128 | formulaPush('-'); | ||
424 | 129 | } | ||
425 | 130 | } | ||
426 | 131 | } | ||
427 | 132 | } | ||
428 | 133 | } | ||
429 | 0 | 134 | ||
430 | === renamed file 'tests/autopilot/ubuntu_calculator_app/emulators/main_buttons.py' => 'tests/autopilot/ubuntu_calculator_app/emulators/simple_page.py' | |||
431 | --- tests/autopilot/ubuntu_calculator_app/emulators/main_buttons.py 2013-03-22 12:15:46 +0000 | |||
432 | +++ tests/autopilot/ubuntu_calculator_app/emulators/simple_page.py 2013-04-12 09:09:27 +0000 | |||
433 | @@ -4,3 +4,15 @@ | |||
434 | 4 | # This program is free software: you can redistribute it and/or modify it | 4 | # This program is free software: you can redistribute it and/or modify it |
435 | 5 | # under the terms of the GNU General Public License version 3, as published | 5 | # under the terms of the GNU General Public License version 3, as published |
436 | 6 | # by the Free Software Foundation. | 6 | # by the Free Software Foundation. |
437 | 7 | |||
438 | 8 | class SimplePage(object): | ||
439 | 9 | """An emulator class that makes it easy to interact with the call panel.""" | ||
440 | 10 | def __init__(self, app): | ||
441 | 11 | self.app = app | ||
442 | 12 | |||
443 | 13 | def get_button(self, text): | ||
444 | 14 | return self.app.select_single('KeyboardButton', text=text) | ||
445 | 15 | |||
446 | 16 | def get_formula_label(self): | ||
447 | 17 | # FIXME: find a better way to find the latest formula label | ||
448 | 18 | return self.app.select_single('Label', objectName='formulaLabel', isLast=True) | ||
449 | 7 | 19 | ||
450 | === modified file 'tests/autopilot/ubuntu_calculator_app/tests/__init__.py' | |||
451 | --- tests/autopilot/ubuntu_calculator_app/tests/__init__.py 2013-03-22 12:15:46 +0000 | |||
452 | +++ tests/autopilot/ubuntu_calculator_app/tests/__init__.py 2013-04-12 09:09:27 +0000 | |||
453 | @@ -17,22 +17,22 @@ | |||
454 | 17 | 17 | ||
455 | 18 | class CalculatorTestCase(AutopilotTestCase, QtIntrospectionTestMixin): | 18 | class CalculatorTestCase(AutopilotTestCase, QtIntrospectionTestMixin): |
456 | 19 | 19 | ||
463 | 20 | """A common testcase class that provides useful methods for calculator app.""" | 20 | """A common testcase class that provides useful methods for calculator app.""" |
464 | 21 | 21 | ||
465 | 22 | def setUp(self): | 22 | def setUp(self): |
466 | 23 | super(CalculatorTestCase, self).setUp() | 23 | super(CalculatorTestCase, self).setUp() |
467 | 24 | 24 | ||
468 | 25 | if os.path.realpath(__file__).startswith("/usr/"): | 25 | if os.path.realpath(__file__).startswith("/usr/"): |
469 | 26 | self.launch_test_installed() | 26 | self.launch_test_installed() |
470 | 27 | else: | 27 | else: |
471 | 28 | self.launch_test_local() | 28 | self.launch_test_local() |
472 | 29 | 29 | ||
473 | 30 | def launch_test_local(self): | 30 | def launch_test_local(self): |
477 | 31 | self.app = self.launch_test_application( | 31 | self.app = self.launch_test_application( |
478 | 32 | "qmlscene", "../../ubuntu-calculator-app.qml" | 32 | "qmlscene", "../../ubuntu-calculator-app.qml" |
479 | 33 | ) | 33 | ) |
480 | 34 | 34 | ||
481 | 35 | def launch_test_installed(self): | 35 | def launch_test_installed(self): |
485 | 36 | self.app = self.launch_test_application( | 36 | self.app = self.launch_test_application( |
486 | 37 | "ubuntu-calculator-app" | 37 | "ubuntu-calculator-app" |
487 | 38 | ) | 38 | ) |
488 | 39 | 39 | ||
489 | === renamed file 'tests/autopilot/ubuntu_calculator_app/tests/test_main_buttons.py' => 'tests/autopilot/ubuntu_calculator_app/tests/test_simple_page.py' | |||
490 | --- tests/autopilot/ubuntu_calculator_app/tests/test_main_buttons.py 2013-03-22 14:17:43 +0000 | |||
491 | +++ tests/autopilot/ubuntu_calculator_app/tests/test_simple_page.py 2013-04-12 09:09:27 +0000 | |||
492 | @@ -14,16 +14,84 @@ | |||
493 | 14 | from autopilot.matchers import Eventually | 14 | from autopilot.matchers import Eventually |
494 | 15 | 15 | ||
495 | 16 | from ubuntu_calculator_app.tests import CalculatorTestCase | 16 | from ubuntu_calculator_app.tests import CalculatorTestCase |
509 | 17 | 17 | from ubuntu_calculator_app.emulators.simple_page import SimplePage | |
510 | 18 | 18 | ||
511 | 19 | class TestMainButtons(CalculatorTestCase): | 19 | class TestSimplePage(CalculatorTestCase): |
512 | 20 | 20 | ||
513 | 21 | def setUp(self): | 21 | def setUp(self): |
514 | 22 | super(TestMainButtons, self).setUp() | 22 | super(TestSimplePage, self).setUp() |
515 | 23 | 23 | ||
516 | 24 | def test_this(self): | 24 | def test_this(self): |
517 | 25 | buttons = self.app.select_many("KeyboardButton") | 25 | buttons = self.app.select_many("KeyboardButton") |
518 | 26 | 26 | ||
519 | 27 | for keys in buttons: | 27 | for keys in buttons: |
520 | 28 | self.pointing_device.move_to_object(keys) | 28 | self.pointing_device.move_to_object(keys) |
521 | 29 | self.pointing_device.click() | 29 | self.pointing_device.click() |
522 | 30 | |||
523 | 31 | def test_operation_after_clear(self): | ||
524 | 32 | """ Test that after clearing one calculation, the next is still correct (bug #1164973) """ | ||
525 | 33 | oneButton = self.simple_page.get_button("1") | ||
526 | 34 | plusButton = self.simple_page.get_button("+") | ||
527 | 35 | equalsButton = self.simple_page.get_button("=") | ||
528 | 36 | clearButton = self.simple_page.get_button("C") | ||
529 | 37 | |||
530 | 38 | # type 1+1= | ||
531 | 39 | self.pointing_device.move_to_object(oneButton) | ||
532 | 40 | self.pointing_device.click() | ||
533 | 41 | self.pointing_device.move_to_object(plusButton) | ||
534 | 42 | self.pointing_device.click() | ||
535 | 43 | self.pointing_device.move_to_object(oneButton) | ||
536 | 44 | self.pointing_device.click() | ||
537 | 45 | self.pointing_device.move_to_object(equalsButton) | ||
538 | 46 | self.pointing_device.click() | ||
539 | 47 | |||
540 | 48 | # make sure the result is already there | ||
541 | 49 | self.assertThat(self.simple_page.get_formula_label().text, Eventually(Equals("2"))) | ||
542 | 50 | |||
543 | 51 | # now clear the input by pressing "C" three times | ||
544 | 52 | self.pointing_device.move_to_object(clearButton) | ||
545 | 53 | self.pointing_device.click() | ||
546 | 54 | self.pointing_device.click() | ||
547 | 55 | self.pointing_device.click() | ||
548 | 56 | |||
549 | 57 | # and do the operation again to make sure the result is correct | ||
550 | 58 | self.pointing_device.move_to_object(oneButton) | ||
551 | 59 | self.pointing_device.click() | ||
552 | 60 | self.pointing_device.move_to_object(plusButton) | ||
553 | 61 | self.pointing_device.click() | ||
554 | 62 | self.pointing_device.move_to_object(oneButton) | ||
555 | 63 | self.pointing_device.click() | ||
556 | 64 | self.pointing_device.move_to_object(equalsButton) | ||
557 | 65 | self.pointing_device.click() | ||
558 | 66 | |||
559 | 67 | # make sure the result is correct | ||
560 | 68 | self.assertThat(self.simple_page.get_formula_label().text, Eventually(Equals("2"))) | ||
561 | 69 | |||
562 | 70 | def test_equals_dont_change_numbers(self): | ||
563 | 71 | """ Test that typing a number and pressing "=" won't change the number (bug #1165894) """ | ||
564 | 72 | oneButton = self.simple_page.get_button("1") | ||
565 | 73 | twoButton = self.simple_page.get_button("2") | ||
566 | 74 | threeButton = self.simple_page.get_button("3") | ||
567 | 75 | equalsButton = self.simple_page.get_button("=") | ||
568 | 76 | |||
569 | 77 | # type the initial number | ||
570 | 78 | self.pointing_device.move_to_object(oneButton) | ||
571 | 79 | self.pointing_device.click() | ||
572 | 80 | self.pointing_device.move_to_object(twoButton) | ||
573 | 81 | self.pointing_device.click() | ||
574 | 82 | self.pointing_device.move_to_object(threeButton) | ||
575 | 83 | self.pointing_device.click() | ||
576 | 84 | |||
577 | 85 | # check that the label is displaying correctly | ||
578 | 86 | self.assertThat(self.simple_page.get_formula_label().text, Eventually(Equals("123"))) | ||
579 | 87 | |||
580 | 88 | # click the "=" button | ||
581 | 89 | self.pointing_device.move_to_object(equalsButton) | ||
582 | 90 | self.pointing_device.click() | ||
583 | 91 | |||
584 | 92 | # check that the label is still displaying correctly | ||
585 | 93 | self.assertThat(self.simple_page.get_formula_label().text, Eventually(Equals("123"))) | ||
586 | 94 | |||
587 | 95 | @property | ||
588 | 96 | def simple_page(self): | ||
589 | 97 | return SimplePage(self.app) |
108 + if(last.type === CALC.T_NUMBER || last.type === CALC.T_ UNARY_MINUS) { screenFormula. length - 1]._number += last.value. toString( ); push({_ text:'' , _operation: last.value. toString( ), _number: ''})
109 + screenFormula[
110 + } else {
111 + screenFormula.
Would you mind adding a comment in the code explaining what is the use case being handle here? It will make it easier to understand and avoid wrong changes in the future.