Hunker
Hunker

Reputation: 97

How to add a editable TableView header in qml?

import QtQuick 2.7
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3

Rectangle {
    width: 640
    height: 480
    ListModel {
        id: tstModel
        ListElement { animal: "dog" }
    }
    TableView {
        id: tableView
        anchors.fill: parent
        model: tstModel

        headerDelegate: Item{
            height: 50
            width: animalColumn.width
            TextField{
                text: styleData.value
                anchors.fill: parent
            }
        }
        TableViewColumn {
            id: animalColumn
            title: "Animal"
            role: "animal"
            width: 50
            resizable: false
            movable:  false
        }
    }
}

This code is not acting as I expect. Textfield gets focus only when I am clicking the header with right button. And there is a Textfield works fine next to the first column header, but it's not what I want.

How to add a editable TableView header in qml?

Upvotes: 2

Views: 1891

Answers (1)

rsht
rsht

Reputation: 1582

I find this headerDelegate to be rather buggy or not supposed to be used in this scenario. I would rather implemnt a header from scrath to use for your use-case. Try this as a starting point:

Rectangle {
    width: 640
    height: 480

    ListModel {
        id: tstModel
        ListElement { animal: "cat" }
        ListElement { animal: "cat" }
        ListElement { animal: "cat" }
        ListElement { animal: "cat" }
        ListElement { animal: "cat" }
        ListElement { animal: "cat" }
        ListElement { animal: "cat" }
    }


    TextField{
        id: tableViewCustomHeader

        property int curRow: tableView.currentRow
        property bool isActual: curRow >= 0

        function reloadText() { text = tstModel.get(curRow).animal }
        function saveText()   { tstModel.setProperty(curRow, "animal", text); tableView.model = tstModel;  }

        width: animalColumn.width
        height: isActual ? 20 : 0

        onCurRowChanged: {
            if ( isActual >= 0 ) reloadText();
            focus = true;
        }
        onTextChanged: if ( isActual >= 0 ) saveText()
    }

    TableView {
        id: tableView
        anchors {
            top: tableViewCustomHeader.bottom
            bottom: parent.bottom
            left: parent.left
            right: parent.right
        }

        model: tstModel
        headerVisible: false

        TableViewColumn {
            id: animalColumn

            title: "Animal"
            role: "animal"
            width: 200
            resizable: false
            movable:  false
        }
    }
}

You can edit this anyway you want afterwards.

If it's a strict requirement to go with headerDelegate - this what I've end up with:

Rectangle {
    width: 640
    height: 480

    ListModel {
        id: tstModel
        ListElement { animal: "dog" }
        ListElement { animal: "cat" }
    }

    TableView {
        id: tableView
        anchors.fill: parent
        model: tstModel

        headerDelegate:
            TextField{
                property int curRow: tableView.currentRow

                function reloadText() { text = tstModel.get(curRow).animal }
                function saveText()   { tstModel.setProperty(curRow, "animal", text); tableView.model = tstModel;  }

                onCurRowChanged: {
                    if ( curRow >= 0 ) reloadText()
                }
                onTextChanged: saveText()
                width: parent.width
        }

        TableViewColumn {
            id: animalColumn

            title: "Animal"
            role: "animal"
            width: 200
            resizable: false
            movable:  false
        }
    }

}

But, again, it works in a very strange way once you are adding TextField to it, so I would vote against it.

Upvotes: 1

Related Questions