#include "dolphinview.h"
-#include <config-baloo.h>
-
-#include <QAbstractItemView>
-#include <QApplication>
-#include <QBoxLayout>
-#include <QClipboard>
-#include <QDropEvent>
-#include <QGraphicsSceneDragDropEvent>
-#include <QKeyEvent>
-#include <QItemSelection>
-#include <QTimer>
-#include <QScrollBar>
-#include <QPointer>
-#include <QMenu>
-
-#include <KDesktopFile>
-#include <KProtocolManager>
-#include <KActionCollection>
-#include <KColorScheme>
-#include <KDirModel>
-#include <KIconEffect>
-#include <KFileItem>
-#include <KFileItemListProperties>
-#include <KLocale>
-#include <kitemviews/kfileitemmodel.h>
-#include <kitemviews/kfileitemlistview.h>
-#include <kitemviews/kitemlistcontainer.h>
-#include <kitemviews/kitemlistheader.h>
-#include <kitemviews/kitemlistselectionmanager.h>
-#include <kitemviews/kitemlistview.h>
-#include <kitemviews/kitemlistcontroller.h>
-#include <KIO/DeleteJob>
-#include <KIO/JobUiDelegate>
-#include <KIO/NetAccess>
-#include <KIO/PreviewJob>
-#include <KJob>
-#include <KMenu>
-#include <KGlobal>
-#include <KMessageBox>
-#include <KJobWidgets>
-#include <konq_fileitemcapabilities.h>
-#include <konq_operations.h>
-#include <konqmimedata.h>
-#include <KToggleAction>
-#include <KUrl>
-
-#include "dolphinnewfilemenuobserver.h"
#include "dolphin_detailsmodesettings.h"
#include "dolphin_generalsettings.h"
#include "dolphinitemlistview.h"
+#include "dolphinnewfilemenuobserver.h"
#include "draganddrophelper.h"
-#include "renamedialog.h"
+#include "kitemviews/kfileitemlistview.h"
+#include "kitemviews/kfileitemmodel.h"
+#include "kitemviews/kitemlistcontainer.h"
+#include "kitemviews/kitemlistcontroller.h"
+#include "kitemviews/kitemlistheader.h"
+#include "kitemviews/kitemlistselectionmanager.h"
#include "versioncontrol/versioncontrolobserver.h"
-#include "viewmodecontroller.h"
#include "viewproperties.h"
#include "views/tooltips/tooltipmanager.h"
#include "zoomlevelinfo.h"
#ifdef HAVE_BALOO
- #include <KF5/Baloo/indexerconfig.h>
+#include <Baloo/IndexerConfig>
#endif
+#include <KColorScheme>
+#include <KDesktopFile>
+#include <KDirModel>
+#include <KFileItemListProperties>
+#include <KFormat>
+#include <KIO/CopyJob>
+#include <KIO/DeleteJob>
+#include <KIO/DropJob>
+#include <KIO/JobUiDelegate>
+#include <KIO/Paste>
+#include <KIO/PasteJob>
+#include <KIO/PreviewJob>
+#include <KIO/RenameFileDialog>
+#include <KJobWidgets>
+#include <KLocalizedString>
+#include <KMessageBox>
+#include <KProtocolManager>
-namespace {
- const int MaxModeEnum = DolphinView::CompactView;
-};
+#include <QAbstractItemView>
+#include <QApplication>
+#include <QClipboard>
+#include <QDropEvent>
+#include <QGraphicsSceneDragDropEvent>
+#include <QMenu>
+#include <QMimeDatabase>
+#include <QPixmapCache>
+#include <QPointer>
+#include <QScrollBar>
+#include <QSize>
+#include <QTimer>
+#include <QVBoxLayout>
-DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
+DolphinView::DolphinView(const QUrl& url, QWidget* parent) :
QWidget(parent),
m_active(true),
m_tabsForFiles(false),
m_viewPropertiesContext(),
m_mode(DolphinView::IconsView),
m_visibleRoles(),
- m_topLayout(0),
- m_model(0),
- m_view(0),
- m_container(0),
- m_toolTipManager(0),
- m_selectionChangedTimer(0),
+ m_topLayout(nullptr),
+ m_model(nullptr),
+ m_view(nullptr),
+ m_container(nullptr),
+ m_toolTipManager(nullptr),
+ m_selectionChangedTimer(nullptr),
m_currentItemUrl(),
m_scrollToCurrentItem(false),
m_restoredContentsPosition(),
m_selectedUrls(),
m_clearSelectionBeforeSelectingNewItems(false),
m_markFirstNewlySelectedItemAsCurrent(false),
- m_versionControlObserver(0)
+ m_versionControlObserver(nullptr),
+ m_twoClicksRenamingTimer(nullptr)
{
m_topLayout = new QVBoxLayout(this);
m_topLayout->setSpacing(0);
- m_topLayout->setMargin(0);
+ m_topLayout->setContentsMargins(0, 0, 0, 0);
// When a new item has been created by the "Create New..." menu, the item should
// get selected and it must be assured that the item will get visible. As the
m_model = new KFileItemModel(this);
m_view = new DolphinItemListView();
m_view->setEnabledSelectionToggles(GeneralSettings::showSelectionToggle());
- m_view->setVisibleRoles(QList<QByteArray>() << "text");
+ m_view->setVisibleRoles({"text"});
applyModeToView();
KItemListController* controller = new KItemListController(m_model, m_view, this);
m_container = new KItemListContainer(controller, this);
m_container->installEventFilter(this);
setFocusProxy(m_container);
- connect(m_container->horizontalScrollBar(), &QScrollBar::valueChanged, this, &DolphinView::hideToolTip);
- connect(m_container->verticalScrollBar(), &QScrollBar::valueChanged, this, &DolphinView::hideToolTip);
+ connect(m_container->horizontalScrollBar(), &QScrollBar::valueChanged, this, [=] { hideToolTip(); });
+ connect(m_container->verticalScrollBar(), &QScrollBar::valueChanged, this, [=] { hideToolTip(); });
controller->setSelectionBehavior(KItemListController::MultiSelection);
connect(controller, &KItemListController::itemActivated, this, &DolphinView::slotItemActivated);
connect(controller, &KItemListController::itemDropEvent, this, &DolphinView::slotItemDropEvent);
connect(controller, &KItemListController::escapePressed, this, &DolphinView::stopLoading);
connect(controller, &KItemListController::modelChanged, this, &DolphinView::slotModelChanged);
+ connect(controller, &KItemListController::selectedItemTextPressed, this, &DolphinView::slotSelectedItemTextPressed);
connect(m_model, &KFileItemModel::directoryLoadingStarted, this, &DolphinView::slotDirectoryLoadingStarted);
connect(m_model, &KFileItemModel::directoryLoadingCompleted, this, &DolphinView::slotDirectoryLoadingCompleted);
this, &DolphinView::slotVisibleRolesChangedByHeader);
connect(m_view, &DolphinItemListView::roleEditingCanceled,
this, &DolphinView::slotRoleEditingCanceled);
- connect(m_view->header(), &KItemListHeader::columnWidthChanged,
- this, &DolphinView::slotHeaderColumnWidthChanged);
+ connect(m_view->header(), &KItemListHeader::columnWidthChangeFinished,
+ this, &DolphinView::slotHeaderColumnWidthChangeFinished);
KItemListSelectionManager* selectionManager = controller->selectionManager();
connect(selectionManager, &KItemListSelectionManager::selectionChanged,
this, &DolphinView::slotSelectionChanged);
+#ifdef HAVE_BALOO
m_toolTipManager = new ToolTipManager(this);
+ connect(m_toolTipManager, &ToolTipManager::urlActivated, this, &DolphinView::urlActivated);
+#endif
m_versionControlObserver = new VersionControlObserver(this);
+ m_versionControlObserver->setView(this);
m_versionControlObserver->setModel(m_model);
connect(m_versionControlObserver, &VersionControlObserver::infoMessage, this, &DolphinView::infoMessage);
connect(m_versionControlObserver, &VersionControlObserver::errorMessage, this, &DolphinView::errorMessage);
connect(m_versionControlObserver, &VersionControlObserver::operationCompletedMessage, this, &DolphinView::operationCompletedMessage);
+ m_twoClicksRenamingTimer = new QTimer(this);
+ m_twoClicksRenamingTimer->setSingleShot(true);
+ connect(m_twoClicksRenamingTimer, &QTimer::timeout, this, &DolphinView::slotTwoClicksRenamingTimerTimeout);
+
applyViewProperties();
m_topLayout->addWidget(m_container);
{
}
-KUrl DolphinView::url() const
+QUrl DolphinView::url() const
{
return m_url;
}
m_active = active;
- QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
- if (!active) {
- color.setAlpha(150);
- }
-
- QWidget* viewport = m_container->viewport();
- if (viewport) {
- QPalette palette;
- palette.setColor(viewport->backgroundRole(), color);
- viewport->setPalette(palette);
- }
-
- update();
+ updatePalette();
if (active) {
m_container->setFocus();
const KFileItemList itemList = selectedItems();
m_selectedUrls.clear();
- m_selectedUrls = KUrl::List(itemList.urlList());
+ m_selectedUrls = itemList.urlList();
ViewProperties props(viewPropertiesUrl());
props.setHiddenFilesShown(show);
const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
KFileItemList selectedItems;
- foreach (int index, selectionManager->selectedItems()) {
+ const auto items = selectionManager->selectedItems();
+ selectedItems.reserve(items.count());
+ for (int index : items) {
selectedItems.append(m_model->fileItem(index));
}
return selectedItems;
return selectionManager->selectedItems().count();
}
-void DolphinView::markUrlsAsSelected(const QList<KUrl>& urls)
+void DolphinView::markUrlsAsSelected(const QList<QUrl>& urls)
{
m_selectedUrls = urls;
}
-void DolphinView::markUrlAsCurrent(const KUrl& url)
+void DolphinView::markUrlAsCurrent(const QUrl &url)
{
m_currentItemUrl = url;
m_scrollToCurrentItem = true;
}
-void DolphinView::selectItems(const QRegExp& pattern, bool enabled)
+void DolphinView::selectItems(const QRegularExpression ®exp, bool enabled)
{
const KItemListSelectionManager::SelectionMode mode = enabled
? KItemListSelectionManager::Select
for (int index = 0; index < m_model->count(); index++) {
const KFileItem item = m_model->fileItem(index);
- if (pattern.exactMatch(item.text())) {
+ if (regexp.match(item.text()).hasMatch()) {
// An alternative approach would be to store the matching items in a KItemSet and
// select them in one go after the loop, but we'd need a new function
// KItemListSelectionManager::setSelected(KItemSet, SelectionMode mode)
QDataStream saveStream(&viewState, QIODevice::WriteOnly);
saveState(saveStream);
- const KFileItemList itemList = selectedItems();
- m_selectedUrls.clear();
- m_selectedUrls = KUrl::List(itemList.urlList());
-
setUrl(url());
loadDirectory(url(), true);
{
const int oldZoomLevel = m_view->zoomLevel();
- GeneralSettings::self()->readConfig();
+ GeneralSettings::self()->load();
m_view->readSettings();
applyViewProperties();
void DolphinView::writeSettings()
{
- GeneralSettings::self()->writeConfig();
+ GeneralSettings::self()->save();
m_view->writeSettings();
}
if (fileCount > 0 && folderCount > 0) {
summary = i18nc("@info:status folders, files (size)", "%1, %2 (%3)",
foldersText, filesText,
- KGlobal::locale()->formatByteSize(totalFileSize));
+ KFormat().formatByteSize(totalFileSize));
} else if (fileCount > 0) {
summary = i18nc("@info:status files (size)", "%1 (%2)",
filesText,
- KGlobal::locale()->formatByteSize(totalFileSize));
+ KFormat().formatByteSize(totalFileSize));
} else if (folderCount > 0) {
summary = foldersText;
} else {
return actions;
}
-void DolphinView::setUrl(const KUrl& url)
+void DolphinView::setUrl(const QUrl& url)
{
if (url == m_url) {
return;
clearSelection();
- emit urlAboutToBeChanged(url);
m_url = url;
hideToolTip();
connect(m_view, &DolphinItemListView::roleEditingFinished,
this, &DolphinView::slotRoleEditingFinished);
} else {
- RenameDialog* dialog = new RenameDialog(this, items);
- dialog->setAttribute(Qt::WA_DeleteOnClose);
- dialog->show();
- dialog->raise();
- dialog->activateWindow();
+ KIO::RenameFileDialog* dialog = new KIO::RenameFileDialog(items, this);
+ connect(dialog, &KIO::RenameFileDialog::renamingFinished,
+ this, &DolphinView::slotRenameDialogRenamingFinished);
+
+ dialog->open();
}
// Assure that the current index remains visible when KFileItemModel
void DolphinView::trashSelectedItems()
{
- const KUrl::List list = simplifiedSelectedUrls();
- KonqOperations::del(this, KonqOperations::TRASH, list);
+ const QList<QUrl> list = simplifiedSelectedUrls();
+ 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);
+ }
}
void DolphinView::deleteSelectedItems()
{
- const KUrl::List list = simplifiedSelectedUrls();
- const bool del = KonqOperations::askDeleteConfirmation(list,
- KonqOperations::DEL,
- KonqOperations::DEFAULT_CONFIRMATION,
- this);
+ const QList<QUrl> list = simplifiedSelectedUrls();
- if (del) {
+ KIO::JobUiDelegate uiDelegate;
+ uiDelegate.setWindow(window());
+ if (uiDelegate.askDeleteConfirmation(list, KIO::JobUiDelegate::Delete, KIO::JobUiDelegate::DefaultConfirmation)) {
KIO::Job* job = KIO::del(list);
- if (job->ui()) {
- KJobWidgets::setWindow(job, this);
- }
+ KJobWidgets::setWindow(job, this);
connect(job, &KIO::Job::result,
this, &DolphinView::slotDeleteFileFinished);
}
void DolphinView::cutSelectedItems()
{
QMimeData* mimeData = selectionMimeData();
- KonqMimeData::addIsCutSelection(mimeData, true);
+ KIO::setClipboardDataCut(mimeData, true);
QApplication::clipboard()->setMimeData(mimeData);
}
-void DolphinView::copySelectedItems()
+void DolphinView::copySelectedItemsToClipboard()
{
QMimeData* mimeData = selectionMimeData();
QApplication::clipboard()->setMimeData(mimeData);
}
}
+void DolphinView::duplicateSelectedItems()
+{
+ const KFileItemList itemList = selectedItems();
+ if (itemList.isEmpty()) {
+ return;
+ }
+
+ const QMimeDatabase db;
+
+ // 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();
+ const QString originalFileName = item.name();
+
+ QString extension = db.suffixForFileName(originalFileName);
+
+ QUrl duplicateURL = originalURL;
+
+ // No extension; new filename is "<oldfilename> copy"
+ if (extension.isEmpty()) {
+ duplicateURL.setPath(originalDirectoryPath + i18nc("<filename> copy", "%1 copy", originalFileName));
+ // There's an extension; new filename is "<oldfilename> copy.<extension>"
+ } else {
+ // Need to add a dot since QMimeDatabase::suffixForFileName() doesn't include it
+ extension = QLatin1String(".") + extension;
+ const QString originalFilenameWithoutExtension = originalFileName.chopped(extension.size());
+ // Preserve file's original filename extension in case the casing differs
+ // from what QMimeDatabase::suffixForFileName() returned
+ const QString originalExtension = originalFileName.right(extension.size());
+ duplicateURL.setPath(originalDirectoryPath + i18nc("<filename> copy", "%1 copy", originalFilenameWithoutExtension) + originalExtension);
+ }
+
+ KIO::CopyJob* job = KIO::copyAs(originalURL, duplicateURL, KIO::HideProgressInfo);
+ KJobWidgets::setWindow(job, this);
+
+ if (job) {
+ newSelection << duplicateURL;
+ KIO::FileUndoManager::self()->recordCopyJob(job);
+ }
+ }
+
+ forceUrlsSelection(newSelection.first(), newSelection);
+}
+
void DolphinView::stopLoading()
{
m_model->cancelDirectoryLoading();
}
+void DolphinView::updatePalette()
+{
+ QColor color = KColorScheme(isActiveWindow() ? QPalette::Active : QPalette::Inactive, KColorScheme::View).background().color();
+ if (!m_active) {
+ color.setAlpha(150);
+ }
+
+ QWidget* viewport = m_container->viewport();
+ if (viewport) {
+ QPalette palette;
+ palette.setColor(viewport->backgroundRole(), color);
+ viewport->setPalette(palette);
+ }
+
+ update();
+}
+
+void DolphinView::abortTwoClicksRenaming()
+{
+ m_twoClicksRenamingItemUrl.clear();
+ m_twoClicksRenamingTimer->stop();
+}
+
bool DolphinView::eventFilter(QObject* watched, QEvent* event)
{
switch (event->type()) {
+ case QEvent::PaletteChange:
+ updatePalette();
+ QPixmapCache::clear();
+ break;
+
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ updatePalette();
+ break;
+
+ case QEvent::KeyPress:
+ hideToolTip(ToolTipManager::HideBehavior::Instantly);
+ if (GeneralSettings::useTabForSwitchingSplitView()) {
+ QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
+ if (keyEvent->key() == Qt::Key_Tab && keyEvent->modifiers() == Qt::NoModifier) {
+ emit toggleActiveViewRequested();
+ return true;
+ }
+ }
+ break;
case QEvent::FocusIn:
if (watched == m_container) {
setActive(true);
case QEvent::GraphicsSceneDragEnter:
if (watched == m_view) {
m_dragging = true;
+ abortTwoClicksRenaming();
}
break;
bool DolphinView::event(QEvent* event)
{
- /* See Bug 297355
- * Dolphin leaves file preview tooltips open even when is not visible.
- *
- * Hide tool-tip when Dolphin loses focus.
- */
if (event->type() == QEvent::WindowDeactivate) {
+ /* See Bug 297355
+ * Dolphin leaves file preview tooltips open even when is not visible.
+ *
+ * Hide tool-tip when Dolphin loses focus.
+ */
hideToolTip();
+ abortTwoClicksRenaming();
}
return QWidget::event(event);
void DolphinView::slotItemActivated(int index)
{
+ abortTwoClicksRenaming();
+
const KFileItem item = m_model->fileItem(index);
if (!item.isNull()) {
emit itemActivated(item);
{
Q_ASSERT(indexes.count() >= 2);
+ abortTwoClicksRenaming();
+
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());
const int answer = KMessageBox::warningYesNo(this, question);
KFileItemList items;
items.reserve(indexes.count());
- foreach (int index, indexes) {
+ for (int index : indexes) {
KFileItem item = m_model->fileItem(index);
- const KUrl& url = openItemAsFolderUrl(item);
+ const QUrl& url = openItemAsFolderUrl(item);
if (!url.isEmpty()) { // Open folders in new tabs
- emit tabRequested(url);
+ emit tabRequested(url, DolphinTabWidget::AfterLastTab);
} else {
items.append(item);
}
void DolphinView::slotItemMiddleClicked(int index)
{
const KFileItem& item = m_model->fileItem(index);
- const KUrl& url = openItemAsFolderUrl(item);
+ const QUrl& url = openItemAsFolderUrl(item);
if (!url.isEmpty()) {
- emit tabRequested(url);
+ emit tabRequested(url, DolphinTabWidget::AfterCurrentTab);
} else if (isTabsForFilesEnabled()) {
- emit tabRequested(item.url());
+ emit tabRequested(item.url(), DolphinTabWidget::AfterCurrentTab);
}
}
{
ViewProperties props(viewPropertiesUrl());
- QPointer<KMenu> menu = new KMenu(QApplication::activeWindow());
+ QPointer<QMenu> menu = new QMenu(QApplication::activeWindow());
KItemListView* view = m_container->controller()->view();
const QSet<QByteArray> visibleRolesSet = view->visibleRoles().toSet();
#endif
QString groupName;
- QMenu* groupMenu = 0;
+ QMenu* groupMenu = nullptr;
// Add all roles to the menu that can be shown or hidden by the user
const QList<KFileItemModel::RoleInfo> rolesInfo = KFileItemModel::rolesInformation();
}
const QString text = m_model->roleDescription(info.role);
- QAction* action = 0;
+ QAction* action = nullptr;
if (info.group.isEmpty()) {
action = menu->addAction(text);
} else {
// Apply the current column-widths as custom column-widths and turn
// off the automatic resizing of the columns
QList<int> columnWidths;
+ columnWidths.reserve(view->visibleRoles().count());
foreach (const QByteArray& role, view->visibleRoles()) {
columnWidths.append(header->columnWidth(role));
}
QList<int> columnWidths;
if (!header->automaticColumnResizing()) {
+ columnWidths.reserve(view->visibleRoles().count());
foreach (const QByteArray& role, view->visibleRoles()) {
columnWidths.append(header->columnWidth(role));
}
delete menu;
}
-void DolphinView::slotHeaderColumnWidthChanged(const QByteArray& role, qreal current, qreal previous)
+void DolphinView::slotHeaderColumnWidthChangeFinished(const QByteArray& role, qreal current)
{
- Q_UNUSED(previous);
-
const QList<QByteArray> visibleRoles = m_view->visibleRoles();
ViewProperties props(viewPropertiesUrl());
const QPoint pos = m_container->mapToGlobal(itemRect.topLeft().toPoint());
itemRect.moveTo(pos);
- m_toolTipManager->showToolTip(item, itemRect);
+#ifdef HAVE_BALOO
+ m_toolTipManager->showToolTip(item, itemRect, nativeParentWidget()->windowHandle());
+#endif
}
emit requestItemInfo(item);
void DolphinView::slotItemUnhovered(int index)
{
- Q_UNUSED(index);
+ Q_UNUSED(index)
hideToolTip();
emit requestItemInfo(KFileItem());
}
void DolphinView::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event)
{
- KUrl destUrl;
+ QUrl destUrl;
KFileItem destItem = m_model->fileItem(index);
if (destItem.isNull() || (!destItem.isDir() && !destItem.isDesktopFile())) {
// Use the URL of the view as drop target if the item is no directory
destUrl = url();
} else {
// The item represents a directory or desktop-file
- destUrl = destItem.url();
+ destUrl = destItem.mostLocalUrl();
}
QDropEvent dropEvent(event->pos().toPoint(),
event->mimeData(),
event->buttons(),
event->modifiers());
+ dropUrls(destUrl, &dropEvent, this);
- QString error;
- KonqOperations* op = DragAndDropHelper::dropUrls(destItem, destUrl, &dropEvent, error);
- if (!error.isEmpty()) {
- emit infoMessage(error);
- }
+ setActive(true);
+}
- if (op && destUrl == url()) {
- // Mark the dropped urls as selected.
- m_clearSelectionBeforeSelectingNewItems = true;
- m_markFirstNewlySelectedItemAsCurrent = true;
- connect(op, static_cast<void(KonqOperations::*)(const KUrl::List&)>(&KonqOperations::aboutToCreate), this, &DolphinView::slotAboutToCreate);
- }
+void DolphinView::dropUrls(const QUrl &destUrl, QDropEvent *dropEvent, QWidget *dropWidget)
+{
+ KIO::DropJob* job = DragAndDropHelper::dropUrls(destUrl, dropEvent, dropWidget);
- setActive(true);
+ if (job) {
+ connect(job, &KIO::DropJob::result, this, &DolphinView::slotPasteJobResult);
+
+ if (destUrl == url()) {
+ // Mark the dropped urls as selected.
+ m_clearSelectionBeforeSelectingNewItems = true;
+ m_markFirstNewlySelectedItemAsCurrent = true;
+ connect(job, &KIO::DropJob::itemCreated, this, &DolphinView::slotItemCreated);
+ }
+ }
}
void DolphinView::slotModelChanged(KItemModelBase* current, KItemModelBase* previous)
{
- if (previous != 0) {
+ if (previous != nullptr) {
Q_ASSERT(qobject_cast<KFileItemModel*>(previous));
KFileItemModel* fileItemModel = static_cast<KFileItemModel*>(previous);
disconnect(fileItemModel, &KFileItemModel::directoryLoadingCompleted, this, &DolphinView::slotDirectoryLoadingCompleted);
- m_versionControlObserver->setModel(0);
+ m_versionControlObserver->setModel(nullptr);
}
if (current) {
void DolphinView::slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons)
{
- Q_UNUSED(itemIndex);
+ Q_UNUSED(itemIndex)
hideToolTip();
- // TODO: Qt5: Replace Qt::XButton1 by Qt::BackButton and Qt::XButton2 by Qt::ForwardButton
- if (buttons & Qt::XButton1) {
+ if (buttons & Qt::BackButton) {
emit goBackRequested();
- } else if (buttons & Qt::XButton2) {
+ } else if (buttons & Qt::ForwardButton) {
emit goForwardRequested();
}
}
-void DolphinView::slotAboutToCreate(const KUrl::List& urls)
+void DolphinView::slotSelectedItemTextPressed(int index)
{
- if (!urls.isEmpty()) {
- if (m_markFirstNewlySelectedItemAsCurrent) {
- markUrlAsCurrent(urls.first());
- m_markFirstNewlySelectedItemAsCurrent = false;
+ if (GeneralSettings::renameInline() && !m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)) {
+ const KFileItem item = m_model->fileItem(index);
+ const KFileItemListProperties capabilities(KFileItemList() << item);
+ if (capabilities.supportsMoving()) {
+ m_twoClicksRenamingItemUrl = item.url();
+ m_twoClicksRenamingTimer->start(QApplication::doubleClickInterval());
}
- m_selectedUrls << KUrl::List(KDirModel::simplifiedUrlList(urls));
+ }
+}
+
+void DolphinView::slotItemCreated(const QUrl& url)
+{
+ if (m_markFirstNewlySelectedItemAsCurrent) {
+ markUrlAsCurrent(url);
+ m_markFirstNewlySelectedItemAsCurrent = false;
+ }
+ m_selectedUrls << url;
+}
+
+void DolphinView::slotPasteJobResult(KJob *job)
+{
+ if (job->error()) {
+ emit errorMessage(job->errorString());
+ }
+ if (!m_selectedUrls.isEmpty()) {
+ m_selectedUrls = KDirModel::simplifiedUrlList(m_selectedUrls);
}
}
QPair<bool, QString> DolphinView::pasteInfo() const
{
- return KonqOperations::pasteInfo(url());
+ const QMimeData *mimeData = QApplication::clipboard()->mimeData();
+ QPair<bool, QString> info;
+ info.second = KIO::pasteActionText(mimeData, &info.first, rootItem());
+ return info;
}
void DolphinView::setTabsForFilesEnabled(bool tabsForFiles)
void DolphinView::restoreState(QDataStream& stream)
{
+ // Read the version number of the view state and check if the version is supported.
+ quint32 version = 0;
+ stream >> version;
+ if (version != 1) {
+ // The version of the view state isn't supported, we can't restore it.
+ return;
+ }
+
// Restore the current item that had the keyboard focus
stream >> m_currentItemUrl;
+ // Restore the previously selected items
+ stream >> m_selectedUrls;
+
// Restore the view position
stream >> m_restoredContentsPosition;
// Restore expanded folders (only relevant for the details view - will be ignored by the view in other view modes)
- QSet<KUrl> urls;
+ QSet<QUrl> urls;
stream >> urls;
m_model->restoreExpandedDirectories(urls);
}
void DolphinView::saveState(QDataStream& stream)
{
+ stream << quint32(1); // View state version
+
// Save the current item that has the keyboard focus
const int currentIndex = m_container->controller()->selectionManager()->currentItem();
if (currentIndex != -1) {
KFileItem item = m_model->fileItem(currentIndex);
Q_ASSERT(!item.isNull()); // If the current index is valid a item must exist
- KUrl currentItemUrl = item.url();
+ QUrl currentItemUrl = item.url();
stream << currentItemUrl;
} else {
- stream << KUrl();
+ stream << QUrl();
}
+ // Save the selected urls
+ stream << selectedItems().urlList();
+
// Save view position
const qreal x = m_container->horizontalScrollBar()->value();
const qreal y = m_container->verticalScrollBar()->value();
return m_viewPropertiesContext;
}
-KUrl DolphinView::openItemAsFolderUrl(const KFileItem& item, const bool browseThroughArchives)
+QUrl DolphinView::openItemAsFolderUrl(const KFileItem& item, const bool browseThroughArchives)
{
if (item.isNull()) {
- return KUrl();
+ return QUrl();
}
- KUrl url = item.targetUrl();
+ QUrl url = item.targetUrl();
if (item.isDir()) {
return url;
// open OpenDocument files as zip folders...
const QString& protocol = KProtocolManager::protocolForArchiveMimetype(mimetype);
if (!protocol.isEmpty()) {
- url.setProtocol(protocol);
+ url.setScheme(protocol);
return url;
}
}
if (desktopFile.hasLinkType()) {
const QString linkUrl = desktopFile.readUrl();
if (!linkUrl.startsWith(QLatin1String("http"))) {
- return linkUrl;
+ return QUrl::fromUserInput(linkUrl);
}
}
}
}
- return KUrl();
+ return QUrl();
+}
+
+void DolphinView::resetZoomLevel()
+{
+ ViewModeSettings::ViewMode mode;
+
+ switch (m_mode) {
+ case IconsView: mode = ViewModeSettings::IconsMode; break;
+ case CompactView: mode = ViewModeSettings::CompactMode; break;
+ case DetailsView: mode = ViewModeSettings::DetailsMode; break;
+ }
+ const ViewModeSettings settings(mode);
+ const QSize iconSize = QSize(settings.iconSize(), settings.iconSize());
+ setZoomLevel(ZoomLevelInfo::zoomLevelForIconSize(iconSize));
}
-void DolphinView::observeCreatedItem(const KUrl& url)
+void DolphinView::observeCreatedItem(const QUrl& url)
{
if (m_active) {
- clearSelection();
- markUrlAsCurrent(url);
- markUrlsAsSelected(QList<KUrl>() << url);
+ forceUrlsSelection(url, {url});
}
}
-void DolphinView::slotDirectoryRedirection(const KUrl& oldUrl, const KUrl& newUrl)
+void DolphinView::slotDirectoryRedirection(const QUrl& oldUrl, const QUrl& newUrl)
{
- if (oldUrl.equals(url(), KUrl::CompareWithoutTrailingSlash)) {
+ if (oldUrl.matches(url(), QUrl::StripTrailingSlash)) {
emit redirection(oldUrl, newUrl);
m_url = newUrl; // #186947
}
void DolphinView::updateViewState()
{
- if (m_currentItemUrl != KUrl()) {
+ if (m_currentItemUrl != QUrl()) {
KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
- const int currentIndex = m_model->index(m_currentItemUrl);
- if (currentIndex != -1) {
- selectionManager->setCurrentItem(currentIndex);
-
- // scroll to current item and reset the state
- if (m_scrollToCurrentItem) {
- m_view->scrollToItem(currentIndex);
- m_scrollToCurrentItem = false;
- }
- m_currentItemUrl = KUrl();
- } else {
- selectionManager->setCurrentItem(0);
+ // if there is a selection already, leave it that way
+ if (!selectionManager->hasSelection()) {
+ const int currentIndex = m_model->index(m_currentItemUrl);
+ if (currentIndex != -1) {
+ selectionManager->setCurrentItem(currentIndex);
+
+ // scroll to current item and reset the state
+ if (m_scrollToCurrentItem) {
+ m_view->scrollToItem(currentIndex);
+ m_scrollToCurrentItem = false;
+ }
+ } else {
+ selectionManager->setCurrentItem(0);
+ }
}
+
+ m_currentItemUrl = QUrl();
}
if (!m_restoredContentsPosition.isNull()) {
if (!m_selectedUrls.isEmpty()) {
KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
- if (m_clearSelectionBeforeSelectingNewItems) {
- selectionManager->clearSelection();
- m_clearSelectionBeforeSelectingNewItems = false;
- }
+ // if there is a selection already, leave it that way
+ if (!selectionManager->hasSelection()) {
+ if (m_clearSelectionBeforeSelectingNewItems) {
+ selectionManager->clearSelection();
+ m_clearSelectionBeforeSelectingNewItems = false;
+ }
- KItemSet selectedItems = selectionManager->selectedItems();
+ KItemSet selectedItems = selectionManager->selectedItems();
- QList<KUrl>::iterator it = m_selectedUrls.begin();
- while (it != m_selectedUrls.end()) {
- const int index = m_model->index(*it);
- if (index >= 0) {
- selectedItems.insert(index);
- it = m_selectedUrls.erase(it);
- } else {
- ++it;
+ QList<QUrl>::iterator it = m_selectedUrls.begin();
+ while (it != m_selectedUrls.end()) {
+ const int index = m_model->index(*it);
+ if (index >= 0) {
+ selectedItems.insert(index);
+ it = m_selectedUrls.erase(it);
+ } else {
+ ++it;
+ }
}
- }
- selectionManager->setSelectedItems(selectedItems);
+ selectionManager->beginAnchoredSelection(selectionManager->currentItem());
+ selectionManager->setSelectedItems(selectedItems);
+ }
}
}
-void DolphinView::hideToolTip()
+void DolphinView::hideToolTip(const ToolTipManager::HideBehavior behavior)
{
+#ifdef HAVE_BALOO
if (GeneralSettings::showToolTips()) {
- m_toolTipManager->hideToolTip();
+ m_toolTipManager->hideToolTip(behavior);
}
+#endif
}
void DolphinView::calculateItemCount(int& fileCount,
KIO::filesize_t& totalFileSize) const
{
const int itemCount = m_model->count();
+
+ bool countFileSize = true;
+
+ // In case we have a precomputed value
+ const auto job = KIO::statDetails(m_model->rootItem().url(), KIO::StatJob::SourceSide, KIO::StatRecursiveSize);
+ job->exec();
+ const auto entry = job->statResult();
+ if (entry.contains(KIO::UDSEntry::UDS_RECURSIVE_SIZE)) {
+ totalFileSize = static_cast<KIO::filesize_t>(entry.numberValue(KIO::UDSEntry::UDS_RECURSIVE_SIZE));
+ countFileSize = false;
+ }
+
for (int i = 0; i < itemCount; ++i) {
const KFileItem item = m_model->fileItem(i);
if (item.isDir()) {
++folderCount;
} else {
++fileCount;
- totalFileSize += item.size();
+ if (countFileSize) {
+ totalFileSize += item.size();
+ }
}
}
}
+void DolphinView::slotTwoClicksRenamingTimerTimeout()
+{
+ const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
+
+ // verify that only one item is selected
+ if (selectionManager->selectedItems().count() == 1) {
+ const int index = selectionManager->currentItem();
+ const QUrl fileItemUrl = m_model->fileItem(index).url();
+
+ // check if the selected item was the same item that started the twoClicksRenaming
+ if (fileItemUrl.isValid() && m_twoClicksRenamingItemUrl == fileItemUrl) {
+ renameSelectedItems();
+ }
+ }
+}
+
+void DolphinView::slotTrashFileFinished(KJob* job)
+{
+ if (job->error() == 0) {
+ emit operationCompletedMessage(i18nc("@info:status", "Trash operation completed."));
+ } else if (job->error() != KIO::ERR_USER_CANCELED) {
+ emit errorMessage(job->errorString());
+ }
+}
+
void DolphinView::slotDeleteFileFinished(KJob* job)
{
if (job->error() == 0) {
}
}
-void DolphinView::slotRenamingFailed(const KUrl& oldUrl, const KUrl& newUrl)
+void DolphinView::slotRenamingResult(KJob* job)
{
- const int index = m_model->index(newUrl);
- if (index >= 0) {
- QHash<QByteArray, QVariant> data;
- data.insert("text", oldUrl.fileName());
- m_model->setData(index, data);
+ if (job->error()) {
+ KIO::CopyJob *copyJob = qobject_cast<KIO::CopyJob *>(job);
+ Q_ASSERT(copyJob);
+ const QUrl newUrl = copyJob->destUrl();
+ const int index = m_model->index(newUrl);
+ if (index >= 0) {
+ QHash<QByteArray, QVariant> data;
+ const QUrl oldUrl = copyJob->srcUrls().at(0);
+ data.insert("text", oldUrl.fileName());
+ m_model->setData(index, data);
+ }
}
}
void DolphinView::slotDirectoryLoadingStarted()
{
// Disable the writestate temporary until it can be determined in a fast way
- // in DolphinView::slotLoadingCompleted()
+ // in DolphinView::slotDirectoryLoadingCompleted()
if (m_isFolderWritable) {
m_isFolderWritable = false;
emit writeStateChanged(m_isFolderWritable);
{
// Update the view-state. This has to be done asynchronously
// because the view might not be in its final state yet.
- QTimer::singleShot(0, this, SLOT(updateViewState()));
+ QTimer::singleShot(0, this, &DolphinView::updateViewState);
emit directoryLoadingCompleted();
void DolphinView::slotSortOrderChangedByHeader(Qt::SortOrder current, Qt::SortOrder previous)
{
- Q_UNUSED(previous);
+ Q_UNUSED(previous)
Q_ASSERT(m_model->sortOrder() == current);
ViewProperties props(viewPropertiesUrl());
void DolphinView::slotSortRoleChangedByHeader(const QByteArray& current, const QByteArray& previous)
{
- Q_UNUSED(previous);
+ Q_UNUSED(previous)
Q_ASSERT(m_model->sortRole() == current);
ViewProperties props(viewPropertiesUrl());
void DolphinView::slotVisibleRolesChangedByHeader(const QList<QByteArray>& current,
const QList<QByteArray>& previous)
{
- Q_UNUSED(previous);
+ Q_UNUSED(previous)
Q_ASSERT(m_container->controller()->view()->visibleRoles() == current);
const QList<QByteArray> previousVisibleRoles = m_visibleRoles;
if (role == "text") {
const KFileItem oldItem = m_model->fileItem(index);
const QString newName = value.toString();
- if (!newName.isEmpty() && newName != oldItem.text() && newName != QLatin1String(".") && newName != QLatin1String("..")) {
- const KUrl oldUrl = oldItem.url();
+ if (!newName.isEmpty() && newName != oldItem.text() && newName != QLatin1Char('.') && newName != QLatin1String("..")) {
+ const QUrl oldUrl = oldItem.url();
+
+ QUrl newUrl = oldUrl.adjusted(QUrl::RemoveFilename);
+ newUrl.setPath(newUrl.path() + KIO::encodeFileName(newName));
+
+#ifndef Q_OS_WIN
+ //Confirm hiding file/directory by renaming inline
+ if (!hiddenFilesShown() && newName.startsWith(QLatin1Char('.')) && !oldItem.name().startsWith(QLatin1Char('.'))) {
+ KGuiItem yesGuiItem(KStandardGuiItem::yes());
+ yesGuiItem.setText(i18nc("@action:button", "Rename and Hide"));
+
+ const auto code = KMessageBox::questionYesNo(this,
+ 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"
+ "Do you still want to rename it?"),
+ oldItem.isFile() ? i18n("Hide this File?") : i18n("Hide this Folder?"),
+ yesGuiItem,
+ KStandardGuiItem::cancel(),
+ QStringLiteral("ConfirmHide")
+ );
+
+ if (code == KMessageBox::No) {
+ return;
+ }
+ }
+#endif
- const KUrl newUrl(url().path(KUrl::AddTrailingSlash) + 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 KonqOperations::rename() will open a dialog
+ // 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.
QHash<QByteArray, QVariant> data;
m_model->setData(index, data);
}
- KonqOperations* op = KonqOperations::renameV2(this, oldUrl, newName);
- if (op && !newNameExistsAlready) {
- // Only connect the renamingFailed signal if there is no item with the new name
+ KIO::Job * job = KIO::moveAs(oldUrl, newUrl);
+ KJobWidgets::setWindow(job, this);
+ KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Rename, {oldUrl}, newUrl, job);
+ job->uiDelegate()->setAutoErrorHandlingEnabled(true);
+
+ forceUrlsSelection(newUrl, {newUrl});
+
+ if (!newNameExistsAlready) {
+ // Only connect the result signal if there is no item with the new name
// in the model yet, see bug 328262.
- connect(op, &KonqOperations::renamingFailed, this, &DolphinView::slotRenamingFailed);
+ connect(job, &KJob::result, this, &DolphinView::slotRenamingResult);
}
}
}
}
-void DolphinView::loadDirectory(const KUrl& url, bool reload)
+void DolphinView::loadDirectory(const QUrl& url, bool reload)
{
if (!url.isValid()) {
- const QString location(url.pathOrUrl());
+ const QString location(url.toDisplayString(QUrl::PreferLocalFile));
if (location.isEmpty()) {
emit errorMessage(i18nc("@info:status", "The location is empty."));
} else {
}
}
-void DolphinView::pasteToUrl(const KUrl& url)
+void DolphinView::pasteToUrl(const QUrl& url)
{
- KonqOperations* op = KonqOperations::doPasteV2(this, url);
- if (op) {
- m_clearSelectionBeforeSelectingNewItems = true;
- m_markFirstNewlySelectedItemAsCurrent = true;
- connect(op, static_cast<void(KonqOperations::*)(const KUrl::List&)>(&KonqOperations::aboutToCreate), this, &DolphinView::slotAboutToCreate);
- }
+ KIO::PasteJob *job = KIO::paste(QApplication::clipboard()->mimeData(), url);
+ KJobWidgets::setWindow(job, this);
+ m_clearSelectionBeforeSelectingNewItems = true;
+ m_markFirstNewlySelectedItemAsCurrent = true;
+ connect(job, &KIO::PasteJob::itemCreated, this, &DolphinView::slotItemCreated);
+ connect(job, &KIO::PasteJob::result, this, &DolphinView::slotPasteJobResult);
}
-KUrl::List DolphinView::simplifiedSelectedUrls() const
+QList<QUrl> DolphinView::simplifiedSelectedUrls() const
{
- KUrl::List urls;
+ QList<QUrl> urls;
const KFileItemList items = selectedItems();
+ urls.reserve(items.count());
foreach (const KFileItem& item, items) {
urls.append(item.url());
}
if (item.isNull()) {
// Try to find out if the URL is writable even if the "root item" is
// null, see https://bugs.kde.org/show_bug.cgi?id=330001
- item = KFileItem(KFileItem::Unknown, KFileItem::Unknown, url(), true);
+ item = KFileItem(url());
+ item.setDelayedMimeTypes(true);
}
KFileItemListProperties capabilities(KFileItemList() << item);
}
}
-KUrl DolphinView::viewPropertiesUrl() const
+QUrl DolphinView::viewPropertiesUrl() const
{
if (m_viewPropertiesContext.isEmpty()) {
return m_url;
}
- KUrl url;
- url.setProtocol(m_url.protocol());
+ QUrl url;
+ url.setScheme(m_url.scheme());
url.setPath(m_viewPropertiesContext);
return url;
}
-#include "dolphinview.moc"
+void DolphinView::slotRenameDialogRenamingFinished(const QList<QUrl>& urls)
+{
+ forceUrlsSelection(urls.first(), urls);
+}
+
+void DolphinView::forceUrlsSelection(const QUrl& current, const QList<QUrl>& selected)
+{
+ clearSelection();
+ m_clearSelectionBeforeSelectingNewItems = true;
+ markUrlAsCurrent(current);
+ markUrlsAsSelected(selected);
+}