QProcess input string with accents - c++

I have two programs each with QProcess and I have a different behavior concerning the QProcess input with accentuated characters
(more precisely I create a Qprocess to execute a dos copy command and the path takes accent).
The environnement of execution and development is Windows 10.
The first program is a simple prototype that I made to test if my code can work correctly.
Here is the prototype code I have, in which the copy works correctly, integrated in a simple main() function.
The code is supposed to copy a file named sfx.exe into a path with accent F:\path_accentué and it indeed does the copy correctly.
#include <QCoreApplication>
#include <Qdebug>
#include <QObject>
#include <QProcess>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QProcess* processus = new QProcess();
QStringList args;
QString path("F:\\path_accentué");
args << "/C" << "copy" << "E:\\test\\sfx.exe" << path;
processus->start("cmd.exe", args);
if (!processus->waitForStarted())
{
qDebug() << "Could not launch the process";
}
//processus->write(s.c_str());
if (!processus->waitForFinished(-1))
{
qDebug() << "Finished";
}
delete processus;
return app.exec();
}
However, when I integrate (literally copies and pasted without changing) this prototype within a bigger code project, my instance of QProcess does not recognize the accentuated path, as if accents are no more supported.
This is the part that I copy/paste in the bigger project and which I now execute via a button click in QT.
And this time, the QProcess doesn't recognize the accentuated path (Instead it creates a file with name like this path_accentu�)
QProcess* processus = new QProcess();
QStringList args;
QString path("F:\\path_accentué");
args << "/C" << "copy" << "E:\\test\\sfx.exe" << path; processus->start("cmd.exe", args);
if (!processus->waitForStarted())
{
qDebug() << "Could not launch the process";
}
//processus->write(s.c_str());
if (!processus->waitForFinished(-1))
{
qDebug() << "Finished";
}
I do not find in the documentation a way to force the QProcess to recognize accentuated inputs.
I would like to understand why the QProcess instance behaves differently when integrated within my bigger project.
What may impact the behavior of the QProcess and leads it to treat differently the input in the second case?
Note:
The QProcess is needed for more things but not only for the copy (such as getting feedback and percentage of operations). The copy is only to isolate the problem. In reality, I do much more things.

I tried to recreate your behaviour with Qt 5.15 and could create a file with accent with
start("cmd",{args...})
start("cmd /c args...")
setNativeArguments("/c args...") + start("cmd")
Last one is recommended for "cmd" calls, see the remarks here:
https://doc.qt.io/qt-5/qprocess.html#start
The only thing, which did not work, because it deadlocks was
setArguments({args...}) + start("cmd")
Demo here:
https://gist.github.com/elsamuko/59f110cf3a678beae9db27860f6305c9

Related

In qt QFileDialog setsuffix is not working in linux, how to solve?

I am working on a Save dialog for my qt app. Everything works, but if no file extension is added behind the filename, it won't automatically be saved with the file extension although the filter is selected.
I know i need to set a defaultsuffix option, but even if i do, then it still won't add the extension automatically if its not given.
I found several other similar questions, where i read it works in windows but it could fail on linux distro's. If so, is there a simple workaround? Because right now, i don't have a working solution...
void MainWindow::on_actionSave_Chart_As_triggered()
{
QFileDialog *fileDialog = new QFileDialog;
fileDialog->setDefaultSuffix("files (*);;AstroQt aqt (*.aqt)");
QString fileName = fileDialog->getSaveFileName(this, "Save Radix", ui->label_2->text() +".aqt", "AstroQT(*.aqt)");
qDebug() << " save file name " << fileName << endl;
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString());
return;
}
setWindowTitle(fileName);
QTextStream out(&file);
QString text = "text that will be saved...";
out << text;
file.close();
}
Edit: After trying multiple solutions, none seemed to work. But it should have, i guess. Why else is there a aftersuffix function...? For now i solved it doing it manually. But i'm not happy with it, there should be a better solution/explanation.
// add extension if none is found.
if(!fileName.endsWith(".aqt"))
fileName.append(".aqt");
If you use the static method getSaveFileName things seems to work correctly:
#include <QFileDialog>
#include <QApplication>
#include <QDebug>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QString fileName = QFileDialog::getSaveFileName(
nullptr, QObject::tr("Save File"),
"teste.aqt",
QObject::tr("AstroQt (*.aqt)"));
qDebug() << " save file name " << fileName << endl;
return app.exec();
}
I get the correct file name with the extension, if I type something without the extension.
If you take a look at QFileDialog documentation, you will see that getSaveFileName() is an static function. Because of this, there is no way for this method to access a member of the instance of the class that makes use of setDefaultSuffix(). So whatever you set in fileDialog->setDefaultSuffix(...) has nothing to do with what the getSaveFileName() function does.
In ordertTo make it work, you have to run the dialog directly from the instance. You should do something like this:
QFileDialog fileDialog(this, "Choose file to save");
fileDialog.setDefaultSuffix("json");
fileDialog.setNameFilter("json-files (*.json)");
fileDialog.exec();
QFile f(fileDialog.selectedFiles().first());
QFileInfo fileInfo(f);
QString FILE_NAME(fileInfo.fileName());

Qt Start process in interactive shell

I've created two programs in Qt.
Program A - Console project with interactions in shell
Program B - GUI project
Now I want to start Program A from Program B. For that purpose I tried many things and ended with:
QProcess *process = new QProcess(this);
QString command = "cmd.exe";
QStringList arguments;
arguments << "/C" << settings.getPath().replace("/","\\");
process->start(command, arguments);
This starts a process, but doesn't open a cmd in Windows.
I also tried out:
QProcess *process = new QProcess(this);
QString command = "start";
QStringList arguments;
arguments << "cmd.exe" << "/C" << settings.getPath().replace("/","\\");
process->start(command, arguments);
It looks like the process is started in the background. In that case I am unable to use my command line program.
How can I start an interactive cmd?
Which devenv are you using for each of the projects?
Depending on the dev-env you are using, you could try setting up your console project to run in a cmd.exe which is not in the background (you would need to look at the manual from your dev-env in this case)
Other thing:
Can you start your (compiled) console project via
system("projecta.exe"); ?
from project b?
If you are using Visual Studio compiler, take a look at this : QProcess with 'cmd' command does not result in command-line window
Which uses following code (note the CREATE_NEW_CONSOLE flag):
#include <QProcess>
#include <QString>
#include <QStringList>
#include "Windows.h"
class QDetachableProcess
: public QProcess {
public:
QDetachableProcess(QObject *parent = 0)
: QProcess(parent) {
}
void detach() {
waitForStarted();
setProcessState(QProcess::NotRunning);
}
};
int main(int argc, char *argv[]) {
QDetachableProcess process;
QString program = "cmd.exe";
QStringList arguments = QStringList() << "/K" << "python.exe";
process.setCreateProcessArgumentsModifier(
[](QProcess::CreateProcessArguments *args) {
args->flags |= CREATE_NEW_CONSOLE;
args->startupInfo->dwFlags &=~ STARTF_USESTDHANDLES;
});
process.start(program, arguments);
process.detach();
return 0;
}

Giving file location from parent of the parent folder in C++

I'm a newbie to C++ and I know its a basic question but couldnt find a satisfactory answer from anywhere so I'll read the file location from parent folder but I dont know how.
Executed file is in
C:\A\B\C\D\Test.exe
The file I need to open is in
C:\A\E\F\Open.exe
But I want to do this dynamically. So config of the text.exe should give a path to A then into E and F. Because this program can be located anywhere and I dont want to give a path starting from C:\
Any help would be appriciated. I'm using QT too if it helps. Thanks
EDIT :
I am looking for something like
file.pdf
in html
EDIT 2:
This is my code but its not working
QSettings setting("config.ini",QSettings::IniFormat);
QString prolocation = setting.value("ProDir","../../../E/F/pro.exe").toString();
QProcess process;
process.start(prolocation);
And config file is:
(bla bla other settings)
ProDir=../../../E/F/pro.exe
Here is a working Qt solution
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <cassert>
int main(int argc, char **argv)
{
// Init + get app path
//
QCoreApplication app(argc, argv);
QString appPath = app.applicationDirPath();
qInfo() << appPath;
// App path manips
//
QDir dir(appPath);
// Goes up two times... your C\D dirs
bool ok;
ok = dir.cdUp();
assert(ok);
ok = dir.cdUp();
assert(ok);
qInfo() << dir.path();
// Goes to picaud/Temp again
// -> in your case /E/F dirs
ok = dir.cd("picaud");
assert(ok);
ok = dir.cd("Temp");
assert(ok);
qInfo() << dir.path();
}
which prints:
"/home/picaud/Temp"
"/home"
"/home/picaud/Temp"
In your case, like you already use Qt I think this is the simplest approach. You can still use the C++ standard filesystem but this requires either to use C++17 or to use the Boost initial implementation.
You also can use QUrl::resolved
Calling resolved() with ".." returns a QUrl whose directory is one level higher than the original. Similarly, calling resolved() with "../.." removes two levels from the path. If relative is "/", the path becomes "/".
QUrl oBase("file:///home/A/B/");
QString oResolvedFile = oBase.resolved(QUrl("../../other/file.pdf")).toString();
// Test
QFile oLocalFile(QUrl(oResolvedFile).toLocalFile());
if (oLocalFile.exists())
{
// your file
}

Newbie problem with QT C++ - Qimage dont work?

I am trying to do console application to read pixels from image:
#include <QtCore/QCoreApplication>
#include <QtGui/QImage>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QImage *img = new QImage("adadad.jpg");
//std::cout << "Type filename:" << std::endl;
img->isNull();
return a.exec();
}
That doesn't work I got: (IT doesn't compile, but anyway file isn't exist yet...)
File not found: tmp/obj/debug_shared/main.o:: In function `main':
What is going on? Is it impossible to use Qimage with console app?!
EDIT:
screen
It is possible to use QImage in a console application, you must make sure that QtGui is configured though. If you chose a console app, your .pro file might contain something like
CONFIG += console
QT -= gui
If that's the case, remove the QT -= gui line.
QImage("adadad.jpg");
Will probably look for a file called adadad.jpg on the current working directory for your application. Check if that file is present. Otherwise, use a fully qualified path.
img->isNull() doesn't do anything on it's own, try this instead:
if(img->isNull())
std::cout << "Image isNull!\n";
else
std::cout << "Image loaded\n";
My guess is that the local directory of the executable is not the same as the location of that image, so Qt can't find the file. Try specifying the complete path.
EDIT: Ahh... didn't realize it was a compilation problem. That looks suspiciously like a moc issue. What build system are you using? and can you confirm that the moc step is executing?
This modification of your code will compile and run as expected if there is a valid image file in the current working directory when you run the app. It will display Image loaded
#include <QtGui/QImage>
#include <iostream>
int main(int argc, char *argv[])
{
QImage *img = new QImage("adadad.jpg");
if(img->isNull())
std::cout << "Image is null";
else
std::cout << "Image loaded";
return 0;
}
You do not need to create an instance of QCoreApplication unless you have subclassed it and put your program code in that subclass.
Update:
Your program does not exit so you are probably getting that compile error because it can't replace the executable because it is still running (and locked). The file locking is more likely to be an issue under Windows.
An important note when you are loading a file using directly "adadad.jpg" in your code. Even if you put the file inside the debug/release folder, QImage will always be null if loaded this way.
I run into this problem yesterday and I fixed it by using the Qt library to get the full path: QCoreApplication::applicationDirPath().
There is two way to achieve that, first one is when you create the img object.
QImage img( QCoreApplication::applicationDirPath() + "adadad.jpg");
if( img.isNull())
{
qDebug() << "Loading Error - file: adadad.jpg.";
return false;
}
or using the load function
QImage img;
if( !img.load(QCoreApplication::applicationDirPath() + "adadad.jpg"))
{
qDebug() << "Loading Error - file: adadad.jpg.";
return false;
}

Console output in a Qt GUI app?

I have a Qt GUI application running on Windows that allows command-line options to be passed and under some circumstances I want to output a message to the console and then quit, for example:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
if (someCommandLineParam)
{
std::cout << "Hello, world!";
return 0;
}
MainWindow w;
w.show();
return a.exec();
}
However, the console messages do not appear when I run the app from a command-prompt. Does anyone know how I can get this to work?
Windows does not really support dual mode applications.
To see console output you need to create a console application
CONFIG += console
However, if you double click on the program to start the GUI mode version then you will get a console window appearing, which is probably not what you want. To prevent the console window appearing you have to create a GUI mode application in which case you get no output in the console.
One idea may be to create a second small application which is a console application and provides the output. This can call the second one to do the work.
Or you could put all the functionality in a DLL then create two versions of the .exe file which have very simple main functions which call into the DLL. One is for the GUI and one is for the console.
Add:
#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
}
#endif
at the top of main(). This will enable output to the console only if the program is started in a console, and won't pop up a console window in other situations. If you want to create a console window to display messages when you run the app outside a console you can change the condition to:
if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole())
void Console()
{
AllocConsole();
FILE *pFileCon = NULL;
pFileCon = freopen("CONOUT$", "w", stdout);
COORD coordInfo;
coordInfo.X = 130;
coordInfo.Y = 9000;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coordInfo);
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE),ENABLE_QUICK_EDIT_MODE| ENABLE_EXTENDED_FLAGS);
}
int main(int argc, char *argv[])
{
Console();
std::cout<<"start##";
qDebug()<<"start!";
You can't use std::cout as others have said,my way is perfect even for some code can't include "qdebug" !
So many answers to this topic. 0.0
So I tried it with Qt5.x from Win7 to Win10. It took me some hours to have a good working solution which doesn't produce any problems somewhere in the chain:
#include "mainwindow.h"
#include <QApplication>
#include <windows.h>
#include <stdio.h>
#include <iostream>
//
// Add to project file:
// CONFIG += console
//
int main( int argc, char *argv[] )
{
if( argc < 2 )
{
#if defined( Q_OS_WIN )
::ShowWindow( ::GetConsoleWindow(), SW_HIDE ); //hide console window
#endif
QApplication a( argc, argv );
MainWindow *w = new MainWindow;
w->show();
int e = a.exec();
delete w; //needed to execute deconstructor
exit( e ); //needed to exit the hidden console
return e;
}
else
{
QCoreApplication a( argc, argv );
std::string g;
std::cout << "Enter name: ";
std::cin >> g;
std::cout << "Name is: " << g << std::endl;
exit( 0 );
return a.exec();
}
}
I tried it also without the "CONFIG += console", but then you need to redirect the streams and create the console on your own:
#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole()){
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
freopen("CONIN$", "r", stdin);
}
#endif
BUT this only works if you start it through a debugger, otherwise all inputs are directed towards the system too. Means, if you type a name via std::cin the system tries to execute the name as a command. (very strange)
Two other warnings to this attempt would be, that you can't use ::FreeConsole() it won't close it and if you start it through a console the app won't close.
Last there is a Qt help section in QApplication to this topic. I tried the example there with an application and it doesn't work for the GUI, it stucked somewhere in an endless loop and the GUI won't be rendered or it simply crashes:
QCoreApplication* createApplication(int &argc, char *argv[])
{
for (int i = 1; i < argc; ++i)
if (!qstrcmp(argv[i], "-no-gui"))
return new QCoreApplication(argc, argv);
return new QApplication(argc, argv);
}
int main(int argc, char* argv[])
{
QScopedPointer<QCoreApplication> app(createApplication(argc, argv));
if (qobject_cast<QApplication *>(app.data())) {
// start GUI version...
} else {
// start non-GUI version...
}
return app->exec();
}
So if you are using Windows and Qt simply use the console option, hide the console if you need the GUI and close it via exit.
No way to output a message to console when using QT += gui.
fprintf(stderr, ...) also can't print output.
Use QMessageBox instead to show the message.
Oh you can Output a message when using QT += gui and CONFIG += console.
You need printf("foo bar") but cout << "foo bar" doesn't works
Something you may want to investigate, at least for windows, is the AllocConsole() function in the windows api. It calls GetStdHandle a few times to redirect stdout, stderr, etc. (A quick test shows this doesn't entirely do what we want it to do. You do get a console window opened alongside your other Qt stuff, but you can't output to it. Presumably, because the console window is open, there is some way to access it, get a handle to it, or access and manipulate it somehow. Here's the MSDN documentation for those interested in figuring this out:
AllocConsole():
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681944%28v=vs.85%29.aspx
GetStdHandle(...):
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
(I'd add this as a comment, but the rules prevent me from doing so...)
I used this header below for my projects. Hope it helps.
#ifndef __DEBUG__H
#define __DEBUG__H
#include <QtGui>
static void myMessageOutput(bool debug, QtMsgType type, const QString & msg) {
if (!debug) return;
QDateTime dateTime = QDateTime::currentDateTime();
QString dateString = dateTime.toString("yyyy.MM.dd hh:mm:ss:zzz");
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s\n", msg.toAscii().data());
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s\n", msg.toAscii().data());
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s\n", msg.toAscii().data());
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s\n", msg.toAscii().data());
abort();
}
}
#endif
PS: you could add dateString to output if you want in future.
First of all, why would you need to output to console in a release mode build? Nobody will think to look there when there's a gui...
Second, qDebug is fancy :)
Third, you can try adding console to your .pro's CONFIG, it might work.
In your .pro add
CONFIG += console
It may have been an oversight of other answers, or perhaps it is a requirement of the user to indeed need console output, but the obvious answer to me is to create a secondary window that can be shown or hidden (with a checkbox or button) that shows all messages by appending lines of text to a text box widget and use that as a console?
The benefits of such a solution are:
A simple solution (providing all it displays is a simple log).
The ability to dock the 'console' widget onto the main application window. (In Qt, anyhow).
The ability to create many consoles (if more than 1 thread, etc).
A pretty easy change from local console output to sending log over network to a client.
Hope this gives you food for thought, although I am not in any way yet qualified to postulate on how you should do this, I can imagine it is something very achievable by any one of us with a little searching / reading!
Make sure Qt5Core.dll is in the same directory with your application executable.
I had a similar issue in Qt5 with a console application:
if I start the application from Qt Creator, the output text is visible,
if I open cmd.exe and start the same application there, no output is visible.
Very strange!
I solved it by copying Qt5Core.dll to the directory with the application executable.
Here is my tiny console application:
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
int x=343;
QString str("Hello World");
qDebug()<< str << x<<"lalalaa";
QTextStream out(stdout);
out << "aldfjals alsdfajs...";
}
I also played with this, discovering that redirecting output worked, but I never saw output to the console window, which is present for every windows application. This is my solution so far, until I find a Qt replacement for ShowWindow and GetConsoleWindow.
Run this from a command prompt without parameters - get the window. Run from command prompt with parameters (eg. cmd aaa bbb ccc) - you get the text output on the command prompt window - just as you would expect for any Windows console app.
Please excuse the lame example - it represents about 30 minutes of tinkering.
#include "mainwindow.h"
#include <QTextStream>
#include <QCoreApplication>
#include <QApplication>
#include <QWidget>
#include <windows.h>
QT_USE_NAMESPACE
int main(int argc, char *argv[])
{
if (argc > 1) {
// User has specified command-line arguments
QCoreApplication a(argc, argv);
QTextStream out(stdout);
int i;
ShowWindow (GetConsoleWindow(),SW_NORMAL);
for (i=1; i<argc; i++)
out << i << ':' << argv [i] << endl;
out << endl << "Hello, World" << endl;
out << "Application Directory Path:" << a.applicationDirPath() << endl;
out << "Application File Path:" << a.applicationFilePath() << endl;
MessageBox (0,(LPCWSTR)"Continue?",(LPCWSTR)"Silly Question",MB_YESNO);
return 0;
} else {
QApplication a(argc, argv);
MainWindow w;
w.setWindowTitle("Simple example");
w.show();
return a.exec();
}
}
After a rather long struggle with exactly the same problem I found that simply
CONFIG += console
really does the trick. It won't work until you explicitly tell QtCreator to execute qmake on the project (right click on project) AND change something inside the source file, then rebuild. Otherwise compilation is skipped and you still won't see the output on the command line.
Now my program works in both GUI and cmd line mode.
One solution is to run powershell and redirect the output to whatever stream you want.
Below is an example of running powershell from cmd.exe and redirecting my_exec.exe output to both the console and an output.txt file:
powershell ".\my_exec.exe | tee output.txt"
An example (from cmd.exe) which holds open stdout/stderr and doesn't require tee or a temporary file:
my_exec.exe > NUL 2>&1
Easy
Step1: Create new project. Go File->New File or Project --> Other Project -->Empty Project
Step2: Use the below code.
In .pro file
QT +=widgets
CONFIG += console
TARGET = minimal
SOURCES += \ main.cpp
Step3: Create main.cpp and copy the below code.
#include <QApplication>
#include <QtCore>
using namespace std;
QTextStream in(stdin);
QTextStream out(stdout);
int main(int argc, char *argv[]){
QApplication app(argc,argv);
qDebug() << "Please enter some text over here: " << endl;
out.flush();
QString input;
input = in.readLine();
out << "The input is " << input << endl;
return app.exec();
}
I created necessary objects in the code for your understanding.
Just Run It
If you want your program to get multiple inputs with some conditions. Then past the below code in Main.cpp
#include <QApplication>
#include <QtCore>
using namespace std;
QTextStream in(stdin);
QTextStream out(stdout);
int main(int argc, char *argv[]){
QApplication app(argc,argv);
qDebug() << "Please enter some text over here: " << endl;
out.flush();
QString input;
do{
input = in.readLine();
if(input.size()==6){
out << "The input is " << input << endl;
}
else
{
qDebug("Not the exact input man");
}
}while(!input.size()==0);
qDebug(" WE ARE AT THE END");
// endif
return app.exec();
} // end main
Hope it educates you.
Good day,
First of all you can try flushing the buffer
std::cout << "Hello, world!"<<std::endl;
For more Qt based logging you can try using qDebug.