Merge lp:~hiroshidi/ubuntu-terminal-app/app-rev200513 into lp:ubuntu-terminal-app
- app-rev200513
- Merge into trunk
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 |
Related bugs: |
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
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) |
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