From aca9c93fa06e266dd44a74410eb129bdbc719607 Mon Sep 17 00:00:00 2001 From: Dongmei Wang Date: Tue, 25 Jul 2017 13:11:04 -0700 Subject: QFileDialog: Fix a crash occurring when deleting a file A crash has been observed on Windows in the use case below: 1) In a non-native QFileDialog, select a file and press "Del" key to delete it, and a warning message box appears for user to confirm the deletion. 2) Delete the file in the Windows Explorer. 3) Click "Yes" on the warning message box, a crash happens In QFileDialog::_q_deleteCurrent(), use QPersistentModelIndex instead of QModelIndex to ensure that the index is valid to be deleted. The change is intended to fix . The patch is to use QPersistentModelIndex instead of QModelIndex in QFileDialog::_q_deleteCurrent() to ensure that the index is valid to be deleted. Change-Id: I8959124dc071f7cf0ab47f954d611211a789978d Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qfiledialog.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/widgets/dialogs') diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index b638adeaec..b953c63569 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -3417,7 +3417,7 @@ void QFileDialogPrivate::_q_deleteCurrent() QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows(); for (int i = list.count() - 1; i >= 0; --i) { - QModelIndex index = list.at(i); + QPersistentModelIndex index = list.at(i); if (index == qFileDialogUi->listView->rootIndex()) continue; @@ -3443,12 +3443,15 @@ void QFileDialogPrivate::_q_deleteCurrent() QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) return; + // the event loop has run, we have to validate if the index is valid because the model might have removed it. + if (!index.isValid()) + return; + #else if (!(p & QFile::WriteUser)) return; #endif // QT_CONFIG(messagebox) - // the event loop has run, we can NOT reuse index because the model might have removed it. if (isDir) { if (!removeDirectory(filePath)) { #if QT_CONFIG(messagebox) -- cgit v1.2.3 From 5157c3e8bd78d31efea885d8e2d36e24f41a4a2f Mon Sep 17 00:00:00 2001 From: Dongmei Wang Date: Sat, 22 Jul 2017 10:57:59 -0700 Subject: In QFileDialog delete a symlink rather than actual target it points to In QFileDialog, when a resolved symlink gets deleted, the actual target it points to gets deleted instead of the symlink itself. The patch is to delete the symlink rather than actual target by doing the following: 1. In QFileDialog, if a directory being deleted is a resolved symlink, do not remove the directory. Instead, call QFileSystemModel to remove the model index. 2. In QFileSystemModel::remove(), use the full file path instead of the resolved file path for deletion. For a symlink, delete the symlink itself. The patch is for Windows and Linux. Task-number: QTBUG-29770 Change-Id: I4db545f0b5963acde3f89a8ee858338c23104804 Reviewed-by: Friedemann Kleint Reviewed-by: Gabriel de Dietrich --- src/widgets/dialogs/qfiledialog.cpp | 3 +-- src/widgets/dialogs/qfilesystemmodel.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/widgets/dialogs') diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index b953c63569..97afce1734 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -3427,7 +3427,6 @@ void QFileDialogPrivate::_q_deleteCurrent() QString fileName = index.data(QFileSystemModel::FileNameRole).toString(); QString filePath = index.data(QFileSystemModel::FilePathRole).toString(); - bool isDir = model->isDir(index); QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt()); #if QT_CONFIG(messagebox) @@ -3452,7 +3451,7 @@ void QFileDialogPrivate::_q_deleteCurrent() return; #endif // QT_CONFIG(messagebox) - if (isDir) { + if (model->isDir(index) && !model->fileInfo(index).isSymLink()) { if (!removeDirectory(filePath)) { #if QT_CONFIG(messagebox) QMessageBox::warning(q, q->windowTitle(), diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 63b5cf7aaf..bf14b5c6fd 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -203,8 +203,12 @@ QFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const bool QFileSystemModel::remove(const QModelIndex &aindex) { - const QString path = filePath(aindex); - const bool success = QFileInfo(path).isFile() ? QFile::remove(path) : QDir(path).removeRecursively(); + Q_D(QFileSystemModel); + + const QString path = d->filePath(aindex); + const QFileInfo fileInfo(path); + const bool success = (fileInfo.isFile() || fileInfo.isSymLink()) + ? QFile::remove(path) : QDir(path).removeRecursively(); #ifndef QT_NO_FILESYSTEMWATCHER if (success) { QFileSystemModelPrivate * d = const_cast(d_func()); -- cgit v1.2.3 From 256854cf9760f2b8e8702c2ce2066f67213c0169 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 28 Jul 2017 10:54:44 +0200 Subject: Windows/QFileSystemModel: Fix updating of removed drives Previously, the updating of drives in QFileSystemModel was connected to a signal triggering when a drive containing watched files was removed via QFileSystemWatcher notification. This did not trigger when a drive that was not expanded in the view was removed, since no files were watched. Since QFileSystemModel is not interested in the path of the drive being removed, add a generic signal triggered by DBT_DEVTYP_VOLUME/DBT_DEVICEREMOVECOMPLETE and use that to update the drives. Complements 8e79806d08ab77aa0f87b69a2ef65789216f41c0. Task-number: QTBUG-18729 Task-number: QTBUG-53436 Change-Id: Ibcde4665824c41151042237d4d620c48bc1e2e18 Reviewed-by: Oliver Wolff Reviewed-by: Joerg Bornemann --- src/widgets/dialogs/qfileinfogatherer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/widgets/dialogs') diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp index 9f2d15d31b..710ee611b9 100644 --- a/src/widgets/dialogs/qfileinfogatherer.cpp +++ b/src/widgets/dialogs/qfileinfogatherer.cpp @@ -98,7 +98,7 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent) if (listener.canConvert()) { if (QObject *driveListener = listener.value()) { connect(driveListener, SIGNAL(driveAdded()), this, SLOT(driveAdded())); - connect(driveListener, SIGNAL(driveRemoved(QString)), this, SLOT(driveRemoved())); + connect(driveListener, SIGNAL(driveRemoved()), this, SLOT(driveRemoved())); } } # endif // Q_OS_WIN && !Q_OS_WINRT -- cgit v1.2.3