Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to display the text file content in Qml List view
Qt 6.12 LTS is out! See what's new in the release blog

How to display the text file content in Qml List view

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
16 Posts 4 Posters 7.0k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • sierdzioS Offline
    sierdzioS Offline
    sierdzio
    Moderators
    wrote on last edited by
    #2

    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

    (Z(:^

    Naveen_DN 1 Reply Last reply
    1
    • sierdzioS sierdzio

      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

      Naveen_DN Offline
      Naveen_DN Offline
      Naveen_D
      wrote on last edited by
      #3

      @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

      1 Reply Last reply
      0
      • K Offline
        K Offline
        karlheinzreichel
        wrote on last edited by
        #4

        @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

        Naveen_DN 1 Reply Last reply
        1
        • K karlheinzreichel

          @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

          Naveen_DN Offline
          Naveen_DN Offline
          Naveen_D
          wrote on last edited by
          #5

          @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.

          Naveen_D

          1 Reply Last reply
          0
          • sierdzioS Offline
            sierdzioS Offline
            sierdzio
            Moderators
            wrote on last edited by
            #6

            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.

            (Z(:^

            Naveen_DN 1 Reply Last reply
            1
            • sierdzioS sierdzio

              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.

              Naveen_DN Offline
              Naveen_DN Offline
              Naveen_D
              wrote on last edited by
              #7

              @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 ?

              Naveen_D

              1 Reply Last reply
              0
              • sierdzioS Offline
                sierdzioS Offline
                sierdzio
                Moderators
                wrote on last edited by
                #8

                It's all described in the docs.

                (Z(:^

                Naveen_DN 1 Reply Last reply
                3
                • sierdzioS sierdzio

                  It's all described in the docs.

                  Naveen_DN Offline
                  Naveen_DN Offline
                  Naveen_D
                  wrote on last edited by
                  #9

                  @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

                  Naveen_D

                  1 Reply Last reply
                  0
                  • sierdzioS Offline
                    sierdzioS Offline
                    sierdzio
                    Moderators
                    wrote on last edited by
                    #10

                    @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.

                    (Z(:^

                    1 Reply Last reply
                    0
                    • MarukoM Offline
                      MarukoM Offline
                      Maruko
                      wrote on last edited by
                      #11

                      Hello,
                      I was studying this thead and from my understanding the best solution of this problem is the following function, adding every single line at a time.
                      Is it correct?
                      What about performances on large amount of data.

                      void ToDoList::appendItem()
                         {
                             ToDoItem item;
                      
                             QFile file("/home/ubuntu/qt/list.txt");
                             if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
                         	qDebug()<<" File not opened !!!" << endl;
                             else
                         	qDebug()<<" File opened !!!" << endl;
                      
                             while (!file.atEnd()) {
                         	QByteArray line = file.readLine();
                      
                         	deviceStr = QString::fromStdString(line.toStdString());
                         	qDebug()<< "string is: " << deviceStr;
                      
                         	emit preItemAppended();
                         	    item.deviceName = deviceStr;
                         	    m_items.append(item);
                         	emit postItemAppended();
                             }
                         }
                      
                      sierdzioS 1 Reply Last reply
                      0
                      • MarukoM Maruko

                        Hello,
                        I was studying this thead and from my understanding the best solution of this problem is the following function, adding every single line at a time.
                        Is it correct?
                        What about performances on large amount of data.

                        void ToDoList::appendItem()
                           {
                               ToDoItem item;
                        
                               QFile file("/home/ubuntu/qt/list.txt");
                               if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
                           	qDebug()<<" File not opened !!!" << endl;
                               else
                           	qDebug()<<" File opened !!!" << endl;
                        
                               while (!file.atEnd()) {
                           	QByteArray line = file.readLine();
                        
                           	deviceStr = QString::fromStdString(line.toStdString());
                           	qDebug()<< "string is: " << deviceStr;
                        
                           	emit preItemAppended();
                           	    item.deviceName = deviceStr;
                           	    m_items.append(item);
                           	emit postItemAppended();
                               }
                           }
                        
                        sierdzioS Offline
                        sierdzioS Offline
                        sierdzio
                        Moderators
                        wrote on last edited by
                        #12

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

                        What about performances on large amount of data.

                        You wrote the code, you should check the performance ;-)

                        If you have a lot of rows, and you have all of them available (since you're reding them from disk), then I'd rather recommend loading them all and then informing the view (beginResetModel() and endResetModel()). If there can be too many rows for model to handle at once, you can implement lazy loading (canFetchMore() and fetchMore()).

                        (Z(:^

                        1 Reply Last reply
                        0
                        • MarukoM Offline
                          MarukoM Offline
                          Maruko
                          wrote on last edited by Maruko
                          #13

                          @sierdzio thanks for the reply.
                          My problemis that I don't understand how to manage the big load.
                          As I argued by previous answers to this topic, looks like I have to pass a items counter to beginInsertRows(QModelIndex(), index, index).
                          Could you please tell me how can I do that?
                          TIA

                          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();
                          }
                          
                          1 Reply Last reply
                          0
                          • sierdzioS Offline
                            sierdzioS Offline
                            sierdzio
                            Moderators
                            wrote on last edited by
                            #14

                            As I argued by previous answers to this topic, looks like I have to pass a items counter to beginInsertRows(QModelIndex(), index, index).

                            Your code looks OK, I don't know what else I can say here. Yes when you add new rows you need to specify correct index.

                            if(mList)
                                    mList->disconnect(this);
                            

                            Are you deleting the old list anywhere? If not, then you have a memory leak after you call mList = list.

                            (Z(:^

                            1 Reply Last reply
                            0
                            • MarukoM Offline
                              MarukoM Offline
                              Maruko
                              wrote on last edited by
                              #15

                              @sierdzio that's exactly the point. How can I know the number of items to add inside TodoModel::setList ?

                              sierdzioS 1 Reply Last reply
                              0
                              • MarukoM Maruko

                                @sierdzio that's exactly the point. How can I know the number of items to add inside TodoModel::setList ?

                                sierdzioS Offline
                                sierdzioS Offline
                                sierdzio
                                Moderators
                                wrote on last edited by
                                #16

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

                                @sierdzio that's exactly the point. How can I know the number of items to add inside TodoModel::setList ?

                                That's not a question I can answer. You know the ToDoList class, so you should also know the item count.

                                But in setList() you don't need to know the count at all, because that method resets the model. So the model knows it needs to invalidate all indexes and rebuild the whole tree - it does not need to know the count of items. It will get built automatically using model's index(), parent() and rowCount() methods.

                                (Z(:^

                                1 Reply Last reply
                                0

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt
                                • Unsolved