Reading Windows encoded files in Qt - c++

I have been struggling for an embarrassingly long time now to correctly read Umlaute from a Windows encoded file. The file is saved using the Windows-1252 codec and consists of one single line:
123 äöü 456
My simple test program to isolate the behavior I don't understand is;
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QTextCodec>
#include <QByteArray>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QStringList ids;
QFile inputFile("test.txt");
QTextCodec *codec = QTextCodec::codecForName("Windows-1252");
if (inputFile.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile);
while (!in.atEnd())
{
QByteArray line = inputFile.readLine();
QString string = codec->toUnicode(line);
qDebug() << string;
}
inputFile.close();
}
else
qDebug() << "Cannot open file";
return a.exec();
}
The console output is:
"123 ??? 456\r\n"
So all the Umlaute get eaten up.
I am running this in Linux, the terminal emulator is set to use UTF-8. What can possibly go wrong here.

Related

Qt 5 Play wav sound while input from user

My program alerts the user when something has happened. To get his attention, a alert sound plays. It stops when the user enter something to confirm receipt.
But the QTextStream input blocks the sound !
When I remove it, the sound plays perfectly.
Besides, the "alert" QSound object doesn't work. The only way to play is to use the static function QSound::play("file.wav"). But it can't be stopped.
Here is my code :
#include <QCoreApplication>
#include <QSound>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
/*
QSound alert("../SoundAlerte/alert.wav");
alert.setLoops(QSound::Infinite);
alert.play();
*/
QSound::play("../SoundAlerte/alert.wav");
qDebug() << "ALERT";
qDebug() << "Enter Something to confirm receipt" ;
QTextStream s(stdin);
QString value = s.readLine();
qDebug() << "Received !";
//alert.stop();
qDebug() << "Sound stopped";
return a.exec();
}
It seems like it can't play a sound and wait for input at the same time !
Do you have have an idea on how to proceed ?
Thanks
QSound::play is asynchron, but
QString value = s.readLine();
contains a do-while and will block the audio file. See scan function called by readLine()
A working example would be QtConcurrent, but you can't stop the audio file, so you might want to switch to a real QThread approach.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFuture<void> future = QtConcurrent::run([]() {
QSoundEffect effect;
QEventLoop loop;
effect.setSource(QUrl::fromLocalFile("C:\\piano2.wav"));
effect.setVolume(0.25f);
effect.play();
QObject::connect(&effect, &QSoundEffect::playingChanged, [&loop]() { qDebug() << "finished"; loop.exit(); });
loop.exec();
});
QTextStream s(stdin);
QString value = s.readLine();
return a.exec();
}

Why messages printed after closing main window in Qt C++?

With this code
#include "mainwindow.h"
#include <QApplication>
#include <iostream>
#include <QDir>
#include <QTextStream>
int main(int argc, char *argv[]){
QApplication a(argc, argv);
QTextStream out(stdout);
out << QDir::currentPath();
std::cout << "Why is that?";
MainWindow mainWindow;
mainWindow.show();
return a.exec();
}
Both messages printed only after closing Main Window of my app, why is this?
I tried to debug, debugger thinks that he done with this line, but I see no messages.
extern std::ostream cout; is buffered, so it may choose when to flush its buffer to stdout. In your case, it is doing it when your program is terminating.
You can tell std::ostream to flush using std::flush, as such:
std::cout << "Why is that?" << std::flush;

Qt freeing memory

I wrote a C++ program in Qt that used dynamic memory allocation, and I made sure to include the free() call at the end. However, when the program reaches the free statement, it crashes. (I know this because the test that I added never printed after the free statements) Anyway, here's the code:
#include <QCoreApplication>
#include <QSerialPort>
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <Windows.h>
using namespace std;
int main(int argc, char *argv[])
{
QSerialPort serial0;
//serial.open(serial);
serial0.setBaudRate(QSerialPort::Baud9600);
serial0.setDataBits(QSerialPort::Data8);
serial0.setParity(QSerialPort::NoParity);
serial0.setStopBits(QSerialPort::OneStop);
serial0.setFlowControl(QSerialPort::NoFlowControl);
char *com="com";
int number;
char *comPlusNumber;
comPlusNumber=(char*) malloc(8*sizeof(char));
int j=10000;
while(j>0)
{
number=j;
sprintf(comPlusNumber, "%s%d",com,number);
//printf("%s \n",comPlusNumber);
serial0.setPortName(comPlusNumber);
serial0.open(QIODevice::ReadWrite);
if(serial0.isOpen()==true)
{
printf("YES*****************");
printf("%s \n",comPlusNumber);
}
else
//printf("No %d\n", number);
serial0.close();
j--;
}
free(com);
free(comPlusNumber);
printf("\n\n Test");
//QCoreApplication a(argc, argv);
//return a.exec();
}
I just wanted to make sure that I wasn't creating a memory leak.
Use the framework. You've got the power of Qt!
There are several problems:
The C-style string manipulations are unnecessary and wrong. Use QString:
auto name = QStringLiteral("COM%1").arg(i);
You can't use the serial port without a QCoreApplication instance present.
You shouldn't be testing for the presence of a port by iterating what you think might be valid ports. This is non-portable and unnecessary. Get a list of ports to start with.
Thus:
// https://github.com/KubaO/stackoverflown/tree/master/questions/simple-serial-35181906
#include <QtCore>
#include <QtSerialPort>
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
QSerialPort serial;
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
for (auto port : QSerialPortInfo::availablePorts()) {
serial.setPort(port);
serial.open(QIODevice::ReadWrite);
if (serial.isOpen()) {
qDebug() << "port" << port.portName() << "is open";
serial.close();
} else
qDebug() << "port" << port.portName() << "couldn't be opened";
}
}
Here's the output on my machine:
port "cu.serial1" is open
port "cu.usbserial-FTELA9I5" is open
port "cu.usbserial-PX9A3C3B" is open
You can only free what you dynamically allocated. You never dynamically allocated anything for com, so passing it to free is an error. It's equivalent to free("com"); which attempts to free a string constant.

Checking for existing .exe file Qt

why when i want to check .exe file this program will print false but when i add .txt file and check prints True?
i mean its only recognize .txt file not .exe
#include <QCoreApplication>
#include <QFile>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFile read("C:\\Users\\Ramin\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\Time.exe");
if(read.exists()){
qDebug()<<"True";
}
else{
qDebug()<<"False";
}
return a.exec();
}
thanks in advance

Basic Communications with QSerialPort

I am trying to rig up some basic serial communications in QT
I am getting the port COM19 from QSerialPortInfo, and I speaking successfully to the port via Arduino. However, I cannot get anything back via QT.
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <QTextStream>
#include <QFile>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){
qDebug() << "Name :" << info.portName();
qDebug() << "Description :" << info.description();
qDebug() << "Manufactuer :" << info.manufacturer();
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
qDebug() << serial.errorString();
serial.write("M114 \n");
qDebug() << serial.readAll();
serial.close();
// Now we need to send and receive commands
serial.setPortName("COM19");
serial.setBaudRate(QSerialPort::Baud57600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
if(serial.open(QIODevice::ReadWrite)){
qDebug() << "opened";
}else{
qDebug() << "Not opened";
}
qDebug() << serial.errorString();
serial.write("M114 \n");
qDebug() << serial.readAll();
serial.close();
}
MainWindow w;
w.show();
return a.exec();
}
As you can see, I am trying a simple connection along the lines of the documentation, and one where I write out all the baud rate information. They throw two different errors.
Like I said, I am connecting via arduino to this same port and having success. Any ideas what's wrong?
Name : "COM19"
Description : "USB Serial (Communication Class, Abstract Control Model)"
Manufactuer : "PJRC.COM, LLC."
"Unknown error"
""
opened
"The handle is invalid."
""
Any ideas for what I am doing wrong?
My idea is to send commands to the device, and read them back to the console.
the code looks a bit confuse. You open all port available and then you try to do something wrong.
NOTE: You use a GUI application like a shell application. It is wrong.
Try:
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <QTextStream>
#include <QFile>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSerialPort serial;
serial.setPortName("COM19");
if(serial.open(QIODevice::ReadWrite)){
//Now the serial port is open try to set configuration
if(!serial.setBaudRate(QSerialPort::Baud57600))
qDebug()<<serial.errorString();
if(!serial.setDataBits(QSerialPort::Data8))
qDebug()<<serial.errorString();
if(!serial.setParity(QSerialPort::NoParity))
qDebug()<<serial.errorString();
if(!serial.setStopBits(QSerialPort::OneStop))
qDebug()<<serial.errorString();
if(!serial.setFlowControl(QSerialPort::NoFlowControl))
qDebug()<<serial.errorString();
//If any error was returned the serial il corrctly configured
serial.write("M114 \n");
//the serial must remain opened
if(serial.waitForReadyRead(100)){
//Data was returned
qDebug()<<"Response: "<<serial.readAll();
}else{
//No data
qDebug()<<"Time out";
}
//I have finish alla operation
serial.close();
}else{
qDebug()<<"Serial COM19 not opened. Error: "<<serial.errorString();
}
MainWindow w;
w.show();
return a.exec();
}
Starting with the tenth port, his name will be \\.\COM10
You can reassign the port to a different number in Device Manager