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! -
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-qmlits also possible to do in QML
https://github.com/RSATom/Qt/blob/master/qtdeclarative/src/quick/doc/snippets/qml/qml-data-models/dynamic-listmodel.qmlbut 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_OBJECTQ_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);
#endifQGuiApplication 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.0Window {
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}
}
-
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_OBJECTQ_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);
#endifQGuiApplication 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.0Window {
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! -
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-rightand
https://stackoverflow.com/questions/25104923/read-file-using-relative-path-on-linux-qt