X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/093efca22dfd247f06e2a669ad968300e71ef08d..a0d3cf4aa8ffa76ed22a67efa4ea156eb2ef9f68:/src/dolphincolumnview.cpp diff --git a/src/dolphincolumnview.cpp b/src/dolphincolumnview.cpp index 3f6523ebe..debe10d35 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 * @@ -20,915 +20,449 @@ #include "dolphincolumnview.h" #include "dolphinmodel.h" +#include "dolphincolumnviewcontainer.h" #include "dolphincontroller.h" -#include "dolphinsettings.h" - +#include "dolphindirlister.h" +#include "dolphinsortfilterproxymodel.h" +#include "settings/dolphinsettings.h" +#include "dolphinviewautoscroller.h" #include "dolphin_columnmodesettings.h" +#include "dolphin_generalsettings.h" +#include "draganddrophelper.h" +#include "folderexpander.h" +#include "tooltips/tooltipmanager.h" +#include "viewextensionsfactory.h" +#include "zoomlevelinfo.h" -#include #include #include +#include +#include +#include +#include +#include -#include #include +#include +#include #include #include -#include -#include - -/** - * Represents one column inside the DolphinColumnView and has been - * extended to respect view options and hovering information. - */ -class ColumnWidget : public QListView -{ -public: - ColumnWidget(QWidget* parent, - DolphinColumnView* columnView, - const KUrl& url); - virtual ~ColumnWidget(); - - /** 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 - * 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. */ - inline const KUrl& url() const; - -protected: - virtual QStyleOptionViewItem viewOptions() const; - 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 keyPressEvent(QKeyEvent* event); - virtual void contextMenuEvent(QContextMenuEvent* event); - virtual void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected); - -private: - /** Used by ColumnWidget::setActive(). */ - void activate(); - - /** Used by ColumnWidget::setActive(). */ - void deactivate(); - -private: - bool m_active; - DolphinColumnView* m_view; - KUrl m_url; // URL of the directory that is shown - KUrl m_childUrl; // URL of the next column that is shown - QStyleOptionViewItem m_viewOptions; - - bool m_dragging; // TODO: remove this property when the issue #160611 is solved in Qt 4.4 - QRect m_dropRect; // TODO: remove this property when the issue #160611 is solved in Qt 4.4 -}; - -ColumnWidget::ColumnWidget(QWidget* parent, - DolphinColumnView* columnView, - const KUrl& url) : + +DolphinColumnView::DolphinColumnView(QWidget* parent, + DolphinColumnViewContainer* container, + const KUrl& url) : QListView(parent), - m_active(true), - m_view(columnView), + m_active(false), + m_container(container), + m_extensionsFactory(0), m_url(url), m_childUrl(), - m_dragging(false), + m_font(), + m_decorationSize(), + m_dirLister(0), + m_dolphinModel(0), + m_proxyModel(0), m_dropRect() { setMouseTracking(true); - viewport()->setAttribute(Qt::WA_Hover); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setSelectionBehavior(SelectItems); setSelectionMode(QAbstractItemView::ExtendedSelection); setDragDropMode(QAbstractItemView::DragDrop); setDropIndicatorShown(false); - setFocusPolicy(Qt::NoFocus); + setSelectionRectVisible(true); + setEditTriggers(QAbstractItemView::NoEditTriggers); + + setVerticalScrollMode(QListView::ScrollPerPixel); + setHorizontalScrollMode(QListView::ScrollPerPixel); // apply the column mode settings to the widget const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); Q_ASSERT(settings != 0); - m_viewOptions = QListView::viewOptions(); + if (settings->useSystemFont()) { + m_font = KGlobalSettings::generalFont(); + } else { + m_font = QFont(settings->fontFamily(), + settings->fontSize(), + settings->fontWeight(), + settings->italicFont()); + } - QFont font(settings->fontFamily(), settings->fontSize()); - font.setItalic(settings->italicFont()); - font.setBold(settings->boldFont()); - m_viewOptions.font = font; + activate(); - const int iconSize = settings->iconSize(); - m_viewOptions.decorationSize = QSize(iconSize, iconSize); + connect(this, SIGNAL(viewportEntered()), + m_container->m_controller, SLOT(emitViewportEntered())); + connect(this, SIGNAL(entered(const QModelIndex&)), + this, SLOT(slotEntered(const QModelIndex&))); - KFileItemDelegate* delegate = new KFileItemDelegate(this); - setItemDelegate(delegate); + const DolphinView* dolphinView = m_container->m_controller->dolphinView(); + connect(dolphinView, SIGNAL(showPreviewChanged()), + this, SLOT(slotShowPreviewChanged())); - activate(); + 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); - connect(this, SIGNAL(entered(const QModelIndex&)), - m_view->m_controller, SLOT(emitItemEntered(const QModelIndex&))); - connect(this, SIGNAL(viewportEntered()), - m_view->m_controller, SLOT(emitViewportEntered())); -} + m_dolphinModel = new DolphinModel(this); + m_dolphinModel->setDirLister(m_dirLister); + m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory); -ColumnWidget::~ColumnWidget() -{ + m_proxyModel = new DolphinSortFilterProxyModel(this); + m_proxyModel->setSourceModel(m_dolphinModel); + m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + + m_proxyModel->setSorting(dolphinView->sorting()); + m_proxyModel->setSortOrder(dolphinView->sortOrder()); + m_proxyModel->setSortFoldersFirst(dolphinView->sortFoldersFirst()); + + setModel(m_proxyModel); + + connect(KGlobalSettings::self(), SIGNAL(kdisplayFontChanged()), + this, SLOT(updateFont())); + + DolphinController* controller = m_container->m_controller; + connect(controller, SIGNAL(zoomLevelChanged(int)), + this, SLOT(setZoomLevel(int))); + + const QString nameFilter = controller->nameFilter(); + if (!nameFilter.isEmpty()) { + m_proxyModel->setFilterFixedString(nameFilter); + } + + updateDecorationSize(dolphinView->showPreview()); + m_extensionsFactory = new ViewExtensionsFactory(this, controller); } -void ColumnWidget::setDecorationSize(const QSize& size) +DolphinColumnView::~DolphinColumnView() { - m_viewOptions.decorationSize = size; - doItemsLayout(); + delete m_proxyModel; + m_proxyModel = 0; + delete m_dolphinModel; + m_dolphinModel = 0; + m_dirLister = 0; // deleted by m_dolphinModel } -void ColumnWidget::setActive(bool active) +void DolphinColumnView::setActive(bool active) { - if (m_active == active) { - return; + if (active && (m_container->focusProxy() != this)) { + m_container->setFocusProxy(this); } - m_active = active; + if (m_active != active) { + m_active = active; - if (active) { - activate(); - } else { - deactivate(); + if (active) { + activate(); + } else { + deactivate(); + } } } -inline bool ColumnWidget::isActive() const +void DolphinColumnView::updateBackground() { - return m_active; -} + // 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); -inline void ColumnWidget::setChildUrl(const KUrl& url) -{ - m_childUrl = url; + QPalette palette = viewport()->palette(); + palette.setColor(role, color); + viewport()->setPalette(palette); + + update(); } -inline const KUrl& ColumnWidget::childUrl() const +KFileItem DolphinColumnView::itemAt(const QPoint& pos) const { - return m_childUrl; + 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; } -inline void ColumnWidget::setUrl(const KUrl& url) +void DolphinColumnView::setSelectionModel(QItemSelectionModel* model) { - m_url = url; + // If a change of the selection is done although the view is not active + // (e. g. by the selection markers), the column must be activated. This + // is done by listening to the current selectionChanged() signal. + if (selectionModel() != 0) { + disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(requestActivation())); + } + + QListView::setSelectionModel(model); + + connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(requestActivation())); } -const KUrl& ColumnWidget::url() const +QStyleOptionViewItem DolphinColumnView::viewOptions() const { - return m_url; + QStyleOptionViewItem viewOptions = QListView::viewOptions(); + viewOptions.font = m_font; + viewOptions.fontMetrics = QFontMetrics(m_font); + viewOptions.decorationSize = m_decorationSize; + viewOptions.showDecorationSelected = true; + return viewOptions; } -QStyleOptionViewItem ColumnWidget::viewOptions() const +void DolphinColumnView::startDrag(Qt::DropActions supportedActions) { - return m_viewOptions; + DragAndDropHelper::instance().startDrag(this, supportedActions, m_container->m_controller); } -void ColumnWidget::dragEnterEvent(QDragEnterEvent* event) +void DolphinColumnView::dragEnterEvent(QDragEnterEvent* event) { - if (event->mimeData()->hasUrls()) { + if (DragAndDropHelper::instance().isMimeDataSupported(event->mimeData())) { event->acceptProposedAction(); + requestActivation(); } - - m_dragging = true; } -void ColumnWidget::dragLeaveEvent(QDragLeaveEvent* event) +void DolphinColumnView::dragLeaveEvent(QDragLeaveEvent* event) { QListView::dragLeaveEvent(event); - - // TODO: remove this code when the issue #160611 is solved in Qt 4.4 - m_dragging = false; setDirtyRegion(m_dropRect); } -void ColumnWidget::dragMoveEvent(QDragMoveEvent* event) +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 = visualRect(index); + + 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); -} -void ColumnWidget::dropEvent(QDropEvent* event) -{ - const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); - if (!urls.isEmpty()) { + if (DragAndDropHelper::instance().isMimeDataSupported(event->mimeData())) { + // accept url drops, independently from the destination item event->acceptProposedAction(); - m_view->m_controller->indicateDroppedUrls(urls, - url(), - indexAt(event->pos()), - event->source()); } +} + +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); - m_dragging = false; } -void ColumnWidget::paintEvent(QPaintEvent* 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_view->m_dolphinModel->indexForUrl(m_childUrl); - const QModelIndex proxyIndex = m_view->m_proxyModel->mapFromSource(dirIndex); + 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()); - painter.save(); - QColor color = KColorScheme(QPalette::Active, KColorScheme::View).foreground().color(); color.setAlpha(32); painter.setPen(Qt::NoPen); painter.setBrush(color); painter.drawRect(itemRect); - - painter.restore(); } } QListView::paintEvent(event); - - // TODO: remove this code when the issue #160611 is solved in Qt 4.4 - if (m_dragging) { - const QBrush& brush = m_viewOptions.palette.brush(QPalette::Normal, QPalette::Highlight); - DolphinController::drawHoverIndication(viewport(), m_dropRect, brush); - } } -void ColumnWidget::mousePressEvent(QMouseEvent* event) +void DolphinColumnView::mousePressEvent(QMouseEvent* event) { - if (!m_active) { - m_view->requestActivation(this); + 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); } -void ColumnWidget::keyPressEvent(QKeyEvent* event) +void DolphinColumnView::keyPressEvent(QKeyEvent* event) { QListView::keyPressEvent(event); - - const QItemSelectionModel* selModel = selectionModel(); - const QModelIndex currentIndex = selModel->currentIndex(); - const bool triggerItem = currentIndex.isValid() - && (event->key() == Qt::Key_Return) - && (selModel->selectedIndexes().count() <= 1); - if (triggerItem) { - m_view->m_controller->triggerItem(currentIndex); - } -} - -void ColumnWidget::contextMenuEvent(QContextMenuEvent* event) -{ - if (!m_active) { - m_view->requestActivation(this); - } - - QListView::contextMenuEvent(event); - - const QModelIndex index = indexAt(event->pos()); - if (index.isValid() || m_active) { - // Only open a context menu above an item or if the mouse is above - // the active column. - const QPoint pos = m_view->viewport()->mapFromGlobal(event->globalPos()); - m_view->m_controller->triggerContextMenuRequest(pos); - } -} - -void ColumnWidget::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) -{ - QListView::selectionChanged(selected, deselected); - - QItemSelectionModel* selModel = m_view->selectionModel(); - selModel->select(selected, QItemSelectionModel::Select); - selModel->select(deselected, QItemSelectionModel::Deselect); -} - -void ColumnWidget::activate() -{ - if (m_view->hasFocus()) { - setFocus(Qt::OtherFocusReason); - } - m_view->setFocusProxy(this); - - // TODO: Connecting to the signal 'activated()' is not possible, as kstyle - // does not forward the single vs. doubleclick to it yet (KDE 4.1?). Hence it is - // necessary connecting the signal 'singleClick()' or 'doubleClick'. - if (KGlobalSettings::singleClick()) { - connect(this, SIGNAL(clicked(const QModelIndex&)), - m_view->m_controller, SLOT(triggerItem(const QModelIndex&))); - } else { - connect(this, SIGNAL(doubleClicked(const QModelIndex&)), - m_view->m_controller, SLOT(triggerItem(const QModelIndex&))); - } - - const QColor bgColor = KColorScheme(QPalette::Active, KColorScheme::View).background().color(); - QPalette palette = viewport()->palette(); - palette.setColor(viewport()->backgroundRole(), bgColor); - viewport()->setPalette(palette); - - if (!m_childUrl.isEmpty()) { - // assure that the current index is set on the index that represents - // the child URL - const QModelIndex dirIndex = m_view->m_dolphinModel->indexForUrl(m_childUrl); - const QModelIndex proxyIndex = m_view->m_proxyModel->mapFromSource(dirIndex); - selectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::Current); - } - - update(); -} - -void ColumnWidget::deactivate() -{ - // TODO: Connecting to the signal 'activated()' is not possible, as kstyle - // does not forward the single vs. doubleclick to it yet (KDE 4.1?). Hence it is - // necessary connecting the signal 'singleClick()' or 'doubleClick'. - if (KGlobalSettings::singleClick()) { - disconnect(this, SIGNAL(clicked(const QModelIndex&)), - m_view->m_controller, SLOT(triggerItem(const QModelIndex&))); - } else { - disconnect(this, SIGNAL(doubleClicked(const QModelIndex&)), - m_view->m_controller, SLOT(triggerItem(const QModelIndex&))); - } - - const QPalette palette = m_view->viewport()->palette(); - viewport()->setPalette(palette); - - selectionModel()->clear(); - update(); -} - -// --- - -DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* controller) : - QAbstractItemView(parent), - m_controller(controller), - m_restoreActiveColumnFocus(false), - m_dirListerCompleted(false), - m_index(-1), - m_contentX(0), - m_columns(), - m_animation(0), - m_dolphinModel(0), - m_proxyModel(0) -{ - Q_ASSERT(controller != 0); - - setAcceptDrops(true); - setDragDropMode(QAbstractItemView::DragDrop); - setDropIndicatorShown(false); - setSelectionMode(ExtendedSelection); - - connect(this, SIGNAL(entered(const QModelIndex&)), - controller, SLOT(emitItemEntered(const QModelIndex&))); - connect(this, SIGNAL(viewportEntered()), - controller, SLOT(emitViewportEntered())); - connect(controller, SIGNAL(zoomIn()), - this, SLOT(zoomIn())); - connect(controller, SIGNAL(zoomOut()), - this, SLOT(zoomOut())); - connect(controller, SIGNAL(urlChanged(const KUrl&)), - this, SLOT(showColumn(const KUrl&))); - - connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), - this, SLOT(moveContentHorizontally(int))); - - ColumnWidget* column = new ColumnWidget(viewport(), this, m_controller->url()); - m_columns.append(column); - setActiveColumnIndex(0); - - updateDecorationSize(); - - m_animation = new QTimeLine(500, this); - connect(m_animation, SIGNAL(frameChanged(int)), horizontalScrollBar(), SLOT(setValue(int))); - - // dim the background of the viewport - QColor bgColor = KColorScheme(QPalette::Active, KColorScheme::View).background().color(); - const QColor fgColor = KColorScheme(QPalette::Active, KColorScheme::View).foreground().color(); - bgColor = KColorUtils::mix(bgColor, fgColor, 0.04); - - QPalette palette = viewport()->palette(); - palette.setColor(viewport()->backgroundRole(), bgColor); - viewport()->setPalette(palette); -} - -DolphinColumnView::~DolphinColumnView() -{ -} - -QModelIndex DolphinColumnView::indexAt(const QPoint& point) const -{ - foreach (ColumnWidget* column, m_columns) { - const QPoint topLeft = column->frameGeometry().topLeft(); - const QPoint adjustedPoint(point.x() - topLeft.x(), point.y() - topLeft.y()); - const QModelIndex index = column->indexAt(adjustedPoint); - if (index.isValid()) { - return index; - } - } - - return QModelIndex(); -} - -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::setModel(QAbstractItemModel* model) -{ - if (m_dolphinModel != 0) { - m_dolphinModel->disconnect(this); - } - - m_proxyModel = static_cast(model); - m_dolphinModel = static_cast(m_proxyModel->sourceModel()); - connect(m_dolphinModel, SIGNAL(expand(const QModelIndex&)), - this, SLOT(triggerReloadColumns(const QModelIndex&))); - - KDirLister* dirLister = m_dolphinModel->dirLister(); - connect(dirLister, SIGNAL(started(const KUrl&)), - this, SLOT(slotDirListerStarted(const KUrl&))); - connect(dirLister, SIGNAL(completed()), - this, SLOT(slotDirListerCompleted())); - - activeColumn()->setModel(model); - QAbstractItemView::setModel(model); -} - -void DolphinColumnView::invertSelection() -{ - // TODO: this approach of inverting the selection is quite slow. It should - // be possible to speedup the implementation by using QItemSelection, but - // all adempts have failed yet... - - ColumnWidget* column = activeColumn(); - QItemSelectionModel* selModel = column->selectionModel(); - - KDirLister* dirLister = m_dolphinModel->dirLister(); - const KFileItemList list = dirLister->itemsForDir(column->url()); - foreach (KFileItem* item, list) { - const QModelIndex index = m_dolphinModel->indexForUrl(item->url()); - selModel->select(m_proxyModel->mapFromSource(index), QItemSelectionModel::Toggle); - } -} - -void DolphinColumnView::reload() -{ - // Due to the reloading of the model all columns will be reset to show - // the same content as the first column. As this is not wanted, all columns - // except of the first column are temporary hidden until the root index can - // be updated again. - m_restoreActiveColumnFocus = false; - QList::iterator start = m_columns.begin() + 1; - QList::iterator end = m_columns.end(); - for (QList::iterator it = start; it != end; ++it) { - ColumnWidget* column = (*it); - if (column->isActive() && column->hasFocus()) { - // because of hiding the column, it will lose the focus - // -> remember that the focus should be restored after reloading - m_restoreActiveColumnFocus = true; - } - column->hide(); - } - - // all columns are hidden, now reload the directory lister - KDirLister* dirLister = m_dolphinModel->dirLister(); - const KUrl& rootUrl = m_columns[0]->url(); - dirLister->openUrl(rootUrl, false, true); - updateColumns(); -} - -void DolphinColumnView::showColumn(const KUrl& url) -{ - const KUrl& rootUrl = m_columns[0]->url(); - if (!rootUrl.isParentOf(url)) { - // the URL is no child URL of the column view, hence clear all columns - // and reset the root column - QList::iterator start = m_columns.begin() + 1; - QList::iterator end = m_columns.end(); - for (QList::iterator it = start; it != end; ++it) { - (*it)->deleteLater(); - } - m_columns.erase(start, end); - m_index = 0; - m_columns[0]->setActive(true); - m_columns[0]->setUrl(url); - assureVisibleActiveColumn(); - return; - } - - KDirLister* dirLister = m_dolphinModel->dirLister(); - const KUrl dirListerUrl = dirLister->url(); - if (dirListerUrl != rootUrl) { - // It is possible that root URL of the directory lister is adjusted - // after creating the column widget (e. g. when restoring the history - // having a different root URL than the controller indicates). - m_columns[0]->setUrl(dirListerUrl); - } - - int columnIndex = 0; - foreach (ColumnWidget* column, m_columns) { - if (column->url() == url) { - // the column represents already the requested URL, hence activate it - requestActivation(column); - 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) { - (*it)->deleteLater(); - } - 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); - const QModelIndex dirIndex = m_dolphinModel->indexForUrl(KUrl(path)); - const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); - - m_columns[columnIndex]->setChildUrl(childUrl); - columnIndex++; - - ColumnWidget* column = new ColumnWidget(viewport(), this, childUrl); - column->setVerticalScrollMode(ColumnWidget::ScrollPerPixel); - column->setHorizontalScrollMode(ColumnWidget::ScrollPerPixel); - column->setModel(model()); - column->setRootIndex(proxyIndex); - 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(); - - // the layout is finished, now let the column be invisible until it - // gets a valid root index due to expandToActiveUrl() - column->hide(); - } - } - - // set the last column as active column without modifying the controller - // and hence the history - activeColumn()->setActive(false); - m_index = columnIndex; - activeColumn()->setActive(true); -} - -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; - } - } - - switch (cursorAction) { - case MoveLeft: - if (m_index > 0) { - setActiveColumnIndex(m_index - 1); + 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); - } + case Qt::Key_Escape: + selectionModel()->setCurrentIndex(selectionModel()->currentIndex(), + QItemSelectionModel::Current | + QItemSelectionModel::Clear); break; default: break; } - - return QModelIndex(); -} - -void DolphinColumnView::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags) -{ - Q_UNUSED(rect); - Q_UNUSED(flags); - //activeColumn()->setSelection(rect, flags); } -QRegion DolphinColumnView::visualRegionForSelection(const QItemSelection& selection) const +void DolphinColumnView::contextMenuEvent(QContextMenuEvent* event) { - Q_UNUSED(selection); - return QRegion(); //activeColumn()->visualRegionForSelection(selection); -} - -int DolphinColumnView::horizontalOffset() const -{ - return -m_contentX; -} - -int DolphinColumnView::verticalOffset() const -{ - return 0; -} - -void DolphinColumnView::mousePressEvent(QMouseEvent* event) -{ - m_controller->triggerActivation(); - QAbstractItemView::mousePressEvent(event); -} + 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); -void DolphinColumnView::resizeEvent(QResizeEvent* event) -{ - QAbstractItemView::resizeEvent(event); - layoutColumns(); - updateScrollBar(); + QListView::contextMenuEvent(event); + m_container->m_controller->triggerContextMenuRequest(event->pos()); } -void DolphinColumnView::zoomIn() +void DolphinColumnView::wheelEvent(QWheelEvent* event) { - if (isZoomInPossible()) { - ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); - // TODO: get rid of K3Icon sizes - switch (settings->iconSize()) { - case K3Icon::SizeSmall: settings->setIconSize(K3Icon::SizeMedium); break; - case K3Icon::SizeMedium: settings->setIconSize(K3Icon::SizeLarge); break; - default: Q_ASSERT(false); break; - } - updateDecorationSize(); - } + const int step = m_decorationSize.height(); + verticalScrollBar()->setSingleStep(step); + QListView::wheelEvent(event); } -void DolphinColumnView::zoomOut() +void DolphinColumnView::leaveEvent(QEvent* event) { - if (isZoomOutPossible()) { - ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); - // TODO: get rid of K3Icon sizes - switch (settings->iconSize()) { - case K3Icon::SizeLarge: settings->setIconSize(K3Icon::SizeMedium); break; - case K3Icon::SizeMedium: settings->setIconSize(K3Icon::SizeSmall); break; - default: Q_ASSERT(false); break; - } - updateDecorationSize(); - } + 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::moveContentHorizontally(int x) +void DolphinColumnView::currentChanged(const QModelIndex& current, const QModelIndex& previous) { - m_contentX = -x; - layoutColumns(); + QListView::currentChanged(current, previous); + m_extensionsFactory->handleCurrentIndexChange(current, previous); } -void DolphinColumnView::updateDecorationSize() +void DolphinColumnView::setZoomLevel(int level) { + const int size = ZoomLevelInfo::iconSizeForZoomLevel(level); ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); - const int iconSize = settings->iconSize(); - foreach (QObject* object, viewport()->children()) { - if (object->inherits("QListView")) { - ColumnWidget* widget = static_cast(object); - widget->setDecorationSize(QSize(iconSize, iconSize)); - } + const bool showPreview = m_container->m_controller->dolphinView()->showPreview(); + if (showPreview) { + settings->setPreviewSize(size); + } else { + settings->setIconSize(size); } - m_controller->setZoomInPossible(isZoomInPossible()); - m_controller->setZoomOutPossible(isZoomOutPossible()); - - doItemsLayout(); -} - -void DolphinColumnView::expandToActiveUrl() -{ - const int lastIndex = m_columns.count() - 1; - Q_ASSERT(lastIndex >= 0); - const KUrl& activeUrl = m_columns[lastIndex]->url(); - const KUrl rootUrl = m_dolphinModel->dirLister()->url(); - const bool expand = m_dirListerCompleted - && rootUrl.isParentOf(activeUrl) - && !rootUrl.equals(activeUrl, KUrl::CompareWithoutTrailingSlash); - if (expand) { - m_dolphinModel->expandToUrl(activeUrl); - } - updateColumns(); + updateDecorationSize(showPreview); } -void DolphinColumnView::triggerUpdateColumns(const QModelIndex& index) +void DolphinColumnView::slotEntered(const QModelIndex& index) { - Q_UNUSED(index); - // the updating of the columns may not be done in the context of this slot - QMetaObject::invokeMethod(this, "updateColumns", Qt::QueuedConnection); + m_container->m_controller->setItemView(this); + m_container->m_controller->emitItemEntered(index); } -void DolphinColumnView::updateColumns() +void DolphinColumnView::requestActivation() { - KDirLister* dirLister = m_dolphinModel->dirLister(); - foreach (ColumnWidget* column, m_columns) { - dirLister->updateDirectory(column->url()); - } - - const int end = m_columns.count() - 2; // next to last column - for (int i = 0; i <= end; ++i) { - ColumnWidget* nextColumn = m_columns[i + 1]; - const QModelIndex rootIndex = nextColumn->rootIndex(); - if (rootIndex.isValid()) { - nextColumn->show(); - } else { - const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_columns[i]->childUrl()); - const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); - if (proxyIndex.isValid()) { - nextColumn->setRootIndex(proxyIndex); - nextColumn->show(); - if (nextColumn->isActive() && m_restoreActiveColumnFocus) { - nextColumn->setFocus(); - m_restoreActiveColumnFocus = false; - } - } - } + 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(); } - assureVisibleActiveColumn(); } -void DolphinColumnView::slotDirListerStarted(const KUrl& url) +void DolphinColumnView::updateFont() { - Q_UNUSED(url); - m_dirListerCompleted = false; -} + const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); + Q_ASSERT(settings != 0); -void DolphinColumnView::slotDirListerCompleted() -{ - m_dirListerCompleted = true; - QMetaObject::invokeMethod(this, "expandToActiveUrl", Qt::QueuedConnection); + if (settings->useSystemFont()) { + m_font = KGlobalSettings::generalFont(); + } } -bool DolphinColumnView::isZoomInPossible() const +void DolphinColumnView::slotShowPreviewChanged() { - ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); - return settings->iconSize() < K3Icon::SizeLarge; + const DolphinView* view = m_container->m_controller->dolphinView(); + updateDecorationSize(view->showPreview()); } -bool DolphinColumnView::isZoomOutPossible() const +void DolphinColumnView::activate() { - ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); - return settings->iconSize() > K3Icon::SizeSmall; -} + setFocus(Qt::OtherFocusReason); -void DolphinColumnView::setActiveColumnIndex(int index) -{ - if (m_index == index) { - return; + 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&))); } - const bool hasActiveColumn = (m_index >= 0); - if (hasActiveColumn) { - m_columns[m_index]->setActive(false); + if (selectionModel() && selectionModel()->currentIndex().isValid()) { + selectionModel()->setCurrentIndex(selectionModel()->currentIndex(), QItemSelectionModel::SelectCurrent); } - m_index = index; - m_columns[m_index]->setActive(true); - - m_controller->setUrl(m_columns[m_index]->url()); -} - -void DolphinColumnView::layoutColumns() -{ - int x = m_contentX; - ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); - const int columnWidth = settings->columnWidth(); - foreach (ColumnWidget* column, m_columns) { - column->setGeometry(QRect(x, 0, columnWidth, viewport()->height())); - x += columnWidth; - } + updateBackground(); } -void DolphinColumnView::updateScrollBar() +void DolphinColumnView::deactivate() { - int contentWidth = 0; - foreach (ColumnWidget* column, m_columns) { - contentWidth += column->width(); + 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&))); } - horizontalScrollBar()->setPageStep(contentWidth); - horizontalScrollBar()->setRange(0, contentWidth - viewport()->width()); + const QModelIndex current = selectionModel()->currentIndex(); + selectionModel()->clear(); + selectionModel()->setCurrentIndex(current, QItemSelectionModel::NoUpdate); + updateBackground(); } -void DolphinColumnView::assureVisibleActiveColumn() +void DolphinColumnView::updateDecorationSize(bool showPreview) { - const int viewportWidth = viewport()->width(); - const int x = activeColumn()->x(); - const int width = activeColumn()->width(); - if (x + width > viewportWidth) { - int newContentX = m_contentX - x - width + viewportWidth; - if (newContentX > 0) { - newContentX = 0; - } - m_animation->setFrameRange(-m_contentX, -newContentX); - m_animation->start(); - } else if (x < 0) { - const int newContentX = m_contentX - x; - m_animation->setFrameRange(-m_contentX, -newContentX); - m_animation->start(); - } -} + ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); + const int iconSize = showPreview ? settings->previewSize() : settings->iconSize(); + const QSize size(iconSize, iconSize); + setIconSize(size); -void DolphinColumnView::requestActivation(ColumnWidget* column) -{ - if (column->isActive()) { - assureVisibleActiveColumn(); - } else { - int index = 0; - foreach (ColumnWidget* currColumn, m_columns) { - if (currColumn == column) { - setActiveColumnIndex(index); - assureVisibleActiveColumn(); - return; - } - ++index; - } - } + m_decorationSize = size; + + doItemsLayout(); } #include "dolphincolumnview.moc"