File indexing completed on 2024-05-12 17:22:02
0001 /* 0002 SPDX-FileCopyrightText: 2009 Csaba Karai <cskarai@freemail.hu> 0003 SPDX-FileCopyrightText: 2009-2022 Krusader Krew <https://krusader.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "krmousehandler.h" 0009 #include "../defaults.h" 0010 #include "../krglobal.h" 0011 #include "krselectionmode.h" 0012 #include "krview.h" 0013 #include "krviewitem.h" 0014 0015 // QtCore 0016 #include <QStandardPaths> 0017 // QtWidgets 0018 #include <QApplication> 0019 #include <QStyle> 0020 0021 #include <KConfigCore/KSharedConfig> 0022 #include <KCoreAddons/KUrlMimeData> 0023 0024 #define CANCEL_TWO_CLICK_RENAME \ 0025 { \ 0026 _singleClicked = false; \ 0027 _renameTimer.stop(); \ 0028 } 0029 0030 KrMouseHandler::KrMouseHandler(KrView *view, int contextMenuShift) 0031 : _view(view) 0032 , _rightClickedItem(nullptr) 0033 , _contextMenuShift(contextMenuShift) 0034 , _singleClicked(false) 0035 , _dragStartPos(-1, -1) 0036 , _emptyContextMenu(false) 0037 { 0038 KConfigGroup grpSvr(krConfig, "Look&Feel"); 0039 // decide on single click/double click selection 0040 bool singleClickTmp = QApplication::style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick); 0041 _singleClick = grpSvr.readEntry("Single Click Selects", _SingleClickSelects) && singleClickTmp; 0042 connect(&_contextMenuTimer, &QTimer::timeout, this, &KrMouseHandler::showContextMenu); 0043 connect(&_renameTimer, &QTimer::timeout, this, &KrMouseHandler::renameCurrentItem); 0044 } 0045 0046 bool KrMouseHandler::mousePressEvent(QMouseEvent *e) 0047 { 0048 _rightClickedItem = _clickedItem = nullptr; 0049 KrViewItem *item = _view->getKrViewItemAt(e->pos()); 0050 KrSelectionMode *mode = KrSelectionMode::getSelectionHandler(); 0051 0052 if (!_view->isFocused()) 0053 _view->op()->emitNeedFocus(); 0054 if (e->button() == Qt::LeftButton) { 0055 _dragStartPos = e->pos(); 0056 if (e->modifiers() == Qt::NoModifier) { 0057 if (item) { 0058 if (mode->leftButtonSelects()) { 0059 if (mode->leftButtonPreservesSelection()) 0060 item->setSelected(!item->isSelected()); 0061 else { 0062 if (item->isSelected()) 0063 _clickedItem = item; 0064 else { 0065 // clear the current selection 0066 _view->unselectAll(); 0067 item->setSelected(true); 0068 } 0069 } 0070 } 0071 _view->setCurrentKrViewItem(item); 0072 } else { 0073 // empty space under items clicked 0074 if (mode->leftButtonSelects() && !mode->leftButtonPreservesSelection()) { 0075 // clear the current selection 0076 _view->unselectAll(); 0077 } 0078 } 0079 e->accept(); 0080 return true; 0081 } else if (e->modifiers() == Qt::ControlModifier) { 0082 if (item && (mode->shiftCtrlLeftButtonSelects() || mode->leftButtonSelects())) { 0083 // get current selected item names 0084 _selectedItemNames.clear(); 0085 _view->getSelectedItems(&_selectedItemNames, false); 0086 0087 item->setSelected(!item->isSelected()); 0088 0089 // select also the focused item if there are no other selected items 0090 KrViewItem *previousItem = _view->getCurrentKrViewItem(); 0091 if (previousItem->name() != ".." && _selectedItemNames.empty()) { 0092 previousItem->setSelected(true); 0093 } 0094 } 0095 if (item) { 0096 _view->setCurrentKrViewItem(item); 0097 } 0098 e->accept(); 0099 return true; 0100 } else if (e->modifiers() == Qt::ShiftModifier) { 0101 if (item && (mode->shiftCtrlLeftButtonSelects() || mode->leftButtonSelects())) { 0102 KrViewItem *current = _view->getCurrentKrViewItem(); 0103 if (current != nullptr) 0104 _view->selectRegion(item, current, true); 0105 } 0106 if (item) 0107 _view->setCurrentKrViewItem(item); 0108 e->accept(); 0109 return true; 0110 } 0111 } 0112 if (e->button() == Qt::RightButton) { 0113 // dragStartPos = e->pos(); 0114 if (e->modifiers() == Qt::NoModifier) { 0115 if (item) { 0116 if (mode->rightButtonSelects()) { 0117 if (mode->rightButtonPreservesSelection()) { 0118 if (mode->showContextMenu() >= 0) { 0119 _rightClickSelects = !item->isSelected(); 0120 _rightClickedItem = item; 0121 } 0122 item->setSelected(!item->isSelected()); 0123 } else { 0124 if (item->isSelected()) { 0125 _clickedItem = item; 0126 } else { 0127 // clear the current selection 0128 _view->unselectAll(); 0129 item->setSelected(true); 0130 } 0131 } 0132 } 0133 _view->setCurrentKrViewItem(item); 0134 } 0135 handleContextMenu(item, e->globalPos()); 0136 e->accept(); 0137 return true; 0138 } else if (e->modifiers() == Qt::ControlModifier) { 0139 if (item && (mode->shiftCtrlRightButtonSelects() || mode->rightButtonSelects())) { 0140 item->setSelected(!item->isSelected()); 0141 } 0142 if (item) 0143 _view->setCurrentKrViewItem(item); 0144 e->accept(); 0145 return true; 0146 } else if (e->modifiers() == Qt::ShiftModifier) { 0147 if (item && (mode->shiftCtrlRightButtonSelects() || mode->rightButtonSelects())) { 0148 KrViewItem *current = _view->getCurrentKrViewItem(); 0149 if (current != nullptr) 0150 _view->selectRegion(item, current, true); 0151 } 0152 if (item) 0153 _view->setCurrentKrViewItem(item); 0154 e->accept(); 0155 return true; 0156 } 0157 } 0158 if (e->button() == Qt::ForwardButton) { 0159 _view->op()->emitGoForward(); 0160 return true; 0161 } 0162 if (e->button() == Qt::BackButton) { 0163 _view->op()->emitGoBack(); 0164 return true; 0165 } 0166 return false; 0167 } 0168 0169 bool KrMouseHandler::mouseReleaseEvent(QMouseEvent *e) 0170 { 0171 if (e->button() == Qt::LeftButton) 0172 _dragStartPos = QPoint(-1, -1); 0173 0174 KrViewItem *item = _view->getKrViewItemAt(e->pos()); 0175 KrSelectionMode *mode = KrSelectionMode::getSelectionHandler(); 0176 0177 if (item && item == _clickedItem) { 0178 if (((e->button() == Qt::LeftButton) && (e->modifiers() == Qt::NoModifier) && (mode->leftButtonSelects()) && !(mode->leftButtonPreservesSelection())) 0179 || ((e->button() == Qt::RightButton) && (e->modifiers() == Qt::NoModifier) && (mode->rightButtonSelects()) 0180 && !(mode->rightButtonPreservesSelection()))) { 0181 // clear the current selection 0182 _view->unselectAll(); 0183 item->setSelected(true); 0184 } 0185 } 0186 0187 if (mode->resetSelectionItems()) { 0188 bool leftButtonClicked = (e->button() == Qt::LeftButton) && (e->modifiers() == Qt::NoModifier); 0189 bool rightButtonClicked = (e->button() == Qt::RightButton) && (e->modifiers() == Qt::NoModifier); 0190 0191 bool leftTriggerCondition = !mode->leftButtonSelects() && mode->shiftCtrlLeftButtonSelects(); 0192 bool rightTriggerCondition = !mode->rightButtonSelects() && mode->shiftCtrlRightButtonSelects(); 0193 0194 if ((leftButtonClicked && leftTriggerCondition) || (rightButtonClicked && rightTriggerCondition)) { 0195 // clear the current selection 0196 _view->unselectAll(); 0197 } 0198 } 0199 0200 if (e->button() == Qt::RightButton) { 0201 _rightClickedItem = nullptr; 0202 _contextMenuTimer.stop(); 0203 } 0204 if (_singleClick && e->button() == Qt::LeftButton && e->modifiers() == Qt::NoModifier) { 0205 CANCEL_TWO_CLICK_RENAME; 0206 e->accept(); 0207 if (item == nullptr) 0208 return true; 0209 QString tmp = item->name(); 0210 _view->op()->emitExecuted(tmp); 0211 return true; 0212 } else if (!_singleClick && e->button() == Qt::LeftButton) { 0213 if (item && e->modifiers() == Qt::NoModifier) { 0214 if (_singleClicked && !_renameTimer.isActive() && _singleClickedItem == item) { 0215 KSharedConfigPtr config = KSharedConfig::openConfig(); 0216 KConfigGroup group(krConfig, "KDE"); 0217 int doubleClickInterval = group.readEntry("DoubleClickInterval", 400); 0218 0219 int msecsFromLastClick = _singleClickTime.msecsTo(QTime::currentTime()); 0220 0221 if (msecsFromLastClick > doubleClickInterval && msecsFromLastClick < 5 * doubleClickInterval) { 0222 _singleClicked = false; 0223 _renameTimer.setSingleShot(true); 0224 _renameTimer.start(doubleClickInterval); 0225 return true; 0226 } 0227 } 0228 0229 CANCEL_TWO_CLICK_RENAME; 0230 _singleClicked = true; 0231 _singleClickedItem = item; 0232 _singleClickTime = QTime::currentTime(); 0233 0234 return true; 0235 } 0236 } 0237 0238 CANCEL_TWO_CLICK_RENAME; 0239 0240 if (e->button() == Qt::MidButton && item != nullptr) { 0241 e->accept(); 0242 if (item == nullptr) 0243 return true; 0244 _view->op()->emitMiddleButtonClicked(item); 0245 return true; 0246 } 0247 return false; 0248 } 0249 0250 bool KrMouseHandler::mouseDoubleClickEvent(QMouseEvent *e) 0251 { 0252 CANCEL_TWO_CLICK_RENAME; 0253 0254 KrViewItem *item = _view->getKrViewItemAt(e->pos()); 0255 if (_singleClick) 0256 return false; 0257 if (e->button() == Qt::LeftButton && item != nullptr) { 0258 e->accept(); 0259 const QString &tmp = item->name(); 0260 _view->op()->emitExecuted(tmp); 0261 return true; 0262 } 0263 return false; 0264 } 0265 0266 bool KrMouseHandler::mouseMoveEvent(QMouseEvent *e) 0267 { 0268 KrViewItem *item = _view->getKrViewItemAt(e->pos()); 0269 KrSelectionMode *mode = KrSelectionMode::getSelectionHandler(); 0270 0271 if ((_singleClicked || _renameTimer.isActive()) && item != _singleClickedItem) 0272 CANCEL_TWO_CLICK_RENAME; 0273 0274 if (!item) 0275 return false; 0276 0277 const QString desc = item->description(); 0278 _view->op()->emitItemDescription(desc); 0279 0280 if (_dragStartPos != QPoint(-1, -1) && (e->buttons() & Qt::LeftButton) 0281 && (_dragStartPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) { 0282 _view->op()->startDrag(); 0283 return true; 0284 } 0285 0286 if (mode->rightButtonPreservesSelection() && mode->rightButtonSelects() && mode->showContextMenu() >= 0 && e->buttons() == Qt::RightButton) { 0287 e->accept(); 0288 if (item != _rightClickedItem && item && _rightClickedItem) { 0289 _view->selectRegion(item, _rightClickedItem, _rightClickSelects); 0290 _rightClickedItem = item; 0291 _view->setCurrentKrViewItem(item); 0292 _contextMenuTimer.stop(); 0293 } 0294 return true; 0295 } 0296 return false; 0297 } 0298 0299 bool KrMouseHandler::wheelEvent(QWheelEvent *e) 0300 { 0301 if (!_view->isFocused()) 0302 _view->op()->emitNeedFocus(); 0303 0304 if (e->modifiers() == Qt::ControlModifier) { 0305 if (e->angleDelta().y() > 0) { 0306 _view->zoomIn(); 0307 } else { 0308 _view->zoomOut(); 0309 } 0310 e->accept(); 0311 return true; 0312 } 0313 0314 return false; 0315 } 0316 0317 void KrMouseHandler::showContextMenu() 0318 { 0319 if (_rightClickedItem) 0320 _rightClickedItem->setSelected(true); 0321 if (_emptyContextMenu) 0322 _view->op()->emitEmptyContextMenu(_contextMenuPoint); 0323 else 0324 _view->op()->emitContextMenu(_contextMenuPoint); 0325 } 0326 0327 void KrMouseHandler::handleContextMenu(KrViewItem *it, const QPoint &pos) 0328 { 0329 if (!_view->isFocused()) 0330 _view->op()->emitNeedFocus(); 0331 int i = KrSelectionMode::getSelectionHandler()->showContextMenu(); 0332 _contextMenuPoint = QPoint(pos.x(), pos.y() - _contextMenuShift); 0333 if (i < 0) { 0334 if (!it || it->isDummy()) 0335 _view->op()->emitEmptyContextMenu(_contextMenuPoint); 0336 else { 0337 _view->setCurrentKrViewItem(it); 0338 _view->op()->emitContextMenu(_contextMenuPoint); 0339 } 0340 } else if (i > 0) { 0341 _emptyContextMenu = !it || it->isDummy(); 0342 _contextMenuTimer.setSingleShot(true); 0343 _contextMenuTimer.start(i); 0344 } 0345 } 0346 0347 void KrMouseHandler::otherEvent(QEvent *e) 0348 { 0349 switch (e->type()) { 0350 case QEvent::Timer: 0351 case QEvent::MouseMove: 0352 case QEvent::MouseButtonPress: 0353 case QEvent::MouseButtonRelease: 0354 break; 0355 default: 0356 CANCEL_TWO_CLICK_RENAME; 0357 } 0358 } 0359 0360 void KrMouseHandler::cancelTwoClickRename() 0361 { 0362 CANCEL_TWO_CLICK_RENAME; 0363 } 0364 0365 bool KrMouseHandler::dragEnterEvent(QDragEnterEvent *e) 0366 { 0367 QList<QUrl> URLs = KUrlMimeData::urlsFromMimeData(e->mimeData()); 0368 e->setAccepted(!URLs.isEmpty()); 0369 return true; 0370 } 0371 0372 bool KrMouseHandler::dragMoveEvent(QDragMoveEvent *e) 0373 { 0374 QList<QUrl> URLs = KUrlMimeData::urlsFromMimeData(e->mimeData()); 0375 e->setAccepted(!URLs.isEmpty()); 0376 return true; 0377 } 0378 0379 bool KrMouseHandler::dragLeaveEvent(QDragLeaveEvent * /*e*/) 0380 { 0381 return false; 0382 } 0383 0384 bool KrMouseHandler::dropEvent(QDropEvent *e) 0385 { 0386 _view->op()->emitGotDrop(e); 0387 return true; 0388 }