]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/dolphincolumnview.cpp
Let the user choose if folders are always shown first in the views of
[dolphin.git] / src / dolphincolumnview.cpp
index c0f08eaeb2b0edf3d5ff94aa51403ba4d1b78e84..f34be92e9b58e96809a1c3ef9a0eaeb66108cea5 100644 (file)
 
 #include "dolphincolumnview.h"
 
-#include "dolphinmodel.h"
 #include "dolphincolumnwidget.h"
 #include "dolphincontroller.h"
-#include "dolphindirlister.h"
-#include "dolphinmodel.h"
-#include "dolphinsortfilterproxymodel.h"
-#include "dolphinsettings.h"
+#include "settings/dolphinsettings.h"
+#include "zoomlevelinfo.h"
 
 #include "dolphin_columnmodesettings.h"
 
-#include <kcolorutils.h>
-#include <kcolorscheme.h>
-#include <kdirlister.h>
+#include <kfilepreviewgenerator.h>
 
-#include <QAbstractProxyModel>
-#include <QApplication>
 #include <QPoint>
 #include <QScrollBar>
-#include <QTimer>
 #include <QTimeLine>
 
 DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* controller) :
@@ -47,7 +39,9 @@ DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* control
     m_index(-1),
     m_contentX(0),
     m_columns(),
-    m_animation(0)
+    m_emptyViewport(0),
+    m_animation(0),
+    m_nameFilter()
 {
     Q_ASSERT(controller != 0);
 
@@ -55,22 +49,29 @@ DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* control
     setDragDropMode(QAbstractItemView::DragDrop);
     setDropIndicatorShown(false);
     setSelectionMode(ExtendedSelection);
+    setFocusPolicy(Qt::NoFocus);
+    setFrameShape(QFrame::NoFrame);
+    setLayoutDirection(Qt::LeftToRight);
 
-    connect(this, SIGNAL(entered(const QModelIndex&)),
-            controller, SLOT(emitItemEntered(const QModelIndex&)));
     connect(this, SIGNAL(viewportEntered()),
             controller, SLOT(emitViewportEntered()));
-    connect(controller, SIGNAL(zoomIn()),
-            this, SLOT(zoomIn()));
-    connect(controller, SIGNAL(zoomOut()),
-            this, SLOT(zoomOut()));
-    connect(controller, SIGNAL(showHiddenFilesChanged(bool)),
-            this, SLOT(slotShowHiddenFilesChanged(bool)));
-    connect(controller, SIGNAL(showPreviewChanged(bool)),
-            this, SLOT(slotShowPreviewChanged(bool)));
+    connect(controller, SIGNAL(zoomLevelChanged(int)),
+            this, SLOT(setZoomLevel(int)));
     connect(controller, SIGNAL(activationChanged(bool)),
             this, SLOT(updateColumnsBackground(bool)));
 
+    const DolphinView* view = controller->dolphinView();
+    connect(view, SIGNAL(sortingChanged(DolphinView::Sorting)),
+            this, SLOT(slotSortingChanged(DolphinView::Sorting)));
+    connect(view, SIGNAL(sortOrderChanged(Qt::SortOrder)),
+            this, SLOT(slotSortOrderChanged(Qt::SortOrder)));
+    connect(view, SIGNAL(sortFoldersFirstChanged(bool)),
+            this, SLOT(slotSortFoldersFirstChanged(bool)));
+    connect(view, SIGNAL(showHiddenFilesChanged()),
+            this, SLOT(slotShowHiddenFilesChanged()));
+    connect(view, SIGNAL(showPreviewChanged()),
+            this, SLOT(slotShowPreviewChanged()));
+
     connect(horizontalScrollBar(), SIGNAL(valueChanged(int)),
             this, SLOT(moveContentHorizontally(int)));
 
@@ -81,7 +82,10 @@ DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* control
     m_columns.append(column);
     setActiveColumnIndex(0);
 
-    updateDecorationSize();
+    m_emptyViewport = new QFrame(viewport());
+    m_emptyViewport->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+
+    updateDecorationSize(view->showPreview());
     updateColumnsBackground(true);
 }
 
@@ -92,9 +96,7 @@ DolphinColumnView::~DolphinColumnView()
 QModelIndex DolphinColumnView::indexAt(const QPoint& point) const
 {
     foreach (DolphinColumnWidget* column, m_columns) {
-        const QPoint topLeft = column->frameGeometry().topLeft();
-        const QPoint adjustedPoint(point.x() - topLeft.x(), point.y() - topLeft.y());
-        const QModelIndex index = column->indexAt(adjustedPoint);
+        const QModelIndex index = column->indexAt(columnPosition(column, point));
         if (index.isValid()) {
             return index;
         }
@@ -103,6 +105,18 @@ QModelIndex DolphinColumnView::indexAt(const QPoint& point) const
     return QModelIndex();
 }
 
+KFileItem DolphinColumnView::itemAt(const QPoint& point) const
+{
+    foreach (DolphinColumnWidget* column, m_columns) {
+        KFileItem item = column->itemAt(columnPosition(column, point));
+        if (!item.isNull()) {
+            return item;
+        }
+    }
+
+    return KFileItem();
+}
+
 void DolphinColumnView::scrollTo(const QModelIndex& index, ScrollHint hint)
 {
     activeColumn()->scrollTo(index, hint);
@@ -141,14 +155,17 @@ void DolphinColumnView::setRootUrl(const KUrl& url)
 
 void DolphinColumnView::setNameFilter(const QString& nameFilter)
 {
-    foreach (DolphinColumnWidget* column, m_columns) {
-        column->setNameFilter(nameFilter);
+    if (nameFilter != m_nameFilter) {
+        m_nameFilter = nameFilter;
+        foreach (DolphinColumnWidget* column, m_columns) {
+            column->setNameFilter(nameFilter);
+        }
     }
 }
 
 QString DolphinColumnView::nameFilter() const
 {
-    return activeColumn()->nameFilter();
+    return m_nameFilter;
 }
 
 KUrl DolphinColumnView::rootUrl() const
@@ -168,6 +185,7 @@ void DolphinColumnView::showColumn(const KUrl& url)
         if (column->url() == url) {
             // the column represents already the requested URL, hence activate it
             requestActivation(column);
+            layoutColumns();
             return;
         } else if (!column->url().isParentOf(url)) {
             // the column is no parent of the requested URL, hence
@@ -176,7 +194,7 @@ void DolphinColumnView::showColumn(const KUrl& url)
                 QList<DolphinColumnWidget*>::iterator start = m_columns.begin() + columnIndex;
                 QList<DolphinColumnWidget*>::iterator end = m_columns.end();
                 for (QList<DolphinColumnWidget*>::iterator it = start; it != end; ++it) {
-                    (*it)->deleteLater();
+                    deleteColumn(*it);
                 }
                 m_columns.erase(start, end);
 
@@ -245,6 +263,21 @@ void DolphinColumnView::showColumn(const KUrl& url)
     assureVisibleActiveColumn();
 }
 
+void DolphinColumnView::editItem(const KFileItem& item)
+{
+    activeColumn()->editItem(item);
+}
+
+KFileItemList DolphinColumnView::selectedItems() const
+{
+    return activeColumn()->selectedItems();
+}
+
+QMimeData* DolphinColumnView::selectionMimeData() const
+{
+    return activeColumn()->selectionMimeData();
+}
+
 void DolphinColumnView::selectAll()
 {
     activeColumn()->selectAll();
@@ -301,13 +334,12 @@ void DolphinColumnView::setSelection(const QRect& rect, QItemSelectionModel::Sel
 {
     Q_UNUSED(rect);
     Q_UNUSED(flags);
-    //activeColumn()->setSelection(rect, flags);
 }
 
 QRegion DolphinColumnView::visualRegionForSelection(const QItemSelection& selection) const
 {
     Q_UNUSED(selection);
-    return QRegion(); //activeColumn()->visualRegionForSelection(selection);
+    return QRegion();
 }
 
 int DolphinColumnView::horizontalOffset() const
@@ -331,32 +363,32 @@ void DolphinColumnView::resizeEvent(QResizeEvent* event)
     QAbstractItemView::resizeEvent(event);
     layoutColumns();
     updateScrollBar();
+    assureVisibleActiveColumn();
 }
 
-void DolphinColumnView::zoomIn()
+void DolphinColumnView::wheelEvent(QWheelEvent* event)
 {
-    if (isZoomInPossible()) {
-        ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-        switch (settings->iconSize()) {
-        case KIconLoader::SizeSmall:  settings->setIconSize(KIconLoader::SizeMedium); break;
-        case KIconLoader::SizeMedium: settings->setIconSize(KIconLoader::SizeLarge); break;
-        default: Q_ASSERT(false); break;
-        }
-        updateDecorationSize();
+    // let Ctrl+wheel events propagate to the DolphinView for icon zooming
+    if ((event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier) {
+        event->ignore();
+    } else {
+        QAbstractItemView::wheelEvent(event);
     }
 }
 
-void DolphinColumnView::zoomOut()
+void DolphinColumnView::setZoomLevel(int level)
 {
-    if (isZoomOutPossible()) {
-        ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-        switch (settings->iconSize()) {
-        case KIconLoader::SizeLarge:  settings->setIconSize(KIconLoader::SizeMedium); break;
-        case KIconLoader::SizeMedium: settings->setIconSize(KIconLoader::SizeSmall); break;
-        default: Q_ASSERT(false); break;
-        }
-        updateDecorationSize();
+    const int size = ZoomLevelInfo::iconSizeForZoomLevel(level);
+    ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
+
+    const bool showPreview = m_controller->dolphinView()->showPreview();
+    if (showPreview) {
+        settings->setPreviewSize(size);
+    } else {
+        settings->setIconSize(size);
     }
+
+    updateDecorationSize(showPreview);
 }
 
 void DolphinColumnView::moveContentHorizontally(int x)
@@ -365,21 +397,20 @@ void DolphinColumnView::moveContentHorizontally(int x)
     layoutColumns();
 }
 
-void DolphinColumnView::updateDecorationSize()
+void DolphinColumnView::updateDecorationSize(bool showPreview)
 {
     ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-    const int iconSize = settings->iconSize();
+    const int iconSize = showPreview ? settings->previewSize() : settings->iconSize();
+    const QSize size(iconSize, iconSize);
+    setIconSize(size);
 
     foreach (QObject* object, viewport()->children()) {
         if (object->inherits("QListView")) {
             DolphinColumnWidget* widget = static_cast<DolphinColumnWidget*>(object);
-            widget->setDecorationSize(QSize(iconSize, iconSize));
+            widget->setDecorationSize(size);
         }
     }
 
-    m_controller->setZoomInPossible(isZoomInPossible());
-    m_controller->setZoomOutPossible(isZoomOutPossible());
-
     doItemsLayout();
 }
 
@@ -392,11 +423,12 @@ void DolphinColumnView::updateColumnsBackground(bool active)
     m_active = active;
 
     // dim the background of the viewport
-    QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
-    color.setAlpha(150);
+    const QPalette::ColorRole role = viewport()->backgroundRole();
+    QColor background = viewport()->palette().color(role);
+    background.setAlpha(0);  // make background transparent
 
-    QPalette palette;
-    palette.setColor(viewport()->backgroundRole(), color);
+    QPalette palette = viewport()->palette();
+    palette.setColor(role, background);
     viewport()->setPalette(palette);
 
     foreach (DolphinColumnWidget* column, m_columns) {
@@ -404,30 +436,42 @@ void DolphinColumnView::updateColumnsBackground(bool active)
     }
 }
 
-void DolphinColumnView::slotShowHiddenFilesChanged(bool show)
+void DolphinColumnView::slotSortingChanged(DolphinView::Sorting sorting)
 {
     foreach (DolphinColumnWidget* column, m_columns) {
-        column->setShowHiddenFiles(show);
+        column->setSorting(sorting);
     }
 }
 
-void DolphinColumnView::slotShowPreviewChanged(bool show)
+void DolphinColumnView::slotSortOrderChanged(Qt::SortOrder order)
 {
     foreach (DolphinColumnWidget* column, m_columns) {
-        column->setShowPreview(show);
+        column->setSortOrder(order);
     }
 }
 
-bool DolphinColumnView::isZoomInPossible() const
+void DolphinColumnView::slotSortFoldersFirstChanged(bool foldersFirst)
 {
-    ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-    return settings->iconSize() < KIconLoader::SizeLarge;
+    foreach (DolphinColumnWidget* column, m_columns) {
+        column->setSortFoldersFirst(foldersFirst);
+    }
 }
 
-bool DolphinColumnView::isZoomOutPossible() const
+void DolphinColumnView::slotShowHiddenFilesChanged()
 {
-    ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
-    return settings->iconSize() > KIconLoader::SizeSmall;
+    const bool show = m_controller->dolphinView()->showHiddenFiles();
+    foreach (DolphinColumnWidget* column, m_columns) {
+        column->setShowHiddenFiles(show);
+    }
+}
+
+void DolphinColumnView::slotShowPreviewChanged()
+{
+    const bool show = m_controller->dolphinView()->showPreview();
+    updateDecorationSize(show);
+    foreach (DolphinColumnWidget* column, m_columns) {
+        column->setShowPreview(show);
+    }
 }
 
 void DolphinColumnView::setActiveColumnIndex(int index)
@@ -449,29 +493,40 @@ void DolphinColumnView::setActiveColumnIndex(int index)
 
 void DolphinColumnView::layoutColumns()
 {
+    const int gap = 4;
+
     ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
     const int columnWidth = settings->columnWidth();
+
+    QRect emptyViewportRect;
     if (isRightToLeft()) {
         int x = viewport()->width() - columnWidth + m_contentX;
         foreach (DolphinColumnWidget* column, m_columns) {
-            column->setGeometry(QRect(x, 0, columnWidth, viewport()->height()));
+            column->setGeometry(QRect(x, 0, columnWidth - gap, viewport()->height()));
             x -= columnWidth;
         }
+        emptyViewportRect = QRect(0, 0, x + columnWidth - gap, viewport()->height());
     } else {
         int x = m_contentX;
         foreach (DolphinColumnWidget* column, m_columns) {
-            column->setGeometry(QRect(x, 0, columnWidth, viewport()->height()));
+            column->setGeometry(QRect(x, 0, columnWidth - gap, viewport()->height()));
             x += columnWidth;
         }
+        emptyViewportRect = QRect(x, 0, viewport()->width() - x - gap, viewport()->height());
+    }
+
+    if (emptyViewportRect.isValid()) {
+        m_emptyViewport->show();
+        m_emptyViewport->setGeometry(emptyViewportRect);
+    } else {
+        m_emptyViewport->hide();
     }
 }
 
 void DolphinColumnView::updateScrollBar()
 {
-    int contentWidth = 0;
-    foreach (DolphinColumnWidget* column, m_columns) {
-        contentWidth += column->width();
-    }
+    ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
+    const int contentWidth = m_columns.count() * settings->columnWidth();
 
     horizontalScrollBar()->setPageStep(contentWidth);
     horizontalScrollBar()->setRange(0, contentWidth - viewport()->width());
@@ -481,7 +536,10 @@ void DolphinColumnView::assureVisibleActiveColumn()
 {
     const int viewportWidth = viewport()->width();
     const int x = activeColumn()->x();
-    const int width = activeColumn()->width();
+
+    ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
+    const int width = settings->columnWidth();
+
     if (x + width > viewportWidth) {
         const int newContentX = m_contentX - x - width + viewportWidth;
         if (isRightToLeft()) {
@@ -489,7 +547,9 @@ void DolphinColumnView::assureVisibleActiveColumn()
         } else {
             m_animation->setFrameRange(-m_contentX, -newContentX);
         }
-        m_animation->start();
+        if (m_animation->state() != QTimeLine::Running) {
+           m_animation->start();
+        }
     } else if (x < 0) {
         const int newContentX = m_contentX - x;
         if (isRightToLeft()) {
@@ -497,12 +557,15 @@ void DolphinColumnView::assureVisibleActiveColumn()
         } else {
             m_animation->setFrameRange(-m_contentX, -newContentX);
         }
-        m_animation->start();
+        if (m_animation->state() != QTimeLine::Running) {
+           m_animation->start();
+        }
     }
 }
 
 void DolphinColumnView::requestActivation(DolphinColumnWidget* column)
 {
+    m_controller->setItemView(column);
     if (column->isActive()) {
         assureVisibleActiveColumn();
     } else {
@@ -522,7 +585,7 @@ void DolphinColumnView::removeAllColumns()
     QList<DolphinColumnWidget*>::iterator start = m_columns.begin() + 1;
     QList<DolphinColumnWidget*>::iterator end = m_columns.end();
     for (QList<DolphinColumnWidget*>::iterator it = start; it != end; ++it) {
-        (*it)->deleteLater();
+        deleteColumn(*it);
     }
     m_columns.erase(start, end);
     m_index = 0;
@@ -530,4 +593,29 @@ void DolphinColumnView::removeAllColumns()
     assureVisibleActiveColumn();
 }
 
+QPoint DolphinColumnView::columnPosition(DolphinColumnWidget* column, const QPoint& point) const
+{
+    const QPoint topLeft = column->frameGeometry().topLeft();
+    return QPoint(point.x() - topLeft.x(), point.y() - topLeft.y());
+}
+
+void DolphinColumnView::deleteColumn(DolphinColumnWidget* column)
+{
+    if (column != 0) {
+        if (m_controller->itemView() == column) {
+            m_controller->setItemView(0);
+        }
+        // deleteWhenNotDragSource(column) does not necessarily delete column,
+        // and we want its preview generator destroyed immediately.
+        column->m_previewGenerator->deleteLater();
+        column->m_previewGenerator = 0;
+        column->hide();
+        // Prevent automatic destruction of column when this DolphinColumnView
+        // is destroyed.
+        column->setParent(0);
+        column->disconnect();
+        emit requestColumnDeletion(column);
+    }
+}
+
 #include "dolphincolumnview.moc"