Skip to content

Commit 25659d7

Browse files
authored
Merge pull request #437 from QuangNguyenMinh123/feature/Go_to_definition_Ctrl_Click
Go to definition, but with Ctrl + Click
2 parents 872f578 + 325c458 commit 25659d7

3 files changed

Lines changed: 110 additions & 5 deletions

File tree

src/SeerEditorWidgetSource.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <QtCore/QMap>
2121
#include <QtCore/QFileSystemWatcher>
2222
#include <QtCore/QPoint>
23-
23+
#include <QMouseEvent>
2424

2525
class SeerEditorWidgetSourceLineNumberArea;
2626
class SeerEditorWidgetSourceBreakPointArea;
@@ -162,6 +162,8 @@ class SeerEditorWidgetSourceArea : public SeerPlainTextEdit {
162162
void showExpressionTooltip ();
163163
void hideExpressionTooltip ();
164164
void mousePressEvent (QMouseEvent *event) override;
165+
void keyPressEvent (QKeyEvent* event) override;
166+
void keyReleaseEvent (QKeyEvent* event) override;
165167

166168
private slots:
167169
void refreshExtraSelections ();
@@ -172,6 +174,9 @@ class SeerEditorWidgetSourceArea : public SeerPlainTextEdit {
172174

173175
private:
174176
void handleCursorPositionChanged ();
177+
void updateCursor (const QPoint &pos);
178+
bool isOverWord (const QPoint &pos);
179+
QString wordUnderCursor (const QPoint &pos) const;
175180
bool isValidIdentifier (const QString& text);
176181

177182
QString _fullname;
@@ -207,6 +212,11 @@ class SeerEditorWidgetSourceArea : public SeerPlainTextEdit {
207212
QString _externalEditorCommand;
208213
bool _autoSourceReload;
209214
int _ignoreThumbMouseEvent = 0;
215+
216+
// Variables for Goto Definition (Ctrl + Click)
217+
static QTimer* _ctrlHeldTimer;
218+
static bool _ctrlHeld;
219+
QString _wordUnderCursor;
210220
};
211221

212222
class SeerEditorWidgetSourceLineNumberArea : public QWidget {

src/SeerEditorWidgetSourceAreas.cpp

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
#include <QtCore/QCoreApplication>
3535
#include <QtCore/QProcess>
3636

37+
bool SeerEditorWidgetSourceArea::_ctrlHeld = false;
38+
QTimer* SeerEditorWidgetSourceArea::_ctrlHeldTimer = new QTimer();
39+
3740
SeerEditorWidgetSourceArea::SeerEditorWidgetSourceArea(QWidget* parent) : SeerPlainTextEdit(parent) {
3841

3942
_fileWatcher = 0;
@@ -64,6 +67,11 @@ SeerEditorWidgetSourceArea::SeerEditorWidgetSourceArea(QWidget* parent) : SeerPl
6467
enableLineNumberArea(true);
6568
enableBreakPointArea(true);
6669

70+
_ctrlHeldTimer->setInterval(40); // 40 ms interval = 25Hz update rate
71+
QObject::connect(_ctrlHeldTimer, &QTimer::timeout, this, [this]() {
72+
updateCursor(QCursor::pos());
73+
});
74+
6775
QObject::connect(this, &SeerEditorWidgetSourceArea::blockCountChanged, this, &SeerEditorWidgetSourceArea::updateMarginAreasWidth);
6876
QObject::connect(this, &SeerEditorWidgetSourceArea::updateRequest, this, &SeerEditorWidgetSourceArea::updateLineNumberArea);
6977
QObject::connect(this, &SeerEditorWidgetSourceArea::updateRequest, this, &SeerEditorWidgetSourceArea::updateBreakPointArea);
@@ -83,6 +91,8 @@ SeerEditorWidgetSourceArea::SeerEditorWidgetSourceArea(QWidget* parent) : SeerPl
8391
_lineNumberArea->installEventFilter(lineNumberAreaWheelForwarder);
8492
_breakPointArea->installEventFilter(breakPointAreaWheelForwarder);
8593

94+
_ctrlHeldTimer->start();
95+
8696
// Calling close() will clear the text document.
8797
close();
8898
}
@@ -2066,6 +2076,16 @@ void SeerEditorWidgetSourceArea::mousePressEvent(QMouseEvent *event)
20662076
}
20672077
} );
20682078
}
2079+
// This part is for Go to definition (Ctrl + Click) feature
2080+
if (event->button() == Qt::LeftButton && _ctrlHeld) {
2081+
if (_wordUnderCursor != "")
2082+
{
2083+
QApplication::restoreOverrideCursor();
2084+
signalGotoDefinition(_wordUnderCursor);
2085+
event->ignore(); // If we don't ignore the event, the cursor will move to that position, which is not desired
2086+
return;
2087+
}
2088+
}
20692089
QPlainTextEdit::mousePressEvent(event);
20702090
}
20712091

@@ -2089,8 +2109,72 @@ void SeerEditorWidgetSourceArea::handleCursorPositionChanged()
20892109
}
20902110

20912111
/***********************************************************************************************************************
2092-
* Go to definition (F12) feature *
2112+
* Go to definition (F12) feature *
20932113
**********************************************************************************************************************/
2114+
void SeerEditorWidgetSourceArea::keyPressEvent(QKeyEvent *event)
2115+
{
2116+
if (event->key() == Qt::Key_Control)
2117+
{
2118+
_ctrlHeld = true;
2119+
}
2120+
QPlainTextEdit::keyPressEvent(event);
2121+
}
2122+
2123+
void SeerEditorWidgetSourceArea::keyReleaseEvent(QKeyEvent *event)
2124+
{
2125+
if (event->key() == Qt::Key_Control)
2126+
{
2127+
_ctrlHeld = false;
2128+
}
2129+
QPlainTextEdit::keyReleaseEvent(event);
2130+
}
2131+
2132+
bool SeerEditorWidgetSourceArea::isOverWord(const QPoint &pos)
2133+
{
2134+
QTextCursor cursor = cursorForPosition(pos);
2135+
cursor.select(QTextCursor::WordUnderCursor);
2136+
return !cursor.selectedText().isEmpty();
2137+
}
2138+
2139+
QString SeerEditorWidgetSourceArea::wordUnderCursor(const QPoint &pos) const
2140+
{
2141+
int leftMarginOffset = 0;
2142+
QMargins margins = viewportMargins();
2143+
QPoint adjustedPos = pos;
2144+
2145+
// The correct position to get the word under cursor should subtract the left margin
2146+
// offset (breakpoint area and line number area)
2147+
leftMarginOffset = margins.left();
2148+
adjustedPos.setX(pos.x() - leftMarginOffset);
2149+
QTextCursor cursor = cursorForPosition(adjustedPos);
2150+
cursor.select(QTextCursor::WordUnderCursor);
2151+
return cursor.selectedText();
2152+
}
2153+
2154+
void SeerEditorWidgetSourceArea::updateCursor(const QPoint &pos)
2155+
{
2156+
// Why not QApplication::setOverrideCursor()? Because QApplication::setOverrideCursor uses internal stack
2157+
// It causes delay and sometimes the cursor won't change back to normal when we want it to.
2158+
// In short, QApplication::setOverrideCursor is global and not real time
2159+
// In contrary, viewport()->setCursor() is local and real time, apply only for that widget, in this case, the text area
2160+
QPoint localPos = mapFromGlobal(pos);
2161+
if (!_ctrlHeld) {
2162+
viewport()->setCursor(Qt::IBeamCursor);
2163+
_wordUnderCursor = "";
2164+
return;
2165+
}
2166+
if (!hasFocus())
2167+
return;
2168+
_wordUnderCursor = wordUnderCursor(localPos);
2169+
if (isValidIdentifier(_wordUnderCursor))
2170+
{
2171+
viewport()->setCursor(Qt::PointingHandCursor);
2172+
} else {
2173+
viewport()->setCursor(Qt::IBeamCursor);
2174+
_wordUnderCursor = "";
2175+
}
2176+
}
2177+
20942178
// Check text and decide if that text is valid identifier (function, variable, type name)
20952179
bool SeerEditorWidgetSourceArea::isValidIdentifier(const QString& text)
20962180
{

src/resources/help/CodeManager.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,20 @@ The easiest method for logging a variable to the Variable Logger is to double-cl
4444
Ctrl+Shift Prepend '*&' to variable '*&argc'
4545
```
4646

47-
Using ^F will bring up a search bar in the source window.
48-
49-
Using ^O will bring up a file bar to help locate the file for the source (in case it isn't in the directory that GDB thinks it is).
47+
Other key sequences.
48+
```
49+
Keys Description
50+
------------ ------------------------------------
51+
Ctrl+LMB Goto function defintion identified by
52+
text under cursor.
53+
^F Bring up a text search bar in the
54+
source window.
55+
^L Bring up a line number search bar in
56+
the source window.
57+
^O Bring up a file bar to help locate the file
58+
for the source (in case it isn't in the
59+
directory that GDB thinks it is).
60+
```
5061

5162
### Buttons
5263

0 commit comments

Comments
 (0)