#include <KFileItemListProperties>
#include <KFormat>
#include <KIO/CopyJob>
-#include <KIO/DeleteJob>
+#include <KIO/DeleteOrTrashJob>
#include <KIO/DropJob>
#include <KIO/JobUiDelegate>
#include <KIO/Paste>
#include <kwidgetsaddons_version.h>
-#include <kio_version.h>
-#if KIO_VERSION >= QT_VERSION_CHECK(5, 100, 0)
-#include <KIO/DeleteOrTrashJob>
-#endif
-
#include <QAbstractItemView>
#include <QActionGroup>
#include <QApplication>
, m_currentItemUrl()
, m_scrollToCurrentItem(false)
, m_restoredContentsPosition()
+ , m_controlWheelAccumulatedDelta(0)
, m_selectedUrls()
, m_clearSelectionBeforeSelectingNewItems(false)
, m_markFirstNewlySelectedItemAsCurrent(false)
m_container = new KItemListContainer(controller, this);
m_container->installEventFilter(this);
+#ifndef QT_NO_ACCESSIBILITY
+ m_view->setAccessibleParentsObject(m_container);
+#endif
setFocusProxy(m_container);
connect(m_container->horizontalScrollBar(), &QScrollBar::valueChanged, this, [=] {
hideToolTip();
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);
+ // #473377: Use a QueuedConnection to avoid modifying KCoreDirLister before KCoreDirListerCache::deleteDir() returns.
+ connect(m_model, &KFileItemModel::currentDirectoryRemoved, this, &DolphinView::currentDirectoryRemoved, Qt::QueuedConnection);
connect(this, &DolphinView::itemCountChanged, this, &DolphinView::updatePlaceholderLabel);
if (active) {
m_container->setFocus();
Q_EMIT activated();
- Q_EMIT writeStateChanged(m_isFolderWritable);
}
}
void DolphinView::setViewMode(Mode mode)
{
if (mode != m_mode) {
+ // Reset scrollbars before changing the view mode.
+ m_container->horizontalScrollBar()->setValue(0);
+ m_container->verticalScrollBar()->setValue(0);
+
ViewProperties props(viewPropertiesUrl());
props.setViewMode(mode);
m_view->setStyle(m_proxyStyle.get());
m_view->setEnabledSelectionToggles(DolphinItemListView::SelectionTogglesEnabled::False);
} else {
- setStyle(QApplication::style());
- m_view->setStyle(QApplication::style());
+ setStyle(nullptr);
+ m_view->setStyle(nullptr);
m_view->setEnabledSelectionToggles(DolphinItemListView::SelectionTogglesEnabled::FollowSetting);
}
m_container->controller()->setSelectionModeEnabled(enabled);
void DolphinView::setSortRole(const QByteArray &role)
{
if (role != sortRole()) {
- updateSortRole(role);
+ ViewProperties props(viewPropertiesUrl());
+ props.setSortRole(role);
+
+ KItemModelBase *model = m_container->controller()->model();
+ model->setSortRole(role);
+
+ Q_EMIT sortRoleChanged(role);
}
}
void DolphinView::setSortOrder(Qt::SortOrder order)
{
if (sortOrder() != order) {
- updateSortOrder(order);
+ ViewProperties props(viewPropertiesUrl());
+ props.setSortOrder(order);
+
+ m_model->setSortOrder(order);
+
+ Q_EMIT sortOrderChanged(order);
}
}
return;
}
- m_statJobForStatusBarText = KIO::statDetails(m_model->rootItem().url(), KIO::StatJob::SourceSide, KIO::StatRecursiveSize, KIO::HideProgressInfo);
+ m_statJobForStatusBarText = KIO::stat(m_model->rootItem().url(), KIO::StatJob::SourceSide, KIO::StatRecursiveSize, KIO::HideProgressInfo);
connect(m_statJobForStatusBarText, &KJob::result, this, &DolphinView::slotStatJobResult);
m_statJobForStatusBarText->start();
}
if (selection == HasSelection) {
// At least 2 items are selected because the case of 1 selected item is handled in
// DolphinView::requestStatusBarText().
- foldersText = i18ncp("@info:status", "1 Folder selected", "%1 Folders selected", folderCount);
- filesText = i18ncp("@info:status", "1 File selected", "%1 Files selected", fileCount);
+ foldersText = i18ncp("@info:status", "1 folder selected", "%1 folders selected", folderCount);
+ filesText = i18ncp("@info:status", "1 file selected", "%1 files selected", fileCount);
} else {
- foldersText = i18ncp("@info:status", "1 Folder", "%1 Folders", folderCount);
- filesText = i18ncp("@info:status", "1 File", "%1 Files", fileCount);
+ foldersText = i18ncp("@info:status", "1 folder", "%1 folders", folderCount);
+ filesText = i18ncp("@info:status", "1 file", "%1 files", fileCount);
}
if (fileCount > 0 && folderCount > 0) {
} else if (folderCount > 0) {
summary = foldersText;
} else {
- summary = i18nc("@info:status", "0 Folders, 0 Files");
+ summary = i18nc("@info:status", "0 folders, 0 files");
}
Q_EMIT statusBarTextChanged(summary);
}
if (items.count() == 1 && GeneralSettings::renameInline()) {
const int index = m_model->index(items.first());
- QMetaObject::Connection *const connection = new QMetaObject::Connection;
- *connection = connect(m_view, &KItemListView::scrollingStopped, this, [=]() {
- QObject::disconnect(*connection);
- delete connection;
-
- m_view->editRole(index, "text");
+ connect(
+ m_view,
+ &KItemListView::scrollingStopped,
+ this,
+ [this, index]() {
+ m_view->editRole(index, "text");
- hideToolTip();
+ hideToolTip();
- connect(m_view, &DolphinItemListView::roleEditingFinished, this, &DolphinView::slotRoleEditingFinished);
- });
+ connect(m_view, &DolphinItemListView::roleEditingFinished, this, &DolphinView::slotRoleEditingFinished);
+ },
+ Qt::SingleShotConnection);
m_view->scrollToItem(index);
} else {
{
const QList<QUrl> list = simplifiedSelectedUrls();
-#if KIO_VERSION >= QT_VERSION_CHECK(5, 100, 0)
using Iface = KIO::AskUserActionInterface;
auto *trashJob = new KIO::DeleteOrTrashJob(list, Iface::Trash, Iface::DefaultConfirmation, this);
connect(trashJob, &KJob::result, this, &DolphinView::slotTrashFileFinished);
m_selectNextItem = true;
trashJob->start();
-#else
- KIO::JobUiDelegate uiDelegate;
- uiDelegate.setWindow(window());
- if (uiDelegate.askDeleteConfirmation(list, KIO::JobUiDelegate::Trash, KIO::JobUiDelegate::DefaultConfirmation)) {
- KIO::Job *job = KIO::trash(list);
- KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Trash, list, QUrl(QStringLiteral("trash:/")), job);
- KJobWidgets::setWindow(job, this);
- connect(job, &KIO::Job::result, this, &DolphinView::slotTrashFileFinished);
- }
-#endif
}
void DolphinView::deleteSelectedItems()
{
const QList<QUrl> list = simplifiedSelectedUrls();
-#if KIO_VERSION >= QT_VERSION_CHECK(5, 100, 0)
using Iface = KIO::AskUserActionInterface;
auto *trashJob = new KIO::DeleteOrTrashJob(list, Iface::Delete, Iface::DefaultConfirmation, this);
connect(trashJob, &KJob::result, this, &DolphinView::slotTrashFileFinished);
m_selectNextItem = true;
trashJob->start();
-#else
- KIO::JobUiDelegate uiDelegate;
- uiDelegate.setWindow(window());
- if (uiDelegate.askDeleteConfirmation(list, KIO::JobUiDelegate::Delete, KIO::JobUiDelegate::DefaultConfirmation)) {
- KIO::Job *job = KIO::del(list);
- KJobWidgets::setWindow(job, this);
- connect(job, &KIO::Job::result, this, &DolphinView::slotDeleteFileFinished);
- }
-#endif
}
void DolphinView::cutSelectedItemsToClipboard()
const QMimeDatabase db;
+ m_clearSelectionBeforeSelectingNewItems = true;
+ m_markFirstNewlySelectedItemAsCurrent = true;
+ m_selectJobCreatedItems = true;
+
// Duplicate all selected items and append "copy" to the end of the file name
// but before the filename extension, if present
- QList<QUrl> newSelection;
for (const auto &item : itemList) {
const QUrl originalURL = item.url();
const QString originalDirectoryPath = originalURL.adjusted(QUrl::RemoveFilename).path();
}
KIO::CopyJob *job = KIO::copyAs(originalURL, duplicateURL);
+ job->setAutoRename(true);
KJobWidgets::setWindow(job, this);
- if (job) {
- newSelection << duplicateURL;
- KIO::FileUndoManager::self()->recordCopyJob(job);
- }
+ connect(job, &KIO::CopyJob::result, this, &DolphinView::slotJobResult);
+ connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotItemCreatedFromJob);
+ connect(job, &KIO::CopyJob::copyingLinkDone, this, &DolphinView::slotItemLinkCreatedFromJob);
+ KIO::FileUndoManager::self()->recordCopyJob(job);
}
-
- forceUrlsSelection(newSelection.first(), newSelection);
}
void DolphinView::stopLoading()
if (indexes.count() > 5) {
QString question = i18np("Are you sure you want to open 1 item?", "Are you sure you want to open %1 items?", indexes.count());
-#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
- const int answer = KMessageBox::warningTwoActions(
+ const int answer = KMessageBox::warningContinueCancel(
this,
question,
{},
-#else
- const int answer =
- KMessageBox::warningYesNo(this,
- question,
- {},
-#endif
KGuiItem(i18ncp("@action:button", "Open %1 Item", "Open %1 Items", indexes.count()), QStringLiteral("document-open")),
- KStandardGuiItem::cancel());
-#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
- if (answer != KMessageBox::PrimaryAction) {
-#else
- if (answer != KMessageBox::Yes) {
-#endif
+ KStandardGuiItem::cancel(),
+ QStringLiteral("ConfirmOpenManyFolders"));
+ if (answer != KMessageBox::PrimaryAction && answer != KMessageBox::Continue) {
return;
}
}
} else {
Q_EMIT tabRequested(item.url());
}
+ } else {
+ Q_EMIT fileMiddleClickActivated(item);
}
}
{
ViewProperties props(viewPropertiesUrl());
- QPointer<QMenu> menu = new QMenu(QApplication::activeWindow());
+ QPointer<QMenu> menu = new QMenu(this);
KItemListView *view = m_container->controller()->view();
const QList<QByteArray> visibleRolesSet = view->visibleRoles();
slotItemCreated(to);
}
+void DolphinView::slotItemLinkCreatedFromJob(KIO::Job *, const QUrl &, const QString &, const QUrl &to)
+{
+ slotItemCreated(to);
+}
+
void DolphinView::slotItemCreated(const QUrl &url)
{
if (m_markFirstNewlySelectedItemAsCurrent) {
}
}
+void DolphinView::onDirectoryLoadingCompletedAfterJob()
+{
+ // the model should now contain all the items created by the job
+ m_selectJobCreatedItems = true; // to make sure we overwrite selection
+ // update the view: scroll into View and selection
+ updateViewState();
+ m_selectJobCreatedItems = false;
+ m_selectedUrls.clear();
+}
+
void DolphinView::slotJobResult(KJob *job)
{
if (job->error() && job->error() != KIO::ERR_USER_CANCELED) {
updateSelectionState();
if (!m_selectedUrls.isEmpty()) {
// not all urls were found, the model may not be up to date
- // TODO KF6 replace with Qt::singleShotConnection
- QMetaObject::Connection *const connection = new QMetaObject::Connection;
- *connection = connect(
- m_model,
- &KFileItemModel::directoryLoadingCompleted,
- this,
- [this, connection]() {
- // the model should now contain all the items created by the job
- updateSelectionState();
- m_selectJobCreatedItems = false;
- m_selectedUrls.clear();
- QObject::disconnect(*connection);
- delete connection;
- },
- Qt::UniqueConnection);
+ connect(m_model, &KFileItemModel::directoryLoadingCompleted, this, &DolphinView::onDirectoryLoadingCompletedAfterJob, Qt::SingleShotConnection);
} else {
m_selectJobCreatedItems = false;
m_selectedUrls.clear();
emitStatusBarText(folderCount, fileCount, totalFileSize, NoSelection);
}
-void DolphinView::updateSortRole(const QByteArray &role)
-{
- ViewProperties props(viewPropertiesUrl());
- props.setSortRole(role);
-
- KItemModelBase *model = m_container->controller()->model();
- model->setSortRole(role);
-
- Q_EMIT sortRoleChanged(role);
-}
-
-void DolphinView::updateSortOrder(Qt::SortOrder order)
-{
- ViewProperties props(viewPropertiesUrl());
- props.setSortOrder(order);
-
- m_model->setSortOrder(order);
-
- Q_EMIT sortOrderChanged(order);
-}
-
void DolphinView::updateSortFoldersFirst(bool foldersFirst)
{
ViewProperties props(viewPropertiesUrl());
// scroll to current item and reset the state
if (m_scrollToCurrentItem) {
- m_view->scrollToItem(currentIndex);
+ m_view->scrollToItem(currentIndex, KItemListView::ViewItemPosition::Middle);
m_scrollToCurrentItem = false;
}
m_currentItemUrl = QUrl();
Q_UNUSED(previous)
Q_ASSERT(m_model->sortRole() == current);
- ViewProperties props(viewPropertiesUrl());
- props.setSortRole(current);
-
- Q_EMIT sortRoleChanged(current);
+ setSortRole(current);
}
void DolphinView::slotVisibleRolesChangedByHeader(const QList<QByteArray> ¤t, const QList<QByteArray> &previous)
if (!hiddenFilesShown() && newName.startsWith(QLatin1Char('.')) && !oldItem.name().startsWith(QLatin1Char('.'))) {
KGuiItem yesGuiItem(i18nc("@action:button", "Rename and Hide"), QStringLiteral("view-hidden"));
-#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
const auto code =
KMessageBox::questionTwoActions(this,
-#else
- const auto code =
- KMessageBox::questionYesNo(this,
-#endif
oldItem.isFile() ? i18n("Adding a dot to the beginning of this file's name will hide it from view.\n"
"Do you still want to rename it?")
: i18n("Adding a dot to the beginning of this folder's name will hide it from view.\n"
KStandardGuiItem::cancel(),
QStringLiteral("ConfirmHide"));
-#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
if (code == KMessageBox::SecondaryAction) {
-#else
- if (code == KMessageBox::No) {
-#endif
return;
}
}
KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Rename, {oldUrl}, newUrl, job);
job->uiDelegate()->setAutoErrorHandlingEnabled(true);
- forceUrlsSelection(newUrl, {newUrl});
-
if (!newNameExistsAlready) {
+ forceUrlsSelection(newUrl, {newUrl});
+
// Only connect the result signal if there is no item with the new name
// in the model yet, see bug 328262.
connect(job, &KJob::result, this, &DolphinView::slotRenamingResult);
}
}
+bool DolphinView::isFolderWritable() const
+{
+ return m_isFolderWritable;
+}
+
QUrl DolphinView::viewPropertiesUrl() const
{
if (m_viewPropertiesContext.isEmpty()) {
if (clipboard == nullptr) {
return;
}
- clipboard->setText(path);
+ clipboard->setText(QDir::toNativeSeparators(path));
}
void DolphinView::slotIncreaseZoom()
void DolphinView::showLoadingPlaceholder()
{
- m_placeholderLabel->setText(i18n("Loading..."));
+ m_placeholderLabel->setText(i18n("Loading…"));
m_placeholderLabel->setVisible(true);
}
}
return false;
}
+
+#include "moc_dolphinview.cpp"