How to display the text file content in Qml List view



  • Hi all,

    I am trying to display the contents of text file in list view in qml, but facing few problems. for example i have an text file a.txt which contains few names, if i want to display this names in listview how can i do that ?

    I have tried sending the values through a c++ file, using a signal, the content is sent and i am able to receive the data, but when i try to display it in the list view i am getting only the last data which is sent through the signal.

    can anyone please guide me further, here is the code which i have tried

    Thank you
    .cpp file

    #include "systemscript.h"
    
    SystemScript::SystemScript(QWidget *parent) : QWidget(parent)
    {
    
    }
    
    void SystemScript::vRunBluetoothOnScript()
    {
        qDebug()<<Q_FUNC_INFO<<"entered this function"<<endl;
        system("hciconfig hci0 on");
        system("hciconfig hci0 piscan");
    }
    
    void SystemScript::vRunScanDeviceScript()
    {
        qDebug()<<Q_FUNC_INFO<< "entered this function"<< endl;
    
        QFile file("/home/user/list.txt");
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){
            qDebug()<<" file not opened !!!"<< endl;
        }
    
        while (!file.atEnd()) {
            QByteArray line = file.readLine();
    
            str= QString::fromStdString(line.toStdString());
            deviceList.append(str);
            count ++;
        }
        qDebug()<<count<<endl;
        for( int i=0;i<count;i++) {
    
        qDebug()<<"file data>>>>"<<deviceList.at(i)<<endl;
        QString sendDevName= deviceList.at(i);
        qDebug()<<"data to be sent >>>"<<sendDevName<<endl;
    
    
        emit vSendDeviceName(sendDevName);
        }
    }
    
    

    .qml file

    import QtQuick 2.6
    import QtQuick.Controls 1.4
    import QtQuick.Controls.Styles 1.4
    import QtQuick.Layouts 1.1
    import QtQuick.Dialogs 1.2
    import Qt.labs.folderlistmodel 2.1
    
    Rectangle {
        id: mainRect
        implicitHeight: appWindow.height
        implicitWidth: appWindow.width
        color: "Transparent"
        property string receivedDeviceName;
    
        Image {
            id: backgroundImage
            source: "qrc:/bg.jpg"
            width: parent.width
            height: parent.height
        }
    
        Connections{
            target: BluetoothObject
    
            onVSendDeviceName :{
    //            console.log("device names>>>"+ DevName)
    
                receivedDeviceName = DevName.slice(6)
                console.log(receivedDeviceName)
            }
        }
    
    
        RowLayout{
            anchors.fill: parent
            Rectangle {
                id: bluetoothOptionsRect
                Layout.fillHeight: true
                Layout.preferredWidth: (mainRect.width/2)-(mainRect.width/6)
                color: "transparent"
                ColumnLayout{
                    anchors.fill: parent
                    Rectangle{
                        Layout.fillWidth: true
                        Layout.preferredHeight: ((bluetoothOptionsRect.height/2)-(bluetoothOptionsRect.height/3))-35
                        color: "Transparent"
                        Rectangle{
                            id: bluetoothlabelRect
                            implicitHeight: parent.height-10
                            implicitWidth: parent.width-10
                            anchors.centerIn: parent
                            color: "Grey"
                            radius: 5
                            opacity: 0.6
                            RowLayout{
                                anchors.fill: parent
                                Label {
                                    id: bluetoothlabel
                                    text: "Bluetooth"
                                    font.pixelSize: 24
                                    color: "#ffffff"
                                    Layout.alignment: Qt.AlignHCenter
                                }
                                Switch{
                                    id: bluetoothSwitch
                                    Layout.alignment: Qt.AlignHCenter
    
                                    onClicked: {
                                        if(bluetoothSwitch.checked){
                                            BluetoothObject.vRunBluetoothOnScript()
                                        }
                                    }
                                }
                            }
                        }
                    }
                    Rectangle{
                        id: deviceListRect
                        Layout.fillWidth: true
                        Layout.fillHeight: true
                        color: "Grey"
                        radius: 5
                        Layout.leftMargin: 5
    
                        ListModel{
                            id: bluetoothListModel
                            ListElement{
                                name: "receivedDeviceName"
                            }
                            ListElement{
                                name: "receivedDeviceName"
                            }
                            ListElement{
                                name: "receivedDeviceName"
                            }
                        }
    
                        Component{
                            id: bluetoothListDelegate
                            Button{
                                id: deviceLabelComponent
                                width: deviceListRect.width
                                height: deviceListRect.height/10
    
                                RowLayout{
                                    anchors.fill: parent
    
                                    Rectangle{
                                        id:bluetoothlistlabelrect
                                        Layout.preferredWidth: deviceLabelComponent.width/2
                                        Layout.fillHeight: true
                                        color: "transparent"
                                        Label {
                                            id: bluetoothListLabel
                                            text: receivedDeviceName
                                            width: parent.width
                                            anchors.verticalCenter: parent.verticalCenter
                                            elide: Label.ElideRight
                                            color: "#000000"
                                            font.pixelSize: 18
                                            font.family:"Myriad Pro"
    
                                        }
                                    }
                                }
                                style: ButtonStyle{
                                    background: Rectangle{
                                        id: buttonBG
                                        implicitHeight: parent.height
                                        implicitWidth: parent.width
                                        color: "#607d8b"
                                        opacity: deviceLabelComponent.pressed ? 0.5: 1.0
                                        radius: 5
                                    }
                                }
                            }
                        }
                        ListView {
                            id: bluetoothListView
                            anchors.fill: parent
                            width: parent.width
                            height: parent.height
                            model: bluetoothListModel
                            delegate: bluetoothListDelegate
                        }
                    }
                    Rectangle{
                        Layout.fillWidth: true
                        Layout.leftMargin: 5
                        Layout.bottomMargin: 5
                        Layout.preferredHeight: ((bluetoothOptionsRect.height/2)-(bluetoothOptionsRect.height/3))-35
                        color: "transparent"
                        opacity: 0.6
                        Button{
                            id: scanButton
                            implicitHeight: parent.height
                            implicitWidth: parent.width
                            style: ButtonStyle{
                                background: Rectangle{
                                    color: "Grey"
                                    radius: 5
                                }
                            }
                            RowLayout{
                                anchors.fill: parent
                                Text{
                                    id: scanText
                                    text: "Scan for Device"
                                    font.pixelSize: 22
                                    color: "#ffffff"
                                    Layout.alignment: Qt.AlignHCenter
                                }
                                Rectangle{
                                    id: scanSymbolRect
                                    Layout.preferredHeight: 35
                                    Layout.preferredWidth: 35
                                    color: "red"
                                    visible: false
                                    Layout.alignment: Qt.AlignHCenter
                                    AnimatedImage{
                                        width: parent.width
                                        height: parent.height
                                        source: "qrc:/loading.gif"
                                    }
                                }
                            }
                            onClicked: {
                                scanSymbolRect.visible= true
                                scanText.text= "Scanning..."
                                BluetoothObject.vRunScanDeviceScript()
                            }
                        }
                    }
                }
            }
            Rectangle {
                id: bluetoothConnectivityRect
                Layout.fillHeight: true
                Layout.fillWidth: true
                color: "Transparent"
                ColumnLayout{
                    anchors.fill: parent
                    Rectangle{
                        id: bluetoothIconRect
                        Layout.fillHeight: true
                        Layout.fillWidth: true
                        color: "Transparent"
                        Image {
                            id: bluetoorhImage
                            source: "qrc:/bluetooth-headphone.png"
                            height:  (parent.height/2)+(parent.height/6)
                            width: (parent.width/2)+(parent.width/6)
                            anchors.centerIn: parent
                        }
                    }
                    Rectangle{
                        id: connectOptionsRect
                        Layout.fillWidth: true
                        Layout.bottomMargin: 5
                        Layout.preferredHeight: (bluetoothConnectivityRect.height/2)-(bluetoothConnectivityRect.height/3)-35
                        color: "Transparent"
                        RowLayout{
                            anchors.fill: parent
                            Rectangle{
                                Layout.fillHeight: true
                                Layout.fillWidth:  true
                                color: "transparent"
                                opacity: 0.6
                                Button{
                                    id: connectButton
                                    implicitHeight: parent.height
                                    implicitWidth: parent.width
                                    style: ButtonStyle{
                                        background: Rectangle{
                                            color: "Grey"
                                            radius: 5
                                        }
                                    }
                                    Text {
                                        id: connectText
                                        text: qsTr("Connect")
                                        font.pixelSize: 22
                                        color: "#ffffff"
                                        anchors.centerIn: parent
                                    }
                                }
                            }
                            Rectangle{
                                Layout.fillHeight: true
                                Layout.fillWidth:  true
                                color: "Transparent"
                                Image {
                                    id: playImage
                                    source: "qrc:/001-play-button-1.png"
                                    width: (parent.width/2)-50
                                    height: parent.height-35
                                    anchors.centerIn: parent
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    

  • Moderators

    Use a dynamic model, not static ListElement. You can read more about models in the docs http://doc.qt.io/qt-5.6/qtquick-modelviewsdata-modelview.html#qml-data-models



  • @sierdzio Thank you for the reply,
    i tried with the QStringListModel, but i am getting an error
    qrc:/Bluetooth.qml:157: ReferenceError: myModel is not defined

    the scenario is, based on a button click the file.txt will be created in a particular path, which contains the values. these values i want to display in a list view in qml. i tried with the following code,
    main.cpp

    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QDebug>
    
    #include <qqmlengine.h>
    #include <qqmlcontext.h>
    #include <qqml.h>
    #include <QtQuick/qquickitem.h>
    #include <QtQuick/qquickview.h>
    
    #include "systemscript.h"
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        SystemScript bluetoothOnScript;
    
        QQmlApplicationEngine engine;
        QQmlContext* context= engine.rootContext();
        context->setContextProperty("BluetoothObject",&bluetoothOnScript);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        context->setContextProperty("myModel",QVariant::fromValue(bluetoothOnScript.deviceList));
    
        return app.exec();
    }
    
    

    .cpp file is the same which i have already posted. Thank you



  • @Naveen_D said in How to display the text file content in Qml List view:

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    context->setContextProperty("myModel",QVariant::fromValue(bluetoothOnScript.deviceList));

    you have first to set the context property before loading your qml file!

    context->setContextProperty("myModel",QVariant::fromValue(bluetoothOnScript.deviceList));
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    

    Regards
    Karl-Heinz



  • @karlheinzreichel yes, i did that..
    actually i am not aware how to do this, because i will get the respective text file once the window is launched and when i click on scan button the file will be generated and i want to display the content of this file in list view. i tried setting the context property in .cpp file once the file is generated but didn't work.
    Thank you.


  • Moderators

    If you used QAbstractItemModel, you can start with an empty model and then update it when the file becomes available.

    Actually, you can - sort of - do the same with QStringListModel, too - first pass an empty list, then a real one. Make sure to read through the documentation about how to update models, and which do support updating in the first place.



  • @sierdzio

    first pass an empty list, then a real one

    i am passing the empty list at first, but how to pass the stringlist once the text file is created ?


  • Moderators

    It's all described in the docs.



  • @sierdzio hi, i am trying with the following code snippet to update the list view in qml using AbstractListModel, but i am getting only first value from the .txt file.
    here is the code:
    main.qml

    import QtQuick 2.6
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.4
    import QtQuick.Controls.Styles 1.4
    import QtQuick.Layouts 1.1
    
    import ToDo 1.0
    
    Window {
        id: appWindow
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
    
    
        ColumnLayout{
            anchors.fill: parent
            ListView{
                Layout.fillHeight: true
                Layout.fillWidth: true
                clip: true
    
                model: ToDoModel{
                    list: toDoList
                }
    
                delegate: RowLayout {
                    width: parent.width
    
                    Label{
                        text : model.deviceName
                        Layout.fillWidth: true
                    }
                }
            }
    
            RowLayout{
                Button{
                    text: "Add new item"
                    onClicked: toDoList.appendItem()
                    Layout.fillWidth: true
                }
            }
        }
    }
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    
    #include "ToDoList.h"
    #include "TodoModel.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<TodoModel>("ToDo", 1, 0, "ToDoModel");
        qmlRegisterUncreatableType<ToDoList> ("ToDo", 1, 0, "ToDoList",
                                              QStringLiteral("ToDoList should not be created"));
        ToDoList toDoList;
    
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty(QStringLiteral("toDoList"),&toDoList);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        return app.exec();
    }
    
    

    ToDoModel.cpp

    #include "TodoModel.h"
    
    #include "ToDoList.h"
    
    TodoModel::TodoModel(QObject *parent)
        : QAbstractListModel(parent)
        , mList(nullptr)
    {
    }
    
    int TodoModel::rowCount(const QModelIndex &parent) const
    {
        // For list models only the root node (an invalid parent) should return the list's size. For all
        // other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
        if (parent.isValid() || !mList)
            return 0;
    
        // FIXME: Implement me!
    
        return mList->items().size();
    }
    
    QVariant TodoModel::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid() || !mList)
            return QVariant();
    
        const ToDoItem item= mList->items().at(index.row());
    
        switch (role){
        case DeviceNameRole:
            return QVariant(item.deviceName);
        }
    
        return QVariant();
    }
    
    bool TodoModel::setData(const QModelIndex &index, const QVariant &value, int role)
    {
    
        if(!mList)
            return false;
    
        ToDoItem item= mList->items().at(index.row());
    
        switch (role){
        case DeviceNameRole:
            item.deviceName= value.toString();
            break;
        }
    
        if (mList->setItemsAt(index.row(), item)) {
            // FIXME: Implement me!
            emit dataChanged(index, index, QVector<int>() << role);
            return true;
        }
        return false;
    }
    
    Qt::ItemFlags TodoModel::flags(const QModelIndex &index) const
    {
        if (!index.isValid())
            return Qt::NoItemFlags;
    
        return Qt::ItemIsEditable;
    }
    
    QHash<int, QByteArray> TodoModel::roleNames() const
    {
        QHash<int, QByteArray> names;
        names[DeviceNameRole]= "deviceName";
        return names;
    }
    
    ToDoList *TodoModel::list() const
    {
        return mList;
    }
    
    void TodoModel::setList(ToDoList *list)
    {
        beginResetModel();
    
        if(mList)
            mList->disconnect(this);
    
        mList = list;
    
        if(mList) {
            connect(mList, &ToDoList::preItemAppended, this, [=]() {
                const int index=mList->items().size();
                qDebug()<< "index size>>>" <<index;
                beginInsertRows(QModelIndex(), index, index);
            });
    
            connect(mList, &ToDoList::postItemAppended, this, [=]() {
                endInsertRows();
            });
    
        }
        endResetModel();
    }
    

    ToDoModel.cpp

    #ifndef TODOMODEL_H
    #define TODOMODEL_H
    
    #include <QAbstractListModel>
    #include <QDebug>
    
    class ToDoList;
    
    class TodoModel : public QAbstractListModel
    {
        Q_OBJECT
        Q_PROPERTY(ToDoList *list READ list WRITE setList)
    
    public:
        explicit TodoModel(QObject *parent = 0);
    
        enum {
            DeviceNameRole= Qt::UserRole,
        };
    
        // Basic functionality:
        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    
        // Editable:
        bool setData(const QModelIndex &index, const QVariant &value,
                     int role = Qt::EditRole) override;
    
        Qt::ItemFlags flags(const QModelIndex& index) const override;
    
        QHash<int, QByteArray> roleNames() const override;
    
        ToDoList *list() const;
        void setList(ToDoList *list);
    
    private:
        ToDoList *mList;
    };
    
    #endif // TODOMODEL_H
    

    ToDoList.h

    #include "ToDoList.h"
    
    ToDoList::ToDoList(QObject *parent) : QObject(parent)
    {
    
    }
    
    QVector<ToDoItem> ToDoList::items() const
    {
        return m_items;
    }
    
    bool ToDoList::setItemsAt(int index, const ToDoItem &item)
    {
        if(index <0 || index >= m_items.size())
            return false;
    
        const ToDoItem &oldItem= m_items.at(index);
        if(item.deviceName== oldItem.deviceName)
            return false;
    
        m_items[index]= item;
        return true;
    }
    
    void ToDoList::appendItem()
    {
        emit preItemAppended();
    
        ToDoItem item;
    
        QFile file("/home/ubuntu/Documents/Sample_Examples_Qt_Qml/list.txt");
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){
            qDebug()<<" file not opened !!!"<< endl;
        }
    
        while (!file.atEnd()) {
            QByteArray line = file.readLine();
    
            deviceStr= QString::fromStdString(line.toStdString());
            qDebug()<< "string is >>"<<deviceStr<<endl;
    
            deviceList.append(deviceStr);
        }
        qDebug()<<"device lis atfer appending>>>>"<<deviceList<<endl;
    
        for(int i = 0; i < deviceList.length(); i++){
    
            item.deviceName = deviceList.at(i);
            qDebug()<<"item device name>>>"<<item.deviceName<<endl;
    
            m_items.append(item.deviceName);
        }
    
        emit postItemAppended();
    }
    

    ToDoList.h

    #ifndef TODOLIST_H
    #define TODOLIST_H
    
    #include <QObject>
    #include <QVector>
    #include <QFile>
    #include <QDebug>
    
    struct ToDoItem
    {
        QString deviceName;
    };
    
    class ToDoList : public QObject
    {
        Q_OBJECT
    public:
        explicit ToDoList(QObject *parent = 0);
    
        QVector<ToDoItem> items() const;
    
        bool setItemsAt(int index, const ToDoItem &item);
    
        QString deviceStr;
        QStringList deviceList;
    
    signals:
        void preItemAppended();
        void postItemAppended();
    
        void preItemRemoved(int index);
        void postItemRemoved();
    
    public slots:
        void appendItem();
    //    void removeCompletedItems();
    
    private:
        QVector<ToDoItem> m_items;
    };
    
    #endif // TODOLIST_H
    
    

    can you tell me what is wrong with the code above.
    Thank you


  • Moderators

    @Naveen_D said in How to display the text file content in Qml List view:

    beginInsertRows(QModelIndex(), index, index);

    I guess this is the culprit. You tell the model that only the last index will be updated. But you use this preItemAppended() signal also when resetting list (in that case you should start with index 0 and go up to list.size() - 1). I think you should rethink how you reset your model, this approach is not ideal. Consider using your model class to update the list instead of emitting signals from the list.

    Also, when resetting model, you are disconnecting the old list, but not deleting it - that's a memory leak.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.