From: Peter Penz Date: Sat, 26 Jan 2008 21:45:28 +0000 (+0000) Subject: Blend in a toggle button when hovering items. This allows selecting items without... X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/f6c7b90edf05a52fba6e2a06caa0247e909b43e8 Blend in a toggle button when hovering items. This allows selecting items without using the rubberband or Ctrl/Shift-keys in the single-click mode. Any feedback from users is highly welcome (I think people will either love or hate this feature, I'm really not sure -> it can be turned off too). svn path=/trunk/KDE/kdebase/apps/; revision=766901 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f11b62817..4d0d097dd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,8 @@ set(dolphinprivate_LIB_SRCS iconmanager.cpp ratingpainter.cpp renamedialog.cpp + selectiontoggle.cpp + selectionmanager.cpp viewproperties.cpp ) diff --git a/src/dolphin_generalsettings.kcfg b/src/dolphin_generalsettings.kcfg index 7bf41d030..6149480b3 100644 --- a/src/dolphin_generalsettings.kcfg +++ b/src/dolphin_generalsettings.kcfg @@ -31,6 +31,10 @@ false + + + true + diff --git a/src/dolphincolumnwidget.cpp b/src/dolphincolumnwidget.cpp index ae5f32fcf..8bf66b2c8 100644 --- a/src/dolphincolumnwidget.cpp +++ b/src/dolphincolumnwidget.cpp @@ -26,7 +26,9 @@ #include "dolphinsortfilterproxymodel.h" #include "dolphinsettings.h" #include "dolphin_columnmodesettings.h" +#include "dolphin_generalsettings.h" #include "draganddrophelper.h" +#include "selectionmanager.h" #include #include @@ -118,6 +120,13 @@ DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); setModel(m_proxyModel); + const bool useSelManager = KGlobalSettings::singleClick() && + DolphinSettings::instance().generalSettings()->showSelectionToggle(); + if (useSelManager) { + SelectionManager* selManager = new SelectionManager(this); + connect(selManager, SIGNAL(selectionChanged()), + this, SLOT(requestActivation())); + } new KMimeTypeResolver(this, m_dolphinModel); m_iconManager = new IconManager(this, m_proxyModel); m_iconManager->setShowPreview(m_view->m_controller->dolphinView()->showPreview()); @@ -304,12 +313,7 @@ void DolphinColumnWidget::paintEvent(QPaintEvent* event) void DolphinColumnWidget::mousePressEvent(QMouseEvent* event) { - m_view->m_controller->requestActivation(); - if (!m_active) { - m_view->requestActivation(this); - m_view->m_controller->triggerUrlChangeRequest(m_url); - } - + requestActivation(); QListView::mousePressEvent(event); } @@ -367,6 +371,16 @@ void DolphinColumnWidget::slotEntered(const QModelIndex& index) m_view->m_controller->emitItemEntered(item); } +void DolphinColumnWidget::requestActivation() +{ + m_view->m_controller->requestActivation(); + if (!m_active) { + m_view->requestActivation(this); + m_view->m_controller->triggerUrlChangeRequest(m_url); + selectionModel()->clear(); + } +} + void DolphinColumnWidget::activate() { setFocus(Qt::OtherFocusReason); diff --git a/src/dolphincolumnwidget.h b/src/dolphincolumnwidget.h index de14576e7..87c7ab577 100644 --- a/src/dolphincolumnwidget.h +++ b/src/dolphincolumnwidget.h @@ -117,6 +117,8 @@ private slots: void slotEntered(const QModelIndex& index); + void requestActivation(); + private: /** Used by DolphinColumnWidget::setActive(). */ void activate(); diff --git a/src/dolphindetailsview.cpp b/src/dolphindetailsview.cpp index c5852fa68..09645a489 100644 --- a/src/dolphindetailsview.cpp +++ b/src/dolphindetailsview.cpp @@ -25,9 +25,11 @@ #include "dolphinsettings.h" #include "dolphinsortfilterproxymodel.h" #include "draganddrophelper.h" +#include "selectionmanager.h" #include "viewproperties.h" #include "dolphin_detailsmodesettings.h" +#include "dolphin_generalsettings.h" #include #include @@ -94,6 +96,11 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, DolphinController* contr if (KGlobalSettings::singleClick()) { connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(triggerItem(const QModelIndex&))); + if (DolphinSettings::instance().generalSettings()->showSelectionToggle()) { + SelectionManager* selManager = new SelectionManager(this); + connect(selManager, SIGNAL(selectionChanged()), + this, SLOT(requestActivation())); + } } else { connect(this, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(triggerItem(const QModelIndex&))); @@ -508,6 +515,11 @@ void DolphinDetailsView::disableAutoResizing() m_autoResize = false; } +void DolphinDetailsView::requestActivation() +{ + m_controller->requestActivation(); +} + bool DolphinDetailsView::isZoomInPossible() const { DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings(); diff --git a/src/dolphindetailsview.h b/src/dolphindetailsview.h index a9201d8b3..316620a5a 100644 --- a/src/dolphindetailsview.h +++ b/src/dolphindetailsview.h @@ -130,6 +130,8 @@ private slots: */ void disableAutoResizing(); + void requestActivation(); + private: bool isZoomInPossible() const; bool isZoomOutPossible() const; diff --git a/src/dolphiniconsview.cpp b/src/dolphiniconsview.cpp index c867ce611..18d4accec 100644 --- a/src/dolphiniconsview.cpp +++ b/src/dolphiniconsview.cpp @@ -23,7 +23,9 @@ #include "dolphincontroller.h" #include "dolphinsettings.h" #include "dolphin_iconsmodesettings.h" +#include "dolphin_generalsettings.h" #include "draganddrophelper.h" +#include "selectionmanager.h" #include #include @@ -65,6 +67,11 @@ DolphinIconsView::DolphinIconsView(QWidget* parent, DolphinController* controlle if (KGlobalSettings::singleClick()) { connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(triggerItem(const QModelIndex&))); + if (DolphinSettings::instance().generalSettings()->showSelectionToggle()) { + SelectionManager* selManager = new SelectionManager(this); + connect(selManager, SIGNAL(selectionChanged()), + this, SLOT(requestActivation())); + } } else { connect(this, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(triggerItem(const QModelIndex&))); @@ -389,6 +396,11 @@ void DolphinIconsView::zoomOut() } } +void DolphinIconsView::requestActivation() +{ + m_controller->requestActivation(); +} + bool DolphinIconsView::isZoomInPossible() const { IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings(); diff --git a/src/dolphiniconsview.h b/src/dolphiniconsview.h index ade58e156..05b21a2b0 100644 --- a/src/dolphiniconsview.h +++ b/src/dolphiniconsview.h @@ -71,6 +71,7 @@ private slots: void slotAdditionalInfoChanged(); void zoomIn(); void zoomOut(); + void requestActivation(); private: bool isZoomInPossible() const; diff --git a/src/generalviewsettingspage.cpp b/src/generalviewsettingspage.cpp index b9fbc17be..ebf235f2a 100644 --- a/src/generalviewsettingspage.cpp +++ b/src/generalviewsettingspage.cpp @@ -47,7 +47,8 @@ GeneralViewSettingsPage::GeneralViewSettingsPage(DolphinMainWindow* mainWindow, m_globalProps(0), m_maxPreviewSize(0), m_spinBox(0), - m_useFileThumbnails(0) + m_useFileThumbnails(0), + m_showSelectionToggle(0) { const int spacing = KDialog::spacingHint(); const int margin = KDialog::marginHint(); @@ -87,6 +88,8 @@ GeneralViewSettingsPage::GeneralViewSettingsPage(DolphinMainWindow* mainWindow, previewBoxLayout->addWidget(vBox); previewBoxLayout->addWidget(m_useFileThumbnails); + m_showSelectionToggle = new QCheckBox(i18nc("option:check", "Show selection toggle"), this); + // Add a dummy widget with no restriction regarding // a vertical resizing. This assures that the dialog layout // is not stretched vertically. @@ -128,6 +131,8 @@ void GeneralViewSettingsPage::applySettings() m_useFileThumbnails->isChecked(), KConfigBase::Normal | KConfigBase::Global); globalConfig.sync(); + + settings->setShowSelectionToggle(m_showSelectionToggle->isChecked()); } void GeneralViewSettingsPage::restoreDefaults() @@ -174,6 +179,8 @@ void GeneralViewSettingsPage::loadSettings() const bool useFileThumbnails = globalConfig.readEntry("UseFileThumbnails", true); m_useFileThumbnails->setChecked(useFileThumbnails); + + m_showSelectionToggle->setChecked(settings->showSelectionToggle()); } #include "generalviewsettingspage.moc" diff --git a/src/generalviewsettingspage.h b/src/generalviewsettingspage.h index 5aad4be4f..c84335dc1 100644 --- a/src/generalviewsettingspage.h +++ b/src/generalviewsettingspage.h @@ -60,6 +60,7 @@ private: QSlider* m_maxPreviewSize; QSpinBox* m_spinBox; QCheckBox* m_useFileThumbnails; + QCheckBox* m_showSelectionToggle; }; #endif diff --git a/src/selectionmanager.cpp b/src/selectionmanager.cpp new file mode 100644 index 000000000..1f9d99b85 --- /dev/null +++ b/src/selectionmanager.cpp @@ -0,0 +1,132 @@ +/*************************************************************************** + * Copyright (C) 2008 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 "selectionmanager.h" + +#include "dolphinmodel.h" +#include "selectiontoggle.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +SelectionManager::SelectionManager(QAbstractItemView* parent) : + QObject(parent), + m_view(parent), + m_button(0), + m_item() +{ + connect(parent, SIGNAL(entered(const QModelIndex&)), + this, SLOT(slotEntered(const QModelIndex&))); + connect(parent, SIGNAL(viewportEntered()), + this, SLOT(slotViewportEntered())); + m_button = new SelectionToggle(m_view->viewport()); + m_button->setCheckable(true); + m_button->hide(); + connect(m_button, SIGNAL(clicked(bool)), + this, SLOT(setItemSelected(bool))); + connect(m_view->selectionModel(), SIGNAL(selectionChanged()), + this, SLOT(slotSelectionChanged())); +} + +SelectionManager::~SelectionManager() +{ +} + +void SelectionManager::slotEntered(const QModelIndex& index) +{ + m_button->hide(); + if (index.isValid() && (index.column() == DolphinModel::Name)) { + m_item = itemForIndex(index); + + const QRect rect = m_view->visualRect(index); + const int gap = 2; + const int x = rect.right() - m_button->width() - gap; + int y = rect.top(); + if (rect.height() <= m_button->height() * 2) { + // center the button vertically + y += (rect.height() - m_button->height()) / 2; + } else { + y += gap; + } + + m_button->move(QPoint(x, y)); + + QItemSelectionModel* selModel = m_view->selectionModel(); + m_button->setChecked(selModel->isSelected(index)); + m_button->show(); + } else { + m_item = KFileItem(); + } +} + +void SelectionManager::slotViewportEntered() +{ + m_button->hide(); + m_item = KFileItem(); +} + +void SelectionManager::slotSelectionChanged() +{ + const QModelIndex index = indexForItem(m_item); + if (index.isValid()) { + QItemSelectionModel* selModel = m_view->selectionModel(); + m_button->setChecked(selModel->isSelected(index)); + } +} + +void SelectionManager::setItemSelected(bool selected) +{ + emit selectionChanged(); + Q_ASSERT(!m_item.isNull()); + + const QModelIndex index = indexForItem(m_item); + if (index.isValid()) { + QItemSelectionModel* selModel = m_view->selectionModel(); + if (selected) { + selModel->select(index, QItemSelectionModel::Select); + } else { + selModel->select(index, QItemSelectionModel::Deselect); + } + } +} + +KFileItem SelectionManager::itemForIndex(const QModelIndex& index) const +{ + QAbstractProxyModel* proxyModel = static_cast(m_view->model()); + KDirModel* dirModel = static_cast(proxyModel->sourceModel()); + const QModelIndex dirIndex = proxyModel->mapToSource(index); + return dirModel->itemForIndex(dirIndex); +} + +const QModelIndex SelectionManager::indexForItem(const KFileItem& item) const +{ + QAbstractProxyModel* proxyModel = static_cast(m_view->model()); + KDirModel* dirModel = static_cast(proxyModel->sourceModel()); + const QModelIndex dirIndex = dirModel->indexForItem(item); + return proxyModel->mapFromSource(dirIndex); +} + +#include "selectionmanager.moc" diff --git a/src/selectionmanager.h b/src/selectionmanager.h new file mode 100644 index 000000000..1bf4f8b8c --- /dev/null +++ b/src/selectionmanager.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2008 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 SELECTIONMANAGER_H +#define SELECTIONMANAGER_H + +#include + +#include + +class DolphinSortFilterProxyModel; +class QAbstractItemView; +class QModelIndex; +class QAbstractButton; + +/** + * @brief Allows to select and deselect items for the single-click mode. + * + * Whenever an item is hovered by the mouse, a toggle button is shown + * which allows to select/deselect the current item. + */ +class SelectionManager : public QObject +{ + Q_OBJECT + +public: + SelectionManager(QAbstractItemView* parent); + virtual ~SelectionManager(); + +signals: + /** Is emitted if the selection has been changed by the toggle button. */ + void selectionChanged(); + +private slots: + void slotEntered(const QModelIndex& index); + void slotViewportEntered(); + void slotSelectionChanged(); + void setItemSelected(bool selected); + +private: + KFileItem itemForIndex(const QModelIndex& index) const; + const QModelIndex indexForItem(const KFileItem& item) const; + +private: + QAbstractItemView* m_view; + QAbstractButton* m_button; + KFileItem m_item; +}; + +#endif diff --git a/src/selectiontoggle.cpp b/src/selectiontoggle.cpp new file mode 100644 index 000000000..244f51583 --- /dev/null +++ b/src/selectiontoggle.cpp @@ -0,0 +1,113 @@ +/*************************************************************************** + * Copyright (C) 2008 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 "selectiontoggle.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include + +SelectionToggle::SelectionToggle(QWidget* parent) : + QAbstractButton(parent), + m_showIcon(false), + m_isHovered(false), + m_icon(), + m_timer(0) +{ + parent->installEventFilter(this); + resize(sizeHint()); + m_icon = KIconLoader::global()->loadIcon("dialog-ok", + KIconLoader::NoGroup, + KIconLoader::SizeSmall); + m_timer = new QTimer(this); + connect(m_timer, SIGNAL(timeout()), + this, SLOT(showIcon())); +} + +SelectionToggle::~SelectionToggle() +{ +} + +QSize SelectionToggle::sizeHint() const +{ + return QSize(16, 16); +} + +void SelectionToggle::setVisible(bool visible) +{ + QAbstractButton::setVisible(visible); + if (visible) { + m_timer->start(1000); + } else { + m_timer->stop(); + m_showIcon = false; + } +} + +bool SelectionToggle::eventFilter(QObject* obj, QEvent* event) +{ + if ((obj == parent()) && (event->type() == QEvent::Leave)) { + hide(); + } + return QAbstractButton::eventFilter(obj, event); +} + +void SelectionToggle::enterEvent(QEvent* event) +{ + QAbstractButton::enterEvent(event); + m_isHovered = true; + m_showIcon = true; + update(); +} + +void SelectionToggle::leaveEvent(QEvent* event) +{ + QAbstractButton::leaveEvent(event); + m_isHovered = false; + update(); +} + +void SelectionToggle::paintEvent(QPaintEvent* event) +{ + QPainter painter(this); + painter.setClipRect(event->rect()); + + if (m_isHovered) { + KIconEffect iconEffect; + QPixmap activeIcon = iconEffect.apply(m_icon, KIconLoader::Desktop, KIconLoader::ActiveState); + painter.drawPixmap(0, 0, activeIcon); + } else if (m_showIcon) { + painter.drawPixmap(0, 0, m_icon); + } +} + +void SelectionToggle::showIcon() +{ + m_showIcon = true; + update(); +} + +#include "selectiontoggle.moc" diff --git a/src/selectiontoggle.h b/src/selectiontoggle.h new file mode 100644 index 000000000..5815c5dae --- /dev/null +++ b/src/selectiontoggle.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2008 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 SELECTIONTOGGLE_H +#define SELECTIONTOGGLE_H + +#include +#include +#include + +/** + * @brief Toggle button for changing the selection of an hovered item. + * @see SelectionManager + */ +class SelectionToggle : public QAbstractButton +{ + Q_OBJECT + +public: + explicit SelectionToggle(QWidget* parent); + virtual ~SelectionToggle(); + virtual QSize sizeHint() const; + +public slots: + virtual void setVisible(bool visible); + +protected: + virtual bool eventFilter(QObject* obj, QEvent* event); + virtual void enterEvent(QEvent* event); + virtual void leaveEvent(QEvent* event); + virtual void paintEvent(QPaintEvent* event); + +private slots: + void showIcon(); + +private: + bool m_showIcon; + bool m_isHovered; + QPixmap m_icon; + QTimer* m_timer; +}; + +#endif