I am trying to learn how to display a QFileSystemModel as TreeView in QML, following this example: https://doc.qt.io/qt-5.10/qtquickcontrols-filesystembrowser-example.html
I copied the non-main-function-code from the examples main.cpp into a header file, and try to use it in my main.cpp as follows:
QQmlApplicationEngine engine;
qmlRegisterUncreatableType<DisplayFileSystemModel>("myfile", 1, 0,
"FileSystemModel", "Cannot create a FileSystemModel instance.");
QFileSystemModel *fsm = new DisplayFileSystemModel(&engine);
cout << "current path: "<< QDir::currentPath().toStdString() << endl;
cout << "home path: "<< QDir::homePath().toStdString() << endl;
//fsm->setRootPath(QDir::currentPath());
fsm->setRootPath(QDir::homePath());
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
However, I experience the following issue: If I do fsm->setRootPath(QDir::homePath()) the app crashs on startup, if I use the currentPath() instead it is working fine. The output of the cout for the paths is fine for both. This happens regardless of whether I display anything in my qml files. What is the reason for the crash?
Edit: I realize now that the problem is related to the fact, that I am using a QGuiApplication. If I use a QApplication also homePath is working. Still, what is the reason for this behaviour, as the path is correctly retrieved in the cout?
One issue is that QFileSystemModel requires a QApplication to run.. it says so in the detailed description.
Note: QFileSystemModel requires an instance of QApplication.
The other reason that it could fail is because QFileSystemModel creates a QFileSystemWatcher for each directory in the tree. QFileSystemWatcher can only have a maximum of so many instances on your machine under certain operating systems. This is due to RAM limitations as well as open file descriptor limits. Every operating system is different, but if you have more files than your machine is able to watch concurrently, it will crash.
Specifically from the Documentation:
On systems running a Linux kernel without inotify support, file
systems that contain watched paths cannot be unmounted. The act of
monitoring files and directories for modifications consumes system
resources. This implies there is a limit to the number of files and
directories your process can monitor simultaneously. On all BSD
variants, for example, an open file descriptor is required for each
monitored file. Some system limits the number of open file descriptors
to 256 by default. This means that addPath() and addPaths() will fail
if your process tries to add more than 256 files or directories to the
file system monitor. Also note that your process may have other file
descriptors open in addition to the ones for files being monitored,
and these other open descriptors also count in the total. macOS uses a
different backend and does not suffer from this issue.
Related
When running my Qt5 application on linux, I don't see any output from qDebug, qWarning, qCritical or qFatal. I know that I can use qInstallMsgHandler to install a message handler and see them, but this is rather heavyweight.
I just want to check the qWarning log to see if there is any signal that mis-connected. Is there a way to look at this log? A special command-line option, an environment variable?
I think I remember that in the past, everything was printed to stderr, perhaps that's a Qt5 change?
Please do not make the mistake of assuming that qDebug, qWarning, qCritical and qFatal always log on standard error. That's absolutely not the case.
The actual destination varies depending on the Qt configuration and the targeting OS. Plus, 5.4 and then 5.11 introduced some behavioural changes. See here and here for discussions.
TL;DR:
On Qt >= 5.11
If the process' stderr has a console attached, that's where the debug log will go.
If you want to always log on stderr, set QT_FORCE_STDERR_LOGGING to 1.
In alternative, set QT_ASSUME_STDERR_HAS_CONSOLE to 1. I suspect this one is meant to be used by a parent process that reads a child's stderr and shows it to the user somehow.
QT_LOGGING_TO_CONSOLE to 1 still works, but Qt will complain.
On Qt >= 5.4 and < 5.11
If you want to always log on stderr, set the QT_LOGGING_TO_CONSOLE environment variable to 1.
If you do not want to log on stderr, the QT_LOGGING_TO_CONSOLE environment variable to 0 (this will force logging through the native system logger).
If the QT_LOGGING_TO_CONSOLE environment variable is not set, then whether logging to the console or not depends on whether the application is running in a TTY (on UNIX) or whether there's a console window (on Windows).
On Qt < 5.4, the situation is more confusing.
If Qt has been built with support for a specific logging framework (e.g. SLOG2, journald, Android log, etc.) then logging always goes to that framework
Otherwise on UNIX it goes to stderr
Otherwise on Windows OutputDebugString or stderr is used depending whether the app is a console app.
The problem with the pre-5.4 approach was that, f.i., under Unix IDEs would not capture an application's debug output if Qt had been built with journald support. That's because the output went to journald, not to the IDE. In 5.4 the approach has been made more flexible and uniform across OSes.
If you happen to run Arch Linux, which compiles Qt with the -journald option, all debug output is per default directed to the systemd journal (display with journalctl).
You can override this behaviour by defining QT_LOGGING_TO_CONSOLE=1 as an environment variable.
They are still printed to standard error.
If you launch the application from the command line, it is usually printed there, or if using Qt Creator, it's displayed in the Application Output window.
If you are using visual studio, qDebug etc are printed to the output window in the IDE.
I use QSettings to save and load parameters to/from an ini file using Linux:
write:
QSettings settings("setup.ini", QSettings::IniFormat);
settings.beginGroup("Setup_Parameter");
settings.setValue("Parameter1",parameter1_value);
settings.sync();
settings.endGroup();
read:
QSettings settings("setup.ini", QSettings::IniFormat);
settings.beginGroup("Setup_Parameter");
parameter1_value = settings.value("Parameter1","0").toInt();
settings.endGroup();
The setup.ini works fine, while the system is on.
If i reboot my system by switching power off and on again, the setup.ini file gets completely empty sometimes. I would say in 3 out of 5 trys.
I already tryed saving the file in application and root/Settings path.
As well as copying the file after writing it, but then also the copy is empty after power off and on.
Why does the setup.ini File looses its content? It needs to keep the parameters while restart.
A sync() was required after the write function:
QSettings settings("setup.ini", QSettings::IniFormat);
settings.beginGroup("Setup_Parameter");
settings.setValue("Parameter1",parameter1_value);
settings.endGroup();
settings.sync();
sync();
I am experiencing the same problem. My QSettings file gets wiped out sometimes after a power reset. The file remains, but it is zero bytes in size. The QT application is running on Debian Squeeze on an ARM processor. The filesystem, OS, and application are all located on a 4G SD Card.
I've modified the application to call the sync function after any change to the Settings file. But we had a power reset last night and one of the units (we have about 60 running) lost its settings. We're running QTEmbedded-4.8.2, and I am at a loss how to fix this.
We have fixed the same problem calling 'sync' linux command after the 'sync' function of QSettings.
I'm using Ubuntu and Qt Creator 4
I have a .cpp program in the executable form (say abc.out) that I wish to run when I press a button. It contains a number of cin and cout, so I want it to run on a "terminal" (on Ubuntu) so that I am able to input and output values to it. How can I do that?
I've tried system() and
also,
QProcess p1;
p1.start(./abc.out);
Using QProcess, my executable runs but stops at the first cout. It runs on the application output screen in Qt Creator and not on terminal.
For example:
I see on application output:
enter name:
When I type the value and press enter here, it doesn't accept the value, but moves to the next line and allows me to type further.
I want to run this abc.out file on the terminal. Any ideas would be really helpful.
Do you mean Qt Creator 2.4? In any case, on the Projects tab, you should find the Run settings section and from there you can find a "Run in terminal" checkbox. You could also use a Custom Executable option and type there: gnome-terminal --command ./abc.out The exact details can vary a bit as I'm using Qt Creator 2.5.
This should work when launching from Qt Creator, but when you use your app outside the IDE, you need to launch it from terminal and not by double clicking the executable. To fix this, I can think of two ways:
Launch a terminal window from QtGui (something like QProcess::execute("gnome-terminal --command ./abc.out"); ), though the problem is different systems have different terminal names.
Provide a Qt input/text box yourself as part of your GUI which then forwards the user input to the executable (something like myqprocess.write(input_asked_from_user_by_QtGui); ). Here you probably need to know what information to ask the user beforehand. If you want to display the cout output of the started process, you can use the read method and friends of the QProcess.
From your question I assume that you are writing an application that launches other applications using QProcess. Thats fine, but if your subprocess is waiting for data from the standard input it will wait forever since you did not provide any data. The stdin of your parent application cannot be automatically guided to the subprocess. Imagine you are starting two processes from your main app. To which child process should the input go?
If you want to communicate with child processes, you must use the QIODevice methods of QProcess and send/read data from/to that application.
The only sensible solution is to launch the target application in a terminal. Whether your own code provides the terminal window or you reuse an existing terminal application is up to you.
I am working on an application targeted to Mac OSX 10.6+ using Qt 4.7.4
I have a folder with as much as 1000 files + and some or many or even all of these files may be renamed or moved or deleted, so I want to report to my application if:
File is renamed (report original and renamed filename)
Folder renamed (report original and renamed folder name)
File/folder is deleted (just report it as deleted)/moved (report the moved location)
PROBLEM: is the underlying system may (its MAY) only allow 256 descriptors to be monitored so at most 256 files! How can I over come this?
Note: used QFileSystemWatcher interface (it has the above stated problem)
ALSO : How to handle in case of version lower than OSX 10.5
Do mention how do i get renamed filename/foldername
From the QFileSystemWatcher docs:
On Mac OS X 10.4 and all BSD variants, for example, an open file descriptor is required for each monitored file. Some system limits the number of open file descriptors to 256 by default. This means that addPath() and addPaths() will fail if your process tries to add more than 256 files or directories to the file system monitor. Also note that your process may have other file descriptors open in addition to the ones for files being monitored, and these other open descriptors also count in the total. Mac OS X 10.5 and up use a different backend and do not suffer from this issue.
So you should not need to worry about this at all in your case.
QFileSystemWatcher doesn't provide the information you requested in your edit. It will emit signals when one of the paths it monitors changes, but in case of a rename, you won't get the new name. It's intended more for things like file manager programs that will just update/reload their current view on receipt of such events.
If you need more information than that, you'll need to use OS specific APIs. You can look at the code Qt uses for different platforms in the Qt source. It's in src/core/io/qfilsystemwatcher_*.[h|cpp].
For Mac OS X 10.5 or greater, the underlying API used is the FSEvents API. You can read in the Technology Overview page:
The important point to take away is that the granularity of notifications is at a directory level. It tells you only that something in the directory has changed, but does not tell you what changed.
So that OS-level API doesn't provide what you want either directly.
For older versions of Mac OS X and FreeBSD, Qt uses the kqueue API, with the EVFILT_VNODE event filter. That API doesn't provide the new name of a renamed file either.
In short, either you'll need to code something yourself based on one of those APIs, find a library that does it (with guarantees that meet your needs), or you'll need to redesign your application. "Watching" a directory in a portable manner is at best very tricky, and generally race- and error-prone. If I were you, I wouldn't be too optimistic especially if your design requires that no "event" be missed.
I have created a standalone Qt application to run on Windows. It is in a form of a questionnaire, where the user answers a few questions, and when it is done, the app should generate a .txt file with the answers in the same folder where the .exe is.
It works fine on my own machine (Win7, 64b). It also runs on other Windows machines that have no Qt installed (tried it on another two Win7 64b and one Win XP).
The problem is, the first time the app is run on some machines, it does not generate the output text file. It generates it without problems in the subsequent runs of the application. This happened on the XP and one Win7 64b. The other Win7 64b I tested on (other than my own) had no such issues.
I tried to find out what could be causing the problem, but no luck. The application is run from a directory where it is allowed to write, so that would not be the issue.
You could try to output the complete path to the debug console just before you open the file:
qDebug() << "Current Path: " << QDir::currentPath();
That might give you some insights on why sometimes it works or not...