QSettings not saving ini changes without admin privileges - c++

Problem
I am currently learning Qt by writing a mp3 player on Windows. Now I want to use QSettings to save changes made to the application. I already tried saving the changes to the registry (which works fine) but I would like to store them in an ini-file (for portability reasons).
But for some reason I am unable to create or write an existing ini-file (reading works perfectly).
What I've tried so far
run the application with admin privileges, which works but is not viable all the time
use QStandardPath to ensure a writable path
MCVE
#include <QCoreApplication>
#include <QSettings>
#include <QDebug>
#include <QFileInfo>
#include <QStandardPaths>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QString path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
path = path + "/settings.ini";
QFileInfo info(path);
qDebug() << info.exists();
qDebug() << info.isWritable();
QSettings settings(path, QSettings::IniFormat);
settings.setValue("key", "value");
settings.sync();
return 0;
}
Question
Why does the ini-file only get generated / updated when the application is running with admin privileges? Is there any way to do it without?

It's not clear what versions of OS are used. Windows 10 (version 1709) come with new feature called "Protected folders" to prevent e.g. Ransomware threats. You can reconfigure it somewhere. It disallow write access to desktop/documents etc.
But more preferable approach will be to store ini file into other location e.g. AppData.

Related

QFileSystemWatcher: Modified files in a directory

I am trying to keep track of files in a directory. Not only do I want to get notion of new files being created or existing files being deleted, but I also would like to watch for modifications done to existing files (i.e., when the file content is modified).
QFileSystemWatcher allows for watching directories and files. Given a large number of files in the directory it is not feasible to add every file to the watcher (QFileSystemWatcher::addFile()). In return, however, it would be totally sufficient to hinge the modification of a file on its modification time alone.
Now I've set up a little test like this:
#include <QtCore>
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QFileSystemWatcher *w = new QFileSystemWatcher;
w->addPath("/tmp/xxx");
QObject::connect(w, &QFileSystemWatcher::directoryChanged,
[]{ qDebug() << "change"; }
);
QFile f("/tmp/xxx/the.file");
f.open(QFile::WriteOnly);
f.write("blabla");
f.setFileTime(QDateTime::fromSecsSinceEpoch(10000), QFile::FileModificationTime);
f.close();
QDialog d;
d.show();
app.exec();
}
Yet whatever I try within this program (writing to the file, setting the file times) no change is ever detected.
But what strikes me is that if I use touch on the file the change is detected. So what on earth does touch do differently?
Obviously I am running Linux.

Changing Default Source File On Qt Creator

I'm simply looking for a quick and easy solution on how to change the default source code (if at all possible) for when you open a qtCreator C++ project.
As soon as you open up a new project you see something like below in your main.cpp file.
#include <QCoreApplication>
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
return a.exec(); }
I'm wondering if there's a way to change this code snippet to user defined code. I personally just think its a hassle to wipe all this code out every time I create a project and would rather it look something like below, when I make a new project.
#include <QCoreApplication>
#include <iostream>
using namespace std;
int main() {
}
Anyways, open to all different types of solutions just let me know...

Modbusclient as a console application, "Stuck in Connectingstate loop"

I'm trying hardly to convert the Modbusmaster example (qt example) which is a widget application to a console application. I wanted to build a connection between a local slave and my master. The problem I'm facing is that my code is changing its state to “Connecting state” ,gets stuck and doesn't want to build a connection. That's why, I recon that the Modbus library is limited and it's only compatible with the widget form.
Could someone tell me if my guesses are right.
down below you will find my code:
#include <QCoreApplication>
#include <QDebug>
#include <QModbusDataUnit>
#include<iostream>
#include <QTimer>// this bib was add to the 50ms Loop check
#include <string>
#include <QString>
#include <QThread>
#include <QModbusTcpClient>
#include <QModbusDataUnit>
#include <QUrl>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Mainmodbus T ;
T.modbusDevice = new QModbusTcpClient();
if (!T.modbusDevice) qDebug()<<"error 1";
if (T.modbusDevice->state() != QModbusDevice::ConnectedState) {
T.modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "127.0.0.1");
T.modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);
T.modbusDevice->connectDevice();
while(true){
qDebug()<<T.modbusDevice->state();}
}
return a.exec();
}
I can be wrong but I think the QModbusDevice::ConnectingState you see actually means your server is up and running and waiting for a connection.
I guess what you are missing is opening a connection from a Modbus client. You can do that with different tools, I guess running the client example
would be a good idea. Otherwise, you can use QModMaster or any other tool you like.
Once you open the connection from the client the state on your server should change to QModbusDevice::ConnectedState.
Be aware that the server you built is just an empty shell, there is no register map defined so if you query the contents of any register from the client you will get an error.
At the very minimum, you should at least define a map with some default values or get them from command-line options. To do that you need to look at the server example a bit more carefully.
First you need to define the register map with something like this:
QModbusDataUnitMap reg;
reg.insert(QModbusDataUnit::Coils, { QModbusDataUnit::Coils, 0, 10 });
reg.insert(QModbusDataUnit::DiscreteInputs, { QModbusDataUnit::DiscreteInputs, 0, 10 });
reg.insert(QModbusDataUnit::InputRegisters, { QModbusDataUnit::InputRegisters, 0, 10 });
reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 0, 10 });
modbusDevice->setMap(reg);
setupDeviceData();
And then for the setupDeviceData(); you can copy the function in the example but instead of taking the data from the widget, you will have to load default values or something from the command line.
In answer to your question: no, there should be no limitation and you should be able to run the server from the command line. I wonder why somebody on his/her right mind would want to do that when you have excellent alternatives like libmodbus. But honestly, I won't miss much sleep wondering.

How to print version of a Qt GUI application to console

I have a GUI application written using Qt Widgets. I've added versioning and I'm planning to write an update manager too. In order this to work the update manager must be able to determine the version of my app. I thought of implementing this by running my app with a version switch then parsing it's output. I did a research and I found out that Qt has some kind of built in solution for this.
Here is an example:
#include "mainwindow.h"
#include <QApplication>
#include <QCommandLineParser>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QApplication::setApplicationVersion("1.0.0");
QCommandLineParser parser;
auto versionOption = parser.addVersionOption();
parser.process(app);
if (parser.isSet(versionOption))
{
MainWindow w;
w.show();
return app.exec();
}
return 0;
}
If I launch this app with a -v or --version command line switch, I get a message box containing the version information.
I need to achieve the same, only the information should be printed to standard output. If the app is launched with the version switch it should only display the version in the console then close.
How could I print the version information to the standard console output with a GUI app?
As we cleared some points in comments let's move on. ;)
Take a look at the documentation (http://doc.qt.io/qt-5/qapplication.html#details). In the detail section you see a sane way how to properly parse and handle command line options.
And here (https://stackoverflow.com/a/3886128/6385043) you can see a possibility for writing to standard output. Notice the QDebug caveat.
In my opinion, stick to the text file. You may generate it during build with qmake using the variable VERSION, which you can also use with QApplication::setApplicationVersion(QString).

Reading a CSS file using Qt C++

I'm trying to load in a CSS file for formatting across my entire Qt application. Currently I have my "stylesheet.css" file in the same folder as my built exe (both debug and release). However, upon running the program it produces no errors and simply outputs "test: ", so it's clearly not finding the file or perhaps I'm not reading it properly?
Forgive me if it's a dumb mistake - I'm fairly new to both Qt and C++.
#include "mainwindow.h"
#include "qfile.h"
#include "qtextstream.h"
#include <QApplication>
#include <iostream>
int main(int argc, char *argv[])
{
QApplication program(argc, argv);
QFile styleFile("stylesheet.css");
styleFile.open(QIODevice::ReadOnly);
QTextStream textStream(&styleFile);
QString styleSheet = textStream.readAll();
styleFile.close();
program.setStyleSheet(styleSheet);
std::cout << "test: " << styleSheet.toStdString() << std::endl;
MainWindow w;
w.showMaximized();
return program.exec();
}
After digging a bit deeper, it turns out I was lacking a QRC file (which I wasn't even aware existed). So I created a resource (QRC) file, added the prefix "/style", and then added my stylesheet to that prefix. It now works flawlessly. Also, at one point I changed the .css to a .qss (thought I should mention it, although I doubt it made any difference).
Here's the final code:
#include "mainwindow.h"
#include "qfile.h"
#include "qtextstream.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication program(argc, argv);
QFile styleFile(":/style/stylesheet.qss");
if(styleFile.open(QIODevice::ReadOnly))
{
QTextStream textStream(&styleFile);
QString styleSheet = textStream.readAll();
styleFile.close();
program.setStyleSheet(styleSheet);
}
MainWindow w;
w.showMaximized();
return program.exec();
}
Change
QFile styleFile("stylesheet.css");
to
QFile styleFile("C:/path/to/stylesheet.css");
You need to pass the full file path for your program to find the file. If you just give its name but not the directory it's in, the program will search for it in the current directory only (which is not necessarily the directory of your exe file), and if it's not there, it won't find it.
If you want to deploy this CSS file with your application, you are looking for the Qt resource file support.
its coz u shoud uncheck " shadow build " under projects. and check the path of the project . and make sure that .css file is inside the project folder