Warning, file /office/calligra/libs/widgets/KoViewItemContextBar.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002 *
0003 * Copyright (C) 2008 Peter Penz <peter.penz19@gmail.com>
0004 * Copyright (C) 2011 Paul Mendez <paulestebanms@gmail.com>
0005 *
0006 * This library is free software; you can redistribute it and/or
0007 * modify it under the terms of the GNU Library General Public
0008 * License as published by the Free Software Foundation; either
0009 * version 2 of the License, or (at your option) any later version.
0010 *
0011 * This library is distributed in the hope that it will be useful,
0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014 * Library General Public License for more details.
0015 *
0016 * You should have received a copy of the GNU Library General Public License
0017 * along with this library; see the file COPYING.LIB.  If not, write to
0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019 * Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "KoViewItemContextBar.h"
0023 
0024 //Calligra headers
0025 #include "KoContextBarButton.h"
0026 #include <KoIcon.h>
0027 
0028 // KF5
0029 #include <klocalizedstring.h>
0030 
0031 //Qt Headers
0032 #include <QAbstractItemView>
0033 #include <QModelIndex>
0034 #include <QApplication>
0035 #include <QHBoxLayout>
0036 #include <QHoverEvent>
0037 
0038 /** Space between the item outer rect and the context bar */
0039 const int CONTEXTBAR_MARGIN = 4;
0040 const int MIN_BUTTON_WIDTH = 24;
0041 
0042 KoViewItemContextBar::KoViewItemContextBar(QAbstractItemView *parent)
0043     : QObject(parent)
0044     , m_view(parent)
0045     , m_enabled(true)
0046     , m_showToggleButton(true)
0047 {
0048     connect(parent, SIGNAL(entered(QModelIndex)),
0049             this, SLOT(slotEntered(QModelIndex)));
0050     connect(parent, SIGNAL(viewportEntered()),
0051             this, SLOT(slotViewportEntered()));
0052 
0053     m_ContextBar = new QWidget(m_view->viewport());
0054     m_ContextBar->hide();
0055     m_ToggleSelectionButton = new KoContextBarButton(koIconName("list-add"));
0056 
0057     m_Layout = new QHBoxLayout(m_ContextBar);
0058     m_Layout->setMargin(2);
0059     m_Layout->setSpacing(2);
0060     m_Layout->addWidget(m_ToggleSelectionButton);
0061 
0062     connect(m_ToggleSelectionButton, SIGNAL(clicked()),
0063             this, SLOT(setItemSelected()));
0064     // Hides context bar if item removed
0065     connect(m_view->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
0066             this, SLOT(slotRowsRemoved(QModelIndex,int,int)));
0067 
0068     connect(m_view->model(), SIGNAL(modelReset()), this, SLOT(slotModelReset()));
0069 
0070     m_ContextBar->installEventFilter(this);
0071     m_view->viewport()->installEventFilter(this);
0072     m_view->setMouseTracking(true);
0073 }
0074 
0075 bool KoViewItemContextBar::eventFilter(QObject *watched, QEvent *event)
0076 {
0077     if (watched == m_view->viewport()) {
0078         switch (event->type()) {
0079         case QEvent::Leave:
0080             if (m_ContextBar->isVisible()) {
0081                 m_ContextBar->hide();
0082             }
0083             break;
0084         default:
0085             break;
0086         }
0087     }
0088     return QObject::eventFilter(watched, event);
0089 }
0090 
0091 void KoViewItemContextBar::slotEntered(const QModelIndex &index)
0092 {
0093     const bool isSelectionCandidate = index.isValid() &&
0094             (QApplication::mouseButtons() == Qt::NoButton);
0095 
0096     if (!m_ContextBar || !m_enabled) {
0097         return;
0098     }
0099 
0100     m_ContextBar->hide();
0101     if (isSelectionCandidate) {
0102         updateHoverUi(index);
0103     }
0104     else {
0105         updateHoverUi(QModelIndex());
0106     }
0107 }
0108 
0109 void KoViewItemContextBar::updateHoverUi(const QModelIndex &index)
0110 {
0111     QModelIndex oldIndex = m_IndexUnderCursor;
0112     m_IndexUnderCursor = index;
0113     m_view->update(oldIndex);
0114 
0115     const bool isSelectionCandidate = index.isValid();
0116 
0117     m_ContextBar->hide();
0118     if (isSelectionCandidate) {
0119         updateToggleSelectionButton();
0120         const QRect rect = m_view->visualRect(m_IndexUnderCursor);
0121         showContextBar(rect);
0122         m_view->update(m_IndexUnderCursor);
0123     } else {
0124         m_ContextBar->hide();
0125     }
0126 }
0127 
0128 void KoViewItemContextBar::showContextBar(const QRect &rect)
0129 {
0130     // Center bar in FullContextBar mode, left align in
0131     // SelectionOnlyContextBar mode
0132     const int posX = 0;
0133     const int posY = CONTEXTBAR_MARGIN / 4;
0134     int numButtons = 0;
0135     m_ContextBar->move(rect.topLeft() + QPoint(posX, posY));
0136     //Hide buttons if item is too small
0137     int width = m_ToggleSelectionButton->width();
0138     if (!m_showToggleButton) {
0139         m_ToggleSelectionButton->setVisible(false);
0140         width = qMin(m_contextBarButtons.at(0)->width(), MIN_BUTTON_WIDTH);
0141     }
0142     for (int i=m_contextBarButtons.size()-1; i>=0; --i) {
0143         if ((rect.width() - 2 * CONTEXTBAR_MARGIN) > ((i + 1) * width)) {
0144             m_contextBarButtons.at(i)->setVisible(true);
0145             numButtons++;
0146             continue;
0147         }
0148         m_contextBarButtons.at(i)->setVisible(false);
0149     }
0150     m_ContextBar->adjustSize();
0151     if (numButtons > 0) {
0152         const int centerX = (rect.width() - m_ContextBar->rect().width()) / 2;
0153         m_ContextBar->move(rect.topLeft() + QPoint(centerX, posY));
0154     }
0155     m_ContextBar->show();
0156 }
0157 
0158 void KoViewItemContextBar::slotViewportEntered()
0159 {
0160     m_ContextBar->hide();
0161 }
0162 
0163 void KoViewItemContextBar::setItemSelected()
0164 {
0165     emit selectionChanged();
0166 
0167     if (m_IndexUnderCursor.isValid()) {
0168         QItemSelectionModel *selModel = m_view->selectionModel();
0169         if (!selModel->isSelected(m_IndexUnderCursor)) {
0170             selModel->select(m_IndexUnderCursor, QItemSelectionModel::Select);
0171         }
0172         else {
0173             selModel->select(m_IndexUnderCursor, QItemSelectionModel::Deselect);
0174         }
0175         selModel->setCurrentIndex(m_IndexUnderCursor, QItemSelectionModel::Current);
0176     }
0177     updateHoverUi(m_IndexUnderCursor);
0178 }
0179 
0180 void KoViewItemContextBar::slotRowsRemoved(const QModelIndex &parent, int start, int end)
0181 {
0182     Q_UNUSED(parent);
0183     Q_UNUSED(start);
0184     Q_UNUSED(end);
0185     if (m_ContextBar) {
0186         m_ContextBar->hide();
0187     }
0188 }
0189 
0190 void KoViewItemContextBar::updateToggleSelectionButton()
0191 {
0192     const bool isHoveredIndexSelected = m_view->selectionModel()->isSelected(m_IndexUnderCursor);
0193     const char *const iconName = (isHoveredIndexSelected ? koIconNameCStr("list-remove") : koIconNameCStr("list-add"));
0194 
0195     m_ToggleSelectionButton->setIcon(QIcon::fromTheme(QLatin1String(iconName)));
0196     m_ToggleSelectionButton->setToolTip(isHoveredIndexSelected ? i18n("deselect item") : i18n("select item"));
0197 }
0198 
0199 void KoViewItemContextBar::update()
0200 {
0201     // Check if the current index is still valid and then update the context bar
0202     if (m_view->model()->index(currentIndex().row(), currentIndex().column(), currentIndex().parent()).isValid()) {
0203         updateHoverUi(currentIndex());
0204     }
0205     else {
0206         updateHoverUi(QModelIndex());
0207     }
0208 }
0209 
0210 QToolButton * KoViewItemContextBar::addContextButton(const QString &text, const QString &iconName)
0211 {
0212     KoContextBarButton *newContexButton = new KoContextBarButton(iconName);
0213     newContexButton->setToolTip(text);
0214     m_Layout->addWidget(newContexButton);
0215     m_contextBarButtons.append(newContexButton);
0216     return newContexButton;
0217 }
0218 
0219 QModelIndex KoViewItemContextBar::currentIndex()
0220 {
0221     return m_IndexUnderCursor;
0222 }
0223 
0224 int KoViewItemContextBar::preferredWidth()
0225 {
0226     return ((m_contextBarButtons.count()+1)*m_ToggleSelectionButton->sizeHint().width() + 2*CONTEXTBAR_MARGIN);
0227 }
0228 
0229 void KoViewItemContextBar::setShowSelectionToggleButton(bool enabled)
0230 {
0231     m_showToggleButton = enabled;
0232 }
0233 
0234 void KoViewItemContextBar::reset()
0235 {
0236     if (m_ContextBar) {
0237         m_ContextBar->hide();
0238     }
0239 }
0240 
0241 void KoViewItemContextBar::slotModelReset()
0242 {
0243     // reset the model index so it does no longer point to suff no longer available.
0244     m_IndexUnderCursor = QModelIndex();
0245 }
0246 
0247 void KoViewItemContextBar::enableContextBar()
0248 {
0249     m_enabled = true;
0250 }
0251 
0252 void KoViewItemContextBar::disableContextBar()
0253 {
0254     m_enabled = false;
0255 }