]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/views/dolphinview.cpp
After disconnecting and reconnecting to the selectionChangedSignal() it must be check...
[dolphin.git] / src / views / dolphinview.cpp
index 73a0c63c3072761c1091775a37268f798ec7122a..238ce7ebcf829c88dc88418da480868d5079165f 100644 (file)
@@ -45,7 +45,6 @@
 #include <konq_fileitemcapabilities.h>
 #include <konq_operations.h>
 #include <konqmimedata.h>
-#include <kstringhandler.h>
 #include <ktoggleaction.h>
 #include <kurl.h>
 
@@ -55,7 +54,7 @@
 #include "dolphinviewcontroller.h"
 #include "dolphindetailsview.h"
 #include "dolphinfileitemdelegate.h"
-#include "dolphinnewmenuobserver.h"
+#include "dolphinnewfilemenuobserver.h"
 #include "dolphinsortfilterproxymodel.h"
 #include "dolphin_detailsmodesettings.h"
 #include "dolphiniconsview.h"
 #include "zoomlevelinfo.h"
 #include "dolphindetailsviewexpander.h"
 
-/**
- * Helper function for sorting items with qSort() in
- * DolphinView::renameSelectedItems().
- */
-bool lessThan(const KFileItem& item1, const KFileItem& item2)
-{
-    return KStringHandler::naturalCompare(item1.name(), item2.name()) < 0;
-}
-
 DolphinView::DolphinView(QWidget* parent,
                          const KUrl& url,
                          DolphinSortFilterProxyModel* proxyModel) :
@@ -86,14 +76,12 @@ DolphinView::DolphinView(QWidget* parent,
     m_storedCategorizedSorting(false),
     m_tabsForFiles(false),
     m_isContextMenuOpen(false),
-    m_ignoreViewProperties(false),
     m_assureVisibleCurrentIndex(false),
     m_mode(DolphinView::IconsView),
     m_topLayout(0),
     m_dolphinViewController(0),
     m_viewModeController(0),
     m_viewAccessor(proxyModel),
-    m_selectionModel(0),
     m_selectionChangedTimer(0),
     m_rootUrl(),
     m_activeItemUrl(),
@@ -150,7 +138,7 @@ DolphinView::DolphinView(QWidget* parent,
     // 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
     // creation is done asynchronously, several signals must be checked:
-    connect(&DolphinNewMenuObserver::instance(), SIGNAL(itemCreated(const KUrl&)),
+    connect(&DolphinNewFileMenuObserver::instance(), SIGNAL(itemCreated(const KUrl&)),
             this, SLOT(observeCreatedItem(const KUrl&)));
 
     m_selectionChangedTimer = new QTimer(this);
@@ -439,10 +427,13 @@ void DolphinView::reload()
     restoreState(restoreStream);
 }
 
-void DolphinView::refresh()
+void DolphinView::stopLoading()
 {
-    m_ignoreViewProperties = false;
+    m_viewAccessor.dirLister()->stop();
+}
 
+void DolphinView::refresh()
+{
     const bool oldActivationState = m_active;
     const int oldZoomLevel = m_viewModeController->zoomLevel();
     m_active = true;
@@ -540,29 +531,36 @@ QList<QAction*> DolphinView::versionControlActions(const KFileItemList& items) c
 
 void DolphinView::setUrl(const KUrl& url)
 {
-    if (m_viewModeController->url() != url) {
-        m_newFileNames.clear();
+    if (m_viewModeController->url() == url) {
+        return;
+    }
 
-        m_viewModeController->setUrl(url); // emits urlChanged, which we forward
-        m_viewAccessor.prepareUrlChange(url);
-        applyViewProperties();
-        loadDirectory(url);
+    // 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.
+    const bool hadSelection = hasSelection();
+    QAbstractItemView* view = m_viewAccessor.itemView();
+    disconnect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+               this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
 
-        // When changing the URL there is no need to keep the version
-        // data of the previous URL.
-        m_viewAccessor.dirModel()->clearVersionData();
+    m_newFileNames.clear();
 
-        emit startedPathLoading(url);
-    }
+    m_viewModeController->setUrl(url); // emits urlChanged, which we forward
+    m_viewAccessor.prepareUrlChange(url);
+    applyViewProperties();
+    loadDirectory(url);
 
-    // the selection model might have changed in the case of a column view
-    QItemSelectionModel* selectionModel = m_viewAccessor.itemView()->selectionModel();
-    if (m_selectionModel != selectionModel) {
-        disconnect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-                   this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
-        m_selectionModel = selectionModel;
-        connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
-                this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
+    // 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
+    view = m_viewAccessor.itemView();
+    connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+            this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
+    if (hadSelection || hasSelection()) {
+        emitSelectionChangedSignal();
     }
 }
 
@@ -597,82 +595,17 @@ void DolphinView::renameSelectedItems()
         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 (DolphinSettings::instance().generalSettings()->renameInline()) {
-        Q_ASSERT(itemCount == 1);
+    if ((itemCount == 1) && DolphinSettings::instance().generalSettings()->renameInline()) {
         const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForItem(items.first());
         const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->mapFromSource(dirIndex);
         m_viewAccessor.itemView()->edit(proxyIndex);
     } else {
-        Q_ASSERT(itemCount == 1);
-
-        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;
-
-        const KUrl& oldUrl = items.first().url();
-        KUrl newUrl = oldUrl;
-        newUrl.setFileName(newName);
-        KonqOperations::rename(this, oldUrl, newUrl);
+        RenameDialog* dialog = new RenameDialog(this, items);
+        dialog->setAttribute(Qt::WA_DeleteOnClose);
+        dialog->show();
+        dialog->raise();
+        dialog->activateWindow();
     }
-
-    // assure that the current index remains visible when KDirLister
-    // will notify the view about changed items
-    m_assureVisibleCurrentIndex = true;
 }
 
 void DolphinView::trashSelectedItems()
@@ -903,7 +836,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,
@@ -974,18 +908,18 @@ void DolphinView::updateAdditionalInfoActions(KActionCollection* collection)
 {
     const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
 
-    const KFileItemDelegate::InformationList checkedInfos = m_viewAccessor.itemDelegate()->showInformation();
-    const KFileItemDelegate::InformationList infos = infoAccessor.keys();
+    const KFileItemDelegate::InformationList checkedInfo = m_viewAccessor.itemDelegate()->showInformation();
+    const KFileItemDelegate::InformationList infoKeys = infoAccessor.keys();
 
     const bool enable = (m_mode == DolphinView::DetailsView) ||
                         (m_mode == DolphinView::IconsView);
 
-    foreach (const KFileItemDelegate::Information& info, infos) {
+    foreach (const KFileItemDelegate::Information& info, infoKeys) {
         const QString name = infoAccessor.actionCollectionName(info, AdditionalInfoAccessor::AdditionalInfoType);
         QAction* action = collection->action(name);
         Q_ASSERT(action != 0);
         action->setEnabled(enable);
-        action->setChecked(checkedInfos.contains(info));
+        action->setChecked(checkedInfo.contains(info));
     }
 }
 
@@ -1162,6 +1096,8 @@ void DolphinView::slotLoadingCompleted()
     // Restore the contents position. This has to be done using a Qt::QueuedConnection
     // because the view might not be in its final state yet.
     QMetaObject::invokeMethod(this, "restoreContentsPosition", Qt::QueuedConnection);
+
+    emit finishedPathLoading(url());
 }
 
 void DolphinView::slotRefreshItems()
@@ -1190,10 +1126,6 @@ void DolphinView::loadDirectory(const KUrl& url, bool reload)
 
 void DolphinView::applyViewProperties()
 {
-    if (m_ignoreViewProperties) {
-        return;
-    }
-
     const ViewProperties props(rootUrl());
 
     const Mode mode = props.viewMode();
@@ -1260,13 +1192,6 @@ void DolphinView::applyViewProperties()
         // the used zoom level of the controller must be adjusted manually:
         updateZoomLevel(oldZoomLevel);
     }
-
-    if (DolphinSettings::instance().generalSettings()->globalViewProps()) {
-        // During the lifetime of a DolphinView instance the global view properties
-        // should not be changed. This allows e. g. to split a view and use different
-        // view properties for each view.
-        m_ignoreViewProperties = true;
-    }
 }
 
 void DolphinView::createView()
@@ -1274,6 +1199,7 @@ void DolphinView::createView()
     deleteView();
 
     Q_ASSERT(m_viewAccessor.itemView() == 0);
+    Q_ASSERT(m_dolphinViewController->itemView() == 0);
     m_viewAccessor.createView(this, m_dolphinViewController, m_viewModeController, m_mode);
 
     QAbstractItemView* view = m_viewAccessor.itemView();
@@ -1283,16 +1209,10 @@ void DolphinView::createView()
 
     m_dolphinViewController->setItemView(view);
 
-    // When changing the view mode, the selection is lost due to reinstantiating
-    // a new item view with a custom selection model. Pass the ownership of the
-    // selection model to DolphinView, so that it can be shared by all item views.
-    if (m_selectionModel != 0) {
-        view->setSelectionModel(m_selectionModel);
-    } else {
-        m_selectionModel = view->selectionModel();
-    }
-    m_selectionModel->setParent(this);
-    connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+    const int zoomLevel = ZoomLevelInfo::zoomLevelForIconSize(view->iconSize());
+    m_viewModeController->setZoomLevel(zoomLevel);
+
+    connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
             this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
 
     setFocusProxy(m_viewAccessor.layoutTarget());
@@ -1302,7 +1222,15 @@ 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) {
+        if (view->selectionModel() != 0) {
+            disconnect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+                       this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
+        }
+
         // 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
@@ -1310,13 +1238,7 @@ void DolphinView::deleteView()
         setFocusProxy(0);
         setFocus();
 
-        m_topLayout->removeWidget(view);
-        view->close();
-
-        // disconnect all signal/slots
-        disconnect(view);
         m_viewModeController->disconnect(view);
-        view->disconnect();
 
         m_viewAccessor.deleteView();
     }
@@ -1412,32 +1334,38 @@ 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;
 }