PDA

View Full Version : QFileSystemModel remove bug



Alundra
28th February 2015, 07:34
Hi,
I have a qfilesystemmodel and I have a menu to delete a file/folder.
Here the code :


for( int i = 0; i < SelectedIndexes.count(); ++i )
{
const QFileInfo FileInfo = Model->fileInfo( SelectedIndexes[ i ] );
if( FileInfo.isDir() )
{
if( QDir( FileInfo.absoluteFilePath() ).removeRecursively() == false )
DE::CEngine::GetLogger().LogError( "\"%s\" can not be deleted", FileInfo.absoluteFilePath().toUtf8().data() );
}
else
{
if( QDir( FileInfo.dir().absolutePath() ).remove( FileInfo.fileName() ) == false )
DE::CEngine::GetLogger().LogError( "\"%s\" can not be deleted", FileInfo.absoluteFilePath().toUtf8().data() );
}
}

The problem is when you enter the folder inside a folder and try to remove, you can't remove.
* Root
** Folder
*** Inside_Folder
Once a setRootIndex is called on the "Inside_Folder" if you set the rootIndex to the root and try to remove Folder, you can't.
That removes "Inside_Folder" but not "Folder" you have to redo a remove action on Folder a second time to remove it.
A fix exists on this problem ? How ?
Thanks for the help

d_stranz
28th February 2015, 16:45
Maybe it is a bug, but you can always check to see if the file / folder exists after you do a remove, and have your code do it again. You don't have to make your user do it twice when you can do it for them.

Alundra
28th February 2015, 19:16
Doing it twice if the remove return false gives two times the error message and I can't remove the folder outside the app using Windows explorer, Windows says the folder is used can't be deleted. Looks like a QFileWatcher problem. I tried to remove recursively manually but gives the same result, that remove all inside recursively but not the folder where the delete starts.

d_stranz
28th February 2015, 22:31
I think the problem might be that because the QFileInfo instance is still in scope and is still "looking" at the folder, that is why you are getting the "in use" message.

Since you don't actually need the QFileInfo instance (you need the absolute path, filename and a bool to say if it is a directory), then you could put the QFileInfo instance into its own local scope:



for( int i = 0; i < SelectedIndexes.count(); ++i )
{
QString absPath;
QString fileName;
bool isDir = false;
{
const QFileInfo FileInfo = Model->fileInfo( SelectedIndexes[ i ] );
absPath = FileInfo.absoluteFilePath();
isDir = FileInfo.isDir();
if ( isDir )
fileName = FileInfo.fileName();
}

if ( isDir )
{
if( QDir( absPath ).removeRecursively() == false )
DE::CEngine::GetLogger().LogError( "\"%s\" can not be deleted", absPath.toUtf8().data() );
}
else
{
if( QDir( absPath ).remove( fileName ) == false )
DE::CEngine::GetLogger().LogError( "\"%s\" can not be deleted", absPath.toUtf8().data() );
}
}

Alundra
1st March 2015, 03:36
Same result, needs double action.
I found the code can be reduced like that :


for( int i = 0; i < SelectedIndexes.count(); ++i )
{
if( Model->remove( SelectedIndexes[ i ] ) == false )
{
const QString AbsoluteFilePath = Model->fileInfo( SelectedIndexes[ i ] ).absoluteFilePath();
DE::CEngine::GetLogger().LogError( "\"%s\" can not be deleted", AbsoluteFilePath.toUtf8().data() );
}
}

The problem is there only if I enter in the folder before remove it, I delete it on the start of the application, that works fine.
Root
**Folder
***Inside_Folder
Only if you enter the "Inside_Folder", if you just enter "Folder" and go back to "Root" and delete "Folder" that delete "Folder" and "Inside_Folder" correctly.
The Qt doc says that installs a file system watcher : http://doc.qt.io/qt-5/qfilesystemmodel.html#setRootPath
I'm pretty sure that doesn't remove it when you change the path, must be the problem, I only see that.
When I change folder I do : m_DetailList->setRootIndex( DetailModel->index( CurrentPath ) );
That shows me the inside of the folder since I use an icon view on the list.

ChrisW67
1st March 2015, 05:46
If you are calling setRootIndex() then it possibly invalidates any existing QModelIndexes, including those in your SelectionIndexes vector/list. Are you rebuilding this list after your change of root index? Have you checked the indexes are valid and pointing where you think they are?

Is there a reason for not deleting through the model?

Alundra
1st March 2015, 14:16
Is there a reason for not deleting through the model?

I have changed to use "Model->remove( SelectedIndexes[ i ] )" like I showed before.

"setRootIndex()" is called only when double on a folder, when delete is involved, "setRootIndex()" is not called.
On the beginning of the delete function I do :
const QModelIndexList SelectedIndexes = selectedIndexes();
I use icon view on the list, the user can not select inside folder since he only see the root folder of the delete.
Since that deletes all folder inside, the index is valid. Only if I enter in the inside folder then it's impossible to delete without two delete actions.
The full function :


void DeleteSelectedItems()
{
const QModelIndexList SelectedIndexes = selectedIndexes();
if( selectedIndexes().empty() )
return;
CFileSystemModel* Model = static_cast< CFileSystemModel* >( model() );
for( int i = 0; i < SelectedIndexes.count(); ++i )
{
if( Model->remove( SelectedIndexes[ i ] ) == false )
{
const QString AbsoluteFilePath = Model->fileInfo( SelectedIndexes[ i ] ).absoluteFilePath();
DE::CEngine::GetLogger().LogError( "\"%s\" can not be deleted", AbsoluteFilePath.toUtf8().data() );
}
}
}