Merge lp:~hiroshidi/ubuntu-terminal-app/app-rev200513 into lp:ubuntu-terminal-app

Proposed by Dmitry Zagnoyko
Status: Merged
Approved by: Michael Hall
Approved revision: 8
Merged at revision: 8
Proposed branch: lp:~hiroshidi/ubuntu-terminal-app/app-rev200513
Merge into: lp:ubuntu-terminal-app
Diff against target: 600 lines (+366/-186)
4 files modified
Terminal.qml (+137/-186)
debian/changelog (+9/-0)
extraPanel/CircleMenu.qml (+219/-0)
ubuntu-terminal-app.qml (+1/-0)
To merge this branch: bzr merge lp:~hiroshidi/ubuntu-terminal-app/app-rev200513
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Michael Hall Approve
Review via email: mp+164726@code.launchpad.net

Commit message

Version bump (0.4):
- KTerminal widget uses only available space (no scrolling)
- widged scrolling replaced with improved swipe gestures
- added double tap for autocomplete
- added circle menu on long tap (currently - ctrl+<key>)

Description of the change

REMOVED Flickable Item to fill only the available space by KTerminal item. This means is no scrolling!

Swipe gestures will be used instead of removed scrolling to provide up/down/left/right keys events with according swipes.

Double tap is used for autocomplete (analogue of TAB key).

Long tap will be used for circle menu instead of switching swipe mode.

Circle Menu has some issue with shaders on device, but works. At current revision it provide quick access to CTRL+<key> shortcuts.

To post a comment you must log in.
Revision history for this message
Michael Hall (mhall119) wrote :

The Circle Menu looks cool, but it might be more "Ubuntu-like" to use one of the SDK's Popup component like Popover, to display a list of options.

http://developer.ubuntu.com/api/ubuntu-12.10/qml/mobile/qml-ubuntu-components-popups0-popover.html

review: Approve
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Terminal.qml'
2--- Terminal.qml 2013-05-06 19:03:02 +0000
3+++ Terminal.qml 2013-05-20 13:51:29 +0000
4@@ -9,6 +9,10 @@
5 height: Qt.inputMethod.visible ? parent.height - Qt.inputMethod.keyboardRectangle.height : parent.height
6 width: parent.width
7
8+ onHeightChanged: {
9+ screenRow.vheight = height
10+ }
11+
12 //property int headerHeight: units.gu(10);
13
14 function showExtraPanel(i){
15@@ -49,57 +53,6 @@
16
17 JsConfig{id: jsConf }
18
19- Timer {
20- id: tiInformal
21- repeat: false
22- interval: 5*1000
23-
24- onTriggered: {
25- usInformal.visible = false
26- lbInformal.visible = false
27- }
28- }
29-
30- UbuntuShape {
31- id: usInformal
32- visible: false
33- z: 98
34- width: lbInformal.width + units.gu(2)
35- height: lbInformal.height + units.gu(2)
36- color: "lightgrey"
37- anchors{
38- bottom: parent.bottom
39- bottomMargin: units.gu(2)
40- horizontalCenter: parent.horizontalCenter
41- }
42-
43- NumberAnimation on opacity {
44- running: usInformal.visible;
45- from: 0.6
46- to: 0;
47- duration: tiInformal.interval
48- }
49- }
50-
51- Label {
52- id: lbInformal
53- visible: false
54- z: 99
55- anchors{
56- bottom: parent.bottom
57- bottomMargin: units.gu(3)
58- horizontalCenter: parent.horizontalCenter
59- }
60- color: "white"
61- text: "Normal mode"
62-
63- NumberAnimation on opacity {
64- running: lbInformal.visible;
65- from: 1
66- to: 0;
67- duration: tiInformal.interval
68- }
69- }
70
71 Column {
72 id: mcol
73@@ -168,141 +121,139 @@
74 property real shift: 0
75 property real vheight: parent.height
76
77- Flickable {
78- id: flickable
79- height: parent.height
80- width: parent.width
81- contentHeight: kterm.height
82- contentWidth: kterm.width
83- clip: true
84-
85- onHeightChanged: {
86- console.log("flickable.height = " + height)
87- }
88-
89- Item {
90- width: units.gu(100)
91- height: mparent.height
92-
93- KTerminal {
94- id: kterm
95-
96- //////////////////////////////////////
97- /// FONT SIZE = 24 (FINE FOR GNEXUS)
98- /// FONT SIZE = 12 (FINE FOR DESKTOP)
99- //////////////////////////////////////
100- font.family: "Ubuntu Mono"
101- font.pointSize: jsConf.getFontSize() //units.gu(1.5)
102-
103- colorScheme: jsConf.getColorSheme() //"DarkPastels"
104- width: parent.width
105- height: parent.height
106-
107- session: KSession {
108- id: ksession
109- kbScheme: "linux"
110- }
111- }
112-
113- MouseArea {
114- anchors.fill: parent
115- enabled: true
116- preventStealing: false
117-
118- property int cPosX: 0
119- property int cPosY: 0
120-
121- property int prevPosX: 0
122- property int prevPosY: 0
123-
124- property bool axisX: true
125- property bool grab: false
126- property bool fixedAxis: false
127-
128- onPreventStealingChanged: {
129- if (preventStealing) {
130- lbInformal.text = "Control mode"
131- usInformal.color = "green"
132- usInformal.visible = true
133- lbInformal.visible = true
134- tiInformal.start()
135- }
136- else {
137- lbInformal.text = "Normal mode"
138- usInformal.color = "lightgrey"
139- usInformal.visible = true
140- lbInformal.visible = true
141- tiInformal.start()
142- }
143- }
144-
145- onClicked: {
146- prevPosX = cPosX = mouse.x;
147- prevPosY = cPosY = mouse.y;
148-
149- kterm.click(mouse.x,mouse.y);
150- grab = true;
151- fixedAxis = false
152- }
153-
154- onPressAndHold: {
155- if (grab) {
156- preventStealing = !preventStealing;
157- grab = false;
158- }
159- }
160-
161- onPositionChanged: {
162- grab = false;
163-
164- var dX = prevPosX - mouse.x;
165- var dY = prevPosY - mouse.y;
166- var sens = 10;
167-
168- if (!fixedAxis) {
169- axisX = Math.abs(dX)/sens > Math.abs(dY)/sens;
170- fixedAxis = true;
171- }
172-
173- if (preventStealing) {
174-
175- if (axisX && dX > 0) {
176- ksession.sendKey(1, Qt.Key_Left, Qt.NoModifier)
177- //console.log("dltX = " + prevPosX + " - " + mouse.x);
178- }
179- else if (axisX && dX < 0) {
180- ksession.sendKey(1, Qt.Key_Right, Qt.NoModifier)
181- //console.log("dltX = " + prevPosX + " - " + mouse.x);
182- }
183-
184- if (!axisX && dY > 0) {
185- ksession.sendKey(1, Qt.Key_Up, Qt.NoModifier)
186- //console.log("dltY = " + prevPosY + " - " + mouse.y);
187- }
188- else if (!axisX && dY < 0) {
189- ksession.sendKey(1, Qt.Key_Down, Qt.NoModifier)
190- //console.log("dltY = " + prevPosY + " - " + mouse.y);
191- }
192-
193- prevPosX = mouse.x;
194- prevPosY = mouse.y;
195-
196- }
197- }
198- }
199-
200- }
201-
202- }
203-
204- Scrollbar {
205- flickableItem: flickable
206- align: Qt.AlignTrailing
207- }
208- Scrollbar {
209- flickableItem: flickable
210- align: Qt.AlignBottom
211- }
212+ //...
213+
214+ Item {
215+ anchors.fill: parent
216+
217+ CircleMenu {
218+ id: cmenu
219+ z: 99
220+ visible: false
221+ anchors.centerIn: parent
222+ circleButtonLable: "CTRL +"
223+ sideButtons: ["A", "C", "D", "S", "X", "Z"]
224+
225+ //onOutsideClicked: visible = false;
226+ onCircleButtonClicked: console.log("Circle button clicked")
227+ onSideButtonClicked: {
228+ switch (index) {
229+ case 0:
230+ // CTRL+A
231+ ksession.sendKey(1, Qt.Key_A, Qt.ControlModifier);
232+ break;
233+ case 1:
234+ // CTRL+C
235+ ksession.sendKey(1, Qt.Key_C, Qt.ControlModifier);
236+ break
237+ case 2:
238+ // CTRL+D
239+ ksession.sendKey(1, Qt.Key_D, Qt.ControlModifier);
240+ break
241+ case 3:
242+ // CTRL+S
243+ ksession.sendKey(1, Qt.Key_S, Qt.ControlModifier);
244+ break
245+ case 4:
246+ // CTRL+X
247+ ksession.sendKey(1, Qt.Key_X, Qt.ControlModifier);
248+ break
249+ case 5:
250+ // CTRL+Z
251+ ksession.sendKey(1, Qt.Key_Z, Qt.ControlModifier);
252+ break
253+ }
254+ }
255+ }
256+
257+ KTerminal {
258+ id: kterm
259+
260+ //////////////////////////////////////
261+ /// FONT SIZE = 24 (FINE FOR GNEXUS)
262+ /// FONT SIZE = 12 (FINE FOR DESKTOP)
263+ //////////////////////////////////////
264+ font.family: "Ubuntu Mono"
265+ font.pointSize: jsConf.getFontSize() //units.gu(1.5)
266+
267+ colorScheme: jsConf.getColorSheme() //"DarkPastels"
268+ width: parent.width
269+ height: parent.height
270+
271+ session: KSession {
272+ id: ksession
273+ kbScheme: "linux"
274+ }
275+ }
276+
277+ MouseArea {
278+ anchors.fill: parent
279+ enabled: true
280+ //preventStealing: false
281+
282+ property int cPosX: 0
283+ property int cPosY: 0
284+
285+ property int prevPosX: 0
286+ property int prevPosY: 0
287+
288+ property bool swiped: false
289+
290+ onPressed: {
291+ prevPosX = cPosX = mouse.x;
292+ prevPosY = cPosY = mouse.y;
293+
294+ kterm.click(mouse.x,mouse.y);
295+
296+ if (cmenu.visible) cmenu.visible = false;
297+ }
298+
299+ onReleased: {
300+ swiped = false;
301+ }
302+
303+ onDoubleClicked: {
304+ ksession.sendKey(1, Qt.Key_Tab, Qt.NoModifier)
305+ }
306+
307+ onPressAndHold: {
308+ if (!swiped) cmenu.visible = true;
309+ }
310+
311+ onPositionChanged: {
312+ var dltX = mouse.x - prevPosX;
313+ var dltY = mouse.y - prevPosY;
314+ var s1 = 50;
315+ var s2 = 30;
316+
317+ if (Math.abs(dltX) > s1 || Math.abs(dltY) > s1) {
318+
319+ swiped = true;
320+
321+ if (dltX > s2 && Math.abs(dltY) < s2) {
322+ // swipe right
323+ ksession.sendKey(1, Qt.Key_Right, Qt.NoModifier)
324+ } else if (dltX < -s2 && Math.abs(dltY) < s2) {
325+ // swipe left
326+ ksession.sendKey(1, Qt.Key_Left, Qt.NoModifier)
327+ } else if (Math.abs(dltX) < s2 && dltY > s2) {
328+ // swipe down
329+ ksession.sendKey(1, Qt.Key_Down, Qt.NoModifier)
330+ } else if (Math.abs(dltX) < s2 && dltY < s2) {
331+ // swipe up
332+ ksession.sendKey(1, Qt.Key_Up, Qt.NoModifier)
333+ }
334+
335+ prevPosX = mouse.x;
336+ prevPosY = mouse.y;
337+ }
338+
339+ }
340+ }
341+
342+ }
343+
344+ //...
345
346 }
347
348
349=== modified file 'debian/changelog'
350--- debian/changelog 2013-05-06 21:20:44 +0000
351+++ debian/changelog 2013-05-20 13:51:29 +0000
352@@ -1,3 +1,12 @@
353+ubuntu-terminal-app (0.4) raring; urgency=low
354+
355+ * Widget uses only available space
356+ * Widget scrolling replaced with swipe gestures
357+ * Added double tap for autocomplete
358+ * Added circle menu (test ver., aliases for CTRL+<key>)
359+
360+ -- Dmitry Zagnoyko <hiroshidi@gmail.com> Mon, 20 May 2013 12:52:01 +0300
361+
362 ubuntu-terminal-app (0.3) raring; urgency=low
363
364 * Added swipe gesture
365
366=== added file 'extraPanel/CircleMenu.qml'
367--- extraPanel/CircleMenu.qml 1970-01-01 00:00:00 +0000
368+++ extraPanel/CircleMenu.qml 2013-05-20 13:51:29 +0000
369@@ -0,0 +1,219 @@
370+import QtQuick 2.0
371+import Ubuntu.Components 0.1
372+
373+Item {
374+ id: mparent
375+ height: units.gu(30)
376+ width: units.gu(30)
377+
378+ property variant sideButtons: [ "1", "2", "3", "4" ]
379+ property alias circleButtonLable: lbCircle.text
380+
381+ signal sideButtonClicked( int index)
382+ signal circleButtonClicked
383+ //signal outsideClicked
384+
385+ //onSideButtonClicked: console.log("Clicked segment " + (index+1));
386+
387+ Repeater {
388+ model: sideButtons.length/2
389+ delegate: Rectangle {
390+ width: btnTorus.radius*2
391+ height: units.gu(0.25)
392+ color: "grey"
393+ x: 0
394+ y: btnTorus.radius - height/2
395+ rotation: (index * marea.anglePerSegment + marea.anglePerSegment/2) * 180 / Math.PI
396+ z: 89
397+ }
398+ }
399+
400+ Repeater {
401+ id: btnSider
402+ model: sideButtons.length
403+ delegate: Rectangle {
404+ width: 30
405+ height: 30
406+ color: "transparent"
407+ x: parent.width / 2 + ( btnTorus.radius - units.gu(4)) *
408+ Math.cos(index * marea.anglePerSegment ) - width/2;
409+ y: parent.height / 2 - ( btnTorus.radius - units.gu(4)) *
410+ Math.sin(index * marea.anglePerSegment ) - height/2;
411+ z: 90
412+
413+ Label {
414+ //color: "black"
415+ fontSize: "large"
416+ anchors.centerIn: parent
417+ text: sideButtons[index]
418+ }
419+
420+ }
421+ }
422+
423+ Rectangle {
424+ id: btnTorus
425+ anchors.fill: parent
426+ radius: width/2
427+ color: "lightgrey"
428+ }
429+
430+ // For some reason won't works proper on device
431+ // Works perfect on PC
432+ ShaderEffect{
433+ id: effect
434+ anchors.fill: parent
435+
436+ property real anglePerSegment: (2 * Math.PI) / sideButtons.length
437+ property real selSegment: -1
438+ property real segCount: sideButtons.length
439+ property real pi: Math.PI
440+ property real r: 1 //units.gu(1)
441+ property color color: "#85838388"
442+
443+ property variant source: ShaderEffectSource {
444+ sourceItem: btnTorus;
445+ hideSource: true
446+ }
447+
448+ fragmentShader:
449+ "varying highp vec2 qt_TexCoord0;
450+ uniform sampler2D source;
451+
452+ uniform highp float anglePerSegment;
453+ uniform highp float selSegment;
454+ uniform highp float segCount;
455+ uniform highp vec4 color;
456+ uniform highp float pi;
457+ uniform highp float r;
458+
459+ void main(void)
460+ {
461+ highp float a = 0.0;
462+
463+ if (qt_TexCoord0.x != 0.0 || qt_TexCoord0.y != 0.0) {
464+ a = atan((-1.0)*(qt_TexCoord0.y - r*0.5), qt_TexCoord0.x - r*0.5);
465+ if (a < 0.0) a = 2.0 * pi + a;
466+ }
467+
468+ if ( selSegment >= 0.0 ) {
469+ if ( ( ( selSegment * anglePerSegment - anglePerSegment*0.5 ) < a &&
470+ ( (selSegment + 1.0) * anglePerSegment - anglePerSegment*0.5) > a ) ||
471+ ( selSegment == 0.0 && ( segCount * anglePerSegment - anglePerSegment*0.5 ) < a &&
472+ ( (segCount + 1.0) * anglePerSegment - anglePerSegment*0.5) > a ) )
473+ {
474+ gl_FragColor = color * texture2D(source, qt_TexCoord0);
475+ }
476+ else
477+ gl_FragColor = texture2D( source, qt_TexCoord0 );
478+ }
479+ else
480+ gl_FragColor = texture2D( source, qt_TexCoord0 );
481+
482+ }"
483+
484+ }
485+
486+ Rectangle {
487+ color: "grey"
488+ z: 91
489+ anchors{
490+ verticalCenter: parent.verticalCenter
491+ horizontalCenter: parent.horizontalCenter
492+ }
493+
494+ width: parent.width/2.5 + units.gu(0.5)
495+ height: width
496+ radius: width/2
497+ }
498+
499+ Rectangle {
500+ id: shdwCircle
501+ color: "#85838388"
502+ visible: false
503+ z: 93
504+ anchors{
505+ verticalCenter: parent.verticalCenter
506+ horizontalCenter: parent.horizontalCenter
507+ }
508+
509+ width: parent.width/2.5
510+ height: width
511+ radius: width/2
512+ }
513+
514+ Rectangle {
515+ id: btnCircle
516+ color: "lightgrey"
517+ z: 92
518+ anchors{
519+ verticalCenter: parent.verticalCenter
520+ horizontalCenter: parent.horizontalCenter
521+ }
522+
523+ width: parent.width/2.5
524+ height: width
525+ radius: width/2
526+
527+ Label {
528+ id: lbCircle
529+ //color: "black"
530+ fontSize: "large"
531+ anchors.centerIn: parent
532+ text: "Central"
533+ }
534+ }
535+
536+ MouseArea {
537+ id: marea
538+ z: 99
539+ preventStealing: true
540+ anchors.fill: parent
541+ enabled: mparent.visible
542+
543+ property real radius: btnTorus.width/2
544+ property real inner_radius: btnCircle.radius
545+ property real anglePerSegment: (2 * Math.PI) / sideButtons.length
546+
547+ onPressed: {
548+
549+ var x = mouse.x - radius;
550+ var y = mouse.y - radius;
551+ var a = Math.atan2(-y, x) < 0 ? 2*Math.PI + Math.atan2(-y, x) : Math.atan2(-y, x);
552+ var r = Math.sqrt( Math.pow(x, 2) + Math.pow(y, 2) );
553+
554+ if ( r < radius ) {
555+ if ( r > inner_radius ) {
556+ for (var i = 0; i < sideButtons.length; i++){
557+
558+ if ( ( (i * anglePerSegment - marea.anglePerSegment/2) < a &&
559+ ((i+1) * anglePerSegment - marea.anglePerSegment/2) > a ) ||
560+ (i == 0 && (sideButtons.length * anglePerSegment - marea.anglePerSegment/2) < a &&
561+ ((( sideButtons.length + 1 ) * anglePerSegment - marea.anglePerSegment/2) > a )))
562+ {
563+ effect.selSegment = i;
564+ sideButtonClicked(i);
565+ }
566+ }
567+ //console.log("Clicked inside torus")
568+ } else {
569+ shdwCircle.visible = true;
570+ circleButtonClicked();
571+ //console.log("Clicked inside inner circle")
572+ }
573+
574+ }
575+ else {
576+ //outsideClicked();
577+ mparent.visible = false;
578+ }
579+
580+ }
581+
582+ onReleased: {
583+ if (effect.selSegment != -1) effect.selSegment = -1;
584+ if (shdwCircle.visible) shdwCircle.visible = false;
585+ mparent.visible = false;
586+ }
587+ }
588+}
589
590=== modified file 'ubuntu-terminal-app.qml'
591--- ubuntu-terminal-app.qml 2013-05-06 19:03:02 +0000
592+++ ubuntu-terminal-app.qml 2013-05-20 13:51:29 +0000
593@@ -8,6 +8,7 @@
594 id: mview
595 objectName: "terminal"
596 applicationName: "ubuntu-terminal-app"
597+ //automaticOrientation: true
598
599 width: units.gu(50)
600 height: units.gu(75)

Subscribers

People subscribed via source and target branches