QSettings IniFormat File gets empty after restart - qt

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.

Related

Using GPS as external editor for AdaMULTI

I'm trying to use GPS (version 19.1) as an external editor for Greenhills AdaMULTI.
I entered -P<myproject.gpr> +%LINE %FILE0 %FILES into the "command line arguments" and also the correct path to GPS for "AdaMULTI Other Editor Configuration".
So far this works as expected, i.e. when pressing CTRL+E in the AdaMULTI Project Manager GPS opens with the file to be edited. Also, when a bug is encountered while compiling GPS opens at the proper line and file.
But ... when configured this way, always a new instance of GPS is opened, which is some kind of annoying because you'll have several instances running all with a single file opened after a while.
Is there a way (option, environment variable or whatever) to tell GPS to use an already running instance?
I have read both the AdaMULTI documentation and GPS User'S Guide to find anything relevant, but to no avail.
you can write some Python plugin for GPS to watch some file for changes, then read a "command" from it to open a file at a given position. Or some other kind of IPC.
What OS do you use? Windows?
I wonder whether you could treat the GPS system as "running on a remote server", see GPS documentation chapter 14, Using GPS for Remote Development, where the "remote" server is in fact the local machine.

QFileSystemModel crashing when seeting root path

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.

Qt App. Deployment on Mac/XP/Vista/Windows 7: Any common access directory to put the License File?

I have to deploy a Qt Application on the following environments:
Mac OS/X (>= Tiger 10.4 Intel Based, up to Snow Leopard 10.6.+)
Windows XP
Windows Vista
Windows 7
I need a common access directory to put the License File, and I need every user of the machine to have read/write access to it - not only the administrator.
I checked many Qt functions like the following:
QString QDir::homePath()
QDir QDir::home ()
QString QDir::rootPath ()
QString QDir::tempPath ()
...but they all seem to return either user-specific or too-general paths.
Is there any Qt specific function to get a common "Applications Path"?
I 've started to think about creating my own function taking into account the OS version,
but even in this case I feel a bit lost.
Do you know any good source to find what should be an appropriate path for each one for the OS I mentioned above?
This is an answer to my own question,
but I 'll wait to see if there is any better solutions.
(maybe there is a Qt function I missed).
I did the following hack using the QSettings class
(#thequark: +1 for the inspiration):
---------------------------------------------
QString orgName = "fooOrg";
QString appName = "fooApp";
QSettings qsettings(QSettings::IniFormat, QSettings::SystemScope, orgName, appName);
QString iniFilepath = qsettings.fileName();
QString commAppPath = iniFilepath.left(iniFilepath.length() -
QString("/fooOrg/fooApp.ini").length());
---------------------------------------------
As you can see, I don't really use the QSettings object but
I just get its filepath to see where Qt is going to store it.
It's important to use:
QSettings::IniFormat: Because we are
interested in a file - not e.g. a
Windows registry position
QSettings::SystemScope: Because we want a machine specific and not
a user-specific path
The above code yields the following results for (1) iniFilepath (2) commAppPath variables and the various O/S:
Mac Snow Leopard 10.6.7
/Library/Preferences/Qt/fooOrg/fooApp.ini
/Library/Preferences/Qt
Windows XP-SP3
C:/Documents And Settings/All Users/Application Data/fooOrg/fooApp.ini
C:/Documents And Settings/All Users/Application Data
Windows 7 (64) and Windows Vista SP2
C:/ProgramData/fooOrg/fooApp.ini
C:/ProgramData
Although it's a hack, I think it's a good solution
involving only internal Qt calls and not using any O/S specific functions.
If you have any better idea... please let me know.
EDIT - PS: In Mac OS-X the directory "/Library/Preferences" is not writable for a non-admin user. I finally used the directory "/Users/Shared".
I am a n00b in Qt too so I am not sure if this is the best option but how about using QSettings to get the path to license file from a settings/configuration file. This file with proper values should be created by the installer. Installer can take care of using some default values specific to the OS or even ask user at the time of installation, so you application is independent of the OS. QSettings has persistence so you don't have to bother about reading, writing on to a file.
Have a look at QDesktopServices::storageLocation.
QDesktopServices::DataLocation enum seems appropriate.
For Windows 2000 and higher, this folder is known as CSIDL_COMMON_APPDATA.

QProcess::startDetached blocked by UAC (running an updater)

I have an update function in my app - it downloads and verifies the installer (a setup.exe, created with NSIS). To actually kick off the update, I have simply been doing:
QString path = .. absolute path to the downloaded file ...
QProcess::startDetached(path, QStringList());
This works fine on XP - but on Vista and Win7, nothing happens once the download completes. If I browse to the downloaded update and run it manually, it works fine. I assume what's happening is that UAC is blocking the installer at CreateProcess time, but this is where my knowledge runs out.
Additional complication - when I'm running a debug build from the command line, the steps above work - I get the UAC prompt and can run the installer. It's the release builds, started form the start menu/shortcut, which have the issue - I assume there's a difference in the auth token when running from a command shell.
You can also use
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
Might be surprising and counterintuitive, but it works and is more cross-platform
If you are not admin and you call CreateProcess() on a .exe with a "Vista" manifest (or no manifest, but a .exe that windows detects as an installer (This includes NSIS)) the call fails, you need to use ShellExecute[Ex](). ShellExecute will trigger UAC prompt if required...
This seems to be a Qt bug, see QTBUG-9761 , the correct workaround is to use ShellExecute with lpOperation set to runas.
Another alternative is to prepend your execution with cmd.exe /C. This effectively routes your execution through the shell, so you do get the UAC prompt. The downside is that if your process fails you probably won't get as much information had you gone through ShellExecute[Ex], but on the plus side you will get all the facilities of QProcess that you miss if you use QDesktopServices::openUrl, where you have no idea if things worked or not.

QFile open file on a shared drive

I have the following:
Q_ASSERT(QFile::exists("\\.host\Shared Folders\username On My Mac\Desktop\New Deck.txt"));
The file is picked from QFileDialog but when check if it exists with QFile::exists it returns FALSE;
Is there any reason why QT cannot open a file on a shared drive.
Btw, this path is a valid one on Windows and is generated by putting the "New Deck.txt" file on my Mac OSX desktop and tried to be read from a QT application run from VM Ware Windows XP SP2.
You must escape \ in the string literal via \: "\\.host\Shared Folders\..."
Also, unless this is for your debugging only, asserting on the existing of files is a bad idea. The file could always disappear between selecting it in the file dialog and opening it.

Resources