I'm currently create an apps in Meego using QML and JS on most of the part. and now I stumbled upon a problem.
From javascript I want to call a C++ function to read text file, parse it, and then return an array of the parsing result.
so I create a Q_INVOKABLE function called parse() and call it through javascript
function parse() {
var myArray = new Array();
myArray = parser.parse("/home/user/MyDocs/angklungtext.txt")
if(myArray === undefined){
console.log("null found");
}
for(var i = 0; i < myArray.length; i++){
console.log(myArray[i][0] + "," + myArray[i][1])
}
}
and here is the parse function in C++
QVariantList* QMLParser::parse(QString filename)
{
qDebug() << "start debugging";
qDebug() << filename;
qDebug() << QDir::currentPath();
QDir dir;
qDebug()<< dir.absoluteFilePath(filename);
QFile file(filename);
if(!file.exists())
{
qDebug() << "File: " << file.fileName() << "tidak ditemukan";
return NULL;
}
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug() << "Tidak dapat membuka file" << file.fileName() << "untuk ditulis";
return NULL;
}
QTextStream stream(&file);
QVariantList* myList = new QList<QVariant>;
while(!stream.atEnd())
{
QString line = stream.readLine();
qDebug() << line.trimmed();
QStringList lineList = line.split(":");
myList->append(lineList);
}
file.close();
return myList;
}
sadly.
when I try to run it it giving a result like this
start debugging
"/home/user/MyDocs/angklungtext.txt"
"/home/developer"
"/home/user/MyDocs/angklungtext.txt"
"1:1000"
"4:2000"
"5:3000"
"2:4000"
null found
file:///opt/memoryreader/qml/memoryreader/myjs.js:8: TypeError: Result of expression 'myArray' [undefined] is not an object.
looks like the C++ parse function successfully parsing the file. it can read it and it can save it into the QVariantList.
but after it return the result into javascript myArray still [undefined].
is there something wrong with the conversion?
Just simplify the C++ side like this :
QVariant QMLParser::parse(QString filename)
{
QStringList myList;
qDebug() << "start debugging";
qDebug() << filename;
qDebug() << QDir::currentPath();
QDir dir;
qDebug() << dir.absoluteFilePath(filename);
QFile file(filename);
if(!file.exists()) {
qDebug() << "File: " << file.fileName() << "tidak ditemukan";
return NULL;
}
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Tidak dapat membuka file" << file.fileName() << "untuk ditulis";
return NULL;
}
QTextStream stream(&file);
while(!stream.atEnd()) {
QString line = stream.readLine();
qDebug() << line.trimmed();
myList << line.trimmed().split(":");
}
file.close();
return QVariant::fromValue(myList);
}
And it should work !
Just remember, QML must see a QVariant, even if a QList is wrapped inside it, and Qt is able to convert most of its base types to QVariant using QVariant::fromValue(T) so use it extensively.
Oh and BTW a QVariant is reference not pointer.
Haven't done this myself, so I'm just thinking out loud. But I note that you're returning a pointer to a QVariantList...which looks suspect. (Also: if you new, then who would do the delete?)
Have you tried returning it by value?
Related
I'm trying to read in a file of trace addresses (each on their own line) and append to the front of each. This input file is intended to be the engine of a cache emulator i'm trying to build. I am having issues reading the file in without getting into an infinite loop. When I change the do-while to run on a false condition, I get the proper output for just the do segment. Therefore, I know I'm running into an infinite loop issue with how I worded my while segment. Maybe i'm fatigued and can't see the issue with this function:
void MainWindow::readFile(){
infoLabel->setText(tr("Invoked <b>File|Open</b>"));
QString filename="trace.txt";
QString path = QDir::currentPath();
QFile file("//Users//nathan1324//Desktop//trace.txt");
//file.open(QIODevice::ReadOnly);
if(!file.exists()){
qDebug() << "File cannot be found "<<filename;
qDebug() << " " << path;
}else{
qDebug() << filename<<" Opening...";
}
QString line;
textEdit->clear();
if (file.open(QIODevice::ReadOnly | QIODevice::Text)){
QTextStream stream(&file);
do {
line = stream.readLine();
textEdit->setText(textEdit->toPlainText()+"0x"+line+"\n");
qDebug() << "line: "<<line;
} while (!line.isNull());
}
file.close();
}
Any suggestions of an alternative way to write this function?
To add items use the append function of QTextEdit:
void QTextEdit::append(const QString & text)
Appends a new paragraph with text to the end of the text edit.
Note: The new paragraph appended will have the same character format
and block format as the current paragraph, determined by the position
of the cursor.
To iterate through the QTextStream atEnd()
bool QTextStream::atEnd() const
Returns true if there is no more data to be read from the QTextStream;
otherwise returns false. This is similar to, but not the same as
calling QIODevice::atEnd(), as QTextStream also takes into account its
internal Unicode buffer.
Code:
void MainWindow::readFile(){
infoLabel->setText(tr("Invoked <b>File|Open</b>"));
QString filename = "trace.txt";
QString path = QDir::currentPath();
QFile file("//Users//nathan1324//Desktop//trace.txt");
if(!file.exists()){
qDebug() << "File cannot be found "<<filename;
qDebug() << " " << path;
return;
}
QString line;
textEdit->clear();
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "Could not open file" << filename;
return;
}
qDebug() << filename<<" Opening...";
QTextStream stream(&file);
while (!stream.atEnd()) {
line = stream.readLine();
if(!line.isNull()){
textEdit->append("0x"+line);
qDebug() << "line: "<<line;
}
}
file.close();
}
Use atEnd to detect the end of a stream:
bool QTextStream::atEnd() const
Returns true if there is no more data to be read from the QTextStream;
otherwise returns false. This is similar to, but not the same as
calling QIODevice::atEnd(), as QTextStream also takes into account its
internal Unicode buffer.
while (!stream.atEnd()) {
line = stream.readLine();
textEdit->setText(textEdit->toPlainText()+"0x"+line+"\n");
qDebug() << "line: "<<line;
}
I am attempting to compare a QByteArray of an already saved html file with a QByteArray that was just downloaded. I have to convert the QString of the file's contents to QByteArray in order to compare them (or vice versa) and comparing bytes seems like the cleanest method, however when converted from QString to QByteArray, the size of the new QByteArray is smaller than what it should be. QByteArray QString::toLocal8Bit() const states that if it is undefined, the characters will be suppressed or replaced. It also said that it uses toLatin1() by default and tried to use ASCII since that is what a website is encoded in. I still get the same results.
bool NewsBulletin::compareDownload(QByteArray new_contents, QString filename)
{
bool return_what = false;
qDebug() << "I am in compareDownload";
// qDebug() << new_contents[1];
// qDebug() << new_contents[1] << endl
// << new_contents[2];
QFile file(application_path + filename);
if (file.exists())
{
// QString new_contents_qstr(new_contents);
file.open(QIODevice::ReadOnly | QIODevice::Text);
QTextStream in(&file);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("ASCII"));
QString file_contents = in.readAll();
QByteArray file_byte_array = file_contents.toLocal8Bit();
qDebug() << "outputting new file array";
qDebug() << new_contents[5] << new_contents.size();
qDebug() << "outputting old file array";
qDebug() << file_byte_array[5] << file_byte_array.size();
for (int i=0; i<=file_byte_array.size(); i++)
{
if (file_byte_array[i] != new_contents[i])
{
return_what = true;
break;
}
else if (i == file_byte_array.size())
{
qDebug() << "compareDownload will return false, duplicate file.";
return_what = false;
}
}
}
else
{
qDebug() << "compareDownload will return true, DNE.";
return_what = true;
}
return return_what;
}
The output of the qDebug() from the function is:
I am in compareDownload
outputting new file array
T 64704
outputting old file array
T 64576
After reading the api for hours, I found the reason for the bytes being different.
file.open(QIODevice::ReadOnly | QIODevice::Text);
QIODevice::Text needs to be removed. This flag changes end of line terminators into the terminator for cpp, "\n", thus giving a byte difference.
I have a treeview that displays a folder with text files. There is a 'open' button. That will open the file. But when this button is pressed it should rename the file to: read filename.txt. So if there is a file for example that is name nameslist.txt and the button is pressed it should rename it to read nameslist.txt or something similar. I thought of something like this:
void berichtenhistorie::on_Openbutton_released()
{
QModelIndex index = ui->treeView->currentIndex();
QString name = index.fileName();
QString path = index.filePath();
QFile file(path);
file.open(QIODevice::WriteOnly | QIODevice::Text);
file.rename("read " + name);
file.close();
}
But this isnt working. I get the following error's:
error: C2352: 'QDirModel::fileName' : illegal call of non-static member function
But I dont know how to use fileName() and filePath() correctly.
Thanks for help!
I think that here is what you looking for:
void berichtenhistorie::on_Openbutton_released()
{
QModelIndex index = ui->treeView->currentIndex();
QFileSystemModel *model = (QFileSystemModel*)ui->treeView->model();
QString path = model->filePath(index);
QString name = model->fileName(index);
QString dir = path;
dir.remove(dir.size() - name.size(), name.size());
QFile file(path);
if(file.open(QIODevice::WriteOnly | QIODevice::Text))
{
//Interact with the file
file.close();
if(file.rename(QString("%1read %2").arg(dir, name)))
qDebug() << "Renamed";
}
}
Here's a break out of each step you'll need to do to work with QFile.
QFile file("test.txt");
if(file.exists())
{
qDebug() << "found file";
if(file.open(QIODevice::ReadWrite))
{
qDebug() << "opened";
if(file.rename("text1.txt"))
{
qDebug() << "renamed";
}
else
{
qDebug() << "failed to rename";
}
file.close();
}
}
else
{
qDebug() << "file does not exist";
}
In the end, you'll only really need your debugger to step through instead of printing out everything known to your application. E.g.
QFile file("test.txt");
if(file.exists() && file.open(QIODevice::ReadWrite))
{
if(file.rename("text1.txt"))
{
qDebug() << "renamed";
}
file.close();
}
I'm trying to save an object called f to a file, getting errors: no match for operator << in stream << f
here is the function:
void FilmWriter::saveFilm(Film& f){
QString fileName = QFileDialog::getSaveFileName(this,("Save File"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::critical(this, ("Error"),("Could not open file"));// error message
} else {
QTextStream stream(&file);
stream << f;
stream.flush();
file.close();
}
}
}
Please let me know if you need any more information?
These are 2 functions in a different class filmInput
void FilmInput::getFilm(){
Film f1(titleEdit->toPlainText(),durationEdit->toPlainText().toInt() ,directorEdit->toPlainText(),
QDate::fromString(relDateEdit->toPlainText(),"dd/MM/YYYY"));;
obtainFilmData(f1);
}
void FilmInput::obtainFilmData(Film &f){
saveFilm(f);
}
QTextStream is made for storing text, not Film. You need something that can store your object. Maybe QDataStream will help you? But you'll need to serialize your Film object to something like QByteArray.Update:
Now I see that you need Film::toString() method that will give you a string representation of Film object. Then you just write stream<<f.toString(); instead of stream<<f;. Or you can implement operator<< that takes QTextStream and Film.
Example of Film::toString():
QString Film::toString()
{
return mTitle + " " + mDuration + " " + mDirector + " " + mDate.toString();
}
with the function below (which may not be 100% syntacticly correct) you can now write to your stream, Film.toString()
QString Film::toString()
{
QTextStream stream;
stream << someFilmVariable << " " << someOtherFilmVariable;
return stream.string()
}
I'm trying to read a text file and display the contents in a QPlainTextEdit. Please can you point out what I'm doing wrong:
QFile jsonFile("data.json");
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug() << "Failed to open file";
qDebug() << jsonFile.errorString();
return;
}
else
{
qDebug() << "File opened";
} //It returns that the file opened successfully
qDebug() << "File Exists?: " << jsonFile.exists(); //Yep, it exists.
QTextStream outStream(&jsonFile);
QString textString = outStream.readAll();
qDebug() << "Text string: " << textString; //textString is empty! ""
ui->fileToPost->setPlainText(textString); //fileToPost is the QPlainTextEdit
jsonFile.close();
If I do something like
QString textString = "The cat sat on the mat";
it displays fine. The problem is that nothing is being read from the stream (or maybe the file).
Try to check file's absolute path, probably it is not where, you expect it: qDebug()<<QFileInfo("data.json").absoluteFilePath();