Merge lp:~zsombi/ubuntu-ui-toolkit/calculator-example into lp:ubuntu-ui-toolkit

Proposed by Zsombor Egri
Status: Merged
Approved by: Tim Peeters
Approved revision: 570
Merged at revision: 577
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/calculator-example
Merge into: lp:ubuntu-ui-toolkit
Diff against target: 598 lines (+550/-1)
8 files modified
examples/calculator/calculator.desktop (+8/-0)
examples/calculator/calculator.pro (+18/-0)
examples/calculator/calculator.qml (+126/-0)
examples/calculator/calculator.qmlproject (+31/-0)
examples/calculator/components/DefaultLayout.qml (+100/-0)
examples/calculator/components/Functions.qml (+46/-0)
examples/calculator/components/calculator.js (+219/-0)
examples/examples.pro (+2/-1)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/calculator-example
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Tim Peeters Pending
Review via email: mp+172534@code.launchpad.net

Commit message

Calculator example which turns from simple calculator (phone portrait mode) into scientific one (phone landscape mode) reflecting the use of Ubuntu.Layouts.

To post a comment you must log in.
567. By Zsombor Egri

makefile removed; pro-file added to fix application installation; desktop file corrected

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
568. By Zsombor Egri

license headers updated

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
569. By Zsombor Egri

trunk merge

570. By Zsombor Egri

memory indication added

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

on desktop, the text is very tiny, can we scale the text with the buttons?

Revision history for this message
Tim Peeters (tpeeters) wrote :

why add this example? We have a calculator app https://wiki.ubuntu.com/Touch/CoreApps/Calculator

Revision history for this message
Tim Peeters (tpeeters) wrote :

why do you have a Flickable? The buttons resize to fit in the view without flicking.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> on desktop, the text is very tiny, can we scale the text with the buttons?

Button label cannot be enlarged only with creating a different style for it.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> why add this example? We have a calculator app
> https://wiki.ubuntu.com/Touch/CoreApps/Calculator

As we discussed, the app we have does not forbid us to create a simplier one to illustrate what we can do with certain SDK building blocks.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> why do you have a Flickable? The buttons resize to fit in the view without
> flicking.

Without Flickable the content goes below the Header :(. Haven't found a better way atm to circumvent that...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'examples/calculator'
2=== added file 'examples/calculator/calculator.desktop'
3--- examples/calculator/calculator.desktop 1970-01-01 00:00:00 +0000
4+++ examples/calculator/calculator.desktop 2013-07-03 06:43:28 +0000
5@@ -0,0 +1,8 @@
6+[Desktop Entry]
7+Name=calculator
8+Comment=My project description
9+Exec=/usr/bin/qmlscene $@ /usr/lib/ubuntu-ui-toolkit/examples/calculator/calculator.qml
10+Icon=qmlscene
11+Terminal=false
12+Type=Application
13+X-Ubuntu-Touch=true
14
15=== added file 'examples/calculator/calculator.pro'
16--- examples/calculator/calculator.pro 1970-01-01 00:00:00 +0000
17+++ examples/calculator/calculator.pro 2013-07-03 06:43:28 +0000
18@@ -0,0 +1,18 @@
19+TEMPLATE = subdirs
20+
21+filetypes = qml png svg js qmltheme jpg qmlproject desktop wav
22+
23+OTHER_FILES = ""
24+
25+for(filetype, filetypes) {
26+ OTHER_FILES += *.$$filetype
27+}
28+
29+desktop_files.path = /usr/share/applications
30+desktop_files.files = calculator.desktop
31+
32+other_files.path = /usr/lib/ubuntu-ui-toolkit/examples/calculator
33+other_files.files = $$OTHER_FILES
34+
35+INSTALLS += other_files desktop_files
36+
37
38=== added file 'examples/calculator/calculator.qml'
39--- examples/calculator/calculator.qml 1970-01-01 00:00:00 +0000
40+++ examples/calculator/calculator.qml 2013-07-03 06:43:28 +0000
41@@ -0,0 +1,126 @@
42+/*
43+ * Copyright 2013 Canonical Ltd.
44+ *
45+ * This program is free software; you can redistribute it and/or modify
46+ * it under the terms of the GNU Lesser General Public License as published by
47+ * the Free Software Foundation; version 3.
48+ *
49+ * This program is distributed in the hope that it will be useful,
50+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52+ * GNU Lesser General Public License for more details.
53+ *
54+ * You should have received a copy of the GNU Lesser General Public License
55+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
56+ *
57+ * Author: Zsombor Egri <zsombor.egri@canonical.com>
58+ */
59+
60+import QtQuick 2.0
61+import Ubuntu.Components 0.1
62+import Ubuntu.Layouts 0.1
63+import "components"
64+import "components/calculator.js" as Calculator
65+
66+/*!
67+ \brief MainView with a Label and Button elements.
68+*/
69+
70+MainView {
71+ id: mainView
72+ // objectName for functional testing purposes (autopilot-qt5)
73+ objectName: "mainView"
74+
75+ // Note! applicationName needs to match the .desktop filename
76+ applicationName: "calculator"
77+
78+ /*
79+ This property enables the application to change orientation
80+ when the device is rotated. The default is false.
81+ */
82+ automaticOrientation: true
83+
84+ width: units.gu(40)
85+ height: units.gu(71)
86+
87+ property var calculator: new Calculator.Calculator(numericInput, memoryIndicator);
88+
89+ // default portrait layout
90+ Page {
91+ id: page
92+ title: i18n.tr("Calculator")
93+ anchors.fill: parent
94+
95+ Flickable {
96+ anchors.fill: parent
97+ contentWidth: column.width
98+ contentHeight: column.height
99+ Column {
100+ id: column
101+ width: page.width
102+ height: childrenRect.height
103+ spacing: units.gu(0.5)
104+ TextField {
105+ id: numericInput
106+ anchors {
107+ left: parent.left
108+ right: parent.right
109+ }
110+ readOnly: true
111+ font.pixelSize: FontUtils.sizeToPixels("x-large")
112+ font.bold: true
113+ horizontalAlignment: Text.AlignRight
114+ height: layout.currentLayout === "landscape" ?
115+ units.gu(5) : units.gu(7)
116+ primaryItem: Label {
117+ id: memoryIndicator
118+ width: units.gu(3)
119+ height: parent.height
120+ text: "M"
121+ fontSize: "large"
122+ font.bold: true
123+ }
124+ }
125+
126+ Layouts {
127+ id: layout
128+ anchors {
129+ left: parent.left
130+ right: parent.right
131+ }
132+ height: page.height - numericInput.height - mainView.header.height
133+
134+ layouts: [
135+ ConditionalLayout {
136+ name: "landscape"
137+ when: mainView.width > mainView.height
138+ Item {
139+ anchors.fill: parent
140+ Functions {
141+ operations: calculator
142+ anchors.fill: parent
143+ anchors.rightMargin: parent.width / 2 + units.gu(0.25)
144+ spacing: units.gu(0.4)
145+ }
146+
147+ ItemLayout {
148+ item: "buttons"
149+ anchors.fill: parent
150+
151+ anchors.leftMargin: parent.width / 2 + units.gu(0.25)
152+ }
153+ }
154+ }
155+
156+ ]
157+ DefaultLayout {
158+ anchors.fill: parent
159+ anchors.margins: units.gu(0.5)
160+ operations: calculator
161+ spacing: (layout.currentLayout === "landscape") ? units.gu(0.4) : units.gu(2)
162+ }
163+ }
164+ }
165+ }
166+ }
167+}
168
169=== added file 'examples/calculator/calculator.qmlproject'
170--- examples/calculator/calculator.qmlproject 1970-01-01 00:00:00 +0000
171+++ examples/calculator/calculator.qmlproject 2013-07-03 06:43:28 +0000
172@@ -0,0 +1,31 @@
173+/* File generated by Qt Creator (with Ubuntu Plugin), version 2.7.1 */
174+
175+import QmlProject 1.1
176+
177+Project {
178+ mainFile: "calculator.qml"
179+
180+ /* Include .qml, .js, and image files from current directory and subdirectories */
181+ QmlFiles {
182+ directory: "."
183+ }
184+ JavaScriptFiles {
185+ directory: "."
186+ }
187+ ImageFiles {
188+ directory: "."
189+ }
190+ Files {
191+ filter: "*.desktop"
192+ }
193+ Files {
194+ directory: "html"
195+ filter: "*"
196+ }
197+ Files {
198+ directory: "debian"
199+ filter: "*"
200+ }
201+ /* List of plugin directories passed to QML runtime */
202+ importPaths: [ "." ,"/usr/bin","/usr/lib/*/qt5/qml" ]
203+}
204
205=== added directory 'examples/calculator/components'
206=== added file 'examples/calculator/components/DefaultLayout.qml'
207--- examples/calculator/components/DefaultLayout.qml 1970-01-01 00:00:00 +0000
208+++ examples/calculator/components/DefaultLayout.qml 2013-07-03 06:43:28 +0000
209@@ -0,0 +1,100 @@
210+/*
211+ * Copyright 2013 Canonical Ltd.
212+ *
213+ * This program is free software; you can redistribute it and/or modify
214+ * it under the terms of the GNU Lesser General Public License as published by
215+ * the Free Software Foundation; version 3.
216+ *
217+ * This program is distributed in the hope that it will be useful,
218+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
219+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
220+ * GNU Lesser General Public License for more details.
221+ *
222+ * You should have received a copy of the GNU Lesser General Public License
223+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
224+ *
225+ * Author: Zsombor Egri <zsombor.egri@canonical.com>
226+ */
227+
228+import QtQuick 2.0
229+import Ubuntu.Components 0.1
230+import Ubuntu.Layouts 0.1
231+
232+Item {
233+ id: buttonGrid
234+ Layouts.item: "buttons"
235+
236+ property real spacing: units.gu(0.5)
237+ property real buttonHeight: (buttonGrid.height - 5 * buttonGrid.spacing) / 6
238+ property real buttonWidth: (buttonGrid.width - 3 * buttonGrid.spacing) / 4
239+
240+ property var operations
241+
242+ property var __model: [
243+ {"label": "mc", "color": "darkgray", "width" : buttonWidth, "height": buttonHeight},
244+ {"label": "m+", "color": "darkgray", "width" : buttonWidth, "height": buttonHeight},
245+ {"label": "m-", "color": "darkgray", "width" : buttonWidth, "height": buttonHeight},
246+ {"label": "mr", "color": "darkgray", "width" : buttonWidth, "height": buttonHeight},
247+
248+ {"label": "c", "color": "brown", "width" : buttonWidth, "height": buttonHeight},
249+ {"label": "+/-", "color": "brown", "width" : buttonWidth, "height": buttonHeight},
250+ {"label": "/", "color": "brown", "width" : buttonWidth, "height": buttonHeight},
251+ {"label": "*", "color": "brown", "width" : buttonWidth, "height": buttonHeight},
252+
253+ {"label": "7", "color": "#5f5f5f", "width" : buttonWidth, "height": buttonHeight},
254+ {"label": "8", "color": "#5f5f5f", "width" : buttonWidth, "height": buttonHeight},
255+ {"label": "9", "color": "#5f5f5f", "width" : buttonWidth, "height": buttonHeight},
256+ {"label": "-", "color": "brown", "width" : buttonWidth, "height": buttonHeight},
257+
258+ {"label": "4", "color": "#5f5f5f", "width" : buttonWidth, "height": buttonHeight},
259+ {"label": "5", "color": "#5f5f5f", "width" : buttonWidth, "height": buttonHeight},
260+ {"label": "6", "color": "#5f5f5f", "width" : buttonWidth, "height": buttonHeight},
261+ {"label": "+", "color": "brown", "width" : buttonWidth, "height": buttonHeight},
262+
263+ {"label": "1", "color": "#5f5f5f", "width" : buttonWidth, "height": buttonHeight},
264+ {"label": "2", "color": "#5f5f5f", "width" : buttonWidth, "height": buttonHeight},
265+ {"label": "3", "color": "#5f5f5f", "width" : buttonWidth, "height": buttonHeight},
266+ {"label": "=", "color": "orange", "width" : buttonWidth, "height": buttonHeight * 2 + spacing},
267+ ]
268+ property var __lastRow: [
269+ {"label": "0", "color": "#5f5f5f", "width" : 2 * buttonWidth + spacing, "height": buttonHeight},
270+ {"label": ".", "color": "#5f5f5f", "width" : buttonWidth, "height": buttonHeight},
271+ ]
272+ Grid {
273+ id: grid
274+ spacing: buttonGrid.spacing
275+ anchors.fill: parent
276+
277+ // memory
278+ Repeater {
279+ model: __model
280+ delegate: Button {
281+ text: modelData.label
282+ color: modelData.color
283+ width: modelData.width
284+ height: modelData.height
285+ onClicked: operations.execute(modelData.label)
286+ }
287+ }
288+ }
289+ Row {
290+ anchors{
291+ top: grid.bottom
292+ topMargin: -buttonHeight
293+ }
294+
295+ spacing: buttonGrid.spacing
296+
297+ // memory
298+ Repeater {
299+ model: __lastRow
300+ delegate: Button {
301+ text: modelData.label
302+ color: modelData.color
303+ width: modelData.width
304+ height: modelData.height
305+ onClicked: operations.execute(modelData.label)
306+ }
307+ }
308+ }
309+}
310
311=== added file 'examples/calculator/components/Functions.qml'
312--- examples/calculator/components/Functions.qml 1970-01-01 00:00:00 +0000
313+++ examples/calculator/components/Functions.qml 2013-07-03 06:43:28 +0000
314@@ -0,0 +1,46 @@
315+/*
316+ * Copyright 2013 Canonical Ltd.
317+ *
318+ * This program is free software; you can redistribute it and/or modify
319+ * it under the terms of the GNU Lesser General Public License as published by
320+ * the Free Software Foundation; version 3.
321+ *
322+ * This program is distributed in the hope that it will be useful,
323+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
324+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
325+ * GNU Lesser General Public License for more details.
326+ *
327+ * You should have received a copy of the GNU Lesser General Public License
328+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
329+ *
330+ * Author: Zsombor Egri <zsombor.egri@canonical.com>
331+ */
332+
333+import QtQuick 2.0
334+import Ubuntu.Components 0.1
335+import Ubuntu.Layouts 0.1
336+
337+Grid {
338+ id: buttonGrid
339+ columns: 4
340+ rows: 7
341+ spacing: units.gu(1)
342+
343+ property var operations
344+
345+ Repeater {
346+ model: [
347+ "%", "1/x", "x!", "x^2",
348+ "x^3", "x^y", "2^x", "sqrt",
349+ "ln", "e^x", "sin()", "cos()",
350+ "tan()", "cot()", "sec()", "csc()",
351+ ]
352+ delegate: Button {
353+ text: modelData
354+ width: (buttonGrid.width - 3 * buttonGrid.spacing) / 4
355+ height: (buttonGrid.height - 3 * buttonGrid.spacing) / 4
356+ onClicked: operations.execute(modelData)
357+ }
358+ }
359+
360+}
361
362=== added file 'examples/calculator/components/calculator.js'
363--- examples/calculator/components/calculator.js 1970-01-01 00:00:00 +0000
364+++ examples/calculator/components/calculator.js 2013-07-03 06:43:28 +0000
365@@ -0,0 +1,219 @@
366+/*
367+ * Copyright 2013 Canonical Ltd.
368+ *
369+ * This program is free software; you can redistribute it and/or modify
370+ * it under the terms of the GNU Lesser General Public License as published by
371+ * the Free Software Foundation; version 3.
372+ *
373+ * This program is distributed in the hope that it will be useful,
374+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
375+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
376+ * GNU Lesser General Public License for more details.
377+ *
378+ * You should have received a copy of the GNU Lesser General Public License
379+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
380+ *
381+ * Author: Zsombor Egri <zsombor.egri@canonical.com>
382+ */
383+
384+.pragma library
385+
386+function Calculator(textInput, memoryIndicator) {
387+ var operationStage = 0; // 0-lvalue, 1-rvalue
388+ var lvalue = 0.0;
389+ var rvalue = 0.0;
390+ var lastOperation = -1;
391+ var memory = 0.0;
392+ var clearInputNext = true;
393+
394+ textInput.text = lvalue;
395+ memoryIndicator.visible = false;
396+
397+ function setValue(value) {
398+ if (operationStage === 0) {
399+ lvalue = parseFloat(value);
400+ return lvalue;
401+ } else if (operationStage === 1) {
402+ rvalue = parseFloat(value);
403+ return rvalue;
404+ }
405+ }
406+ function value() {
407+ return (operationStage === 0) ? lvalue : rvalue;
408+ }
409+
410+ function clear() {
411+ operationStage = 1;
412+ lvalue = rvalue = 0;
413+ lastOperation = -1;
414+ textInput.text = 0.0;
415+ }
416+ function memClear() {
417+ memory = 0;
418+ memoryIndicator.visible = false;
419+ }
420+ function memRecall() {
421+ if (memory <= 0)
422+ return;
423+ textInput.text = setValue(memory);
424+ }
425+ function memAdd() {
426+ memory += value();
427+ textInput.text = setValue(memory);
428+ memoryIndicator.visible = true;
429+ }
430+ function memDec() {
431+ memory -= value();
432+ textInput.text = setValue(memory);
433+ memoryIndicator.visible = true;
434+ }
435+
436+ // arythmetic functions
437+ function add() {
438+ lvalue += rvalue;
439+ }
440+ function dec() {
441+ lvalue -= rvalue;
442+ }
443+ function mul() {
444+ lvalue *= rvalue;
445+ }
446+ function div() {
447+ lvalue /= rvalue;
448+ }
449+
450+ function sign() {
451+ textInput.text = setValue(-value());
452+ }
453+
454+ function invert() {
455+ textInput.text = setValue(1/value());
456+ }
457+ function percent() {
458+ textInput.text = setValue(value() / 100);
459+ }
460+ function sqr() {
461+ textInput.text = setValue(Math.pow(value(), 2));
462+ }
463+ function cube() {
464+ textInput.text = setValue(Math.pow(value(), 3));
465+ }
466+ function power() {
467+ lvalue = Math.pow(lvalue, rvalue);
468+ }
469+ function powerOf2() {
470+ textInput.text = setValue(Math.pow(2, value()));
471+ }
472+ function factorial() {
473+ var rval = 1;
474+ for (var i = 2; i <= value(); i++) {
475+ rval *= i;
476+ }
477+ textInput.text = setValue(rval);
478+ }
479+ function sqrt() {
480+ textInput.text = setValue(Math.sqrt(value()));
481+ }
482+ function ln() {
483+ textInput.text = setValue(Math.log(value()));
484+ }
485+ function exp()
486+ {
487+ textInput.text = setValue(Math.exp(value()));
488+ }
489+ function sin() {
490+ textInput.text = setValue(Math.sin(value()));
491+ }
492+ function cos() {
493+ textInput.text = setValue(Math.cos(value()));
494+ }
495+ function tan() {
496+ textInput.text = setValue(Math.tan(value()));
497+ }
498+ function cot() {
499+ textInput.text = setValue(1/Math.tan(value()));
500+ }
501+ function sec() {
502+ textInput.text = setValue(1/Math.cos(value()));
503+ }
504+ function csc() {
505+ textInput.text = setValue(1/Math.sin(value()));
506+ }
507+
508+ var operations = [
509+ {code: "+", operationFunc: add},
510+ {code: "-", operationFunc: dec},
511+ {code: "*", operationFunc: mul},
512+ {code: "/", operationFunc: div},
513+
514+ {code: "+/-", controlFunc: sign},
515+ {code: "c", controlFunc: clear},
516+
517+ {code: "mc", controlFunc: memClear},
518+ {code: "mr", controlFunc: memRecall},
519+ {code: "m+", controlFunc: memAdd},
520+ {code: "m-", controlFunc: memDec},
521+
522+ {code: "%", controlFunc: percent},
523+ {code: "1/x", controlFunc: invert},
524+ {code: "x!", controlFunc: factorial},
525+ {code: "x^2", controlFunc: sqr},
526+ {code: "x^3", controlFunc: cube},
527+ {code: "x^y", operationFunc: power},
528+ {code: "2^x", controlFunc: powerOf2},
529+ {code: "sqrt", controlFunc: sqrt},
530+ {code: "ln", controlFunc: ln},
531+ {code: "e^x", controlFunc: exp},
532+ {code: "sin()", controlFunc: sin},
533+ {code: "cos()", controlFunc: cos},
534+ {code: "tan()", controlFunc: tan},
535+ {code: "cot()", controlFunc: cot},
536+ {code: "sec()", controlFunc: sec},
537+ {code: "csc()", controlFunc: csc},
538+
539+ ];
540+
541+ this.execute = function (operation) {
542+ if (operation === "=") {
543+ if (lastOperation > -1) {
544+ operations[lastOperation].operationFunc();
545+ textInput.text = lvalue;
546+ }
547+ operationStage = 0;
548+ clearInputNext = true;
549+ } else {
550+ for (var i = 0; i < operations.length; i++) {
551+ if (operations[i].code === operation) {
552+ if (operations[i].operationFunc) {
553+ clearInputNext = true;
554+ if (operations[i].singleOp) {
555+ operations[i].operationFunc();
556+ return;
557+ }
558+
559+ lastOperation = i;
560+ if (operationStage === 0) {
561+ operationStage = 1;
562+ } else if (operationStage === 1) {
563+ // evaluate and continue receiving rvalue
564+ operations[i].operationFunc(lvalue, rvalue);
565+ textInput.text = lvalue;
566+ }
567+ } else if (operations[i].controlFunc) {
568+ operations[i].controlFunc();
569+ clearInputNext = true;
570+ }
571+
572+ return;
573+ }
574+ }
575+
576+ // if no opeartion was performed, add operation to input
577+ if (clearInputNext) {
578+ clearInputNext = false;
579+ textInput.text = "";
580+ }
581+ textInput.text = setValue(textInput.text + operation);
582+ }
583+ }
584+}
585
586=== modified file 'examples/examples.pro'
587--- examples/examples.pro 2013-06-26 22:55:34 +0000
588+++ examples/examples.pro 2013-07-03 06:43:28 +0000
589@@ -4,7 +4,8 @@
590 ubuntu-ui-toolkit-gallery\
591 jokes \
592 locale \
593- unit-converter
594+ unit-converter \
595+ calculator
596
597
598 #examples = jokes unit-converter

Subscribers

People subscribed via source and target branches

to status/vote changes: