/***************************************************************************
- * Copyright (C) 2006 by Peter Penz (peter.penz@gmx.at) *
+ * Copyright (C) 2007 by Peter Penz <peter.penz@gmx.at> *
* *
* 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 *
#include "dolphincolumnview.h"
+#include "dolphinmodel.h"
#include "dolphincontroller.h"
#include "dolphinsettings.h"
#include <kcolorutils.h>
#include <kcolorscheme.h>
-#include <kdirmodel.h>
#include <kdirlister.h>
-#include <kfileitem.h>
#include <QAbstractProxyModel>
+#include <QApplication>
#include <QPoint>
+#include <QScrollBar>
+#include <QTimer>
+#include <QTimeLine>
/**
* Represents one column inside the DolphinColumnView and has been
* drawn in a lighter color. All operations are applied to this column.
*/
void setActive(bool active);
+ bool isActive() const;
- inline const KUrl& url() 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;
protected:
virtual QStyleOptionViewItem viewOptions() const;
virtual void dragLeaveEvent(QDragLeaveEvent* event);
virtual void dragMoveEvent(QDragMoveEvent* event);
virtual void dropEvent(QDropEvent* event);
- virtual void mousePressEvent(QMouseEvent* 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(). */
private:
bool m_active;
- KUrl m_url;
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
const KUrl& url) :
QListView(parent),
m_active(true),
- m_url(url),
m_view(columnView),
+ m_url(url),
+ m_childUrl(),
m_dragging(false),
m_dropRect()
{
- setAcceptDrops(true);
- setDragDropMode(QAbstractItemView::DragDrop);
- setDropIndicatorShown(false);
-
setMouseTracking(true);
viewport()->setAttribute(Qt::WA_Hover);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ setSelectionBehavior(SelectItems);
+ setSelectionMode(QAbstractItemView::ExtendedSelection);
+ setDragDropMode(QAbstractItemView::DragDrop);
+ setDropIndicatorShown(false);
+ setFocusPolicy(Qt::NoFocus);
// apply the column mode settings to the widget
const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
const int iconSize = settings->iconSize();
m_viewOptions.decorationSize = QSize(iconSize, iconSize);
+ m_viewOptions.showDecorationSelected = true;
+
+ KFileItemDelegate* delegate = new KFileItemDelegate(this);
+ setItemDelegate(delegate);
+
activate();
+
+ connect(this, SIGNAL(entered(const QModelIndex&)),
+ m_view->m_controller, SLOT(emitItemEntered(const QModelIndex&)));
+ connect(this, SIGNAL(viewportEntered()),
+ m_view->m_controller, SLOT(emitViewportEntered()));
}
ColumnWidget::~ColumnWidget()
}
}
-const KUrl& ColumnWidget::url() const
+inline bool ColumnWidget::isActive() const
+{
+ return m_active;
+}
+
+inline void ColumnWidget::setChildUrl(const KUrl& url)
+{
+ m_childUrl = url;
+}
+
+inline const KUrl& ColumnWidget::childUrl() const
+{
+ return m_childUrl;
+}
+
+inline void ColumnWidget::setUrl(const KUrl& url)
+{
+ m_url = url;
+}
+
+inline const KUrl& ColumnWidget::url() const
{
return m_url;
}
-QStyleOptionViewItem ColumnWidget::viewOptions() const
+inline QStyleOptionViewItem ColumnWidget::viewOptions() const
{
return m_viewOptions;
}
{
QListView::dragMoveEvent(event);
- // TODO: remove this code when the issue #160611 is solved in Qt 4.4
+ // 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);
if (!urls.isEmpty()) {
event->acceptProposedAction();
m_view->m_controller->indicateDroppedUrls(urls,
- indexAt(event->pos()),
- event->source());
+ url(),
+ indexAt(event->pos()),
+ event->source());
}
QListView::dropEvent(event);
m_dragging = false;
}
-void ColumnWidget::mousePressEvent(QMouseEvent* event)
+void ColumnWidget::paintEvent(QPaintEvent* event)
{
- if (m_active || indexAt(event->pos()).isValid()) {
- // Only accept the mouse press event in inactive views,
- // if a click is done on an item. This assures that
- // the current selection, which usually shows the
- // the directory for next column, won't get deleted.
- QListView::mousePressEvent(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);
+ 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();
+ }
}
-}
-void ColumnWidget::paintEvent(QPaintEvent* event)
-{
QListView::paintEvent(event);
// TODO: remove this code when the issue #160611 is solved in Qt 4.4
}
}
+void ColumnWidget::mousePressEvent(QMouseEvent* event)
+{
+ if (!m_active) {
+ m_view->requestActivation(this);
+ }
+
+ QListView::mousePressEvent(event);
+}
+
+void ColumnWidget::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_view->viewport()->children().first() == this) {
- // This column widget represents the root column. DolphinColumnView::createColumn()
- // cannot retrieve the correct URL at this stage, as the directory lister will be
- // started after the model has been assigned. This will be fixed here, where it is
- // assured that the directory lister has been started already.
- const QAbstractProxyModel* proxyModel = static_cast<const QAbstractProxyModel*>(model());
- const KDirModel* dirModel = static_cast<const KDirModel*>(proxyModel->sourceModel());
- const KDirLister* dirLister = dirModel->dirLister();
- m_url = dirLister->url();
+ if (!m_active) {
+ m_view->requestActivation(this);
}
QListView::contextMenuEvent(event);
- const QPoint pos = m_view->viewport()->mapFromGlobal(event->globalPos());
- m_view->m_controller->triggerContextMenuRequest(pos, m_url);
+
+ 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()
{
- const QColor bgColor = KColorScheme(KColorScheme::View).background();
+ 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);
- setSelectionMode(MultiSelection);
+ 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()
{
- QColor bgColor = KColorScheme(KColorScheme::View).background();
- const QColor fgColor = KColorScheme(KColorScheme::View).foreground();
- bgColor = KColorUtils::mix(bgColor, fgColor, 0.04);
+ // 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&)));
+ }
- QPalette palette = viewport()->palette();
- palette.setColor(viewport()->backgroundRole(), bgColor);
+ const QPalette palette = m_view->viewport()->palette();
viewport()->setPalette(palette);
- setSelectionMode(SingleSelection);
+ selectionModel()->clear();
+ update();
}
// ---
DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* controller) :
- QColumnView(parent),
- m_controller(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);
- setSelectionBehavior(SelectItems);
setDragDropMode(QAbstractItemView::DragDrop);
setDropIndicatorShown(false);
+ setSelectionMode(ExtendedSelection);
- 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(activated(const QModelIndex&)),
- this, SLOT(triggerItem(const QModelIndex&)));
connect(this, SIGNAL(entered(const QModelIndex&)),
controller, SLOT(emitItemEntered(const QModelIndex&)));
connect(this, SIGNAL(viewportEntered()),
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)));
+
+ m_animation = new QTimeLine(500, this);
+ connect(m_animation, SIGNAL(frameChanged(int)), horizontalScrollBar(), SLOT(setValue(int)));
+
+ ColumnWidget* column = new ColumnWidget(viewport(), this, m_controller->url());
+ m_columns.append(column);
+ setActiveColumnIndex(0);
updateDecorationSize();
+
+ // 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()
{
}
-QAbstractItemView* DolphinColumnView::createColumn(const QModelIndex& index)
+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)
{
- // To be able to visually indicate whether a column is active (which means
- // that it represents the content of the URL navigator), the column
- // must remember its URL.
- const QAbstractProxyModel* proxyModel = static_cast<const QAbstractProxyModel*>(model());
- const KDirModel* dirModel = static_cast<const KDirModel*>(proxyModel->sourceModel());
+ activeColumn()->scrollTo(index, hint);
+}
- const QModelIndex dirModelIndex = proxyModel->mapToSource(index);
- KFileItem* fileItem = dirModel->itemForIndex(dirModelIndex);
+QRect DolphinColumnView::visualRect(const QModelIndex& index) const
+{
+ return activeColumn()->visualRect(index);
+}
- KUrl columnUrl;
- if (fileItem != 0) {
- columnUrl = fileItem->url();
+void DolphinColumnView::setModel(QAbstractItemModel* model)
+{
+ if (m_dolphinModel != 0) {
+ m_dolphinModel->disconnect(this);
}
- ColumnWidget* view = new ColumnWidget(viewport(),
- this,
- columnUrl);
+ m_proxyModel = static_cast<QAbstractProxyModel*>(model);
+ m_dolphinModel = static_cast<DolphinModel*>(m_proxyModel->sourceModel());
+ connect(m_dolphinModel, SIGNAL(expand(const QModelIndex&)),
+ this, SLOT(triggerReloadColumns(const QModelIndex&)));
- // 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.
+ KDirLister* dirLister = m_dolphinModel->dirLister();
+ connect(dirLister, SIGNAL(started(const KUrl&)),
+ this, SLOT(slotDirListerStarted(const KUrl&)));
+ connect(dirLister, SIGNAL(completed()),
+ this, SLOT(slotDirListerCompleted()));
- 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());
+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 (const KFileItem item, list) {
+ const QModelIndex index = m_dolphinModel->indexForUrl(item.url());
+ selModel->select(m_proxyModel->mapFromSource(index), QItemSelectionModel::Toggle);
+ }
+}
- view->setModel(model());
+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<ColumnWidget*>::iterator start = m_columns.begin() + 1;
+ QList<ColumnWidget*>::iterator end = m_columns.end();
+ for (QList<ColumnWidget*>::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();
+ }
- // set the delegate to be the columnview delegate
- QAbstractItemDelegate* delegate = view->itemDelegate();
- view->setItemDelegate(itemDelegate());
- delete delegate;
+ // 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();
+}
- view->setRootIndex(index);
+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<ColumnWidget*>::iterator start = m_columns.begin() + 1;
+ QList<ColumnWidget*>::iterator end = m_columns.end();
+ for (QList<ColumnWidget*>::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;
+ }
- if (model()->canFetchMore(index)) {
- model()->fetchMore(index);
+ 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);
}
- return view;
+ 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<ColumnWidget*>::iterator start = m_columns.begin() + columnIndex;
+ QList<ColumnWidget*>::iterator end = m_columns.end();
+ for (QList<ColumnWidget*>::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->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);
+ assureVisibleActiveColumn();
}
-void DolphinColumnView::mousePressEvent(QMouseEvent* event)
+void DolphinColumnView::selectAll()
{
- m_controller->triggerActivation();
- QColumnView::mousePressEvent(event);
+ activeColumn()->selectAll();
}
-void DolphinColumnView::dragEnterEvent(QDragEnterEvent* event)
+bool DolphinColumnView::isIndexHidden(const QModelIndex& index) const
{
- if (event->mimeData()->hasUrls()) {
- event->acceptProposedAction();
- }
+ Q_UNUSED(index);
+ return false;//activeColumn()->isIndexHidden(index);
}
-void DolphinColumnView::dropEvent(QDropEvent* event)
+QModelIndex DolphinColumnView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
{
- const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
- if (!urls.isEmpty()) {
- m_controller->indicateDroppedUrls(urls,
- indexAt(event->pos()),
- event->source());
- event->acceptProposedAction();
+ // 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);
+ }
+ break;
+
+ case MoveRight:
+ if (m_index < m_columns.count() - 1) {
+ setActiveColumnIndex(m_index + 1);
+ }
+ break;
+
+ default:
+ break;
}
- QColumnView::dropEvent(event);
+
+ 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
+{
+ 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);
+}
+
+void DolphinColumnView::resizeEvent(QResizeEvent* event)
+{
+ QAbstractItemView::resizeEvent(event);
+ layoutColumns();
+ updateScrollBar();
}
void DolphinColumnView::zoomIn()
{
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;
+ case KIconLoader::SizeSmall: settings->setIconSize(KIconLoader::SizeMedium); break;
+ case KIconLoader::SizeMedium: settings->setIconSize(KIconLoader::SizeLarge); break;
default: Q_ASSERT(false); break;
}
updateDecorationSize();
{
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;
+ case KIconLoader::SizeLarge: settings->setIconSize(KIconLoader::SizeMedium); break;
+ case KIconLoader::SizeMedium: settings->setIconSize(KIconLoader::SizeSmall); break;
default: Q_ASSERT(false); break;
}
updateDecorationSize();
}
}
-void DolphinColumnView::triggerItem(const QModelIndex& index)
+void DolphinColumnView::moveContentHorizontally(int x)
{
- m_controller->triggerItem(index);
+ m_contentX = isRightToLeft() ? +x : -x;
+ layoutColumns();
+}
+
+void DolphinColumnView::updateDecorationSize()
+{
+ ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
+ const int iconSize = settings->iconSize();
- // Update the activation state of all columns. Only the column
- // which represents the URL of the URL navigator is marked as active.
- const KUrl& navigatorUrl = m_controller->url();
foreach (QObject* object, viewport()->children()) {
if (object->inherits("QListView")) {
ColumnWidget* widget = static_cast<ColumnWidget*>(object);
- widget->setActive(navigatorUrl == widget->url());
+ widget->setDecorationSize(QSize(iconSize, iconSize));
+ }
+ }
+
+ 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();
+}
+
+void DolphinColumnView::triggerUpdateColumns(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);
+}
+
+void DolphinColumnView::updateColumns()
+{
+ 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;
+ }
+ }
}
}
}
+void DolphinColumnView::slotDirListerStarted(const KUrl& url)
+{
+ Q_UNUSED(url);
+ m_dirListerCompleted = false;
+}
+
+void DolphinColumnView::slotDirListerCompleted()
+{
+ m_dirListerCompleted = true;
+ QMetaObject::invokeMethod(this, "expandToActiveUrl", Qt::QueuedConnection);
+}
+
bool DolphinColumnView::isZoomInPossible() const
{
ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
- return settings->iconSize() < K3Icon::SizeLarge;
+ return settings->iconSize() < KIconLoader::SizeLarge;
}
bool DolphinColumnView::isZoomOutPossible() const
{
ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
- return settings->iconSize() > K3Icon::SizeSmall;
+ return settings->iconSize() > KIconLoader::SizeSmall;
}
-void DolphinColumnView::updateDecorationSize()
+void DolphinColumnView::setActiveColumnIndex(int index)
{
- ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
- const int iconSize = settings->iconSize();
+ if (m_index == index) {
+ return;
+ }
- foreach (QObject* object, viewport()->children()) {
- if (object->inherits("QListView")) {
- ColumnWidget* widget = static_cast<ColumnWidget*>(object);
- widget->setDecorationSize(QSize(iconSize, iconSize));
+ const bool hasActiveColumn = (m_index >= 0);
+ if (hasActiveColumn) {
+ m_columns[m_index]->setActive(false);
+ }
+
+ m_index = index;
+ m_columns[m_index]->setActive(true);
+
+ m_controller->setUrl(m_columns[m_index]->url());
+
+ assureVisibleActiveColumn();
+}
+
+void DolphinColumnView::layoutColumns()
+{
+ ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
+ const int columnWidth = settings->columnWidth();
+ if (isRightToLeft()) {
+ int x = viewport()->width() - columnWidth + m_contentX;
+ foreach (ColumnWidget* column, m_columns) {
+ column->setGeometry(QRect(x, 0, columnWidth, viewport()->height()));
+ x -= columnWidth;
+ }
+ } else {
+ int x = m_contentX;
+ foreach (ColumnWidget* column, m_columns) {
+ column->setGeometry(QRect(x, 0, columnWidth, viewport()->height()));
+ x += columnWidth;
}
}
+}
- m_controller->setZoomInPossible(isZoomInPossible());
- m_controller->setZoomOutPossible(isZoomOutPossible());
+void DolphinColumnView::updateScrollBar()
+{
+ int contentWidth = 0;
+ foreach (ColumnWidget* column, m_columns) {
+ contentWidth += column->width();
+ }
- doItemsLayout();
+ 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) {
+ const int newContentX = m_contentX - x - width + viewportWidth;
+ if (isRightToLeft()) {
+ m_animation->setFrameRange(m_contentX, newContentX);
+ } else {
+ m_animation->setFrameRange(-m_contentX, -newContentX);
+ }
+ 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);
+ }
+ m_animation->start();
+ }
+}
+
+void DolphinColumnView::requestActivation(ColumnWidget* column)
+{
+ if (column->isActive()) {
+ assureVisibleActiveColumn();
+ } else {
+ int index = 0;
+ foreach (ColumnWidget* currColumn, m_columns) {
+ if (currColumn == column) {
+ setActiveColumnIndex(index);
+ return;
+ }
+ ++index;
+ }
+ }
}
#include "dolphincolumnview.moc"