Giving file location from parent of the parent folder in C++ - 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
}

Related

QProcess input string with accents

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

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 QProcess sometimes works and sometimes does not work

I want to convert a ps file to pdf by ps2pdf and this codes in Qt:
QPixmap graphPng(filePath + "report/pictures/graph-000.png");
int graphPsWidth=graphPng.width();
int graphPsHeight=graphPng.height();
//convert "ps" file to "pdf" file
QProcess process;
QStringList arg;
arg<<"-dDEVICEWIDTHPOINTS=" + QString::number(graphPsWidth)<<"-dDEVICEHEIGHTPOINTS=" + QString::number(graphPsHeight)<<"export/report/pictures/graph-000.ps"<<"export/report/pictures/graph-000.pdf";
process.start("ps2pdf",arg);
//process.waitForStarted(-1);
process.waitForFinished(-1);
(I use a png file as the same dimensions of the ps file to get the dimensions and use it in creating pdf file)
I don't know why sometimes the pdf file is created and some times without any output message (process::readAllStandardError() and process::readAllStandardOutput()) there is no pdf file!
When the pdf file is not created if I run that immediately in terminal, the pdf file will be created!!!
What is the reason and how can I solve it?
It is always advisable to verify all the steps, so I share a more robust version of your code.
For example it is not necessary to use QPixmap, the correct thing is to use QImage. In addition, the path of the files is verified.
#include <QCoreApplication>
#include <QDir>
#include <QProcess>
#include <QImage>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QDir directory(QString("%1%2%3")
.arg(a.applicationDirPath())
.arg(QDir::separator())
.arg("export/report/pictures/"));
QString name = "graph-000";
QString png_path = directory.filePath(name + ".png");
QString ps_path = directory.filePath(name + ".ps");
// verify path
Q_ASSERT(QFileInfo(png_path).exists());
Q_ASSERT(QFileInfo(ps_path).exists());
QString pdf_path = directory.filePath(name+".pdf");
QImage img(png_path);
int graphPsWidth = img.width();
int graphPsHeight = img.height();
QProcess process;
QStringList arg;
arg << QString("-dDEVICEWIDTHPOINTS=%1").arg(graphPsWidth) <<
QString("-dDEVICEHEIGHTPOINTS=%1").arg(graphPsHeight) <<
ps_path << pdf_path;
process.start("ps2pdf",arg);
process.waitForFinished();
Q_ASSERT(QFileInfo(pdf_path).exists());
return 0;
}
I can solve the problem by handling the RAM, because if the ram exceed the specific limit (almost near the full capacity of the RAM), the QProcess can not be started. So every time it diagnoses the exceeded limit, the PDF file is not created and vice versa.

Can not read text file with Qt 5

I wrote a simple code to open plain text file with Qt 5's QFile as seen below;
// main.cpp
#include <iostream>
using std::endl;
using std::cout;
#include <QCoreApplication>
#include <QFile>
#include <QIODevice>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFile plainFile("plain.txt");
if(plainFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
cout << "File opened successfull" << endl;
plainFile.close();
}
else{
cout << "could not open file." << endl;
}
return a.exec();
}
The output when compiled and run is "could not open file".
What am I do wrong?
Probably because plain.txt does not exist in the current working directory or in the PATH. Make sure the file is in the working directory or pass the absolute path to QFile.
Also see what QFile::exists returns.
Wouter Huysentruit is right.
Remember, that, by default, when you running application from QtCreator working directory is, for example, C:\Projects\build-Test-Desktop_Qt_5_1_0_MinGW_32bit-Debug. But your .exe file lay in C:\Projects\build-Test-Desktop_Qt_5_1_0_MinGW_32bit-Debug\Debug.
When you run your .exe directly, then working directory will be that folder, where this file is layed now.
So, you can:
1.Pass absolute path.
2.Put file in current working directory (I suppose that it is best solution).
3.Just change relative path: QFile plainFile("debug/plain.txt");

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;
}