File indexing completed on 2024-03-24 15:27:43
0001 /* This file is part of the KDE libraries 0002 Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License version 2 as published by the Free Software Foundation. 0007 0008 This library is distributed in the hope that it will be useful, 0009 but WITHOUT ANY WARRANTY; without even the implied warranty of 0010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0011 Library General Public License for more details. 0012 0013 You should have received a copy of the GNU Library General Public License 0014 along with this library; see the file COPYING.LIB. If not, write to 0015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0016 Boston, MA 02110-1301, USA. 0017 */ 0018 0019 #include "klistwidget.h" 0020 0021 #include <kglobalsettings.h> 0022 #include <kdebug.h> 0023 0024 #include <QTimer> 0025 #include <QKeyEvent> 0026 #include <QApplication> 0027 0028 class Q_DECL_HIDDEN KListWidget::KListWidgetPrivate 0029 { 0030 public: 0031 KListWidgetPrivate(KListWidget *q) 0032 : q(q), 0033 m_pCurrentItem(nullptr), 0034 m_eventPos() 0035 { 0036 } 0037 0038 void _k_slotItemEntered(QListWidgetItem *); 0039 void _k_slotOnViewport(); 0040 void _k_slotSettingsChanged(int); 0041 void _k_slotAutoSelect(); 0042 void _k_slotEmitExecute(QListWidgetItem *item); 0043 0044 KListWidget *q; 0045 bool m_bUseSingle : 1; 0046 bool m_bChangeCursorOverItem : 1; 0047 0048 QListWidgetItem *m_pCurrentItem; 0049 QTimer *m_pAutoSelect; 0050 int m_autoSelectDelay; 0051 QPoint m_eventPos; 0052 }; 0053 0054 KListWidget::KListWidget(QWidget *parent) 0055 : QListWidget(parent), d(new KListWidgetPrivate(this)) 0056 { 0057 connect(this, SIGNAL(viewportEntered()), 0058 this, SLOT(_k_slotOnViewport())); 0059 connect(this, SIGNAL(itemEntered(QListWidgetItem*)), 0060 this, SLOT(_k_slotItemEntered(QListWidgetItem*))); 0061 d->_k_slotSettingsChanged(KGlobalSettings::SETTINGS_MOUSE); 0062 connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)), SLOT(_k_slotSettingsChanged(int))); 0063 0064 d->m_pAutoSelect = new QTimer(this); 0065 connect(d->m_pAutoSelect, SIGNAL(timeout()), 0066 this, SLOT(_k_slotAutoSelect())); 0067 } 0068 0069 KListWidget::~KListWidget() 0070 { 0071 delete d; 0072 } 0073 0074 void KListWidget::KListWidgetPrivate::_k_slotItemEntered(QListWidgetItem *item) 0075 { 0076 if (item && m_bChangeCursorOverItem && m_bUseSingle) { 0077 q->viewport()->setCursor(QCursor(Qt::OpenHandCursor)); 0078 } 0079 0080 if (item && (m_autoSelectDelay > -1) && m_bUseSingle) { 0081 m_pAutoSelect->setSingleShot(true); 0082 m_pAutoSelect->start(m_autoSelectDelay); 0083 m_pCurrentItem = item; 0084 } 0085 } 0086 0087 void KListWidget::KListWidgetPrivate::_k_slotOnViewport() 0088 { 0089 if (m_bChangeCursorOverItem) { 0090 q->viewport()->unsetCursor(); 0091 } 0092 0093 m_pAutoSelect->stop(); 0094 m_pCurrentItem = nullptr; 0095 } 0096 0097 void KListWidget::KListWidgetPrivate::_k_slotSettingsChanged(int category) 0098 { 0099 if (category != KGlobalSettings::SETTINGS_MOUSE) { 0100 return; 0101 } 0102 m_bUseSingle = q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick); 0103 0104 q->disconnect(q, SIGNAL(itemClicked(QListWidgetItem*))); 0105 q->disconnect(q, SIGNAL(itemDoubleClicked(QListWidgetItem*))); 0106 0107 if (m_bUseSingle) { 0108 q->connect(q, SIGNAL(itemClicked(QListWidgetItem*)), 0109 SLOT(_k_slotEmitExecute(QListWidgetItem*))); 0110 } else { 0111 q->connect(q, SIGNAL(itemDoubleClicked(QListWidgetItem*)), 0112 SLOT(_k_slotEmitExecute(QListWidgetItem*))); 0113 } 0114 0115 m_bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon(); 0116 m_autoSelectDelay = KGlobalSettings::autoSelectDelay(); 0117 0118 if (!m_bUseSingle || !m_bChangeCursorOverItem) { 0119 q->viewport()->unsetCursor(); 0120 } 0121 } 0122 0123 void KListWidget::KListWidgetPrivate::_k_slotAutoSelect() 0124 { 0125 // check that the item still exists 0126 if (q->row(m_pCurrentItem) == -1) { 0127 return; 0128 } 0129 0130 //Give this widget the keyboard focus. 0131 if (!q->hasFocus()) { 0132 q->setFocus(); 0133 } 0134 0135 Qt::KeyboardModifiers keybstate = QApplication::keyboardModifiers(); 0136 0137 QListWidgetItem *previousItem = q->currentItem(); 0138 q->setCurrentItem(m_pCurrentItem); 0139 0140 if (m_pCurrentItem) { 0141 //Shift pressed? 0142 if ((keybstate & Qt::ShiftModifier)) { 0143 bool block = q->signalsBlocked(); 0144 q->blockSignals(true); 0145 0146 //No Ctrl? Then clear before! 0147 if (!(keybstate & Qt::ControlModifier)) { 0148 q->clearSelection(); 0149 } 0150 0151 bool select = !m_pCurrentItem->isSelected(); 0152 bool update = q->viewport()->updatesEnabled(); 0153 q->viewport()->setUpdatesEnabled(false); 0154 0155 bool down = q->row(previousItem) < q->row(m_pCurrentItem); 0156 QListWidgetItem *it = down ? previousItem : m_pCurrentItem; 0157 0158 for (int i = q->row(it); i < q->count(); i++) { 0159 if (down && q->item(i) == m_pCurrentItem) { 0160 m_pCurrentItem->setSelected(select); 0161 break; 0162 } 0163 0164 if (!down && q->item(i) == previousItem) { 0165 previousItem->setSelected(select); 0166 break; 0167 } 0168 it->setSelected(select); 0169 } 0170 0171 q->blockSignals(block); 0172 q->viewport()->setUpdatesEnabled(update); 0173 0174 emit q->itemSelectionChanged(); 0175 0176 if (q->selectionMode() == QAbstractItemView::SingleSelection) { 0177 q->emit itemSelectionChanged(); 0178 } 0179 } else if ((keybstate & Qt::ControlModifier)) { 0180 m_pCurrentItem->setSelected(!m_pCurrentItem->isSelected()); 0181 } else { 0182 bool block = q->signalsBlocked(); 0183 q->blockSignals(true); 0184 0185 if (!m_pCurrentItem->isSelected()) { 0186 q->clearSelection(); 0187 } 0188 0189 q->blockSignals(block); 0190 0191 m_pCurrentItem->setSelected(true); 0192 } 0193 } else { 0194 kDebug() << "That's not supposed to happen!!!!"; 0195 } 0196 } 0197 0198 void KListWidget::KListWidgetPrivate::_k_slotEmitExecute(QListWidgetItem *item) 0199 { 0200 Qt::KeyboardModifiers keybstate = QApplication::keyboardModifiers(); 0201 0202 m_pAutoSelect->stop(); 0203 0204 //Don't emit executed if in SC mode and Shift or Ctrl are pressed 0205 if (!(m_bUseSingle && ((keybstate & Qt::ShiftModifier) || (keybstate & Qt::ControlModifier)))) { 0206 emit q->executed(item); 0207 if (!m_eventPos.isNull()) { 0208 emit q->executed(item, m_eventPos); 0209 } 0210 } 0211 } 0212 0213 // 0214 // 2000-16-01 Espen Sand 0215 // This widget is used in dialogs. It should ignore 0216 // F1 (and combinations) and Escape since these are used 0217 // to start help or close the dialog. This functionality 0218 // should be done in QListView but it is not (at least now) 0219 // 0220 void KListWidget::keyPressEvent(QKeyEvent *e) 0221 { 0222 if (e->key() == Qt::Key_Escape) { 0223 e->ignore(); 0224 } else if (e->key() == Qt::Key_F1) { 0225 e->ignore(); 0226 } else { 0227 QListWidget::keyPressEvent(e); 0228 } 0229 } 0230 0231 void KListWidget::focusOutEvent(QFocusEvent *fe) 0232 { 0233 d->m_pAutoSelect->stop(); 0234 0235 QListWidget::focusOutEvent(fe); 0236 } 0237 0238 void KListWidget::leaveEvent(QEvent *e) 0239 { 0240 d->m_pAutoSelect->stop(); 0241 0242 QListWidget::leaveEvent(e); 0243 } 0244 0245 void KListWidget::mousePressEvent(QMouseEvent *e) 0246 { 0247 if ((selectionMode() == QAbstractItemView::ExtendedSelection) && (e->modifiers() & Qt::ShiftModifier) && !(e->modifiers() & Qt::ControlModifier)) { 0248 bool block = signalsBlocked(); 0249 blockSignals(true); 0250 0251 clearSelection(); 0252 0253 blockSignals(block); 0254 } 0255 0256 QListWidget::mousePressEvent(e); 0257 } 0258 0259 void KListWidget::mouseDoubleClickEvent(QMouseEvent *e) 0260 { 0261 QPoint oldPos = d->m_eventPos; 0262 d->m_eventPos = e->globalPos(); 0263 QListWidget::mouseDoubleClickEvent(e); 0264 d->m_eventPos = oldPos; 0265 } 0266 0267 void KListWidget::mouseReleaseEvent(QMouseEvent *e) 0268 { 0269 QPoint oldPos = d->m_eventPos; 0270 d->m_eventPos = e->globalPos(); 0271 QListWidget::mouseReleaseEvent(e); 0272 d->m_eventPos = oldPos; 0273 } 0274 0275 #include "moc_klistwidget.cpp"