From 41c14c5f8ebc00ba443f13d300f5b445aee7aa1b Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Fri, 28 Aug 2009 21:04:15 +0000 Subject: [PATCH] I wanted to this for KDE 4.1 already, but well... Columview refactoring: Get rid of "isColumnView()" special cases in DolphinView and the interface code duplications due to delegating non-QAbstractItemView interfaces to the column view. This reduces the code size + complexity a lot and will make future maintainance of the columnview and DolphinView a lot easier. Currently there are some regressions in the column view, but this will be fixed during the next 14 days. svn path=/trunk/KDE/kdebase/apps/; revision=1016776 --- src/CMakeLists.txt | 2 +- src/dolphincolumnview.cpp | 930 +++++++++++++---------------- src/dolphincolumnview.h | 284 ++++----- src/dolphincolumnviewcontainer.cpp | 409 +++++++++++++ src/dolphincolumnviewcontainer.h | 152 +++++ src/dolphincolumnwidget.cpp | 87 ++- src/dolphincolumnwidget.h | 23 +- src/dolphindetailsview.cpp | 1 - src/dolphinpart.cpp | 7 +- src/dolphinview.cpp | 584 +++++++++--------- src/dolphinview.h | 96 +-- src/dolphinviewcontainer.cpp | 6 +- 12 files changed, 1526 insertions(+), 1055 deletions(-) create mode 100644 src/dolphincolumnviewcontainer.cpp create mode 100644 src/dolphincolumnviewcontainer.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f220597235..275c64323c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,7 +20,7 @@ set(dolphinprivate_LIB_SRCS dolphindetailsview.cpp dolphiniconsview.cpp dolphincolumnview.cpp - dolphincolumnwidget.cpp + dolphincolumnviewcontainer.cpp dolphindirlister.cpp dolphinfileitemdelegate.cpp dolphinmodel.cpp diff --git a/src/dolphincolumnview.cpp b/src/dolphincolumnview.cpp index f34be92e9b..4b17c2c9ea 100644 --- a/src/dolphincolumnview.cpp +++ b/src/dolphincolumnview.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2007 by Peter Penz * + * Copyright (C) 2007-2009 by Peter Penz * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -19,382 +19,507 @@ #include "dolphincolumnview.h" -#include "dolphincolumnwidget.h" +#include "dolphinmodel.h" +#include "dolphincolumnviewcontainer.h" #include "dolphincontroller.h" +#include "dolphindirlister.h" +#include "dolphinsortfilterproxymodel.h" #include "settings/dolphinsettings.h" -#include "zoomlevelinfo.h" - +#include "dolphinviewautoscroller.h" #include "dolphin_columnmodesettings.h" +#include "dolphin_generalsettings.h" +#include "draganddrophelper.h" +#include "folderexpander.h" +#include "selectionmanager.h" +#include "tooltips/tooltipmanager.h" +#include "versioncontrolobserver.h" +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* controller) : - QAbstractItemView(parent), - m_controller(controller), +DolphinColumnView::DolphinColumnView(QWidget* parent, + DolphinColumnViewContainer* container, + const KUrl& url) : + QListView(parent), m_active(false), - m_index(-1), - m_contentX(0), - m_columns(), - m_emptyViewport(0), - m_animation(0), - m_nameFilter() + m_container(container), + m_selectionManager(0), + m_autoScroller(0), + m_url(url), + m_childUrl(), + m_font(), + m_decorationSize(), + m_dirLister(0), + m_dolphinModel(0), + m_proxyModel(0), + m_previewGenerator(0), + m_toolTipManager(0), + m_dropRect() { - Q_ASSERT(controller != 0); - - setAcceptDrops(true); + setMouseTracking(true); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + setSelectionBehavior(SelectItems); + setSelectionMode(QAbstractItemView::ExtendedSelection); setDragDropMode(QAbstractItemView::DragDrop); setDropIndicatorShown(false); - setSelectionMode(ExtendedSelection); - setFocusPolicy(Qt::NoFocus); - setFrameShape(QFrame::NoFrame); - setLayoutDirection(Qt::LeftToRight); + setSelectionRectVisible(true); + setEditTriggers(QAbstractItemView::NoEditTriggers); + + setVerticalScrollMode(QListView::ScrollPerPixel); + setHorizontalScrollMode(QListView::ScrollPerPixel); + + m_autoScroller = new DolphinViewAutoScroller(this); + + // apply the column mode settings to the widget + const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); + Q_ASSERT(settings != 0); + + if (settings->useSystemFont()) { + m_font = KGlobalSettings::generalFont(); + } else { + m_font = QFont(settings->fontFamily(), + settings->fontSize(), + settings->fontWeight(), + settings->italicFont()); + } + + // KFileItemDelegate* delegate = new KFileItemDelegate(this); + // delegate->setShowToolTipWhenElided(false); + // setItemDelegate(delegate); + + activate(); connect(this, SIGNAL(viewportEntered()), - controller, SLOT(emitViewportEntered())); - connect(controller, SIGNAL(zoomLevelChanged(int)), - this, SLOT(setZoomLevel(int))); - connect(controller, SIGNAL(activationChanged(bool)), - this, SLOT(updateColumnsBackground(bool))); + m_container->m_controller, SLOT(emitViewportEntered())); + connect(this, SIGNAL(entered(const QModelIndex&)), + this, SLOT(slotEntered(const QModelIndex&))); - const DolphinView* view = controller->dolphinView(); - connect(view, SIGNAL(sortingChanged(DolphinView::Sorting)), + const DolphinView* dolphinView = m_container->m_controller->dolphinView(); + connect(dolphinView, SIGNAL(sortingChanged(DolphinView::Sorting)), this, SLOT(slotSortingChanged(DolphinView::Sorting))); - connect(view, SIGNAL(sortOrderChanged(Qt::SortOrder)), + connect(dolphinView, SIGNAL(sortOrderChanged(Qt::SortOrder)), this, SLOT(slotSortOrderChanged(Qt::SortOrder))); - connect(view, SIGNAL(sortFoldersFirstChanged(bool)), + connect(dolphinView, SIGNAL(sortFoldersFirstChanged(bool)), this, SLOT(slotSortFoldersFirstChanged(bool))); - connect(view, SIGNAL(showHiddenFilesChanged()), + connect(dolphinView, SIGNAL(showHiddenFilesChanged()), this, SLOT(slotShowHiddenFilesChanged())); - connect(view, SIGNAL(showPreviewChanged()), + connect(dolphinView, SIGNAL(showPreviewChanged()), this, SLOT(slotShowPreviewChanged())); - connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), - this, SLOT(moveContentHorizontally(int))); + m_dirLister = new DolphinDirLister(); + m_dirLister->setAutoUpdate(true); + m_dirLister->setMainWindow(window()); + m_dirLister->setDelayedMimeTypes(true); + const bool showHiddenFiles = m_container->m_controller->dolphinView()->showHiddenFiles(); + m_dirLister->setShowingDotFiles(showHiddenFiles); - m_animation = new QTimeLine(500, this); - connect(m_animation, SIGNAL(frameChanged(int)), horizontalScrollBar(), SLOT(setValue(int))); + m_dolphinModel = new DolphinModel(this); + m_dolphinModel->setDirLister(m_dirLister); + m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory); - DolphinColumnWidget* column = new DolphinColumnWidget(viewport(), this, m_controller->url()); - m_columns.append(column); - setActiveColumnIndex(0); + m_proxyModel = new DolphinSortFilterProxyModel(this); + m_proxyModel->setSourceModel(m_dolphinModel); + m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - m_emptyViewport = new QFrame(viewport()); - m_emptyViewport->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + m_proxyModel->setSorting(dolphinView->sorting()); + m_proxyModel->setSortOrder(dolphinView->sortOrder()); + m_proxyModel->setSortFoldersFirst(dolphinView->sortFoldersFirst()); - updateDecorationSize(view->showPreview()); - updateColumnsBackground(true); + setModel(m_proxyModel); + + if (DolphinSettings::instance().generalSettings()->showSelectionToggle()) { + m_selectionManager = new SelectionManager(this); + connect(m_selectionManager, SIGNAL(selectionChanged()), + this, SLOT(requestActivation())); + connect(m_container->m_controller, SIGNAL(urlChanged(const KUrl&)), + m_selectionManager, SLOT(reset())); + } + + //m_previewGenerator = new KFilePreviewGenerator(this); + //m_previewGenerator->setPreviewShown(m_container->m_controller->dolphinView()->showPreview()); + + //if (DolphinSettings::instance().generalSettings()->showToolTips()) { + // m_toolTipManager = new ToolTipManager(this, m_proxyModel); + //} + + //m_dirLister->openUrl(url, KDirLister::NoFlags); + + connect(KGlobalSettings::self(), SIGNAL(kdisplayFontChanged()), + this, SLOT(updateFont())); + + /*FolderExpander* folderExpander = new FolderExpander(this, m_proxyModel); + folderExpander->setEnabled(DolphinSettings::instance().generalSettings()->autoExpandFolders()); + connect (folderExpander, SIGNAL(enterDir(const QModelIndex&)), + m_container->m_controller, SLOT(triggerItem(const QModelIndex&))); + + new VersionControlObserver(this);*/ + + updateDecorationSize(m_container->m_controller->dolphinView()->showPreview()); } DolphinColumnView::~DolphinColumnView() { + delete m_proxyModel; + m_proxyModel = 0; + delete m_dolphinModel; + m_dolphinModel = 0; + m_dirLister = 0; // deleted by m_dolphinModel } -QModelIndex DolphinColumnView::indexAt(const QPoint& point) const +void DolphinColumnView::setActive(bool active) { - foreach (DolphinColumnWidget* column, m_columns) { - const QModelIndex index = column->indexAt(columnPosition(column, point)); - if (index.isValid()) { - return index; - } + if (active && (m_container->focusProxy() != this)) { + m_container->setFocusProxy(this); } - return QModelIndex(); -} + if (m_active != active) { + m_active = active; -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); -} - -QRect DolphinColumnView::visualRect(const QModelIndex& index) const -{ - return activeColumn()->visualRect(index); -} - -void DolphinColumnView::invertSelection() -{ - QItemSelectionModel* selectionModel = activeColumn()->selectionModel(); - const QAbstractItemModel* itemModel = selectionModel->model(); - - const QModelIndex topLeft = itemModel->index(0, 0); - const QModelIndex bottomRight = itemModel->index(itemModel->rowCount() - 1, - itemModel->columnCount() - 1); - - const QItemSelection selection(topLeft, bottomRight); - selectionModel->select(selection, QItemSelectionModel::Toggle); -} - -void DolphinColumnView::reload() -{ - foreach (DolphinColumnWidget* column, m_columns) { - column->reload(); - } -} - -void DolphinColumnView::setRootUrl(const KUrl& url) -{ - removeAllColumns(); - m_columns[0]->setUrl(url); -} - -void DolphinColumnView::setNameFilter(const QString& nameFilter) -{ - if (nameFilter != m_nameFilter) { - m_nameFilter = nameFilter; - foreach (DolphinColumnWidget* column, m_columns) { - column->setNameFilter(nameFilter); - } - } -} - -QString DolphinColumnView::nameFilter() const -{ - return m_nameFilter; -} - -KUrl DolphinColumnView::rootUrl() const -{ - return m_columns[0]->url(); -} - -void DolphinColumnView::showColumn(const KUrl& url) -{ - if (!rootUrl().isParentOf(url)) { - setRootUrl(url); - return; - } - - int columnIndex = 0; - foreach (DolphinColumnWidget* column, m_columns) { - 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 - // just delete all remaining columns - if (columnIndex > 0) { - QList::iterator start = m_columns.begin() + columnIndex; - QList::iterator end = m_columns.end(); - for (QList::iterator it = start; it != end; ++it) { - deleteColumn(*it); - } - m_columns.erase(start, end); - - const int maxIndex = m_columns.count() - 1; - Q_ASSERT(maxIndex >= 0); - if (m_index > maxIndex) { - m_index = maxIndex; - } - break; - } - } - ++columnIndex; - } - - // Create missing columns. Assuming that the path is "/home/peter/Temp/" and - // the target path is "/home/peter/Temp/a/b/c/", then the columns "a", "b" and - // "c" will be created. - const int lastIndex = m_columns.count() - 1; - Q_ASSERT(lastIndex >= 0); - - const KUrl& activeUrl = m_columns[lastIndex]->url(); - Q_ASSERT(activeUrl.isParentOf(url)); - Q_ASSERT(activeUrl != url); - - QString path = activeUrl.url(KUrl::AddTrailingSlash); - const QString targetPath = url.url(KUrl::AddTrailingSlash); - - columnIndex = lastIndex; - int slashIndex = path.count('/'); - bool hasSubPath = (slashIndex >= 0); - while (hasSubPath) { - const QString subPath = targetPath.section('/', slashIndex, slashIndex); - if (subPath.isEmpty()) { - hasSubPath = false; + if (active) { + activate(); } else { - path += subPath + '/'; - ++slashIndex; + deactivate(); + } + } +} - const KUrl childUrl = KUrl(path); - m_columns[columnIndex]->setChildUrl(childUrl); - columnIndex++; +/*void DolphinColumnView::setSorting(DolphinView::Sorting sorting) +{ + m_proxyModel->setSorting(sorting); +} - DolphinColumnWidget* column = new DolphinColumnWidget(viewport(), this, childUrl); - const QString filter = nameFilter(); - if (!filter.isEmpty()) { - column->setNameFilter(filter); - } - column->setActive(false); +void DolphinColumnView::setSortOrder(Qt::SortOrder order) +{ + m_proxyModel->setSortOrder(order); +} - m_columns.append(column); +void DolphinColumnView::setSortFoldersFirst(bool foldersFirst) +{ + m_proxyModel->setSortFoldersFirst(foldersFirst); +} - // Before invoking layoutColumns() the column must be set visible temporary. - // To prevent a flickering the initial geometry is set to a hidden position. - column->setGeometry(QRect(-1, -1, 1, 1)); - column->show(); - layoutColumns(); - updateScrollBar(); +void DolphinColumnView::setShowHiddenFiles(bool show) +{ + if (show != m_dirLister->showingDotFiles()) { + m_dirLister->setShowingDotFiles(show); + m_dirLister->stop(); + m_dirLister->openUrl(m_url, KDirLister::Reload); + } +} + +void DolphinColumnView::setShowPreview(bool show) +{ + m_previewGenerator->setPreviewShown(show); + + m_dirLister->stop(); + m_dirLister->openUrl(m_url, KDirLister::Reload); +}*/ + +void DolphinColumnView::updateBackground() +{ + // TODO: The alpha-value 150 is copied from DolphinView::setActive(). When + // cleaning up the cut-indication of DolphinColumnView with the code from + // DolphinView a common helper-class should be available which can be shared + // by all view implementations -> no hardcoded value anymore + const QPalette::ColorRole role = viewport()->backgroundRole(); + QColor color = viewport()->palette().color(role); + color.setAlpha((m_active && m_container->m_active) ? 255 : 150); + + QPalette palette = viewport()->palette(); + palette.setColor(role, color); + viewport()->setPalette(palette); + + update(); +} + +KFileItem DolphinColumnView::itemAt(const QPoint& pos) const +{ + KFileItem item; + const QModelIndex index = indexAt(pos); + if (index.isValid() && (index.column() == DolphinModel::Name)) { + const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index); + item = m_dolphinModel->itemForIndex(dolphinModelIndex); + } + return item; +} + +QStyleOptionViewItem DolphinColumnView::viewOptions() const +{ + QStyleOptionViewItem viewOptions = QListView::viewOptions(); + viewOptions.font = m_font; + viewOptions.decorationSize = m_decorationSize; + viewOptions.showDecorationSelected = true; + return viewOptions; +} + +void DolphinColumnView::startDrag(Qt::DropActions supportedActions) +{ + DragAndDropHelper::instance().startDrag(this, supportedActions, m_container->m_controller); +} + +void DolphinColumnView::dragEnterEvent(QDragEnterEvent* event) +{ + if (DragAndDropHelper::instance().isMimeDataSupported(event->mimeData())) { + event->acceptProposedAction(); + requestActivation(); + } +} + +void DolphinColumnView::dragLeaveEvent(QDragLeaveEvent* event) +{ + QListView::dragLeaveEvent(event); + setDirtyRegion(m_dropRect); +} + +void DolphinColumnView::dragMoveEvent(QDragMoveEvent* event) +{ + QListView::dragMoveEvent(event); + + // TODO: remove this code when the issue #160611 is solved in Qt 4.4 + const QModelIndex index = indexAt(event->pos()); + setDirtyRegion(m_dropRect); + + m_dropRect.setSize(QSize()); // set as invalid + if (index.isValid()) { + m_container->m_controller->setItemView(this); + const KFileItem item = m_container->m_controller->itemForIndex(index); + if (!item.isNull() && item.isDir()) { + m_dropRect = visualRect(index); + } + } + setDirtyRegion(m_dropRect); + + if (DragAndDropHelper::instance().isMimeDataSupported(event->mimeData())) { + // accept url drops, independently from the destination item + event->acceptProposedAction(); + } +} + +void DolphinColumnView::dropEvent(QDropEvent* event) +{ + const QModelIndex index = indexAt(event->pos()); + m_container->m_controller->setItemView(this); + const KFileItem item = m_container->m_controller->itemForIndex(index); + m_container->m_controller->indicateDroppedUrls(item, url(), event); + QListView::dropEvent(event); +} + +void DolphinColumnView::paintEvent(QPaintEvent* event) +{ + if (!m_childUrl.isEmpty()) { + // indicate the shown URL of the next column by highlighting the shown folder item + const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_childUrl); + const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); + if (proxyIndex.isValid() && !selectionModel()->isSelected(proxyIndex)) { + const QRect itemRect = visualRect(proxyIndex); + QPainter painter(viewport()); + QColor color = KColorScheme(QPalette::Active, KColorScheme::View).foreground().color(); + color.setAlpha(32); + painter.setPen(Qt::NoPen); + painter.setBrush(color); + painter.drawRect(itemRect); } } - // set the last column as active column without modifying the controller - // and hence the history - activeColumn()->setActive(false); - m_index = columnIndex; - activeColumn()->setActive(true); - assureVisibleActiveColumn(); + QListView::paintEvent(event); } -void DolphinColumnView::editItem(const KFileItem& item) +void DolphinColumnView::mousePressEvent(QMouseEvent* event) { - activeColumn()->editItem(item); -} - -KFileItemList DolphinColumnView::selectedItems() const -{ - return activeColumn()->selectedItems(); -} - -QMimeData* DolphinColumnView::selectionMimeData() const -{ - return activeColumn()->selectionMimeData(); -} - -void DolphinColumnView::selectAll() -{ - activeColumn()->selectAll(); -} - -bool DolphinColumnView::isIndexHidden(const QModelIndex& index) const -{ - Q_UNUSED(index); - return false;//activeColumn()->isIndexHidden(index); -} - -QModelIndex DolphinColumnView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) -{ - // Parts of this code have been taken from QColumnView::moveCursor(). - // Copyright (C) 1992-2007 Trolltech ASA. - - Q_UNUSED(modifiers); - if (model() == 0) { - return QModelIndex(); - } - - const QModelIndex current = currentIndex(); - if (isRightToLeft()) { - if (cursorAction == MoveLeft) { - cursorAction = MoveRight; - } else if (cursorAction == MoveRight) { - cursorAction = MoveLeft; + requestActivation(); + if (!indexAt(event->pos()).isValid()) { + if (QApplication::mouseButtons() & Qt::MidButton) { + m_container->m_controller->replaceUrlByClipboard(); } + } else if (event->button() == Qt::LeftButton) { + // TODO: see comment in DolphinIconsView::mousePressEvent() + setState(QAbstractItemView::DraggingState); } + QListView::mousePressEvent(event); +} - switch (cursorAction) { - case MoveLeft: - if (m_index > 0) { - setActiveColumnIndex(m_index - 1); - m_controller->triggerUrlChangeRequest(activeColumn()->url()); +void DolphinColumnView::keyPressEvent(QKeyEvent* event) +{ + QListView::keyPressEvent(event); + requestActivation(); + + DolphinController* controller = m_container->m_controller; + controller->handleKeyPressEvent(event); + switch (event->key()) { + case Qt::Key_Right: { + // Special key handling for the column: A Key_Right should + // open a new column for the currently selected folder. + const QModelIndex index = currentIndex(); + const KFileItem item = controller->itemForIndex(index); + if (!item.isNull() && item.isDir()) { + controller->emitItemTriggered(item); } break; + } - case MoveRight: - if (m_index < m_columns.count() - 1) { - setActiveColumnIndex(m_index + 1); - m_controller->triggerUrlChangeRequest(m_columns[m_index]->url()); - } + case Qt::Key_Escape: + selectionModel()->setCurrentIndex(selectionModel()->currentIndex(), + QItemSelectionModel::Current | + QItemSelectionModel::Clear); break; default: break; } - return QModelIndex(); + if (m_toolTipManager != 0) { + m_toolTipManager->hideTip(); + } } -void DolphinColumnView::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags) +void DolphinColumnView::contextMenuEvent(QContextMenuEvent* event) { - Q_UNUSED(rect); - Q_UNUSED(flags); -} + if (!m_active) { + m_container->requestActivation(this); + Q_ASSERT(m_container->m_controller->itemView() == this); + m_container->m_controller->triggerUrlChangeRequest(m_url); + } + Q_ASSERT(m_active); -QRegion DolphinColumnView::visualRegionForSelection(const QItemSelection& selection) const -{ - Q_UNUSED(selection); - return QRegion(); -} + QListView::contextMenuEvent(event); -int DolphinColumnView::horizontalOffset() const -{ - return -m_contentX; -} + const QModelIndex index = indexAt(event->pos()); + if (!index.isValid()) { + clearSelection(); + } -int DolphinColumnView::verticalOffset() const -{ - return 0; -} + if (m_toolTipManager != 0) { + m_toolTipManager->hideTip(); + } -void DolphinColumnView::mousePressEvent(QMouseEvent* event) -{ - m_controller->requestActivation(); - QAbstractItemView::mousePressEvent(event); -} - -void DolphinColumnView::resizeEvent(QResizeEvent* event) -{ - QAbstractItemView::resizeEvent(event); - layoutColumns(); - updateScrollBar(); - assureVisibleActiveColumn(); + const QPoint pos = m_container->viewport()->mapFromGlobal(event->globalPos()); + Q_ASSERT(m_container->m_controller->itemView() == this); + m_container->m_controller->triggerContextMenuRequest(pos); } void DolphinColumnView::wheelEvent(QWheelEvent* event) { + if (m_selectionManager != 0) { + m_selectionManager->reset(); + } + // let Ctrl+wheel events propagate to the DolphinView for icon zooming - if ((event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier) { + if (event->modifiers() & Qt::ControlModifier) { event->ignore(); - } else { - QAbstractItemView::wheelEvent(event); + return; + } + + const int height = m_decorationSize.height(); + const int step = (height >= KIconLoader::SizeHuge) ? height / 10 : (KIconLoader::SizeHuge - height) / 2; + verticalScrollBar()->setSingleStep(step); + + QListView::wheelEvent(event); +} + +void DolphinColumnView::leaveEvent(QEvent* event) +{ + QListView::leaveEvent(event); + // if the mouse is above an item and moved very fast outside the widget, + // no viewportEntered() signal might be emitted although the mouse has been moved + // above the viewport + m_container->m_controller->emitViewportEntered(); +} + +void DolphinColumnView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) +{ + QListView::selectionChanged(selected, deselected); + + //QItemSelectionModel* selModel = m_container->selectionModel(); + //selModel->select(selected, QItemSelectionModel::Select); + //selModel->select(deselected, QItemSelectionModel::Deselect); +} + +void DolphinColumnView::currentChanged(const QModelIndex& current, const QModelIndex& previous) +{ + QListView::currentChanged(current, previous); + m_autoScroller->handleCurrentIndexChange(current, previous); +} + +void DolphinColumnView::slotEntered(const QModelIndex& index) +{ + m_container->m_controller->setItemView(this); + m_container->m_controller->emitItemEntered(index); +} + +void DolphinColumnView::requestActivation() +{ + m_container->m_controller->setItemView(this); + m_container->m_controller->requestActivation(); + if (!m_active) { + m_container->requestActivation(this); + m_container->m_controller->triggerUrlChangeRequest(m_url); + selectionModel()->clear(); } } -void DolphinColumnView::setZoomLevel(int level) +void DolphinColumnView::updateFont() { - const int size = ZoomLevelInfo::iconSizeForZoomLevel(level); - ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); + const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); + Q_ASSERT(settings != 0); - const bool showPreview = m_controller->dolphinView()->showPreview(); - if (showPreview) { - settings->setPreviewSize(size); - } else { - settings->setIconSize(size); + if (settings->useSystemFont()) { + m_font = KGlobalSettings::generalFont(); } - - updateDecorationSize(showPreview); } -void DolphinColumnView::moveContentHorizontally(int x) +void DolphinColumnView::slotShowPreviewChanged() { - m_contentX = isRightToLeft() ? +x : -x; - layoutColumns(); + const DolphinView* view = m_container->m_controller->dolphinView(); + updateDecorationSize(view->showPreview()); +} + +void DolphinColumnView::activate() +{ + setFocus(Qt::OtherFocusReason); + + if (KGlobalSettings::singleClick()) { + connect(this, SIGNAL(clicked(const QModelIndex&)), + m_container->m_controller, SLOT(triggerItem(const QModelIndex&))); + } else { + connect(this, SIGNAL(doubleClicked(const QModelIndex&)), + m_container->m_controller, SLOT(triggerItem(const QModelIndex&))); + } + + if (selectionModel() && selectionModel()->currentIndex().isValid()) { + selectionModel()->setCurrentIndex(selectionModel()->currentIndex(), QItemSelectionModel::SelectCurrent); + } + + updateBackground(); +} + +void DolphinColumnView::deactivate() +{ + clearFocus(); + if (KGlobalSettings::singleClick()) { + disconnect(this, SIGNAL(clicked(const QModelIndex&)), + m_container->m_controller, SLOT(triggerItem(const QModelIndex&))); + } else { + disconnect(this, SIGNAL(doubleClicked(const QModelIndex&)), + m_container->m_controller, SLOT(triggerItem(const QModelIndex&))); + } + + const QModelIndex current = selectionModel()->currentIndex(); + selectionModel()->clear(); + selectionModel()->setCurrentIndex(current, QItemSelectionModel::NoUpdate); + updateBackground(); } void DolphinColumnView::updateDecorationSize(bool showPreview) @@ -404,218 +529,13 @@ void DolphinColumnView::updateDecorationSize(bool showPreview) const QSize size(iconSize, iconSize); setIconSize(size); - foreach (QObject* object, viewport()->children()) { - if (object->inherits("QListView")) { - DolphinColumnWidget* widget = static_cast(object); - widget->setDecorationSize(size); - } + m_decorationSize = size; + + if (m_selectionManager != 0) { + m_selectionManager->reset(); } doItemsLayout(); } -void DolphinColumnView::updateColumnsBackground(bool active) -{ - if (active == m_active) { - return; - } - - m_active = active; - - // dim the background of the viewport - const QPalette::ColorRole role = viewport()->backgroundRole(); - QColor background = viewport()->palette().color(role); - background.setAlpha(0); // make background transparent - - QPalette palette = viewport()->palette(); - palette.setColor(role, background); - viewport()->setPalette(palette); - - foreach (DolphinColumnWidget* column, m_columns) { - column->updateBackground(); - } -} - -void DolphinColumnView::slotSortingChanged(DolphinView::Sorting sorting) -{ - foreach (DolphinColumnWidget* column, m_columns) { - column->setSorting(sorting); - } -} - -void DolphinColumnView::slotSortOrderChanged(Qt::SortOrder order) -{ - foreach (DolphinColumnWidget* column, m_columns) { - column->setSortOrder(order); - } -} - -void DolphinColumnView::slotSortFoldersFirstChanged(bool foldersFirst) -{ - foreach (DolphinColumnWidget* column, m_columns) { - column->setSortFoldersFirst(foldersFirst); - } -} - -void DolphinColumnView::slotShowHiddenFilesChanged() -{ - 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) -{ - if (m_index == index) { - return; - } - - const bool hasActiveColumn = (m_index >= 0); - if (hasActiveColumn) { - m_columns[m_index]->setActive(false); - } - - m_index = index; - m_columns[m_index]->setActive(true); - - assureVisibleActiveColumn(); -} - -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 - 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 - 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() -{ - ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); - const int contentWidth = m_columns.count() * settings->columnWidth(); - - horizontalScrollBar()->setPageStep(contentWidth); - horizontalScrollBar()->setRange(0, contentWidth - viewport()->width()); -} - -void DolphinColumnView::assureVisibleActiveColumn() -{ - const int viewportWidth = viewport()->width(); - const int x = activeColumn()->x(); - - ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); - const int width = settings->columnWidth(); - - if (x + width > viewportWidth) { - const int newContentX = m_contentX - x - width + viewportWidth; - if (isRightToLeft()) { - m_animation->setFrameRange(m_contentX, newContentX); - } else { - m_animation->setFrameRange(-m_contentX, -newContentX); - } - if (m_animation->state() != QTimeLine::Running) { - m_animation->start(); - } - } else if (x < 0) { - const int newContentX = m_contentX - x; - if (isRightToLeft()) { - m_animation->setFrameRange(m_contentX, newContentX); - } else { - m_animation->setFrameRange(-m_contentX, -newContentX); - } - if (m_animation->state() != QTimeLine::Running) { - m_animation->start(); - } - } -} - -void DolphinColumnView::requestActivation(DolphinColumnWidget* column) -{ - m_controller->setItemView(column); - if (column->isActive()) { - assureVisibleActiveColumn(); - } else { - int index = 0; - foreach (DolphinColumnWidget* currColumn, m_columns) { - if (currColumn == column) { - setActiveColumnIndex(index); - return; - } - ++index; - } - } -} - -void DolphinColumnView::removeAllColumns() -{ - QList::iterator start = m_columns.begin() + 1; - QList::iterator end = m_columns.end(); - for (QList::iterator it = start; it != end; ++it) { - deleteColumn(*it); - } - m_columns.erase(start, end); - m_index = 0; - m_columns[0]->setActive(true); - 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" diff --git a/src/dolphincolumnview.h b/src/dolphincolumnview.h index 142bd2c2ae..91624db2e5 100644 --- a/src/dolphincolumnview.h +++ b/src/dolphincolumnview.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2007 by Peter Penz * + * Copyright (C) 2007-2009 by Peter Penz * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -22,211 +22,153 @@ #include "dolphinview.h" -#include - -#include -#include -#include +#include +#include +#include #include -class DolphinColumnWidget; -class DolphinController; -class QFrame; -class QTimeLine; +#include + +class DolphinColumnViewContainer; +class DolphinModel; +class DolphinSortFilterProxyModel; +class DolphinDirLister; +class DolphinViewAutoScroller; +class KFilePreviewGenerator; +class KFileItem; +class KFileItemList; +class SelectionManager; +class ToolTipManager; /** - * @brief Represents the view, where each directory is show as separate column. - * - * @see DolphinIconsView - * @see DolphinDetailsView + * Represents one column inside the DolphinColumnViewContainer. */ -class DolphinColumnView : public QAbstractItemView +class DolphinColumnView : public QListView { Q_OBJECT public: - explicit DolphinColumnView(QWidget* parent, DolphinController* controller); + DolphinColumnView(QWidget* parent, + DolphinColumnViewContainer* container, + const KUrl& url); virtual ~DolphinColumnView(); - /** @see QAbstractItemView::indexAt() */ - virtual QModelIndex indexAt(const QPoint& point) const; + /** + * An active column is defined as column, which shows the same URL + * as indicated by the URL navigator. The active column is usually + * drawn in a lighter color. All operations are applied to this column. + */ + void setActive(bool active); + bool isActive() const; + + /** + * Sets the directory URL of the child column that is shown next to + * this column. This property is only used for a visual indication + * of the shown directory, it does not trigger a loading of the model. + */ + void setChildUrl(const KUrl& url); + const KUrl& childUrl() const; + + /** Sets the directory URL that is shown inside the column widget. */ + void setUrl(const KUrl& url); + + /** Returns the directory URL that is shown inside the column widget. */ + const KUrl& url() const; + + /** + * Updates the background color dependent from the activation state + * \a isViewActive of the column view. + */ + void updateBackground(); /** * Returns the item on the position \a pos. The KFileItem instance * is null if no item is below the position. */ - KFileItem itemAt(const QPoint& point) const; - - /** @see QAbstractItemView::scrollTo() */ - virtual void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible); - - /** @see QAbstractItemView::visualRect() */ - virtual QRect visualRect(const QModelIndex& index) const; - - /** Inverts the selection of the currently active column. */ - void invertSelection(); - - /** - * Reloads the content of all columns. In opposite to non-hierarchical views - * it is not enough to reload the KDirLister, instead this method must be explicitly - * invoked. - */ - void reload(); - - /** - * Adjusts the root URL of the first column and removes all - * other columns. - */ - void setRootUrl(const KUrl& url); - - /** Returns the URL of the first column. */ - KUrl rootUrl() const; - - /** - * Filters the currently shown items by \a nameFilter. All items - * which contain the given filter string will be shown. - */ - void setNameFilter(const QString& nameFilter); - - /** - * Returns the currently used name filter. All items - * which contain the name filter will be shown. - */ - QString nameFilter() const; - - /** - * Shows the column which represents the URL \a url. If the column - * is already shown, it gets activated, otherwise it will be created. - */ - void showColumn(const KUrl& url); - - /** - * Does an inline editing for the item \a item - * inside the active column. - */ - void editItem(const KFileItem& item); - - /** - * Returns the selected items of the active column. - */ - KFileItemList selectedItems() const; - - /** - * Returns the MIME data for the selected items - * of the active column. - */ - QMimeData* selectionMimeData() const; - -public slots: - /** @see QAbstractItemView::selectAll() */ - virtual void selectAll(); - -signals: - /** - * Requests that the given column be deleted at the discretion - * of the receiver of the signal. - */ - void requestColumnDeletion(QAbstractItemView* column); + KFileItem itemAt(const QPoint& pos) const; protected: - virtual bool isIndexHidden(const QModelIndex& index) const; - virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers); - virtual void setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags); - virtual QRegion visualRegionForSelection(const QItemSelection& selection) const; - virtual int horizontalOffset() const; - virtual int verticalOffset() const; - + virtual QStyleOptionViewItem viewOptions() const; + virtual void startDrag(Qt::DropActions supportedActions); + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dragLeaveEvent(QDragLeaveEvent* event); + virtual void dragMoveEvent(QDragMoveEvent* event); + virtual void dropEvent(QDropEvent* event); + virtual void paintEvent(QPaintEvent* event); virtual void mousePressEvent(QMouseEvent* event); - virtual void resizeEvent(QResizeEvent* event); + virtual void keyPressEvent(QKeyEvent* event); + virtual void contextMenuEvent(QContextMenuEvent* event); virtual void wheelEvent(QWheelEvent* event); + virtual void leaveEvent(QEvent* event); + virtual void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected); + virtual void currentChanged(const QModelIndex& current, const QModelIndex& previous); private slots: - void setZoomLevel(int level); + void slotEntered(const QModelIndex& index); + void requestActivation(); + void updateFont(); - /** - * Moves the content of the columns view to represent - * the scrollbar position \a x. - */ - void moveContentHorizontally(int x); - - /** - * Updates the size of the decoration dependent on the - * icon size of the ColumnModeSettings. The controller - * will get informed about possible zoom in/zoom out - * operations. - */ - void updateDecorationSize(bool showPreview); - - /** - * Updates the background color of the columns to respect - * the current activation state \a active. - */ - void updateColumnsBackground(bool active); - - void slotSortingChanged(DolphinView::Sorting sorting); - void slotSortOrderChanged(Qt::SortOrder order); - void slotSortFoldersFirstChanged(bool foldersFirst); - void slotShowHiddenFilesChanged(); void slotShowPreviewChanged(); private: - DolphinColumnWidget* activeColumn() const; + /** Used by DolphinColumnView::setActive(). */ + void activate(); - /** - * Deactivates the currently active column and activates - * the new column indicated by \a index. m_index represents - * the active column afterwards. Also the URL of the navigator - * will be adjusted to reflect the column URL. - */ - void setActiveColumnIndex(int index); + /** Used by DolphinColumnView::setActive(). */ + void deactivate(); - void layoutColumns(); - void updateScrollBar(); - - /** - * Assures that the currently active column is fully visible - * by adjusting the horizontal position of the content. - */ - void assureVisibleActiveColumn(); - - /** - * Request the activation for the column \a column. It is assured - * that the columns gets fully visible by adjusting the horizontal - * position of the content. - */ - void requestActivation(DolphinColumnWidget* column); - - /** Removes all columns except of the root column. */ - void removeAllColumns(); - - /** - * Returns the position of the point \a point relative to the column - * \a column. - */ - QPoint columnPosition(DolphinColumnWidget* column, const QPoint& point) const; - - /** - * Deletes the column. If the itemview of the controller is set to the column, - * the controllers itemview is set to 0. - */ - void deleteColumn(DolphinColumnWidget* column); + void updateDecorationSize(bool showPreview); private: - DolphinController* m_controller; bool m_active; - int m_index; - int m_contentX; - QList m_columns; - QFrame* m_emptyViewport; - QTimeLine* m_animation; - QString m_nameFilter; + DolphinColumnViewContainer* m_container; + SelectionManager* m_selectionManager; + DolphinViewAutoScroller* m_autoScroller; + KUrl m_url; // URL of the directory that is shown + KUrl m_childUrl; // URL of the next column that is shown - friend class DolphinColumnWidget; + QFont m_font; + QSize m_decorationSize; + + DolphinDirLister* m_dirLister; + DolphinModel* m_dolphinModel; + DolphinSortFilterProxyModel* m_proxyModel; + + KFilePreviewGenerator* m_previewGenerator; + + ToolTipManager* m_toolTipManager; + + QRect m_dropRect; + + friend class DolphinColumnViewContainer; }; -inline DolphinColumnWidget* DolphinColumnView::activeColumn() const +inline bool DolphinColumnView::isActive() const { - return m_columns[m_index]; + return m_active; +} + +inline void DolphinColumnView::setChildUrl(const KUrl& url) +{ + m_childUrl = url; +} + +inline const KUrl& DolphinColumnView::childUrl() const +{ + return m_childUrl; +} + +inline void DolphinColumnView::setUrl(const KUrl& url) +{ + if (url != m_url) { + m_url = url; + //reload(); + } +} + +inline const KUrl& DolphinColumnView::url() const +{ + return m_url; } #endif diff --git a/src/dolphincolumnviewcontainer.cpp b/src/dolphincolumnviewcontainer.cpp new file mode 100644 index 0000000000..dd7ee1c9c4 --- /dev/null +++ b/src/dolphincolumnviewcontainer.cpp @@ -0,0 +1,409 @@ +/*************************************************************************** + * Copyright (C) 2007-2009 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "dolphincolumnviewcontainer.h" + +#include "dolphincolumnview.h" +#include "dolphincontroller.h" +#include "dolphinsortfilterproxymodel.h" +#include "settings/dolphinsettings.h" +#include "zoomlevelinfo.h" + +#include "dolphin_columnmodesettings.h" + +#include + +#include +#include +#include + +DolphinColumnViewContainer::DolphinColumnViewContainer(QWidget* parent, DolphinController* controller) : + QScrollArea(parent), + m_controller(controller), + m_active(false), + m_index(-1), + m_contentX(0), + m_columns(), + m_emptyViewport(0), + m_animation(0), + m_nameFilter() +{ + Q_ASSERT(controller != 0); + + setAcceptDrops(true); + setFocusPolicy(Qt::NoFocus); + setFrameShape(QFrame::NoFrame); + setLayoutDirection(Qt::LeftToRight); + + connect(this, SIGNAL(viewportEntered()), + controller, SLOT(emitViewportEntered())); + connect(controller, SIGNAL(zoomLevelChanged(int)), + this, SLOT(setZoomLevel(int))); + connect(controller, SIGNAL(activationChanged(bool)), + this, SLOT(updateColumnsBackground(bool))); + + connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), + this, SLOT(moveContentHorizontally(int))); + + m_animation = new QTimeLine(500, this); + connect(m_animation, SIGNAL(frameChanged(int)), horizontalScrollBar(), SLOT(setValue(int))); + + DolphinColumnView* column = new DolphinColumnView(viewport(), this, m_controller->url()); + m_columns.append(column); + setActiveColumnIndex(0); + + m_emptyViewport = new QFrame(viewport()); + m_emptyViewport->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + + updateColumnsBackground(true); +} + +DolphinColumnViewContainer::~DolphinColumnViewContainer() +{ +} + +void DolphinColumnViewContainer::setNameFilter(const QString& nameFilter) +{ + if (nameFilter != m_nameFilter) { + m_nameFilter = nameFilter; + foreach (DolphinColumnView* column, m_columns) { + DolphinSortFilterProxyModel* proxyModel = static_cast(column->model()); + proxyModel->setFilterRegExp(nameFilter); + } + } +} + +QString DolphinColumnViewContainer::nameFilter() const +{ + return m_nameFilter; +} + +KUrl DolphinColumnViewContainer::rootUrl() const +{ + return m_columns[0]->url(); +} + +QAbstractItemView* DolphinColumnViewContainer::activeColumn() const +{ + return m_columns[m_index]; +} + +bool DolphinColumnViewContainer::showColumn(const KUrl& url) +{ + if (!rootUrl().isParentOf(url)) { + removeAllColumns(); + m_columns[0]->setUrl(url); + return false; + } + + int columnIndex = 0; + foreach (DolphinColumnView* column, m_columns) { + if (column->url() == url) { + // the column represents already the requested URL, hence activate it + requestActivation(column); + layoutColumns(); + return false; + } else if (!column->url().isParentOf(url)) { + // the column is no parent of the requested URL, hence + // just delete all remaining columns + if (columnIndex > 0) { + QList::iterator start = m_columns.begin() + columnIndex; + QList::iterator end = m_columns.end(); + for (QList::iterator it = start; it != end; ++it) { + deleteColumn(*it); + } + m_columns.erase(start, end); + + const int maxIndex = m_columns.count() - 1; + Q_ASSERT(maxIndex >= 0); + if (m_index > maxIndex) { + m_index = maxIndex; + } + break; + } + } + ++columnIndex; + } + + // Create missing columns. Assuming that the path is "/home/peter/Temp/" and + // the target path is "/home/peter/Temp/a/b/c/", then the columns "a", "b" and + // "c" will be created. + const int lastIndex = m_columns.count() - 1; + Q_ASSERT(lastIndex >= 0); + + const KUrl& activeUrl = m_columns[lastIndex]->url(); + Q_ASSERT(activeUrl.isParentOf(url)); + Q_ASSERT(activeUrl != url); + + QString path = activeUrl.url(KUrl::AddTrailingSlash); + const QString targetPath = url.url(KUrl::AddTrailingSlash); + + columnIndex = lastIndex; + int slashIndex = path.count('/'); + bool hasSubPath = (slashIndex >= 0); + while (hasSubPath) { + const QString subPath = targetPath.section('/', slashIndex, slashIndex); + if (subPath.isEmpty()) { + hasSubPath = false; + } else { + path += subPath + '/'; + ++slashIndex; + + const KUrl childUrl = KUrl(path); + m_columns[columnIndex]->setChildUrl(childUrl); + columnIndex++; + + DolphinColumnView* column = new DolphinColumnView(viewport(), this, childUrl); + if (!m_nameFilter.isEmpty()) { + DolphinSortFilterProxyModel* proxyModel = static_cast(column->model()); + proxyModel->setFilterRegExp(m_nameFilter); + } + column->setActive(false); + + m_columns.append(column); + + // Before invoking layoutColumns() the column must be set visible temporary. + // To prevent a flickering the initial geometry is set to a hidden position. + column->setGeometry(QRect(-1, -1, 1, 1)); + column->show(); + layoutColumns(); + updateScrollBar(); + } + } + + // set the last column as active column without modifying the controller + // and hence the history + m_columns[m_index]->setActive(false); + m_index = columnIndex; + m_columns[m_index]->setActive(true); + assureVisibleActiveColumn(); + + return true; +} + +void DolphinColumnViewContainer::mousePressEvent(QMouseEvent* event) +{ + m_controller->requestActivation(); + QScrollArea::mousePressEvent(event); +} + +void DolphinColumnViewContainer::resizeEvent(QResizeEvent* event) +{ + QScrollArea::resizeEvent(event); + layoutColumns(); + updateScrollBar(); + assureVisibleActiveColumn(); +} + +void DolphinColumnViewContainer::wheelEvent(QWheelEvent* event) +{ + // let Ctrl+wheel events propagate to the DolphinView for icon zooming + if ((event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier) { + event->ignore(); + } else { + QScrollArea::wheelEvent(event); + } +} + +void DolphinColumnViewContainer::setZoomLevel(int level) +{ + 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); + } +} + +void DolphinColumnViewContainer::moveContentHorizontally(int x) +{ + m_contentX = isRightToLeft() ? +x : -x; + layoutColumns(); +} + +void DolphinColumnViewContainer::updateColumnsBackground(bool active) +{ + if (active == m_active) { + return; + } + + m_active = active; + + // dim the background of the viewport + const QPalette::ColorRole role = viewport()->backgroundRole(); + QColor background = viewport()->palette().color(role); + background.setAlpha(0); // make background transparent + + QPalette palette = viewport()->palette(); + palette.setColor(role, background); + viewport()->setPalette(palette); + + foreach (DolphinColumnView* column, m_columns) { + column->updateBackground(); + } +} + +void DolphinColumnViewContainer::setActiveColumnIndex(int index) +{ + if (m_index == index) { + return; + } + + const bool hasActiveColumn = (m_index >= 0); + if (hasActiveColumn) { + m_columns[m_index]->setActive(false); + } + + m_index = index; + m_columns[m_index]->setActive(true); + + assureVisibleActiveColumn(); +} + +void DolphinColumnViewContainer::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 (DolphinColumnView* column, m_columns) { + 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 (DolphinColumnView* column, m_columns) { + 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 DolphinColumnViewContainer::updateScrollBar() +{ + ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); + const int contentWidth = m_columns.count() * settings->columnWidth(); + + horizontalScrollBar()->setPageStep(contentWidth); + horizontalScrollBar()->setRange(0, contentWidth - viewport()->width()); +} + +void DolphinColumnViewContainer::assureVisibleActiveColumn() +{ + const int viewportWidth = viewport()->width(); + const int x = activeColumn()->x(); + + ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); + const int width = settings->columnWidth(); + + if (x + width > viewportWidth) { + const int newContentX = m_contentX - x - width + viewportWidth; + if (isRightToLeft()) { + m_animation->setFrameRange(m_contentX, newContentX); + } else { + m_animation->setFrameRange(-m_contentX, -newContentX); + } + if (m_animation->state() != QTimeLine::Running) { + m_animation->start(); + } + } else if (x < 0) { + const int newContentX = m_contentX - x; + if (isRightToLeft()) { + m_animation->setFrameRange(m_contentX, newContentX); + } else { + m_animation->setFrameRange(-m_contentX, -newContentX); + } + if (m_animation->state() != QTimeLine::Running) { + m_animation->start(); + } + } +} + +void DolphinColumnViewContainer::requestActivation(DolphinColumnView* column) +{ + m_controller->setItemView(column); + if (column->isActive()) { + assureVisibleActiveColumn(); + } else { + int index = 0; + foreach (DolphinColumnView* currColumn, m_columns) { + if (currColumn == column) { + setActiveColumnIndex(index); + return; + } + ++index; + } + } +} + +void DolphinColumnViewContainer::removeAllColumns() +{ + QList::iterator start = m_columns.begin() + 1; + QList::iterator end = m_columns.end(); + for (QList::iterator it = start; it != end; ++it) { + deleteColumn(*it); + } + m_columns.erase(start, end); + m_index = 0; + m_columns[0]->setActive(true); + assureVisibleActiveColumn(); +} + +QPoint DolphinColumnViewContainer::columnPosition(DolphinColumnView* column, const QPoint& point) const +{ + const QPoint topLeft = column->frameGeometry().topLeft(); + return QPoint(point.x() - topLeft.x(), point.y() - topLeft.y()); +} + +void DolphinColumnViewContainer::deleteColumn(DolphinColumnView* 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 DolphinColumnViewContainer + // is destroyed. + column->setParent(0); + column->disconnect(); + emit requestColumnDeletion(column); + } +} + +#include "dolphincolumnviewcontainer.moc" diff --git a/src/dolphincolumnviewcontainer.h b/src/dolphincolumnviewcontainer.h new file mode 100644 index 0000000000..3d593ddbd0 --- /dev/null +++ b/src/dolphincolumnviewcontainer.h @@ -0,0 +1,152 @@ +/*************************************************************************** + * Copyright (C) 2007-2009 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef DOLPHINCOLUMNVIEWCONTAINER_H +#define DOLPHINCOLUMNVIEWCONTAINER_H + +#include "dolphinview.h" + +#include + +#include +#include +#include + +class DolphinColumnView; +class DolphinController; +class QFrame; +class QTimeLine; + +/** + * @brief Represents a container for columns represented as instances + * of DolphinColumnView. + * + * @see DolphinColumnView + */ +class DolphinColumnViewContainer : public QScrollArea +{ + Q_OBJECT + +public: + explicit DolphinColumnViewContainer(QWidget* parent, DolphinController* controller); + virtual ~DolphinColumnViewContainer(); + + /** + * Filters the currently shown items by \a nameFilter. All items + * which contain the given filter string will be shown. + */ + void setNameFilter(const QString& nameFilter); + + /** + * Returns the currently used name filter. All items + * which contain the name filter will be shown. + */ + QString nameFilter() const; + + KUrl rootUrl() const; + + QAbstractItemView* activeColumn() const; + + /** + * Shows the column which represents the URL \a url. If the column + * is already shown, it gets activated, otherwise it will be created. + */ + bool showColumn(const KUrl& url); + +signals: + /** + * Requests that the given column be deleted at the discretion + * of the receiver of the signal. + */ + void requestColumnDeletion(QAbstractItemView* column); + +protected: + virtual void mousePressEvent(QMouseEvent* event); + virtual void resizeEvent(QResizeEvent* event); + virtual void wheelEvent(QWheelEvent* event); + +private slots: + void setZoomLevel(int level); + + /** + * Moves the content of the columns view to represent + * the scrollbar position \a x. + */ + void moveContentHorizontally(int x); + + /** + * Updates the background color of the columns to respect + * the current activation state \a active. + */ + void updateColumnsBackground(bool active); + +private: + /** + * Deactivates the currently active column and activates + * the new column indicated by \a index. m_index represents + * the active column afterwards. Also the URL of the navigator + * will be adjusted to reflect the column URL. + */ + void setActiveColumnIndex(int index); + + void layoutColumns(); + void updateScrollBar(); + + /** + * Assures that the currently active column is fully visible + * by adjusting the horizontal position of the content. + */ + void assureVisibleActiveColumn(); + + /** + * Request the activation for the column \a column. It is assured + * that the columns gets fully visible by adjusting the horizontal + * position of the content. + */ + void requestActivation(DolphinColumnView* column); + + /** Removes all columns except of the root column. */ + void removeAllColumns(); + + /** + * Returns the position of the point \a point relative to the column + * \a column. + */ + QPoint columnPosition(DolphinColumnView* column, const QPoint& point) const; + + /** + * Deletes the column. If the itemview of the controller is set to the column, + * the controllers itemview is set to 0. + */ + void deleteColumn(DolphinColumnView* column); + +private: + DolphinController* m_controller; + bool m_active; + int m_index; + int m_contentX; + QList m_columns; + QFrame* m_emptyViewport; + QTimeLine* m_animation; + QString m_nameFilter; + + friend class DolphinColumnView; +}; + +#endif diff --git a/src/dolphincolumnwidget.cpp b/src/dolphincolumnwidget.cpp index 0ad02c71e8..d80ef1c47b 100644 --- a/src/dolphincolumnwidget.cpp +++ b/src/dolphincolumnwidget.cpp @@ -1,3 +1,5 @@ +Don't compile + /*************************************************************************** * Copyright (C) 2007 by Peter Penz * * * @@ -49,6 +51,8 @@ #include #include +#include + DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, DolphinColumnView* columnView, const KUrl& url) : @@ -96,9 +100,6 @@ DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, settings->italicFont()); } - const int iconSize = settings->iconSize(); - setDecorationSize(QSize(iconSize, iconSize)); - KFileItemDelegate* delegate = new KFileItemDelegate(this); delegate->setShowToolTipWhenElided(false); setItemDelegate(delegate); @@ -110,6 +111,18 @@ DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, connect(this, SIGNAL(entered(const QModelIndex&)), this, SLOT(slotEntered(const QModelIndex&))); + const DolphinView* dolphinView = m_view->m_controller->dolphinView(); + connect(dolphinView, SIGNAL(sortingChanged(DolphinView::Sorting)), + this, SLOT(slotSortingChanged(DolphinView::Sorting))); + connect(dolphinView, SIGNAL(sortOrderChanged(Qt::SortOrder)), + this, SLOT(slotSortOrderChanged(Qt::SortOrder))); + connect(dolphinView, SIGNAL(sortFoldersFirstChanged(bool)), + this, SLOT(slotSortFoldersFirstChanged(bool))); + connect(dolphinView, SIGNAL(showHiddenFilesChanged()), + this, SLOT(slotShowHiddenFilesChanged())); + connect(dolphinView, SIGNAL(showPreviewChanged()), + this, SLOT(slotShowPreviewChanged())); + m_dirLister = new DolphinDirLister(); m_dirLister->setAutoUpdate(true); m_dirLister->setMainWindow(window()); @@ -124,7 +137,7 @@ DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, m_proxyModel = new DolphinSortFilterProxyModel(this); m_proxyModel->setSourceModel(m_dolphinModel); m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - const DolphinView* dolphinView = m_view->m_controller->dolphinView(); + m_proxyModel->setSorting(dolphinView->sorting()); m_proxyModel->setSortOrder(dolphinView->sortOrder()); m_proxyModel->setSortFoldersFirst(dolphinView->sortFoldersFirst()); @@ -139,24 +152,26 @@ DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, m_selectionManager, SLOT(reset())); } - m_previewGenerator = new KFilePreviewGenerator(this); - m_previewGenerator->setPreviewShown(m_view->m_controller->dolphinView()->showPreview()); + //m_previewGenerator = new KFilePreviewGenerator(this); + //m_previewGenerator->setPreviewShown(m_view->m_controller->dolphinView()->showPreview()); - if (DolphinSettings::instance().generalSettings()->showToolTips()) { - m_toolTipManager = new ToolTipManager(this, m_proxyModel); - } + //if (DolphinSettings::instance().generalSettings()->showToolTips()) { + // m_toolTipManager = new ToolTipManager(this, m_proxyModel); + //} - m_dirLister->openUrl(url, KDirLister::NoFlags); + //m_dirLister->openUrl(url, KDirLister::NoFlags); connect(KGlobalSettings::self(), SIGNAL(kdisplayFontChanged()), this, SLOT(updateFont())); - FolderExpander* folderExpander = new FolderExpander(this, m_proxyModel); + /*FolderExpander* folderExpander = new FolderExpander(this, m_proxyModel); folderExpander->setEnabled(DolphinSettings::instance().generalSettings()->autoExpandFolders()); connect (folderExpander, SIGNAL(enterDir(const QModelIndex&)), m_view->m_controller, SLOT(triggerItem(const QModelIndex&))); - new VersionControlObserver(this); + new VersionControlObserver(this);*/ + + updateDecorationSize(m_view->m_controller->dolphinView()->showPreview()); } DolphinColumnWidget::~DolphinColumnWidget() @@ -168,19 +183,6 @@ DolphinColumnWidget::~DolphinColumnWidget() m_dirLister = 0; // deleted by m_dolphinModel } -void DolphinColumnWidget::setDecorationSize(const QSize& size) -{ - setIconSize(size); - m_decorationSize = size; - doItemsLayout(); - if (m_previewGenerator != 0) { - m_previewGenerator->updateIcons(); - } - if (m_selectionManager != 0) { - m_selectionManager->reset(); - } -} - void DolphinColumnWidget::setActive(bool active) { if (active && (m_view->focusProxy() != this)) { @@ -198,13 +200,13 @@ void DolphinColumnWidget::setActive(bool active) } } -void DolphinColumnWidget::reload() +/*void DolphinColumnWidget::reload() { m_dirLister->stop(); m_dirLister->openUrl(m_url, KDirLister::Reload); -} +}*/ -void DolphinColumnWidget::setSorting(DolphinView::Sorting sorting) +/*void DolphinColumnWidget::setSorting(DolphinView::Sorting sorting) { m_proxyModel->setSorting(sorting); } @@ -234,7 +236,7 @@ void DolphinColumnWidget::setShowPreview(bool show) m_dirLister->stop(); m_dirLister->openUrl(m_url, KDirLister::Reload); -} +}*/ void DolphinColumnWidget::updateBackground() { @@ -487,8 +489,8 @@ void DolphinColumnWidget::selectionChanged(const QItemSelection& selected, const QListView::selectionChanged(selected, deselected); QItemSelectionModel* selModel = m_view->selectionModel(); - selModel->select(selected, QItemSelectionModel::Select); - selModel->select(deselected, QItemSelectionModel::Deselect); + //selModel->select(selected, QItemSelectionModel::Select); + //selModel->select(deselected, QItemSelectionModel::Deselect); } void DolphinColumnWidget::currentChanged(const QModelIndex& current, const QModelIndex& previous) @@ -524,6 +526,13 @@ void DolphinColumnWidget::updateFont() } } +void DolphinColumnWidget::slotShowPreviewChanged() +{ + kDebug() << "--- slotpreviewchanged"; + const DolphinView* view = m_view->m_controller->dolphinView(); + updateDecorationSize(view->showPreview()); +} + void DolphinColumnWidget::activate() { setFocus(Qt::OtherFocusReason); @@ -560,4 +569,20 @@ void DolphinColumnWidget::deactivate() updateBackground(); } +void DolphinColumnWidget::updateDecorationSize(bool showPreview) +{ + ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); + const int iconSize = showPreview ? settings->previewSize() : settings->iconSize(); + const QSize size(iconSize, iconSize); + setIconSize(size); + + m_decorationSize = size; + + if (m_selectionManager != 0) { + m_selectionManager->reset(); + } + + doItemsLayout(); +} + #include "dolphincolumnwidget.moc" diff --git a/src/dolphincolumnwidget.h b/src/dolphincolumnwidget.h index 3568d4cf7d..92b2a8f542 100644 --- a/src/dolphincolumnwidget.h +++ b/src/dolphincolumnwidget.h @@ -1,3 +1,5 @@ +Don't compile + /*************************************************************************** * Copyright (C) 2007 by Peter Penz * * * @@ -54,9 +56,6 @@ public: const KUrl& url); virtual ~DolphinColumnWidget(); - /** Sets the size of the icons. */ - void setDecorationSize(const QSize& size); - /** * An active column is defined as column, which shows the same URL * as indicated by the URL navigator. The active column is usually @@ -80,13 +79,13 @@ public: const KUrl& url() const; /** Reloads the directory DolphinColumnWidget::url(). */ - void reload(); + //void reload(); - void setSorting(DolphinView::Sorting sorting); + /*void setSorting(DolphinView::Sorting sorting); void setSortOrder(Qt::SortOrder order); void setSortFoldersFirst(bool foldersFirst); void setShowHiddenFiles(bool show); - void setShowPreview(bool show); + void setShowPreview(bool show);*/ /** * Updates the background color dependent from the activation state @@ -94,12 +93,6 @@ public: */ void updateBackground(); - /** - * Filters the currently shown items by \a nameFilter. All items - * which contain the given filter string will be shown. - */ - void setNameFilter(const QString& nameFilter); - /** * Does an inline editing for the item \a item. */ @@ -139,6 +132,8 @@ private slots: void requestActivation(); void updateFont(); + void slotShowPreviewChanged(); + private: /** Used by DolphinColumnWidget::setActive(). */ void activate(); @@ -146,6 +141,8 @@ private: /** Used by DolphinColumnWidget::setActive(). */ void deactivate(); + void updateDecorationSize(bool showPreview); + private: bool m_active; DolphinColumnView* m_view; @@ -189,7 +186,7 @@ inline void DolphinColumnWidget::setUrl(const KUrl& url) { if (url != m_url) { m_url = url; - reload(); + //reload(); } } diff --git a/src/dolphindetailsview.cpp b/src/dolphindetailsview.cpp index 69fe5760f0..7f75fdda63 100644 --- a/src/dolphindetailsview.cpp +++ b/src/dolphindetailsview.cpp @@ -546,7 +546,6 @@ void DolphinDetailsView::setZoomLevel(int level) updateDecorationSize(showPreview); } - void DolphinDetailsView::slotShowPreviewChanged() { const DolphinView* view = m_controller->dolphinView(); diff --git a/src/dolphinpart.cpp b/src/dolphinpart.cpp index 6452ba36a6..21b0ccdfc8 100644 --- a/src/dolphinpart.cpp +++ b/src/dolphinpart.cpp @@ -70,7 +70,6 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QVariantL } m_dirLister->setDelayedMimeTypes(true); - //connect(m_dirLister, SIGNAL(started(KUrl)), this, SLOT(slotStarted())); connect(m_dirLister, SIGNAL(completed(KUrl)), this, SLOT(slotCompleted(KUrl))); connect(m_dirLister, SIGNAL(canceled(KUrl)), this, SLOT(slotCanceled(KUrl))); connect(m_dirLister, SIGNAL(percent(int)), this, SLOT(updateProgress(int))); @@ -81,11 +80,7 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QVariantL m_proxyModel = new DolphinSortFilterProxyModel(this); m_proxyModel->setSourceModel(m_dolphinModel); - m_view = new DolphinView(parentWidget, - KUrl(), - m_dirLister, - m_dolphinModel, - m_proxyModel); + m_view = new DolphinView(parentWidget, KUrl(), m_proxyModel); m_view->setTabsForFilesEnabled(true); setWidget(m_view); diff --git a/src/dolphinview.cpp b/src/dolphinview.cpp index aa0bb96194..e9b33e9a14 100644 --- a/src/dolphinview.cpp +++ b/src/dolphinview.cpp @@ -50,7 +50,7 @@ #include #include "dolphinmodel.h" -#include "dolphincolumnview.h" +#include "dolphincolumnviewcontainer.h" #include "dolphincontroller.h" #include "dolphindetailsview.h" #include "dolphinfileitemdelegate.h" @@ -79,8 +79,6 @@ bool lessThan(const KFileItem& item1, const KFileItem& item2) DolphinView::DolphinView(QWidget* parent, const KUrl& url, - KDirLister* dirLister, - DolphinModel* dolphinModel, DolphinSortFilterProxyModel* proxyModel) : QWidget(parent), m_active(true), @@ -94,15 +92,10 @@ DolphinView::DolphinView(QWidget* parent, m_mode(DolphinView::IconsView), m_topLayout(0), m_controller(0), - m_iconsView(0), - m_detailsView(0), - m_columnView(0), m_fileItemDelegate(0), + m_viewAccessor(proxyModel), m_selectionModel(0), m_selectionChangedTimer(0), - m_dolphinModel(dolphinModel), - m_dirLister(dirLister), - m_proxyModel(proxyModel), m_previewGenerator(0), m_toolTipManager(0), m_versionControlObserver(0), @@ -148,11 +141,12 @@ DolphinView::DolphinView(QWidget* parent, connect(m_controller, SIGNAL(viewportEntered()), this, SLOT(clearHoverInformation())); - connect(m_dirLister, SIGNAL(redirection(KUrl, KUrl)), + KDirLister* dirLister = m_viewAccessor.dirLister(); + connect(dirLister, SIGNAL(redirection(KUrl, KUrl)), this, SIGNAL(redirection(KUrl, KUrl))); - connect(m_dirLister, SIGNAL(completed()), + connect(dirLister, SIGNAL(completed()), this, SLOT(slotDirListerCompleted())); - connect(m_dirLister, SIGNAL(refreshItems(const QList>&)), + connect(dirLister, SIGNAL(refreshItems(const QList>&)), this, SLOT(slotRefreshItems())); // When a new item has been created by the "Create New..." menu, the item should @@ -161,8 +155,8 @@ DolphinView::DolphinView(QWidget* parent, connect(&DolphinNewMenuObserver::instance(), SIGNAL(itemCreated(const KUrl&)), this, SLOT(observeCreatedItem(const KUrl&))); - applyViewProperties(url); - m_topLayout->addWidget(itemView()); + applyViewProperties(); + m_topLayout->addWidget(m_viewAccessor.itemView()); } DolphinView::~DolphinView() @@ -178,7 +172,12 @@ const KUrl& DolphinView::url() const KUrl DolphinView::rootUrl() const { - return isColumnViewActive() ? m_columnView->rootUrl() : url(); + const KUrl viewUrl = url(); + const KUrl root = m_viewAccessor.rootUrl(); + if (root.isEmpty() || !root.isParentOf(viewUrl)) { + return viewUrl; + } + return root; } void DolphinView::setActive(bool active) @@ -196,7 +195,7 @@ void DolphinView::setActive(bool active) color.setAlpha(150); } - QWidget* viewport = itemView()->viewport(); + QWidget* viewport = m_viewAccessor.itemView()->viewport(); QPalette palette; palette.setColor(viewport->backgroundRole(), color); viewport->setPalette(palette); @@ -204,7 +203,7 @@ void DolphinView::setActive(bool active) update(); if (active) { - itemView()->setFocus(); + m_viewAccessor.itemView()->setFocus(); emit activated(); } @@ -227,7 +226,7 @@ void DolphinView::setMode(Mode mode) deleteView(); - const KUrl viewPropsUrl = viewPropertiesUrl(); + const KUrl viewPropsUrl = rootUrl(); ViewProperties props(viewPropsUrl); props.setViewMode(m_mode); createView(); @@ -243,8 +242,8 @@ void DolphinView::setMode(Mode mode) // capabilities. m_storedCategorizedSorting = props.categorizedSorting(); const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting(); - if (categorized != m_proxyModel->isCategorizedModel()) { - m_proxyModel->setCategorizedModel(categorized); + if (categorized != m_viewAccessor.proxyModel()->isCategorizedModel()) { + m_viewAccessor.proxyModel()->setCategorizedModel(categorized); emit categorizedSortingChanged(); } @@ -268,13 +267,13 @@ bool DolphinView::showPreview() const bool DolphinView::showHiddenFiles() const { - return m_dirLister->showingDotFiles(); + return m_viewAccessor.dirLister()->showingDotFiles(); } bool DolphinView::categorizedSorting() const { // If all view modes would support categorized sorting, returning - // m_proxyModel->isCategorizedModel() would be the way to go. As + // m_viewAccessor.proxyModel()->isCategorizedModel() would be the way to go. As // currently only the icons view supports caterized sorting, we remember // the stored view properties state in m_storedCategorizedSorting and // return this state. The application takes care to disable the corresponding @@ -285,12 +284,12 @@ bool DolphinView::categorizedSorting() const bool DolphinView::supportsCategorizedSorting() const { - return m_iconsView != 0; + return m_viewAccessor.supportsCategorizedSorting(); } void DolphinView::selectAll() { - QAbstractItemView* view = itemView(); + QAbstractItemView* view = m_viewAccessor.itemView(); // TODO: there seems to be a bug in QAbstractItemView::selectAll(); if // the Ctrl-key is pressed (e. g. for Ctrl+A), selectAll() inverts the // selection instead of selecting all items. This is bypassed for KDE 4.0 @@ -301,34 +300,25 @@ void DolphinView::selectAll() void DolphinView::invertSelection() { - if (isColumnViewActive()) { - // QAbstractItemView does not offer a virtual method invertSelection() - // as counterpart to QAbstractItemView::selectAll(). This makes it - // necessary to delegate the inverting of the selection to the - // column view, as only the selection of the active column should - // get inverted. - m_columnView->invertSelection(); - } else { - QItemSelectionModel* selectionModel = itemView()->selectionModel(); - const QAbstractItemModel* itemModel = selectionModel->model(); + 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); + const QModelIndex topLeft = itemModel->index(0, 0); + const QModelIndex bottomRight = itemModel->index(itemModel->rowCount() - 1, + itemModel->columnCount() - 1); - const QItemSelection selection(topLeft, bottomRight); - selectionModel->select(selection, QItemSelectionModel::Toggle); - } + const QItemSelection selection(topLeft, bottomRight); + selectionModel->select(selection, QItemSelectionModel::Toggle); } bool DolphinView::hasSelection() const { - return itemView()->selectionModel()->hasSelection(); + return m_viewAccessor.itemView()->selectionModel()->hasSelection(); } void DolphinView::clearSelection() { - QItemSelectionModel* selModel = itemView()->selectionModel(); + QItemSelectionModel* selModel = m_viewAccessor.itemView()->selectionModel(); const QModelIndex currentIndex = selModel->currentIndex(); selModel->setCurrentIndex(currentIndex, QItemSelectionModel::Current | QItemSelectionModel::Clear); @@ -337,22 +327,18 @@ void DolphinView::clearSelection() KFileItemList DolphinView::selectedItems() const { - if (isColumnViewActive()) { - return m_columnView->selectedItems(); - } - - const QAbstractItemView* view = itemView(); + const QAbstractItemView* view = m_viewAccessor.itemView(); // Our view has a selection, we will map them back to the DolphinModel // and then fill the KFileItemList. Q_ASSERT((view != 0) && (view->selectionModel() != 0)); - const QItemSelection selection = m_proxyModel->mapSelectionToSource(view->selectionModel()->selection()); + const QItemSelection selection = m_viewAccessor.proxyModel()->mapSelectionToSource(view->selectionModel()->selection()); KFileItemList itemList; const QModelIndexList indexList = selection.indexes(); foreach (const QModelIndex &index, indexList) { - KFileItem item = m_dolphinModel->itemForIndex(index); + KFileItem item = m_viewAccessor.dirModel()->itemForIndex(index); if (!item.isNull()) { itemList.append(item); } @@ -373,23 +359,13 @@ KUrl::List DolphinView::selectedUrls() const int DolphinView::selectedItemsCount() const { - if (isColumnViewActive()) { - // TODO: get rid of this special case by adjusting the dir lister - // to the current column - return m_columnView->selectedItems().count(); - } - - return itemView()->selectionModel()->selectedIndexes().count(); + return m_viewAccessor.itemView()->selectionModel()->selectedIndexes().count(); } void DolphinView::setContentsPosition(int x, int y) { - QAbstractItemView* view = itemView(); - - // the ColumnView takes care itself for the horizontal scrolling - if (!isColumnViewActive()) { - view->horizontalScrollBar()->setValue(x); - } + QAbstractItemView* view = m_viewAccessor.itemView(); + view->horizontalScrollBar()->setValue(x); view->verticalScrollBar()->setValue(y); m_loadingDirectory = false; @@ -397,8 +373,8 @@ void DolphinView::setContentsPosition(int x, int y) QPoint DolphinView::contentsPosition() const { - const int x = itemView()->horizontalScrollBar()->value(); - const int y = itemView()->verticalScrollBar()->value(); + const int x = m_viewAccessor.itemView()->horizontalScrollBar()->value(); + const int y = m_viewAccessor.itemView()->verticalScrollBar()->value(); return QPoint(x, y); } @@ -431,7 +407,7 @@ void DolphinView::setSorting(Sorting sorting) DolphinView::Sorting DolphinView::sorting() const { - return m_proxyModel->sorting(); + return m_viewAccessor.proxyModel()->sorting(); } void DolphinView::setSortOrder(Qt::SortOrder order) @@ -443,7 +419,7 @@ void DolphinView::setSortOrder(Qt::SortOrder order) Qt::SortOrder DolphinView::sortOrder() const { - return m_proxyModel->sortOrder(); + return m_viewAccessor.proxyModel()->sortOrder(); } void DolphinView::setSortFoldersFirst(bool foldersFirst) @@ -455,21 +431,19 @@ void DolphinView::setSortFoldersFirst(bool foldersFirst) bool DolphinView::sortFoldersFirst() const { - return m_proxyModel->sortFoldersFirst(); + return m_viewAccessor.proxyModel()->sortFoldersFirst(); } void DolphinView::setAdditionalInfo(KFileItemDelegate::InformationList info) { - const KUrl viewPropsUrl = viewPropertiesUrl(); + const KUrl viewPropsUrl = rootUrl(); ViewProperties props(viewPropsUrl); props.setAdditionalInfo(info); m_fileItemDelegate->setShowInformation(info); emit additionalInfoChanged(); - if (itemView() != m_detailsView) { - // the details view requires no reloading of the directory, as it maps - // the file item delegate info to its columns internally + if (m_viewAccessor.reloadOnAdditionalInfoChange()) { loadDirectory(viewPropsUrl); } } @@ -494,7 +468,7 @@ void DolphinView::refresh() m_active = true; createView(); - applyViewProperties(m_controller->url()); + applyViewProperties(); reload(); setActive(oldActivationState); @@ -503,48 +477,37 @@ void DolphinView::refresh() void DolphinView::updateView(const KUrl& url, const KUrl& rootUrl) { + Q_UNUSED(rootUrl); // TODO: remove after columnview-cleanup has been finished + if (m_controller->url() == url) { return; } m_previewGenerator->cancelPreviews(); m_controller->setUrl(url); // emits urlChanged, which we forward - - if (!rootUrl.isEmpty() && rootUrl.isParentOf(url)) { - applyViewProperties(rootUrl); - loadDirectory(rootUrl); - if (itemView() == m_columnView) { - m_columnView->setRootUrl(rootUrl); - m_columnView->showColumn(url); - } - } else { - applyViewProperties(url); - loadDirectory(url); + if (m_viewAccessor.prepareUrlChange(url)) { + initializeView(); } + applyViewProperties(); + loadDirectory(url); // When changing the URL there is no need to keep the version // data of the previous URL. - m_dolphinModel->clearVersionData(); + m_viewAccessor.dirModel()->clearVersionData(); emit startedPathLoading(url); } void DolphinView::setNameFilter(const QString& nameFilter) { - m_proxyModel->setFilterRegExp(nameFilter); - - if (isColumnViewActive()) { - // adjusting the directory lister is not enough in the case of the - // column view, as each column has its own directory lister internally... - m_columnView->setNameFilter(nameFilter); - } + m_viewAccessor.setNameFilter(nameFilter); } void DolphinView::calculateItemCount(int& fileCount, int& folderCount, KIO::filesize_t& totalFileSize) const { - foreach (const KFileItem& item, m_dirLister->items()) { + foreach (const KFileItem& item, m_viewAccessor.dirLister()->items()) { if (item.isDir()) { ++folderCount; } else { @@ -638,11 +601,11 @@ void DolphinView::changeSelection(const KFileItemList& selection) foreach(const KFileItem& item, selection) { url = item.url().upUrl(); if (baseUrl.equals(url, KUrl::CompareWithoutTrailingSlash)) { - QModelIndex index = m_proxyModel->mapFromSource(m_dolphinModel->indexForItem(item)); + QModelIndex index = m_viewAccessor.proxyModel()->mapFromSource(m_viewAccessor.dirModel()->indexForItem(item)); newSelection.select(index, index); } } - itemView()->selectionModel()->select(newSelection, + m_viewAccessor.itemView()->selectionModel()->select(newSelection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current); } @@ -702,14 +665,9 @@ void DolphinView::renameSelectedItems() } } else if (DolphinSettings::instance().generalSettings()->renameInline()) { Q_ASSERT(itemCount == 1); - - if (isColumnViewActive()) { - m_columnView->editItem(items.first()); - } else { - const QModelIndex dirIndex = m_dolphinModel->indexForItem(items.first()); - const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); - itemView()->edit(proxyIndex); - } + 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); @@ -791,7 +749,7 @@ void DolphinView::setShowPreview(bool show) return; } - const KUrl viewPropsUrl = viewPropertiesUrl(); + const KUrl viewPropsUrl = rootUrl(); ViewProperties props(viewPropsUrl); props.setShowPreview(show); @@ -811,15 +769,15 @@ void DolphinView::setShowPreview(bool show) void DolphinView::setShowHiddenFiles(bool show) { - if (m_dirLister->showingDotFiles() == show) { + if (m_viewAccessor.dirLister()->showingDotFiles() == show) { return; } - const KUrl viewPropsUrl = viewPropertiesUrl(); + const KUrl viewPropsUrl = rootUrl(); ViewProperties props(viewPropsUrl); props.setShowHiddenFiles(show); - m_dirLister->setShowingDotFiles(show); + m_viewAccessor.dirLister()->setShowingDotFiles(show); emit showHiddenFilesChanged(); loadDirectory(viewPropsUrl); @@ -835,12 +793,12 @@ void DolphinView::setCategorizedSorting(bool categorized) // if the view supports categorized sorting Q_ASSERT(!categorized || supportsCategorizedSorting()); - ViewProperties props(viewPropertiesUrl()); + ViewProperties props(rootUrl()); props.setCategorizedSorting(categorized); props.save(); m_storedCategorizedSorting = categorized; - m_proxyModel->setCategorizedModel(categorized); + m_viewAccessor.proxyModel()->setCategorizedModel(categorized); emit categorizedSortingChanged(); } @@ -903,13 +861,13 @@ bool DolphinView::eventFilter(QObject* watched, QEvent* event) { switch (event->type()) { case QEvent::FocusIn: - if (watched == itemView()) { + if (watched == m_viewAccessor.itemView()) { m_controller->requestActivation(); } break; case QEvent::MouseButtonPress: - if ((watched == itemView()->viewport()) && (m_expandedDragSource != 0)) { + if ((watched == m_viewAccessor.itemView()->viewport()) && (m_expandedDragSource != 0)) { // Listening to a mousebutton press event to delete expanded views is a // workaround, as it seems impossible for the FolderExpander to know when // a dragging outside a view has been finished. However it works quite well: @@ -921,13 +879,13 @@ bool DolphinView::eventFilter(QObject* watched, QEvent* event) break; case QEvent::DragEnter: - if (watched == itemView()->viewport()) { + if (watched == m_viewAccessor.itemView()->viewport()) { setActive(true); } break; case QEvent::KeyPress: - if (watched == itemView()) { + if (watched == m_viewAccessor.itemView()) { if (m_toolTipManager != 0) { m_toolTipManager->hideTip(); } @@ -989,14 +947,10 @@ void DolphinView::openContextMenu(const QPoint& pos, const QList& customActions) { KFileItem item; - if (isColumnViewActive()) { - item = m_columnView->itemAt(pos); - } else { - const QModelIndex index = itemView()->indexAt(pos); - if (index.isValid() && (index.column() == DolphinModel::Name)) { - const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index); - item = m_dolphinModel->itemForIndex(dolphinModelIndex); - } + const QModelIndex index = m_viewAccessor.itemView()->indexAt(pos); + if (index.isValid() && (index.column() == DolphinModel::Name)) { + const QModelIndex dolphinModelIndex = m_viewAccessor.proxyModel()->mapToSource(index); + item = m_viewAccessor.dirModel()->itemForIndex(dolphinModelIndex); } if (m_toolTipManager != 0) { @@ -1018,37 +972,37 @@ void DolphinView::dropUrls(const KFileItem& destItem, void DolphinView::updateSorting(DolphinView::Sorting sorting) { - ViewProperties props(viewPropertiesUrl()); + ViewProperties props(rootUrl()); props.setSorting(sorting); - m_proxyModel->setSorting(sorting); + m_viewAccessor.proxyModel()->setSorting(sorting); emit sortingChanged(sorting); } void DolphinView::updateSortOrder(Qt::SortOrder order) { - ViewProperties props(viewPropertiesUrl()); + ViewProperties props(rootUrl()); props.setSortOrder(order); - m_proxyModel->setSortOrder(order); + m_viewAccessor.proxyModel()->setSortOrder(order); emit sortOrderChanged(order); } void DolphinView::updateSortFoldersFirst(bool foldersFirst) { - ViewProperties props(viewPropertiesUrl()); + ViewProperties props(rootUrl()); props.setSortFoldersFirst(foldersFirst); - m_proxyModel->setSortFoldersFirst(foldersFirst); + m_viewAccessor.proxyModel()->setSortFoldersFirst(foldersFirst); emit sortFoldersFirstChanged(foldersFirst); } void DolphinView::updateAdditionalInfo(const KFileItemDelegate::InformationList& info) { - ViewProperties props(viewPropertiesUrl()); + ViewProperties props(rootUrl()); props.setAdditionalInfo(info); props.save(); @@ -1131,7 +1085,7 @@ void DolphinView::activateItem(const KUrl& url) bool DolphinView::itemsExpandable() const { - return (m_detailsView != 0) && m_detailsView->itemsExpandable(); + return m_viewAccessor.itemsExpandable(); } void DolphinView::deleteWhenNotDragSource(QAbstractItemView *view) @@ -1157,37 +1111,34 @@ void DolphinView::deleteWhenNotDragSource(QAbstractItemView *view) void DolphinView::observeCreatedItem(const KUrl& url) { m_createdItemUrl = url; - connect(m_dolphinModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)), + connect(m_viewAccessor.dirModel(), SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(selectAndScrollToCreatedItem())); } void DolphinView::selectAndScrollToCreatedItem() { - const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_createdItemUrl); + const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForUrl(m_createdItemUrl); if (dirIndex.isValid()) { - const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); - itemView()->setCurrentIndex(proxyIndex); + const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->mapFromSource(dirIndex); + m_viewAccessor.itemView()->setCurrentIndex(proxyIndex); } - disconnect(m_dolphinModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)), + disconnect(m_viewAccessor.dirModel(), SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(selectAndScrollToCreatedItem())); m_createdItemUrl = KUrl(); } void DolphinView::restoreSelection() { - disconnect(m_dirLister, SIGNAL(completed()), this, SLOT(restoreSelection())); + disconnect(m_viewAccessor.dirLister(), SIGNAL(completed()), this, SLOT(restoreSelection())); changeSelection(m_selectedItems); } void DolphinView::emitContentsMoved() { - // only emit the contents moved signal if: - // - no directory loading is ongoing (this would reset the contents position - // always to (0, 0)) - // - if the Column View is active: the column view does an automatic - // positioning during the loading operation, which must be remembered - if (!m_loadingDirectory || isColumnViewActive()) { + // only emit the contents moved signal if no directory loading is ongoing + // (this would reset the contents position always to (0, 0)) + if (!m_loadingDirectory) { const QPoint pos(contentsPosition()); emit contentsMoved(pos.x(), pos.y()); } @@ -1222,10 +1173,10 @@ void DolphinView::slotDirListerCompleted() { if (!m_activeItemUrl.isEmpty()) { // assure that the current item remains visible - const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_activeItemUrl); + const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForUrl(m_activeItemUrl); if (dirIndex.isValid()) { - const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); - QAbstractItemView* view = itemView(); + const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->mapFromSource(dirIndex); + QAbstractItemView* view = m_viewAccessor.itemView(); const bool clearSelection = !hasSelection(); view->setCurrentIndex(proxyIndex); if (clearSelection) { @@ -1238,17 +1189,17 @@ void DolphinView::slotDirListerCompleted() if (!m_newFileNames.isEmpty()) { // select all newly added items created by a paste operation or // a drag & drop operation - const int rowCount = m_proxyModel->rowCount(); + const int rowCount = m_viewAccessor.proxyModel()->rowCount(); QItemSelection selection; for (int row = 0; row < rowCount; ++row) { - const QModelIndex proxyIndex = m_proxyModel->index(row, 0); - const QModelIndex dirIndex = m_proxyModel->mapToSource(proxyIndex); - const KUrl url = m_dolphinModel->itemForIndex(dirIndex).url(); + const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->index(row, 0); + const QModelIndex dirIndex = m_viewAccessor.proxyModel()->mapToSource(proxyIndex); + const KUrl url = m_viewAccessor.dirModel()->itemForIndex(dirIndex).url(); if (m_newFileNames.contains(url.fileName())) { selection.merge(QItemSelection(proxyIndex, proxyIndex), QItemSelectionModel::Select); } } - itemView()->selectionModel()->select(selection, QItemSelectionModel::Select); + m_viewAccessor.itemView()->selectionModel()->select(selection, QItemSelectionModel::Select); m_newFileNames.clear(); } @@ -1258,7 +1209,7 @@ void DolphinView::slotRefreshItems() { if (m_assureVisibleCurrentIndex) { m_assureVisibleCurrentIndex = false; - itemView()->scrollTo(itemView()->currentIndex()); + m_viewAccessor.itemView()->scrollTo(m_viewAccessor.itemView()->currentIndex()); } } @@ -1278,46 +1229,20 @@ void DolphinView::loadDirectory(const KUrl& url, bool reload) if (reload) { m_selectedItems = selectedItems(); - connect(m_dirLister, SIGNAL(completed()), this, SLOT(restoreSelection())); + connect(m_viewAccessor.dirLister(), SIGNAL(completed()), this, SLOT(restoreSelection())); } - m_dirLister->stop(); - m_dirLister->openUrl(url, reload ? KDirLister::Reload : KDirLister::NoFlags); - - if (isColumnViewActive()) { - // adjusting the directory lister is not enough in the case of the - // column view, as each column has its own directory lister internally... - if (reload) { - m_columnView->reload(); - } else { - m_columnView->showColumn(url); - } - } + m_viewAccessor.dirLister()->stop(); + m_viewAccessor.dirLister()->openUrl(url, reload ? KDirLister::Reload : KDirLister::NoFlags); } -KUrl DolphinView::viewPropertiesUrl() const -{ - if (isColumnViewActive()) { - return m_columnView->rootUrl(); - } - - return url(); -} - -void DolphinView::applyViewProperties(const KUrl& url) +void DolphinView::applyViewProperties() { if (m_ignoreViewProperties) { return; } - if (isColumnViewActive() && rootUrl().isParentOf(url)) { - // The column view is active, hence don't apply the view properties - // of sub directories (represented by columns) to the view. The - // view always represents the properties of the first column. - return; - } - - const ViewProperties props(url); + const ViewProperties props(rootUrl()); const Mode mode = props.viewMode(); if (m_mode != mode) { @@ -1329,40 +1254,40 @@ void DolphinView::applyViewProperties(const KUrl& url) updateZoomLevel(oldZoomLevel); } - if (itemView() == 0) { + if (m_viewAccessor.itemView() == 0) { createView(); } - Q_ASSERT(itemView() != 0); + Q_ASSERT(m_viewAccessor.itemView() != 0); Q_ASSERT(m_fileItemDelegate != 0); const bool showHiddenFiles = props.showHiddenFiles(); - if (showHiddenFiles != m_dirLister->showingDotFiles()) { - m_dirLister->setShowingDotFiles(showHiddenFiles); + if (showHiddenFiles != m_viewAccessor.dirLister()->showingDotFiles()) { + m_viewAccessor.dirLister()->setShowingDotFiles(showHiddenFiles); emit showHiddenFilesChanged(); } m_storedCategorizedSorting = props.categorizedSorting(); const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting(); - if (categorized != m_proxyModel->isCategorizedModel()) { - m_proxyModel->setCategorizedModel(categorized); + if (categorized != m_viewAccessor.proxyModel()->isCategorizedModel()) { + m_viewAccessor.proxyModel()->setCategorizedModel(categorized); emit categorizedSortingChanged(); } const DolphinView::Sorting sorting = props.sorting(); - if (sorting != m_proxyModel->sorting()) { - m_proxyModel->setSorting(sorting); + if (sorting != m_viewAccessor.proxyModel()->sorting()) { + m_viewAccessor.proxyModel()->setSorting(sorting); emit sortingChanged(sorting); } const Qt::SortOrder sortOrder = props.sortOrder(); - if (sortOrder != m_proxyModel->sortOrder()) { - m_proxyModel->setSortOrder(sortOrder); + if (sortOrder != m_viewAccessor.proxyModel()->sortOrder()) { + m_viewAccessor.proxyModel()->setSortOrder(sortOrder); emit sortOrderChanged(sortOrder); } const bool sortFoldersFirst = props.sortFoldersFirst(); - if (sortFoldersFirst != m_proxyModel->sortFoldersFirst()) { - m_proxyModel->setSortFoldersFirst(sortFoldersFirst); + if (sortFoldersFirst != m_viewAccessor.proxyModel()->sortFoldersFirst()) { + m_viewAccessor.proxyModel()->setSortFoldersFirst(sortFoldersFirst); emit sortFoldersFirstChanged(sortFoldersFirst); } @@ -1397,52 +1322,69 @@ void DolphinView::applyViewProperties(const KUrl& url) void DolphinView::createView() { deleteView(); - Q_ASSERT(m_iconsView == 0); - Q_ASSERT(m_detailsView == 0); - Q_ASSERT(m_columnView == 0); + Q_ASSERT(m_viewAccessor.itemView() == 0); + m_viewAccessor.createView(this, m_controller, m_mode); + initializeView(); + m_topLayout->insertWidget(1, m_viewAccessor.layoutTarget()); +} - QAbstractItemView* view = 0; - switch (m_mode) { - case IconsView: { - m_iconsView = new DolphinIconsView(this, m_controller); - view = m_iconsView; - break; - } - - case DetailsView: - m_detailsView = new DolphinDetailsView(this, m_controller); - view = m_detailsView; - break; - - case ColumnView: - m_columnView = new DolphinColumnView(this, m_controller); - view = m_columnView; - break; +void DolphinView::deleteView() +{ + QAbstractItemView* view = m_viewAccessor.itemView(); + 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(); + + // m_previewGenerator's parent is not always destroyed, and we + // don't want two active at once - manually delete. + delete m_previewGenerator; + m_previewGenerator = 0; + + disconnect(view); + m_controller->disconnect(view); + view->disconnect(); + + // TODO: move this code into ViewAccessor::deleteView() + deleteWhenNotDragSource(view); + view = 0; + + m_viewAccessor.deleteView(); + m_fileItemDelegate = 0; + m_toolTipManager = 0; } +} +void DolphinView::initializeView() +{ + QAbstractItemView* view = m_viewAccessor.itemView(); Q_ASSERT(view != 0); view->installEventFilter(this); view->viewport()->installEventFilter(this); setFocusProxy(view); - if (m_mode != ColumnView) { + //if (m_mode != ColumnView) { // Give the view the ability to auto-expand its directories on hovering // (the column view takes care about this itself). If the details view // uses expandable folders, the auto-expanding should be used always. - DolphinSettings& settings = DolphinSettings::instance(); - const bool enabled = settings.generalSettings()->autoExpandFolders() || - ((m_detailsView != 0) && settings.detailsModeSettings()->expandableFolders()); - - FolderExpander* folderExpander = new FolderExpander(view, m_proxyModel); - folderExpander->setEnabled(enabled); + FolderExpander* folderExpander = new FolderExpander(view, m_viewAccessor.proxyModel()); + folderExpander->setEnabled(m_viewAccessor.hasExpandableFolders()); connect(folderExpander, SIGNAL(enterDir(const QModelIndex&)), m_controller, SLOT(triggerItem(const QModelIndex&))); - } + + // TODO: enable again later + /*} else { // Listen out for requests to delete the current column. - connect(m_columnView, SIGNAL(requestColumnDeletion(QAbstractItemView*)), + connect(m_viewAccessor.columnsContainer(), SIGNAL(requestColumnDeletion(QAbstractItemView*)), this, SLOT(deleteWhenNotDragSource(QAbstractItemView*))); - } + }*/ m_controller->setItemView(view); @@ -1451,7 +1393,7 @@ void DolphinView::createView() m_fileItemDelegate->setMinimizedNameColumn(m_mode == DetailsView); view->setItemDelegate(m_fileItemDelegate); - view->setModel(m_proxyModel); + view->setModel(m_viewAccessor.proxyModel()); if (m_selectionModel != 0) { view->setSelectionModel(m_selectionModel); } else { @@ -1482,13 +1424,11 @@ void DolphinView::createView() this, SIGNAL(operationCompletedMessage(const QString&))); if (DolphinSettings::instance().generalSettings()->showToolTips()) { - m_toolTipManager = new ToolTipManager(view, m_proxyModel); + m_toolTipManager = new ToolTipManager(view, m_viewAccessor.proxyModel()); connect(m_controller, SIGNAL(hideToolTip()), m_toolTipManager, SLOT(hideTip())); } - m_topLayout->insertWidget(1, view); - connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), this, SLOT(emitDelayedSelectionChangedSignal())); connect(view->verticalScrollBar(), SIGNAL(valueChanged(int)), @@ -1497,51 +1437,6 @@ void DolphinView::createView() this, SLOT(emitContentsMoved())); } -void DolphinView::deleteView() -{ - QAbstractItemView* view = itemView(); - 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(); - - // m_previewGenerator's parent is not always destroyed, and we - // don't want two active at once - manually delete. - delete m_previewGenerator; - m_previewGenerator = 0; - - disconnect(view); - m_controller->disconnect(view); - view->disconnect(); - - deleteWhenNotDragSource(view); - view = 0; - - m_iconsView = 0; - m_detailsView = 0; - m_columnView = 0; - m_fileItemDelegate = 0; - m_toolTipManager = 0; - } -} - -QAbstractItemView* DolphinView::itemView() const -{ - if (m_detailsView != 0) { - return m_detailsView; - } else if (m_columnView != 0) { - return m_columnView; - } - - return m_iconsView; -} - void DolphinView::pasteToUrl(const KUrl& url) { addNewFileNames(QApplication::clipboard()->mimeData()); @@ -1550,7 +1445,7 @@ void DolphinView::pasteToUrl(const KUrl& url) void DolphinView::updateZoomLevel(int oldZoomLevel) { - const int newZoomLevel = ZoomLevelInfo::zoomLevelForIconSize(itemView()->iconSize()); + const int newZoomLevel = ZoomLevelInfo::zoomLevelForIconSize(m_viewAccessor.itemView()->iconSize()); if (oldZoomLevel != newZoomLevel) { m_controller->setZoomLevel(newZoomLevel); emit zoomLevelChanged(newZoomLevel); @@ -1568,14 +1463,10 @@ KUrl::List DolphinView::simplifiedSelectedUrls() const QMimeData* DolphinView::selectionMimeData() const { - if (isColumnViewActive()) { - return m_columnView->selectionMimeData(); - } - - const QAbstractItemView* view = itemView(); + const QAbstractItemView* view = m_viewAccessor.itemView(); Q_ASSERT((view != 0) && (view->selectionModel() != 0)); - const QItemSelection selection = m_proxyModel->mapSelectionToSource(view->selectionModel()->selection()); - return m_dolphinModel->mimeData(selection.indexes()); + const QItemSelection selection = m_viewAccessor.proxyModel()->mapSelectionToSource(view->selectionModel()->selection()); + return m_viewAccessor.dirModel()->mimeData(selection.indexes()); } void DolphinView::addNewFileNames(const QMimeData* mimeData) @@ -1586,4 +1477,139 @@ void DolphinView::addNewFileNames(const QMimeData* mimeData) } } +DolphinView::ViewAccessor::ViewAccessor(DolphinSortFilterProxyModel* proxyModel) : + m_iconsView(0), + m_detailsView(0), + m_columnsContainer(0), + m_proxyModel(proxyModel) +{ +} + +void DolphinView::ViewAccessor::createView(QWidget* parent, + DolphinController* controller, + Mode mode) +{ + Q_ASSERT(itemView() == 0); + + switch (mode) { + case IconsView: + m_iconsView = new DolphinIconsView(parent, controller); + break; + + case DetailsView: + m_detailsView = new DolphinDetailsView(parent, controller); + break; + + case ColumnView: + m_columnsContainer = new DolphinColumnViewContainer(parent, controller); + break; + + default: + Q_ASSERT(false); + } +} + +void DolphinView::ViewAccessor::deleteView() +{ + // TODO: Move the deleteWhenNotDragSource() code into the view + // accessor, so that creating and deleting is fully done by + // the view accessor. + m_iconsView = 0; + m_detailsView = 0; + + m_columnsContainer->deleteLater(); + m_columnsContainer = 0; +} + + +bool DolphinView::ViewAccessor::prepareUrlChange(const KUrl& url) +{ + if (m_columnsContainer != 0) { + return m_columnsContainer->showColumn(url); + } + return false; +} + +QAbstractItemView* DolphinView::ViewAccessor::itemView() const +{ + if (m_iconsView != 0) { + return m_iconsView; + } + + if (m_detailsView != 0) { + return m_detailsView; + } + + if (m_columnsContainer != 0) { + return m_columnsContainer->activeColumn(); + } + + return 0; +} + +QWidget* DolphinView::ViewAccessor::layoutTarget() const +{ + if (m_columnsContainer != 0) { + return m_columnsContainer; + } + return itemView(); +} + +void DolphinView::ViewAccessor::setNameFilter(const QString& nameFilter) +{ + if (m_columnsContainer == 0) { + m_columnsContainer->setNameFilter(nameFilter); + } else { + proxyModel()->setFilterRegExp(nameFilter); + } +} + +KUrl DolphinView::ViewAccessor::rootUrl() const +{ + return (m_columnsContainer != 0) ? m_columnsContainer->rootUrl() : KUrl(); +} + +bool DolphinView::ViewAccessor::supportsCategorizedSorting() const +{ + return m_iconsView != 0; +} + +bool DolphinView::ViewAccessor::hasExpandableFolders() const +{ + const DolphinSettings& settings = DolphinSettings::instance(); + return settings.generalSettings()->autoExpandFolders() || + ((m_detailsView != 0) && settings.detailsModeSettings()->expandableFolders()); +} + +bool DolphinView::ViewAccessor::itemsExpandable() const +{ + return (m_detailsView != 0) && m_detailsView->itemsExpandable(); +} + +bool DolphinView::ViewAccessor::reloadOnAdditionalInfoChange() const +{ + // the details view requires no reloading of the directory, as it maps + // the file item delegate info to its columns internally + return m_detailsView != 0; +} + + +DolphinModel* DolphinView::ViewAccessor::dirModel() const +{ + return static_cast(proxyModel()->sourceModel()); +} + +DolphinSortFilterProxyModel* DolphinView::ViewAccessor::proxyModel() const +{ + if (m_columnsContainer != 0) { + return static_cast(m_columnsContainer->activeColumn()->model()); + } + return m_proxyModel; +} + +KDirLister* DolphinView::ViewAccessor::dirLister() const +{ + return dirModel()->dirLister(); +} + #include "dolphinview.moc" diff --git a/src/dolphinview.h b/src/dolphinview.h index 58924697ed..93299b4301 100644 --- a/src/dolphinview.h +++ b/src/dolphinview.h @@ -42,7 +42,7 @@ typedef KIO::FileUndoManager::CommandType CommandType; class DolphinController; -class DolphinColumnView; +class DolphinColumnViewContainer; class DolphinDetailsView; class DolphinFileItemDelegate; class DolphinIconsView; @@ -123,18 +123,12 @@ public: /** * @param parent Parent widget of the view. * @param url Specifies the content which should be shown. - * @param dirLister Used directory lister. The lister is not owned - * by the view and won't get deleted. - * @param dolphinModel Used directory model. The model is not owned - * by the view and won't get deleted. * @param proxyModel Used proxy model which specifies the sorting. The * model is not owned by the view and won't get * deleted. */ DolphinView(QWidget* parent, const KUrl& url, - KDirLister* dirLister, - DolphinModel* dolphinModel, DolphinSortFilterProxyModel* proxyModel); virtual ~DolphinView(); @@ -713,20 +707,11 @@ private slots: private: void loadDirectory(const KUrl& url, bool reload = false); - /** - * Returns the URL where the view properties should be stored. Usually - * DolphinView::url() is returned, but in the case of a Column View the - * view properties are always stored in the directory represented by the - * first column. It is recommendend whenever using the ViewProperties class - * to use DolphinView::viewPropertiesUrl() as URL. - */ - KUrl viewPropertiesUrl() const; - /** * Applies the view properties which are defined by the current URL - * m_url to the DolphinView properties. + * to the DolphinView properties. */ - void applyViewProperties(const KUrl& url); + void applyViewProperties(); /** * Creates a new view representing the given view mode (DolphinView::mode()). @@ -736,11 +721,7 @@ private: void deleteView(); - /** - * Returns a pointer to the currently used item view, which is either - * a ListView or a TreeView. - */ - QAbstractItemView* itemView() const; + void initializeView(); /** * Helper method for DolphinView::paste() and DolphinView::pasteIntoFolder(). @@ -763,13 +744,6 @@ private: */ KUrl::List simplifiedSelectedUrls() const; - /** - * Returns true, if the ColumnView is activated. As the column view - * requires some special handling for iterating through directories, - * this method has been introduced for convenience. - */ - bool isColumnViewActive() const; - /** * Returns the MIME data for all selected items. */ @@ -784,6 +758,53 @@ private: void addNewFileNames(const QMimeData* mimeData); private: + /** + * Abstracts the access to the different view implementations + * for icons-, details- and column-view. + */ + class ViewAccessor + { + public: + ViewAccessor(DolphinSortFilterProxyModel* proxyModel); + + void createView(QWidget* parent, DolphinController* controller, Mode mode); + void deleteView(); + bool prepareUrlChange(const KUrl& url); + QAbstractItemView* itemView() const; + + /** + * Returns the widget that should be added to the layout as target. Usually + * the item view itself is returned, but in the case of the column view + * a container widget is returned. + */ + QWidget* layoutTarget() const; + + void setNameFilter(const QString& nameFilter); + + KUrl rootUrl() const; + + bool supportsCategorizedSorting() const; + bool hasExpandableFolders() const; + bool itemsExpandable() const; + + /** + * Returns true, if a reloading of the items is required + * when the additional information properties have been changed + * by the user. + */ + bool reloadOnAdditionalInfoChange() const; + + DolphinModel* dirModel() const; + DolphinSortFilterProxyModel* proxyModel() const; + KDirLister* dirLister() const; + + private: + DolphinIconsView* m_iconsView; + DolphinDetailsView* m_detailsView; + DolphinColumnViewContainer* m_columnsContainer; + DolphinSortFilterProxyModel* m_proxyModel; + }; + bool m_active : 1; bool m_showPreview : 1; bool m_loadingDirectory : 1; @@ -799,18 +820,12 @@ private: QVBoxLayout* m_topLayout; DolphinController* m_controller; - DolphinIconsView* m_iconsView; - DolphinDetailsView* m_detailsView; - DolphinColumnView* m_columnView; DolphinFileItemDelegate* m_fileItemDelegate; + ViewAccessor m_viewAccessor; QItemSelectionModel* m_selectionModel; QTimer* m_selectionChangedTimer; - DolphinModel* m_dolphinModel; - KDirLister* m_dirLister; - DolphinSortFilterProxyModel* m_proxyModel; - KFilePreviewGenerator* m_previewGenerator; ToolTipManager* m_toolTipManager; @@ -828,14 +843,9 @@ private: */ QSet m_newFileNames; - QAbstractItemView* m_expandedDragSource; + QAbstractItemView* m_expandedDragSource; // TODO: move to ViewAccessor }; -inline bool DolphinView::isColumnViewActive() const -{ - return m_columnView != 0; -} - /// Allow using DolphinView::Mode in QVariant Q_DECLARE_METATYPE(DolphinView::Mode) diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp index e9417e1bc8..ae6953aad0 100644 --- a/src/dolphinviewcontainer.cpp +++ b/src/dolphinviewcontainer.cpp @@ -128,11 +128,7 @@ DolphinViewContainer::DolphinViewContainer(DolphinMainWindow* mainWindow, connect(m_dirLister, SIGNAL(urlIsFileError(const KUrl&)), this, SLOT(openFile(const KUrl&))); - m_view = new DolphinView(this, - url, - m_dirLister, - m_dolphinModel, - m_proxyModel); + m_view = new DolphinView(this, url, m_proxyModel); connect(m_view, SIGNAL(urlChanged(const KUrl&)), m_urlNavigator, SLOT(setUrl(const KUrl&))); connect(m_view, SIGNAL(requestContextMenu(KFileItem, const KUrl&, const QList&)),