X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/9cf54dcc025073f29e6a1f55c83c4edcec6a5ea3..64afe7b22622f79b34aafd54501b08120ab2fc5c:/src/views/dolphinview.cpp diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index d69d664af..63b53f2e2 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -20,7 +20,7 @@ #include "dolphinview.h" -#include +#include #include #include @@ -33,6 +33,8 @@ #include #include +#include +#include #include #include #include @@ -72,8 +74,8 @@ #include "views/tooltips/tooltipmanager.h" #include "zoomlevelinfo.h" -#ifdef HAVE_NEPOMUK - #include +#ifdef HAVE_BALOO + #include #endif namespace { @@ -102,6 +104,7 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) : m_restoredContentsPosition(), m_selectedUrls(), m_clearSelectionBeforeSelectingNewItems(false), + m_markFirstNewlySelectedItemAsCurrent(false), m_versionControlObserver(0) { m_topLayout = new QVBoxLayout(this); @@ -142,7 +145,7 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) : controller->setSelectionBehavior(KItemListController::MultiSelection); connect(controller, SIGNAL(itemActivated(int)), this, SLOT(slotItemActivated(int))); - connect(controller, SIGNAL(itemsActivated(QSet)), this, SLOT(slotItemsActivated(QSet))); + connect(controller, SIGNAL(itemsActivated(KItemSet)), this, SLOT(slotItemsActivated(KItemSet))); connect(controller, SIGNAL(itemMiddleClicked(int)), this, SLOT(slotItemMiddleClicked(int))); connect(controller, SIGNAL(itemContextMenuRequested(int,QPointF)), this, SLOT(slotItemContextMenuRequested(int,QPointF))); connect(controller, SIGNAL(viewContextMenuRequested(QPointF)), this, SLOT(slotViewContextMenuRequested(QPointF))); @@ -151,6 +154,7 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) : connect(controller, SIGNAL(itemHovered(int)), this, SLOT(slotItemHovered(int))); connect(controller, SIGNAL(itemUnhovered(int)), this, SLOT(slotItemUnhovered(int))); connect(controller, SIGNAL(itemDropEvent(int,QGraphicsSceneDragDropEvent*)), this, SLOT(slotItemDropEvent(int,QGraphicsSceneDragDropEvent*))); + connect(controller, SIGNAL(escapePressed()), this, SLOT(stopLoading())); connect(controller, SIGNAL(modelChanged(KItemModelBase*,KItemModelBase*)), this, SLOT(slotModelChanged(KItemModelBase*,KItemModelBase*))); connect(m_model, SIGNAL(directoryLoadingStarted()), this, SLOT(slotDirectoryLoadingStarted())); @@ -175,13 +179,13 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) : connect(m_view, SIGNAL(visibleRolesChanged(QList,QList)), this, SLOT(slotVisibleRolesChangedByHeader(QList,QList))); connect(m_view, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)), - this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant))); + this, SLOT(slotRoleEditingCanceled())); connect(m_view->header(), SIGNAL(columnWidthChanged(QByteArray,qreal,qreal)), this, SLOT(slotHeaderColumnWidthChanged(QByteArray,qreal,qreal))); KItemListSelectionManager* selectionManager = controller->selectionManager(); - connect(selectionManager, SIGNAL(selectionChanged(QSet,QSet)), - this, SLOT(slotSelectionChanged(QSet,QSet))); + connect(selectionManager, SIGNAL(selectionChanged(KItemSet,KItemSet)), + this, SLOT(slotSelectionChanged(KItemSet,KItemSet))); m_toolTipManager = new ToolTipManager(this); @@ -245,9 +249,12 @@ void DolphinView::setMode(Mode mode) if (mode != m_mode) { ViewProperties props(viewPropertiesUrl()); props.setViewMode(mode); - props.save(); - applyViewProperties(); + // We pass the new ViewProperties to applyViewProperties, rather than + // storing them on disk and letting applyViewProperties() read them + // from there, to prevent that changing the view mode fails if the + // .directory file is not writable (see bug 318534). + applyViewProperties(props); } } @@ -343,14 +350,9 @@ int DolphinView::itemsCount() const KFileItemList DolphinView::selectedItems() const { const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager(); - QList selectedIndexes = selectionManager->selectedItems().toList(); - - qSort(selectedIndexes); KFileItemList selectedItems; - QListIterator it(selectedIndexes); - while (it.hasNext()) { - const int index = it.next(); + foreach (int index, selectionManager->selectedItems()) { selectedItems.append(m_model->fileItem(index)); } return selectedItems; @@ -383,9 +385,9 @@ void DolphinView::selectItems(const QRegExp& pattern, bool enabled) for (int index = 0; index < m_model->count(); index++) { const KFileItem item = m_model->fileItem(index); if (pattern.exactMatch(item.text())) { - // An alternative approach would be to store the matching items in a QSet and + // 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(QSet, SelectionMode mode) + // KItemListSelectionManager::setSelected(KItemSet, SelectionMode mode) // for that. selectionManager->setSelected(index, 1, mode); } @@ -479,11 +481,6 @@ void DolphinView::reload() restoreState(restoreStream); } -void DolphinView::stopLoading() -{ - m_model->cancelDirectoryLoading(); -} - void DolphinView::readSettings() { const int oldZoomLevel = m_view->zoomLevel(); @@ -550,8 +547,8 @@ QString DolphinView::statusBarText() const } if (folderCount + fileCount == 1) { - // If only one item is selected, show the filename - filesText = i18nc("@info:status", "%1 selected", list.first().text()); + // If only one item is selected, show info about it + return list.first().getStatusBarInfo(); } else { // At least 2 items are selected foldersText = i18ncp("@info:status", "1 Folder selected", "%1 Folders selected", folderCount); @@ -652,6 +649,8 @@ void DolphinView::renameSelectedItems() const int index = m_model->index(items.first()); m_view->editRole(index, "text"); + hideToolTip(); + connect(m_view, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)), this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant))); } else { @@ -718,6 +717,11 @@ void DolphinView::pasteIntoFolder() } } +void DolphinView::stopLoading() +{ + m_model->cancelDirectoryLoading(); +} + bool DolphinView::eventFilter(QObject* watched, QEvent* event) { switch (event->type()) { @@ -796,7 +800,7 @@ void DolphinView::slotItemActivated(int index) } } -void DolphinView::slotItemsActivated(const QSet& indexes) +void DolphinView::slotItemsActivated(const KItemSet& indexes) { Q_ASSERT(indexes.count() >= 2); @@ -811,13 +815,12 @@ void DolphinView::slotItemsActivated(const QSet& indexes) KFileItemList items; items.reserve(indexes.count()); - QSetIterator it(indexes); - while (it.hasNext()) { - const int index = it.next(); + foreach (int index, indexes) { KFileItem item = m_model->fileItem(index); + const KUrl& url = openItemAsFolderUrl(item); - if (item.isDir()) { // Open folders in new tabs - emit tabRequested(item.url()); + if (!url.isEmpty()) { // Open folders in new tabs + emit tabRequested(url); } else { items.append(item); } @@ -832,14 +835,23 @@ void DolphinView::slotItemsActivated(const QSet& indexes) void DolphinView::slotItemMiddleClicked(int index) { - const KFileItem item = m_model->fileItem(index); - if (item.isDir() || isTabsForFilesEnabled()) { + const KFileItem& item = m_model->fileItem(index); + const KUrl& url = openItemAsFolderUrl(item); + if (!url.isEmpty()) { + emit tabRequested(url); + } else if (isTabsForFilesEnabled()) { emit tabRequested(item.url()); } } void DolphinView::slotItemContextMenuRequested(int index, const QPointF& pos) { + // Force emit of a selection changed signal before we request the + // context menu, to update the edit-actions first. (See Bug 294013) + if (m_selectionChangedTimer->isActive()) { + emitSelectionChangedSignal(); + } + const KFileItem item = m_model->fileItem(index); emit requestContextMenu(pos.toPoint(), item, url(), QList()); } @@ -858,14 +870,10 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos) KItemListView* view = m_container->controller()->view(); const QSet visibleRolesSet = view->visibleRoles().toSet(); - bool nepomukRunning = false; bool indexingEnabled = false; -#ifdef HAVE_NEPOMUK - nepomukRunning = (Nepomuk2::ResourceManager::instance()->initialized()); - if (nepomukRunning) { - KConfig config("nepomukserverrc"); - indexingEnabled = config.group("Service-nepomukfileindexer").readEntry("autostart", true); - } +#ifdef HAVE_BALOO + Baloo::IndexerConfig config; + indexingEnabled = config.fileIndexingEnabled(); #endif QString groupName; @@ -896,8 +904,8 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF& pos) action->setChecked(visibleRolesSet.contains(info.role)); action->setData(info.role); - const bool enable = (!info.requiresNepomuk && !info.requiresIndexer) || - (info.requiresNepomuk && nepomukRunning) || + const bool enable = (!info.requiresBaloo && !info.requiresIndexer) || + (info.requiresBaloo) || (info.requiresIndexer && indexingEnabled); action->setEnabled(enable); } @@ -1029,15 +1037,19 @@ void DolphinView::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even event->buttons(), event->modifiers()); - const QString error = DragAndDropHelper::dropUrls(destItem, destUrl, &dropEvent); + QString error; + KonqOperations* op = DragAndDropHelper::dropUrls(destItem, destUrl, &dropEvent, error); if (!error.isEmpty()) { emit infoMessage(error); } - if (destUrl == url()) { + if (op && destUrl == url()) { // Mark the dropped urls as selected. - markPastedUrlsAsSelected(event->mimeData()); + m_clearSelectionBeforeSelectingNewItems = true; + connect(op, SIGNAL(aboutToCreate(KUrl::List)), this, SLOT(slotAboutToCreate(KUrl::List))); } + + setActive(true); } void DolphinView::slotModelChanged(KItemModelBase* current, KItemModelBase* previous) @@ -1072,7 +1084,18 @@ void DolphinView::slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons } } -void DolphinView::slotSelectionChanged(const QSet& current, const QSet& previous) +void DolphinView::slotAboutToCreate(const KUrl::List& urls) +{ + if (!urls.isEmpty()) { + if (m_markFirstNewlySelectedItemAsCurrent) { + markUrlAsCurrent(urls.first()); + m_markFirstNewlySelectedItemAsCurrent = false; + } + m_selectedUrls << KDirModel::simplifiedUrlList(urls); + } +} + +void DolphinView::slotSelectionChanged(const KItemSet& current, const KItemSet& previous) { const int currentCount = current.count(); const int previousCount = previous.count(); @@ -1194,6 +1217,49 @@ QString DolphinView::viewPropertiesContext() const return m_viewPropertiesContext; } +KUrl DolphinView::openItemAsFolderUrl(const KFileItem& item, const bool browseThroughArchives) +{ + if (item.isNull()) { + return KUrl(); + } + + KUrl url = item.targetUrl(); + + if (item.isDir()) { + return url; + } + + if (item.isMimeTypeKnown()) { + const QString& mimetype = item.mimetype(); + + if (browseThroughArchives && item.isFile() && url.isLocalFile()) { + // Generic mechanism for redirecting to tar:// when clicking on a tar file, + // zip:// when clicking on a zip file, etc. + // The .protocol file specifies the mimetype that the kioslave handles. + // Note that we don't use mimetype inheritance since we don't want to + // open OpenDocument files as zip folders... + const QString& protocol = KProtocolManager::protocolForArchiveMimetype(mimetype); + if (!protocol.isEmpty()) { + url.setProtocol(protocol); + return url; + } + } + + if (mimetype == QLatin1String("application/x-desktop")) { + // Redirect to the URL in Type=Link desktop files, unless it is a http(s) URL. + KDesktopFile desktopFile(url.toLocalFile()); + if (desktopFile.hasLinkType()) { + const QString linkUrl = desktopFile.readUrl(); + if (!linkUrl.startsWith(QLatin1String("http"))) { + return linkUrl; + } + } + } + } + + return KUrl(); +} + void DolphinView::observeCreatedItem(const KUrl& url) { if (m_active) { @@ -1224,10 +1290,11 @@ void DolphinView::updateViewState() m_view->scrollToItem(currentIndex); m_scrollToCurrentItem = false; } + + m_currentItemUrl = KUrl(); } else { selectionManager->setCurrentItem(0); } - m_currentItemUrl = KUrl(); } if (!m_restoredContentsPosition.isNull()) { @@ -1247,7 +1314,7 @@ void DolphinView::updateViewState() m_clearSelectionBeforeSelectingNewItems = false; } - QSet selectedItems = selectionManager->selectedItems(); + KItemSet selectedItems = selectionManager->selectedItems(); QList::iterator it = m_selectedUrls.begin(); while (it != m_selectedUrls.end()) { @@ -1306,6 +1373,16 @@ void DolphinView::slotDeleteFileFinished(KJob* job) } } +void DolphinView::slotRenamingFailed(const KUrl& oldUrl, const KUrl& newUrl) +{ + const int index = m_model->index(newUrl); + if (index >= 0) { + QHash data; + 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 @@ -1372,7 +1449,7 @@ void DolphinView::slotVisibleRolesChangedByHeader(const QList& curre emit visibleRolesChanged(m_visibleRoles, previousVisibleRoles); } -void DolphinView::slotRoleEditingCanceled(int index, const QByteArray& role, const QVariant& value) +void DolphinView::slotRoleEditingCanceled() { disconnect(m_view, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)), this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant))); @@ -1406,7 +1483,12 @@ void DolphinView::slotRoleEditingFinished(int index, const QByteArray& role, con m_model->setData(index, data); } - KonqOperations::rename(this, oldUrl, newName); + KonqOperations* op = KonqOperations::renameV2(this, oldUrl, newName); + if (op && !newNameExistsAlready) { + // Only connect the renamingFailed signal if there is no item with the new name + // in the model yet, see bug 328262. + connect(op, SIGNAL(renamingFailed(KUrl,KUrl)), SLOT(slotRenamingFailed(KUrl,KUrl))); + } } } } @@ -1432,9 +1514,13 @@ void DolphinView::loadDirectory(const KUrl& url, bool reload) void DolphinView::applyViewProperties() { - m_view->beginTransaction(); - const ViewProperties props(viewPropertiesUrl()); + applyViewProperties(props); +} + +void DolphinView::applyViewProperties(const ViewProperties& props) +{ + m_view->beginTransaction(); const Mode mode = props.viewMode(); if (m_mode != mode) { @@ -1538,8 +1624,12 @@ void DolphinView::applyModeToView() void DolphinView::pasteToUrl(const KUrl& url) { - markPastedUrlsAsSelected(QApplication::clipboard()->mimeData()); - KonqOperations::doPaste(this, url); + KonqOperations* op = KonqOperations::doPasteV2(this, url); + if (op) { + m_clearSelectionBeforeSelectingNewItems = true; + m_markFirstNewlySelectedItemAsCurrent = true; + connect(op, SIGNAL(aboutToCreate(KUrl::List)), this, SLOT(slotAboutToCreate(KUrl::List))); + } } KUrl::List DolphinView::simplifiedSelectedUrls() const @@ -1562,27 +1652,15 @@ KUrl::List DolphinView::simplifiedSelectedUrls() const QMimeData* DolphinView::selectionMimeData() const { const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager(); - const QSet selectedIndexes = selectionManager->selectedItems(); + const KItemSet selectedIndexes = selectionManager->selectedItems(); return m_model->createMimeData(selectedIndexes); } -void DolphinView::markPastedUrlsAsSelected(const QMimeData* mimeData) -{ - const KUrl::List sourceUrls = KUrl::List::fromMimeData(mimeData); - KUrl::List destUrls; - foreach (const KUrl& source, sourceUrls) { - KUrl destination(url().url() + '/' + source.fileName()); - destUrls << destination; - } - markUrlsAsSelected(destUrls); - m_clearSelectionBeforeSelectingNewItems = true; -} - void DolphinView::updateWritableState() { const bool wasFolderWritable = m_isFolderWritable; - m_isFolderWritable = true; + m_isFolderWritable = false; const KFileItem item = m_model->rootItem(); if (!item.isNull()) {