The following code works - "echo" program is called for "abc" and "def",
the results are collected and printed.
If timer delay is set to 0, it stops working.
"echo" is called, even the readLine (if called) would return the right content,
but "finished" slot is never called. process.state() shows that the process is still running.
Why?
QFuture<QString> tfuture;
QFutureWatcher<QString> twatcher;
QString ftest(QString a){
QProcess process;
QEventLoop loop;
QObject::connect(&process, &QProcess::finished, [&](int exit_code) {
qDebug() << "OK " << a << " " << exit_code;
loop.exit(0);
});
QTimer::singleShot(1, [&] {
qDebug() << "STARTING " << a;
process.start("echo", {{"ECHO ", a}});
});
loop.exec();
return process.readLine();
};
void tfinished() {
QList<QString> result = twatcher.future().results();
qDebug() << "finished " << result;
}
...
QStringList params = {{"abc", "def"}};
tfuture = QtConcurrent::mapped(params, ftest);
connect(&twatcher, &QFutureWatcher<QString>::finished, this, &tfinished);
twatcher.setFuture(tfuture);
Related
I have this function :
bool TCPClient::sendPacket(Protocol::Packet &packet)
{
if(this->tcpSocket->state() == QAbstractSocket::ConnectedState)
{
std::cout << "writing ..." << std::endl;
std::cout << sizeof(BabelPacket) + packet.dataLength << std::endl;
this->tcpSocket->write((const char *)&packet, sizeof(Protocol::BabelPacket) + packet.dataLength);
return this->tcpSocket->waitForBytesWritten(-1);
}
else
{
std::cout << "socket close" << std::endl;
return false;
}
}
But when I called it, it blocks my GUI.
Have you got an idea how I can make this call non blocking, and still have the readyRead signal triggered ?
Thanks
I have multiples DNS record (MX, CNAME , TXT) and I would like to read the TXT record content.
The lookup() function never emit finished(), I am using this code to test:
QDnsLookup m_dns = new QDnsLookup(this);
connect(m_dns, SIGNAL(finished()), this, SLOT(onHandle()));
m_dns->setType(QDnsLookup::TXT);
m_dns->setName("uol.com.br");
m_dns->lookup();
void Update::onHandle()
{
if (m_dns->error() != QDnsLookup::NoError)
qDebug() << m_dns->error() << m_dns->errorString();
foreach (const QDnsServiceRecord &record, m_dns->serviceRecords())
qDebug() << "Name: " << record.name();
emit handled();
}
If I use a online service to read the record, it works!
The onHandle slot should be looking at m_dns->textRecords(), not m_dns->serviceRecords().
The correct code:
foreach (const QDnsTextRecord &record , m_dns->textRecords()) {
qDebug() << "Values: " << record.values();
qDebug() << "Name: " << record.name();
}
The following code is from an example shows how to use QNetworkAccessManager to download things.
void Downloader::replyFinished (QNetworkReply *reply)
{
if(reply->error())
{
qDebug() << "ERROR!";
qDebug() << reply->errorString();
}
else
{
qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toString();
qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString();
qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
QFile *file = new QFile("C:/Qt/Dummy/downloaded.txt");
if(file->open(QFile::Append))
{
file->write(reply->readAll());
file->flush();
file->close();
}
delete file;
}
reply->deleteLater();
}
My question is do we have to call reply->deleteLater(); here? If we don't call it, when we perform QNetworkAccessManager::get() call the second time, will the QNetworkReply* in the slot be the same QNetworkReply* ?
If you don't call deleteLater(), the QNetworkReply object will be leaked and its memory not freed. A second get() call will create a new QNetworkReply object.
I have a sever client application and in the beginning client loads data from server. I have a dialog showing status of getting data from server (has progress bar). But when I call the function the dialog appears with no contents in it with white background and suddenly changes to completed status.
void SystemScreen::loadServerData()
{
qDebug() << Q_FUNC_INFO << "Invoked";
if (NULL != mpDataManagerDlg)
{
qDebug() << Q_FUNC_INFO << "show progres screen";
mpDataManagerDlg->showScreen();
}
loadData();
qDebug() << Q_FUNC_INFO << "Exits";
}
void SystemScreen::loadData()
{
qDebug() << Q_FUNC_INFO << "Invoked";
if (NULL != mpDataManager)
{
mpDataManager->loadDataFromServer();
}
qDebug() << Q_FUNC_INFO << "Exits";
}
I feel that dialog is displayed only after loadData() function is completed. Is there any alternative to do this?
I used a timer to start
QTimer::singleShot(100, this, SLOT(loadData()));
But then I have some trouble in getting data. ie data is empty if I read suddenly.
EDIT:
void DataManagerDialog::setDefault()
{
qDebug() << Q_FUNC_INFO << "Invoked";
setProgressBar(0);
setProgressBarColor(false);
ui->deptFailButton->hide();
ui->deptOkButton->hide();
ui->deptLabel->setStyleSheet("color:gray");
ui->subGroupFailButton->hide();
ui->subGroupOkButton->hide();
ui->subGroupLabel->setStyleSheet("color:gray");
ui->itemFailButton->hide();
ui->itemOkButton->hide();
ui->itemLabel->setStyleSheet("color:gray");
ui->salesBtnFailButton->hide();
ui->salesBtnOkButton->hide();
ui->salesBtnLabel->setStyleSheet("color:gray");
qDebug() << Q_FUNC_INFO << "Exits";
}
void DataManagerDialog::alignCenter()
{
qDebug() << Q_FUNC_INFO << "Invoked";
QWidget *par = parentWidget();
if (par)
{
int x = width()/2;
int y = height()/2;
QPoint mid(mapToGlobal(QPoint(x, y)));
int px = par->width()/2;
int py = par->height()/2;
QPoint parMid(mapToGlobal(QPoint(px, py)));
move(parMid.x()-mid.x(), parMid.y()-mid.y());
}
qDebug() << Q_FUNC_INFO << "Exits";
}
void DataManagerDialog::showScreen()
{
setDefault();
alignCenter();
show();
}
You probably do not enter the event loop.
Try to call QCoreApplication::processEvents() from time to time in mpDataManager->loadDataFromServer() to update the GUI.
From the processEvents documentation :
You can call this function occasionally when your program is busy performing a long operation (e.g. copying a file).
Edit added after getting feedback from the comments
A better approach would be to send signals in your loadDataFromServer() method with the status information and have a slot listen to the signal and update the GUI.
Here a prototype illustrating the idea :
void mpDataManagerDlg::loadDataFromServer() {
while(true) {
// do some work
int progress = // some value
emit updateDialogSignal(progress);
}
}
// in your dialog class
public slots:
void DataManagerDialog::updateDialog(int progress) {
// update gui
}
More about signals and slots can be found here.
I've got some code that starts mencoder in a QProcess, converts a video while displaying a progress bar, then exits. The problem is, mencoder always exits before it's actually finished. The loop runs through a few times, and then closes. If I comment out the line that updates the progress bar (progress.setValue()), mencoder runs to completion and exits happily.
Been at this for a day, and can't figure it out! Also, I should mention I'm on a Mac.
Any ideas?
Thanks
Marlon
void MainWindow::convertVideo()
{
QString input_filename = "/var/input.avi";
QString output_filename = "/var/output.264";
QStringList arguments;
arguments << input_filename << "-nosound" << "-of" << "rawvideo" << "-ofps" << "30" << "-vf" << "harddup" << "-ovc" << "x264" << "-x264encopts" << "bframes=0" << "-o" << output_filename;
QProcess* myProcess = new QProcess(this);
myProcess->setReadChannel(QProcess::StandardOutput);
myProcess->start("/opt/local/bin/mencoder", arguments);
QString output_string;
QStringList output_pieces;
QProgressDialog progress("Converting video...", "Abort", 0, 100, this);
progress.setWindowModality(Qt::WindowModal);
progress.setValue(0);
progress.show();
while(myProcess->state() != QProcess::NotRunning)
{
output_string = myProcess->readAllStandardOutput();
output_pieces = output_string.split(" ");
QStringList width_string_list = output_pieces.filter("%)");
if(width_string_list.length() > 0)
{
width_string_list = width_string_list[width_string_list.length() - 1].split("(");
if(width_string_list.length() > 1)
{
width_string_list = width_string_list[1].split("%");
}
else
{
width_string_list = width_string_list[0].split("%");
}
progress.setValue(width_string_list[0].toInt());
qDebug() << width_string_list[0].toInt();
}
myProcess->waitForReadyRead();
}
return;
}
I think the QProcess timeouts before it finishes its job. Adding a myProcess->waitForFinished(-1) might help. Then your process wont timeout.