]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/views/dolphinview.cpp
Use capitalized KDE includes
[dolphin.git] / src / views / dolphinview.cpp
index 79706358ff716b44b28121a8ed5a518aa5309225..a4e97bf6e6593a24ddee56c49c7964a352e259d0 100644 (file)
 #include <QTimer>
 #include <QScrollBar>
 
-#include <kactioncollection.h>
-#include <kcolorscheme.h>
-#include <kdirlister.h>
-#include <kiconeffect.h>
-#include <kfileitem.h>
-#include <klocale.h>
-#include <kio/deletejob.h>
-#include <kio/netaccess.h>
-#include <kio/previewjob.h>
-#include <kjob.h>
-#include <kmenu.h>
-#include <kmessagebox.h>
-#include <kmimetyperesolver.h>
+#include <KActionCollection>
+#include <KColorScheme>
+#include <KDirLister>
+#include <KIconEffect>
+#include <KFileItem>
+#include <KFileItemListProperties>
+#include <KLocale>
+#include <KIO/DeleteJob>
+#include <KIO/NetAccess>
+#include <KIO/PreviewJob>
+#include <KJob>
+#include <KMenu>
+#include <KMessageBox>
 #include <konq_fileitemcapabilities.h>
 #include <konq_operations.h>
 #include <konqmimedata.h>
-#include <ktoggleaction.h>
-#include <kurl.h>
+#include <KToggleAction>
+#include <KUrl>
 
 #include "additionalinfoaccessor.h"
+#include "dolphindirlister.h"
 #include "dolphinmodel.h"
 #include "dolphincolumnviewcontainer.h"
 #include "dolphinviewcontroller.h"
@@ -67,9 +68,7 @@
 #include "zoomlevelinfo.h"
 #include "dolphindetailsviewexpander.h"
 
-DolphinView::DolphinView(QWidget* parent,
-                         const KUrl& url,
-                         DolphinSortFilterProxyModel* proxyModel) :
+DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
     QWidget(parent),
     m_active(true),
     m_showPreview(false),
@@ -77,13 +76,14 @@ DolphinView::DolphinView(QWidget* parent,
     m_tabsForFiles(false),
     m_isContextMenuOpen(false),
     m_assureVisibleCurrentIndex(false),
+    m_expanderActive(false),
+    m_isFolderWritable(true),
     m_mode(DolphinView::IconsView),
     m_topLayout(0),
     m_dolphinViewController(0),
     m_viewModeController(0),
-    m_viewAccessor(proxyModel),
+    m_viewAccessor(),
     m_selectionChangedTimer(0),
-    m_rootUrl(),
     m_activeItemUrl(),
     m_restoredContentsPosition(),
     m_createdItemUrl(),
@@ -125,15 +125,7 @@ DolphinView::DolphinView(QWidget* parent,
     connect(m_dolphinViewController, SIGNAL(viewportEntered()),
             this, SLOT(clearHoverInformation()));
     connect(m_dolphinViewController, SIGNAL(urlChangeRequested(KUrl)),
-            m_viewModeController, SLOT(setUrl(KUrl)));
-
-    KDirLister* dirLister = m_viewAccessor.dirLister();
-    connect(dirLister, SIGNAL(redirection(KUrl,KUrl)),
-            this, SLOT(slotRedirection(KUrl,KUrl)));
-    connect(dirLister, SIGNAL(completed()),
-            this, SLOT(slotDirListerCompleted()));
-    connect(dirLister, SIGNAL(refreshItems(const QList<QPair<KFileItem,KFileItem>>&)),
-            this, SLOT(slotRefreshItems()));
+            this, SLOT(slotUrlChangeRequested(KUrl)));
 
     // 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
@@ -179,9 +171,7 @@ void DolphinView::setActive(bool active)
     m_active = active;
 
     QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
-    if (active) {
-        emitSelectionChangedSignal();
-    } else {
+    if (!active) {
         color.setAlpha(150);
     }
 
@@ -195,6 +185,8 @@ void DolphinView::setActive(bool active)
     if (active) {
         m_viewAccessor.itemView()->setFocus();
         emit activated();
+        emitSelectionChangedSignal();
+        emit writeStateChanged(m_isFolderWritable);
     }
 
     m_viewModeController->indicateActivationChange(active);
@@ -218,6 +210,7 @@ void DolphinView::setMode(Mode mode)
     // be restored after reloading the directory
     m_selectedItems = selectedItems();
 
+    const bool hasFocus = m_viewAccessor.itemView()->hasFocus();
     deleteView();
 
     const KUrl viewPropsUrl = rootUrl();
@@ -225,6 +218,10 @@ void DolphinView::setMode(Mode mode)
     props.setViewMode(m_mode);
     createView();
 
+    if (hasFocus) {
+        m_viewAccessor.itemView()->setFocus();
+    }
+
     // the file item delegate has been recreated, apply the current
     // additional information manually
     const KFileItemDelegate::InformationList infoList = props.additionalInfo();
@@ -279,18 +276,14 @@ bool DolphinView::supportsCategorizedSorting() const
     return m_viewAccessor.supportsCategorizedSorting();
 }
 
-bool DolphinView::hasSelection() const
+KFileItem DolphinView::rootItem() const
 {
-    const QAbstractItemView* view = m_viewAccessor.itemView();
-    return (view != 0) && view->selectionModel()->hasSelection();
+    return m_viewAccessor.dirLister()->rootItem();
 }
 
-void DolphinView::markUrlsAsSelected(const QList<KUrl>& urls)
+KFileItemList DolphinView::items() const
 {
-    foreach (const KUrl& url, urls) {
-        KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
-        m_selectedItems.append(item);
-    }
+    return m_viewAccessor.dirLister()->items();
 }
 
 KFileItemList DolphinView::selectedItems() const
@@ -314,16 +307,6 @@ KFileItemList DolphinView::selectedItems() const
     return itemList;
 }
 
-KUrl::List DolphinView::selectedUrls() const
-{
-    KUrl::List urls;
-    const KFileItemList list = selectedItems();
-    foreach (const KFileItem &item, list) {
-        urls.append(item.url());
-    }
-    return urls;
-}
-
 int DolphinView::selectedItemsCount() const
 {
     const QAbstractItemView* view = m_viewAccessor.itemView();
@@ -334,9 +317,21 @@ int DolphinView::selectedItemsCount() const
     return view->selectionModel()->selectedIndexes().count();
 }
 
-QItemSelectionModel* DolphinView::selectionModel() const
+void DolphinView::markUrlsAsSelected(const QList<KUrl>& urls)
 {
-    return m_viewAccessor.itemView()->selectionModel();
+    foreach (const KUrl& url, urls) {
+        KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
+        m_selectedItems.append(item);
+    }
+}
+
+void DolphinView::setItemSelectionEnabled(const QRegExp& pattern, bool enabled)
+{
+    const QItemSelection matchingIndexes = childrenMatchingPattern(QModelIndex(), pattern);
+    const QItemSelectionModel::SelectionFlags command = enabled
+                                                      ? QItemSelectionModel::Select
+                                                      : QItemSelectionModel::Deselect;
+    m_viewAccessor.itemView()->selectionModel()->select(matchingIndexes, command);
 }
 
 void DolphinView::setZoomLevel(int level)
@@ -451,6 +446,11 @@ void DolphinView::setNameFilter(const QString& nameFilter)
     m_viewModeController->setNameFilter(nameFilter);
 }
 
+QString DolphinView::nameFilter() const
+{
+    return m_viewModeController->nameFilter();
+}
+
 void DolphinView::calculateItemCount(int& fileCount,
                                      int& folderCount,
                                      KIO::filesize_t& totalFileSize) const
@@ -535,29 +535,28 @@ void DolphinView::setUrl(const KUrl& url)
         return;
     }
 
-    // The selection model might change in the case of the column view. Disconnect
-    // from the current selection model and reconnect later after the URL switch.
-    QAbstractItemView* view = m_viewAccessor.itemView();
-    disconnect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-               this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
+    const bool hadSelection = hasSelection();
+
+    // The selection model and directory lister might change in the case of the column view:
+    disconnectViewAccessor();
 
     m_newFileNames.clear();
 
     m_viewModeController->setUrl(url); // emits urlChanged, which we forward
     m_viewAccessor.prepareUrlChange(url);
     applyViewProperties();
-    loadDirectory(url);
 
     // When changing the URL there is no need to keep the version
     // data of the previous URL.
     m_viewAccessor.dirModel()->clearVersionData();
 
-    emit startedPathLoading(url);
+    // Reconnect to the (probably) new selection model and directory lister
+    connectViewAccessor();
+    loadDirectory(url);
 
-    // Reconnect to the (probably) new selection model
-    view = m_viewAccessor.itemView();
-    connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-            this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
+    if (hadSelection || hasSelection()) {
+        emitSelectionChangedSignal();
+    }
 }
 
 void DolphinView::selectAll()
@@ -567,15 +566,23 @@ void DolphinView::selectAll()
 
 void DolphinView::invertSelection()
 {
-    QItemSelectionModel* selectionModel = m_viewAccessor.itemView()->selectionModel();
-    const QAbstractItemModel* itemModel = selectionModel->model();
-
-    const QModelIndex topLeft = itemModel->index(0, 0);
-    const QModelIndex bottomRight = itemModel->index(itemModel->rowCount() - 1,
-                                                     itemModel->columnCount() - 1);
+    // Implementation note: Using selectionModel->select(selection, QItemSelectionModel::Toggle) does not
+    // work, as QItemSelectionModel::hasSelection() provides invalid values in this case. This might be a Qt-issue -
+    // when changing the implementation with an updated Qt-version don't forget to run the Dolphin-unit-tests that
+    // verify this usecase.
+    const KFileItemList selItems = selectedItems();
+    clearSelection();
+
+    QItemSelection invertedSelection;
+    foreach (const KFileItem& item, items()) {
+        if (!selItems.contains(item)) {
+            const QModelIndex index = m_viewAccessor.proxyModel()->mapFromSource(m_viewAccessor.dirModel()->indexForItem(item));
+            invertedSelection.select(index, index);
+        }
+    }
 
-    const QItemSelection selection(topLeft, bottomRight);
-    selectionModel->select(selection, QItemSelectionModel::Toggle);
+    QItemSelectionModel* selectionModel = m_viewAccessor.itemView()->selectionModel();
+    selectionModel->select(invertedSelection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current);
 }
 
 void DolphinView::clearSelection()
@@ -590,53 +597,6 @@ void DolphinView::renameSelectedItems()
     if (itemCount < 1) {
         return;
     }
-/*
-    if (itemCount > 1) {
-        // More than one item has been selected for renaming. Open
-        // a rename dialog and rename all items afterwards.
-        QPointer<RenameDialog> dialog = new RenameDialog(this, items);
-        if (dialog->exec() == QDialog::Rejected) {
-            delete dialog;
-            return;
-        }
-
-        const QString newName = dialog->newName();
-        if (newName.isEmpty()) {
-            emit errorMessage(dialog->errorString());
-            delete dialog;
-            return;
-        }
-        delete dialog;
-
-        // the selection would be invalid after renaming the items, so just clear
-        // it before
-        clearSelection();
-
-        // TODO: check how this can be integrated into KIO::FileUndoManager/KonqOperations
-        // as one operation instead of n rename operations like it is done now...
-        Q_ASSERT(newName.contains('#'));
-
-        // currently the items are sorted by the selection order, resort
-        // them by the file name
-        qSort(items.begin(), items.end(), lessThan);
-
-        // iterate through all selected items and rename them...
-        int index = 1;
-        foreach (const KFileItem& item, items) {
-            const KUrl& oldUrl = item.url();
-            QString number;
-            number.setNum(index++);
-
-            QString name = newName;
-            name.replace('#', number);
-
-            if (oldUrl.fileName() != name) {
-                KUrl newUrl = oldUrl;
-                newUrl.setFileName(name);
-                KonqOperations::rename(this, oldUrl, newUrl);
-            }
-        }
-    } else*/
 
     if ((itemCount == 1) && DolphinSettings::instance().generalSettings()->renameInline()) {
         const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForItem(items.first());
@@ -648,30 +608,7 @@ void DolphinView::renameSelectedItems()
         dialog->show();
         dialog->raise();
         dialog->activateWindow();
-
-        // XXX
-      /*  if (dialog->exec() == QDialog::Rejected) {
-            delete dialog;
-            return;
-        }
-
-        const QString newName = dialog->newName();
-        if (newName.isEmpty()) {
-            emit errorMessage(dialog->errorString());
-            delete dialog;
-            return;
-        }
-        delete dialog;
-
-        const KUrl& oldUrl = items.first().url();
-        KUrl newUrl = oldUrl;
-        newUrl.setFileName(newName);
-        KonqOperations::rename(this, oldUrl, newUrl);*/
     }
-
-    // assure that the current index remains visible when KDirLister
-    // will notify the view about changed items
-    m_assureVisibleCurrentIndex = true;
 }
 
 void DolphinView::trashSelectedItems()
@@ -775,40 +712,6 @@ void DolphinView::setCategorizedSorting(bool categorized)
     emit categorizedSortingChanged();
 }
 
-void DolphinView::toggleSortOrder()
-{
-    const Qt::SortOrder order = (sortOrder() == Qt::AscendingOrder) ?
-                                Qt::DescendingOrder :
-                                Qt::AscendingOrder;
-    setSortOrder(order);
-}
-
-void DolphinView::toggleSortFoldersFirst()
-{
-    setSortFoldersFirst(!sortFoldersFirst());
-}
-
-void DolphinView::toggleAdditionalInfo(QAction* action)
-{
-    const KFileItemDelegate::Information info =
-        static_cast<KFileItemDelegate::Information>(action->data().toInt());
-
-    KFileItemDelegate::InformationList list = additionalInfo();
-
-    const bool show = action->isChecked();
-
-    const int index = list.indexOf(info);
-    const bool containsInfo = (index >= 0);
-    if (show && !containsInfo) {
-        list.append(info);
-        setAdditionalInfo(list);
-    } else if (!show && containsInfo) {
-        list.removeAt(index);
-        setAdditionalInfo(list);
-        Q_ASSERT(list.indexOf(info) < 0);
-    }
-}
-
 void DolphinView::mouseReleaseEvent(QMouseEvent* event)
 {
     QWidget::mouseReleaseEvent(event);
@@ -902,7 +805,8 @@ void DolphinView::slotSelectionChanged(const QItemSelection& selected, const QIt
 
 void DolphinView::emitSelectionChangedSignal()
 {
-    emit selectionChanged(DolphinView::selectedItems());
+    m_selectionChangedTimer->stop();
+    emit selectionChanged(selectedItems());
 }
 
 void DolphinView::openContextMenu(const QPoint& pos,
@@ -1010,13 +914,18 @@ bool DolphinView::itemsExpandable() const
 
 void DolphinView::restoreState(QDataStream& stream)
 {
-    // current item
+    // Restore the URL of the current item that had the keyboard focus
     stream >> m_activeItemUrl;
 
-    // view position
+    // Restore the root URL
+    KUrl rootUrl;
+    stream >> rootUrl;
+    m_viewAccessor.setRootUrl(rootUrl);
+
+    // Restore the view position
     stream >> m_restoredContentsPosition;
 
-    // expanded folders (only relevant for the details view - will be ignored by the view in other view modes)
+    // Restore expanded folders (only relevant for the details view - will be ignored by the view in other view modes)
     QSet<KUrl> urlsToExpand;
     stream >> urlsToExpand;
     const DolphinDetailsViewExpander* expander = m_viewAccessor.setExpandedUrls(urlsToExpand);
@@ -1031,7 +940,7 @@ void DolphinView::restoreState(QDataStream& stream)
 
 void DolphinView::saveState(QDataStream& stream)
 {
-    // current item
+    // Save the URL of the current item that has the keyboard focus
     KFileItem currentItem;
     const QAbstractItemView* view = m_viewAccessor.itemView();
 
@@ -1041,22 +950,31 @@ void DolphinView::saveState(QDataStream& stream)
         currentItem = m_viewAccessor.dirModel()->itemForIndex(dirModelIndex);
     }
 
-    KUrl currentUrl;
+    KUrl currentItemUrl;
     if (!currentItem.isNull()) {
-        currentUrl = currentItem.url();
+        currentItemUrl = currentItem.url();
     }
 
-    stream << currentUrl;
+    stream << currentItemUrl;
 
-    // view position
+    // Save the root URL
+    stream << m_viewAccessor.rootUrl();
+
+    // Save view position
     const int x = view->horizontalScrollBar()->value();
     const int y = view->verticalScrollBar()->value();
     stream << QPoint(x, y);
 
-    // expanded folders (only relevant for the details view - the set will be empty in other view modes)
+    // Save expanded folders (only relevant for the details view - the set will be empty in other view modes)
     stream << m_viewAccessor.expandedUrls();
 }
 
+bool DolphinView::hasSelection() const
+{
+    const QAbstractItemView* view = m_viewAccessor.itemView();
+    return (view != 0) && view->selectionModel()->hasSelection();
+}
+
 void DolphinView::observeCreatedItem(const KUrl& url)
 {
     m_createdItemUrl = url;
@@ -1077,6 +995,34 @@ void DolphinView::selectAndScrollToCreatedItem()
     m_createdItemUrl = KUrl();
 }
 
+void DolphinView::slotRedirection(const KUrl& oldUrl, const KUrl& newUrl)
+{
+    if (oldUrl.equals(url(), KUrl::CompareWithoutTrailingSlash)) {
+        emit redirection(oldUrl, newUrl);
+        m_viewModeController->redirectToUrl(newUrl); // #186947
+    }
+}
+
+void DolphinView::restoreContentsPosition()
+{
+    if (!m_restoredContentsPosition.isNull()) {
+        const int x = m_restoredContentsPosition.x();
+        const int y = m_restoredContentsPosition.y();
+        m_restoredContentsPosition = QPoint();
+
+        QAbstractItemView* view = m_viewAccessor.itemView();
+        Q_ASSERT(view != 0);
+        view->horizontalScrollBar()->setValue(x);
+        view->verticalScrollBar()->setValue(y);
+    }
+}
+
+void DolphinView::slotUrlChangeRequested(const KUrl& url)
+{
+    m_viewModeController->setUrl(url);
+    updateWritableState();
+}
+
 void DolphinView::showHoverInformation(const KFileItem& item)
 {
     emit requestItemInfo(item);
@@ -1096,6 +1042,18 @@ void DolphinView::slotDeleteFileFinished(KJob* job)
     }
 }
 
+void DolphinView::slotDirListerStarted(const KUrl& url)
+{
+    // Disable the writestate temporary until it can be determined in a fast way
+    // in DolphinView::slotDirListerCompleted()
+    if (m_isFolderWritable) {
+        m_isFolderWritable = false;
+        emit writeStateChanged(m_isFolderWritable);
+    }
+
+    emit startedPathLoading(url);
+}
+
 void DolphinView::slotDirListerCompleted()
 {
     if (!m_expanderActive) {
@@ -1120,6 +1078,8 @@ void DolphinView::slotDirListerCompleted()
 
         m_newFileNames.clear();
     }
+
+    updateWritableState();
 }
 
 void DolphinView::slotLoadingCompleted()
@@ -1148,7 +1108,7 @@ void DolphinView::slotLoadingCompleted()
         foreach(const KFileItem& item, m_selectedItems) {
             url = item.url().upUrl();
             if (baseUrl.equals(url, KUrl::CompareWithoutTrailingSlash)) {
-                QModelIndex index = m_viewAccessor.proxyModel()->mapFromSource(m_viewAccessor.dirModel()->indexForItem(item));
+                const QModelIndex index = m_viewAccessor.proxyModel()->mapFromSource(m_viewAccessor.dirModel()->indexForItem(item));
                 newSelection.select(index, index);
             }
         }
@@ -1206,6 +1166,7 @@ void DolphinView::applyViewProperties()
     if (m_viewAccessor.itemView() == 0) {
         createView();
     }
+
     Q_ASSERT(m_viewAccessor.itemView() != 0);
     Q_ASSERT(m_viewAccessor.itemDelegate() != 0);
 
@@ -1261,18 +1222,13 @@ void DolphinView::applyViewProperties()
 
 void DolphinView::createView()
 {
-    QAbstractItemView* view = m_viewAccessor.itemView();
-    if ((view != 0) && (view->selectionModel() != 0)) {
-        disconnect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-                   this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
-    }
-
     deleteView();
 
     Q_ASSERT(m_viewAccessor.itemView() == 0);
+    Q_ASSERT(m_dolphinViewController->itemView() == 0);
     m_viewAccessor.createView(this, m_dolphinViewController, m_viewModeController, m_mode);
 
-    view = m_viewAccessor.itemView();
+    QAbstractItemView* view = m_viewAccessor.itemView();
     Q_ASSERT(view != 0);
     view->installEventFilter(this);
     view->viewport()->installEventFilter(this);
@@ -1282,8 +1238,7 @@ void DolphinView::createView()
     const int zoomLevel = ZoomLevelInfo::zoomLevelForIconSize(view->iconSize());
     m_viewModeController->setZoomLevel(zoomLevel);
 
-    connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-            this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
+    connectViewAccessor();
 
     setFocusProxy(m_viewAccessor.layoutTarget());
     m_topLayout->insertWidget(1, m_viewAccessor.layoutTarget());
@@ -1292,21 +1247,22 @@ void DolphinView::createView()
 void DolphinView::deleteView()
 {
     QAbstractItemView* view = m_viewAccessor.itemView();
+    Q_ASSERT((m_dolphinViewController->itemView() == 0) || (m_dolphinViewController->itemView() == view));
+    m_dolphinViewController->setItemView(0);
+
     if (view != 0) {
-        // It's important to set the keyboard focus to the parent
-        // before deleting the view: Otherwise when having a split
-        // view the other view will get the focus and will request
-        // an activation (see DolphinView::eventFilter()).
-        setFocusProxy(0);
-        setFocus();
-
-        m_topLayout->removeWidget(view);
-        view->close();
-
-        // disconnect all signal/slots
-        disconnect(view);
+        disconnectViewAccessor();
+
+        if (hasFocus()) {
+            // It's important to set the keyboard focus to the parent
+            // before deleting the view: Otherwise when having a split
+            // view the other view will get the focus and will request
+            // an activation (see DolphinView::eventFilter()).
+            setFocusProxy(0);
+            setFocus();
+        }
+
         m_viewModeController->disconnect(view);
-        view->disconnect();
 
         m_viewAccessor.deleteView();
     }
@@ -1329,11 +1285,19 @@ void DolphinView::updateZoomLevel(int oldZoomLevel)
 
 KUrl::List DolphinView::simplifiedSelectedUrls() const
 {
-    KUrl::List list = selectedUrls();
-    if (itemsExpandable() ) {
-        list = KDirModel::simplifiedUrlList(list);
+    KUrl::List urls;
+
+    const KFileItemList items = selectedItems();
+    foreach (const KFileItem &item, items) {
+        urls.append(item.url());
     }
-    return list;
+
+
+    if (itemsExpandable()) {
+        urls = KDirModel::simplifiedUrlList(urls);
+    }
+
+    return urls;
 }
 
 QMimeData* DolphinView::selectionMimeData() const
@@ -1352,17 +1316,119 @@ void DolphinView::addNewFileNames(const QMimeData* mimeData)
     }
 }
 
-DolphinView::ViewAccessor::ViewAccessor(DolphinSortFilterProxyModel* proxyModel) :
+QItemSelection DolphinView::childrenMatchingPattern(const QModelIndex& parent, const QRegExp& pattern) const
+{
+    QItemSelection matchingIndexes;
+    const DolphinSortFilterProxyModel* proxyModel = m_viewAccessor.proxyModel();
+    const DolphinModel* dolphinModel = m_viewAccessor.dirModel();
+
+    const int rowCount = proxyModel->rowCount(parent);
+
+    for (int row = 0; row < rowCount; ++row) {
+        QModelIndex index = proxyModel->index(row, 0, parent);
+        QModelIndex sourceIndex = proxyModel->mapToSource(index);
+
+        if (sourceIndex.isValid() && pattern.exactMatch(dolphinModel->data(sourceIndex).toString())) {
+            matchingIndexes += QItemSelectionRange(index);
+        }
+
+        if (proxyModel->hasChildren(index)) {
+            matchingIndexes += childrenMatchingPattern(index, pattern);
+        }
+    }
+
+    return matchingIndexes;
+}
+
+void DolphinView::connectViewAccessor()
+{
+    KDirLister* dirLister = m_viewAccessor.dirLister();
+    connect(dirLister, SIGNAL(redirection(KUrl,KUrl)), this, SLOT(slotRedirection(KUrl,KUrl)));
+    connect(dirLister, SIGNAL(started(KUrl)),          this, SLOT(slotDirListerStarted(KUrl)));
+    connect(dirLister, SIGNAL(completed()),            this, SLOT(slotDirListerCompleted()));
+    connect(dirLister, SIGNAL(refreshItems(const QList<QPair<KFileItem,KFileItem>>&)),
+            this, SLOT(slotRefreshItems()));
+
+    connect(dirLister, SIGNAL(clear()),                      this, SIGNAL(itemCountChanged()));
+    connect(dirLister, SIGNAL(newItems(KFileItemList)),      this, SIGNAL(itemCountChanged()));
+    connect(dirLister, SIGNAL(infoMessage(const QString&)),  this, SIGNAL(infoMessage(const QString&)));
+    connect(dirLister, SIGNAL(errorMessage(const QString&)), this, SIGNAL(infoMessage(const QString&)));
+    connect(dirLister, SIGNAL(percent(int)),                 this, SIGNAL(pathLoadingProgress(int)));
+    connect(dirLister, SIGNAL(urlIsFileError(const KUrl&)),  this, SIGNAL(urlIsFileError(const KUrl&)));
+    connect(dirLister, SIGNAL(itemsDeleted(const KFileItemList&)), this, SIGNAL(itemCountChanged()));
+
+    QAbstractItemView* view = m_viewAccessor.itemView();
+    connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+            this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
+}
+
+void DolphinView::disconnectViewAccessor()
+{
+    KDirLister* dirLister = m_viewAccessor.dirLister();
+    disconnect(dirLister, SIGNAL(redirection(KUrl,KUrl)), this, SLOT(slotRedirection(KUrl,KUrl)));
+    disconnect(dirLister, SIGNAL(started(KUrl)),          this, SLOT(slotDirListerStarted(KUrl)));
+    disconnect(dirLister, SIGNAL(completed()),            this, SLOT(slotDirListerCompleted()));
+    disconnect(dirLister, SIGNAL(refreshItems(const QList<QPair<KFileItem,KFileItem>>&)),
+               this, SLOT(slotRefreshItems()));
+
+    disconnect(dirLister, SIGNAL(clear()),                      this, SIGNAL(itemCountChanged()));
+    disconnect(dirLister, SIGNAL(newItems(KFileItemList)),      this, SIGNAL(itemCountChanged()));
+    disconnect(dirLister, SIGNAL(infoMessage(const QString&)),  this, SIGNAL(infoMessage(const QString&)));
+    disconnect(dirLister, SIGNAL(errorMessage(const QString&)), this, SIGNAL(errorMessage(const QString&)));
+    disconnect(dirLister, SIGNAL(percent(int)),                 this, SIGNAL(pathLoadingProgress(int)));
+    disconnect(dirLister, SIGNAL(urlIsFileError(const KUrl&)),  this, SIGNAL(urlIsFileError(const KUrl&)));
+    disconnect(dirLister, SIGNAL(itemsDeleted(const KFileItemList&)), this, SIGNAL(itemCountChanged()));
+
+    QAbstractItemView* view = m_viewAccessor.itemView();
+    disconnect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+               this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
+}
+
+void DolphinView::updateWritableState()
+{
+    const bool wasFolderWritable = m_isFolderWritable;
+    m_isFolderWritable = true;
+
+    const KFileItem item = m_viewAccessor.dirLister()->rootItem();
+    if (!item.isNull()) {
+        KFileItemListProperties capabilities(KFileItemList() << item);
+        m_isFolderWritable = capabilities.supportsWriting();
+    }
+    if (m_isFolderWritable != wasFolderWritable) {
+        emit writeStateChanged(m_isFolderWritable);
+    }
+}
+
+DolphinView::ViewAccessor::ViewAccessor() :
+    m_rootUrl(),
     m_iconsView(0),
     m_detailsView(0),
     m_columnsContainer(0),
-    m_proxyModel(proxyModel),
+    m_dolphinModel(0),
+    m_proxyModel(0),
     m_dragSource(0)
 {
+    DolphinDirLister* dirLister = new DolphinDirLister();
+    dirLister->setAutoUpdate(true);
+    dirLister->setDelayedMimeTypes(true);
+
+    m_dolphinModel = new DolphinModel();
+    m_dolphinModel->setDirLister(dirLister);  // m_dolphinModel takes ownership of dirLister
+    m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory);
+
+    m_proxyModel = new DolphinSortFilterProxyModel();
+    m_proxyModel->setSourceModel(m_dolphinModel);
+    m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
 }
 
 DolphinView::ViewAccessor::~ViewAccessor()
 {
+    delete m_proxyModel;
+    m_proxyModel = 0;
+
+    delete m_dolphinModel;
+    m_dolphinModel = 0;
+
     delete m_dragSource;
     m_dragSource = 0;
 }
@@ -1393,6 +1459,12 @@ void DolphinView::ViewAccessor::createView(QWidget* parent,
         m_columnsContainer = new DolphinColumnViewContainer(parent,
                                                             dolphinViewController,
                                                             viewModeController);
+        if (!m_rootUrl.isEmpty() && m_rootUrl.isParentOf(viewModeController->url())) {
+            // The column-view must show several columns starting with m_rootUrl as
+            // first column and viewModeController->url() as last column.
+            m_columnsContainer->showColumn(m_rootUrl);
+            m_columnsContainer->showColumn(viewModeController->url());
+        }
         break;
 
     default:
@@ -1402,35 +1474,40 @@ void DolphinView::ViewAccessor::createView(QWidget* parent,
 
 void DolphinView::ViewAccessor::deleteView()
 {
-    QAbstractItemView* view = itemView();
-    if (view != 0) {
-        if (DragAndDropHelper::instance().isDragSource(view)) {
-            // The view is a drag source (the feature "Open folders
-            // during drag operations" is used). Deleting the view
-            // during an ongoing drag operation is not allowed, so
-            // this will postponed.
-            if (m_dragSource != 0) {
-                // the old stored view is obviously not the drag source anymore
-                m_dragSource->deleteLater();
-                m_dragSource = 0;
+    if (m_columnsContainer != 0) {
+        m_columnsContainer->close();
+        m_columnsContainer->disconnect();
+        m_columnsContainer->deleteLater();
+        m_columnsContainer = 0;
+    } else {
+        QAbstractItemView* view = itemView();
+        if (view != 0) {
+            view->close();
+            view->disconnect();
+
+            if (DragAndDropHelper::instance().isDragSource(view)) {
+                // The view is a drag source (the feature "Open folders
+                // during drag operations" is used). Deleting the view
+                // during an ongoing drag operation is not allowed, so
+                // this will postponed.
+                if (m_dragSource != 0) {
+                    // the old stored view is obviously not the drag source anymore
+                    m_dragSource->deleteLater();
+                    m_dragSource = 0;
+                }
+                view->hide();
+                m_dragSource = view;
+            } else {
+                view->deleteLater();
+                view = 0;
             }
-            view->hide();
-            m_dragSource = view;
-        } else {
-            view->deleteLater();
         }
-    }
 
-    m_iconsView = 0;
-    m_detailsView = 0;
-
-    if (m_columnsContainer != 0) {
-        m_columnsContainer->deleteLater();
+        m_iconsView = 0;
+        m_detailsView = 0;
     }
-    m_columnsContainer = 0;
 }
 
-
 void DolphinView::ViewAccessor::prepareUrlChange(const KUrl& url)
 {
     if (m_columnsContainer != 0) {
@@ -1468,9 +1545,14 @@ QWidget* DolphinView::ViewAccessor::layoutTarget() const
     return itemView();
 }
 
+void DolphinView::ViewAccessor::setRootUrl(const KUrl& rootUrl)
+{
+    m_rootUrl = rootUrl;
+}
+
 KUrl DolphinView::ViewAccessor::rootUrl() const
 {
-    return (m_columnsContainer != 0) ? m_columnsContainer->rootUrl() : KUrl();
+    return (m_columnsContainer != 0) ? m_columnsContainer->rootUrl() : m_rootUrl;
 }
 
 bool DolphinView::ViewAccessor::supportsCategorizedSorting() const
@@ -1483,7 +1565,6 @@ bool DolphinView::ViewAccessor::itemsExpandable() const
     return (m_detailsView != 0) && m_detailsView->itemsExpandable();
 }
 
-
 QSet<KUrl> DolphinView::ViewAccessor::expandedUrls() const
 {
     if (m_detailsView != 0) {
@@ -1534,26 +1615,4 @@ KDirLister* DolphinView::ViewAccessor::dirLister() const
     return dirModel()->dirLister();
 }
 
-void DolphinView::slotRedirection(const KUrl& oldUrl, const KUrl& newUrl)
-{
-    if (oldUrl.equals(url(), KUrl::CompareWithoutTrailingSlash)) {
-        emit redirection(oldUrl, newUrl);
-        m_viewModeController->redirectToUrl(newUrl); // #186947
-    }
-}
-
-void DolphinView::restoreContentsPosition()
-{
-    if (!m_restoredContentsPosition.isNull()) {
-        const int x = m_restoredContentsPosition.x();
-        const int y = m_restoredContentsPosition.y();
-        m_restoredContentsPosition = QPoint();
-
-        QAbstractItemView* view = m_viewAccessor.itemView();
-        Q_ASSERT(view != 0);
-        view->horizontalScrollBar()->setValue(x);
-        view->verticalScrollBar()->setValue(y);
-    }
-}
-
 #include "dolphinview.moc"