Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QML/C++ How to convert string to ListModel



  • 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!


  • Lifetime Qt Champion

    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.



  • 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])
    }



  • 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}
    

    }



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



  • 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!



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



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


Log in to reply