Merge lp:~fboucault/ubuntu-terminal-app/tiled_view into lp:ubuntu-terminal-app

Proposed by Florian Boucault
Status: Merged
Merged at revision: 325
Proposed branch: lp:~fboucault/ubuntu-terminal-app/tiled_view
Merge into: lp:ubuntu-terminal-app
Diff against target: 1857 lines (+1413/-150)
18 files modified
po/com.ubuntu.terminal.pot (+13/-5)
src/app/qml/AlternateActionPopover.qml (+14/-1)
src/app/qml/Settings/SettingsShortcutsSection.qml (+30/-0)
src/app/qml/TabsModel.qml (+6/-5)
src/app/qml/TabsPage.qml (+1/-1)
src/app/qml/Terminal.qml (+117/-4)
src/app/qml/TerminalPage.qml (+6/-127)
src/app/qml/TerminalSettings.qml (+12/-0)
src/app/qml/TerminalWindow.qml (+20/-5)
src/app/qml/TiledTerminalView.qml (+96/-0)
src/app/qml/TiledView.qml (+135/-0)
src/app/qml/TiledViewSeparator.qml (+76/-0)
src/app/qml/binarytree.js (+378/-0)
src/plugin/qmltermwidget/lib/TerminalDisplay.h (+2/-2)
tests/CMakeLists.txt (+1/-0)
tests/qtquicktest/CMakeLists.txt (+20/-0)
tests/qtquicktest/qtquicktest.cpp (+18/-0)
tests/qtquicktest/tst_TiledView.qml (+468/-0)
To merge this branch: bzr merge lp:~fboucault/ubuntu-terminal-app/tiled_view
Reviewer Review Type Date Requested Status
Ubuntu Terminal Developers Pending
Review via email: mp+314617@code.launchpad.net

Commit message

New feature: terminals can be organised as tiles.

Description of the change

New feature: terminals can be organised as tiles.

To post a comment you must log in.
333. By Florian Boucault

Added automated tests for tile resizing.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'po/com.ubuntu.terminal.pot'
--- po/com.ubuntu.terminal.pot 2017-01-06 08:39:01 +0000
+++ po/com.ubuntu.terminal.pot 2017-01-12 13:29:38 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: \n"9"Project-Id-Version: \n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2017-01-06 08:38+0000\n"11"POT-Creation-Date: 2017-01-12 14:17+0100\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -29,15 +29,23 @@
29msgid "Paste"29msgid "Paste"
30msgstr ""30msgstr ""
3131
32#: ../src/app/qml/AlternateActionPopover.qml:86 ../src/app/qml/TabsPage.qml:3232#: ../src/app/qml/AlternateActionPopover.qml:86
33msgid "Split horizontally"
34msgstr ""
35
36#: ../src/app/qml/AlternateActionPopover.qml:92
37msgid "Split vertically"
38msgstr ""
39
40#: ../src/app/qml/AlternateActionPopover.qml:99 ../src/app/qml/TabsPage.qml:32
33msgid "New tab"41msgid "New tab"
34msgstr ""42msgstr ""
3543
36#: ../src/app/qml/AlternateActionPopover.qml:9144#: ../src/app/qml/AlternateActionPopover.qml:104
37msgid "New window"45msgid "New window"
38msgstr ""46msgstr ""
3947
40#: ../src/app/qml/AlternateActionPopover.qml:9648#: ../src/app/qml/AlternateActionPopover.qml:109
41msgid "Close"49msgid "Close"
42msgstr ""50msgstr ""
4351
@@ -303,7 +311,7 @@
303msgid "Tabs"311msgid "Tabs"
304msgstr ""312msgstr ""
305313
306#: ../src/app/qml/TerminalPage.qml:252314#: ../src/app/qml/TerminalPage.qml:132
307msgid "Selection Mode"315msgid "Selection Mode"
308msgstr ""316msgstr ""
309317
310318
=== modified file 'src/app/qml/AlternateActionPopover.qml'
--- src/app/qml/AlternateActionPopover.qml 2017-01-06 08:38:45 +0000
+++ src/app/qml/AlternateActionPopover.qml 2017-01-12 13:29:38 +0000
@@ -83,6 +83,19 @@
83 property bool divider: true83 property bool divider: true
84 }84 }
85 Action {85 Action {
86 text: i18n.tr("Split horizontally")
87 onTriggered: tiledTerminalView.splitTerminal(terminal, Qt.Vertical)
88 shortcut: settings.shortcutSplitHorizontally
89 enabled: terminal.height >= 2 * tiledTerminalView.minimumTileHeight
90 }
91 Action {
92 text: i18n.tr("Split vertically")
93 onTriggered: tiledTerminalView.splitTerminal(terminal, Qt.Horizontal)
94 shortcut: settings.shortcutSplitVertically
95 enabled: terminal.width >= 2 * tiledTerminalView.minimumTileWidth
96 property bool divider: true
97 }
98 Action {
86 text: i18n.tr("New tab")99 text: i18n.tr("New tab")
87 onTriggered: tabsModel.addTerminalTab()100 onTriggered: tabsModel.addTerminalTab()
88 shortcut: settings.shortcutNewTab101 shortcut: settings.shortcutNewTab
@@ -94,7 +107,7 @@
94 }107 }
95 Action {108 Action {
96 text: i18n.tr("Close")109 text: i18n.tr("Close")
97 onTriggered: tabsModel.removeItem(tabsModel.indexOf(tabsModel.currentItem))110 onTriggered: terminal.finished()
98 shortcut: settings.shortcutCloseTab111 shortcut: settings.shortcutCloseTab
99 }112 }
100 }113 }
101114
=== modified file 'src/app/qml/Settings/SettingsShortcutsSection.qml'
--- src/app/qml/Settings/SettingsShortcutsSection.qml 2016-11-30 22:56:25 +0000
+++ src/app/qml/Settings/SettingsShortcutsSection.qml 2017-01-12 13:29:38 +0000
@@ -186,6 +186,36 @@
186 actionLabel: QT_TR_NOOP("Toggle fullscreen")186 actionLabel: QT_TR_NOOP("Toggle fullscreen")
187 shortcutSetting: "shortcutFullscreen"187 shortcutSetting: "shortcutFullscreen"
188 }188 }
189 ListElement {
190 section: QT_TR_NOOP("View")
191 actionLabel: QT_TR_NOOP("Split terminal horizontally")
192 shortcutSetting: "shortcutSplitHorizontally"
193 }
194 ListElement {
195 section: QT_TR_NOOP("View")
196 actionLabel: QT_TR_NOOP("Split terminal vertically")
197 shortcutSetting: "shortcutSplitVertically"
198 }
199 ListElement {
200 section: QT_TR_NOOP("View")
201 actionLabel: QT_TR_NOOP("Navigate to terminal above")
202 shortcutSetting: "shortcutMoveToTileAbove"
203 }
204 ListElement {
205 section: QT_TR_NOOP("View")
206 actionLabel: QT_TR_NOOP("Navigate to terminal below")
207 shortcutSetting: "shortcutMoveToTileBelow"
208 }
209 ListElement {
210 section: QT_TR_NOOP("View")
211 actionLabel: QT_TR_NOOP("Navigate to terminal on the left")
212 shortcutSetting: "shortcutMoveToTileLeft"
213 }
214 ListElement {
215 section: QT_TR_NOOP("View")
216 actionLabel: QT_TR_NOOP("Navigate to terminal on the right")
217 shortcutSetting: "shortcutMoveToTileRight"
218 }
189 }219 }
190220
191 delegate: ShortcutRow {221 delegate: ShortcutRow {
192222
=== modified file 'src/app/qml/TabsModel.qml'
--- src/app/qml/TabsModel.qml 2016-12-12 21:18:17 +0000
+++ src/app/qml/TabsModel.qml 2017-01-12 13:29:38 +0000
@@ -34,17 +34,18 @@
34 moveItem(from, to);34 moveItem(from, to);
35 }35 }
3636
37 property Component terminalComponent: TerminalComponent {}37 property Component tiledViewComponent: TiledTerminalView {}
3838
39 function addTerminalTab(initialWorkingDirectory) {39 function addTerminalTab(initialWorkingDirectory) {
40 if (currentItem) {40 if (currentItem) {
41 initialWorkingDirectory = currentItem.session.getWorkingDirectory();41 initialWorkingDirectory = currentItem.focusedTerminal.session.getWorkingDirectory();
42 }42 }
4343
44 var termObject = terminalComponent.createObject(terminalPage.terminalContainer,44 var tiledView = tiledViewComponent.createObject(terminalPage.terminalContainer,
45 {"initialWorkingDirectory": initialWorkingDirectory,45 {"initialWorkingDirectory": initialWorkingDirectory,
46 "visible": Qt.binding(function () { return tabsModel.currentItem === termObject})});46 "visible": Qt.binding(function () { return tabsModel.currentItem === tiledView})});
47 tabsModel.addItem(termObject);47 tiledView.emptied.connect(function () {tabsModel.removeItem(tabsModel.indexOf(tiledView));})
48 tabsModel.addItem(tiledView);
48 currentIndex = tabsModel.count - 1;49 currentIndex = tabsModel.count - 1;
49 }50 }
5051
5152
=== modified file 'src/app/qml/TabsPage.qml'
--- src/app/qml/TabsPage.qml 2016-12-12 12:44:22 +0000
+++ src/app/qml/TabsPage.qml 2017-01-12 13:29:38 +0000
@@ -103,7 +103,7 @@
103 Label {103 Label {
104 anchors { fill: blackRect; margins: units.dp(2) }104 anchors { fill: blackRect; margins: units.dp(2) }
105 property var tab: tabsModel.itemAt(index)105 property var tab: tabsModel.itemAt(index)
106 text: tab ? tab.session.title : ""106 text: tab && tab.focusedTerminal ? tab.focusedTerminal.session.title : ""
107 wrapMode: Text.Wrap107 wrapMode: Text.Wrap
108 color: "white"108 color: "white"
109 }109 }
110110
=== renamed file 'src/app/qml/TerminalComponent.qml' => 'src/app/qml/Terminal.qml'
--- src/app/qml/TerminalComponent.qml 2016-12-12 12:44:22 +0000
+++ src/app/qml/Terminal.qml 2017-01-12 13:29:38 +0000
@@ -17,20 +17,21 @@
17 */17 */
18import QtQuick 2.418import QtQuick 2.4
19import Ubuntu.Components 1.319import Ubuntu.Components 1.3
20import Ubuntu.Components.Popups 1.3
20import QMLTermWidget 1.021import QMLTermWidget 1.0
21import Terminal 0.122import Terminal 0.1
2223
23QMLTermWidget {24QMLTermWidget {
24 id: terminal25 id: terminal
25 width: parent.width
26 height: parent.height
2726
28 colorScheme: settings.colorScheme27 colorScheme: settings.colorScheme
29 font.family: settings.fontStyle28 font.family: settings.fontStyle
30 font.pixelSize: FontUtils.sizeToPixels("medium") * settings.fontSize / 1029 font.pixelSize: FontUtils.sizeToPixels("medium") * settings.fontSize / 10
3130
31 property bool isDarkBackground: ColorUtils.luminance(backgroundColor) <= 0.85
32 property color contourColor: isDarkBackground ? Qt.rgba(1.0, 1.0, 1.0, 0.4) : Qt.rgba(0.0, 0.0, 0.0, 0.2)
32 property string initialWorkingDirectory33 property string initialWorkingDirectory
33 signal sessionFinished(var session);34 signal finished()
3435
35 session: QMLTermSession {36 session: QMLTermSession {
36 id: terminalSession37 id: terminalSession
@@ -68,7 +69,7 @@
68 "-o", "LogLevel=Error",69 "-o", "LogLevel=Error",
69 "mkdir -p `dirname %1`; echo -n $$ > %1; cd %2; bash".arg(sshShellPidFile).arg(initialWorkingDirectory)]70 "mkdir -p `dirname %1`; echo -n $$ > %1; cd %2; bash".arg(sshShellPidFile).arg(initialWorkingDirectory)]
70 : [])71 : [])
71 onFinished: tabsModel.removeItem(tabsModel.indexOf(terminal))72 onFinished: terminal.finished()
72 }73 }
7374
74 property int totalLines: terminal.scrollbarMaximum - terminal.scrollbarMinimum + terminal.lines75 property int totalLines: terminal.scrollbarMaximum - terminal.scrollbarMinimum + terminal.lines
@@ -77,4 +78,116 @@
77 terminalSession.startShellProgram();78 terminalSession.startShellProgram();
78 forceActiveFocus();79 forceActiveFocus();
79 }80 }
81
82 // TODO: This invisible button is used to position the popover where the
83 // alternate action was called. Terrible terrible workaround!
84 Item {
85 id: hiddenButton
86 width: 1
87 height: 1
88 visible: false
89 enabled: false
90 }
91
92 TerminalInputArea {
93 id: inputArea
94 enabled: terminalPage.state != "SELECTION"
95 anchors.fill: parent
96 // FIXME: should anchor to the bottom of the window to cater for the case when the OSK is up
97
98 // This is the minimum wheel event registered by the plugin (with the current settings).
99 property real wheelValue: 40
100
101 // This is needed to fake a "flickable" scrolling.
102 swipeDelta: terminal.fontMetrics.height
103
104 // Mouse actions
105 onMouseMoveDetected: terminal.simulateMouseMove(x, y, button, buttons, modifiers);
106 onDoubleClickDetected: terminal.simulateMouseDoubleClick(x, y, button, buttons, modifiers);
107 onMousePressDetected: {
108 terminal.forceActiveFocus();
109 terminal.simulateMousePress(x, y, button, buttons, modifiers);
110 }
111 onMouseReleaseDetected: terminal.simulateMouseRelease(x, y, button, buttons, modifiers);
112 onMouseWheelDetected: terminal.simulateWheel(x, y, buttons, modifiers, angleDelta);
113
114 // Touch actions
115 onTouchPress: terminal.forceActiveFocus()
116 onTouchClick: terminal.simulateKeyPress(Qt.Key_Tab, Qt.NoModifier, true, 0, "");
117 onTouchPressAndHold: alternateAction(x, y);
118
119 // Swipe actions
120 onSwipeYDetected: {
121 if (steps > 0) {
122 simulateSwipeDown(steps);
123 } else {
124 simulateSwipeUp(-steps);
125 }
126 }
127 onSwipeXDetected: {
128 if (steps > 0) {
129 simulateSwipeRight(steps);
130 } else {
131 simulateSwipeLeft(-steps);
132 }
133 }
134 onTwoFingerSwipeYDetected: {
135 if (steps > 0) {
136 simulateDualSwipeDown(steps);
137 } else {
138 simulateDualSwipeUp(-steps);
139 }
140 }
141
142 function simulateSwipeUp(steps) {
143 while(steps > 0) {
144 terminal.simulateKeyPress(Qt.Key_Up, Qt.NoModifier, true, 0, "");
145 steps--;
146 }
147 }
148 function simulateSwipeDown(steps) {
149 while(steps > 0) {
150 terminal.simulateKeyPress(Qt.Key_Down, Qt.NoModifier, true, 0, "");
151 steps--;
152 }
153 }
154 function simulateSwipeLeft(steps) {
155 while(steps > 0) {
156 terminal.simulateKeyPress(Qt.Key_Left, Qt.NoModifier, true, 0, "");
157 steps--;
158 }
159 }
160 function simulateSwipeRight(steps) {
161 while(steps > 0) {
162 terminal.simulateKeyPress(Qt.Key_Right, Qt.NoModifier, true, 0, "");
163 steps--;
164 }
165 }
166 function simulateDualSwipeUp(steps) {
167 while(steps > 0) {
168 terminal.simulateWheel(width * 0.5, height * 0.5, Qt.NoButton, Qt.NoModifier, Qt.point(0, -wheelValue));
169 steps--;
170 }
171 }
172 function simulateDualSwipeDown(steps) {
173 while(steps > 0) {
174 terminal.simulateWheel(width * 0.5, height * 0.5, Qt.NoButton, Qt.NoModifier, Qt.point(0, wheelValue));
175 steps--;
176 }
177 }
178
179 // Semantic actions
180 onAlternateAction: {
181 // Force the hiddenButton in the event position.
182 hiddenButton.x = x;
183 hiddenButton.y = y;
184 PopupUtils.open(Qt.resolvedUrl("AlternateActionPopover.qml"),
185 hiddenButton);
186 }
187 }
188
189 QMLTermScrollbar {
190 anchors.fill: parent
191 terminal: terminal
192 }
80}193}
81194
=== modified file 'src/app/qml/TerminalPage.qml'
--- src/app/qml/TerminalPage.qml 2017-01-06 08:37:39 +0000
+++ src/app/qml/TerminalPage.qml 2017-01-12 13:29:38 +0000
@@ -27,7 +27,7 @@
27Page {27Page {
28 id: terminalPage28 id: terminalPage
29 property alias terminalContainer: terminalContainer29 property alias terminalContainer: terminalContainer
30 property Item terminal30 property Terminal terminal
31 property var tabsModel31 property var tabsModel
32 property bool narrowLayout32 property bool narrowLayout
33 theme: ThemeSettings {33 theme: ThemeSettings {
@@ -50,15 +50,15 @@
50 top: parent.top50 top: parent.top
51 right: parent.right51 right: parent.right
52 }52 }
53 property bool isDarkBackground: ColorUtils.luminance(backgroundColor) <= 0.8553 property bool isDarkBackground: terminalPage.terminal && terminalPage.terminal.isDarkBackground
54 actionColor: isDarkBackground ? "white" : "black"54 actionColor: isDarkBackground ? "white" : "black"
55 backgroundColor: terminalPage.terminal ? terminalPage.terminal.backgroundColor : ""55 backgroundColor: terminalPage.terminal ? terminalPage.terminal.backgroundColor : ""
56 foregroundColor: terminalPage.terminal ? terminalPage.terminal.foregroundColor : ""56 foregroundColor: terminalPage.terminal ? terminalPage.terminal.foregroundColor : ""
57 contourColor: isDarkBackground ? Qt.rgba(1.0, 1.0, 1.0, 0.4) : Qt.rgba(0.0, 0.0, 0.0, 0.2)57 contourColor: terminalPage.terminal ? terminalPage.terminal.contourColor : ""
58 color: isDarkBackground ? Qt.tint(backgroundColor, "#0DFFFFFF") : Qt.tint(backgroundColor, "#0D000000")58 color: isDarkBackground ? Qt.tint(backgroundColor, "#0DFFFFFF") : Qt.tint(backgroundColor, "#0D000000")
59 model: terminalPage.tabsModel59 model: terminalPage.tabsModel
60 function titleFromModelItem(modelItem) {60 function titleFromModelItem(modelItem) {
61 return modelItem.session.title;61 return modelItem.focusedTerminal ? modelItem.focusedTerminal.session.title : "";
62 }62 }
6363
64 actions: [64 actions: [
@@ -84,7 +84,6 @@
84 top: terminalPage.narrowLayout ? parent.top : tabsBar.bottom;84 top: terminalPage.narrowLayout ? parent.top : tabsBar.bottom;
85 right: parent.right;85 right: parent.right;
86 bottom: keyboardBarLoader.top86 bottom: keyboardBarLoader.top
87 margins: units.gu(1)
88 }87 }
8988
90 Binding {89 Binding {
@@ -94,125 +93,6 @@
94 }93 }
95 }94 }
9695
97 QMLTermScrollbar {
98 anchors {
99 top: terminalContainer.anchors.top
100 bottom: terminalContainer.anchors.bottom
101 left: terminalContainer.anchors.left
102 right: terminalContainer.anchors.right
103 }
104
105 terminal: terminalPage.terminal
106 z: inputArea.z + 1
107 }
108
109 // TODO: This invisible button is used to position the popover where the
110 // alternate action was called. Terrible terrible workaround!
111 Button {
112 id: hiddenButton
113 width: 5
114 height: 5
115 visible: false
116 enabled: false
117 }
118
119 TerminalInputArea{
120 id: inputArea
121 anchors {
122 left: terminalContainer.anchors.left
123 top: terminalContainer.anchors.top
124 right: terminalContainer.anchors.right
125 bottom: parent.bottom
126 margins: terminalContainer.anchors.margins
127 }
128 enabled: terminal
129
130 // This is the minimum wheel event registered by the plugin (with the current settings).
131 property real wheelValue: 40
132
133 // This is needed to fake a "flickable" scrolling.
134 swipeDelta: terminal ? terminal.fontMetrics.height : 0
135
136 // Mouse actions
137 onMouseMoveDetected: terminal.simulateMouseMove(x, y, button, buttons, modifiers);
138 onDoubleClickDetected: terminal.simulateMouseDoubleClick(x, y, button, buttons, modifiers);
139 onMousePressDetected: terminal.simulateMousePress(x, y, button, buttons, modifiers);
140 onMouseReleaseDetected: terminal.simulateMouseRelease(x, y, button, buttons, modifiers);
141 onMouseWheelDetected: terminal.simulateWheel(x, y, buttons, modifiers, angleDelta);
142
143 // Touch actions
144 onTouchClick: terminal.simulateKeyPress(Qt.Key_Tab, Qt.NoModifier, true, 0, "");
145 onTouchPressAndHold: alternateAction(x, y);
146
147 // Swipe actions
148 onSwipeYDetected: {
149 if (steps > 0) {
150 simulateSwipeDown(steps);
151 } else {
152 simulateSwipeUp(-steps);
153 }
154 }
155 onSwipeXDetected: {
156 if (steps > 0) {
157 simulateSwipeRight(steps);
158 } else {
159 simulateSwipeLeft(-steps);
160 }
161 }
162 onTwoFingerSwipeYDetected: {
163 if (steps > 0) {
164 simulateDualSwipeDown(steps);
165 } else {
166 simulateDualSwipeUp(-steps);
167 }
168 }
169
170 function simulateSwipeUp(steps) {
171 while(steps > 0) {
172 terminal.simulateKeyPress(Qt.Key_Up, Qt.NoModifier, true, 0, "");
173 steps--;
174 }
175 }
176 function simulateSwipeDown(steps) {
177 while(steps > 0) {
178 terminal.simulateKeyPress(Qt.Key_Down, Qt.NoModifier, true, 0, "");
179 steps--;
180 }
181 }
182 function simulateSwipeLeft(steps) {
183 while(steps > 0) {
184 terminal.simulateKeyPress(Qt.Key_Left, Qt.NoModifier, true, 0, "");
185 steps--;
186 }
187 }
188 function simulateSwipeRight(steps) {
189 while(steps > 0) {
190 terminal.simulateKeyPress(Qt.Key_Right, Qt.NoModifier, true, 0, "");
191 steps--;
192 }
193 }
194 function simulateDualSwipeUp(steps) {
195 while(steps > 0) {
196 terminal.simulateWheel(width * 0.5, height * 0.5, Qt.NoButton, Qt.NoModifier, Qt.point(0, -wheelValue));
197 steps--;
198 }
199 }
200 function simulateDualSwipeDown(steps) {
201 while(steps > 0) {
202 terminal.simulateWheel(width * 0.5, height * 0.5, Qt.NoButton, Qt.NoModifier, Qt.point(0, wheelValue));
203 steps--;
204 }
205 }
206
207 // Semantic actions
208 onAlternateAction: {
209 // Force the hiddenButton in the event position.
210 hiddenButton.x = x;
211 hiddenButton.y = y;
212 PopupUtils.open(Qt.resolvedUrl("AlternateActionPopover.qml"), hiddenButton);
213 }
214 }
215
216 Loader {96 Loader {
217 id: keyboardBarLoader97 id: keyboardBarLoader
218 height: active ? units.gu(5) : 098 height: active ? units.gu(5) : 0
@@ -227,7 +107,7 @@
227 backgroundColor: tabsBar.color107 backgroundColor: tabsBar.color
228 foregroundColor: tabsBar.foregroundColor108 foregroundColor: tabsBar.foregroundColor
229 onSimulateKey: terminal.simulateKeyPress(key, mod, true, 0, "");109 onSimulateKey: terminal.simulateKeyPress(key, mod, true, 0, "");
230 onSimulateCommand: terminal.session.sendText(command);110 onSimulateCommand: terminal.focusedTerminal.session.sendText(command);
231 }111 }
232 }112 }
233113
@@ -267,7 +147,7 @@
267 iconName: "close"147 iconName: "close"
268 onTriggered: {148 onTriggered: {
269 terminalPage.state = "DEFAULT";149 terminalPage.state = "DEFAULT";
270 PopupUtils.open(Qt.resolvedUrl("AlternateActionPopover.qml"), hiddenButton);150 PopupUtils.open(Qt.resolvedUrl("AlternateActionPopover.qml"));
271 }151 }
272 }152 }
273 }153 }
@@ -333,7 +213,6 @@
333 PropertyChanges { target: keyboardButton; visible: false }213 PropertyChanges { target: keyboardButton; visible: false }
334 PropertyChanges { target: bottomMessage; active: true }214 PropertyChanges { target: bottomMessage; active: true }
335 PropertyChanges { target: keyboardBarLoader; enabled: false }215 PropertyChanges { target: keyboardBarLoader; enabled: false }
336 PropertyChanges { target: inputArea; enabled: false }
337 }216 }
338 ]217 ]
339}218}
340219
=== modified file 'src/app/qml/TerminalSettings.qml'
--- src/app/qml/TerminalSettings.qml 2016-11-30 09:17:02 +0000
+++ src/app/qml/TerminalSettings.qml 2017-01-12 13:29:38 +0000
@@ -34,6 +34,12 @@
34 property alias shortcutCopy: innerSettings.shortcutCopy34 property alias shortcutCopy: innerSettings.shortcutCopy
35 property alias shortcutPaste: innerSettings.shortcutPaste35 property alias shortcutPaste: innerSettings.shortcutPaste
36 property alias shortcutFullscreen: innerSettings.shortcutFullscreen36 property alias shortcutFullscreen: innerSettings.shortcutFullscreen
37 property alias shortcutSplitHorizontally: innerSettings.shortcutSplitHorizontally
38 property alias shortcutSplitVertically: innerSettings.shortcutSplitVertically
39 property alias shortcutMoveToTileAbove: innerSettings.shortcutMoveToTileAbove
40 property alias shortcutMoveToTileBelow: innerSettings.shortcutMoveToTileBelow
41 property alias shortcutMoveToTileLeft: innerSettings.shortcutMoveToTileLeft
42 property alias shortcutMoveToTileRight: innerSettings.shortcutMoveToTileRight
3743
38 readonly property int defaultFontSize: 1244 readonly property int defaultFontSize: 12
39 readonly property int minFontSize: 445 readonly property int minFontSize: 4
@@ -73,6 +79,12 @@
73 property string shortcutCopy: "Ctrl+Shift+C"79 property string shortcutCopy: "Ctrl+Shift+C"
74 property string shortcutPaste: "Ctrl+Shift+V"80 property string shortcutPaste: "Ctrl+Shift+V"
75 property string shortcutFullscreen: "F11"81 property string shortcutFullscreen: "F11"
82 property string shortcutSplitHorizontally: "Ctrl+Shift+E"
83 property string shortcutSplitVertically: "Ctrl+Shift+O"
84 property string shortcutMoveToTileAbove: "Alt+Up"
85 property string shortcutMoveToTileBelow: "Alt+Down"
86 property string shortcutMoveToTileLeft: "Alt+Left"
87 property string shortcutMoveToTileRight: "Alt+Right"
76 }88 }
7789
78 // Load the keyboard profiles.90 // Load the keyboard profiles.
7991
=== modified file 'src/app/qml/TerminalWindow.qml'
--- src/app/qml/TerminalWindow.qml 2016-12-12 13:41:58 +0000
+++ src/app/qml/TerminalWindow.qml 2017-01-12 13:29:38 +0000
@@ -25,7 +25,7 @@
25Window {25Window {
26 id: terminalWindow26 id: terminalWindow
2727
28 title: tabsModel.currentItem ? tabsModel.currentItem.session.title : ""28 title: tabsModel.currentItem && tabsModel.currentItem.focusedTerminal ? tabsModel.currentItem.focusedTerminal.session.title : ""
29 color: terminalPage.active && terminalPage.terminal ? terminalPage.terminal.backgroundColor : theme.palette.selected.overlay29 color: terminalPage.active && terminalPage.terminal ? terminalPage.terminal.backgroundColor : theme.palette.selected.overlay
30 contentOrientation: Screen.orientation30 contentOrientation: Screen.orientation
3131
@@ -35,7 +35,7 @@
35 Binding {35 Binding {
36 target: terminalAppRoot36 target: terminalAppRoot
37 property: "focusedTerminal"37 property: "focusedTerminal"
38 value: tabsModel.currentItem38 value: tabsModel.currentItem ? tabsModel.currentItem.focusedTerminal : null
39 when: terminalWindow.active39 when: terminalWindow.active
40 }40 }
4141
@@ -71,6 +71,21 @@
71 }71 }
72 }72 }
7373
74 property TiledTerminalView tiledTerminalView: tabsModel.currentItem
75 Shortcut {
76 sequence: settings.shortcutSplitVertically
77 onActivated: tiledTerminalView.splitTerminal(tiledTerminalView.focusedTerminal,
78 Qt.Horizontal)
79 enabled: tiledTerminalView.focusedTerminal.width >= 2 * tiledTerminalView.minimumTileWidth
80 }
81
82 Shortcut {
83 sequence: settings.shortcutSplitHorizontally
84 onActivated: tiledTerminalView.splitTerminal(tiledTerminalView.focusedTerminal,
85 Qt.Vertical)
86 enabled: tiledTerminalView.focusedTerminal.height >= 2 * tiledTerminalView.minimumTileHeight
87 }
88
74 Shortcut {89 Shortcut {
75 sequence: settings.shortcutNewTab90 sequence: settings.shortcutNewTab
76 onActivated: tabsModel.addTerminalTab()91 onActivated: tabsModel.addTerminalTab()
@@ -98,12 +113,12 @@
98113
99 Shortcut {114 Shortcut {
100 sequence: settings.shortcutCopy115 sequence: settings.shortcutCopy
101 onActivated: tabsModel.currentItem.copyClipboard()116 onActivated: tabsModel.currentItem.focusedTerminal.copyClipboard()
102 }117 }
103118
104 Shortcut {119 Shortcut {
105 sequence: settings.shortcutPaste120 sequence: settings.shortcutPaste
106 onActivated: tabsModel.currentItem.pasteClipboard()121 onActivated: tabsModel.currentItem.focusedTerminal.pasteClipboard()
107 }122 }
108123
109 Shortcut {124 Shortcut {
@@ -141,7 +156,7 @@
141 TerminalPage {156 TerminalPage {
142 id: terminalPage157 id: terminalPage
143 tabsModel: tabsModel158 tabsModel: tabsModel
144 terminal: tabsModel.currentItem159 terminal: tabsModel.currentItem ? tabsModel.currentItem.focusedTerminal : null
145 narrowLayout: terminalWindow.narrowLayout160 narrowLayout: terminalWindow.narrowLayout
146 // Hide terminal data when the access is still not granted161 // Hide terminal data when the access is still not granted
147 layer.enabled: authService.isDialogVisible162 layer.enabled: authService.isDialogVisible
148163
=== added file 'src/app/qml/TiledTerminalView.qml'
--- src/app/qml/TiledTerminalView.qml 1970-01-01 00:00:00 +0000
+++ src/app/qml/TiledTerminalView.qml 2017-01-12 13:29:38 +0000
@@ -0,0 +1,96 @@
1/*
2 * Copyright (C) 2016-2017 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored-by: Florian Boucault <florian.boucault@canonical.com>
17 */
18import QtQuick 2.5
19import Ubuntu.Components 1.3
20
21TiledView {
22 id: tiledTerminalView
23 anchors.fill: parent
24
25 property string initialWorkingDirectory
26 property Terminal focusedTerminal
27 signal emptied
28 onCountChanged: if (count == 0) emptied()
29
30 function splitTerminal(terminal, orientation) {
31 var initialWorkingDirectory = focusedTerminal.session.getWorkingDirectory();
32 var newTerminal = terminalComponent.createObject(tiledTerminalView,
33 {"initialWorkingDirectory": initialWorkingDirectory});
34 tiledTerminalView.setOrientation(terminal, orientation);
35 tiledTerminalView.add(terminal, newTerminal, Qt.AlignTrailing);
36 }
37
38 handleDelegate: Rectangle {
39 implicitWidth: units.dp(1)
40 implicitHeight: units.dp(1)
41 color: focusedTerminal ? focusedTerminal.contourColor : ""
42 }
43
44 Component.onCompleted: {
45 var newTerminal = terminalComponent.createObject(tiledTerminalView,
46 {"initialWorkingDirectory": initialWorkingDirectory});
47 setRootItem(newTerminal);
48 }
49
50 function moveFocus(direction) {
51 var terminal = tiledTerminalView.closestTileInDirection(focusedTerminal, direction);
52 if (terminal) {
53 terminal.focus = true;
54 }
55 }
56
57 Shortcut {
58 sequence: settings.shortcutMoveToTileRight
59 enabled: tiledTerminalView.focus
60 onActivated: moveFocus(Qt.AlignRight)
61 }
62
63 Shortcut {
64 sequence: settings.shortcutMoveToTileLeft
65 enabled: tiledTerminalView.focus
66 onActivated: moveFocus(Qt.AlignLeft)
67 }
68
69 Shortcut {
70 sequence: settings.shortcutMoveToTileAbove
71 enabled: tiledTerminalView.focus
72 onActivated: moveFocus(Qt.AlignTop)
73 }
74
75 Shortcut {
76 sequence: settings.shortcutMoveToTileBelow
77 enabled: tiledTerminalView.focus
78 onActivated: moveFocus(Qt.AlignBottom)
79 }
80
81 property real minimumTileWidth: units.gu(10)
82 property real minimumTileHeight: units.gu(10)
83 property Component terminalComponent: Terminal {
84 id: terminal
85 Component.onCompleted: if (focus) tiledTerminalView.focusedTerminal = terminal
86 onFocusChanged: if (focus) tiledTerminalView.focusedTerminal = terminal
87 onFinished: {
88 if (terminal.focus) {
89 var nextTerminal = tiledTerminalView.closestTile(terminal);
90 if (nextTerminal) nextTerminal.focus = true;
91 }
92 tiledTerminalView.remove(terminal);
93 terminal.destroy();
94 }
95 }
96}
097
=== added file 'src/app/qml/TiledView.qml'
--- src/app/qml/TiledView.qml 1970-01-01 00:00:00 +0000
+++ src/app/qml/TiledView.qml 2017-01-12 13:29:38 +0000
@@ -0,0 +1,135 @@
1/*
2 * Copyright (C) 2016-2017 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored-by: Florian Boucault <florian.boucault@canonical.com>
17 */
18import QtQuick 2.5
19import "binarytree.js" as BinaryTree
20
21FocusScope {
22 id: tiledView
23
24 property Component handleDelegate: Rectangle {
25 implicitWidth: units.dp(1)
26 implicitHeight: units.dp(1)
27 color: "white"
28 }
29
30 property int count: 0
31
32 // FIXME: odd semantics: what if setRootItem is called later?
33 function setRootItem(rootItem) {
34 if (rootItem && rootItem === __rootNode.value) {
35 return null;
36 }
37
38 var oldRoot = __rootNode.value;
39 if (rootItem) {
40 count = 1;
41 } else {
42 count = 0;
43 __rootNode.cleanup();
44 }
45 __rootNode.setValue(rootItem);
46
47 return oldRoot;
48 }
49
50 property var __rootNode: new BinaryTree.Node()
51 Component.onDestruction: __rootNode.cleanup()
52
53 Component.onCompleted: {
54 __rootNode.setWidth(width);
55 __rootNode.setHeight(height);
56 }
57
58 onWidthChanged: __rootNode.setWidth(width)
59 onHeightChanged: __rootNode.setHeight(height)
60
61 Component {
62 id: separatorComponent
63 TiledViewSeparator {
64 handleDelegate: tiledView.handleDelegate
65 }
66 }
67
68 function add(obj, newObj, side) {
69 var node = __rootNode.findNodeWithValue(obj);
70 var otherSide;
71 if (side == Qt.AlignLeading) {
72 otherSide = Qt.AlignTrailing;
73 } else {
74 otherSide = Qt.AlignLeading;
75 }
76
77 node.value = null;
78 node.setLeftRatio(0.5);
79 var separator = separatorComponent.createObject(tiledView, {"node": node});
80 node.setSeparator(separator);
81
82 var nodeSide = new BinaryTree.Node();
83 nodeSide.setValue(newObj);
84 node.setChild(side, nodeSide);
85
86 var nodeOtherSide = new BinaryTree.Node();
87 nodeOtherSide.setValue(obj);
88 node.setChild(otherSide, nodeOtherSide);
89 count += 1;
90 }
91
92 function remove(obj) {
93 var node = __rootNode.findNodeWithValue(obj);
94 var sibling = node.getSibling();
95 if (sibling) {
96 node.parent.copy(sibling);
97 }
98 count -= 1;
99 }
100
101 function closestTile(obj) {
102 var node = __rootNode.findNodeWithValue(obj);
103 var sibling = node.closestNodeWithValue();
104 if (sibling) {
105 return sibling.value;
106 } else {
107 return null;
108 }
109 }
110
111 function closestTileInDirection(obj, direction) {
112 var node = __rootNode.findNodeWithValue(obj);
113 var closestNode = node.closestNodeWithValueInDirection(direction);
114 if (closestNode && closestNode.value) {
115 return closestNode.value;
116 } else {
117 return null;
118 }
119 }
120
121 function getOrientation(obj) {
122 var node = __rootNode.findNodeWithValue(obj);
123 return node.orientation;
124 }
125
126 function setOrientation(obj, orientation) {
127 var node = __rootNode.findNodeWithValue(obj);
128 node.setOrientation(orientation);
129 }
130
131 function move(obj, targetObj, side) {
132 remove(obj);
133 add(targetObj, obj, side);
134 }
135}
0136
=== added file 'src/app/qml/TiledViewSeparator.qml'
--- src/app/qml/TiledViewSeparator.qml 1970-01-01 00:00:00 +0000
+++ src/app/qml/TiledViewSeparator.qml 2017-01-12 13:29:38 +0000
@@ -0,0 +1,76 @@
1/*
2 * Copyright (C) 2016-2017 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored-by: Florian Boucault <florian.boucault@canonical.com>
17 */
18import QtQuick 2.4
19import Ubuntu.Components 1.3
20
21Item {
22 id: separator
23
24 property int orientation: Qt.Horizontal
25 property var node
26 property Component handleDelegate
27
28 Loader {
29 id: handleLoader
30 sourceComponent: handleDelegate
31 anchors.fill: parent
32 }
33
34 implicitWidth: handleLoader.implicitWidth
35 implicitHeight: handleLoader.implicitHeight
36 z: 1
37
38 MouseArea {
39 anchors.centerIn: parent
40 width: orientation == Qt.Vertical ? units.gu(1) : parent.width
41 height: orientation == Qt.Vertical ? parent.height : units.gu(1)
42 cursorShape: orientation == Qt.Horizontal ? Qt.SizeVerCursor : Qt.SizeHorCursor
43 drag {
44 axis: orientation == Qt.Horizontal ? Drag.YAxis : Drag.XAxis
45 target: resizer
46 smoothed: false
47 }
48 onPressed: {
49 resizer.initialRatio = node.leftRatio;
50 resizer.x = 0;
51 resizer.y = 0;
52 }
53 enabled: separator.visible
54 }
55
56 function clamp(value, min, max) {
57 return Math.min(Math.max(min, value), max);
58 }
59
60 Item {
61 id: resizer
62 property real initialRatio
63 property real minimumRatio: 0.1
64 parent: null
65 onXChanged: {
66 var ratio = initialRatio + x / node.width;
67 ratio = clamp(ratio, minimumRatio, 1.0-minimumRatio);
68 node.setLeftRatio(ratio);
69 }
70 onYChanged: {
71 var ratio = initialRatio + y / node.height;
72 ratio = clamp(ratio, minimumRatio, 1.0-minimumRatio);
73 node.setLeftRatio(ratio);
74 }
75 }
76}
077
=== added file 'src/app/qml/binarytree.js'
--- src/app/qml/binarytree.js 1970-01-01 00:00:00 +0000
+++ src/app/qml/binarytree.js 2017-01-12 13:29:38 +0000
@@ -0,0 +1,378 @@
1/*
2 * Copyright (C) 2016-2017 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored-by: Florian Boucault <florian.boucault@canonical.com>
17 */
18.pragma library
19
20function Node() {
21 this.value = null;
22 this.parent = null;
23 this.left = null;
24 this.right = null;
25 this.separator = null;
26 this.leftRatio = 0.5;
27 this.rightRatio = 0.5;
28 this.orientation = Qt.Horizontal;
29 this.originX = 0;
30 this.originY = 0;
31 this.x = 0;
32 this.y = 0;
33 this.width = 0;
34 this.height = 0;
35}
36
37Node.prototype.cleanup = function cleanup(value) {
38 if (this.separator) {
39 this.separator.destroy();
40 this.separator = null;
41 }
42 this.parent = null;
43 this.value = null;
44 if (this.left) {
45 this.left.cleanup();
46 this.left = null;
47 }
48 if (this.right) {
49 this.right.cleanup();
50 this.right = null;
51 }
52}
53
54Node.prototype.setValue = function setValue(value) {
55 this.value = value;
56 this.updateX();
57 this.updateY();
58 this.updateWidth();
59 this.updateHeight();
60}
61
62Node.prototype.updateWidth = function updateWidth() {
63 if (this.value) {
64 this.value.width = this.width;
65 } else if (this.orientation == Qt.Horizontal) {
66 if (this.right && !this.left) {
67 this.right.setWidth(this.width);
68 this.right.setX(0);
69 }
70 if (this.left && !this.right) {
71 this.left.setWidth(this.width);
72 this.left.setX(0);
73 }
74 if (this.right && this.left) {
75 this.left.setWidth(this.width * this.leftRatio);
76 this.left.setX(0);
77 this.right.setWidth(this.width * this.rightRatio);
78 this.right.setX(this.left.width);
79 }
80 } else if (this.orientation == Qt.Vertical) {
81 if (this.left) {
82 this.left.setWidth(this.width);
83 this.left.setX(0);
84 }
85 if (this.right) {
86 this.right.setWidth(this.width);
87 this.right.setX(0);
88 }
89 }
90 this.updateSeparator();
91}
92
93Node.prototype.setWidth = function setWidth(width) {
94 this.width = width;
95 this.updateWidth();
96};
97
98Node.prototype.updateHeight = function updateHeight() {
99 if (this.value) {
100 this.value.height = this.height;
101 } else if (this.orientation == Qt.Vertical) {
102 if (this.right && !this.left) {
103 this.right.setHeight(this.height);
104 this.right.setY(0);
105 }
106 if (this.left && !this.right) {
107 this.left.setHeight(this.height);
108 this.left.setY(0);
109 }
110 if (this.right && this.left) {
111 this.left.setHeight(this.height * this.leftRatio);
112 this.left.setY(0);
113 this.right.setHeight(this.height * this.rightRatio);
114 this.right.setY(this.left.height);
115 }
116 } else if (this.orientation == Qt.Horizontal) {
117 if (this.left) {
118 this.left.setHeight(this.height);
119 this.left.setY(0);
120 }
121 if (this.right) {
122 this.right.setHeight(this.height);
123 this.right.setY(0);
124 }
125 }
126 this.updateSeparator();
127}
128
129Node.prototype.setHeight = function setHeight(height) {
130 this.height = height;
131 this.updateHeight();
132};
133
134Node.prototype.setLeftRatio = function setLeftRatio(ratio) {
135 this.leftRatio = ratio;
136 this.rightRatio = 1.0 - this.leftRatio;
137 if (this.orientation == Qt.Horizontal) {
138 this.updateWidth();
139 } else {
140 this.updateHeight();
141 }
142};
143
144Node.prototype.setRightRatio = function setRightRatio(ratio) {
145 this.rightRatio = ratio;
146 this.leftRatio = 1.0 - this.rightRatio;
147 if (this.orientation == Qt.Horizontal) {
148 this.updateWidth();
149 } else {
150 this.updateHeight();
151 }
152};
153
154Node.prototype.setChild = function setChild(side, childNode) {
155 switch (side) {
156 case Qt.AlignLeading:
157 if (this.left) {
158 // FIXME: breaks copy()
159// this.left.cleanup();
160 }
161 this.left = childNode;
162 break;
163 case Qt.AlignTrailing:
164 if (this.right) {
165 // FIXME: breaks copy()
166// this.right.cleanup();
167 }
168 this.right = childNode;
169 break;
170 default:
171 break;
172 }
173 if (childNode) {
174 childNode.parent = this;
175 }
176 this.updateX();
177 this.updateY();
178 this.updateWidth();
179 this.updateHeight();
180}
181
182Node.prototype.updateSeparator = function updateSeparator() {
183 if (this.separator) {
184 this.separator.orientation = this.orientation == Qt.Vertical ? Qt.Horizontal : Qt.Vertical;
185 if (this.left && this.right) {
186 // FIXME: separator should be centered
187 this.separator.x = this.right.originX + this.right.x;
188 this.separator.y = this.right.originY + this.right.y;
189 if (this.separator.orientation == Qt.Vertical) {
190 this.separator.width = this.separator.implicitWidth;
191 this.separator.height = this.right.height;
192 } else if (this.separator.orientation == Qt.Horizontal) {
193 this.separator.width = this.right.width;
194 this.separator.height = this.separator.implicitHeight;
195 }
196 this.separator.visible = true;
197 } else {
198 this.separator.visible = false;
199 }
200 }
201}
202
203Node.prototype.setSeparator = function setSeparator(separator) {
204 this.separator = separator;
205 this.updateSeparator();
206}
207
208Node.prototype.copy = function copy(otherNode) {
209 if (!otherNode) return;
210 var newParent = otherNode.parent;
211
212 this.orientation = otherNode.orientation;
213 this.setValue(otherNode.value);
214 this.setChild(Qt.AlignLeading, otherNode.left);
215 this.setChild(Qt.AlignTrailing, otherNode.right);
216
217 if (newParent.left === otherNode) {
218 newParent.setChild(Qt.AlignLeading, this);
219 } else if (otherNode.parent.right === otherNode) {
220 newParent.setChild(Qt.AlignTrailing, this);
221 }
222 otherNode.left = null;
223 otherNode.right = null;
224 otherNode.cleanup();
225 this.updateX();
226 this.updateY();
227 this.updateWidth();
228 this.updateHeight();
229}
230
231Node.prototype.setOrientation = function setOrientation(orientation) {
232 this.orientation = orientation;
233 this.updateWidth();
234 this.updateHeight();
235 this.updateSeparator();
236}
237
238Node.prototype.updateX = function updateX() {
239 var absoluteX = this.originX + this.x;
240 if (this.value) {
241 this.value.x = Math.round(absoluteX);
242 } else {
243 if (this.left) {
244 this.left.setOriginX(absoluteX);
245 }
246 if (this.right) {
247 this.right.setOriginX(absoluteX);
248 }
249 }
250 this.updateSeparator();
251}
252
253Node.prototype.setX = function setX(x) {
254 this.x = x;
255 this.updateX();
256};
257
258Node.prototype.setOriginX = function setOriginX(x) {
259 this.originX = x;
260 this.updateX();
261};
262
263Node.prototype.updateY = function updateY() {
264 var absoluteY = this.originY + this.y;
265 if (this.value) {
266 this.value.y = Math.round(absoluteY);
267 } else {
268 if (this.left) {
269 this.left.setOriginY(absoluteY);
270 }
271 if (this.right) {
272 this.right.setOriginY(absoluteY);
273 }
274 }
275 this.updateSeparator();
276}
277
278Node.prototype.setY = function setY(y) {
279 this.y = y;
280 this.updateY();
281};
282
283Node.prototype.setOriginY = function setOriginY(y) {
284 this.originY = y;
285 this.updateY();
286};
287
288Node.prototype.getSibling = function getSibling() {
289 if (this.parent) {
290 if (this.parent.left === this) {
291 return this.parent.right;
292 } else {
293 return this.parent.left;
294 }
295 }
296 return null;
297}
298
299Node.prototype.findNodeWithValue = function findNodeWithValue(value) {
300 if (this.value === value) return this;
301 var result;
302 if (this.left) {
303 result = this.left.findNodeWithValue(value);
304 if (result) {
305 return result;
306 }
307 }
308 if (this.right) {
309 result = this.right.findNodeWithValue(value);
310 if (result) {
311 return result;
312 }
313 }
314 return null;
315};
316
317Node.prototype.closestChildWithValue = function closestChildWithValue(sides) {
318 var currentLevelNodes = [this];
319 var nextLevelNodes = [];
320 while (currentLevelNodes.length != 0) {
321 for (var i=0; i<currentLevelNodes.length; i++) {
322 var node = currentLevelNodes[i];
323 if (node.value) {
324 return node;
325 }
326 if ((sides == undefined || sides & Qt.AlignLeading) && node.left) {
327 nextLevelNodes.push(node.left);
328 }
329 if ((sides == undefined || sides & Qt.AlignTrailing) && node.right) {
330 nextLevelNodes.push(node.right);
331 }
332 }
333 currentLevelNodes = nextLevelNodes;
334 nextLevelNodes = [];
335 }
336 return null;
337}
338
339Node.prototype.closestNodeWithValue = function closestNodeWithValue() {
340 // explore sibling hierarchy
341 var sibling = this.getSibling();
342 if (sibling) {
343 var closestChild = sibling.closestChildWithValue(Qt.AlignLeading | Qt.AlignTrailing);
344 if (closestChild) {
345 return closestChild;
346 }
347 }
348 // explore parent's sibling hierarchy
349 if (this.parent) {
350 var parentSibling = this.parent.getSibling();
351 if (parentSibling) {
352 var closestChild = parentSibling.closestChildWithValue(Qt.AlignLeading | Qt.AlignTrailing);
353 if (closestChild) {
354 return closestChild;
355 }
356 }
357 }
358 return null;
359};
360
361Node.prototype.closestNodeWithValueInDirection = function closestNodeWithValueInDirection(direction) {
362 if (this.parent) {
363 if (this.parent.left === this) {
364 if ((direction == Qt.AlignRight && this.parent.orientation == Qt.Horizontal) ||
365 (direction == Qt.AlignBottom && this.parent.orientation == Qt.Vertical)) {
366 return this.parent.right.closestChildWithValue(Qt.AlignLeading);
367 }
368 } else if (this.parent.right === this) {
369 if ((direction == Qt.AlignLeft && this.parent.orientation == Qt.Horizontal) ||
370 (direction == Qt.AlignTop && this.parent.orientation == Qt.Vertical)) {
371 return this.parent.left.closestChildWithValue(Qt.AlignTrailing);
372 }
373 }
374 return this.parent.closestNodeWithValueInDirection(direction);
375 } else {
376 return null;
377 }
378}
0379
=== modified file 'src/plugin/qmltermwidget/lib/TerminalDisplay.h'
--- src/plugin/qmltermwidget/lib/TerminalDisplay.h 2017-01-06 08:37:18 +0000
+++ src/plugin/qmltermwidget/lib/TerminalDisplay.h 2017-01-12 13:29:38 +0000
@@ -898,8 +898,8 @@
898898
899 //the delay in milliseconds between redrawing blinking text899 //the delay in milliseconds between redrawing blinking text
900 static const int TEXT_BLINK_DELAY = 500;900 static const int TEXT_BLINK_DELAY = 500;
901 static const int DEFAULT_LEFT_MARGIN = 1;901 static const int DEFAULT_LEFT_MARGIN = 8;
902 static const int DEFAULT_TOP_MARGIN = 1;902 static const int DEFAULT_TOP_MARGIN = 8;
903903
904 // QMLTermWidget port functions904 // QMLTermWidget port functions
905 QFont m_font;905 QFont m_font;
906906
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2015-02-24 23:23:36 +0000
+++ tests/CMakeLists.txt 2017-01-12 13:29:38 +0000
@@ -1,1 +1,2 @@
1add_subdirectory(autopilot)1add_subdirectory(autopilot)
2add_subdirectory(qtquicktest)
23
=== added directory 'tests/qtquicktest'
=== added file 'tests/qtquicktest/CMakeLists.txt'
--- tests/qtquicktest/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/qtquicktest/CMakeLists.txt 2017-01-12 13:29:38 +0000
@@ -0,0 +1,20 @@
1find_program(XVFB_RUN_BIN xvfb-run)
2if(NOT XVFB_RUN_BIN)
3 message(FATAL_ERROR "Could not find xvfb-run, please install the xvfb package")
4endif()
5set(XVFB_RUN_CMD ${XVFB_RUN_BIN} -a -s "-screen 0 1024x768x24")
6
7include(FindPkgConfig)
8find_package(Qt5Core)
9
10# copy qml test files to build directory
11if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
12add_custom_target(qmlTestFiles ALL
13 COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/*.qml ${CMAKE_CURRENT_BINARY_DIR}
14)
15endif(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
16
17set(QTQUICK_TEST tst_qtquicktest)
18add_executable(${QTQUICK_TEST} qtquicktest.cpp)
19qt5_use_modules(${QTQUICK_TEST} Core Qml Quick Test QuickTest)
20add_test(${QTQUICK_TEST} ${XVFB_RUN_CMD} ${CMAKE_CURRENT_BINARY_DIR}/${QTQUICK_TEST})
021
=== added file 'tests/qtquicktest/qtquicktest.cpp'
--- tests/qtquicktest/qtquicktest.cpp 1970-01-01 00:00:00 +0000
+++ tests/qtquicktest/qtquicktest.cpp 2017-01-12 13:29:38 +0000
@@ -0,0 +1,18 @@
1/*
2 * Copyright (C) 2012 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <QtQuickTest/quicktest.h>
18QUICK_TEST_MAIN(qtquicktest)
019
=== added file 'tests/qtquicktest/tst_TiledView.qml'
--- tests/qtquicktest/tst_TiledView.qml 1970-01-01 00:00:00 +0000
+++ tests/qtquicktest/tst_TiledView.qml 2017-01-12 13:29:38 +0000
@@ -0,0 +1,468 @@
1/*
2 * Copyright (C) 2017 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored-by: Florian Boucault <florian.boucault@canonical.com>
17 */
18
19import QtQuick 2.4
20import QtTest 1.0
21import "../../src/app/qml"
22
23TiledView {
24 id: tiledView
25 width: 800
26 height: 600
27
28 TestCase {
29 name: "TiledView"
30 when: windowShown
31
32 property Component objectComponent: Rectangle {
33 width: 100
34 height: 50
35 color: "red"
36 }
37
38 SignalSpy {
39 id: countSpy
40 target: tiledView
41 signalName: "countChanged"
42 }
43
44 function init() {
45 countSpy.clear();
46 }
47
48 function test_defaults() {
49 compare(tiledView.count, 0);
50 }
51
52 function test_setRootItemValid() {
53 var rightObject = objectComponent.createObject(tiledView);
54 var oldRoot = tiledView.setRootItem(rightObject);
55 compare(oldRoot, null);
56 compare(countSpy.count, 1);
57 compare(tiledView.count, 1);
58 compare(rightObject.width, tiledView.width);
59 compare(rightObject.height, tiledView.height);
60 compare(tiledView.getOrientation(rightObject), Qt.Horizontal);
61 tiledView.setRootItem(null);
62 rightObject.destroy();
63 }
64
65 function test_setRootItemNull() {
66 var oldRoot = tiledView.setRootItem(null);
67 compare(oldRoot, null);
68 compare(countSpy.count, 0);
69 compare(tiledView.count, 0);
70 }
71
72 function test_resetRootItem() {
73 // set to new object
74 var rightObject = objectComponent.createObject(tiledView);
75 var oldRoot = tiledView.setRootItem(rightObject);
76 compare(oldRoot, null);
77 compare(countSpy.count, 1);
78 compare(tiledView.count, 1);
79
80 // set to same object
81 oldRoot = tiledView.setRootItem(rightObject);
82 compare(oldRoot, null);
83 compare(countSpy.count, 1);
84 compare(tiledView.count, 1);
85
86 // set to another new object
87 var rightObject2 = objectComponent.createObject(tiledView);
88 oldRoot = tiledView.setRootItem(rightObject2);
89 compare(oldRoot, rightObject);
90 compare(countSpy.count, 1);
91 compare(tiledView.count, 1);
92
93 // set to null
94 oldRoot = tiledView.setRootItem(null);
95 compare(oldRoot, rightObject2);
96 compare(countSpy.count, 2);
97 compare(tiledView.count, 0);
98
99 rightObject.destroy();
100 rightObject2.destroy();
101 }
102
103 function verifySetRootItem(object) {
104 tiledView.setRootItem(object);
105 compare(tiledView.count, 1);
106 compare(object.width, tiledView.width);
107 compare(object.height, tiledView.height);
108 }
109
110 function verifySetOrientation(object, orientation) {
111 tiledView.setOrientation(object, orientation);
112 compare(tiledView.getOrientation(object), orientation);
113 }
114
115 function verifyAdd(object, rightObject, side) {
116 var previousX = object.x;
117 var previousY = object.y;
118 var previousWidth = object.width;
119 var previousHeight = object.height;
120 var previousCount = tiledView.count;
121 var orientation = tiledView.getOrientation(object);
122
123 tiledView.add(object, rightObject, side);
124 compare(tiledView.count, previousCount+1);
125 compare(tiledView.getOrientation(object), Qt.Horizontal);
126 compare(tiledView.getOrientation(rightObject), Qt.Horizontal);
127
128 if (orientation == Qt.Horizontal) {
129 compare(object.width, previousWidth / 2);
130 compare(object.height, previousHeight);
131 compare(rightObject.width, previousWidth / 2);
132 compare(rightObject.height, previousHeight);
133 if (side == Qt.AlignTrailing) {
134 compare(object.x, previousX);
135 compare(object.y, previousY);
136 compare(rightObject.x, previousX + Math.round(previousWidth / 2));
137 compare(rightObject.y, previousY);
138 } else if (side == Qt.AlignLeading) {
139 compare(rightObject.x, previousX);
140 compare(rightObject.y, previousY);
141 compare(object.x, previousX + Math.round(previousWidth / 2));
142 compare(object.y, previousY);
143 }
144 } else if (orientation == Qt.Vertical) {
145 compare(object.width, previousWidth);
146 compare(object.height, previousHeight / 2);
147 compare(rightObject.width, previousWidth);
148 compare(rightObject.height, previousHeight / 2);
149 if (side == Qt.AlignTrailing) {
150 compare(object.x, previousX);
151 compare(object.y, previousY);
152 compare(rightObject.x, previousX);
153 compare(rightObject.y, previousY + Math.round(previousHeight / 2));
154 } else if (side == Qt.AlignLeading) {
155 compare(rightObject.x, previousX);
156 compare(rightObject.y, previousY);
157 compare(object.x, previousX);
158 compare(object.y, previousY + Math.round(previousHeight / 2));
159 }
160 }
161 }
162
163 function verifyRemove(object) {
164 var node = tiledView.__rootNode.findNodeWithValue(object);
165 var siblingNode = node.getSibling();
166 var siblingObject = siblingNode.value;
167
168 var side;
169 if (node.parent.left === node) {
170 side = Qt.AlignLeading;
171 } else {
172 side = Qt.AlignTrailing;
173 }
174 var orientation = node.parent.orientation;
175
176 var expectedX;
177 var expectedY;
178 var expectedWidth;
179 var expectedHeight;
180 if (orientation == Qt.Horizontal) {
181 expectedWidth = object.width + siblingNode.width;
182 expectedHeight = siblingNode.height;
183 if (side == Qt.AlignTrailing) {
184 expectedX = siblingNode.x;
185 expectedY = siblingNode.y;
186 } else if (side == Qt.AlignLeading) {
187 expectedX = object.x;
188 expectedY = siblingNode.y;
189 }
190 } else if (orientation == Qt.Vertical) {
191 expectedWidth = siblingNode.width;
192 expectedHeight = object.height + siblingNode.height;
193 if (side == Qt.AlignTrailing) {
194 expectedX = siblingNode.x;
195 expectedY = siblingNode.y;
196 } else if (side == Qt.AlignLeading) {
197 expectedX = siblingNode.x;
198 expectedY = object.y;
199 }
200 }
201
202 var previousCount = tiledView.count;
203
204 tiledView.remove(object);
205 // TODO: we verify that the resulting node has the correct x/y,width/height
206 // but we could go further and verify that all its children also do
207 var removeNode = tiledView.__rootNode.findNodeWithValue(siblingObject);
208 compare(tiledView.count, previousCount-1);
209 compare(removeNode.width, expectedWidth);
210 compare(removeNode.height, expectedHeight);
211 compare(removeNode.x, expectedX);
212 compare(removeNode.y, expectedY);
213 }
214
215 function test_simpleAdd_data() {
216 return [
217 {orientation: Qt.Horizontal, side: Qt.AlignTrailing},
218 {orientation: Qt.Vertical, side: Qt.AlignTrailing},
219 {orientation: Qt.Horizontal, side: Qt.AlignLeading},
220 {orientation: Qt.Vertical, side: Qt.AlignLeading},
221 ];
222 }
223
224 function test_simpleAdd(data) {
225 var rootObject = objectComponent.createObject(tiledView);
226 verifySetRootItem(rootObject);
227 verifySetOrientation(rootObject, data.orientation);
228
229 var rightObject = objectComponent.createObject(tiledView);
230 verifyAdd(rootObject, rightObject, data.side);
231
232 tiledView.setRootItem(null);
233 rootObject.destroy();
234 rightObject.destroy();
235 }
236
237 function test_nestedAdds() {
238 var objects = [];
239
240 objects["0"] = objectComponent.createObject(tiledView);
241 verifySetRootItem(objects["0"]);
242
243 objects["1"] = objectComponent.createObject(tiledView);
244 verifySetOrientation(objects["0"], Qt.Horizontal);
245 verifyAdd(objects["0"], objects["1"], Qt.AlignTrailing);
246
247 objects["2"] = objectComponent.createObject(tiledView);
248 verifySetOrientation(objects["1"], Qt.Horizontal);
249 verifyAdd(objects["1"], objects["2"], Qt.AlignTrailing);
250
251 objects["3"] = objectComponent.createObject(tiledView);
252 verifySetOrientation(objects["2"], Qt.Horizontal);
253 verifyAdd(objects["2"], objects["3"], Qt.AlignTrailing);
254
255 objects["4"] = objectComponent.createObject(tiledView);
256 verifySetOrientation(objects["3"], Qt.Horizontal);
257 verifyAdd(objects["3"], objects["4"], Qt.AlignTrailing);
258
259 objects["5"] = objectComponent.createObject(tiledView);
260 verifySetOrientation(objects["4"], Qt.Horizontal);
261 verifyAdd(objects["4"], objects["5"], Qt.AlignTrailing);
262
263 objects["6"] = objectComponent.createObject(tiledView);
264 verifySetOrientation(objects["5"], Qt.Horizontal);
265 verifyAdd(objects["5"], objects["6"], Qt.AlignTrailing);
266
267 tiledView.setRootItem(null);
268 for (var i=0; i<objects.length; i++) {
269 objects[i].destroy();
270 }
271 }
272
273 function test_resizeView() {
274 var leftObject = objectComponent.createObject(tiledView);
275 verifySetRootItem(leftObject);
276
277 var bottomRightObject = objectComponent.createObject(tiledView);
278 verifySetOrientation(leftObject, Qt.Horizontal);
279 verifyAdd(leftObject, bottomRightObject, Qt.AlignTrailing);
280
281 var topRightObject = objectComponent.createObject(tiledView);
282 verifySetOrientation(bottomRightObject, Qt.Vertical);
283 verifyAdd(bottomRightObject, topRightObject, Qt.AlignLeading);
284
285 var initialWidth = tiledView.width;
286 var initialHeight = tiledView.height;
287 var factor = 0.7;
288
289 // storing sizes before resizing
290 var sizes = {"leftObject": {"width": leftObject.width, "height": leftObject.height},
291 "bottomRightObject": {"width": bottomRightObject.width, "height": bottomRightObject.height},
292 "topRightObject": {"width": topRightObject.width, "height": topRightObject.height}};
293 tiledView.width = initialWidth * factor;
294 compare(leftObject.width, sizes.leftObject.width * factor);
295 compare(bottomRightObject.width, sizes.bottomRightObject.width * factor);
296 compare(topRightObject.width, sizes.topRightObject.width * factor);
297 compare(leftObject.height, sizes.leftObject.height);
298 compare(bottomRightObject.height, sizes.bottomRightObject.height);
299 compare(topRightObject.height, sizes.topRightObject.height);
300
301 tiledView.height = initialHeight * factor;
302 compare(leftObject.width, sizes.leftObject.width * factor);
303 compare(bottomRightObject.width, sizes.bottomRightObject.width * factor);
304 compare(topRightObject.width, sizes.topRightObject.width * factor);
305 compare(leftObject.height, sizes.leftObject.height * factor);
306 compare(bottomRightObject.height, sizes.bottomRightObject.height * factor);
307 compare(topRightObject.height, sizes.topRightObject.height * factor);
308
309 // resetting initial size
310 tiledView.width = initialWidth;
311 tiledView.height = initialHeight;
312 compare(leftObject.width, sizes.leftObject.width);
313 compare(bottomRightObject.width, sizes.bottomRightObject.width);
314 compare(topRightObject.width, sizes.topRightObject.width);
315 compare(leftObject.height, sizes.leftObject.height);
316 compare(bottomRightObject.height, sizes.bottomRightObject.height);
317 compare(topRightObject.height, sizes.topRightObject.height);
318
319 tiledView.setRootItem(null);
320 leftObject.destroy();
321 bottomRightObject.destroy();
322 topRightObject.destroy();
323 }
324
325 function test_simpleRemove_data() {
326 return [
327 {orientation: Qt.Horizontal, side: Qt.AlignTrailing},
328 {orientation: Qt.Vertical, side: Qt.AlignTrailing},
329 {orientation: Qt.Horizontal, side: Qt.AlignLeading},
330 {orientation: Qt.Vertical, side: Qt.AlignLeading},
331 ];
332 }
333
334 function test_simpleRemove(data) {
335 var rootObject = objectComponent.createObject(tiledView);
336 verifySetRootItem(rootObject);
337 verifySetOrientation(rootObject, data.orientation);
338
339 var rightObject = objectComponent.createObject(tiledView);
340 verifyAdd(rootObject, rightObject, data.side);
341 verifyRemove(rightObject);
342
343 verifyAdd(rootObject, rightObject, data.side);
344 verifyRemove(rootObject);
345
346 verifyAdd(rightObject, rootObject, data.side);
347 verifyRemove(rightObject);
348
349 tiledView.setRootItem(null);
350 rootObject.destroy();
351 rightObject.destroy();
352 }
353
354 function test_nestedAddsRemoveRoot() {
355 var objects = [];
356
357 objects["0"] = objectComponent.createObject(tiledView);
358 verifySetRootItem(objects["0"]);
359
360 objects["1"] = objectComponent.createObject(tiledView);
361 verifySetOrientation(objects["0"], Qt.Horizontal);
362 verifyAdd(objects["0"], objects["1"], Qt.AlignTrailing);
363
364 objects["2"] = objectComponent.createObject(tiledView);
365 verifySetOrientation(objects["1"], Qt.Horizontal);
366 verifyAdd(objects["1"], objects["2"], Qt.AlignTrailing);
367
368 // remove root
369 verifyRemove(objects["0"]);
370
371 // add further
372 objects["3"] = objectComponent.createObject(tiledView);
373 verifySetOrientation(objects["2"], Qt.Horizontal);
374 verifyAdd(objects["2"], objects["3"], Qt.AlignTrailing);
375
376 verifyRemove(objects["2"]);
377
378 objects["4"] = objectComponent.createObject(tiledView);
379 verifySetOrientation(objects["1"], Qt.Horizontal);
380 verifyAdd(objects["1"], objects["4"], Qt.AlignTrailing);
381
382 verifyRemove(objects["1"]);
383
384 tiledView.setRootItem(null);
385 for (var i=0; i<objects.length; i++) {
386 objects[i].destroy();
387 }
388 }
389
390 function test_addsVertical() {
391 var objects = [];
392
393 objects["0"] = objectComponent.createObject(tiledView);
394 verifySetRootItem(objects["0"]);
395
396 objects["1"] = objectComponent.createObject(tiledView);
397 verifySetOrientation(objects["0"], Qt.Vertical);
398 verifyAdd(objects["0"], objects["1"], Qt.AlignTrailing);
399
400 objects["2"] = objectComponent.createObject(tiledView);
401 verifySetOrientation(objects["1"], Qt.Vertical);
402 verifyAdd(objects["1"], objects["2"], Qt.AlignTrailing);
403
404 objects["3"] = objectComponent.createObject(tiledView);
405 verifySetOrientation(objects["2"], Qt.Vertical);
406 verifyAdd(objects["2"], objects["3"], Qt.AlignLeading);
407
408 objects["4"] = objectComponent.createObject(tiledView);
409 verifySetOrientation(objects["3"], Qt.Vertical);
410 verifyAdd(objects["3"], objects["4"], Qt.AlignTrailing);
411
412 tiledView.setRootItem(null);
413 for (var i=0; i<objects.length; i++) {
414 objects[i].destroy();
415 }
416 }
417
418 function verifyResize(leftObject, rightObject, orientation, dragDistance) {
419 var horizontalMove = (orientation == Qt.Horizontal ? dragDistance : 0);
420 var verticalMove = (orientation == Qt.Vertical ? dragDistance : 0);
421 var expectedLeft = {"x": leftObject.x,
422 "y": leftObject.y,
423 "width": leftObject.width + horizontalMove,
424 "height": leftObject.height + verticalMove};
425 var expectedRight = {"x": rightObject.x + horizontalMove,
426 "y": rightObject.y + verticalMove,
427 "width": rightObject.width - horizontalMove,
428 "height": rightObject.height - verticalMove};
429
430 if (orientation == Qt.Horizontal) {
431 mouseDrag(tiledView, rightObject.x, rightObject.y/2, dragDistance, 0);
432 } else if (orientation == Qt.Vertical) {
433 mouseDrag(tiledView, rightObject.x/2, rightObject.y, 0, dragDistance);
434 }
435
436 compare(leftObject.x, expectedLeft.x);
437 compare(leftObject.y, expectedLeft.y);
438 compare(leftObject.width, expectedLeft.width);
439 compare(leftObject.height, expectedLeft.height);
440 compare(rightObject.x, expectedRight.x);
441 compare(rightObject.y, expectedRight.y);
442 compare(rightObject.width, expectedRight.width);
443 compare(rightObject.height, expectedRight.height);
444 }
445
446 function test_resizeSplit_data() {
447 return [
448 {orientation: Qt.Horizontal, distance: 100},
449 {orientation: Qt.Vertical, distance: 100},
450 ];
451 }
452
453 function test_resizeSplit(data) {
454 var leftObject = objectComponent.createObject(tiledView);
455 verifySetRootItem(leftObject);
456 verifySetOrientation(leftObject, data.orientation);
457
458 var rightObject = objectComponent.createObject(tiledView);
459 verifyAdd(leftObject, rightObject, Qt.AlignTrailing);
460
461 verifyResize(leftObject, rightObject, data.orientation, data.distance);
462
463 tiledView.setRootItem(null);
464 leftObject.destroy();
465 rightObject.destroy();
466 }
467 }
468}

Subscribers

People subscribed via source and target branches