C++ QT QFileDialog does not close when using system() in triggered action - c++

void OBJ_Loader::on_actionOpen_triggered()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Open a File"));
if (!filename.isEmpty()) {
filepath=filename.toUtf8().constData();
command.append(filepath);
int TempNumOne=command.size();
for (int a=0;a<=TempNumOne;a++) { //get letters to a char list so it can be used by system();
cmd[a]=command[a];
}
openfile=true;
if (openfile) {
openfile=false;
system(cmd);
}
}
}
When the system(cmd); is called the QFileDialog window does not close till the system command finishes. I would like to know if I can close the search window after clicking open.

The system function blocks the event loop: the user interaction requires the event loop to run, and it runs when your code isn't running. Since the system invocation is in your code, you can't simply have it block your process. You need to use QProcess as it has an asynchronous interface. This answer provides a complete example of one process calling itself -- all done from a single executable.

Related

showing cmd terminal in qt widgets application

I'm trying to pass some cmd commands using system() and I would like to be able to "communicate" with cmd, say I code in system("dir") in my mainwindow.cpp under my clicked function
this is what it looks like for example
void MainWindow::on_pushButton_login_clicked()
{
std::string platform_server_ip = ui->lineEdit_platform_server_ip->text().toStdString();
if (platform_server_ip == "dir"
{
QMessageBox::information(this,"Login", "all required log in details are correct");
close();
const char* c = platform_server_ip.c_str();
system(c);
system("ipconfig");
}
I would like to know why it behaves like this and if that's normal. I've included CONFIG += console
in my project file, and checked "run in terminal" (tried it also without) but it never shows me my desired outcome.
Instead what I get, is a blank terminal that pops up along side my GUI, and then when I enter "dir" in my GUI and hit enter, a cmd window pops up really fast and in less than a second, its gone. I've even tried it with system("ipconfig")andsystem ("pause")
as well as with one system command like this system("ipconfig" "&pause")
desired outcome: is just a normal execution of system("ipconfig"), followed by other system commands, that display the same result as typing them in cmd itself.
I've also tried all this in "qt Console application" and I either get the same result, or the output (what would normally be as output on cmd) is then found in "application output" of qt creator.
Is there another better way I can achieve what I want?
I'm truly a noob and would really appreciate some guidance.
You can try
system("cmd /k ipconfig");
This will open another terminal window which will stay open (k stands for keep) at the end of the command execution.
I think you don't need the CONFIG += console project setting, to achieve this. Calling system will start another process, which isn't related at all with the calling application.
If you want to start external programs from within a Qt application, you can use QProcess class, which lets you somehow interact with the started processes through standard in/out. For a very simple example, have a form with a push button and a text edit called textEdit; in the push button clicked slot:
QProcess process;
process.start("ipconfig");
process.waitForReadyRead();
ui->textEdit->setText(process.readAll());
process.waitForFinished();
This way, you won't see additional console windows, and the command output will be shown directly in your text edit.
This can be generalized in a function like this:
bool exec(QString command)
{
QProcess process;
process.start(command);
if(!process.waitForStarted())
{
return false; //the process failed to start
}
//etc...
return true;
}
Depending on whether this is not just a quick hack/tool, you can look at QProcess for more indepth control over your process so that you can read / write the child process pipes.

QFileDialog causes my application to become less responsive

Firstly, for context, I am connecting a signal from triggered from QAction to a slot called fileOpen in this, and other similar connections are done in a method in my main window class like the following:
void MainWindow::createActions()
{
m_fileNew = new QAction("&New", this);
m_fileOpen = new QAction("&Open", this);
m_fileExit = new QAction("E&xit", this);
connect(m_fileNew, SIGNAL(triggered(bool)), this, SLOT(fileNew()));
connect(m_fileOpen, SIGNAL(triggered(bool)), this, SLOT(fileOpen()));
connect(m_fileExit, SIGNAL(triggered(bool)), this, SLOT(fileExit()));
}
To show the file dialog, the static method QFileDialog::getOpenFileName is used in MainWindow::fileOpen:
void MainWindow::fileOpen()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Open Audio File"),
"", tr("WAVE Files (*.wav);;All Files (*.*)"));
if (filename != QString::null) {
m_fileName = filename;
}
}
The signal-slot connection between m_fileOpen and fileOpen works and displays the file dialog, but after closing the dialog the window takes longer to redraw while resizing.
Why is that happening, and how can I fix it?
All I had to do was build my Qt application in release mode, which means removing the "CONFIG+=debug" argument from the qmake call.
In release mode the performance degradation is gone, which is great, although I don't understand what differences between the debug and release versions of the Qt libraries allow this to occur.

qt wait for signal/event, GUI

I am working on an Qt application which has the possability to use a script to perform several actions. One command within the script requires an external event to happen until the next command in the list can be computed (which is
not the case for the rest of the commands).
Usually, I open the file, read a line of the script and process it. This is repeated until the EOF is reached.
Emitting a signal when the external event occured is possible, but the function which runs through the script hast so to be stopped during this timespan.
How can i archive this whithout locking the GUI response?
Thank you!
I would do it this way:
public:
void execute_script() {
//open file
continue_execution();
}
public slots:
void continue_execution() {
while(!file.atEnd()) {
//read and process command
if(async_command) {
//make sure the signal indicating command completion
//is connected to continue_execution() slot
return;
}
}
emit script_finished();
}

Qt QFileSystemWatcher on Windows doesn't send fileChanged() signal

I'm tracking a log file that is changed by another application. In linux I receive the fileChanged signal correctly as soon as the other application changes the file. In windows QFileSystemWatcher doesn't emit any fileChanged signal until the other application is closed.
I have tried to open the log with notepad to make sure is actually been changed and as soon as the notepad open the log ,QFileSystemWatcher sends the fileChanged signal.
My code:
void LogLoader::createFileWatcher()
{
if(fileWatcher != NULL) delete fileWatcher;
fileWatcher = new QFileSystemWatcher(this);
connect(fileWatcher, SIGNAL(fileChanged(QString)),
this, SLOT(prepareLogWorker(QString)));
if(fileWatcher->addPath(logPath))
{
qDebug() << "LogLoader: "<< "FileWatcher linked.";
}
}
void LogLoader::prepareLogWorker(QString path)
{
//Added this just in case because I read it as solution
//in other question. But in my case the file is not removed.
if (!fileWatcher->files().contains(path))
{
fileWatcher->addPath(path);
}
QTimer::singleShot(1000, this, SLOT(sendLogWorker()));
}
Am I doing something wrong? Is there any other solution than checking
the file manually from time to time?

Display QProcess output in another window

I'm using the QT Creator on Ubuntu.
I have GUI with a mainwindow and another window called "progress".
Upon clicking a button the QProcess starts and executes an rsync command which copies a folder into a specific directory. I created a textbrowser which reads the output from the rsync command. Also clicking the button causes the "progress" window to pop up.
So far so so good, now my problem.
Instead of showing the rsync output in my mainwindow i want it to be in progress.
I've tried several methods to get the QProcess into the progress via connect but that doesn't seem to work.
mainwindow.cpp
void MainWindow::on_pushButton_clicked()
{
if (ui->checkBox->isChecked()
)
m_time ="-t";
QObject parent;
m_myProcess = new QProcess();
connect(m_myProcess, SIGNAL(readyReadStandardOutput()),this, SLOT(printOutput()));
QString program = "/usr/bin/rsync";
arguments << "-r" << m_time << "-v" <<"--progress" <<"-s"
<< m_dir
<< m_dir2;
m_myProcess->start(program, arguments);
}
progress.cpp
void Progress::printOutput()
{
ui->textBrowser->setPlainText(m_myProcess->readAllStandardOutput());
}
I know it's pretty messy iv'e tried alot of things and haven't cleaned the code yet also I'm pretty new to c++.
My goal was to send the QProcess (m_myProcess) to progress via connect but that didn't seem to work.
Can you send commands like readyReadAllStandardOutput via connect to other windows (I don't know the right term )?
Am I doing a mistake or is there just another way to get the output to my progress window ?
m_myProcess is a member of the class MainWindow and you haven't made it visible to the class Progress. That's why you have the compilation error
m_myProcess was not declared in this scope
What you could do:
Redirect standard error of m_myProcess to standard output, such that you also print what is sent to standard error (unless you want to do something else with it). Using
m_myProcess.setProcessChannelMode(QProcess::MergedChannels);
Make the process object available outside MainWindow
QProcess* MainWindow::getProcess()
{
return m_myProcess;
}
Read the process output line by line in Progress. It needs to be saved in a buffer because readAllStandardOutput() only return the data which has been written since the last read.
... // somewhere
connect(window->getProcess(), SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput())
...
void Progress::printOutput(){
//bigbuffer is member
bigbuffer.append(myProcess->readAllStandardOutput();)
ui->textBrowser->setPlainText(bigbuffer);
}