SVN commit 947623 by fredrik: Open a popup view showing the folder contents when the user hovers a folder in the icon view. M +1 -0 CMakeLists.txt M +111 -6 iconview.cpp M +13 -1 iconview.h A popupview.cpp [License: LGPL (v2+)] A popupview.h [License: LGPL (v2+)] --- trunk/KDE/kdebase/apps/plasma/applets/folderview/CMakeLists.txt #947622:947623 @@ -7,6 +7,7 @@ dialog.cpp label.cpp iconview.cpp + popupview.cpp iconwidget.cpp dirlister.cpp proxymodel.cpp --- trunk/KDE/kdebase/apps/plasma/applets/folderview/iconview.cpp #947622:947623 @@ -36,6 +36,7 @@ #include #include +#include #include #include @@ -90,6 +91,8 @@ IconView::~IconView() { + // Make sure that we don't leave any open popup views on the screen when we're deleted + delete m_popupView; } void IconView::setModel(QAbstractItemModel *model) @@ -1163,6 +1166,28 @@ return m_editorIndex.isValid(); } +bool IconView::popupVisible() const +{ + return !m_popupView.isNull(); +} + +int IconView::scrollBarExtent() const +{ + return m_scrollBar->geometry().width(); +} + +QSize IconView::sizeForRowsColumns(int rows, int columns) const +{ + int spacing = 10; + int margin = 10; + + QSize size; + size.rwidth() = 2 * margin + columns * (gridSize().width() + spacing) + scrollBarExtent(); + size.rheight() = 2 * margin + rows * (gridSize().height() + spacing) - spacing; + + return size; +} + void IconView::commitData(QWidget *editor) { m_delegate->setModelData(editor, m_model, m_editorIndex); @@ -1221,14 +1246,66 @@ markAreaDirty(visibleArea()); } +KUrl IconView::targetFolder(const QModelIndex &index) const +{ + if (!index.isValid()) { + return KUrl(); + } + + KFileItem item = m_model->itemForIndex(index); + if (item.isDir()) { + return item.targetUrl(); + } + + if (item.isLink()) { + KFileItem destItem(KFileItem::Unknown, KFileItem::Unknown, KUrl::fromPath(item.linkDest())); + if (destItem.isDir()) { + return destItem.targetUrl(); + } + item = destItem; + } + + if (item.isDesktopFile()) { + KDesktopFile file(item.targetUrl().path()); + if (file.readType() == "Link") { + KUrl url(file.readUrl()); + if (url.isLocalFile()) { + KFileItem destItem(KFileItem::Unknown, KFileItem::Unknown, url); + if (destItem.isDir()) { + return destItem.targetUrl(); + } + } + } + } + + return KUrl(); +} + +void IconView::updateToolTip(const QModelIndex &index) +{ + if (!targetFolder(index).isEmpty()) { + m_toolTipShowTimer.start(500, this); + } else { + m_toolTipShowTimer.stop(); + if (m_popupView) { + if (index.isValid()) { + delete m_popupView; + } else { + m_popupView->delayedHide(); + } + } + m_toolTipWidget->updateToolTip(index, mapFromViewport(visualRect(index))); + } +} + void IconView::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { const QModelIndex index = indexAt(mapToViewport(event->pos())); if (index.isValid()) { m_hoveredIndex = index; markAreaDirty(visualRect(index)); - m_toolTipWidget->updateToolTip(index, mapFromViewport(visualRect(index))); } + updateToolTip(m_hoveredIndex); } void IconView::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) @@ -1238,7 +1315,7 @@ if (m_hoveredIndex.isValid()) { markAreaDirty(visualRect(m_hoveredIndex)); m_hoveredIndex = QModelIndex(); - m_toolTipWidget->updateToolTip(QModelIndex(), QRectF()); + updateToolTip(QModelIndex()); } } @@ -1249,7 +1326,8 @@ markAreaDirty(visualRect(index)); markAreaDirty(visualRect(m_hoveredIndex)); m_hoveredIndex = index; - m_toolTipWidget->updateToolTip(index, mapFromViewport(visualRect(index))); + + updateToolTip(index); } } @@ -1257,6 +1335,7 @@ { // Make sure that any visible tooltip is hidden Plasma::ToolTipManager::self()->hide(m_toolTipWidget); + delete m_popupView; if (!contentsRect().contains(event->pos()) || !m_errorMessage.isEmpty()) { event->ignore(); @@ -1306,10 +1385,12 @@ m_pressedIndex = QModelIndex(); m_buttonDownPos = pos; + const Plasma::Containment *parent = qobject_cast(parentWidget()); + if (event->modifiers() & Qt::ControlModifier) { // Make the current selection persistent m_selectionModel->select(m_selectionModel->selection(), QItemSelectionModel::Select); - } else if (static_cast(parentWidget())->isContainment() && + } else if (parent && parent->isContainment() && event->widget()->window()->inherits("DashboardView")) { // Let the event propagate to the parent widget, which will emit releaseVisualFocus(). // We prefer hiding the Dashboard to allowing rubber band selections in the containment @@ -1495,7 +1576,8 @@ return; } - const QString appletMimeType = static_cast(scene())->appletMimeType(); + Plasma::Corona *corona = qobject_cast(scene()); + const QString appletMimeType = (corona ? corona->appletMimeType() : QString()); QRectF dirtyRect = visualRect(m_hoveredIndex); m_hoveredIndex = QModelIndex(); @@ -1525,7 +1607,8 @@ void IconView::dropEvent(QGraphicsSceneDragDropEvent *event) { // If the dropped item is an applet, let the parent widget handle it - const QString appletMimeType = static_cast(scene())->appletMimeType(); + Plasma::Corona *corona = qobject_cast(scene()); + const QString appletMimeType = (corona ? corona->appletMimeType() : QString()); if (event->mimeData()->hasFormat(appletMimeType)) { event->ignore(); return; @@ -1848,6 +1931,28 @@ m_validRows = 0; } } + } else if (event->timerId() == m_toolTipShowTimer.timerId()) { + m_toolTipShowTimer.stop(); + Plasma::ToolTipManager::self()->hide(m_toolTipWidget); + delete m_popupView; + + const KUrl dir = targetFolder(m_hoveredIndex); + if (!dir.isEmpty()) { + const QPointF viewPos = mapFromViewport(visualRect(m_hoveredIndex)).center(); + const QPoint scenePos = mapToScene(viewPos).toPoint(); + QPoint pos; + + // We position the popup relative to the view under the mouse cursor + foreach (QGraphicsView *view, scene()->views()) { + if (view->underMouse()) { + pos = view->mapToGlobal(scenePos); + break; + } + } + + m_popupView = new PopupView(dir, pos, this); + connect(m_popupView, SIGNAL(destroyed(QObject*)), SIGNAL(popupViewClosed())); + } } } --- trunk/KDE/kdebase/apps/plasma/applets/folderview/iconview.h #947622:947623 @@ -22,6 +22,7 @@ #define ICONVIEW_H #include "abstractitemview.h" +#include "popupview.h" #include #include @@ -102,9 +103,12 @@ void setIconPositionsData(const QStringList &data); QStringList iconPositionsData() const; - void renameSelectedIcon(); bool renameInProgress() const; + bool popupVisible() const; + int scrollBarExtent() const; + QSize sizeForRowsColumns(int rows, int columns) const; + QRect visualRect(const QModelIndex &index) const; QRegion visualRegion(const QModelIndex &index) const; QModelIndex indexAt(const QPointF &point) const; @@ -113,6 +117,7 @@ signals: void indexesMoved(const QModelIndexList &indexes); + void popupViewClosed(); void busy(bool); protected: @@ -146,6 +151,9 @@ void finishedScrolling(); +public slots: + void renameSelectedIcon(); + private slots: void listingStarted(const KUrl &url); void listingClear(); @@ -160,6 +168,7 @@ int rowsForHeight(qreal height) const; QPoint nextGridPosition(const QPoint &prevPos, const QSize &gridSize, const QRect &contentRect) const; QPoint findNextEmptyPosition(const QPoint &prevPos, const QSize &gridSize, const QRect &contentRect) const; + KUrl targetFolder(const QModelIndex &index) const; void layoutItems(); void alignIconsToGrid(); QRect itemsBoundingRect() const; @@ -169,6 +178,7 @@ void updateScrollBar(); void updateScrollBarGeometry(); void updateTextShadows(const QColor &textColor); + void updateToolTip(const QModelIndex &index); QStyleOptionViewItemV4 viewOptions() const; private: @@ -203,7 +213,9 @@ QBasicTimer m_delayedLayoutTimer; QBasicTimer m_delayedRelayoutTimer; QBasicTimer m_delayedCacheClearTimer; + QBasicTimer m_toolTipShowTimer; ToolTipWidget *m_toolTipWidget; + QPointer m_popupView; }; #endif