PDA

View Full Version : How to know the Name of a file, when a file is copied to a folder(QFileSystemWatcher)



blue_sky
31st January 2014, 11:28
How to know the Name of a file, when a file is added(copied) to a folder(QFileSystemWatcher)?

Girish1483
1st February 2014, 12:00
When you copied a file to directory.
connect(watcher,SIGNAL(directoryChanged(QString)), this,SLOT(dirChangedSlot(QString))); will called & you can get file name from QString variable

where wathcer will be QFileSystemWatcher object.

stampede
1st February 2014, 14:57
I don't think so, according to the documentation, you will get a path of the changed directory, as the object can watch multiple directories at once.


void QFileSystemWatcher::directoryChanged ( const QString & path ) [signal]
This signal is emitted when the directory at a specified path, is modified (...)

You can keep track of the directory content yourself:


class MyClass ... {
private slots:
void directoryChanged(const QString& path);
private:
QFileSystemWatcher _watcher;
QStringList _currentEntrylist;
};

...

MClass::MyClass(...)
{
connect(&_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString)) );
}

void MyClass::startMonitor(const QString& path){
_watcher.addPath(path);
const QDir dir(path);
_currentEntryList = dir.entryList();
}

void MyClass::directoryChanged(const QString& path){
const QDir dir(path);
const QStringList files = dir.entryList();
// now in "files" you have current content of directory
// and in variable "_currentEntryList" you have previous content of directory
// so in order to know which files were added or removed you can compare the two lists
... <code to find the difference between two string lists>
//
_currentEntryList = files;
}

d_stranz
1st February 2014, 21:22
@stampede: I would improve the performance of this by storing _currentEntryList as a QSet<QString> rather than a QStringList. QSet<> has very fast lookup, so the job of finding which files are new is to simply iterate over the results of dir.entryList(), calling QSet::contains() for each one.

You could also convert the new directory list into a QSet<QString> using QSet::fromList( const QStringList & ) and use the various QSet operators to find the differences between the old and new sets - in other words, files that have been added, files that have been removed, etc. Saves writing a lot of code to iterate over lists and compare them.

Probably reduces the number of bugs in the program too. ;)



// For example

void MyClass::directoryChanged( const QString & path )
{
const QDir dir(path);
QSet<QString> newDirSet = QSet<QString>::fromList( dir.entryList() );

// Files that haven't changed
QSet<QString> sameFiles = _currentEntrySet & newDirSet ;

// Files that have been added
QSet<QString> newFiles = newDirSet - _currentEntrySet;

// Files that have been removed
QSet<QString> deletedFiles = _currentEntrySet - newDirSet ;

// and update the current set
_currentEntrySet.swap( newDirSet );
}

stampede
1st February 2014, 22:35
@d_stranz: you are right. It was just an idea that came straight out of my mind into the forum post, looks like it is more natural for me to think of a "list" of files rather than a "set":)

d_stranz
2nd February 2014, 01:52
@stampede: Well, if dir.entryList() returns the list of files in alphabetical order, that's one advantage over using the QSet if you want to display the files to the user. QSet stores entries in whatever order the internal hashing determines, so iterating over the contents of the QSet will not return an alphabetical list, even if they were inserted in alphabetical order. If you wanted to display the current contents in alphabetical order, you'd have to copy the QSet into a QStringList, then sort the list. This isn't so bad, since QString instances with the same values are shared.

So let's use the best of both our ideas - keep the current directory contents as a list, but use sets to determine what has changed:



void MyClass::directoryChanged( const QString & path )
{
const QDir dir(path);
QStringList newEntryList = dir.entryList();
QSet<QString> newDirSet = QSet<QString>::fromList( newEntryList );
QSet<QString> currentDirSet = QSet<QString>::fromList( _currentEntryList );

// Files that haven't changed
QSet<QString> sameFiles = currentDirSet & newDirSet;

// Files that have been added
QSet<QString> newFiles = newDirSet - currentDirSet;

// Files that have been removed
QSet<QString> deletedFiles = currentDirSet - newDirSet;

// and update the current set
_currentEntryList = newEntryList;
}

blue_sky
3rd February 2014, 10:48
Thank you ...
I implemented the same logic , but the problem is- In some cases, although entryList() gives file name, but the file takes time to exist physically . i.e- when I tried to load image(through QImage),while copy of file already in process, then most of time i got blank / partial images.
How can I solve this problem.(QFile().exist() failed whether file present completely or not).
I am thinking about SIGNAL SLOTS..
Need helpful suggestions.Thank you


@stampede: Well, if dir.entryList() returns the list of files in alphabetical order, that's one advantage over using the QSet if you want to display the files to the user. QSet stores entries in whatever order the internal hashing determines, so iterating over the contents of the QSet will not return an alphabetical list, even if they were inserted in alphabetical order. If you wanted to display the current contents in alphabetical order, you'd have to copy the QSet into a QStringList, then sort the list. This isn't so bad, since QString instances with the same values are shared.

So let's use the best of both our ideas - keep the current directory contents as a list, but use sets to determine what has changed:



void MyClass::directoryChanged( const QString & path )
{
const QDir dir(path);
QStringList newEntryList = dir.entryList();
QSet<QString> newDirSet = QSet<QString>::fromList( newEntryList );
QSet<QString> currentDirSet = QSet<QString>::fromList( _currentEntryList );

// Files that haven't changed
QSet<QString> sameFiles = currentDirSet & newDirSet;

// Files that have been added
QSet<QString> newFiles = newDirSet - currentDirSet;

// Files that have been removed
QSet<QString> deletedFiles = currentDirSet - newDirSet;

// and update the current set
_currentEntryList = newEntryList;
}

anda_skoa
3rd February 2014, 14:27
Thank you ...
I implemented the same logic , but the problem is- In some cases, although entryList() gives file name, but the file takes time to exist physically . i.e- when I tried to load image(through QImage),while copy of file already in process, then most of time i got blank / partial images.
How can I solve this problem.(QFile().exist() failed whether file present completely or not).
I am thinking about SIGNAL SLOTS..
Need helpful suggestions.Thank you

Question seems to have moved to this thread http://www.qtcentre.org/threads/57910-Problem-with-Copying-files-and-checking-exists-or-not