Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QML/C++ How to convert string to ListModel
QtWS25 Last Chance

QML/C++ How to convert string to ListModel

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
8 Posts 4 Posters 1.4k Views
  • 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.
  • S Offline
    S Offline
    stefan0893
    wrote on last edited by
    #1

    Hello,
    for an application I am reading times from an external tab seperated textfile via FileIO. I got the external file data into my QML application in a single long string, that I now want to convert to work with it.
    How would I convert a given string like this:
    name1 2022-03-21 08:00:00.000 2022-03-21 08:05:00.000 2022-03-21 08:10:00.000 \n
    name2 2022-03-21 08:15:00.000 2022-03-21 08:20:05.000 2022-03-21 08:25:00.000 \n
    ...
    nameX ...
    into a ListModel with fitting properties name, time0, time1, time2 ?
    ListModel{
    ListElement{
    name: "contact 1"
    time0: "2022-03-21 08:00:00.000"
    time1: "2022-03-21 08:05:00.000"
    time2: "2022-03-21 08:15:00.000"
    }
    .......
    }
    Thanks in advance!

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi
      Well you can read into a c++ model and expose that to QML
      https://stackoverflow.com/questions/11806324/how-to-expose-a-c-model-to-qml

      its also possible to do in QML
      https://github.com/RSATom/Qt/blob/master/qtdeclarative/src/quick/doc/snippets/qml/qml-data-models/dynamic-listmodel.qml

      but I doubt you do the reading in QML, correct ?

      you data seems good aligned, so you can use QStringList split to break it into elements
      First split the big string on \n, then split each element(string) on space and you
      have the elements.

      1 Reply Last reply
      1
      • F Offline
        F Offline
        flowery
        wrote on last edited by
        #3

        Once you get the string you can append it to ListModel using append function.Before that use javascript functionality to split the string and store it in an array [https://stackoverflow.com/questions/37838532/javascript-split-string-with-matchregex](link url). For ex:
        Component.onCompleted: {
        var string1= "one two three four"
        var splitString = string1.split(" ")
        console.log("str1 "+splitString[0])
        console.log("str2 "+splitString[1])
        console.log("str3 "+splitString[2])
        }

        1 Reply Last reply
        1
        • S Offline
          S Offline
          stefan0893
          wrote on last edited by
          #4

          Thanks for the replys so far!
          I switched the machines to a ubuntu laptop and set up a new project, where I somehow can't get my FileIO c++ class to work...
          I also switched from qmake to cmake, since this will be the standard project builder if I got it right?

          See my files attached, the fileio.h fileio.cpp and main.cpp & .qml.
          I am trying to read some random text from a textfile, which is parallel to main project ressources (tried different folders and relative pathing like "./my_file.txt" or ":/my_file.txt" as well...
          I am always getting the "Unable to open the file" error message on calling my read() function ... What am I doing wrong?
          To my understanding I did it exactly like in the tutorials that I found.

          My project files look like this:

          fileio.h

          #ifndef FILEIO_H
          #define FILEIO_H

          #include <QObject>

          class FileIO : public QObject
          {
          Q_OBJECT

          Q_PROPERTY(
              QString source
              READ source
              WRITE setSource
              NOTIFY sourceChanged
          )
          

          public:
          explicit FileIO(QObject *parent = nullptr);

          Q_INVOKABLE QString read();
          Q_INVOKABLE bool write(const QString& data);
          
          QString source() { return mSource; };
          
          
          void setSource(const QString& source) {mSource = source;};
          void doSomething(const QString &text);
          

          signals:
          void sourceChanged(const QString& source);
          void error(const QString& msg);

          private:
          QString mSource;

          };

          #endif // FILEIO_H

          fileio.cpp

          #include "fileio.h"
          #include <QFile>
          #include <QTextStream>
          #include <iostream>
          #include <QDebug>

          FileIO::FileIO(QObject *parent) : QObject(parent)
          {

          }

          QString FileIO::read()
          {
          if (mSource.isEmpty()){
          emit error("source is empty");
          return QString();
          }

          QFile file(mSource);
          QString fileContent;
          if ( file.open(QIODevice::ReadOnly) ) {
              QString line;
              QTextStream t( &file );
              do {
                  line = t.readLine();
                  fileContent += line;
               } while (!line.isNull());
          
              file.close();
          } else {
              emit error("Unable to open the file");
              return QString();
          }
          return fileContent;
          

          }

          bool FileIO::write(const QString& data)
          {
          if (mSource.isEmpty())
          return false;

          QFile file(mSource);
          if (!file.open(QFile::WriteOnly | QFile::Truncate))
              return false;
          
          QTextStream out(&file);
          out << data;
          
          file.close();
          
          return true;
          

          }

          And the registratio n in the main.cpp file looks like this:
          main.cpp

          #include <QGuiApplication>
          #include <QQmlApplicationEngine>
          #include <QQmlContext>

          // c++ header to include for using qmlRegisterType();
          //#include <QtDeclarative> // only for qt4
          #include<QtQml> //qt5

          //include custom classes
          #include "fileio.h"

          int main(int argc, char *argv[])
          {
          #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
          QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
          #endif

          QGuiApplication app(argc, argv);
          QQmlApplicationEngine engine;
          
          qmlRegisterType<FileIO>("Test.customClasses",1,0,"FileIO");
          
          const QUrl url(QStringLiteral("qrc:/main.qml"));
          QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                           &app, [url](QObject *obj, const QUrl &objUrl) {
              if (!obj && url == objUrl)
                  QCoreApplication::exit(-1);
          }, Qt::QueuedConnection);
          engine.load(url);
          
          return app.exec();
          

          }

          main.qml

          import QtQuick.Window 2.12
          import QtQml.Models 2.3
          import QtQml 2.15
          import QtQuick.Controls 2.15
          import QtQuick.Layouts 1.3
          import Test.customClasses 1.0

          Window {
          id:mainWindow
          width: 800
          height: 400
          visible: true
          title: qsTr("Main Window")
          color:"black"

          FileIO {
              id: myFile
              source: "my_file.txt"
              onError: console.log(msg  + " " + source )
          }
          
          Component.onCompleted: {
              myText.text =  myFile.read();
          }
          
          Text{id:myText;anchors.centerIn:parent}
          

          }

          DiracsbracketD 1 Reply Last reply
          0
          • S stefan0893

            Thanks for the replys so far!
            I switched the machines to a ubuntu laptop and set up a new project, where I somehow can't get my FileIO c++ class to work...
            I also switched from qmake to cmake, since this will be the standard project builder if I got it right?

            See my files attached, the fileio.h fileio.cpp and main.cpp & .qml.
            I am trying to read some random text from a textfile, which is parallel to main project ressources (tried different folders and relative pathing like "./my_file.txt" or ":/my_file.txt" as well...
            I am always getting the "Unable to open the file" error message on calling my read() function ... What am I doing wrong?
            To my understanding I did it exactly like in the tutorials that I found.

            My project files look like this:

            fileio.h

            #ifndef FILEIO_H
            #define FILEIO_H

            #include <QObject>

            class FileIO : public QObject
            {
            Q_OBJECT

            Q_PROPERTY(
                QString source
                READ source
                WRITE setSource
                NOTIFY sourceChanged
            )
            

            public:
            explicit FileIO(QObject *parent = nullptr);

            Q_INVOKABLE QString read();
            Q_INVOKABLE bool write(const QString& data);
            
            QString source() { return mSource; };
            
            
            void setSource(const QString& source) {mSource = source;};
            void doSomething(const QString &text);
            

            signals:
            void sourceChanged(const QString& source);
            void error(const QString& msg);

            private:
            QString mSource;

            };

            #endif // FILEIO_H

            fileio.cpp

            #include "fileio.h"
            #include <QFile>
            #include <QTextStream>
            #include <iostream>
            #include <QDebug>

            FileIO::FileIO(QObject *parent) : QObject(parent)
            {

            }

            QString FileIO::read()
            {
            if (mSource.isEmpty()){
            emit error("source is empty");
            return QString();
            }

            QFile file(mSource);
            QString fileContent;
            if ( file.open(QIODevice::ReadOnly) ) {
                QString line;
                QTextStream t( &file );
                do {
                    line = t.readLine();
                    fileContent += line;
                 } while (!line.isNull());
            
                file.close();
            } else {
                emit error("Unable to open the file");
                return QString();
            }
            return fileContent;
            

            }

            bool FileIO::write(const QString& data)
            {
            if (mSource.isEmpty())
            return false;

            QFile file(mSource);
            if (!file.open(QFile::WriteOnly | QFile::Truncate))
                return false;
            
            QTextStream out(&file);
            out << data;
            
            file.close();
            
            return true;
            

            }

            And the registratio n in the main.cpp file looks like this:
            main.cpp

            #include <QGuiApplication>
            #include <QQmlApplicationEngine>
            #include <QQmlContext>

            // c++ header to include for using qmlRegisterType();
            //#include <QtDeclarative> // only for qt4
            #include<QtQml> //qt5

            //include custom classes
            #include "fileio.h"

            int main(int argc, char *argv[])
            {
            #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
            QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
            #endif

            QGuiApplication app(argc, argv);
            QQmlApplicationEngine engine;
            
            qmlRegisterType<FileIO>("Test.customClasses",1,0,"FileIO");
            
            const QUrl url(QStringLiteral("qrc:/main.qml"));
            QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                             &app, [url](QObject *obj, const QUrl &objUrl) {
                if (!obj && url == objUrl)
                    QCoreApplication::exit(-1);
            }, Qt::QueuedConnection);
            engine.load(url);
            
            return app.exec();
            

            }

            main.qml

            import QtQuick.Window 2.12
            import QtQml.Models 2.3
            import QtQml 2.15
            import QtQuick.Controls 2.15
            import QtQuick.Layouts 1.3
            import Test.customClasses 1.0

            Window {
            id:mainWindow
            width: 800
            height: 400
            visible: true
            title: qsTr("Main Window")
            color:"black"

            FileIO {
                id: myFile
                source: "my_file.txt"
                onError: console.log(msg  + " " + source )
            }
            
            Component.onCompleted: {
                myText.text =  myFile.read();
            }
            
            Text{id:myText;anchors.centerIn:parent}
            

            }

            DiracsbracketD Offline
            DiracsbracketD Offline
            Diracsbracket
            wrote on last edited by
            #5

            @stefan0893
            Does it work if you use the absolute path for the file?

            1 Reply Last reply
            2
            • S Offline
              S Offline
              stefan0893
              wrote on last edited by
              #6

              It actually did work with the complete path, but I need it to work with a relative path since I am deploying on different machines. Do you know how to implement it?
              Thanks!

              DiracsbracketD 1 Reply Last reply
              0
              • S stefan0893

                It actually did work with the complete path, but I need it to work with a relative path since I am deploying on different machines. Do you know how to implement it?
                Thanks!

                DiracsbracketD Offline
                DiracsbracketD Offline
                Diracsbracket
                wrote on last edited by Diracsbracket
                #7

                @stefan0893
                Maybe the "current" directory at the time you try to open the file is not what you think it is, and hence the relative path is wrong?

                Have a look at:
                https://forum.qt.io/topic/88724/how-to-set-current-working-directory-so-that-qfile-gets-relative-paths-right

                and
                https://stackoverflow.com/questions/25104923/read-file-using-relative-path-on-linux-qt

                1 Reply Last reply
                1
                • F Offline
                  F Offline
                  flowery
                  wrote on last edited by
                  #8

                  If the file is added to qrc then use the path referred from qrc, else if you are referring from system then add file:// prefix before the absolute path .

                  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 Extensions
                  • Unsolved