From a6deb27ba0252bc06fd6f28fb76b552e6320853f Mon Sep 17 00:00:00 2001 From: J-P Nurmi <jpnurmi@digia.com> Date: Tue, 30 Apr 2013 14:18:03 +0200 Subject: [PATCH] Fix TabView not to insert duplicate tabs There are three ways to add tabs: - declare 'static' Tab { } child elements - call addTab() / insertTab() - Component::createObject(tabView) => Do not rely on the calling order of Component.onCompleted() and make sure that the same tabs are not accidentally re-inserted. Task-number: QTBUG-30873 Change-Id: Ib30cfb676debbb302c5e9f7d757f66aab6fcc684 Reviewed-by: Caroline Chao <caroline.chao@digia.com> --- src/controls/Tab.qml | 4 ++ src/controls/TabView.qml | 48 +++++++++++------------- tests/auto/controls/data/tst_tabview.qml | 39 +++++++++++++------ 3 files changed, 54 insertions(+), 37 deletions(-) diff --git a/src/controls/Tab.qml b/src/controls/Tab.qml index 0f88e2388..0cf263410 100644 --- a/src/controls/Tab.qml +++ b/src/controls/Tab.qml @@ -57,6 +57,10 @@ Loader { /*! This property holds the title of the tab. */ property string title + + /*! \internal */ + property bool __inserted: false + Accessible.role: Accessible.LayeredPane active: false visible: false diff --git a/src/controls/TabView.qml b/src/controls/TabView.qml index 6bcaab75c..153c24005 100644 --- a/src/controls/TabView.qml +++ b/src/controls/TabView.qml @@ -85,13 +85,7 @@ FocusScope { Returns the newly added tab. */ function addTab(title, component) { - var tab = tabcomp.createObject(stack) - tab.sourceComponent = component - __tabs.append({tab: tab}) - tab.parent = stack - tab.title = title - __setOpacities() - return tab + return insertTab(__tabs.count, title, component) } /*! Inserts a new tab with title at index, with an optional Component. @@ -102,6 +96,7 @@ FocusScope { tab.sourceComponent = component tab.parent = stack tab.title = title + tab.__inserted = true __tabs.insert(index, {tab: tab}) __setOpacities() return tab @@ -206,12 +201,26 @@ FocusScope { property string style property int baseOverlap - Component.onCompleted: { - for (var i = 0 ; i < stack.children.length ; ++i) { - if (stack.children[i].Accessible.role === Accessible.LayeredPane) - __tabs.append({tab: stack.children[i]}) + Component.onCompleted: addTabs(stack.children) + + function addTabs(tabs) { + var tabAdded = false + for (var i = 0 ; i < tabs.length ; ++i) { + var tab = tabs[i] + if (!tab.__inserted && tab.Accessible.role === Accessible.LayeredPane) { + tab.__inserted = true + if (tab.parent === root) { + tab.parent = stack + // a tab added dynamically by Component::createObject() and passing the + // tab view as a parent should also get automatically removed when destructed + tab.Component.onDestruction.connect(stack.onDynamicTabDestroyed.bind(tab)) + } + __tabs.append({tab: tab}) + tabAdded = true + } } - __setOpacities() + if (tabAdded) + __setOpacities() } function onDynamicTabDestroyed() { @@ -226,20 +235,7 @@ FocusScope { onLoaded: { item.z = -1 } } - onChildrenChanged: { - var tabAdded = false - for (var i = 0; i < children.length; ++i) { - var child = children[i] - if (child.Accessible.role === Accessible.LayeredPane) { - __tabs.append({tab: child}) - child.parent = stack - child.Component.onDestruction.connect(stack.onDynamicTabDestroyed.bind(child)) - tabAdded = true - } - } - if (tabAdded) - __setOpacities() - } + onChildrenChanged: stack.addTabs(root.children) states: [ State { diff --git a/tests/auto/controls/data/tst_tabview.qml b/tests/auto/controls/data/tst_tabview.qml index 973b6fde5..ad1322658 100644 --- a/tests/auto/controls/data/tst_tabview.qml +++ b/tests/auto/controls/data/tst_tabview.qml @@ -192,18 +192,35 @@ TestCase { } function test_dynamicTabs() { - var tabView = Qt.createQmlObject('import QtQuick 2.1; import QtQuick.Controls 1.0; TabView { property Component tabComponent: Component { Tab { } } }', testCase, ''); - compare(tabView.count, 0) - var tab1 = tabView.tabComponent.createObject(tabView) - compare(tabView.count, 1) - var tab2 = tabView.tabComponent.createObject(tabView) - compare(tabView.count, 2) - tab1.destroy() - wait(0) - compare(tabView.count, 1) - tab2.destroy() + var test_tabView = ' \ + import QtQuick 2.1; \ + import QtQuick.Controls 1.0; \ + TabView { \ + id: tabView; \ + Tab { title: "static" } \ + property Component tabComponent: Component { \ + id: tabComponent; \ + Tab { title: "dynamic" } \ + } \ + Component.onCompleted: { \ + addTab("added", tabComponent); \ + insertTab(0, "inserted", tabComponent); \ + tabComponent.createObject(tabView); \ + } \ + } ' + + var tabView = Qt.createQmlObject(test_tabView, testCase, '') + // insertTab(), addTab(), createObject() and static Tab {} + compare(tabView.count, 4) + compare(tabView.tabAt(0).title, "inserted") + + var tab = tabView.tabComponent.createObject(tabView) + compare(tabView.count, 5) + compare(tabView.tabAt(4).title, "dynamic") + tab.destroy() wait(0) - compare(tabView.count, 0) + compare(tabView.count, 4) + tabView.destroy() } function test_mousePressOnTabBar() { -- GitLab