Commit 9430e210 authored by Urs Fleisch's avatar Urs Fleisch
Browse files

Improved closing of file handles before rename and trash operations.

parent 06437db8
......@@ -4668,6 +4668,14 @@ void TagLibFile::getAllFramesV2(FrameCollection& frames)
frames.addMissingStandardFrames();
}
/**
* Close file handle which is held open by the TagLib object.
*/
void TagLibFile::closeFileHandle()
{
closeFile(false);
}
/**
* Get a list of frame IDs which can be added.
*
......
......@@ -453,6 +453,11 @@ public:
*/
virtual void getAllFramesV2(FrameCollection& frames);
/**
* Close file handle which is held open by the TagLib object.
*/
virtual void closeFileHandle();
/**
* Get a list of frame IDs which can be added.
*
......
......@@ -434,19 +434,6 @@ QString FileProxyModel::getPathIfIndexOfDir(const QModelIndex& index) {
return model->filePath(index);
}
/**
* Release a tagged file or directory index from an index.
* If the index has a TaggedFile, it will be deleted.
*
* @param index model index
*/
void FileProxyModel::releaseTaggedFileOfIndex(const QModelIndex& index) {
// setData() will not invalidate the model, so this should be safe.
QAbstractItemModel* model = const_cast<QAbstractItemModel*>(index.model());
if (model)
model->setData(index, QVariant(), FileProxyModel::TaggedFileRole);
}
#if defined HAVE_ID3LIB && defined HAVE_TAGLIB
/**
* Read tagged file with TagLib.
......
......@@ -171,12 +171,6 @@ public:
*/
bool rmdir(const QModelIndex& index) const;
/**
* Initialize tagged file for model index.
* @param index model index
*/
void initTaggedFileData(const QModelIndex& index);
/**
* Get tagged file data of model index.
*
......@@ -207,14 +201,6 @@ public:
*/
static QString getPathIfIndexOfDir(const QModelIndex& index);
/**
* Release a tagged file or directory index from an index.
* If the index has a TaggedFile, it will be deleted.
*
* @param index model index
*/
static void releaseTaggedFileOfIndex(const QModelIndex& index);
/**
* Read tagged file with TagLib.
*
......@@ -284,6 +270,12 @@ private:
*/
void clearTaggedFileStore();
/**
* Initialize tagged file for model index.
* @param index model index
*/
void initTaggedFileData(const QModelIndex& index);
QHash<QPersistentModelIndex, TaggedFile*> m_taggedFiles;
QSet<QPersistentModelIndex> m_filteredOut;
TaggedFileIconProvider* m_iconProvider;
......
......@@ -219,6 +219,19 @@ TaggedFile* TaggedFileIterator::next()
return result;
}
/**
* Try to close the file handles.
*
* @param index root of model to iterate
*/
void TaggedFileIterator::closeFileHandles(const QModelIndex& index)
{
TaggedFileIterator it(index);
while (it.hasNext()) {
it.next()->closeFileHandle();
}
}
/**
* Constructor.
......
......@@ -224,6 +224,13 @@ public:
*/
virtual TaggedFile* peekNext() const { return m_nextFile; }
/**
* Try to close the file handles.
*
* @param index root of model to iterate
*/
static void closeFileHandles(const QModelIndex& index);
private:
ModelIterator m_it;
TaggedFile* m_nextFile;
......
......@@ -1042,6 +1042,17 @@ void TaggedFile::getAllFramesV2(FrameCollection& frames)
}
}
/**
* Close any file handles which are held open by the tagged file object.
* The default implementation does nothing. If a concrete subclass holds
* any file handles open, it has to close them in this method. This method
* can be used before operations which require that a file is not open,
* e.g. file renaming on Windows.
*/
void TaggedFile::closeFileHandle()
{
}
/**
* Set frames in tag 2.
*
......
......@@ -535,6 +535,15 @@ public:
*/
virtual void getAllFramesV2(FrameCollection& frames);
/**
* Close any file handles which are held open by the tagged file object.
* The default implementation does nothing. If a concrete subclass holds
* any file handles open, it has to close them in this method. This method
* can be used before operations which require that a file is not open,
* e.g. file renaming on Windows.
*/
virtual void closeFileHandle();
/**
* Set frames in tag 1.
*
......
......@@ -1910,10 +1910,10 @@ void Kid3MainWindow::renameFile()
}
// This will close the file.
// The file must be closed before renaming on Windows.
FileProxyModel::releaseTaggedFileOfIndex(index);
taggedFile->closeFileHandle();
} else if (model->isDir(index)) {
// The directory must be closed before renaming on Windows.
FileProxyModel::releaseTaggedFileOfIndex(index);
TaggedFileIterator::closeFileHandles(index);
}
QString newPath = dirName + '/' + newFileName;
if (!Utils::safeRename(absFilename, newPath)) {
......@@ -1922,7 +1922,6 @@ void Kid3MainWindow::renameFile()
i18n("Error while renaming:\n") +
i18n("Rename %1 to %2 failed\n").arg(fileName).arg(newFileName),
QMessageBox::Ok, Qt::NoButton);
model->initTaggedFileData(index);
}
}
}
......@@ -1983,10 +1982,11 @@ void Kid3MainWindow::deleteFile()
files.append(absFilename);
}
} else {
if (FileProxyModel::getTaggedFileOfIndex(index)) {
if (TaggedFile* taggedFile =
FileProxyModel::getTaggedFileOfIndex(index)) {
// This will close the file.
// The file must be closed before deleting on Windows.
FileProxyModel::releaseTaggedFileOfIndex(index);
taggedFile->closeFileHandle();
}
if (!Utils::moveToTrash(absFilename)) {
files.append(absFilename);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment