Get active Tab from TabView and change item property

柔情痞子 提交于 2020-01-24 09:31:07

问题


In the context of a dual-pane file manager, I have two TabView items side by side, each contains multiple tabs of course, and each Tab loads a TableView showing the content of a specific directory using FolderListModel.

SplitView
    TabView
        Tab
        Tab
    TabView
        Tab

My current task is to implement a toolbar button to toggle the showHidden property of the FolderListModel instance shown in the active tab. Therefore, I need a way to find out what the currently active tab is.

Next, once I get the active Tab, I need to change Tab.item.some_property, in particular, the property of interest is show_hidden, which is an alias to the showHidden property of the underlying FolderListModel. For example, a hard-coded scenario would be:

ToolButton {
    onClicked: {
        tab1.item.show_hidden = false;
        tab1.destroy();  // need "refresh" instead
    }
}

First I need to get tab1 based on whether it is active, and second, after I change show_hidden, the view doesn't refresh by itself, so I need to call some kind of reload function, but which? Or maybe reload isn't the best way to do it? Is it possible to do it using a custom signal handler? (Again I can only think conceptually without knowing how to implement it.)

As suggested I'm posting a running example below:

/* main.qml */
import QtQuick 2.4
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1

ApplicationWindow {
    visible: true
    width: 1280
    height: 700

    toolBar: ToolBar {
        RowLayout {
            anchors.fill: parent

            ToolButton {
                onClicked: {    // TODO toggle folderModel.showHidden property
                    tab1A.item.show_hidden = false;
//                    tab1A.destroy();  // fixme how to refresh the view?
                }
            }
        }
    }

    Item {
        anchors.fill: parent

        SplitView {
            id: splitView
            anchors.fill: parent

            TabView {
                id: tabView1
                width: splitView.width / 2

                Tab {
                    id: tab1A

                    title: qsTr("Home")
                    source: "dirview.qml"

                    onLoaded: {
                        item.folder_url = "file:///tmp";
                    }
                }

                Tab {
                    title: qsTr("Folder")
                    source: "dirview.qml"
                    onLoaded: {
                        item.folder_url = "file:///home";
                    }
                }
            }

            TabView {
                id: tabView2

                Tab {
                    title: qsTr("Home")
                    source: "dirview.qml"
                    onLoaded: {
                        item.folder_url = "file:///home";
                    }
                }
            }
        }
    }
}

/* dirview.qml */
import QtQuick 2.4
import QtQuick.Controls 1.4
import Qt.labs.folderlistmodel 2.1

TableView {
    property alias folder_url: folderModel.folder
    property alias show_hidden: folderModel.showHidden

    id: tableView
    anchors.fill: parent

    TableViewColumn {
        role: "fileName"
        title: qsTr("Name")
        width: tableView.width * 0.7
    }

    TableViewColumn {
        role: "fileSize"
        title: qsTr("Size")
        width: tableView.width * 0.2
    }

    FolderListModel {
        id: folderModel
        nameFilters: ["*"]
        showHidden: true
        showDirsFirst: true
        showDotAndDotDot: true
    }

    model: folderModel
}

Thank you.


Noticed something weird: Tab.item.folder_url has the right info, however, Tab.item.show_hidden is always false, even if I remove the line where I manually set it to false. This is hard to understand as I initially set FolderListModel.showHidden to true in dirview.qml.

ToolButton {
    onClicked: {    // TODO toggle folderModel.showHidden property
        var cur_tab_idx = tabView1.currentIndex;

        console.log(tabView1.getTab(cur_tab_idx).item.folder_url);
        console.log(tabView1.getTab(cur_tab_idx).item.show_hidden);
    }
}

回答1:


Here is an explanation of how I have got it to work.

I solved first problem using focus flag. When current Tab in TabView changes one Tab gains focus and the other one looses. So by using onFocusChanged() signal you can know exactly when one Tab becomes active or inactive.
The focus of Tab does not change when focus of whole TabView changes. Because of this I created an Array (named tabs in code) containing references to every TabView and Tab it contains. With this when TabView becomes inactive I can set focus of its Tab objects to false using simple for.

Second problem was more tricky. I see no other option of turning showHidden flag off than destroying and creating a new FolderListModel. We cannot (or I could not :) ) provide model to TableView dynamically so I made a ListModel. Advantage of regular ListModel compared to FolderListModel is that it can be cleared and refilled with data. Every time folder_url or show_hidden changes I destroy current FolderListModel and create a new one. After it is created I rewrite its data to the ListModel.


Here is the working code.

main.qml

/* main.qml */
import QtQuick 2.4
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1

ApplicationWindow {
    visible: true
    width: 1280
    height: 700

    property var tabs: [
        [tabView1, [tab1A, tab1B]],
        [tabView2, [tab2A]]
    ]

    toolBar: ToolBar {
        RowLayout {
            anchors.fill: parent

            ToolButton {
                onClicked: {    // TODO toggle folderModel.showHidden property
                    tab1A.item.show_hidden = false;
//                    tab1A.destroy();  // fixme how to refresh the view?
                }
            }
        }
    }

    Item {
        anchors.fill: parent

        SplitView {
            id: splitView
            anchors.fill: parent

            TabView {
                id: tabView1
                width: splitView.width / 2

                Tab {
                    id: tab1A

                    title: qsTr("Home")
                    source: "dirview.qml"

                    onLoaded: {
                        item.folder_url = "file:///tmp";
                    }
                    onFocusChanged: {
                        item.show_hidden = focus
                    }
                }
                onFocusChanged: {
                    if (!focus)
                        for (var i = 0 ; i < tabs[0][1].length ; i++)
                            tabs[0][1][i].focus = false
                }

                Tab {
                    id: tab1B
                    title: qsTr("Folder")
                    source: "dirview.qml"
                    onLoaded: {
                        item.folder_url = "file:///home";
                    }
                    onFocusChanged: {
                        item.show_hidden = focus
                    }
                }
            }

            TabView {
                id: tabView2

                Tab {
                    id: tab2A
                    title: qsTr("Home")
                    source: "dirview.qml"
                    onLoaded: {
                        item.folder_url = "file:///tmp";
                    }
                    onFocusChanged: {
                        item.show_hidden = focus
                    }
                }
                onFocusChanged: {
                    if (!focus)
                        for (var i = 0 ; i < tabs[1][1].length ; i++)
                            tabs[1][1][i].focus = false
                }
            }
        }
    }
}

dirview.qml

/* dirview.qml */
import QtQuick 2.4
import QtQuick.Controls 1.4
import Qt.labs.folderlistmodel 2.1

TableView {
    property string folder_url
    property bool show_hidden

    id: tableView
    anchors.fill: parent

    TableViewColumn {
        role: "fileName"
        title: qsTr("Name")
        width: tableView.width * 0.7
    }

    TableViewColumn {
        role: "fileSize"
        title: qsTr("Size")
        width: tableView.width * 0.2
    }

    ListModel {
        id: secondListModel
    }

    property var fm
    property int folderModelCount

    onFolder_urlChanged: {
        reloadFolderModel()
    }
    onShow_hiddenChanged: {
        reloadFolderModel()
    }

    onFolderModelCountChanged: {
        resetSecondListModel()
    }

    function reloadFolderModel() {
        folderModelCount = 0
        if (typeof(fm) !== "undefined")
            fm.destroy()

        var component = Qt.createComponent("foldermodel.qml")
        if (component.status === Component.Ready)
            fm = component.createObject(
                        tableView, {"folder_url": folder_url, "show_hidden": show_hidden})
        else
            console.error(component.errorString())

        folderModelCount =
                Qt.binding(function(){return fm.folderModel.count})
    }

    function resetSecondListModel() {
        secondListModel.clear()
        for (var i = 0 ; i < folderModelCount ; i++) {
            secondListModel.append({
                                       "fileName": fm.folderModel.get(i, "fileName"),
                                       "filePath": fm.folderModel.get(i, "filePath"),
                                       "fileURL": fm.folderModel.get(i, "fileURL"),
                                       "fileBaseName": fm.folderModel.get(i, "fileBaseName"),
                                       "fileSuffix": fm.folderModel.get(i, "fileSuffix"),
                                       "fileSize": fm.folderModel.get(i, "fileSize"),
                                       "fileModified": fm.folderModel.get(i, "fileModified"),
                                       "fileAccessed": fm.folderModel.get(i, "fileAccessed"),
                                       "fileIsDir": fm.folderModel.get(i, "fileIsDir")
                                   })
        }
    }

    model: secondListModel
}

foldermodel.qml (add this file)

import QtQuick 2.4
import QtQuick.Controls 1.4
import Qt.labs.folderlistmodel 2.1

Item {
    property string folder_url
    property bool show_hidden
    property alias folderModel: folderModelObject
    FolderListModel {
        id: folderModelObject
        nameFilters: ["*"]
        folder: folder_url
        showHidden: show_hidden
        showDirsFirst: true
        showDotAndDotDot: true
    }
}

Now you understand why QML is not very flexible. :)




回答2:


Solution to finding the current Tab in the active TabView (pane): declare a property of SplitView to store the TabView that has activeFocus.

A StatusBar is added to demo the functionality.

import QtQuick 2.4
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1

ApplicationWindow {
    visible: true
    width: 1280
    height: 700

    toolBar: ToolBar {
        RowLayout {
            anchors.fill: parent

            ToolButton {
                onClicked: {    // TODO toggle folderModel.showHidden property
                    // Demo: get the current tab of the active pane
                    var active_pane = splitView.activePane;
                    var cur_tab_idx = active_pane.currentIndex;
                    var cur_tab_item = active_pane.getTab(cur_tab_idx).item;
                    testLabel.text = cur_tab_item.folder_url;
                }
            }
        }
    }

    SplitView {
        id: splitView

        property TabView activePane: tabView1

        anchors.fill: parent

        TabView {
            id: tabView1
            width: splitView.width / 2

            onActiveFocusChanged: {
                if (activeFocus) {
                    splitView.activePane = tabView1;
                }
            }

            Tab {
                title: qsTr("tmp")
                source: "dirview.qml"
                onLoaded: {
                    item.folder_url = "file:///tmp";
                }
            }

            Tab {
                title: qsTr("home")
                source: "dirview.qml"
                onLoaded: {
                    item.folder_url = "file:///home";
                }
            }
        }

        TabView {
            id: tabView2

            onActiveFocusChanged: {
                if (activeFocus) {
                    splitView.activePane = tabView2;
                }
            }

            Tab {
                title: qsTr("bin")
                source: "dirview.qml"
                onLoaded: {
                    item.folder_url = "file:///bin";
                }
            }
        }
    }
    statusBar: StatusBar {
        RowLayout {
            Label {
                text: (splitView.activePane === tabView1) ? "Pane 1" : "Pane 2"
            }
            Label {
                id: testLabel
            }
        }
    }
}


来源:https://stackoverflow.com/questions/33557271/get-active-tab-from-tabview-and-change-item-property

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!