diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -1320,7 +1320,18 @@ KFileItemListProperties capabilities(list); const bool enableMoveToTrash = capabilities.isLocal() && capabilities.supportsMoving(); - renameAction->setEnabled(capabilities.supportsMoving()); + bool enableRename = true; + if (list.count() > 1 && capabilities.isLocal()) { + foreach (const KFileItem &item, list) { + const QString parentDir = item.url().adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash).toLocalFile(); + enableRename = enableRename && QFileInfo(parentDir).isWritable(); + if (!enableRename) { + break; + } + } + } + + renameAction->setEnabled(capabilities.supportsMoving() && enableRename); moveToTrashAction->setEnabled(enableMoveToTrash); deleteAction->setEnabled(capabilities.supportsDeleting()); deleteWithTrashShortcut->setEnabled(capabilities.supportsDeleting() && !enableMoveToTrash); diff --git a/src/dolphinpart.cpp b/src/dolphinpart.cpp --- a/src/dolphinpart.cpp +++ b/src/dolphinpart.cpp @@ -275,6 +275,17 @@ KFileItemListProperties capabilities(selection); const bool enableMoveToTrash = capabilities.isLocal() && capabilities.supportsMoving(); + bool enableRename = true; + if (selection.count() > 1 && capabilities.isLocal()) { + foreach (const KFileItem &item, selection) { + const QString parentDir = item.url().adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash).toLocalFile(); + enableRename = enableRename && QFileInfo(parentDir).isWritable(); + if (!enableRename) { + break; + } + } + } + renameAction->setEnabled(capabilities.supportsMoving()); moveToTrashAction->setEnabled(enableMoveToTrash); deleteAction->setEnabled(capabilities.supportsDeleting()); diff --git a/src/panels/folders/folderspanel.cpp b/src/panels/folders/folderspanel.cpp --- a/src/panels/folders/folderspanel.cpp +++ b/src/panels/folders/folderspanel.cpp @@ -257,7 +257,7 @@ QUrl newUrl = oldUrl.adjusted(QUrl::RemoveFilename); newUrl.setPath(newUrl.path() + KIO::encodeFileName(newName)); - KIO::Job* job = KIO::moveAs(oldUrl, newUrl); + KIO::Job* job = KIO::moveAs(oldUrl, newUrl, KIO::PrivilegeExecution); KJobWidgets::setWindow(job, this); KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Rename, {oldUrl}, newUrl, job); job->uiDelegate()->setAutoErrorHandlingEnabled(true); diff --git a/src/panels/folders/treeviewcontextmenu.cpp b/src/panels/folders/treeviewcontextmenu.cpp --- a/src/panels/folders/treeviewcontextmenu.cpp +++ b/src/panels/folders/treeviewcontextmenu.cpp @@ -183,7 +183,7 @@ void TreeViewContextMenu::paste() { - KIO::PasteJob *job = KIO::paste(QApplication::clipboard()->mimeData(), m_fileItem.url()); + KIO::PasteJob *job = KIO::paste(QApplication::clipboard()->mimeData(), m_fileItem.url(), KIO::PrivilegeExecution); KJobWidgets::setWindow(job, m_parent); } @@ -211,7 +211,7 @@ KIO::JobUiDelegate uiDelegate; uiDelegate.setWindow(m_parent); if (uiDelegate.askDeleteConfirmation(list, KIO::JobUiDelegate::Delete, KIO::JobUiDelegate::DefaultConfirmation)) { - KIO::Job* job = KIO::del(list); + KIO::Job* job = KIO::del(list, KIO::PrivilegeExecution); KJobWidgets::setWindow(job, m_parent); job->uiDelegate()->setAutoErrorHandlingEnabled(true); } diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -668,7 +668,7 @@ KIO::JobUiDelegate uiDelegate; uiDelegate.setWindow(window()); if (uiDelegate.askDeleteConfirmation(list, KIO::JobUiDelegate::Delete, KIO::JobUiDelegate::DefaultConfirmation)) { - KIO::Job* job = KIO::del(list); + KIO::Job* job = KIO::del(list, KIO::PrivilegeExecution); KJobWidgets::setWindow(job, this); connect(job, &KIO::Job::result, this, &DolphinView::slotDeleteFileFinished); @@ -1525,18 +1525,22 @@ newUrl.setPath(newUrl.path() + KIO::encodeFileName(newName)); const bool newNameExistsAlready = (m_model->index(newUrl) >= 0); - if (!newNameExistsAlready) { - // Only change the data in the model if no item with the new name - // is in the model yet. If there is an item with the new name - // already, calling KIO::CopyJob will open a dialog - // asking for a new name, and KFileItemModel will update the - // data when the dir lister signals that the file name has changed. + const bool isParentDirWritable = QFileInfo(oldUrl.adjusted(QUrl::RemoveFileName | QUrl::StripTrailingSlash).toLocalFile()).isWritable(); + if (!newNameExistsAlready && isParentDirWritable) { + // Only change the data in the model if no item with the new name is in the model + // yet and parent directory of the item is writable. + // If there is an item with the new name already, calling KIO::CopyJob will open a + // dialog asking for a new name, and if item's parent directory is non-writable, + // KIO::CopyJob will trigger an authentication dialog. In both the cases we want + // the model to update its data only after user confirms the action. So, if any of + // these cases is true then KFileItemModel will update the data when the dir lister + // signals that the file name has changed. QHash data; data.insert(role, value); m_model->setData(index, data); } - KIO::Job * job = KIO::moveAs(oldUrl, newUrl); + KIO::Job * job = KIO::moveAs(oldUrl, newUrl, KIO::PrivilegeExecution); KJobWidgets::setWindow(job, this); KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Rename, {oldUrl}, newUrl, job); job->uiDelegate()->setAutoErrorHandlingEnabled(true); @@ -1681,7 +1685,7 @@ void DolphinView::pasteToUrl(const QUrl& url) { - KIO::PasteJob *job = KIO::paste(QApplication::clipboard()->mimeData(), url); + KIO::PasteJob *job = KIO::paste(QApplication::clipboard()->mimeData(), url, KIO::PrivilegeExecution); KJobWidgets::setWindow(job, this); m_clearSelectionBeforeSelectingNewItems = true; m_markFirstNewlySelectedItemAsCurrent = true; diff --git a/src/views/draganddrophelper.cpp b/src/views/draganddrophelper.cpp --- a/src/views/draganddrophelper.cpp +++ b/src/views/draganddrophelper.cpp @@ -43,7 +43,7 @@ QDBusConnection::sessionBus().call(message); } else { // Drop into a directory or a desktop-file - KIO::DropJob *job = KIO::drop(event, destUrl); + KIO::DropJob *job = KIO::drop(event, destUrl, KIO::PrivilegeExecution); KJobWidgets::setWindow(job, window); return job; }