I have the following issue: I create a QFileSystemWatcher and it runs and works nicely on Linux, but no way on Windows 7. Can you spot anything in the code that might make it not to work?
Thx.
Here is the code to initialize it:
mConfigChangeWatcher = new QFileSystemWatcher();
mConfigChangeWatcher->addPath(config_file_name);
QObject::connect(mConfigChangeWatcher,
SIGNAL(fileChanged(QString)),
this,
SLOT(configFileChanged(QString)));
and this is supposed to be the slot getting the work done:
void MyClass::configFileChanged(const QString &file)
{
qDebug() << "Changed: " << file ;
}
When you check if the file is added to the watcher using QFileSystemWatcher::files() method after the first modification in the file do you get the correct list?
I was with the issue that some applications, when modifing a file, delete the old file from the system and write it again.
Note that QFileSystemWatcher stops monitoring files once they have been renamed or removed from disk, and directories once they have been removed from disk.
I was using QFileSystemWatcher to watch an image file edited by Photoshop. Somehow the file gets removed from the list of files being watched.
I had the same problem and solved it very fast.
Within the slot that manages the fileChanged signal I noted the path disappears from files(). I simply make a check and re-add it if necessary
if (! watcher_.files().contains(path))
{
watcher_.addPath(path);
}
I hope this helps
Fabio
Related
In my program it is possible to select a sound for an action. the sound is changeable, which means the .wav file gets replaced by another file.
This may cause the problem. When i replace the file and set the source of the QSoundEffect the sound does not change.
At the moment i am having a source like this:
//variable in .h
QUrl sound = "file:///"+soundDirectory+"sound.wav";
QUrl newSound = "file:///"+soundDirectory+"newSound.wav"; ;
QSoundEffect soundeffect;
//called in setSound() in .cpp
soundEffect.setSource(sound);
the sound loads without problem and i can play that sound.
i can change that sound with this code
// changing the sound in changeSound()
soundEffect.setSource(newSound);
this also works fine. the new sound is loaded and i can play it.
But it is also possible to change the sound files in the directory:
//changeSoundFile()
QFile::remove(sound.toLocalFile());
QFile::copy(anyPossibleSound.toLocalFile(), sound.toLocalFile());
This also works and replaces the sound file in its directory with another.
If I call setSound() after changing the file. It seems like the file does not get reload. and the sound is not changed. This is also the problem if changed the sound in between (call setSound on startup, then changeSound, then changeSoundFile and the setSound again)
Am I overlooking something?
It's not mentioned in the official docs, but you can find the implementation on GitHub:
void QSoundEffect::setSource(const QUrl &url) {
if (d->source() == url)
return;
d->setSource(url);
emit sourceChanged();
}
The file does not get reloaded because the URL is the same. The implementation holds an internal cache with the data that has been loaded before, so when you play the file, nothing change.
The API does not provide a way of forcing the reset of the data source. You have two alternatives:
Re-creating the QSoundEffect instance each time you modify the file.
Changing the file name:
// Create a temporal file
const auto uuid = QUuid::createUuid();
const auto new_filename = uuid.toString() + ".wav";
// Copy the file
QFile::remove(sound.toLocalFile());
QFile::copy(anyPossibleSound.toLocalFile(), new_filename);
sound = QUrl(new_filename);
// Use it
soundEffect.setSource(sound);
I'm making an application part of which is reading from an XML which stores some preferences. However, whenever I build the project, all the sources get copied but the preferences file does not! I have added the following to the .pro file -
RESOURCES += rsc.qrc
And my rsc.qrc contains
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>data/preferences.xml</file>
<file>data/gamedata.xml</file>
</qresource>
</RCC>
Now whenever I try to open preferences.xml
QFile preferences(":/data/preferences.xml");
if(!preferences.exists()){
preferences.open(QFile::WriteOnly);
preferences.write("abc");
qDebug() << "Written";
}
else {
qDebug() << "File exists";
}
Absolutely nothing gets printed and even the rest of the application stops working.
You don't use the resource part correctly in your example.
It will most likely not work because you try to write to a resource that is embedded into your executable after you have build your application. Reading is fine, but writing can't work by definition.
If you want a editable setting files, you have to distribute them along with your executable, or use a different method for reading/writing your settings like QSettings.
However using QSettings also means, that you will need to configure all your default settings in your loading function in case the values do not exist if you use the default configuration. Meaning you use registry on windows.
You have the option to force the use of a INI file format in the constructor of QSettings, this can make sense if you want to provide a default settings INI file instead of your xml files.
In case you want to store more complex data a xml file might be needed anyway, so if you want to stick with that you will need a way to copy your setting files to your build path. This can be done within your pro file with QMAKE_POST_LINK.
Example:
COPY_CMD = "$$PWD\\data\\preferences.xml $$OUT_PWD\\release\\data\\preferences.xml"
COPY_CMD = $${QMAKE_COPY} $$replace( COPY_CMD, "/", "\\" ) $$escape_expand( \\n\\t )
QMAKE_POST_LINK += $$COPY_CMD
I can make a file and make my Qt project read and write to it .
But How can I make it create it's own text file for the first time then it writes and reads from and to it later for example i want it to write and read to and from this directory C:\Users\Administrator\Documents .
I will answer supposing that you are asking (don't know if I understood well, since your question is hardly understandable) how to create a file one time, then later, write and read from this file already created.
First, you have to give your file a name.
QString fileName = "C:\Users\Administrator\Documents\file.txt";
QFile file(fileName);
If your file is not already created : calling the function QFile::open(OpenMode mode) will create this file :
bool openOk = file.open(QIODevice::ReadWrite);
if (openOk)
{
// process
}
You can now write and read from your file.
Later, if you want to use your file again, just call this function again : if the file is already created, then you can read/write in this file.
I'm trying to download a file in Qt5, but the file must not be located on the HDD after download.
To clarify> My app will use a downloaded file to update some firmware, and I don't want the downloaded update to remain on the user's hard drive because it could get stolen.
So, I'm trying to make a QFile from QNetworkReply* but without saving it to some path on a hard drive.
I'm downloading a file using QNetworkAccessManager and storing the data into QNetworkReply. I always used to make a QFile with QNetworkReply*, but now I can't do that.
I have found the QTemporaryFile class where a file gets removed right after using it, but that still leaves user with some options of finding the file later.
I tried typecasting that QNetworkReply* as a QFile, but didn't manage to get that to work, seems like QFile can't be without a path on HDD.
Does anyone have any ideas how to do this, and how?
Thanks everyone.
Again not sure your intended end use case but since your data is small enough to hold in memory you can use a QByteArray or QBuffer and write into it from your QNetworkReply. QBuffer provides a QIODevice interface for the QByteArray so it may be a bit easier for you to work with.
Make sure to open the QBuffer for read/write. See the simple example below from the Qt documentation, http://doc.qt.io/qt-5/qbuffer.html#details, below:
QBuffer buffer;
char ch;
buffer.open(QBuffer::ReadWrite);
buffer.write("Qt rocks!");
buffer.seek(0);
buffer.getChar(&ch); // ch == 'Q'
buffer.getChar(&ch); // ch == 't'
buffer.getChar(&ch); // ch == ' '
buffer.getChar(&ch); // ch == 'r'
That should allow you to read back the data and use as required without creating a file on the system.
I am building up a QListWidget, browsing through a directory so that every ".png" gets listed with a preview icon.
The core of my populating loop looks like this:
new QListWidgetItem( QIcon(act_fullname), act_filename);
Right after the whole list is ready, the app crashes.
The error is many times repeated and says this:
On Mac OS X, you might be loading two sets of Qt binaries into the
same process. Check that all plugins are compiled against the right Qt
binaries. Export DYLD_PRINT_LIBRARIES=1 and check that only one set of
binaries are being loaded. QObject::moveToThread: Current thread
(0x103339cb0) is not the object's thread (0x10a848670). Cannot move to
target thread (0x103339cb0)
On Mac OS X, you might be loading two sets of Qt binaries into the
same process. Check that all plugins are compiled against the right Qt
binaries. Export DYLD_PRINT_LIBRARIES=1 and check that only one set of
binaries are being loaded.
Do you have any ideas?
Thanks for your help!
EDIT:
If I skip the icons there is no problem. I have also tried going
QListWidgetItem *item = new QListWidgetItem(act_filename);
ui->listWidget->addItem(item);
item->setIcon(QIcon(act_fullname));
and got no difference.
EDIT 2:
I do not call QObject::moveToThread(QThread*) I don't even use threads (deliberately at least).
Also, the errors appear to come after the loop. I have cout-ed every iteration and the end of the loop and right after my "end loop cout msg" I see that
objc[56963]: Class QCocoaColorPanelDelegate is implemented in both
/Users/Barnabas/QtSDK/Desktop/Qt/4.8.1/gcc/lib/QtGui.framework/Versions/4/QtGui
and
/Users/Barnabas/Programming/Qt/demo_OpenCV-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Release/demo_OpenCV.app/Contents/MacOS/../Frameworks/QtGui.framework/Versions/4/QtGui.
One of the two will be used. Which one is undefined.
Here, too, I do not use QCocoaColorPanelDelegate. I don't even know what it is ... :(
But here is my more detailed code:
boost::filesystem::path p("/path/to/dir");
if(boost::filesystem::is_directory(p))
{
for(boost::filesystem::directory_iterator it(p); it!=boost::filesystem::directory_iterator(); ++it)
{
if(it->path().extension().string()==".png")
{
std::cout<< it->path() <<std::endl;
QString item_name( it->path.stem().c_str() );
QString screen_file( it->path.c_str() );
QListWidgetItem *item = new QListWidgetItem(item_name);
QIcon *icon = new QIcon(screen_file);
item->setIcon(*icon); // if I comment this one out, everything is fine.
ui->imageList->addItem(item);
}
}
}
I have also tested it with a single .png and the image was displayed properly in the list but crash followed with the very same messages.
I have finally found the solution: manually removed the Debug and the Release directories.
For those whose similar problem is not solved by this see: this link.