Exit the deleted directory when it is removed

If current directory is a local file, try to find nearest dir ancestor and
open it. Display warning to the user.
This commit is contained in:
Méven Car 2022-11-29 18:16:59 +00:00
parent de289800b2
commit a2c9c05de2
9 changed files with 89 additions and 0 deletions

View file

@ -172,6 +172,8 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
this, &DolphinViewContainer::slotHiddenFilesShownChanged);
connect(m_view, &DolphinView::sortHiddenLastChanged,
this, &DolphinViewContainer::slotSortHiddenLastChanged);
connect(m_view, &DolphinView::currentDirectoryRemoved,
this, &DolphinViewContainer::slotCurrentDirectoryRemoved);
// Initialize status bar
m_statusBar = new DolphinStatusBar(this);
@ -939,6 +941,19 @@ void DolphinViewContainer::slotSortHiddenLastChanged(bool hiddenLast)
}
}
void DolphinViewContainer::slotCurrentDirectoryRemoved()
{
const QString location(url().toDisplayString(QUrl::PreferLocalFile));
if (url().isLocalFile()) {
const QString dirPath = url().toLocalFile();
const QString newPath = getNearestExistingAncestorOfPath(dirPath);
const QUrl newUrl = QUrl::fromLocalFile(newPath);
setUrl(newUrl);
}
showMessage(xi18n("Current location changed, <filename>%1</filename> is no longer accessible.", location), Warning);
}
void DolphinViewContainer::slotOpenUrlFinished(KJob *job)
{
if (job->error() && job->error() != KIO::ERR_USER_CANCELED) {
@ -967,3 +982,14 @@ void DolphinViewContainer::tryRestoreViewState()
m_view->restoreState(stream);
}
}
QString DolphinViewContainer::getNearestExistingAncestorOfPath(const QString& path) const
{
QDir dir(path);
do {
dir.setPath(QDir::cleanPath(dir.filePath(QStringLiteral(".."))));
}
while (!dir.exists() && !dir.isRoot());
return dir.exists() ? dir.path() : QString{};
}

View file

@ -400,6 +400,7 @@ private Q_SLOTS:
void slotHiddenFilesShownChanged(bool showHiddenFiles);
void slotSortHiddenLastChanged(bool hiddenLast);
void slotCurrentDirectoryRemoved();
void slotOpenUrlFinished(KJob* job);
@ -421,6 +422,11 @@ private:
*/
void tryRestoreViewState();
/**
* @return Path of nearest existing ancestor directory.
*/
QString getNearestExistingAncestorOfPath(const QString& path) const;
private:
QGridLayout *m_topLayout;

View file

@ -1150,7 +1150,14 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items)
indexesToRemove.reserve(items.count());
KFileItemList dirsChanged;
const auto currentDir = directory();
for (const KFileItem& item : items) {
if (item.url() == currentDir) {
Q_EMIT currentDirectoryRemoved();
return;
}
const int indexForItem = index(item);
if (indexForItem >= 0) {
indexesToRemove.append(indexForItem);

View file

@ -263,6 +263,11 @@ Q_SIGNALS:
*/
void fileItemsChanged(const KFileItemList &changedFileItems);
/**
* It is emitted when the parent directory was removed.
*/
void currentDirectoryRemoved();
protected:
void onGroupedSortingChanged(bool current) override;
void onSortRoleChanged(const QByteArray& current, const QByteArray& previous, bool resortItems = true) override;

View file

@ -93,6 +93,7 @@ private Q_SLOTS:
void testCreateMimeData();
void testDeleteFileMoreThanOnce();
void testInsertAfterExpand();
void testCurrentDirRemoved();
private:
QStringList itemsInModel() const;
@ -2124,6 +2125,32 @@ void KFileItemModelTest::testInsertAfterExpand()
}
void KFileItemModelTest::testCurrentDirRemoved()
{
m_model->m_dirLister->setAutoUpdate(true);
QSignalSpy currentDirectoryRemovedSpy(m_model, &KFileItemModel::currentDirectoryRemoved);
QVERIFY(currentDirectoryRemovedSpy.isValid());
QSignalSpy loadingCompletedSpy(m_model, &KFileItemModel::directoryLoadingCompleted);
QVERIFY(loadingCompletedSpy.isValid());
QSignalSpy dirListerClearSpy(m_model->m_dirLister, &KCoreDirLister::clear);
QVERIFY(dirListerClearSpy.isValid());
m_testDir->createFiles({"dir/a.txt", "dir/b.txt"});
m_model->loadDirectory(QUrl::fromLocalFile(m_testDir->path() + "/dir/"));
QVERIFY(loadingCompletedSpy.wait());
QCOMPARE(m_model->count(), 2);
QVERIFY(m_model->isConsistent());
m_testDir->removeDir("dir");
QVERIFY(currentDirectoryRemovedSpy.wait());
// dirLister calls clear
QCOMPARE(dirListerClearSpy.count(), 2);
QVERIFY(m_model->isConsistent());
QVERIFY(m_model->m_itemData.isEmpty());
QCOMPARE(m_model->count(), 0);
}
QStringList KFileItemModelTest::itemsInModel() const
{
QStringList items;

View file

@ -96,6 +96,17 @@ void TestDir::removeFile(const QString& path)
QFile::remove(absolutePath);
}
void TestDir::removeDir(const QString& path)
{
QString absolutePath = path;
QFileInfo fileInfo(absolutePath);
if (!fileInfo.isAbsolute()) {
absolutePath = TestDir::path() + QLatin1Char('/') + path;
}
QDir dirToRemove = QDir(absolutePath);
dirToRemove.removeRecursively();
}
void TestDir::makePathAbsoluteAndCreateParents(QString& path)
{
QFileInfo fileInfo(path);

View file

@ -37,6 +37,7 @@ public:
void removeFile(const QString& path);
void removeFiles(const QStringList& files);
void removeDir(const QString& path);
private:
void makePathAbsoluteAndCreateParents(QString& path);

View file

@ -195,6 +195,7 @@ DolphinView::DolphinView(const QUrl& url, QWidget* parent) :
connect(m_model, &KFileItemModel::directoryRedirection, this, &DolphinView::slotDirectoryRedirection);
connect(m_model, &KFileItemModel::urlIsFileError, this, &DolphinView::urlIsFileError);
connect(m_model, &KFileItemModel::fileItemsChanged, this, &DolphinView::fileItemsChanged);
connect(m_model, &KFileItemModel::currentDirectoryRemoved, this, &DolphinView::currentDirectoryRemoved);
connect(this, &DolphinView::itemCountChanged,
this, &DolphinView::updatePlaceholderLabel);

View file

@ -637,6 +637,11 @@ Q_SIGNALS:
void fileItemsChanged(const KFileItemList &changedFileItems);
/**
* Emitted when the current directory of the model was removed.
*/
void currentDirectoryRemoved();
protected:
/** Changes the zoom level if Control is pressed during a wheel event. */
void wheelEvent(QWheelEvent* event) override;