/* * Copyright © 2009, 2010 Fredrik Höglund * Copyright © 2009 Bruno Bigras * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "actionoverlay.h" #include "asyncfiletester.h" #include "iconview.h" #include #include #include #include #include ActionIcon::ActionIcon(QGraphicsItem* parent) : QGraphicsWidget(parent), m_pressed(false), m_sunken(false) { setAcceptHoverEvents(true); setCacheMode(DeviceCoordinateCache); m_icon = new Plasma::Svg(this); m_icon->setImagePath("widgets/action-overlays"); m_icon->setContainsMultipleImages(true); setMinimumSize(m_icon->elementSize("add-normal")); setMaximumSize(minimumSize()); show(); } void ActionIcon::setElement(const QString &element) { m_element = element; } void ActionIcon::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(option) Q_UNUSED(widget) QString element = m_element; if (m_sunken) { element += "-pressed"; } else if (isUnderMouse()) { element += "-hover"; } else { element += "-normal"; } m_icon->paint(painter, rect(), element); } void ActionIcon::mousePressEvent(QGraphicsSceneMouseEvent* event) { Q_UNUSED(event) m_pressed = true; m_sunken = true; update(); } void ActionIcon::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED(event) m_pressed = false; m_sunken = false; if (isUnderMouse()) { emit clicked(); } update(); } void ActionIcon::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED(event) if (m_sunken != isUnderMouse()) { m_sunken = isUnderMouse(); update(); } } void ActionIcon::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { Q_UNUSED(event) emit iconHoverEnter(); update(); } void ActionIcon::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { Q_UNUSED(event) emit iconHoverLeave(); update(); } // -------------------------------------------------------- ActionOverlay::ActionOverlay(AbstractItemView* parent) : QGraphicsWidget(parent) { m_toggleButton = new ActionIcon(this); m_openButton = new ActionIcon(this); m_openButton->setElement("open"); m_showFolderButton = true; m_showSelectionButton = true; m_layout = new QGraphicsGridLayout(this); m_layout->setContentsMargins(4, 4, 4, 4); m_layout->setSpacing(1); m_layout->addItem(m_toggleButton, 0, 0); m_layout->addItem(m_openButton, 1, 0); connect(parentWidget(), SIGNAL(entered(QModelIndex)), this, SLOT(entered(QModelIndex))); connect(parentWidget(), SIGNAL(left(QModelIndex)), this, SLOT(left(QModelIndex))); connect(parentWidget(), SIGNAL(modelChanged()), this, SLOT(modelChanged())); connect(m_toggleButton, SIGNAL(clicked()), this, SLOT(toggleSelection())); connect(m_openButton, SIGNAL(clicked()), this, SLOT(openPopup())); m_hideActionOverlayIconTimer = new QTimer(this); connect(m_hideActionOverlayIconTimer, SIGNAL(timeout()), this, SLOT(timeout())); connect(m_toggleButton, SIGNAL(iconHoverEnter()), m_hideActionOverlayIconTimer, SLOT(stop())); connect(m_toggleButton, SIGNAL(iconHoverLeave()), m_hideActionOverlayIconTimer, SLOT(start())); connect(m_openButton, SIGNAL(iconHoverEnter()), m_hideActionOverlayIconTimer, SLOT(stop())); connect(m_openButton, SIGNAL(iconHoverLeave()), m_hideActionOverlayIconTimer, SLOT(start())); connect(parent->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(close())); m_hideActionOverlayIconTimer->setInterval(500); m_hideActionOverlayIconTimer->setSingleShot(true); fadeIn = Plasma::Animator::create(Plasma::Animator::FadeAnimation, this); fadeIn->setProperty("startOpacity", 0); fadeIn->setProperty("targetOpacity", 1); fadeIn->setTargetWidget(this); fadeOut = Plasma::Animator::create(Plasma::Animator::FadeAnimation, this); fadeOut->setProperty("startOpacity", 1); fadeOut->setProperty("targetOpacity", 0); fadeOut->setTargetWidget(this); connect(fadeOut, SIGNAL(finished()), SLOT(close())); hide(); } void ActionOverlay::toggleSelection() { AbstractItemView *view = static_cast(parentWidget()); QItemSelectionModel *m_selectionModel = view->selectionModel(); if (m_hoverIndex.isValid()) { const QModelIndex oldCurrent = m_selectionModel->currentIndex(); m_selectionModel->select(m_hoverIndex, QItemSelectionModel::Toggle); m_selectionModel->setCurrentIndex(m_hoverIndex, QItemSelectionModel::NoUpdate); m_toggleButton->setElement(m_selectionModel->isSelected(m_hoverIndex) ? "remove" : "add"); view->markAreaDirty(view->visualRect(m_hoverIndex)); if (oldCurrent.isValid() && oldCurrent != m_hoverIndex) { view->markAreaDirty(view->visualRect(oldCurrent)); } } } void ActionOverlay::openPopup() { if (IconView *view = qobject_cast(parentWidget())) { view->openPopup(m_hoverIndex); } } QPersistentModelIndex ActionOverlay::hoverIndex() { return m_hoverIndex; } void ActionOverlay::entered(const QModelIndex &index) { m_hideActionOverlayIconTimer->stop(); if (index.isValid()) { AbstractItemView *view = static_cast(parentWidget()); QItemSelectionModel *m_selectionModel = view->selectionModel(); m_toggleButton->setElement(m_selectionModel->isSelected(index) ? "remove" : "add"); setPos(view->mapFromViewport(view->visualRect(index)).topLeft()); show(); if (m_hoverIndex != index) { m_toggleButton->update(); fadeOut->stop(); fadeIn->start(); } m_hoverIndex = index; IconView *iview = qobject_cast(view); if (iview && iview->clickToViewFolders()) { AsyncFileTester::checkIfFolder(index, this, "checkIfFolderResult"); } } } void ActionOverlay::checkIfFolderResult(const QModelIndex &index, bool isFolder) { if (index == m_hoverIndex) { m_openButton->setVisible(isFolder); } } void ActionOverlay::left(const QModelIndex &index) { Q_UNUSED(index); if (!m_hideActionOverlayIconTimer->isActive()) { m_hideActionOverlayIconTimer->start(); } } void ActionOverlay::timeout() { // allow the animation to restart after hiding the ActionOverlayIcon even if m_hoverIndex didn't change m_hoverIndex = QPersistentModelIndex(); if (isVisible() && (fadeOut->state() != QAbstractAnimation::Running)) { fadeIn->stop(); fadeOut->start(); } } void ActionOverlay::forceHide(HideHint hint) { m_hideActionOverlayIconTimer->stop(); if (hint == FadeOut) { timeout(); } else { hide(); } } void ActionOverlay::rowsRemoved(const QModelIndex & parent, int start, int end) { Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); if (!m_hoverIndex.isValid()) { hide(); } } void ActionOverlay::modelChanged() { AbstractItemView *view = static_cast(parentWidget()); QAbstractItemModel *mod = view->model(); connect(mod, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(rowsRemoved(QModelIndex,int,int))); } void ActionOverlay::setShowFolderButton(bool show) { if (m_showFolderButton != show) { m_showFolderButton = show; toggleShowActionButton(show, m_openButton, 1); } } void ActionOverlay::setShowSelectionButton(bool show) { if (m_showSelectionButton!= show) { m_showSelectionButton = show; toggleShowActionButton(show, m_toggleButton, 0); } } bool ActionOverlay::showFolderButton() const { return m_showFolderButton; } bool ActionOverlay::showSelectionButton() const { return m_showSelectionButton; } QSizeF ActionOverlay::iconSize() const { return m_openButton->geometry().size(); } void ActionOverlay::toggleShowActionButton(bool show, ActionIcon* button, unsigned int pos) { if (show && m_layout->itemAt(pos, 0) != button) { m_layout->addItem(button, pos, 0); button->show(); } else if (m_layout->itemAt(pos, 0) == button) { button->hide(); m_layout->removeItem(button); } }