Commit 47a8b89b authored by J-P Nurmi's avatar J-P Nurmi Committed by The Qt Project
Browse files

Introduce support for movable tabs


Change-Id: I87a6a582824363197f66f6b7f6f29aa603123458
Reviewed-by: default avatarCaroline Chao <caroline.chao@digia.com>
Reviewed-by: default avatarJens Bache-Wiig <jens.bache-wiig@digia.com>
parent 75642c48
6.2 5.10 5.11 5.12 5.12.1 5.12.10 5.12.11 5.12.12 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13 5.13.0 5.13.1 5.13.2 5.14 5.14.0 5.14.1 5.14.2 5.15 5.15.0 5.15.1 5.15.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.9.8 dev old/5.1 old/5.2 wip/calendar wip/tizen v5.15.0-alpha1 v5.14.1 v5.14.0 v5.14.0-rc2 v5.14.0-rc1 v5.14.0-beta3 v5.14.0-beta2 v5.14.0-beta1 v5.14.0-alpha1 v5.13.2 v5.13.1 v5.13.0 v5.13.0-rc3 v5.13.0-rc2 v5.13.0-rc1 v5.13.0-beta4 v5.13.0-beta3 v5.13.0-beta2 v5.13.0-beta1 v5.13.0-alpha1 v5.12.7 v5.12.6 v5.12.5 v5.12.4 v5.12.3 v5.12.2 v5.12.1 v5.12.0 v5.12.0-rc2 v5.12.0-rc1 v5.12.0-beta4 v5.12.0-beta3 v5.12.0-beta2 v5.12.0-beta1 v5.12.0-alpha1 v5.11.3 v5.11.2 v5.11.1 v5.11.0 v5.11.0-rc2 v5.11.0-rc1 v5.11.0-beta4 v5.11.0-beta3 v5.11.0-beta2 v5.11.0-beta1 v5.11.0-alpha1 v5.10.1 v5.10.0 v5.10.0-rc3 v5.10.0-rc2 v5.10.0-rc1 v5.10.0-beta4 v5.10.0-beta3 v5.10.0-beta2 v5.10.0-beta1 v5.10.0-alpha1 v5.9.9 v5.9.8 v5.9.7 v5.9.6 v5.9.5 v5.9.4 v5.9.3 v5.9.2 v5.9.1 v5.9.0 v5.9.0-rc2 v5.9.0-rc1 v5.9.0-beta4 v5.9.0-beta3 v5.9.0-beta2 v5.9.0-beta1 v5.9.0-alpha1 v5.8.0 v5.8.0-rc1 v5.8.0-beta1 v5.8.0-alpha1 v5.7.1 v5.7.0 v5.7.0-rc1 v5.7.0-beta1 v5.7.0-alpha1 v5.6.3 v5.6.2 v5.6.1 v5.6.1-1 v5.6.0 v5.6.0-rc1 v5.6.0-beta1 v5.6.0-alpha1 v5.5.1 v5.5.0 v5.5.0-rc1 v5.5.0-beta1 v5.5.0-alpha1 v5.4.2 v5.4.1 v5.4.0 v5.4.0-rc1 v5.4.0-beta1 v5.4.0-alpha1 v5.3.2 v5.3.1 v5.3.0 v5.3.0-rc1 v5.3.0-beta1 v5.3.0-alpha1 v5.2.1 v5.2.0 v5.2.0-rc1 v5.2.0-beta1 v5.2.0-alpha1 v5.1.1 v5.1.0 v5.1.0-rc2 v5.1.0-rc1
No related merge requests found
Showing with 127 additions and 51 deletions
...@@ -242,6 +242,7 @@ Item { ...@@ -242,6 +242,7 @@ Item {
tabOverlap: 16 tabOverlap: 16
tabsLeftPadding: 12 tabsLeftPadding: 12
frameOverlap: 4 frameOverlap: 4
tabsMovable: true
frame: Rectangle { frame: Rectangle {
gradient: Gradient{ gradient: Gradient{
......
...@@ -69,6 +69,8 @@ FocusScope { ...@@ -69,6 +69,8 @@ FocusScope {
property var style property var style
property var styleItem: tabView.__styleItem ? tabView.__styleItem : null property var styleItem: tabView.__styleItem ? tabView.__styleItem : null
property bool tabsMovable: styleItem ? styleItem.tabsMovable : false
property int tabsAlignment: styleItem ? styleItem.tabsAlignment : Qt.AlignLeft property int tabsAlignment: styleItem ? styleItem.tabsAlignment : Qt.AlignLeft
property int tabOverlap: styleItem ? styleItem.tabOverlap : 0 property int tabOverlap: styleItem ? styleItem.tabOverlap : 0
...@@ -84,11 +86,25 @@ FocusScope { ...@@ -84,11 +86,25 @@ FocusScope {
return null; return null;
} }
Row { ListView {
id: tabrow id: tabrow
objectName: "tabrow" objectName: "tabrow"
Accessible.role: Accessible.PageTabList Accessible.role: Accessible.PageTabList
spacing: -tabOverlap spacing: -tabOverlap
orientation: Qt.Horizontal
interactive: false
focus: true
width: contentItem ? contentItem.width : 0
height: currentItem ? currentItem.height : 0
displaced: Transition {
NumberAnimation {
property: "x"
duration: 125
easing.type: Easing.OutQuad
}
}
states: [ states: [
State { State {
...@@ -110,60 +126,113 @@ FocusScope { ...@@ -110,60 +126,113 @@ FocusScope {
} }
] ]
model: tabView.__tabs
Repeater { delegate: MouseArea {
id: repeater id: tabitem
objectName: "repeater" objectName: "mousearea"
hoverEnabled: true
focus: true focus: true
model: tabView.__tabs
drag.target: tabsMovable ? tabloader : null
delegate: Item { drag.axis: Drag.XAxis
id: tabitem drag.minimumX: drag.active ? 0 : -Number.MAX_VALUE
focus: true drag.maximumX: tabrow.width - tabitem.width
property int tabindex: index property int tabindex: index
property bool selected : tabView.currentIndex === index property bool selected : tabView.currentIndex === index
property bool hover: mousearea.containsMouse property bool hover: containsMouse
property string title: modelData.title property string title: modelData.title
property bool nextSelected: tabView.currentIndex === index + 1 property bool nextSelected: tabView.currentIndex === index + 1
property bool previousSelected: tabView.currentIndex === index - 1 property bool previousSelected: tabView.currentIndex === index - 1
z: selected ? 1 : -index z: selected ? 1 : -index
implicitWidth: Math.min(tabloader.implicitWidth, tabbar.width/repeater.count) + 1 implicitWidth: Math.min(tabloader.implicitWidth, tabbar.width/tabrow.count) + 1
implicitHeight: tabloader.implicitHeight implicitHeight: tabloader.implicitHeight
Loader { onPressed: {
id: tabloader tabView.currentIndex = index;
tabbar.nextItemInFocusChain(true).forceActiveFocus();
sourceComponent: loader.item ? loader.item.tab : null }
anchors.fill: parent
Loader {
property Item control: tabView id: tabloader
property int index: tabindex
property Item control: tabView
property QtObject tab: QtObject { property int index: tabindex
readonly property alias index: tabitem.tabindex
readonly property alias selected: tabitem.selected property QtObject tab: QtObject {
readonly property alias title: tabitem.title readonly property alias index: tabitem.tabindex
readonly property alias nextSelected: tabitem.nextSelected readonly property alias selected: tabitem.selected
readonly property alias previsousSelected: tabitem.previousSelected readonly property alias title: tabitem.title
readonly property alias hovered: tabitem.hover readonly property alias nextSelected: tabitem.nextSelected
readonly property bool activeFocus: tabbar.activeFocus readonly property alias previsousSelected: tabitem.previousSelected
} readonly property alias hovered: tabitem.hover
readonly property bool activeFocus: tabbar.activeFocus
} }
MouseArea { sourceComponent: loader.item ? loader.item.tab : null
id: mousearea
objectName: "mousearea" Drag.keys: "application/x-tabbartab"
anchors.fill: parent Drag.active: tabitem.drag.active
hoverEnabled: true Drag.source: tabitem
onPressed: {
tabView.currentIndex = index; property real __prevX: 0
tabbar.nextItemInFocusChain(true).forceActiveFocus(); property real __dragX: 0
onXChanged: {
if (Drag.active) {
// keep track for the snap back animation
__dragX = tabitem.mapFromItem(tabrow, tabloader.x, 0).x
// when moving to the left, the hot spot is the left edge and vice versa
Drag.hotSpot.x = x < __prevX ? 0 : width
__prevX = x
} }
} }
Accessible.role: Accessible.PageTab
Accessible.name: modelData.title width: tabitem.width
state: Drag.active ? "drag" : ""
transitions: [
Transition {
to: "drag"
PropertyAction { target: tabloader; property: "parent"; value: tabrow }
},
Transition {
from: "drag"
SequentialAnimation {
PropertyAction { target: tabloader; property: "parent"; value: tabitem }
NumberAnimation {
target: tabloader
duration: 50
easing.type: Easing.OutQuad
property: "x"
from: tabloader.__dragX
to: 0
}
}
}
]
}
Accessible.role: Accessible.PageTab
Accessible.name: modelData.title
}
}
DropArea {
anchors.fill: tabrow
keys: "application/x-tabbartab"
onPositionChanged: {
var source = drag.source
var target = tabrow.itemAt(drag.x, drag.y)
if (source && target && source !== target) {
source = source.drag.target
target = target.drag.target
var center = target.parent.x + target.width / 2
if ((source.index > target.index && source.x < center)
|| (source.index < target.index && source.x + source.width > center))
tabView.moveTab(source.index, target.index)
} }
} }
} }
......
...@@ -44,6 +44,7 @@ import QtQuick.Controls.Styles 1.0 ...@@ -44,6 +44,7 @@ import QtQuick.Controls.Styles 1.0
Style { Style {
id: root id: root
property bool tabsMovable: false
property int tabsLeftPadding: 0 property int tabsLeftPadding: 0
property int tabsRightPadding: 0 property int tabsRightPadding: 0
property int tabsAlignment: __barstyle.styleHint("tabbaralignment") === "center" ? Qt.AlignHCenter : Qt.AlignLeft; property int tabsAlignment: __barstyle.styleHint("tabbaralignment") === "center" ? Qt.AlignHCenter : Qt.AlignLeft;
......
...@@ -83,6 +83,10 @@ Style { ...@@ -83,6 +83,10 @@ Style {
/*! The \l ScrollView attached to this style. */ /*! The \l ScrollView attached to this style. */
readonly property TabView control: __control readonly property TabView control: __control
/*! This property holds whether the user can move the tabs.
Tabs are not movable by default. */
property bool tabsMovable: false
/*! This property holds the horizontal alignment of /*! This property holds the horizontal alignment of
the tab buttons. Supported values are: the tab buttons. Supported values are:
\list \list
......
...@@ -274,6 +274,7 @@ TestCase { ...@@ -274,6 +274,7 @@ TestCase {
compare(tabView.count, 2) compare(tabView.count, 2)
verify(tabView.tab1.status === Loader.Ready) verify(tabView.tab1.status === Loader.Ready)
verify(tabView.tab2.status === Loader.Ready) verify(tabView.tab2.status === Loader.Ready)
waitForRendering(tabView)
var column1 = getColumnItem(tabView.tab1, "column1") var column1 = getColumnItem(tabView.tab1, "column1")
verify(column1 !== null) verify(column1 !== null)
...@@ -294,7 +295,7 @@ TestCase { ...@@ -294,7 +295,7 @@ TestCase {
var mouseareas = populateMouseAreaItems(tabrowItem) var mouseareas = populateMouseAreaItems(tabrowItem)
verify(mouseareas.length, 2) verify(mouseareas.length, 2)
var tab1 = mouseareas[0].parent var tab1 = mouseareas[0]
verify(tab1 !== null) verify(tab1 !== null)
//printGeometry(tab1) //printGeometry(tab1)
...@@ -302,7 +303,7 @@ TestCase { ...@@ -302,7 +303,7 @@ TestCase {
mouseClick(tab1, tab1.width/2, tab1.height/2) mouseClick(tab1, tab1.width/2, tab1.height/2)
verify(child1.activeFocus) verify(child1.activeFocus)
var tab2 = mouseareas[1].parent var tab2 = mouseareas[1]
verify(tab2 !== null) verify(tab2 !== null)
//printGeometry(tab2) //printGeometry(tab2)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment