QFileSystemWatcher: Modified files in a directory - c++

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.

Related

QSettings not saving ini changes without admin privileges

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.

Qt Resource Not Working

I've seen every SE question and have even followed some video tutorials. I have no idea why it isn't working.
I have two QLabels, lblBuyer and lblSeller as well as two pictures. Here is the relevant code:
QPixmap pixmap_buyer(":/Resources/Images/Buyer.png"), pixmap_seller(":/Resources/Images/Seller.png");
size_t lblBuyerWidth = ui->lblBuyer->width(), lblBuyerHeight = ui->lblBuyer->height();
size_t lblSellerWidth = ui->lblSeller->width(), lblSellerHeight = ui->lblSeller->height();
ui->lblBuyer->setPixmap(
pixmap_buyer.scaled(lblBuyerWidth, lblBuyerHeight, Qt::KeepAspectRatio)
);
ui->lblSeller->setPixmap(
pixmap_seller.scaled(lblSellerWidth, lblSellerHeight, Qt::KeepAspectRatio)
);
This is what the resources look like:
And the resources.qrc if you want it:
<RCC>
<qresource prefix="/Resources">
<file>Images/Buyer.png</file>
<file>Images/Seller.png</file>
</qresource>
</RCC>
And the file structure (images are directly in the Images directory):
I selected "Copy as Resource Path" so I was sure not to mess anything up. Also, when I click "Remove Missing Files," neither gets removed... However, when I run it:
QPixmap::scaled: Pixmap is a null pixmap
QPixmap::scaled: Pixmap is a null pixmap
I have seen this a couple of times, and the cure varies:
The first thing to try is clean/rebuild your project.
The second thing to try is to manually clean/rebuild your project (as in delete your build dir by hand in a file manager).
If the problem still persists, you can try putting a resource init macro into main.
In other words, put a line like: Q_INIT_RESOURCE(my_resource); in your main() function just after instantiating your app for each resource in your project, like this:
int main(int argc, char *argv[]){
QApplication app(argc, argv);
Q_INIT_RESOURCE(my_resource);
// ... whatever here ...
return app.exec();}
}
Of course you put the name of your actual resource file in place of my_resource.
This is usually necessary only when I am doing some strange stuff like using my own static Qt or using a wired project structure.

Qt5 QuickView cannot create window: no screens are available

I receive this error (title, below) whenever I try to run the following code:
#include <QCoreApplication>
#include <QQuickView>
int main(int argc, char *argv[]){
QCoreApplication app(argc, argv);
QQuickView view;
view.setSource(QUrl::fromLocalFile("app.qml"));
QObject *object = (QObject*)view.rootObject();
view.show();
delete object;
return app.exec();
}
Cannot create window: no screens available
The program has unexpectedly finished.
All I can find online for that error are bug reports arising from specific conditions significantly more involved than the above.
app.qml is a file that runs fine alone, i.e. without the above C++ and in a separate project configured as a 'Qt Quick UI'. Giving it's qrc:// path, or deliberately specifying a file which does not exist has no effect.
Note the QObject* cast - this was not present in the docs, but without it:
/main.cpp:11: error: cannot initialize a variable of type 'QObject *' with an rvalue of type 'QQuickItem *'
How should this be done?
The QCoreApplication can be used with console application, not with GUI ones, i.e. you have to use a QGuiApplication object. It seems to me that you created a console application instead of a graphical one.
You can create a proper application via the Qt Quick Application, add your "app.qml" as a resource to that project and call such a file instead of the default "main.qml", provided by the project template.
If you want to quick fix your current project, just check that the .pro file is set to import GUI libraries:
QT += gui qml quick
Set your qml file as a resource:
Create a new resource file via file -> new File or Project... -> Qt -> Qt Resource File
Right click the newly created .qrc file and click add existing file to add your "app.qml" file
Finally, rewrite your main like this:
#include <QQuickView>
#include <QGuiApplication>
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv); // GUI APPLICATION!!!
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:///app.qml")));
view.show();
return a.exec();
}
However, going for the Qt Quick Application project would be the wiser choice.

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

How to move a Qt stylesheet to an external file but keep it compiled in resources?

My Qt application has a large stylesheet with lots of margins, pixels and other stuff directly based on and related to drawing and graphics. I would be happy to give all that stuff to the designer, but the stylesheet is kept within the .ui file which is not convenient for the designer; she'd prefer to see a separate file and edit it using her usual tools.
What I want is moving the stylesheet to an external .qss file, adding that file to the program resources and linking it to the .ui file, so the stylesheet would be compiled and used by the widget automatically, and the application wouldn't have to keep the stylesheet file and load it at runtime.
How to achieve that?
Copy all your styles into a file and rename it to something like stylesheet.qss
Then include it in your qrc file as a new resource item. You can simply do this by editing your qrc file, if you already have one. Refer documentation on how to add a new resource.
Then modify your code like this to read the content of the qss file at run time and apply styles to your application.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFile file(":/stylesheet.qss");
if(file.open(QIODevice::ReadOnly | QIODevice::Text))
{
a.setStyleSheet(file.readAll());
file.close();
}
MainWindow w;
w.show();
return a.exec();
}
Note: when you do a change in the stylesheet.qss, you have to compile the qrc file for changes to take effect.
I set the stylesheet when the application is run from an external file. Also, for the designer we added a button to 'reload stylesheet'. This way the designer can modify the file and try the changes immediately.
For example:
QFile styleFile("stylesheet.qss");
styleFile.open(QFile::ReadOnly);
QByteArray bytes = styleFile.readAll();
QApplication *app = (QApplication*)QApplication::instance();
app->setStyleSheet(newStyleSheet);