Qt print document to PDF - qt

I cannot print a QTextDocument to pdf. What I basically want is to print a table of data as a cell into a pdf file. The program runs on a virtual windows server. So I tried this:
Q_INVOKABLE QString ScriptCallback::htmlToPdf(const QString& sHtml) {
qDebug() << "Html To Pdf";
QPdfWriter pdfWriter("c:\\test.pdf");
pdfWriter.setPageSize(QPagedPaintDevice::A4);
pdfWriter.setPageMargins(QMargins(30, 30, 30, 30));
QTextDocument document;
document.setHtml(sHtml);
document.print(&pdfWriter);
QString s = "";
return s;
}
In fact instead of printing to the testfile I want to print to a QBuffer -> QByteArray. But this one above is for testing.
The problem is, I always get the error
QPainter::begin() failed
In Debug Mode the program continues, but in release the program even crashes trying to run the command
document.print(&pdfWriter);
I don't care about using QTextdocument or QPdfWriter. The only thing I am interessted in, is taking a bunch of data and somehow generate a table in a pdf file.
By the way the program runs as a console app (QCoreApplication). But I included gui and printsupport modules. So any alternatives are welcome as well.

Related

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.

Qt's QDir: File Names Dropping Non-Ascii Characters

I am having issues with QDir losing Non-Ascii characters from my file names.
I have files with names like testingöäüß.txt or exampleΦ.shp and when trying to use Qt utilities like QDir and QFile they simply show up as testing.txt and example.shp. Seems as though I cannot tell those classes what kind of encoding to use. I'm trying QDirIterator and the QDir function entryInfoList:
QDir someDir("/home/blah"); //contains testingöäüß.txt
QDirIterator dirIter(someDir.absolutePath(), QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files);
while(dirIter.hasNext())
{
QString fileName1 = QFile::decodeName(dirIter.next().toUtf8());
std::cout << "QDirIterator Name " << fileName1.toStdString().c_str() << std::endl;
}
QFileInfoList fileInfoList = someDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files);
foreach(QFileInfo fileInfo, fileInfoList)
{
QString fileName1 = QFile::decodeName(fileInfo.fileName().toUtf8());
std::cout << "entryInfoList Name " << fileName1.toStdString().c_str() << std::endl;
QString fileName2 = QFile::decodeName(fileInfo.absoluteFilePath().toUtf8());
std::cout << "entryInfoList Name2 " << fileName2.toStdString().c_str() << std::endl;
QString fileName3 = QString::fromUtf8(dirIter.fileInfo().absoluteFilePath().toStdString().c_str());
std::cout << "entryInfoList Name3 " << fileName3.toStdString().c_str() << std::endl;
}
Every one of those prints will lack the non-ascii characters. Seems like as soon as you try to grab the file names to loop over they will be ascii only. Anyone have any ideas on this? Or can Qt simply not handle this? Thanks!
I know this is an old question, but I just ran into the same problem. The same exact Qt code would work fine on my development VM, but when I transferred it to an embedded Linux system (running on x86 so literally the same executable) my directory names just silently got their non-ASCII characters dropped.
Turned out the QTextCodec::codecForLocale on my dev VM was set to UTF-8, and on the embedded box it was System. If I manually changed the locale to UTF-8 before doing any filesystem operations (by calling QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"))), everything started working fine.
So why was this happening in the first place? My suspicion is that in the process of slimming down the embedded system's root filesystem I might have accidentally deleted some locale-related files that Qt was using to try to auto-detect the locale. When it couldn't determine it was on UTF-8, it fell back to System, which for whatever reason is broken (maybe for the same reason it couldn't detect UTF-8 in the first place).
I need to eventually fix whatever is causing it to not auto-detect, but in the short-term just manually setting a UTF-8 locale should work if you are experiencing this same issue.
Note that this has nothing to do with whether the console can display UTF-8, or anything to do with manual conversion of UTF-16 to UTF-8! So Felix's answer to this question is not correct, at least for this particular issue. To completely remove the capability of the console from the equation, I was also simply printing the number of UTF-16 characters in the string, and every non-ASCII character actually made the returned path and filename strings from QDir::entryInfoList have one less UTF-16 character. Additionally, the dead giveaway is that the characters were simply stripped out, not just replaced with garbage or question marks or whatever.
Qt can handle filenames with special characters. You just make them disappear somewhere in that string conversion stuff. (Which is completly unnecessary) Try it this way:
#include <QDebug>
//...
QFileInfoList fileInfoList = someDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files);
foreach(QFileInfo fileInfo, fileInfoList)
{
qDebug() << fileInfo.fileName();//uses qdebug
std::cout << fileInfo.fileName().toStdWString() << std::endl;//uses a 16Bit string on normal cout
}
If you still don't see them, it's because your console settings do not allow to display them. Try to write them to a file or display them in a gui - or simply try to open a file with that name, it will work.

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