Why can't I pass arguments with QProcess when launching blender? - qt

Trying to run this code in the main function of a console app in QT but it only starts up the Blender GUI. These arguments should be starting a background render.
I tested the arguments to be correct and they work fine on CMD. This seems to be a blender specific issue but I might be wrong. It seems as though, using QProcess it doesn't allow for Blender to use the arguments. It launches the app without passing any arguments.
QProcess myProcess;
QString blender = "C:/Program Files/Blender Foundation/Blender/blender.exe";
QStringList arguments;
arguments << "blender" << "-b" << "E:/my/file.blend" << "-o" << " E:/my/output/folder/"<< "-a";
myProcess.start(blender,arguments);
Edit:
So browsing through SO, I found something that's working but this isn't using the QT functionality. I'd rather find the QT way of doing this. What it's essentially doing is running CMD and launching blender through the CMD. Is there a way I can do this using QT?
QDir::setCurrent(blender);
system("blender -b E:\\Blender\\BlendSwap\\55510_Ciclos_Town_-_10_Male_Characters\\cidade_ciclos-bonecos.blend -o E:\\Blender\\BlendSwap\\55510_Ciclos_Town_-_10_Male_Characters\\exp\\frame_### -a");

Thanks for #MaxGo and #G.M. because they set me on the right path.
Two things:
First off, tt's true that using the "blender" flag was one of the issues. I can't launch the .exe file and also expect blender to take in the arguments.
Second, start() will not work, you do need to use startDetached or execute() for it to work.
Below is the final code to make this launch correctly.
QDir::setCurrent(blenderDirectory);
myProcess.startDetached("blender -b " + projectPath + " -o " + projectOutput + " -a");

Related

Qt QMake - Define a string using replace function 'eval'

I'm trying to refactoring some part of my .pro files.
To do that, I'm using 'eval' & 'export' QMake functions. More precisely, I'm trying to define a string to use it in source code.
eval(DEFINES += TEST_DEFINE=\\\"MyString\\\")
eval(export(DEFINES))
When I try to use TEST_DEFINE in source code, TEST_DEFINE is no longer a string...
Ex:
qDebug() << "Test : " << TEST_DEFINE;
Compilation Output:
use of undeclared identifier 'MyString'
And if I try without using eval, it's working properly:
DEFINES += TEST_DEFINE=\\\"MyString\\\"
Any ideas ? :)

Qt qaxwidget setcontrol() from file name in order to "xxx.doc" show in widget,but then the winword.exe process can't quit

I've tried two ways to load a Word document into Qt qaxwidget, but neither successfully quits the winword.exe process.
My first attempt
ui->axWidget->setControl("D:/1.doc");
QAxObject *app = ui->axWidget->querySubObject("Application");
app->dynamicCall("Quit()");
Sometimes the following will work, but not reliably:
ui->axWidget->("Word.Application");
setProperty("DisplayAlerts", false);
setProperty("Visible", false);
ui->axWidget->setControl("D:/1.doc");//then call this line of code
QAxObject *app = ui->axWidget->querySubObject("Application");
ui->axWidget->dynamicCall("Close(bool)", false);
ui->axWidget->clear();
app->dynamicCall("Quit()");
What should I do to properly clos thee "winword.exe" process?
My enviroment is qt4.8.0+vs2008.
The first solution should be correct,but there are some other thing that limit me from closing the process.
The second solution is completely an error,When I call ui->axWidget->setControl("D:/1.doc");,"Word.Application" is out of control.
So,we wanna load a Word document into Qt qaxwidget firmly,my solution is
QProcess p;
QString c = "taskkill /im winword.exe /f";
p.execute(c);
p.close();

Can't run cmd or python from Qt C++ app (but can run, say, notepad)

I have followed numerous examples littered around the web for running a python script from a Qt app, but I just cannot get it to work. I've tried this:
QProcess unknown error
Amongst many other examples.
I have even directly copied examples which other people have said works, but with no success at all. I simply cannot get a python script to run or even launch a cmd window. I can, however, launch notepad.
This, for example is called when I press a button:
void MainWindow::test()
{
qint64 pID;
QProcess *myProcess = new QProcess(this);
QStringList arguments;
arguments << "/k cd /d " << "c:\path to be opened";
myProcess->startDetached("cmd.exe", arguments, "", &pID);
}
To no avail.
Also, this:
QProcess p;
QStringList params;
params.clear();
params.append("C:\\Software\\Qt\\StarLib\\cadstar_workspace_paths.py");
params.append("C:\\Software\\Qt\\StarLib\\TP1268_RDU5.csw");
params.append("C:\\Software\\Qt\\StarLibcadstar_local_user_directories.txt");
p.setWorkingDirectory("C:\\Software\\Qt\\StarLib");
p.setProgram("py");
p.setArguments(params);
p.start();
if (!p.waitForStarted()) {
ui->textEdit->append("Could not start process");
return;
}
else
ui->textEdit->append("The program seems to have started.");
QTime time;
time.start();
while (time.elapsed() < 4000)
QApplication::processEvents();
p.kill();
p.waitForFinished();
With this code, it reports that the application seems to have started, even though it hasn't.
Can someone point me in the right direction please? Am happy to post any further relevant information that would help. I'm clearly missing something fundamental here!

With Qt, how to check if stdin is empty?

I have a Qt program that processes stdin data like this:
QTextStream qtin(stdin);
QString stdindata = qtin.readAll();
QByteArray ba;
ba = stdindata.toUtf8();
QJsonDocument exJSONDoc(QJsonDocument::fromJson(ba));
QJsonObject extRoot;
extRoot = exJSONDoc.object();
QStringList keys;
keys = extRoot.keys();
for (int n=0; n <= keys.count()-1; n++)
{
qDebug() << extRoot.value(keys[n]).toString();
}
It works when I call my program like this:
myprogram < ./data.json
But if I call it without any "<" it hangs in qtin.readAll().
How can I check with Qt if the stdin is empty?
(I am assuming a Linux -or at least POSIX- operating system)
QTextStream qtin(stdin);
QString stdindata = qtin.readAll();
This would read stdin till end-of-file is reached. So works with a redirected input like
myprogram < ./data.json
But if I call it without any "<" it hangs ...
But then (that is, if you run myprogram alone) stdin is not empty. It is the same as your shell's stdin. and your program, being the foreground job, is waiting for input on the terminal you are typing (see also tty(4)). Try (in that case) typing some input on the terminal (which you could end with Ctrl D to make an end-of-file condition). Read about job control and the tty demystified and see also termios(3).
Perhaps you could detect that situation with e.g. isatty(3) on STDIN_FILENO. But that won't detect a pipe(7) like
tail -55 somefile | myprogram
You need to define what an empty stdin is for you. I have no idea what that means to you, and I would instead think of myprogram < /dev/null (see null(4)) as the way to get an empty stdin.
Perhaps you should design myprogram so that some program
option (perhaps --ignore-stdin) is avoiding any read from stdin.
Problem here is readAll. See documentation:
Reads the entire content of the stream, and returns it as a QString.
Avoid this function when working on large files, as it will consume a
significant amount of memory.
So it reads stdin until it encounters end of file and since stdin is associated with console you have to signal end of file. Usually it is Ctrl-D and press enter.
It is more probable you what to read stdin line by line.
To alow user text editing console transfers data to standard input of the application only line by line. This was designed like this ages ago when computer had only a printer as user interface (no screen).
Now question is how to read JSon form stdin console connected with console without end of file information?
I would use some SAX parser, but this would be to complicated for you.
So is there another way to detect end of JSon?
You can try this approach (this is basic idea, not final solution, so it has couple shortcomings):
QFile file(stdin);
QByteArray data = file.peak(largeNumber);
QJsonParseError error;
QJSonDocument doc = QJSonDocument::fromJson(data, &error);
while (!doc.isValid() && JSonNotTerminatedError(error.error))
{
// TODO: wait for new data - it would be best to use readyRead signal
doc = QJSonDocument::fromJson(data, &error);
}
Where JSonNotTerminatedError returns true for respective QJsonParseError::ParseError values (see linked documentation) which are related with unterminated JSon data.
Now I see QFile doesn't have required constructor, but main concept should be clear. Read data from stdin and check if it is a valid JSon document.

How to run a file.m from qt

I have a file.m, which is a file from matlab, and I want it to run when I run my qt project.
I noticed I could use this -r MATLAB_command - Start MATLAB and execute the MATLAB_command.
and this,
-nodesktop - Do not start the MATLAB desktop. Use the current
terminal for commands. The Java virtual machine
will be started.
from the matlab help, but i'm not sure if I'm thinking the right way.
My main.cpp
#include <QtGui/QApplication>
#include <iostream>
using namespace std;
#include <cmath>
#include <QProcess>
#include "planevolume.h"
#include "dialog.h"
int main(int argc, char *argv[])
{
// Start MATLAB MAIN.m
QProcess* p = new QProcess(NULL);
p->start( QString( "/usr/local/MATLAB/R2011b/bin/matlab"),
QStringList() << QString("-r /home/matt/Desktop/PlaneVolumeExec/MAIN.m")
<< QString("-nosplash")
<< QString("-nodesktop"));
QApplication app(argc, argv);
Dialog *dialog= new Dialog;
if (dialog->exec())
{
planevolume mainwindow(dialog->getdirprefix(),dialog->getxpax(), dialog->getypax(), dialog->getzpax(), dialog->getxmmax(), dialog->getymmax(), dialog->getzmmax(), dialog->getintzminp(), dialog->getintzmaxp(), dialog->getintzminm(), dialog->getintzmaxm());
mainwindow.show();
return app.exec();
}
return 0;
}
Matlab help
/*-h|-help - Display arguments.
-n - Display final environment variables,
arguments, and other diagnostic
information. MATLAB is not run.
-e - Display ALL the environment variables and
their values to standard output. MATLAB
is not run. If the exit status is not
0 on return then the variables and values
may not be correct.
-arch - Start MATLAB assuming architecture arch.
v=variant - Start the version of MATLAB found
in bin/glnxa64/variant instead of bin/glnxa64.
v=arch/variant - Start the version of MATLAB found
in bin/arch/variant instead of bin/glnxa64.
-c licensefile - Set location of the license file that MATLAB
should use. It can have the form port#host or
be a colon separated list of license files.
The LM_LICENSE_FILE and MLM_LICENSE_FILE
environment variables will be ignored.
-display Xdisplay - Send X commands to X server display, Xdisplay.
-nodisplay - Do not display any X commands. The MATLAB
desktop will not be started. However, unless
-nojvm is also provided the Java virtual machine
will be started.
-nosplash - Do not display the splash screen during startup.
-mwvisual visualid - The default X visual to use for figure windows.
-debug - Provide debugging information especially for X
based problems.
-desktop - Allow the MATLAB desktop to be started by a
process without a controlling terminal. This is
usually a required command line argument when
attempting to start MATLAB from a window manager
menu or desktop icon.
-nodesktop - Do not start the MATLAB desktop. Use the current
terminal for commands. The Java virtual machine
will be started.
-nojvm - Shut off all Java support by not starting the
Java virtual machine. In particular the MATLAB
desktop will not be started.
-jdb [port] - Enable remote Java debugging on port (default 4444)
-r MATLAB_command - Start MATLAB and execute the MATLAB_command.
-logfile log - Make a copy of any output to the command window
in file log. This includes all crash reports.
-Ddebugger [options] - Start debugger to debug MATLAB.*/
QProcess* p = new QProcess( this );
p->start( "%MATHLAB_EXE_FILE_FULL_PATH%", "%FILE_M_FULL_PATH%" );
so it will be like:
p->start( QString( "C:/Program Files/MatLab 9.0/matlab.exe" ),
QStringList() << QString( "-r D:/My files/matlab/file.m" )
<< QString( "-nosplash" ) );
Try this. It works.
QString program = "C:\\Program Files\\MATLAB\\R2017a\\bin\\matlab.exe";
myProcess->start(program, QStringList() << QString("-nodisplay")<< QString("-nodesktop")<< QString("-nosplash")<<QString("-r")<<QString("run('C:/Users/eleazar.balbon/Documents/MATLAB/Sample.slx');"));
myProcess->waitForFinished();
The answer below may not work beacuse QProcess added quotes to all parametrs in QStringList
You shuld try QProcess::setNativeArguments ( const QString & arguments )
If this also worn't work you can try QProcess::execute ( const QString & program ) [static]
QProcess::execute("My_programm.bin -arg1 val1 -arg2 val2");
I think this is the best way of running uncotrolled external processes.
If you create a QProcess instance and dont delete it manualy it well get you program running until of preces exits. Or if you app exits with help of kill or somethimg else you will have a qDebug issue of deleting of uncompleted proces(dont remeber exect string of this issue in qDebug). In different OS this may cause crush of your app(for example i have this problem on Windows XP)
It might be too late. But, for future references. This is what you should do.
In my script, I'm sending a path that is a variable in mine .m file called ae_run. This is how I have done it.
QProcess* p = new QProcess(NULL);
QString matlab_exe ="matlab /r -nosplash -nodesktop";
QString fileName_path=matlab_exe +" "+ "rec_path='"+path+"\';ae_run";
p->start(fileName_path);
qDebug()<<p->state()<<endl;
rec_path is the variable that I parse to my code, and the fileName is the path. At the end, when I run it. Looks like this.
"matlab /r -nosplash -nodesktop rec_path='D:\\robot_IMU_data\\file_data.txt';ae_run"
If you see, it is like running it from the command line

Resources