Read File Using Relative Path on Linux Qt - qt

Original one : QFile file("/home/casper/QuickRecorder/about_content.txt"); (Work)
I have tried :
"about_content.txt"
"/about_content.txt"
"~/about_content.txt"
"./about_content.txt"
"QuickRecorder/about_content.txt"
"/QuickRecorder/about_content.txt"
"~/QuickRecorder/about_content.txt"
"~/QuickRecorder/about_content.txt"
No one works.=[
My Questions
What path can I use?
If I register the file "about_content.txt" into Resource, how can I read it into text browser?
The following is the entire code :
About::About(QWidget *parent) :
QDialog(parent),
ui(new Ui::About)
{
ui->setupUi(this);
this->setFixedSize(this->width(),this->height());
QFile file("/home/casper/QuickRecorder/about_content.txt");
if ( !file.open(QIODevice::ReadOnly) )
QMessageBox::information(0, "Error", file.errorString());
QTextStream content(&file);
ui->aboutContentBrowser->setText(content.readAll());
}
Reference : QT C++ GUI Tutorial 27- How to read text file and display file to a textbrowser or textEdit
Thank you for your help.

If you place your file about_content.txt inside build directory you can use:
about_content.txt
./about_content.txt
If you must open file right from this path /home/casper/QuickRecorder/about_content.txt
Use absolute path as you wrote in question.
If you want use relative path
Take a look at differrence of relative path vs absolute path. So if you place your file for example to /home/casper/QuickRecorder/about_content.txt and you know exactly that your build lirectory is /home/casper/app-build -- you can use relative path ../QuickRecorder/about_content.txt
Take a look at QDir class. It already consists lots of useful methods.
If you want to place your file to resources
That procedure is pretty simple. Just add resource you your project and add file to your resource according to The Qt Resource System. For example, you can add your file about_content.txt to .qrc file and use it in your program this way: QFile file(":/about_content.txt");.

You can get the path of the user's home directory using the static function QDir::homePath().
QString homePath = QDir::homePath();
QFile file(homePath + "/QuickRecorder/about_content.txt");
...

Related

Is it possible to use system environment variables in Qt resource file?

I want to import some of resources from another project without copying into my project directory. Environment variable ANOTHER_PROJECT_DIR stores path to another project.
I've tried to do something like this:
<file>%ANOTHER_PROJECT_DIR%/file</file>
or this:
<file>$$(ANOTHER_PROJECT_DIR)/file</file>
in my qrc file.
So is it possible to use system environment variables in Qt resource file and how can I do it?
It would be great to find crossplatform solution
qrc resource file is a static binary resource link. You cannot do it dynamically. However, you can do something like this from your code
#include <QProcessEnvironment>
...
somefunc(){
QString env = qgetenv("SOME_VAR");
QString filepath = env + "/path/to/file";
...
}
Rcc does not support such functionality. You can use qmake's "substitutes" (still undocumented?) feature instead.
test.pro
myqrc.input = myqrc.in
myqrc.output = myqrc.qrc
QMAKE_SUBSTITUTES += myqrc
myqrc.in
<file>$$(ANOTHER_PROJECT_DIR)/file</file>
Basically, "substitutes" is a builtin preprocessor capable of evaluating/expanding "qmake"-expressions (plus !!IF / !!ELSE / !!ENDIF conditional).

CMake-qt: Including Autogened file from sibling Project. How to do it right?

commonLib is a collection of Files used for some other Targets declared in sibling folders which are then added to the parent CMakeLists.txt via add_subdirectory(). commonLib contains foo.h and foo.ui (which is translated to ui_foo.h by AUTOUIC)
otherLib includes foo.h from commonLib.
It feels like I am missing something obvious.
Is it necessary to use something like target_link_libraries?
Can I add the autogen folder of commonLib to the include folders of otherLib? (with target_include_directories(commonLib PRIVATE ${AUTOGEN_FOLDER_OF_otherLib}) )
How do I make sure commonLib is autogen-ed before otherLib?
Please let me know if there is information missing for understanding the problem.
I am using cmake-converter to convert existing .sln files to CMakeLists.txt.
I assumed finding success with using target properties like:
* AUTOGEN_TARGET_DEPENDS
* AUTOGEN_BUILD_DIR
but I failed.
commonLib contains following code:
find_package(Qt5 REQUIRED COMPONENTS Widgets)
set_target_properties(${PROJECT_NAME} PROPERTIES
AUTOUIC ON
)
otherLib contains following code:
add_dependencies(${PROJECT_NAME}
commonLib
)
I expected CMake to successfully generate the ui_foo.h from commonLib (which it actually does in the folder commonLib_autogen/include_) and then use ui_foo.h for compilation with otherLib.
Resulting Errormessage is:
d:\path\to\otherLib\../otherLib/foo.h(6): fatal error C1083: Cannot open include file: 'ui_foo.h': No such file or directory [D:\build_dir_of\otherLib\otherLib.vcxproj]
The Problem was the use of
# include "ui_foo.h"
in the header (foo.h). Moving the include to the foo.cpp file and forward declaring the Ui::FooBar like this:
namespace Ui { class FooBar; }
resolved it.

How to prevent Qt/cmake from adding carriage returns to resources on windows

I have a Qt program which was developed on Linux. In it are some user settings which are parsed from a config file. Of course, the users don't tend to have that config file during the first launch and we want things to work even if it isn't present, so a copy of the sensible defaults is stored in a resource text file, which is in the same format as the on-disk version would be.
I've run into an annoyance when running on windows...
The resources have had their "\n" line endings all converted to "\r\n" somewhere along the line! I'd really prefer to not have to alter the parsers to optionally accept more than one type of newline.
Is there a way to tell cmake to tell the Qt resource compiler to not do the conversion by passing a flag or similar?
EDIT: To clarify what's going on, I'll explain all of the little details of why I think qrc is adding the newlines...
First, I have a .qrc file which looks roughly like this:
<RCC>
<qresource prefix="/">
<file>res/DefaultSettings.txt</file>
</qresource>
</RCC>
It is added to the executable via cmake using code like this:
qt5_add_resources(QRC_SOURCES
resource.qrc
)
and
add_executable(my_project
resource.qrc
main.cpp
)
finally, it is being loaded with code like this:
QByteArray loadResource(const QString &resource) {
QResource res(resource);
if(!res.isValid()) {
qFatal("Failed to load internal resource");
}
// don't copy the data, if it's uncompressed, we can deal with it in place
auto defaults = QByteArray::fromRawData(reinterpret_cast<const char *>(res.data()), res.size());
if(res.isCompressed()) {
defaults = qUncompress(defaults);
}
// NOTE: at this point, using a debugger, I observe
// "\r\n" newlines in the defaults byte array
return defaults;
}
If by "resource" text file you mean a binary resource stored in the executable via qrc, then no: qrc will never alter the files - it doesn't discriminate between binary and text resources, it's all binary as far as it's concerned. Version control systems such as git may do that on checkin/checkout, though. You may also be reading the file using APIs that convert line endings. You'd ideally want to have a reproducer that outputs the file, and then another one that uses qrc to embed the file and then demonstrate the changed line endings.

setRootPath() in QT FIleSystemModel to a file

I'm building a simple file browser using QT, and I can't seem to get the setRootPath() of my model to be set to a file, rather than just a directory.
Ex:
setRootPath("/Users/Foo/Bar") works, but
setRootPath("/Users/Foo/Bar/readme.txt") simply sets the root path to "."
Not sure what I'm missing. Everything else within my application works fine.
You can do this:
QFileInfo m_FileInfo = QString("C:/Users/Foo/Bar/readme.txt");
setRootPath(m_FileInfo.absolutePath());
What we're doing is using QFileInfo to get the absolutePath() of the file. So it'll set the root path to C:/Users/Foo/Bar.

CMake : detect "Q_OBJECT" in a file and add it to a list of file to treat by MOC

Currently, I use a variable MYPROJECT_CURRENT_HEADERS in CMake to list all the headers. As I use Qt, my CMakeLists.txt contains :
QT4_WRAP_CPP(MYPROJECT_CURRENT_MOC ${MYPROJECT_CURRENT_HEADERS})
The problem is that all headers are treated by moc, even those that don't have a Q_OBJECT : so it generates many empty file.
Is there a solution to "grep"/detect if the file contains the string Q_OBJECT and if it's the case, add it to MYPROJECT_CURRENT_MOC ?
Thank you
There's a new target property in the soon-to-be-released CMake 2.8.6 called "AUTOMOC" that may help you out.
The test for this feature (which you can use as a guide or example) is found here:
http://cmake.org/gitweb?p=cmake.git;a=tree;f=Tests/QtAutomoc;h=7dae3b16a54dc0b2f63bbfa5c218c48b9bbf34a9;hb=nightly-master
The very simple CMakeLists.txt file is here:
http://cmake.org/gitweb?p=cmake.git;a=blob;f=Tests/QtAutomoc/CMakeLists.txt;h=4a5ff1099ba5249a6f22eea745a031b76e6f440f;hb=nightly-master
If you use this feature, cmake will scan the headers for Q_OBJECT and automatically run moc for you.
If you'd like to try it out before the final release of CMake 2.8.6, you can download one of the release candidates here:
http://cmake.org/files/v2.8/?C=M;O=D
The "-rc2" files do include the AUTOMOC property.
Here's the help text from running "cmake --help-property AUTOMOC":
cmake version 2.8.6-rc2
AUTOMOC
Should the target be processed with automoc (for Qt projects).
AUTOMOC is a boolean specifying whether CMake will handle the Qt moc
preprocessor automatically, i.e. without having to use the
QT4_WRAP_CPP() macro. Currently Qt4 is supported. When this property
is set to TRUE, CMake will scan the source files at build time and
invoke moc accordingly. If an #include statement like #include
"moc_foo.cpp" is found, the Q_OBJECT class declaration is expected in
the header, and moc is run on the header file. If an #include
statement like #include "foo.moc" is found, then a Q_OBJECT is
expected in the current source file and moc is run on the file itself.
Additionally, all header files are parsed for Q_OBJECT macros, and if
found, moc is also executed on those files. The resulting moc files,
which are not included as shown above in any of the source files are
included in a generated _automoc.cpp file, which is
compiled as part of the target.This property is initialized by the
value of the variable CMAKE_AUTOMOC if it is set when a target is
created.
I don't know a simple command to pick headers having a string from the list but you can always make a loop to find all such headers:
set(HEADERS_HAVING_Q_OBJECT)
foreach(header ${MYPROJECT_CURRENT_HEADERS})
file(STRINGS "${header}" lines REGEX "Q_OBJECT")
if(lines)
list(APPEND HEADERS_HAVING_Q_OBJECT "${header}")
endif()
endforeach()
But this solution has its own drawback: if you add a Q_OBJECT into one of the filtered out files you need to rerun cmake manually. Otherwise moc code for new file will not be automatically generated during the build process.

Resources