123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- /****************************************************************************
- **
- ** Copyright (C) 2016 The Qt Company Ltd.
- ** Contact: https://www.qt.io/licensing/
- **
- ** This file is part of the Qt Quick Controls module of the Qt Toolkit.
- **
- ** $QT_BEGIN_LICENSE:LGPL$
- ** Commercial License Usage
- ** Licensees holding valid commercial Qt licenses may use this file in
- ** accordance with the commercial license agreement provided with the
- ** Software or, alternatively, in accordance with the terms contained in
- ** a written agreement between you and The Qt Company. For licensing terms
- ** and conditions see https://www.qt.io/terms-conditions. For further
- ** information use the contact form at https://www.qt.io/contact-us.
- **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 3 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL3 included in the
- ** packaging of this file. Please review the following information to
- ** ensure the GNU Lesser General Public License version 3 requirements
- ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
- **
- ** GNU General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU
- ** General Public License version 2.0 or (at your option) the GNU General
- ** Public license version 3 or any later version approved by the KDE Free
- ** Qt Foundation. The licenses are as published by the Free Software
- ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
- ** included in the packaging of this file. Please review the following
- ** information to ensure the GNU General Public License requirements will
- ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
- ** https://www.gnu.org/licenses/gpl-3.0.html.
- **
- ** $QT_END_LICENSE$
- **
- ****************************************************************************/
- import QtQuick 2.2
- import QtQuick.Controls 1.2
- import QtQuick.Controls.Private 1.0
- /*!
- \qmltype TabView
- \inqmlmodule QtQuick.Controls
- \since 5.1
- \ingroup views
- \ingroup controls
- \brief A control that allows the user to select one of multiple stacked items.
- \image tabview.png
- TabView provides tab-based navigation model for your application.
- For example, the following snippet uses tabs to present rectangles of
- different color on each tab page:
- \qml
- TabView {
- Tab {
- title: "Red"
- Rectangle { color: "red" }
- }
- Tab {
- title: "Blue"
- Rectangle { color: "blue" }
- }
- Tab {
- title: "Green"
- Rectangle { color: "green" }
- }
- }
- \endqml
- \note You can create a custom appearance for a TabView by
- assigning a \l {TabViewStyle}.
- \l Tab represents the content of a tab in a TabView.
- */
- FocusScope {
- id: root
- implicitWidth: 240
- implicitHeight: 150
- /*! The current tab index */
- property int currentIndex: 0
- /*! The current tab count */
- readonly property int count: __tabs.count
- /*! The visibility of the tab frame around contents */
- property bool frameVisible: true
- /*! The visibility of the tab bar */
- property bool tabsVisible: true
- /*!
- \qmlproperty enumeration TabView::tabPosition
- \list
- \li Qt.TopEdge (default)
- \li Qt.BottomEdge
- \endlist
- */
- property int tabPosition: Qt.TopEdge
- /*!
- \qmlproperty Item TabView::contentItem
- \since QtQuick.Controls 1.3
- This property holds the content item of the tab view.
- Tabs declared as children of a TabView are automatically parented to the TabView's contentItem.
- */
- readonly property alias contentItem: stack
- /*! \internal */
- default property alias data: stack.data
- /*!
- \qmlmethod Tab TabView::addTab(string title, Component component)
- Adds a new tab with the given \a title and an optional \a component.
- Returns the newly added tab.
- */
- function addTab(title, component) {
- return insertTab(__tabs.count, title, component)
- }
- /*!
- \qmlmethod Tab TabView::insertTab(int index, string title, Component component)
- Inserts a new tab at \a index, with the given \a title and
- an optional \a component.
- Returns the newly added tab.
- */
- function insertTab(index, title, component) {
- var tab = tabcomp.createObject()
- tab.sourceComponent = component
- tab.title = title
- // insert at appropriate index first, then set the parent to
- // avoid onChildrenChanged appending it to the end of the list
- __tabs.insert(index, {tab: tab})
- tab.__inserted = true
- tab.parent = stack
- __didInsertIndex(index)
- __setOpacities()
- return tab
- }
- /*! \qmlmethod void TabView::removeTab(int index)
- Removes and destroys a tab at the given \a index. */
- function removeTab(index) {
- var tab = __tabs.get(index).tab
- __willRemoveIndex(index)
- __tabs.remove(index, 1)
- tab.destroy()
- __setOpacities()
- }
- /*! \qmlmethod void TabView::moveTab(int from, int to)
- Moves a tab \a from index \a to another. */
- function moveTab(from, to) {
- __tabs.move(from, to, 1)
- if (currentIndex == from) {
- currentIndex = to
- } else {
- var start = Math.min(from, to)
- var end = Math.max(from, to)
- if (currentIndex >= start && currentIndex <= end) {
- if (from < to)
- --currentIndex
- else
- ++currentIndex
- }
- }
- }
- /*! \qmlmethod Tab TabView::getTab(int index)
- Returns the \l Tab item at \a index. */
- function getTab(index) {
- var data = __tabs.get(index)
- return data && data.tab
- }
- /*! \internal */
- property ListModel __tabs: ListModel { }
- /*! \internal */
- property Component style: Settings.styleComponent(Settings.style, "TabViewStyle.qml", root)
- /*! \internal */
- property var __styleItem: loader.item
- onCurrentIndexChanged: __setOpacities()
- /*! \internal */
- function __willRemoveIndex(index) {
- // Make sure currentIndex will points to the same tab after the removal.
- // Also activate the next index if the current index is being removed,
- // except when it's both the current and last index.
- if (count > 1 && (currentIndex > index || currentIndex == count -1))
- --currentIndex
- }
- function __didInsertIndex(index) {
- // Make sure currentIndex points to the same tab as before the insertion.
- if (count > 1 && currentIndex >= index)
- currentIndex++
- }
- function __setOpacities() {
- for (var i = 0; i < __tabs.count; ++i) {
- var child = __tabs.get(i).tab
- child.visible = (i == currentIndex ? true : false)
- }
- }
- activeFocusOnTab: false
- Component {
- id: tabcomp
- Tab {}
- }
- TabBar {
- id: tabbarItem
- objectName: "tabbar"
- tabView: root
- style: loader.item
- anchors.top: parent.top
- anchors.left: root.left
- anchors.right: root.right
- }
- Loader {
- id: loader
- z: tabbarItem.z - 1
- sourceComponent: style
- property var __control: root
- }
- Loader {
- id: frameLoader
- z: tabbarItem.z - 1
- anchors.fill: parent
- anchors.topMargin: tabPosition === Qt.TopEdge && tabbarItem && tabsVisible ? Math.max(0, tabbarItem.height - baseOverlap) : 0
- anchors.bottomMargin: tabPosition === Qt.BottomEdge && tabbarItem && tabsVisible ? Math.max(0, tabbarItem.height -baseOverlap) : 0
- sourceComponent: frameVisible && loader.item ? loader.item.frame : null
- property int baseOverlap: __styleItem ? __styleItem.frameOverlap : 0
- Item {
- id: stack
- anchors.fill: parent
- anchors.margins: (frameVisible ? frameWidth : 0)
- anchors.topMargin: anchors.margins + (style =="mac" ? 6 : 0)
- anchors.bottomMargin: anchors.margins
- property int frameWidth
- property string style
- property bool completed: false
- Component.onCompleted: {
- addTabs(stack.children)
- completed = true
- }
- onChildrenChanged: {
- if (completed)
- stack.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
- // reparent tabs created dynamically by createObject(tabView)
- tab.parent = stack
- // a dynamically added tab should also get automatically removed when destructed
- if (completed)
- tab.Component.onDestruction.connect(stack.onDynamicTabDestroyed.bind(tab))
- __tabs.append({tab: tab})
- tabAdded = true
- }
- }
- if (tabAdded)
- __setOpacities()
- }
- function onDynamicTabDestroyed() {
- for (var i = 0; i < __tabs.count; ++i) {
- if (__tabs.get(i).tab === this) {
- __willRemoveIndex(i)
- __tabs.remove(i, 1)
- __setOpacities()
- break
- }
- }
- }
- }
- onLoaded: { item.z = -1 }
- }
- onChildrenChanged: stack.addTabs(root.children)
- states: [
- State {
- name: "Bottom"
- when: tabPosition === Qt.BottomEdge && tabbarItem != undefined
- PropertyChanges {
- target: tabbarItem
- anchors.topMargin: -frameLoader.baseOverlap
- }
- AnchorChanges {
- target: tabbarItem
- anchors.top: frameLoader.bottom
- }
- }
- ]
- }
|