From: Peter Penz Date: Fri, 5 Oct 2007 21:00:44 +0000 (+0000) Subject: Refactored DolphinColumnWidget so that it does not need a hierarchical KDirLister... X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/29402a79bc09945ccd96201cbb42027b4c581a00?ds=inline Refactored DolphinColumnWidget so that it does not need a hierarchical KDirLister. This simplifies the code a lot and also bypasses the current problems with the KDirLister cache when working on hierarchical directories in parallel. There are some minor regressions which will be fixed, but all in all some improvements are visible already: - the loading of columns is a lot faster - preview in columns is working - no side effects in combination with the treeview-panel because of caching svn path=/trunk/KDE/kdebase/apps/; revision=721678 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1405bf859..c06684d9c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,7 @@ set(dolphinprivate_LIB_SRCS dolphindetailsview.cpp dolphiniconsview.cpp dolphincolumnview.cpp + dolphincolumnwidget.cpp kcategorizedview.cpp kcategorydrawer.cpp dolphinmodel.cpp diff --git a/src/dolphincolumnview.cpp b/src/dolphincolumnview.cpp index 0f4c962ac..b8be24bf0 100644 --- a/src/dolphincolumnview.cpp +++ b/src/dolphincolumnview.cpp @@ -20,7 +20,11 @@ #include "dolphincolumnview.h" #include "dolphinmodel.h" +#include "dolphincolumnwidget.h" #include "dolphincontroller.h" +#include "dolphindirlister.h" +#include "dolphinmodel.h" +#include "dolphinsortfilterproxymodel.h" #include "dolphinsettings.h" #include "dolphin_columnmodesettings.h" @@ -36,363 +40,6 @@ #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. */ - 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) : - QListView(parent), - m_active(true), - m_view(columnView), - m_url(url), - m_childUrl(), - m_dragging(false), - m_dropRect() -{ - setMouseTracking(true); - viewport()->setAttribute(Qt::WA_Hover); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - setSelectionBehavior(SelectItems); - setSelectionMode(QAbstractItemView::ExtendedSelection); - setDragDropMode(QAbstractItemView::DragDrop); - setDropIndicatorShown(false); - setFocusPolicy(Qt::NoFocus); - -// TODO: Remove this check when 4.3.2 is released and KDE requires it... this -// check avoids a division by zero happening on versions before 4.3.1. -// Right now KDE in theory can be shipped with Qt 4.3.0 and above. -// ereslibre -#if (QT_VERSION >= QT_VERSION_CHECK(4, 3, 2) || defined(QT_KDE_QT_COPY)) - setVerticalScrollMode(QListView::ScrollPerPixel); - setHorizontalScrollMode(QListView::ScrollPerPixel); -#endif - - // apply the column mode settings to the widget - const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); - Q_ASSERT(settings != 0); - - m_viewOptions = QListView::viewOptions(); - - QFont font(settings->fontFamily(), settings->fontSize()); - font.setItalic(settings->italicFont()); - font.setBold(settings->boldFont()); - m_viewOptions.font = font; - - 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() -{ -} - -void ColumnWidget::setDecorationSize(const QSize& size) -{ - m_viewOptions.decorationSize = size; - doItemsLayout(); -} - -void ColumnWidget::setActive(bool active) -{ - if (m_active == active) { - return; - } - - m_active = active; - - if (active) { - activate(); - } else { - deactivate(); - } -} - -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; -} - -inline QStyleOptionViewItem ColumnWidget::viewOptions() const -{ - return m_viewOptions; -} - -void ColumnWidget::dragEnterEvent(QDragEnterEvent* event) -{ - if (event->mimeData()->hasUrls()) { - event->acceptProposedAction(); - } - - m_dragging = true; -} - -void ColumnWidget::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) -{ - 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); - setDirtyRegion(m_dropRect); -} - -void ColumnWidget::dropEvent(QDropEvent* event) -{ - const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); - if (!urls.isEmpty()) { - event->acceptProposedAction(); - m_view->m_controller->indicateDroppedUrls(urls, - url(), - indexAt(event->pos()), - event->source()); - } - QListView::dropEvent(event); - m_dragging = false; -} - -void ColumnWidget::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); - 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) -{ - 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_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), @@ -421,6 +68,10 @@ DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* control this, SLOT(zoomOut())); connect(controller, SIGNAL(urlChanged(const KUrl&)), this, SLOT(showColumn(const KUrl&))); + connect(controller, SIGNAL(showHiddenFilesChanged(bool)), + this, SLOT(slotShowHiddenFilesChanged(bool))); + connect(controller, SIGNAL(showPreviewChanged(bool)), + this, SLOT(slotShowPreviewChanged(bool))); connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(moveContentHorizontally(int))); @@ -428,7 +79,7 @@ DolphinColumnView::DolphinColumnView(QWidget* parent, DolphinController* control 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()); + DolphinColumnWidget* column = new DolphinColumnWidget(viewport(), this, m_controller->url()); m_columns.append(column); setActiveColumnIndex(0); @@ -450,7 +101,7 @@ DolphinColumnView::~DolphinColumnView() QModelIndex DolphinColumnView::indexAt(const QPoint& point) const { - foreach (ColumnWidget* column, m_columns) { + foreach (DolphinColumnWidget* column, m_columns) { const QPoint topLeft = column->frameGeometry().topLeft(); const QPoint adjustedPoint(point.x() - topLeft.x(), point.y() - topLeft.y()); const QModelIndex index = column->indexAt(adjustedPoint); @@ -474,64 +125,29 @@ QRect DolphinColumnView::visualRect(const QModelIndex& index) const 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(completed()), - this, SLOT(triggerExpandToActiveUrl())); - - 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... + QItemSelectionModel* selectionModel = activeColumn()->selectionModel(); + const QAbstractItemModel* itemModel = selectionModel->model(); - ColumnWidget* column = activeColumn(); - QItemSelectionModel* selModel = column->selectionModel(); + const QModelIndex topLeft = itemModel->index(0, 0); + const QModelIndex bottomRight = itemModel->index(itemModel->rowCount() - 1, + itemModel->columnCount() - 1); - 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); - } + const QItemSelection selection(topLeft, bottomRight); + selectionModel->select(selection, 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(); + foreach (DolphinColumnWidget* column, m_columns) { + column->reload(); } - - // all columns are hidden, now reload the directory lister - KDirLister* dirLister = m_dolphinModel->dirLister(); - const KUrl& rootUrl = m_columns[0]->url(); - dirLister->openUrl(rootUrl, KDirLister::Reload); - updateColumns(); } void DolphinColumnView::showColumn(const KUrl& url) @@ -540,9 +156,9 @@ void DolphinColumnView::showColumn(const KUrl& 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) { + 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); @@ -563,7 +179,7 @@ void DolphinColumnView::showColumn(const KUrl& url) } int columnIndex = 0; - foreach (ColumnWidget* column, m_columns) { + foreach (DolphinColumnWidget* column, m_columns) { if (column->url() == url) { // the column represents already the requested URL, hence activate it requestActivation(column); @@ -572,9 +188,9 @@ void DolphinColumnView::showColumn(const KUrl& 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) { + 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); @@ -621,9 +237,7 @@ void DolphinColumnView::showColumn(const KUrl& url) m_columns[columnIndex]->setChildUrl(childUrl); columnIndex++; - ColumnWidget* column = new ColumnWidget(viewport(), this, childUrl); - column->setModel(model()); - column->setRootIndex(proxyIndex); + DolphinColumnWidget* column = new DolphinColumnWidget(viewport(), this, childUrl); column->setActive(false); m_columns.append(column); @@ -637,7 +251,7 @@ void DolphinColumnView::showColumn(const KUrl& url) // the layout is finished, now let the column be invisible until it // gets a valid root index due to expandToActiveUrl() - column->hide(); + //column->hide(); } } @@ -774,7 +388,7 @@ void DolphinColumnView::updateDecorationSize() foreach (QObject* object, viewport()->children()) { if (object->inherits("QListView")) { - ColumnWidget* widget = static_cast(object); + DolphinColumnWidget* widget = static_cast(object); widget->setDecorationSize(QSize(iconSize, iconSize)); } } @@ -785,55 +399,20 @@ void DolphinColumnView::updateDecorationSize() doItemsLayout(); } -void DolphinColumnView::expandToActiveUrl() +void DolphinColumnView::slotShowHiddenFilesChanged(bool show) { - 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 = rootUrl.isParentOf(activeUrl) - && !rootUrl.equals(activeUrl, KUrl::CompareWithoutTrailingSlash); - if (expand) { - m_dolphinModel->expandToUrl(activeUrl); + foreach (DolphinColumnWidget* column, m_columns) { + column->setShowHiddenFiles(show); } - 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() +void DolphinColumnView::slotShowPreviewChanged(bool show) { - 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; - } - } - } + foreach (DolphinColumnWidget* column, m_columns) { + column->setShowPreview(show); } } -void DolphinColumnView::triggerExpandToActiveUrl() -{ - QMetaObject::invokeMethod(this, "expandToActiveUrl", Qt::QueuedConnection); -} - bool DolphinColumnView::isZoomInPossible() const { ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); @@ -871,13 +450,13 @@ void DolphinColumnView::layoutColumns() const int columnWidth = settings->columnWidth(); if (isRightToLeft()) { int x = viewport()->width() - columnWidth + m_contentX; - foreach (ColumnWidget* column, m_columns) { + foreach (DolphinColumnWidget* column, m_columns) { column->setGeometry(QRect(x, 0, columnWidth, viewport()->height())); x -= columnWidth; } } else { int x = m_contentX; - foreach (ColumnWidget* column, m_columns) { + foreach (DolphinColumnWidget* column, m_columns) { column->setGeometry(QRect(x, 0, columnWidth, viewport()->height())); x += columnWidth; } @@ -887,7 +466,7 @@ void DolphinColumnView::layoutColumns() void DolphinColumnView::updateScrollBar() { int contentWidth = 0; - foreach (ColumnWidget* column, m_columns) { + foreach (DolphinColumnWidget* column, m_columns) { contentWidth += column->width(); } @@ -919,13 +498,13 @@ void DolphinColumnView::assureVisibleActiveColumn() } } -void DolphinColumnView::requestActivation(ColumnWidget* column) +void DolphinColumnView::requestActivation(DolphinColumnWidget* column) { if (column->isActive()) { assureVisibleActiveColumn(); } else { int index = 0; - foreach (ColumnWidget* currColumn, m_columns) { + foreach (DolphinColumnWidget* currColumn, m_columns) { if (currColumn == column) { setActiveColumnIndex(index); return; diff --git a/src/dolphincolumnview.h b/src/dolphincolumnview.h index 4a6e6140c..b473e790e 100644 --- a/src/dolphincolumnview.h +++ b/src/dolphincolumnview.h @@ -24,7 +24,7 @@ #include #include -class ColumnWidget; +class DolphinColumnWidget; class DolphinController; class DolphinModel; class KUrl; @@ -99,36 +99,14 @@ private slots: */ void updateDecorationSize(); - /** - * Expands the directory model the the currently active URL. - * Used by DolphinColumnView::reload() after the directory - * lister has been loaded. - */ - void expandToActiveUrl(); - - /** - * Triggers the updating of columns after the model index - * \a index has been expanded. Used by DolphinModel::expandToActiveUrl(). - */ - void triggerUpdateColumns(const QModelIndex& index); - - /** - * Adjusts the root index of all columns to represent the reloaded - * model. Used by DolphinModel::triggerUpdateColumns(). - */ - void updateColumns(); - - /** - * Is invoked when the directory lister has completed the loading - * and invokes expandToActiveUrl() asynchronously. - */ - void triggerExpandToActiveUrl(); + void slotShowHiddenFilesChanged(bool show); + void slotShowPreviewChanged(bool show); private: bool isZoomInPossible() const; bool isZoomOutPossible() const; - ColumnWidget* activeColumn() const; + DolphinColumnWidget* activeColumn() const; /** * Deactivates the currently active column and activates @@ -152,23 +130,23 @@ private: * that the columns gets fully visible by adjusting the horizontal * position of the content. */ - void requestActivation(ColumnWidget* column); + void requestActivation(DolphinColumnWidget* column); private: DolphinController* m_controller; bool m_restoreActiveColumnFocus; int m_index; int m_contentX; - QList m_columns; + QList m_columns; QTimeLine* m_animation; DolphinModel* m_dolphinModel; QAbstractProxyModel* m_proxyModel; - friend class ColumnWidget; + friend class DolphinColumnWidget; }; -inline ColumnWidget* DolphinColumnView::activeColumn() const +inline DolphinColumnWidget* DolphinColumnView::activeColumn() const { return m_columns[m_index]; } diff --git a/src/dolphincolumnwidget.cpp b/src/dolphincolumnwidget.cpp new file mode 100644 index 000000000..94bee2bee --- /dev/null +++ b/src/dolphincolumnwidget.cpp @@ -0,0 +1,446 @@ +/*************************************************************************** + * Copyright (C) 2007 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "dolphincolumnwidget.h" + +#include "dolphinmodel.h" +#include "dolphincolumnview.h" +#include "dolphincontroller.h" +#include "dolphindirlister.h" +#include "dolphinmodel.h" +#include "dolphinsortfilterproxymodel.h" +#include "dolphinsettings.h" + +#include "dolphin_columnmodesettings.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, + DolphinColumnView* columnView, + const KUrl& url) : + QListView(parent), + m_active(true), + m_showPreview(false), + m_view(columnView), + m_url(url), + m_childUrl(), + m_viewOptions(), + m_dirLister(0), + m_dolphinModel(0), + m_proxyModel(0), + m_dragging(false), + m_dropRect() +{ + setMouseTracking(true); + viewport()->setAttribute(Qt::WA_Hover); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + setSelectionBehavior(SelectItems); + setSelectionMode(QAbstractItemView::ExtendedSelection); + setDragDropMode(QAbstractItemView::DragDrop); + setDropIndicatorShown(false); + setFocusPolicy(Qt::NoFocus); + +// TODO: Remove this check when 4.3.2 is released and KDE requires it... this +// check avoids a division by zero happening on versions before 4.3.1. +// Right now KDE in theory can be shipped with Qt 4.3.0 and above. +// ereslibre +#if (QT_VERSION >= QT_VERSION_CHECK(4, 3, 2) || defined(QT_KDE_QT_COPY)) + setVerticalScrollMode(QListView::ScrollPerPixel); + setHorizontalScrollMode(QListView::ScrollPerPixel); +#endif + + // apply the column mode settings to the widget + const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); + Q_ASSERT(settings != 0); + + m_viewOptions = QListView::viewOptions(); + + QFont font(settings->fontFamily(), settings->fontSize()); + font.setItalic(settings->italicFont()); + font.setBold(settings->boldFont()); + m_viewOptions.font = font; + + 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())); + connect(this, SIGNAL(viewportEntered()), + m_view->m_controller, SLOT(emitViewportEntered())); + + connect(this, SIGNAL(entered(const QModelIndex&)), + this, SLOT(slotEntered(const QModelIndex&))); + + //m_dirLister = new DolphinDirLister(); TODO + m_dirLister = new KDirLister(); + m_dirLister->setAutoUpdate(true); + m_dirLister->setMainWindow(this); + m_dirLister->setDelayedMimeTypes(true); + m_dirLister->setShowingDotFiles(m_view->m_controller->showHiddenFiles()); + connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)), + this, SLOT(generatePreviews(const KFileItemList&))); + + m_dolphinModel = new DolphinModel(this); + m_dolphinModel->setDirLister(m_dirLister); + m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory); + + m_proxyModel = new DolphinSortFilterProxyModel(this); + m_proxyModel->setSourceModel(m_dolphinModel); + + setModel(m_proxyModel); + + m_dirLister->openUrl(url, KDirLister::NoFlags); +} + +DolphinColumnWidget::~DolphinColumnWidget() +{ + delete m_dirLister; + m_dirLister = 0; +} + +void DolphinColumnWidget::setDecorationSize(const QSize& size) +{ + m_viewOptions.decorationSize = size; + doItemsLayout(); +} + +void DolphinColumnWidget::setActive(bool active) +{ + if (m_active == active) { + return; + } + + m_active = active; + + if (active) { + activate(); + } else { + deactivate(); + } +} + +void DolphinColumnWidget::reload() +{ + m_dirLister->stop(); + m_dirLister->openUrl(m_url, KDirLister::Reload); +} + +void DolphinColumnWidget::setShowHiddenFiles(bool show) +{ + if (show != m_dirLister->showingDotFiles()) { + m_dirLister->setShowingDotFiles(show); + m_dirLister->stop(); + m_dirLister->openUrl(m_url, KDirLister::Reload); + } +} + +void DolphinColumnWidget::setShowPreview(bool show) +{ + if (show != m_showPreview) { + m_dirLister->stop(); + m_dirLister->openUrl(m_url, KDirLister::Reload); + } +} + +void DolphinColumnWidget::dragEnterEvent(QDragEnterEvent* event) +{ + if (event->mimeData()->hasUrls()) { + event->acceptProposedAction(); + } + + m_dragging = true; +} + +void DolphinColumnWidget::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 DolphinColumnWidget::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); + setDirtyRegion(m_dropRect); +} + +void DolphinColumnWidget::dropEvent(QDropEvent* event) +{ + const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); + if (!urls.isEmpty()) { + event->acceptProposedAction(); + m_view->m_controller->indicateDroppedUrls(urls, + url(), + indexAt(event->pos()), + event->source()); + } + QListView::dropEvent(event); + m_dragging = false; +} + +void DolphinColumnWidget::paintEvent(QPaintEvent* event) +{ + if (!m_childUrl.isEmpty()) { + // indicate the shown URL of the next column by highlighting the shown folder item + const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_childUrl); + const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); + if (proxyIndex.isValid() && !selectionModel()->isSelected(proxyIndex)) { + const QRect itemRect = visualRect(proxyIndex); + QPainter painter(viewport()); + 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 DolphinColumnWidget::mousePressEvent(QMouseEvent* event) +{ + if (!m_active) { + m_view->requestActivation(this); + } + + QListView::mousePressEvent(event); +} + +void DolphinColumnWidget::keyPressEvent(QKeyEvent* event) +{ + QListView::keyPressEvent(event); + + const QItemSelectionModel* selModel = selectionModel(); + const QModelIndex currentIndex = selModel->currentIndex(); + const bool trigger = currentIndex.isValid() + && (event->key() == Qt::Key_Return) + && (selModel->selectedIndexes().count() <= 1); + if (trigger) { + triggerItem(currentIndex); + } +} + +void DolphinColumnWidget::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 DolphinColumnWidget::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 DolphinColumnWidget::triggerItem(const QModelIndex& index) +{ + const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers(); + if ((modifier & Qt::ShiftModifier) || (modifier & Qt::ControlModifier)) { + // items are selected by the user, hence don't trigger the + // item specified by 'index' + return; + } + + // TODO: check ZIP support (see DolphinViewContainer::triggerItem) + KFileItem item = m_dolphinModel->itemForIndex(m_proxyModel->mapToSource(index)); + if (item.isDir()) { + bool isLocal; + const KUrl url = item.mostLocalUrl(isLocal); + m_view->showColumn(url); + m_view->m_controller->setUrl(url); + } else if (item.isFile()) { + item.run(); + } +} + +void DolphinColumnWidget::generatePreviews(const KFileItemList& items) +{ + // TODO: same implementation as in DolphinView; create helper class + // for generatePreviews(), showPreview() and isCutItem() + + if (m_view->m_controller->showPreview()) { + KIO::PreviewJob* job = KIO::filePreview(items, 128); + connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)), + this, SLOT(showPreview(const KFileItem&, const QPixmap&))); + } +} + +void DolphinColumnWidget::showPreview(const KFileItem& item, const QPixmap& pixmap) +{ + // TODO: same implementation as in DolphinView; create helper class + // for generatePreviews(), showPreview() and isCutItem() + + Q_ASSERT(!item.isNull()); + if (item.url().directory() != m_dirLister->url().path()) { + // the preview job is still working on items of an older URL, hence + // the item is not part of the directory model anymore + return; + } + + const QModelIndex idx = m_dolphinModel->indexForItem(item); + if (idx.isValid() && (idx.column() == 0)) { + const QMimeData* mimeData = QApplication::clipboard()->mimeData(); + if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) { + KIconEffect iconEffect; + const QPixmap cutPixmap = iconEffect.apply(pixmap, KIconLoader::Desktop, KIconLoader::DisabledState); + m_dolphinModel->setData(idx, QIcon(cutPixmap), Qt::DecorationRole); + } else { + m_dolphinModel->setData(idx, QIcon(pixmap), Qt::DecorationRole); + } + } +} + +void DolphinColumnWidget::slotEntered(const QModelIndex& index) +{ + const QModelIndex dirIndex = m_proxyModel->mapToSource(index); + const KFileItem item = m_dolphinModel->itemForIndex(dirIndex); + m_view->m_controller->emitItemEntered(item); +} + +void DolphinColumnWidget::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&)), + this, SLOT(triggerItem(const QModelIndex&))); + } else { + connect(this, SIGNAL(doubleClicked(const QModelIndex&)), + this, 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_dolphinModel->indexForUrl(m_childUrl); + const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); + selectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::Current); + } + + update(); +} + +void DolphinColumnWidget::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&)), + this, SLOT(triggerItem(const QModelIndex&))); + } else { + disconnect(this, SIGNAL(doubleClicked(const QModelIndex&)), + this, SLOT(triggerItem(const QModelIndex&))); + } + + const QPalette palette = m_view->viewport()->palette(); + viewport()->setPalette(palette); + + selectionModel()->clear(); + update(); +} + +bool DolphinColumnWidget::isCutItem(const KFileItem& item) const +{ + // TODO: same implementation as in DolphinView; create helper class + // for generatePreviews(), showPreview() and isCutItem() + + const QMimeData* mimeData = QApplication::clipboard()->mimeData(); + const KUrl::List cutUrls = KUrl::List::fromMimeData(mimeData); + + const KUrl& itemUrl = item.url(); + KUrl::List::const_iterator it = cutUrls.begin(); + const KUrl::List::const_iterator end = cutUrls.end(); + while (it != end) { + if (*it == itemUrl) { + return true; + } + ++it; + } + + return false; +} + +#include "dolphincolumnwidget.moc" diff --git a/src/dolphincolumnwidget.h b/src/dolphincolumnwidget.h new file mode 100644 index 000000000..0efce0902 --- /dev/null +++ b/src/dolphincolumnwidget.h @@ -0,0 +1,177 @@ +/*************************************************************************** + * Copyright (C) 2007 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef DOLPHINCOLUMNWIDGET_H +#define DOLPHINCOLUMNWIDGET_H + +#include +#include + +#include + +class DolphinColumnView; +class DolphinModel; +class DolphinSortFilterProxyModel; +class KDirLister; +class KFileItem; +class KFileItemList; +class QPixmap; + +/** + * Represents one column inside the DolphinColumnView and has been + * extended to respect view options and hovering information. + */ +class DolphinColumnWidget : public QListView +{ + Q_OBJECT + +public: + DolphinColumnWidget(QWidget* parent, + DolphinColumnView* columnView, + const KUrl& url); + virtual ~DolphinColumnWidget(); + + /** Sets the size of the icons. */ + void setDecorationSize(const QSize& size); + + /** + * An active column is defined as column, which shows the same URL + * as indicated by the URL navigator. The active column is usually + * drawn in a lighter color. All operations are applied to this column. + */ + void setActive(bool active); + bool isActive() const; + + /** + * Sets the directory URL of the child column that is shown next to + * this column. This property is only used for a visual indication + * of the shown directory, it does not trigger a loading of the model. + */ + void setChildUrl(const KUrl& url); + const KUrl& childUrl() const; + + /** Sets the directory URL that is shown inside the column widget. */ + void setUrl(const KUrl& url); + + /** Returns the directory URL that is shown inside the column widget. */ + const KUrl& url() const; + + /** Reloads the directory DolphinColumnWidget::url(). */ + void reload(); + + void setShowHiddenFiles(bool show); + void setShowPreview(bool show); + +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 slots: + /** + * If the item specified by \a index is a directory, then this + * directory will be loaded in a new column. If the item is a + * file, the corresponding application will get started. + */ + void triggerItem(const QModelIndex& index); + + /** + * Generates a preview image for each file item in \a items. + * The current preview settings (maximum size, 'Show Preview' menu) + * are respected. + */ + void generatePreviews(const KFileItemList& items); + + /** + * Replaces the icon of the item \a item by the preview pixmap + * \a pixmap. + */ + void showPreview(const KFileItem& item, const QPixmap& pixmap); + + void slotEntered(const QModelIndex& index); + +private: + /** Used by DolphinColumnWidget::setActive(). */ + void activate(); + + /** Used by DolphinColumnWidget::setActive(). */ + void deactivate(); + + /** + * Returns true, if the item \a item has been cut into + * the clipboard. + */ + bool isCutItem(const KFileItem& item) const; + +private: + bool m_active; + bool m_showPreview; + 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; + KDirLister* m_dirLister; + DolphinModel* m_dolphinModel; + DolphinSortFilterProxyModel* m_proxyModel; + + 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 +}; + +inline bool DolphinColumnWidget::isActive() const +{ + return m_active; +} + +inline void DolphinColumnWidget::setChildUrl(const KUrl& url) +{ + m_childUrl = url; +} + +inline const KUrl& DolphinColumnWidget::childUrl() const +{ + return m_childUrl; +} + +inline void DolphinColumnWidget::setUrl(const KUrl& url) +{ + if (url != m_url) { + m_url = url; + reload(); + } +} + +inline const KUrl& DolphinColumnWidget::url() const +{ + return m_url; +} + +inline QStyleOptionViewItem DolphinColumnWidget::viewOptions() const +{ + return m_viewOptions; +} + +#endif diff --git a/src/dolphincontroller.cpp b/src/dolphincontroller.cpp index 7723fd8ef..4666e617b 100644 --- a/src/dolphincontroller.cpp +++ b/src/dolphincontroller.cpp @@ -23,6 +23,7 @@ DolphinController::DolphinController(QObject* parent) : QObject(parent), + m_showHiddenFiles(false), m_showPreview(false), m_zoomInPossible(false), m_zoomOutPossible(false), @@ -73,6 +74,14 @@ void DolphinController::indicateSortOrderChange(Qt::SortOrder order) emit sortOrderChanged(order); } +void DolphinController::setShowHiddenFiles(bool show) +{ + if (m_showHiddenFiles != show) { + m_showHiddenFiles = show; + emit showHiddenFilesChanged(show); + } +} + void DolphinController::setShowPreview(bool show) { if (m_showPreview != show) { @@ -131,9 +140,9 @@ void DolphinController::triggerItem(const QModelIndex& index) emit itemTriggered(index); } -void DolphinController::emitItemEntered(const QModelIndex& index) +void DolphinController::emitItemEntered(const KFileItem& item) { - emit itemEntered(index); + emit itemEntered(item); } void DolphinController::emitViewportEntered() diff --git a/src/dolphincontroller.h b/src/dolphincontroller.h index d773a8548..3a2720471 100644 --- a/src/dolphincontroller.h +++ b/src/dolphincontroller.h @@ -74,6 +74,9 @@ public: void indicateSortOrderChange(Qt::SortOrder order); + void setShowHiddenFiles(bool show); + bool showHiddenFiles() const; + void setShowPreview(bool show); bool showPreview() const; @@ -103,7 +106,7 @@ public slots: * Emits the signal itemEntered(). The method should be invoked by * the controller parent whenever the mouse cursor is above an item. */ - void emitItemEntered(const QModelIndex& index); + void emitItemEntered(const KFileItem& item); /** * Emits the signal viewportEntered(). The method should be invoked by @@ -149,6 +152,12 @@ signals: /** Is emitted if the sort order has been changed to \a sort order. */ void sortOrderChanged(Qt::SortOrder order); + /** + * Is emitted if the state for showing hidden files has been + * changed to \a show. + */ + void showHiddenFilesChanged(bool show); + /** * Is emitted if the state for showing previews has been * changed to \a show. @@ -173,7 +182,7 @@ signals: * Is emitted if the mouse cursor has entered the item * given by \a index. */ - void itemEntered(const QModelIndex& index); + void itemEntered(const KFileItem& item); /** * Is emitted if the mouse cursor has entered @@ -187,6 +196,7 @@ signals: void zoomOut(); private: + bool m_showHiddenFiles; bool m_showPreview; bool m_zoomInPossible; bool m_zoomOutPossible; @@ -199,6 +209,11 @@ inline const KUrl& DolphinController::url() const return m_url; } +inline bool DolphinController::showHiddenFiles() const +{ + return m_showHiddenFiles; +} + inline bool DolphinController::showPreview() const { return m_showPreview; diff --git a/src/dolphindetailsview.cpp b/src/dolphindetailsview.cpp index 15f108dbb..078f51bf1 100644 --- a/src/dolphindetailsview.cpp +++ b/src/dolphindetailsview.cpp @@ -28,9 +28,11 @@ #include "dolphin_detailsmodesettings.h" +#include #include #include +#include #include #include #include @@ -383,7 +385,7 @@ void DolphinDetailsView::slotEntered(const QModelIndex& index) const QPoint pos = viewport()->mapFromGlobal(QCursor::pos()); const int nameColumnWidth = header()->sectionSize(DolphinModel::Name); if (pos.x() < nameColumnWidth) { - m_controller->emitItemEntered(index); + m_controller->emitItemEntered(itemForIndex(index)); } else { m_controller->emitViewportEntered(); @@ -399,6 +401,13 @@ void DolphinDetailsView::updateElasticBand() setDirtyRegion(dirtyRegion); } +QRect DolphinDetailsView::elasticBandRect() const +{ + const QPoint pos(contentsPos()); + const QPoint topLeft(m_elasticBandOrigin.x() - pos.x(), m_elasticBandOrigin.y() - pos.y()); + return QRect(topLeft, m_elasticBandDestination).normalized(); +} + void DolphinDetailsView::zoomIn() { if (isZoomInPossible()) { @@ -431,7 +440,7 @@ void DolphinDetailsView::slotItemActivated(const QModelIndex& index) m_controller->triggerItem(index); } else { clearSelection(); - m_controller->emitItemEntered(index); + m_controller->emitItemEntered(itemForIndex(index)); } } @@ -518,16 +527,12 @@ QPoint DolphinDetailsView::contentsPos() const return QPoint(0, y); } -QRect DolphinDetailsView::elasticBandRect() const -{ - const QPoint pos(contentsPos()); - const QPoint topLeft(m_elasticBandOrigin.x() - pos.x(), m_elasticBandOrigin.y() - pos.y()); - return QRect(topLeft, m_elasticBandDestination).normalized(); -} - -static bool isValidNameIndex(const QModelIndex& index) +KFileItem DolphinDetailsView::itemForIndex(const QModelIndex& index) const { - return index.isValid() && (index.column() == KDirModel::Name); + QAbstractProxyModel* proxyModel = static_cast(model()); + KDirModel* dirModel = static_cast(proxyModel->sourceModel()); + const QModelIndex dirIndex = proxyModel->mapToSource(index); + return dirModel->itemForIndex(dirIndex); } #include "dolphindetailsview.moc" diff --git a/src/dolphindetailsview.h b/src/dolphindetailsview.h index a0ef0eedf..06cd9a833 100644 --- a/src/dolphindetailsview.h +++ b/src/dolphindetailsview.h @@ -131,6 +131,8 @@ private: /** Return the upper left position in pixels of the viewport content. */ QPoint contentsPos() const; + KFileItem itemForIndex(const QModelIndex& index) const; + private: DolphinController* m_controller; QStyleOptionViewItem m_viewOptions; diff --git a/src/dolphiniconsview.cpp b/src/dolphiniconsview.cpp index 6b584612c..042c9a76c 100644 --- a/src/dolphiniconsview.cpp +++ b/src/dolphiniconsview.cpp @@ -26,6 +26,7 @@ #include "dolphin_iconsmodesettings.h" #include +#include #include #include @@ -58,8 +59,6 @@ DolphinIconsView::DolphinIconsView(QWidget* parent, DolphinController* controlle connect(this, SIGNAL(doubleClicked(const QModelIndex&)), controller, SLOT(triggerItem(const QModelIndex&))); } - connect(this, SIGNAL(entered(const QModelIndex&)), - controller, SLOT(emitItemEntered(const QModelIndex&))); connect(this, SIGNAL(viewportEntered()), controller, SLOT(emitViewportEntered())); connect(controller, SIGNAL(showPreviewChanged(bool)), @@ -71,6 +70,9 @@ DolphinIconsView::DolphinIconsView(QWidget* parent, DolphinController* controlle connect(controller, SIGNAL(zoomOut()), this, SLOT(zoomOut())); + connect(this, SIGNAL(entered(const QModelIndex&)), + this, SLOT(slotEntered(const QModelIndex&))); + // apply the icons mode settings to the widget const IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings(); Q_ASSERT(settings != 0); @@ -228,6 +230,16 @@ void DolphinIconsView::keyPressEvent(QKeyEvent* event) } } +void DolphinIconsView::slotEntered(const QModelIndex& index) +{ + QAbstractProxyModel* proxyModel = static_cast(model()); + KDirModel* dirModel = static_cast(proxyModel->sourceModel()); + const QModelIndex dirIndex = proxyModel->mapToSource(index); + + const KFileItem item = dirModel->itemForIndex(dirIndex); + m_controller->emitItemEntered(item); +} + void DolphinIconsView::slotShowPreviewChanged(bool showPreview) { updateGridSize(showPreview, m_controller->additionalInfoCount()); diff --git a/src/dolphiniconsview.h b/src/dolphiniconsview.h index 7e88f39bd..a95163f3a 100644 --- a/src/dolphiniconsview.h +++ b/src/dolphiniconsview.h @@ -59,6 +59,7 @@ protected: virtual void keyPressEvent(QKeyEvent* event); private slots: + void slotEntered(const QModelIndex& index); void slotShowPreviewChanged(bool show); void slotAdditionalInfoCountChanged(int count); void zoomIn(); diff --git a/src/dolphinview.cpp b/src/dolphinview.cpp index 94ed99b69..ad760fb13 100644 --- a/src/dolphinview.cpp +++ b/src/dolphinview.cpp @@ -60,7 +60,6 @@ DolphinView::DolphinView(QWidget* parent, QWidget(parent), m_active(true), m_loadingDirectory(false), - m_initializeColumnView(false), m_storedCategorizedSorting(false), m_mode(DolphinView::IconsView), m_topLayout(0), @@ -103,8 +102,8 @@ DolphinView::DolphinView(QWidget* parent, this, SLOT(triggerItem(const QModelIndex&))); connect(m_controller, SIGNAL(activated()), this, SLOT(activate())); - connect(m_controller, SIGNAL(itemEntered(const QModelIndex&)), - this, SLOT(showHoverInformation(const QModelIndex&))); + connect(m_controller, SIGNAL(itemEntered(const KFileItem&)), + this, SLOT(showHoverInformation(const KFileItem&))); connect(m_controller, SIGNAL(viewportEntered()), this, SLOT(clearHoverInformation())); @@ -181,7 +180,7 @@ void DolphinView::setMode(Mode mode) emit categorizedSortingChanged(); } - startDirLister(viewPropsUrl); + loadDirectory(viewPropsUrl); emit modeChanged(); } @@ -200,7 +199,7 @@ void DolphinView::setShowPreview(bool show) m_controller->setShowPreview(show); emit showPreviewChanged(); - startDirLister(viewPropsUrl, true); + loadDirectory(viewPropsUrl, true); } bool DolphinView::showPreview() const @@ -219,9 +218,10 @@ void DolphinView::setShowHiddenFiles(bool show) props.setShowHiddenFiles(show); m_dirLister->setShowingDotFiles(show); + m_controller->setShowHiddenFiles(show); emit showHiddenFilesChanged(); - startDirLister(viewPropsUrl, true); + loadDirectory(viewPropsUrl, true); } bool DolphinView::showHiddenFiles() const @@ -278,8 +278,8 @@ void DolphinView::invertSelection() // QAbstractItemView does not offer a virtual method invertSelection() // as counterpart to QAbstractItemView::selectAll(). This makes it // necessary to delegate the inverting of the selection to the - // column view, as only the selection of the active column should get - // inverted. + // column view, as only the selection of the active column should + // get inverted. m_columnView->invertSelection(); } else { QItemSelectionModel* selectionModel = itemView()->selectionModel(); @@ -416,7 +416,7 @@ void DolphinView::setAdditionalInfo(KFileItemDelegate::InformationList info) m_fileItemDelegate->setShowInformation(info); emit additionalInfoChanged(info); - startDirLister(viewPropsUrl, true); + loadDirectory(viewPropsUrl, true); } KFileItemDelegate::InformationList DolphinView::additionalInfo() const @@ -427,7 +427,7 @@ KFileItemDelegate::InformationList DolphinView::additionalInfo() const void DolphinView::reload() { setUrl(url()); - startDirLister(url(), true); + loadDirectory(url(), true); } void DolphinView::refresh() @@ -452,7 +452,7 @@ void DolphinView::updateView(const KUrl& url, const KUrl& rootUrl) if (restoreColumnView) { applyViewProperties(rootUrl); - startDirLister(rootUrl); + loadDirectory(rootUrl); // Restoring the column view relies on the URL-history. It might be possible // that the view properties have been changed or deleted in the meantime, so // it cannot be asserted that really a column view has been created: @@ -461,7 +461,7 @@ void DolphinView::updateView(const KUrl& url, const KUrl& rootUrl) } } else { applyViewProperties(url); - startDirLister(url); + loadDirectory(url); } itemView()->setFocus(); @@ -540,7 +540,7 @@ void DolphinView::emitSelectionChangedSignal() emit selectionChanged(DolphinView::selectedItems()); } -void DolphinView::startDirLister(const KUrl& url, bool reload) +void DolphinView::loadDirectory(const KUrl& url, bool reload) { if (!url.isValid()) { const QString location(url.pathOrUrl()); @@ -556,32 +556,12 @@ void DolphinView::startDirLister(const KUrl& url, bool reload) m_loadingDirectory = true; m_dirLister->stop(); + m_dirLister->openUrl(url, reload ? KDirLister::Reload : KDirLister::NoFlags); - bool keepOldDirs = isColumnViewActive() && !m_initializeColumnView; - m_initializeColumnView = false; - - if (keepOldDirs) { - // keeping old directories is only necessary for hierarchical views - // like the column view - if (reload) { - // for the column view it is not enough to reload the directory lister, - // so this task is delegated to the column view directly - m_columnView->reload(); - } else if (m_dirLister->directories().contains(url)) { - // The dir lister contains the directory already, so - // KDirLister::openUrl() may not get invoked twice. - m_dirLister->updateDirectory(url); - } else { - const KUrl& dirListerUrl = m_dirLister->url(); - if ((dirListerUrl == url) || !m_dirLister->url().isParentOf(url)) { - // The current URL is not a child of the dir lister - // URL. This may happen when e. g. a place has been selected - // and hence the view must be reset. - m_dirLister->openUrl(url, KDirLister::NoFlags); - } - } - } else { - m_dirLister->openUrl(url, reload ? KDirLister::Reload : KDirLister::NoFlags); + if (isColumnViewActive() && reload) { + // reloading the directory lister is not enough in the case of the + // column view, as each column has its own directory lister internally... + m_columnView->reload(); } } @@ -610,14 +590,6 @@ void DolphinView::applyViewProperties(const KUrl& url) m_mode = mode; createView(); emit modeChanged(); - - if (m_mode == ColumnView) { - // The mode has been changed to the Column View. When starting the dir - // lister with DolphinView::startDirLister() it is important to give a - // hint that the dir lister may not keep the current directory - // although this is the default for showing a hierarchy. - m_initializeColumnView = true; - } } if (itemView() == 0) { createView(); @@ -628,6 +600,7 @@ void DolphinView::applyViewProperties(const KUrl& url) const bool showHiddenFiles = props.showHiddenFiles(); if (showHiddenFiles != m_dirLister->showingDotFiles()) { m_dirLister->setShowingDotFiles(showHiddenFiles); + m_controller->setShowHiddenFiles(showHiddenFiles); emit showHiddenFilesChanged(); } @@ -782,16 +755,13 @@ void DolphinView::updateCutItems() applyCutItemEffect(); } -void DolphinView::showHoverInformation(const QModelIndex& index) +void DolphinView::showHoverInformation(const KFileItem& item) { if (hasSelection()) { return; } - const KFileItem item = fileItem(index); - if (!item.isNull()) { - emit requestItemInfo(item); - } + emit requestItemInfo(item); } void DolphinView::clearHoverInformation() diff --git a/src/dolphinview.h b/src/dolphinview.h index c3d1c7abc..d9d2f5cca 100644 --- a/src/dolphinview.h +++ b/src/dolphinview.h @@ -486,11 +486,11 @@ private slots: /** * Updates the status bar to show hover information for the - * item with the index \a index. If currently other items are selected, + * item \a item. If currently other items are selected, * no hover information is shown. * @see DolphinView::clearHoverInformation() */ - void showHoverInformation(const QModelIndex& index); + void showHoverInformation(const KFileItem& item); /** * Clears the hover information shown in the status bar. @@ -499,7 +499,7 @@ private slots: void clearHoverInformation(); private: - void startDirLister(const KUrl& url, bool reload = false); + void loadDirectory(const KUrl& url, bool reload = false); /** * Returns the URL where the view properties should be stored. Usually @@ -571,8 +571,7 @@ private: }; bool m_active; - bool m_loadingDirectory; - bool m_initializeColumnView; + bool m_loadingDirectory;; bool m_storedCategorizedSorting; Mode m_mode; diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp index cb56f5c77..65e587fb2 100644 --- a/src/dolphinviewcontainer.cpp +++ b/src/dolphinviewcontainer.cpp @@ -94,11 +94,10 @@ DolphinViewContainer::DolphinViewContainer(DolphinMainWindow* mainWindow, m_dirLister->setMainWindow(this); m_dirLister->setDelayedMimeTypes(true); - m_dolphinModel = new DolphinModel(); + m_dolphinModel = new DolphinModel(this); m_dolphinModel->setDirLister(m_dirLister); m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory); - m_proxyModel = new DolphinSortFilterProxyModel(this); m_proxyModel->setSourceModel(m_dolphinModel);