C++ integration Qt - qt

So I wrote a Qt quick application that takes user inputs and stores them in a json file. I now want to add a feature that lets me recall the data in my file and display it in a text field within my application. I can get the text in the C++ portion of my application, Im just not sure how to display it in my user interface. Here is the code to get the text from my json file.
void Jsonfile:: display(){
//1. Open the QFile and write it to a byteArray and close the file
QFile file;
file.setFileName("data.json");
if(!file.open(QIODevice::ReadOnly)){
qDebug() << "file couldn't be opened/found";
return;
}
QByteArray byteArray;
byteArray = file.readAll();
file.close();
//2. Format the content of the byteArray as QJsonDocument
//and check on parse Errors
QJsonParseError parseError;
QJsonDocument jsonDoc;
jsonDoc = QJsonDocument::fromJson(byteArray, &parseError);
if(parseError.error != QJsonParseError::NoError){
qWarning() << "Parse error at " << parseError.offset << ":" << parseError.errorString();
return;
}
QTextStream textStream(stdout);
textStream << jsonDoc.toJson(QJsonDocument::Indented);
}

Related

Error transferring https://speech.googleapis.com/v1/speech:recognize?key=,myKey> - server replied: Bad Request [Problem on Windows OS]

I am using google speech-to-text api to convert my audio file to text. Following is my code(in Qt):
`QString fileName = QDir::currentPath() + "/audio.wav"; //this is my audio file
QFile audioFile(fileName);
if(!audioFile.open(QIODevice::ReadOnly | QIODevice::Text)){
QMessageBox::critical(0,"Error",fileName+" Not found!");
ui->pushButton_4->setText("Speech to text");
return;
}
int idx = ui->comboBox->currentIndex();
QString enc;
if (idx == -1)
enc = "en-US";
else
enc = ui->comboBox->itemData(idx).toString(); //Language selected by user
QByteArray audioData=audioFile.readAll();
QUrl url("https://speech.googleapis.com/v1/speech:recognize");
QUrlQuery query;
query.addQueryItem("key","myKeyHere...");
url.setQuery(query);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader,"audio/x-flac");
QJsonObject json;
QJsonObject config;
config["encoding"]="FLAC";
config["sampleRateHertz"]=44100;
config["languageCode"]=enc;
json["config"]=config;
QJsonObject audio;
audio["content"]=QString::fromLatin1(audioData.toBase64());
json["audio"]=audio;
QByteArray jsonData=QJsonDocument(json).toJson();
QNetworkAccessManager *manager=new QNetworkAccessManager();
QNetworkReply *reply=manager->post(request,jsonData);
QObject::connect(reply,&QNetworkReply::finished,[this,reply](){
if(reply->error()!=QNetworkReply::NoError){
QMessageBox::critical(0,"Error Occured",reply->errorString());
qDebug() << reply->readAll();
ui->pushButton_4->setText("Speech to text");
return;
}
else if(reply->error()==QNetworkReply::UnknownNetworkError){
QMessageBox::warning(0,"Network Error","Please check your internet connection and try again!");
ui->pushButton_4->setText("Speech to text");
}
else if(reply->isFinished() && reply->error()==QNetworkReply::NoError){
QJsonDocument responseJson=QJsonDocument::fromJson(reply->readAll());
QJsonObject object=responseJson.object();
QString ResponseText=object["results"].toArray()[0].toObject()
["alternatives"].toArray()[0].toObject()["transcript"].toString();
QTextCursor cur = curr_browser->textCursor();
qDebug() << "Response Data :" << ResponseText;
cur.insertText(ResponseText);
ui->pushButton_4->setText("Speech to text");
}
reply->deleteLater();
});`
This code is working perfectly on Ubuntu but not on windows. When i run this on Ubunutu, i am receiving the response, but on windows i receive the following error:
Error transferring https://speech.googleapis.com/v1/speech:recognize?key=,myKey> - server replied: Bad Request
Following is the code to record an audio file:
`if (m_audioRecorder->state() == QMediaRecorder::StoppedState) {
QString fileName = QDir::currentPath() + "/audio.wav";
m_audioRecorder->setOutputLocation(QUrl::fromLocalFile(fileName));
qDebug()<<"Recording your audio!!";
ui->pushButton_4->setText("Stop ?");
QAudioEncoderSettings settings;
settings.setCodec("audio/x-flac");
settings.setSampleRate(0);
settings.setBitRate(0);
settings.setChannelCount(1);
settings.setQuality(QMultimedia::EncodingQuality(2));
settings.setEncodingMode(QMultimedia::ConstantQualityEncoding);
m_audioRecorder->setEncodingSettings(settings, QVideoEncoderSettings(), "");
m_audioRecorder->record();
}
else {
qDebug()<<"stopped your recording!";
ui->pushButton_4->setText("Processing ...");
m_audioRecorder->stop();
speechToTextCall(); //calling the code to send request to google api
}`
Can anyone help please?
I tried changing the encodig and container type, but nothing worked on Windows.
I have found the solution of above problem. Windows does not recognize the auido/x-flac encoding so i modified my encoding code as follows:
'
#ifdef Q_OS_WIN
settings.setCodec("audio/pcm");
#else
settings.setCodec("audio/x-flac");
#endif
'
I made the same changes at other two places where encoding was set and it worked on windows as well.

How get raw answer data in QWebEngineView?

Next examples work on small html pages, but dont work if page return big html data or json
I try this after loadFinished signal
view->page()->toHtml([cc](const QString &result){
qDebug() << "result ready";
qDebug() << "result string ="<<result;
});
I see "result ready", but second string not print, also I try this:
v->page()->runJavaScript("function jsfun(){return document.getElementsByTagName('html')[0].outerHTML;};");
//v->page()->runJavaScript("alert(jsfun())"); //work correctly
v->page()->runJavaScript("jsfun();",[this](const QVariant &v) {
qDebug() << "result ready";
qDebug() << "result string ="<<v.toString();
});
but again dont see second string
All example work correctly, but if buffer very big qDebug dont print data, you can write data to file or print part of data
Example (call toHtml after loadFinished signal) :
view->page()->toHtml([cc](const QString &result){
QFile file("outerHTML.html");
if(!file.open(QFile::WriteOnly | QFile::Text)){
qDebug() << "Cannot create a file";
return;
}
QTextStream stream(&file);
stream << buff;
file.close();
}

Cannot open QFile for appending/readwrite

I am trying to use the following code to open the existing file to append data at it's end:
void AddPharmacyForm::addInsertToFile(QString insert)
{
QFile inserts(":/new/prefix1/insertstatements.txt");
if(!inserts.exists())
qDebug() << "File does not exist";
if(inserts.isOpen())
qDebug() << "file is open";
if(inserts.open(QFile::ReadWrite | QFile::Text))
{
// Another workaround- could not open file with append flag
qDebug() << "im here!";
QString currentInserts;
QTextStream out(&inserts);
out >> currentInserts;
out << endl << insert;
inserts.close();
}
else
{
QMessageBox::information(this, tr("Error"), tr("Cannot add new pharmacy! "
"Please contact program designer."
));
qDebug() << "error code: " + QString::number(inserts.error());
return;
}
}
The output of this code is the QMessageBox with the error and in qDebug it produces following line:
"error code: 5"
It does not give notice about file not existing and file being open. I have also tried opening file with different flags: QFile::ReadWrite, QFile::append, QFile::WriteOnly and the same modes within QIODevice. The error code is still the same. When I am opening the file from another class, the file opens without errors (it is not an access error).
What might be causing this problem?
There's no support for writing into the resource system, whether implemented using Qt's resource system or native to the platform. Your application typically has no right to modify its own executable, or the application bundle, or its installation location - it'd be a security risk if it did since bugs in networking code could be easily exploited to infect your user's system. So what you're trying to do is just a bad idea.
Instead, store the modified resources in your application's data folder, and revert to reading from the resource if the file doesn't exist. It is also probably not very wise to append to a file if the file is small: such appends are not atomic and can partially fail, leaving the file corrupted. Using a QSaveFile is guaranteed to either completely succeed or to fail without modifying any data.
An example implementation follows. The src.close() is not necessary to close the file, as QFile will automatically close upon destruction, as it is a proper resource-managing C++ class. By closing it earlier we ensure minimal use of the file descriptor - a finite system resource.
// https://github.com/KubaO/stackoverflown/tree/master/questions/resource-bypass-43044268
#include <QtCore>
const char kInsertsFile[] = ":/insertstatements.txt";
QString toWritableName(const QString & qrcFileName) {
Q_ASSERT (qrcFileName.startsWith(":/"));
QFileInfo info(qrcFileName);
return
QStandardPaths::writableLocation(QStandardPaths::DataLocation)
+ info.path().mid(1) + '/' + info.fileName();
}
QString toReadableName(const QString & qrcFileName) {
Q_ASSERT (qrcFileName.startsWith(":/"));
auto writable = toWritableName(qrcFileName);
return QFileInfo(writable).exists() ? writable : qrcFileName;
}
bool setupWritableFile(QSaveFile & dst, QIODevice::OpenMode mode = {}) {
Q_ASSERT (dst.fileName().startsWith(":/"));
Q_ASSERT (mode == QIODevice::OpenMode{} || mode == QIODevice::Text);
QFile src(toReadableName(dst.fileName()));
dst.setFileName(toWritableName(dst.fileName()));
if (!src.open(QIODevice::ReadOnly | mode))
return false;
auto data = src.readAll();
src.close(); // Don't keep the file descriptor tied up any longer.
QFileInfo dstInfo(dst.fileName());
if (!dstInfo.dir().exists() && !QDir().mkpath(dstInfo.path()))
return false;
if (!dst.open(QIODevice::WriteOnly | mode))
return false;
return dst.write(data) == data.size();
}
bool addInsertToFile(const QString & insert) {
QSaveFile file(kInsertsFile);
if (!setupWritableFile(file, QIODevice::Text))
return false;
if (true) {
// Alternative 1
QTextStream s(&file);
s << insert << '\n';
} else {
// Alternative 2
file.write((insert + '\n').toLocal8Bit());
}
return file.commit();
}
QStringList readInserts() {
QFile file(toReadableName(kInsertsFile));
if (!file.open(QIODevice::ReadOnly))
return {};
return QString::fromLocal8Bit(file.readAll()).split('\n', QString::SkipEmptyParts);
}
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
app.setApplicationName("resource-bypass-42044268");
qDebug() << "Original Inserts:" << readInserts();
auto rc = addInsertToFile("NewInsert");
qDebug() << "Modification status:" << rc;
qDebug() << "Current Inserts:" << readInserts();
}
When you use the Qt Resource System (qrc files) to add files for your project, they are compiled directly into the binary of your application, so are therefore readonly. As the documentation states: -
Resource data can either be compiled into the binary and thus accessed immediately in application code, or a binary resource can be created and at a later point in application code registered with the resource system.
And...
Currently, Qt always stores the data directly in the executable, even on Windows, macOS, and iOS, where the operating system provides native support for resources. This might change in a future Qt release.

Read all input from QSerialPort

I am receiving data in this shape:
Q1\n
9.70E-6\n
OK>
from an external device via QSerialPort, but with my reading routine
QString request = "Hello";
qDebug() << "TransAction started!";
QByteArray requestData = request.toLocal8Bit();
qDebug() << "Writing data: " << requestData;
serial->write(requestData);
qDebug() << "Data written";
if(serial->waitForBytesWritten(waitTimeout))
{
if(serial->waitForReadyRead(waitTimeout))
{
qDebug() << "Waiting for data!";
QByteArray responseData = serial->readAll();
while(serial->waitForReadyRead(100))
responseData += serial->readAll();
responseData.replace('\n', ' ');
QString response(responseData);
QByteArray response_arr = response.toLocal8Bit();
qDebug() << "Response is: " << response_arr.toHex();
emit this->response(response);
}
else
{
qDebug() << "Wait read response timeout";
emit this->timeout(tr("Wait read response timeout %1").arg(QTime::currentTime().toString()));
}
}
else
{
qDebug() << "Wait write request timeout!";
emit this->timeout(tr("Wait write request timeout %1").arg(QTime::currentTime().toString()));
}
I only get
Q1
as response. How can I modify my code such that I am able to read all input data?
Update:
When testing it with the serial port script described here: https://stackoverflow.com/a/7654527/2546099, everything works. Apparently the problem is that the qt-version stops reading after the first line break. This problem consists also if I add
char buffer[1000];
for(int i = 0; i < 1000; i++)
{
int tmp = serial->read(buffer, 1000);
if(tmp > 0)
qDebug() << buffer;
}
directly after the line
qDebug() << "Waiting for data!";
Then I still only get the first line (without the \n). Changing times does not change the received data.
The answer to my problem is (partly) described in this question: External vs internal declaration of QByteArray. My problem (why I did not receive any further data) was that I did not send a \x00D after the input line, thus the device just echoed my input, and was waiting for the Enter afterwards. After the input looks exactly as the first line, I misunderstood it for just getting the first line, and nothing else.

Qt Imgur upload fail

I have an uploader like this
void uploader::upload() {
QUrl serviceUrl = QUrl("http://api.imgur.com/2/upload.json");
QByteArray postData;
postData.append("key=MY_KEY&");
postData.append("image=" + file.toBase64());
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(serviceRequestFinished(QNetworkReply*)));
networkManager->post(QNetworkRequest(serviceUrl), postData);
}
void uploader::serviceRequestFinished(QNetworkReply* reply) {
qDebug() << "Done" << endl;
QString response = reply->readAll();
qDebug() << response;
QScriptValue sc;
QScriptEngine engine;
sc = engine.evaluate(response);
qDebug() << sc.property("upload").property("links").property("original").toString();
}
file is QByteArray with PNG file content which i want to upload.
When uploading ends, I receive the response, but uploaded image is not valid (if i save it and trying to open, it writes that the file is not valid PNG image).
What I'm doing wrong?

Resources