┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Penz <[email protected]>2007-09-14 20:50:08 +0000
committerPeter Penz <[email protected]>2007-09-14 20:50:08 +0000
commit26b2ce327f715c805f6cf524d041b30866e41538 (patch)
treed23fdcd87e5393a44ed50b7652144b1ba99d7400 /src
parent0ba0441fc861ae6c30cc26d6644f26e5afc1cd3c (diff)
refactoring of column view, which fixes:
* selection issues * unwanted loading of sub directories * wrong horizontal scroll position svn path=/trunk/KDE/kdebase/apps/; revision=712590
Diffstat (limited to 'src')
-rw-r--r--src/dolphincolumnview.cpp545
-rw-r--r--src/dolphincolumnview.h77
-rw-r--r--src/dolphinview.cpp27
3 files changed, 310 insertions, 339 deletions
diff --git a/src/dolphincolumnview.cpp b/src/dolphincolumnview.cpp
index 3f2cddf60..931cb9eab 100644
--- a/src/dolphincolumnview.cpp
+++ b/src/dolphincolumnview.cpp
@@ -32,46 +32,8 @@
#include <QAbstractProxyModel>
#include <QApplication>
#include <QPoint>
-
-/*
- * General implementation notes
- * ----------------------------
- *
- * In Qt4.3 the QColumnView widget has a default behavior regarding the
- * active column and the selection handling, which leads to some usability
- * problems within Dolphin:
- *
- * - No matter which mouse button has been clicked: If the mouse is above
- * a folder, the folder content will be loaded in the next column. The problem
- * is that this column also will marked as 'active column' within QColumnView,
- * hence it is not possible to select more than one folder within a column.
- *
- * - The currently opened folder is not always marked in the left column when
- * doing drag & drop and selections inside other columns.
- *
- * - The currently active column is visually not recognizable.
- *
- * - It is not possible for derived classes to remove inactive columns.
- *
- * DolphinView tries to bypass those points, but this required some workarounds:
- *
- * - QColumnView internally maps the selection model from the ColumnView to the
- * active column. As the active column from the Dolphin perspective is different
- * as the active column from QColumnView, the selection model is adjusted on
- * each interaction by the methods QColumnWidget::obtainSelectionModel(),
- * QColumnWidget::releaseSelectionModel() and QColumnView::requestSelectionModel().
- * QColumnView offers no hook to adjust this behavior, so those methods have to
- * be invoked throughout the code...
- *
- * - Some copy/paste code from QColumnView is part of DolphinColumnView::createColumn(), but Qt 4.4
- * will offer a solution for this.
- *
- * - The mousePressEvent() has been customized to prevent that folders are loaded on each
- * mouse click.
- *
- * We'll try to give some input for Trolltech if the Dolphin solution is stable enough, so hopefully
- * some workarounds can be removed when switching to Qt 4.4 or later.
- */
+#include <QScrollBar>
+#include <QTimeLine>
/**
* Represents one column inside the DolphinColumnView and has been
@@ -96,19 +58,18 @@ public:
void setActive(bool active);
inline bool isActive() const;
- inline const KUrl& url() const;
-
/**
- * Obtains the selection model from the column view. This assures that
- * selections of the column view will always applied to the active column.
+ * 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 obtainSelectionModel();
+ inline void setChildUrl(const KUrl& url);
+ inline const KUrl& childUrl() const;
/**
- * Releases the selection model from the column view and replaces it by
- * a custom selection model.
+ * Returns the directory URL that is shown inside the column widget.
*/
- void releaseSelectionModel();
+ inline const KUrl& url() const;
protected:
virtual QStyleOptionViewItem viewOptions() const;
@@ -116,15 +77,10 @@ protected:
virtual void dragLeaveEvent(QDragLeaveEvent* event);
virtual void dragMoveEvent(QDragMoveEvent* event);
virtual void dropEvent(QDropEvent* event);
- virtual void mousePressEvent(QMouseEvent* event);
- virtual void mouseMoveEvent(QMouseEvent* event);
- virtual void mouseReleaseEvent(QMouseEvent* event);
virtual void paintEvent(QPaintEvent* event);
+ virtual void mousePressEvent(QMouseEvent* event);
virtual void contextMenuEvent(QContextMenuEvent* event);
-protected slots:
- virtual void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
-
private:
/** Used by ColumnWidget::setActive(). */
void activate();
@@ -134,9 +90,8 @@ private:
private:
bool m_active;
- bool m_swallowMouseMoveEvents;
DolphinColumnView* m_view;
- KUrl m_url;
+ KUrl m_url; // URL of the directory that is shown
KUrl m_childUrl; // URL of the next column that is shown
QStyleOptionViewItem m_viewOptions;
@@ -147,9 +102,8 @@ private:
ColumnWidget::ColumnWidget(QWidget* parent,
DolphinColumnView* columnView,
const KUrl& url) :
- QListView(parent),
+ QListView(columnView),
m_active(true),
- m_swallowMouseMoveEvents(false),
m_view(columnView),
m_url(url),
m_childUrl(),
@@ -158,6 +112,9 @@ ColumnWidget::ColumnWidget(QWidget* parent,
{
setMouseTracking(true);
viewport()->setAttribute(Qt::WA_Hover);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ setSelectionMode(QAbstractItemView::ExtendedSelection);
// apply the column mode settings to the widget
const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
@@ -173,6 +130,9 @@ ColumnWidget::ColumnWidget(QWidget* parent,
const int iconSize = settings->iconSize();
m_viewOptions.decorationSize = QSize(iconSize, iconSize);
+ KFileItemDelegate* delegate = new KFileItemDelegate(this);
+ setItemDelegate(delegate);
+
activate();
}
@@ -188,12 +148,6 @@ void ColumnWidget::setDecorationSize(const QSize& size)
void ColumnWidget::setActive(bool active)
{
- if (active) {
- obtainSelectionModel();
- } else {
- releaseSelectionModel();
- }
-
if (m_active == active) {
return;
}
@@ -212,26 +166,19 @@ inline bool ColumnWidget::isActive() const
return m_active;
}
-const KUrl& ColumnWidget::url() const
+inline void ColumnWidget::setChildUrl(const KUrl& url)
{
- return m_url;
+ m_childUrl = url;
}
-void ColumnWidget::obtainSelectionModel()
+inline const KUrl& ColumnWidget::childUrl() const
{
- if (selectionModel() != m_view->selectionModel()) {
- selectionModel()->deleteLater();
- setSelectionModel(m_view->selectionModel());
- clearSelection();
- }
+ return m_childUrl;
}
-void ColumnWidget::releaseSelectionModel()
+const KUrl& ColumnWidget::url() const
{
- if (selectionModel() == m_view->selectionModel()) {
- QItemSelectionModel* replacementModel = new QItemSelectionModel(model());
- setSelectionModel(replacementModel);
- }
+ return m_url;
}
QStyleOptionViewItem ColumnWidget::viewOptions() const
@@ -281,98 +228,6 @@ void ColumnWidget::dropEvent(QDropEvent* event)
m_dragging = false;
}
-void ColumnWidget::mousePressEvent(QMouseEvent* event)
-{
- // On each mouse press event QColumnView triggers the loading of the
- // current folder in the next column. This is not wanted for Dolphin when
- // opening a context menu or when the CTRL modifier is pressed. Beside usability
- // aspects the loading of the folder also implies losing the current selection,
- // which makes it impossible to select folders from the current column. To bypass
- // this behavior QListView::mousePressEvent() is not invoked in those cases, which
- // is not a nice solution. Maybe another solution can be found in future versions
- // of QColumnView.
-
- m_view->requestSelectionModel(this);
-
- bool swallowMousePressEvent = false;
- const QModelIndex index = indexAt(event->pos());
- if (index.isValid()) {
- // a click on an item has been done
- const QAbstractProxyModel* proxyModel = static_cast<const QAbstractProxyModel*>(m_view->model());
- const KDirModel* dirModel = static_cast<const KDirModel*>(proxyModel->sourceModel());
- const QModelIndex dirIndex = proxyModel->mapToSource(index);
- KFileItem item = dirModel->itemForIndex(dirIndex);
- if (!item.isNull()) {
- QItemSelectionModel* selModel = selectionModel();
-
- bool activate = true;
- const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
- if (modifier & Qt::ControlModifier) {
- m_view->requestActivation(this);
- if (!selModel->hasSelection()) {
- // Assure to set the current index, so that a selection by the SHIFT key
- // will work. TODO: If the index specifies a folder, the loading of the folder will
- // be triggered by QColumnView although this is not wanted by Dolphin.
- selModel->setCurrentIndex(index, QItemSelectionModel::Select);
- }
- selModel->select(index, QItemSelectionModel::Toggle);
- swallowMousePressEvent = true;
- } else if (item.isDir()) {
- m_childUrl = item.url();
- viewport()->update();
-
- // Only request the activation if not the left button is pressed.
- // The left button on a directory opens a new column, hence requesting
- // an activation is useless as the new column will request the activation
- // afterwards.
- if (event->button() == Qt::LeftButton) {
- activate = false;
- }
- }
-
- if (activate) {
- m_view->requestActivation(this);
- }
-
- // TODO: is the assumption OK that Qt::RightButton always represents the context menu button?
- if (event->button() == Qt::RightButton) {
- swallowMousePressEvent = true;
- if (!selModel->isSelected(index)) {
- clearSelection();
- }
- selModel->select(index, QItemSelectionModel::Select);
- }
- }
- } else {
- // a click on the viewport has been done
- m_view->requestActivation(this);
-
- // Swallow mouse move events if a click is done on the viewport. Otherwise the QColumnView
- // triggers an unwanted loading of directories on hovering folder items.
- m_swallowMouseMoveEvents = true;
- clearSelection();
- }
-
- if (!swallowMousePressEvent) {
- QListView::mousePressEvent(event);
- }
-}
-
-void ColumnWidget::mouseMoveEvent(QMouseEvent* event)
-{
- // see description in ColumnView::mousePressEvent()
- if (!m_swallowMouseMoveEvents) {
- QListView::mouseMoveEvent(event);
- }
-}
-
-void ColumnWidget::mouseReleaseEvent(QMouseEvent* event)
-{
- QListView::mouseReleaseEvent(event);
- m_swallowMouseMoveEvents = false;
-}
-
-
void ColumnWidget::paintEvent(QPaintEvent* event)
{
if (!m_childUrl.isEmpty()) {
@@ -405,6 +260,15 @@ void ColumnWidget::paintEvent(QPaintEvent* event)
}
}
+void ColumnWidget::mousePressEvent(QMouseEvent* event)
+{
+ if (!m_active) {
+ m_view->requestActivation(this);
+ }
+
+ QListView::mousePressEvent(event);
+}
+
void ColumnWidget::contextMenuEvent(QContextMenuEvent* event)
{
if (!m_active) {
@@ -422,15 +286,6 @@ void ColumnWidget::contextMenuEvent(QContextMenuEvent* event)
}
}
-void ColumnWidget::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
-{
- // inactive views should not have any selection
- if (!m_active) {
- clearSelection();
- }
- QListView::selectionChanged(selected, deselected);
-}
-
void ColumnWidget::activate()
{
const QColor bgColor = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
@@ -451,14 +306,20 @@ void ColumnWidget::deactivate()
palette.setColor(viewport()->backgroundRole(), bgColor);
viewport()->setPalette(palette);
+ selectionModel()->clear();
+
update();
}
// ---
DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* controller) :
- QColumnView(parent),
- m_controller(controller)
+ QAbstractItemView(parent),
+ m_controller(controller),
+ m_index(-1),
+ m_contentX(0),
+ m_columns(),
+ m_animation(0)
{
Q_ASSERT(controller != 0);
@@ -467,16 +328,6 @@ DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* control
setDropIndicatorShown(false);
setSelectionMode(ExtendedSelection);
- // 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&)),
- this, SLOT(triggerItem(const QModelIndex&)));
- } else {
- connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
- this, SLOT(triggerItem(const QModelIndex&)));
- }
connect(this, SIGNAL(entered(const QModelIndex&)),
controller, SLOT(emitItemEntered(const QModelIndex&)));
connect(this, SIGNAL(viewportEntered()),
@@ -486,91 +337,82 @@ DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* control
connect(controller, SIGNAL(zoomOut()),
this, SLOT(zoomOut()));
connect(controller, SIGNAL(urlChanged(const KUrl&)),
- this, SLOT(updateColumnsState(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)));
}
DolphinColumnView::~DolphinColumnView()
{
}
-void DolphinColumnView::invertSelection()
+QModelIndex DolphinColumnView::indexAt(const QPoint& point) const
{
- selectActiveColumn(QItemSelectionModel::Toggle);
+ return activeColumn()->indexAt(point);
}
-void DolphinColumnView::selectAll()
+void DolphinColumnView::scrollTo(const QModelIndex& index, ScrollHint hint)
{
- selectActiveColumn(QItemSelectionModel::Select);
+ activeColumn()->scrollTo(index, hint);
}
-QAbstractItemView* DolphinColumnView::createColumn(const QModelIndex& index)
+QRect DolphinColumnView::visualRect(const QModelIndex& index) const
{
- // let the column widget be aware about its URL...
- KUrl columnUrl;
- if (viewport()->children().count() == 0) {
- // For the first column widget the directory lister has not been started
- // yet, hence use the URL from the controller instead.
- columnUrl = m_controller->url();
- } else {
- const QAbstractProxyModel* proxyModel = static_cast<const QAbstractProxyModel*>(model());
- const KDirModel* dirModel = static_cast<const KDirModel*>(proxyModel->sourceModel());
-
- const QModelIndex dirModelIndex = proxyModel->mapToSource(index);
- KFileItem fileItem = dirModel->itemForIndex(dirModelIndex);
- if (!fileItem.isNull()) {
- columnUrl = fileItem.url();
- }
- }
-
- ColumnWidget* view = new ColumnWidget(viewport(), this, columnUrl);
+ return activeColumn()->visualRect(index);
+}
- // The following code has been copied 1:1 from QColumnView::createColumn().
- // Copyright (C) 1992-2007 Trolltech ASA. In Qt 4.4 the new method
- // QColumnView::initializeColumn() will be available for this.
+void DolphinColumnView::setModel(QAbstractItemModel* model)
+{
+ // TODO: remove all columns
- view->setFrameShape(QFrame::NoFrame);
- view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
- view->setMinimumWidth(100);
- view->setAttribute(Qt::WA_MacShowFocusRect, false);
+ activeColumn()->setModel(model);
+ QAbstractItemView::setModel(model);
+}
- // copy the 'view' behavior
- view->setDragDropMode(dragDropMode());
- view->setDragDropOverwriteMode(dragDropOverwriteMode());
- view->setDropIndicatorShown(showDropIndicator());
- view->setAlternatingRowColors(alternatingRowColors());
- view->setAutoScroll(hasAutoScroll());
- view->setEditTriggers(editTriggers());
- view->setHorizontalScrollMode(horizontalScrollMode());
- view->setIconSize(iconSize());
- view->setSelectionBehavior(selectionBehavior());
- view->setSelectionMode(selectionMode());
- view->setTabKeyNavigation(tabKeyNavigation());
- view->setTextElideMode(textElideMode());
- view->setVerticalScrollMode(verticalScrollMode());
+bool DolphinColumnView::isIndexHidden(const QModelIndex& index) const
+{
+ return false;//activeColumn()->isIndexHidden(index);
+}
- view->setModel(model());
+QModelIndex DolphinColumnView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
+{
+ return QModelIndex(); //activeColumn()->moveCursor(cursorAction, modifiers);
+}
- // set the delegate to be the columnview delegate
- QAbstractItemDelegate* delegate = view->itemDelegate();
- view->setItemDelegate(itemDelegate());
- delete delegate;
+void DolphinColumnView::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags)
+{
+ //activeColumn()->setSelection(rect, flags);
+}
- view->setRootIndex(index);
+QRegion DolphinColumnView::visualRegionForSelection(const QItemSelection& selection) const
+{
+ return QRegion(); //activeColumn()->visualRegionForSelection(selection);
+}
- if (model()->canFetchMore(index)) {
- model()->fetchMore(index);
- }
+int DolphinColumnView::horizontalOffset() const
+{
+ return -m_contentX;
+}
- return view;
+int DolphinColumnView::verticalOffset() const
+{
+ return 0; // activeColumn()->verticalOffset();
}
void DolphinColumnView::mousePressEvent(QMouseEvent* event)
{
m_controller->triggerActivation();
- QColumnView::mousePressEvent(event);
+ QAbstractItemView::mousePressEvent(event);
}
void DolphinColumnView::dragEnterEvent(QDragEnterEvent* event)
@@ -589,7 +431,14 @@ void DolphinColumnView::dropEvent(QDropEvent* event)
event->source());
event->acceptProposedAction();
}
- QColumnView::dropEvent(event);
+ QAbstractItemView::dropEvent(event);
+}
+
+void DolphinColumnView::resizeEvent(QResizeEvent* event)
+{
+ QAbstractItemView::resizeEvent(event);
+ layoutColumns();
+ updateScrollBar();
}
void DolphinColumnView::zoomIn()
@@ -623,20 +472,79 @@ void DolphinColumnView::zoomOut()
void DolphinColumnView::triggerItem(const QModelIndex& index)
{
m_controller->triggerItem(index);
- updateColumnsState(m_controller->url());
+
+ const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
+ if ((modifiers & Qt::ControlModifier) || (modifiers & Qt::ShiftModifier)) {
+ return;
+ }
+
+ const QAbstractProxyModel* proxyModel = static_cast<const QAbstractProxyModel*>(model());
+ const KDirModel* dirModel = static_cast<const KDirModel*>(proxyModel->sourceModel());
+ const KFileItem item = dirModel->itemForIndex(proxyModel->mapToSource(index));
+ if ((item.url() != activeColumn()->url()) && item.isDir()) {
+ deleteInactiveChildColumns();
+
+ const KUrl& childUrl = m_controller->url();
+ activeColumn()->setChildUrl(childUrl);
+
+ ColumnWidget* column = new ColumnWidget(viewport(), this, childUrl);
+ column->setModel(model());
+ column->setRootIndex(index);
+
+ m_columns.append(column);
+
+ setActiveColumnIndex(m_index + 1);
+
+ // Before invoking layoutColumns() the column must be shown. To prevent
+ // a flickering the initial geometry is set to be invisible.
+ column->setGeometry(QRect(-1, -1, 1, 1));
+ column->show();
+
+ layoutColumns();
+ updateScrollBar();
+ assureVisibleActiveColumn();
+ }
}
-void DolphinColumnView::updateColumnsState(const KUrl& url)
+void DolphinColumnView::moveContentHorizontally(int x)
{
- foreach (QObject* object, viewport()->children()) {
- if (object->inherits("QListView")) {
- ColumnWidget* widget = static_cast<ColumnWidget*>(object);
- widget->setActive(widget->url() == url);
+ m_contentX = -x;
+ layoutColumns();
+}
+
+void DolphinColumnView::showColumn(const KUrl& url)
+{
+ if (!m_columns[0]->url().isParentOf(url)) {
+ // the URL is no child URL of the column view, hence do nothing
+ return;
+ }
+
+ 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 it must
+ // be deleted and a new column must be loaded
+ if (columnIndex > 0) {
+ setActiveColumnIndex(columnIndex - 1);
+ deleteInactiveChildColumns();
+ }
+
+ const QAbstractProxyModel* proxyModel = static_cast<const QAbstractProxyModel*>(model());
+ const KDirModel* dirModel = static_cast<const KDirModel*>(proxyModel->sourceModel());
+ const QModelIndex dirIndex = dirModel->indexForUrl(url);
+ if (dirIndex.isValid()) {
+ triggerItem(proxyModel->mapFromSource(dirIndex));
+ }
+ return;
}
+ ++columnIndex;
}
}
-
void DolphinColumnView::updateDecorationSize()
{
ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
@@ -667,65 +575,106 @@ bool DolphinColumnView::isZoomOutPossible() const
return settings->iconSize() > K3Icon::SizeSmall;
}
-void DolphinColumnView::requestActivation(QWidget* column)
+void DolphinColumnView::setActiveColumnIndex(int index)
{
- foreach (QObject* object, viewport()->children()) {
- if (object->inherits("QListView")) {
- ColumnWidget* widget = static_cast<ColumnWidget*>(object);
- const bool isActive = (widget == column);
- widget->setActive(isActive);
- if (isActive) {
- m_controller->setUrl(widget->url());
- }
+ if (m_index == index) {
+ return;
+ }
+
+ const bool hasActiveColumn = (m_index >= 0);
+ if (hasActiveColumn) {
+ m_columns[m_index]->setActive(false);
+ }
+
+ // 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()) {
+ if (hasActiveColumn) {
+ disconnect(m_columns[m_index], SIGNAL(clicked(const QModelIndex&)),
+ this, SLOT(triggerItem(const QModelIndex&)));
+ }
+ m_index = index;
+ m_columns[m_index]->setActive(true);
+ connect(m_columns[m_index], SIGNAL(clicked(const QModelIndex&)),
+ this, SLOT(triggerItem(const QModelIndex&)));
+ } else {
+ if (hasActiveColumn) {
+ disconnect(m_columns[m_index], SIGNAL(doubleClicked(const QModelIndex&)),
+ this, SLOT(triggerItem(const QModelIndex&)));
}
+ m_index = index;
+ m_columns[m_index]->setActive(true);
+ connect(m_columns[m_index], SIGNAL(doubleClicked(const QModelIndex&)),
+ this, SLOT(triggerItem(const QModelIndex&)));
}
}
-void DolphinColumnView::requestSelectionModel(QAbstractItemView* view)
+void DolphinColumnView::layoutColumns()
{
- foreach (QObject* object, viewport()->children()) {
- if (object->inherits("QListView")) {
- ColumnWidget* widget = static_cast<ColumnWidget*>(object);
- if (widget == view) {
- widget->obtainSelectionModel();
- } else {
- widget->releaseSelectionModel();
- }
- }
+ int x = m_contentX;
+ const int columnWidth = 250;
+ foreach (ColumnWidget* column, m_columns) {
+ column->setGeometry(QRect(x, 0, columnWidth, viewport()->height()));
+ x += columnWidth;
}
}
-void DolphinColumnView::selectActiveColumn(QItemSelectionModel::SelectionFlags flags)
+void DolphinColumnView::updateScrollBar()
{
- // TODO: this approach of selecting the active column is very slow. It should be
- // possible to speedup the implementation by using QItemSelection, but all adempts
- // have failed yet...
+ int contentWidth = 0;
+ foreach (ColumnWidget* column, m_columns) {
+ contentWidth += column->width();
+ }
- // assure that the selection model of the active column is set properly, otherwise
- // no visual update of the selections is done
- const KUrl& activeUrl = m_controller->url();
- foreach (QObject* object, viewport()->children()) {
- if (object->inherits("QListView")) {
- ColumnWidget* widget = static_cast<ColumnWidget*>(object);
- if (widget->url() == activeUrl) {
- widget->obtainSelectionModel();
- } else {
- widget->releaseSelectionModel();
- }
+ horizontalScrollBar()->setPageStep(contentWidth);
+ horizontalScrollBar()->setRange(0, contentWidth - viewport()->width());
+}
+
+void DolphinColumnView::assureVisibleActiveColumn()
+{
+ 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();
}
+}
- QItemSelectionModel* selModel = selectionModel();
-
- const QAbstractProxyModel* proxyModel = static_cast<const QAbstractProxyModel*>(model());
- const KDirModel* dirModel = static_cast<const KDirModel*>(proxyModel->sourceModel());
- KDirLister* dirLister = dirModel->dirLister();
+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;
+ }
+ }
+}
- const KFileItemList list = dirLister->itemsForDir(activeUrl);
- foreach (KFileItem* item, list) {
- const QModelIndex index = dirModel->indexForUrl(item->url());
- selModel->select(proxyModel->mapFromSource(index), flags);
+void DolphinColumnView::deleteInactiveChildColumns()
+{
+ QList<ColumnWidget*>::iterator start = m_columns.begin() + m_index + 1;
+ QList<ColumnWidget*>::iterator end = m_columns.end();
+ for (QList<ColumnWidget*>::iterator it = start; it != end; ++it) {
+ (*it)->deleteLater();
}
+ m_columns.erase(start, end);
}
#include "dolphincolumnview.moc"
diff --git a/src/dolphincolumnview.h b/src/dolphincolumnview.h
index b2471fdb7..eff09c08a 100644
--- a/src/dolphincolumnview.h
+++ b/src/dolphincolumnview.h
@@ -20,12 +20,15 @@
#ifndef DOLPHINCOLUMNVIEW_H
#define DOLPHINCOLUMNVIEW_H
-#include <QColumnView>
+#include <QAbstractItemView>
+#include <QList>
#include <QStyleOption>
+class ColumnWidget;
class DolphinController;
class KDirLister;
class KUrl;
+class QTimeLine;
/**
* @brief Represents the view, where each directory is show as separate column.
@@ -33,7 +36,7 @@ class KUrl;
* @see DolphinIconsView
* @see DolphinDetailsView
*/
-class DolphinColumnView : public QColumnView
+class DolphinColumnView : public QAbstractItemView
{
Q_OBJECT
@@ -41,20 +44,23 @@ public:
explicit DolphinColumnView(QWidget* parent, DolphinController* controller);
virtual ~DolphinColumnView();
- /**
- * Inverts the selection for the current active column.
- */
- void invertSelection();
-
-public slots:
- /** @see QAbstractItemView::selectAll() */
- virtual void selectAll();
+ virtual QModelIndex indexAt(const QPoint& point) const;
+ virtual void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible);
+ virtual QRect visualRect(const QModelIndex& index) const;
+ virtual void setModel(QAbstractItemModel* model);
protected:
- virtual QAbstractItemView* createColumn(const QModelIndex& index);
+ 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 void mousePressEvent(QMouseEvent* event);
virtual void dragEnterEvent(QDragEnterEvent* event);
virtual void dropEvent(QDropEvent* event);
+ virtual void resizeEvent(QResizeEvent* event);
private slots:
void zoomIn();
@@ -62,11 +68,16 @@ private slots:
void triggerItem(const QModelIndex& index);
/**
- * Updates the activation state of all columns, where \a url
- * represents the URL of the active column. All operations
- * are applied only to the column which is marked as active.
+ * Moves the content of the columns view to represent
+ * the scrollbar position \a x.
*/
- void updateColumnsState(const KUrl& url);
+ void moveContentHorizontally(int x);
+
+ /**
+ * 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);
/**
* Updates the size of the decoration dependent on the
@@ -80,30 +91,44 @@ private:
bool isZoomInPossible() const;
bool isZoomOutPossible() const;
+ inline ColumnWidget* activeColumn() const;
+ void setActiveColumnIndex(int index);
+
+ void layoutColumns();
+ void updateScrollBar();
+
/**
- * Requests the activation for the column \a column. The URL
- * navigator will be changed to represent the column. It is
- * assured that the selection model of \a column will be set
- * to the selection model of the Column View.
+ * Assures that the currently active column is fully visible
+ * by adjusting the horizontal position of the content.
*/
- void requestActivation(QWidget* column);
+ void assureVisibleActiveColumn();
/**
- * Requests the selection model from the Column View for \a view.
- * If another column has already obtained the Column View selection
- * model, it will be replaced by a default selection model.
+ * 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 requestSelectionModel(QAbstractItemView* view);
+ void requestActivation(ColumnWidget* column);
/**
- * Helper method for selecting all items of an active column by \a flags.
+ * Deletes all inactive child columns, that are a child of
+ * the currently active column.
*/
- void selectActiveColumn(QItemSelectionModel::SelectionFlags flags);
+ void deleteInactiveChildColumns();
private:
DolphinController* m_controller;
+ int m_index;
+ int m_contentX;
+ QList<ColumnWidget*> m_columns;
+ QTimeLine* m_animation;
friend class ColumnWidget;
};
+ColumnWidget* DolphinColumnView::activeColumn() const
+{
+ return m_columns[m_index];
+}
+
#endif
diff --git a/src/dolphinview.cpp b/src/dolphinview.cpp
index 3e8070cb3..0041ab35d 100644
--- a/src/dolphinview.cpp
+++ b/src/dolphinview.cpp
@@ -262,22 +262,15 @@ void DolphinView::selectAll()
void DolphinView::invertSelection()
{
- if (isColumnViewActive()) {
- // In opposite to QAbstractItemView::selectAll() there is no virtual method
- // for adjusting the invertion of a selection. As the generic approach by using
- // the selection model does not work for the column view, we delegate this task:
- m_columnView->invertSelection();
- } else {
- QItemSelectionModel* selectionModel = itemView()->selectionModel();
- const QAbstractItemModel* itemModel = selectionModel->model();
+ QItemSelectionModel* selectionModel = 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);
- QItemSelection selection(topLeft, bottomRight);
- selectionModel->select(selection, QItemSelectionModel::Toggle);
- }
+ QItemSelection selection(topLeft, bottomRight);
+ selectionModel->select(selection, QItemSelectionModel::Toggle);
}
bool DolphinView::hasSelection() const
@@ -332,7 +325,11 @@ KFileItem DolphinView::fileItem(const QModelIndex& index) const
void DolphinView::setContentsPosition(int x, int y)
{
QAbstractItemView* view = itemView();
- view->horizontalScrollBar()->setValue(x);
+
+ // the ColumnView takes care itself for the horizontal scrolling
+ if (!isColumnViewActive()) {
+ view->horizontalScrollBar()->setValue(x);
+ }
view->verticalScrollBar()->setValue(y);
m_loadingDirectory = false;