]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/views/dolphinview.cpp
Fix crash when expanding/closing a sub-tree
[dolphin.git] / src / views / dolphinview.cpp
index f429529de131406b0f01197f95a58db3ab8c8378..7cb594d8e91c825e2a90e67737c1cd745c863ac5 100644 (file)
 
 #include <QAbstractItemView>
 #include <QApplication>
+#include <QBoxLayout>
 #include <QClipboard>
+#include <QDropEvent>
+#include <QGraphicsSceneDragDropEvent>
 #include <QKeyEvent>
 #include <QItemSelection>
-#include <QBoxLayout>
 #include <QTimer>
 #include <QScrollBar>
 
 #include <KActionCollection>
 #include <KColorScheme>
 #include <KDirLister>
+#include <KDirModel>
 #include <KIconEffect>
 #include <KFileItem>
 #include <KFileItemListProperties>
 #include "dolphin_detailsmodesettings.h"
 #include "dolphin_generalsettings.h"
 #include "dolphinitemlistcontainer.h"
+#include "draganddrophelper.h"
 #include "renamedialog.h"
 #include "settings/dolphinsettings.h"
+#include "versioncontrol/versioncontrolobserver.h"
 #include "viewmodecontroller.h"
 #include "viewproperties.h"
 #include "views/tooltips/tooltipmanager.h"
@@ -88,7 +93,8 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
     m_currentItemIndex(-1),
     m_restoredContentsPosition(),
     m_createdItemUrl(),
-    m_selectedItems()
+    m_selectedItems(),
+    m_versionControlObserver(0)
 {
     m_topLayout = new QVBoxLayout(this);
     m_topLayout->setSpacing(0);
@@ -114,7 +120,7 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
             this, SLOT(updateSortFoldersFirst(bool)));
     connect(m_dolphinViewController, SIGNAL(additionalInfoChanged(QList<DolphinView::AdditionalInfo>)),
             this, SLOT(updateAdditionalInfo(QList<DolphinView::AdditionalInfo>)));*/
-    //connect(m_dolphinViewController, SIGNAL(itemTriggered(KFileItem)),
+    //connect(m_dolphinViewController, SIGNAL(itemActivated(KFileItem)),
     //        this, SLOT(triggerItem(KFileItem)));
     //connect(m_dolphinViewController, SIGNAL(tabRequested(KUrl)),
     //        this, SIGNAL(tabRequested(KUrl)));
@@ -164,11 +170,15 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
 
     KItemListController* controller = m_container->controller();
     controller->setSelectionBehavior(KItemListController::MultiSelection);
-    connect(controller, SIGNAL(itemClicked(int,Qt::MouseButton)),
-            this, SLOT(slotItemClicked(int,Qt::MouseButton)));
+    connect(controller, SIGNAL(itemActivated(int)),
+            this, SLOT(slotItemActivated(int)));
+    connect(controller, SIGNAL(itemMiddleClicked(int)), this, SLOT(slotItemMiddleClicked(int)));
+    connect(controller, SIGNAL(contextMenuRequested(int,QPointF)), this, SLOT(slotContextMenuRequested(int,QPointF)));
     connect(controller, SIGNAL(itemExpansionToggleClicked(int)), this, SLOT(slotItemExpansionToggleClicked(int)));
     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(modelChanged(KItemModelBase*,KItemModelBase*)), this, SLOT(slotModelChanged(KItemModelBase*,KItemModelBase*)));
 
     KItemListSelectionManager* selectionManager = controller->selectionManager();
     connect(selectionManager, SIGNAL(selectionChanged(QSet<int>,QSet<int>)),
@@ -176,6 +186,12 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
 
     m_toolTipManager = new ToolTipManager(this);
 
+    m_versionControlObserver = new VersionControlObserver(this);
+    m_versionControlObserver->setModel(fileItemModel());
+    connect(m_versionControlObserver, SIGNAL(infoMessage(QString)), this, SIGNAL(infoMessage(QString)));
+    connect(m_versionControlObserver, SIGNAL(errorMessage(QString)), this, SIGNAL(errorMessage(QString)));
+    connect(m_versionControlObserver, SIGNAL(operationCompletedMessage(QString)), this, SIGNAL(operationCompletedMessage(QString)));
+
     applyViewProperties();
     m_topLayout->addWidget(m_container);
 
@@ -297,13 +313,22 @@ void DolphinView::markUrlsAsSelected(const QList<KUrl>& urls)
 
 void DolphinView::setItemSelectionEnabled(const QRegExp& pattern, bool enabled)
 {
-    Q_UNUSED(pattern);
-    Q_UNUSED(enabled);
-    /*const QItemSelection matchingIndexes = childrenMatchingPattern(QModelIndex(), pattern);
-    const QItemSelectionModel::SelectionFlags command = enabled
-                                                      ? QItemSelectionModel::Select
-                                                      : QItemSelectionModel::Deselect;
-    m_viewAccessor.itemView()->selectionModel()->select(matchingIndexes, command);*/
+    const KItemListSelectionManager::SelectionMode mode = enabled
+                                                        ? KItemListSelectionManager::Select
+                                                        : KItemListSelectionManager::Deselect;
+    const KFileItemModel* model = fileItemModel();
+    KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
+
+    for (int index = 0; index < model->count(); index++) {
+        const KFileItem item = model->fileItem(index);
+        if (pattern.exactMatch(item.name())) {
+            // An alternative approach would be to store the matching items in a QSet<int> and
+            // select them in one go after the loop, but we'd need a new function
+            // KItemListSelectionManager::setSelected(QSet<int>, SelectionMode mode)
+            // for that.
+            selectionManager->setSelected(index, 1, mode);
+        }
+    }
 }
 
 void DolphinView::setZoomLevel(int level)
@@ -493,8 +518,16 @@ QString DolphinView::statusBarText() const
 
 QList<QAction*> DolphinView::versionControlActions(const KFileItemList& items) const
 {
-    Q_UNUSED(items);
-    return QList<QAction*>(); //m_dolphinViewController->versionControlActions(items);
+    QList<QAction*> actions;
+
+    if (items.isEmpty()) {
+        const KFileItem item = fileItemModel()->rootItem();
+        actions = m_versionControlObserver->actions(KFileItemList() << item);
+    } else {
+        actions = m_versionControlObserver->actions(items);
+    }
+
+    return actions;
 }
 
 void DolphinView::setUrl(const KUrl& url)
@@ -529,23 +562,13 @@ void DolphinView::selectAll()
 
 void DolphinView::invertSelection()
 {
-     KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
-     const QSet<int> selectedItems = selectionManager->selectedItems();
-     QSet<int> invertedSelectedItems;
-
-     const int maxIndex = fileItemModel()->count() - 1;
-     for (int i = 0; i <= maxIndex; ++i) {
-         if (!selectedItems.contains(i)) {
-             invertedSelectedItems.insert(i);
-         }
-     }
-
-     selectionManager->setSelectedItems(invertedSelectedItems);
+    KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
+    selectionManager->setSelected(0, fileItemModel()->count(), KItemListSelectionManager::Toggle);
 }
 
 void DolphinView::clearSelection()
 {
-    //m_viewAccessor.itemView()->clearSelection();
+    m_container->controller()->selectionManager()->clearSelection();
 }
 
 void DolphinView::renameSelectedItems()
@@ -678,34 +701,67 @@ void DolphinView::contextMenuEvent(QContextMenuEvent* event)
     const KItemListView* view = m_container->controller()->view();
     if (view->itemAt(pos) < 0) {
         // Only open the context-menu if the cursor is above the viewport
-        // (the context-menu for items is handled in slotItemClicked())
+        // (the context-menu for items is handled in slotContextMenuRequested())
         requestContextMenu(KFileItem(), url(), QList<QAction*>());
     }
 }
 
+void DolphinView::wheelEvent(QWheelEvent* event)
+{
+    if (event->modifiers().testFlag(Qt::ControlModifier)) {
+        const int numDegrees = event->delta() / 8;
+        const int numSteps = numDegrees / 15;
+
+        setZoomLevel(zoomLevel() + numSteps);
+    }
+    event->accept();
+}
+
 void DolphinView::activate()
 {
     setActive(true);
 }
 
-void DolphinView::slotItemClicked(int index, Qt::MouseButton button)
+void DolphinView::slotItemActivated(int index)
 {
-    const KFileItem item = fileItemModel()->fileItem(index);
+    Q_UNUSED(index);
 
-    if (button & Qt::LeftButton) {
-        emit itemTriggered(item); // caught by DolphinViewContainer or DolphinPart
-    } else if (button & Qt::MidButton) {
-        if (item.isDir() || isTabsForFilesEnabled()) {
-            emit tabRequested(item.url());
-        }
-    } else if (button & Qt::RightButton) {
-        if (GeneralSettings::showToolTips()) {
-            m_toolTipManager->hideToolTip();
+    const KFileItemList items = selectedItems();
+    if (items.isEmpty()) {
+        return;
+    }
+
+    if (items.count() == 1) {
+        emit itemActivated(items.at(0)); // caught by DolphinViewContainer or DolphinPart
+    } else {
+        foreach (const KFileItem& item, items) {
+            if (item.isDir()) {
+                emit tabRequested(item.url());
+            } else {
+                emit itemActivated(item);
+            }
         }
-        emit requestContextMenu(item, url(), QList<QAction*>());
     }
 }
 
+void DolphinView::slotItemMiddleClicked(int index)
+{
+    const KFileItem item = fileItemModel()->fileItem(index);
+    if (item.isDir() || isTabsForFilesEnabled()) {
+        emit tabRequested(item.url());
+    }
+}
+
+void DolphinView::slotContextMenuRequested(int index, const QPointF& pos)
+{
+    Q_UNUSED(pos);
+    if (GeneralSettings::showToolTips()) {
+        m_toolTipManager->hideToolTip();
+    }
+    const KFileItem item = fileItemModel()->fileItem(index);
+    emit requestContextMenu(item, url(), QList<QAction*>());
+}
+
 void DolphinView::slotItemExpansionToggleClicked(int index)
 {
     // TODO: When doing a model->setExpanded(false) it should
@@ -741,6 +797,28 @@ void DolphinView::slotItemUnhovered(int index)
     emit requestItemInfo(KFileItem());
 }
 
+void DolphinView::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event)
+{
+    const KFileItem destItem = fileItemModel()->fileItem(index);
+
+    QDropEvent dropEvent(event->pos().toPoint(),
+                         event->possibleActions(),
+                         event->mimeData(),
+                         event->buttons(),
+                         event->modifiers());
+
+    DragAndDropHelper::dropUrls(destItem, url(), &dropEvent, this);
+}
+
+void DolphinView::slotModelChanged(KItemModelBase* current, KItemModelBase* previous)
+{
+    Q_UNUSED(previous);
+    Q_ASSERT(qobject_cast<KFileItemModel*>(current));
+
+    KFileItemModel* fileItemModel = static_cast<KFileItemModel*>(current);
+    m_versionControlObserver->setModel(fileItemModel);
+}
+
 void DolphinView::slotSelectionChanged(const QSet<int>& current, const QSet<int>& previous)
 {
     const int currentCount = current.count();
@@ -831,7 +909,7 @@ bool DolphinView::isTabsForFilesEnabled() const
 
 bool DolphinView::itemsExpandable() const
 {
-    return false; //m_viewAccessor.itemsExpandable();
+    return m_mode == DetailsView;
 }
 
 void DolphinView::restoreState(QDataStream& stream)
@@ -1141,29 +1219,28 @@ void DolphinView::updateZoomLevel(int oldZoomLevel)
 
 KUrl::List DolphinView::simplifiedSelectedUrls() const
 {
-    Q_ASSERT(false); // TODO
     KUrl::List urls;
-/*
+
     const KFileItemList items = selectedItems();
     foreach (const KFileItem &item, items) {
         urls.append(item.url());
     }
 
-
     if (itemsExpandable()) {
+        // TODO: Check if we still need KDirModel for this in KDE 5.0
         urls = KDirModel::simplifiedUrlList(urls);
-    }*/
+    }
 
     return urls;
 }
 
 QMimeData* DolphinView::selectionMimeData() const
 {
-    /*const QAbstractItemView* view = m_viewAccessor.itemView();
-    Q_ASSERT((view) && (view->selectionModel()));
-    const QItemSelection selection = m_viewAccessor.proxyModel()->mapSelectionToSource(view->selectionModel()->selection());
-    return m_viewAccessor.dirModel()->mimeData(selection.indexes());*/
-    return 0;
+    const KFileItemModel* model = fileItemModel();
+    const KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager();
+    const QSet<int> selectedIndexes = selectionManager->selectedItems();
+
+    return model->createMimeData(selectedIndexes);
 }
 
 void DolphinView::markPastedUrlsAsSelected(const QMimeData* mimeData)
@@ -1172,32 +1249,6 @@ void DolphinView::markPastedUrlsAsSelected(const QMimeData* mimeData)
     markUrlsAsSelected(urls);
 }
 
-QItemSelection DolphinView::childrenMatchingPattern(const QModelIndex& parent, const QRegExp& pattern) const
-{
-    Q_UNUSED(parent);
-    Q_UNUSED(pattern);
-    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::updateWritableState()
 {
     const bool wasFolderWritable = m_isFolderWritable;