Commit cb3449ae authored by Tomaz  Canabrava's avatar Tomaz Canabrava
Browse files

Simplify event handling code and remove a lot of hacks

Code is way simpler now, a lot of duplicated code is removed
from TerminalDisplay, and the behavior is split into the
hotSpot classes instead of having TerminalDisplay be a god class
that knows how to handle everything.

This also simplifies creation of new filters
parent 698c1ce1
......@@ -28,6 +28,7 @@
#include <QTimer>
#include <QToolTip>
#include <QMouseEvent>
#include <QKeyEvent>
#include <KRun>
#include <KLocalizedString>
......@@ -101,22 +102,16 @@ void FileFilterHotSpot::setupMenu(QMenu *menu)
}
// Static variables for the HotSpot
qintptr FileFilterHotSpot::currentThumbnailHotspot = 0;
bool FileFilterHotSpot::_canGenerateThumbnail = false;
QPointer<KIO::PreviewJob> FileFilterHotSpot::_previewJob;
void FileFilterHotSpot::requestThumbnail(Qt::KeyboardModifiers modifiers, const QPoint &pos) {
_canGenerateThumbnail = true;
currentThumbnailHotspot = reinterpret_cast<qintptr>(this);
_eventModifiers = modifiers;
_eventPos = pos;
// Defer the real creation of the thumbnail by a few msec.
QTimer::singleShot(250, this, [this]{
if (currentThumbnailHotspot != reinterpret_cast<qintptr>(this)) {
return;
}
thumbnailRequested();
});
}
......@@ -200,8 +195,16 @@ KFileItem FileFilterHotSpot::fileItem() const
void FileFilterHotSpot::mouseMoveEvent(TerminalDisplay *td, QMouseEvent* ev)
{
HotSpot::mouseMoveEvent(td, ev);
if (this != HotSpot::currentlyHoveredHotSpot) {
HotSpot::currentlyHoveredHotSpot.reset(this);
requestThumbnail(ev->modifiers(), ev->globalPos());
}
requestThumbnail(ev->modifiers(), ev->globalPos());
}
void FileFilterHotSpot::mouseLeaveEvent(TerminalDisplay *td, QMouseEvent *ev)
{
HotSpot::mouseLeaveEvent(td, ev);
stopThumbnailGeneration();
}
void Konsole::FileFilterHotSpot::keyPressEvent(Konsole::TerminalDisplay* td, QKeyEvent* ev)
{
requestThumbnail(ev->modifiers(), QCursor::pos());
}
......@@ -33,6 +33,8 @@
class QAction;
class QPixmap;
class QKeyEvent;
class QMouseEvent;
namespace Konsole {
class TerminalDisplay;
......@@ -61,7 +63,10 @@ public:
static void stopThumbnailGeneration();
void mouseMoveEvent(TerminalDisplay *td, QMouseEvent *ev);
void mouseMoveEvent(TerminalDisplay *td, QMouseEvent *ev) override;
void mouseLeaveEvent(TerminalDisplay *td, QMouseEvent *ev) override;
void keyPressEvent(TerminalDisplay *td, QKeyEvent *ev) override;
private:
void showThumbnail(const KFileItem& item, const QPixmap& preview);
QString _filePath;
......
......@@ -149,10 +149,32 @@ QList<QSharedPointer<HotSpot>> FilterChain::filterBy(HotSpot::Type type) const
void FilterChain::leaveEvent(TerminalDisplay *td, QEvent *ev)
{
Q_UNUSED(ev);
if(!HotSpot::mouseOverHotSpotArea.isEmpty()) {
td->update(HotSpot::mouseOverHotSpotArea);
HotSpot::mouseOverHotSpotArea = QRegion();
td->setCursor(Qt::IBeamCursor);
}
void FilterChain::keyPressEvent(TerminalDisplay *td, QKeyEvent *ev, int charLine, int charColumn)
{
auto spot = hotSpotAt(charLine, charColumn);
if (spot) {
spot->keyPressEvent(td, ev);
}
}
void FilterChain::mouseMoveEvent(TerminalDisplay *td, QMouseEvent *ev, int charLine, int charColumn)
{
auto spot = hotSpotAt(charLine, charColumn);
if (_hotSpotUnderMouse != spot) {
if (_hotSpotUnderMouse) {
_hotSpotUnderMouse->mouseLeaveEvent(td, ev);
}
_hotSpotUnderMouse = spot;
if (_hotSpotUnderMouse) {
_hotSpotUnderMouse->mouseEnterEvent(td, ev);
}
}
if (spot) {
spot->mouseMoveEvent(td, ev);
}
}
......@@ -88,10 +88,13 @@ public:
int count(HotSpot::Type type) const;
QList<QSharedPointer<HotSpot>> filterBy(HotSpot::Type type) const;
void mouseMoveEvent(TerminalDisplay *td, QMouseEvent *ev, int charLine, int charColumn);
void keyPressEvent(TerminalDisplay *td, QKeyEvent *ev, int charLine, int charColumn);
void leaveEvent(TerminalDisplay *td, QEvent *ev);
protected:
QList<Filter *> _filters;
TerminalDisplay *_terminalDisplay;
QSharedPointer<HotSpot> _hotSpotUnderMouse;
};
}
......
......@@ -27,9 +27,6 @@
using namespace Konsole;
QSharedPointer<HotSpot> HotSpot::currentlyHoveredHotSpot;
QRegion HotSpot::mouseOverHotSpotArea;
HotSpot::~HotSpot() = default;
HotSpot::HotSpot(int startLine, int startColumn, int endLine, int endColumn) :
......@@ -116,33 +113,26 @@ QPair<QRegion, QRect> HotSpot::region(int fontWidth, int fontHeight, int columns
return {region, r};
}
void HotSpot::mouseMoveEvent(TerminalDisplay *td, QMouseEvent* ev)
void HotSpot::mouseLeaveEvent(TerminalDisplay *td, QMouseEvent *ev)
{
//TODO: Move this to HotSpot::mouseMoveEvent
QCursor cursor = td->cursor();
if ((type() == HotSpot::Link || type() == HotSpot::EMailAddress || type() == HotSpot::EscapedUrl)) {
QRegion previousHotspotArea = _mouseOverHotspotArea;
_mouseOverHotspotArea = region(td->fontWidth(), td->fontHeight(), td->columns(), td->contentRect()).first;
if ((td->openLinksByDirectClick()|| ((ev->modifiers() & Qt::ControlModifier) != 0u)) && (cursor.shape() != Qt::PointingHandCursor)) {
td->setCursor(Qt::PointingHandCursor);
}
td->update(_mouseOverHotspotArea | previousHotspotArea);
} else if (!_mouseOverHotspotArea.isEmpty()) {
if ((td->openLinksByDirectClick() || ((ev->modifiers() & Qt::ControlModifier) != 0u)) || (cursor.shape() == Qt::PointingHandCursor)) {
td->setCursor(td->usesMouseTracking() ? Qt::ArrowCursor : Qt::IBeamCursor);
}
td->update(_mouseOverHotspotArea);
// set hotspot area to an invalid rectangle
_mouseOverHotspotArea = QRegion();
auto r = region(td->fontWidth(), td->fontHeight(), td->columns(), td->contentRect()).first;
td->update(r);
td->setCursor(Qt::IBeamCursor);
}
// TODO: We need to move this to a `mouseLeaveEvent`
// HACK: Special case, if we move away from a FileFilterHotSpot, we need to stop the thumbnail.
FileFilterHotSpot::stopThumbnailGeneration();
HotSpot::currentlyHoveredHotSpot.clear();
void HotSpot::mouseMoveEvent(TerminalDisplay *td, QMouseEvent *ev)
{
QCursor cursor = td->cursor();
if ((td->openLinksByDirectClick() || ((ev->modifiers() & Qt::ControlModifier) != 0u))
|| (cursor.shape() == Qt::PointingHandCursor)) {
td->setCursor(td->usesMouseTracking() ? Qt::ArrowCursor : Qt::IBeamCursor);
}
auto r = region(td->fontWidth(), td->fontHeight(), td->columns(), td->contentRect()).first;
td->update(r);
}
void HotSpot::debug() {
qDebug() << this;
qDebug() << type();
qDebug() << _startLine << _endLine << _startColumn << _endColumn;
}
......@@ -31,6 +31,7 @@
class QAction;
class QMenu;
class QMouseEvent;
class QKeyEvent;
namespace Konsole {
class TerminalDisplay;
......@@ -61,8 +62,6 @@ public:
HotSpot(int startLine, int startColumn, int endLine, int endColumn);
virtual ~HotSpot();
static QSharedPointer<HotSpot> currentlyHoveredHotSpot;
static QRegion mouseOverHotSpotArea;
enum Type {
// the type of the hotspot is not specified
NotSpecified,
......@@ -111,8 +110,11 @@ public:
QPair<QRegion, QRect> region(int fontWidth, int fontHeight, int columns, QRect terminalDisplayRect) const;
void mouseMoveEvent(TerminalDisplay *td, QMouseEvent *ev);
virtual void mouseEnterEvent(TerminalDisplay *td, QMouseEvent *ev) { Q_UNUSED(td); Q_UNUSED(ev); };
virtual void mouseMoveEvent(TerminalDisplay *td, QMouseEvent *ev);
virtual void mouseLeaveEvent(TerminalDisplay *td, QMouseEvent *ev);
virtual void keyPressEvent(TerminalDisplay *td, QKeyEvent *ev) {};
void debug();
protected:
/** Sets the type of a hotspot. This should only be set once */
void setType(Type type);
......
......@@ -28,8 +28,10 @@
#include <QIcon>
#include <KLocalizedString>
#include <KRun>
#include <QMouseEvent>
#include "UrlFilter.h"
#include "widgets/TerminalDisplay.h"
//regexp matches:
// full url:
......@@ -124,3 +126,15 @@ QList<QAction *> UrlFilterHotSpot::actions()
return {openAction, copyAction};
}
void Konsole::UrlFilterHotSpot::mouseMoveEvent(Konsole::TerminalDisplay* td, QMouseEvent* ev)
{
auto cursor = td->cursor();
auto r = region(td->fontWidth(), td->fontHeight(), td->columns(), td->contentRect()).first;
if ((td->openLinksByDirectClick()|| ((ev->modifiers() & Qt::ControlModifier) != 0u)) && (cursor.shape() != Qt::PointingHandCursor)) {
td->setCursor(Qt::PointingHandCursor);
}
td->update(r);
}
......@@ -45,6 +45,7 @@ public:
* the capturedTexts() method.
*/
void activate(QObject *object = nullptr) override;
void mouseMoveEvent(TerminalDisplay *td, QMouseEvent *ev) override;
private:
enum UrlType {
......
......@@ -97,6 +97,13 @@ using namespace Konsole;
const QChar LTR_OVERRIDE_CHAR(0x202D);
inline int TerminalDisplay::loc(int x, int y) const {
if (y < 0 || y > _lines) {
qDebug() << "Y: " << y << "Lines" << _lines;
}
if (x < 0 || x > _columns ) {
qDebug() << "X" << x << "Columns" << _columns;
}
Q_ASSERT(y >= 0 && y < _lines);
Q_ASSERT(x >= 0 && x < _columns);
x = qBound(0, x, _columns - 1);
......@@ -1455,6 +1462,10 @@ void TerminalDisplay::paintFilters(QPainter& painter)
}
}
if (spot->startLine() < 0 || spot->endLine() < 0) {
qDebug() << "ERROR, invalid hotspot:";
spot->debug();
}
for (int line = spot->startLine() ; line <= spot->endLine() ; line++) {
int startColumn = 0;
int endColumn = _columns - 1; // TODO use number of _columns which are actually
......@@ -2355,13 +2366,8 @@ void TerminalDisplay::mouseMoveEvent(QMouseEvent* ev)
getCharacterPosition(ev->pos(), charLine, charColumn, !_usesMouseTracking);
processFilters();
// handle filters
// change link hot-spot appearance on mouse-over
// TODO: Move this to filterChain::mouseMoveEvent
auto spot = _filterChain->hotSpotAt(charLine, charColumn);
if (spot) {
spot->mouseMoveEvent(this, ev);
}
_filterChain->mouseMoveEvent(this, ev, charLine, charColumn);
// for auto-hiding the cursor, we need mouseTracking
if (ev->buttons() == Qt::NoButton) {
......@@ -3630,13 +3636,11 @@ void TerminalDisplay::keyPressEvent(QKeyEvent* event)
}
}
// TODO: Move this to hotSpot::keyPressEvent.
if (HotSpot::currentlyHoveredHotSpot != nullptr) {
auto fileHotspot = HotSpot::currentlyHoveredHotSpot.dynamicCast<FileFilterHotSpot>();
if (!fileHotspot) {
return;
}
fileHotspot->requestThumbnail(event->modifiers(), QCursor::pos());
{ // C++17: change getCharacterPosition to return a tuple and use auto [charLine, charColumn] to extract the values.
int charLine;
int charColumn;
getCharacterPosition(QCursor::pos(), charLine, charColumn, !_usesMouseTracking);
_filterChain->keyPressEvent(this, event, charLine, charColumn);
}
_screenWindow->screen()->setCurrentTerminalDisplay(this);
......
......@@ -916,6 +916,7 @@ private:
bool _hasCompositeFocus;
bool _displayVerticalLine;
int _displayVerticalLineAtChar;
QSharedPointer<HotSpot> _hotSpotUnderMouse;
};
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment