[WIP] Add multiline selection with Shift + Left Click

This commit is contained in:
yasmin 2024-03-25 06:08:04 -04:00
parent f8c7df8260
commit f8a258f98c
2 changed files with 108 additions and 6 deletions

View File

@ -439,6 +439,29 @@ void DisassemblyWidget::highlightPCLine()
mDisasTextEdit->setExtraSelections(currentSelections); mDisasTextEdit->setExtraSelections(currentSelections);
} }
void DisassemblyWidget::highlightMultiLineSelections()
{
QList<QTextEdit::ExtraSelection> extraSelections;
QTextEdit::ExtraSelection highlightSelection;
QColor highlightColor = ConfigColor("lineHighlight");
// Highlight each selection in the multilineSelections list
for (const QTextEdit::ExtraSelection &selection : mDisasTextEdit->getMultiLineSelections()) {
highlightSelection.format.setBackground(highlightColor);
highlightSelection.format.setProperty(QTextFormat::FullWidthSelection, true);
highlightSelection.cursor = mDisasTextEdit->textCursor();
highlightSelection.cursor.setPosition(selection.cursor.selectionStart());
highlightSelection.cursor.setPosition(selection.cursor.selectionEnd(),
QTextCursor::KeepAnchor);
extraSelections.append(highlightSelection);
}
// Don't override any extraSelections already set
QList<QTextEdit::ExtraSelection> currentSelections = mDisasTextEdit->extraSelections();
currentSelections.append(extraSelections);
mDisasTextEdit->setExtraSelections(currentSelections);
}
void DisassemblyWidget::showDisasContextMenu(const QPoint &pt) void DisassemblyWidget::showDisasContextMenu(const QPoint &pt)
{ {
mCtxMenu->exec(mDisasTextEdit->mapToGlobal(pt)); mCtxMenu->exec(mDisasTextEdit->mapToGlobal(pt));
@ -511,7 +534,7 @@ void DisassemblyWidget::updateCursorPosition()
} }
highlightPCLine(); highlightPCLine();
highlightMultiLineSelections();
connectCursorPositionChanged(false); connectCursorPositionChanged(false);
} }
@ -546,6 +569,7 @@ void DisassemblyWidget::cursorPositionChanged()
seekFromCursor = false; seekFromCursor = false;
highlightCurrentLine(); highlightCurrentLine();
highlightPCLine(); highlightPCLine();
highlightMultiLineSelections();
mCtxMenu->setCanCopy(mDisasTextEdit->textCursor().hasSelection()); mCtxMenu->setCanCopy(mDisasTextEdit->textCursor().hasSelection());
if (mDisasTextEdit->textCursor().hasSelection()) { if (mDisasTextEdit->textCursor().hasSelection()) {
// A word is selected so use it // A word is selected so use it
@ -615,6 +639,7 @@ void DisassemblyWidget::moveCursorRelative(bool up, bool page)
seekable->seek(offset); seekable->seek(offset);
highlightCurrentLine(); highlightCurrentLine();
highlightPCLine(); highlightPCLine();
highlightMultiLineSelections();
} }
} }
} }
@ -661,7 +686,10 @@ bool DisassemblyWidget::eventFilter(QObject *obj, QEvent *event)
void DisassemblyWidget::keyPressEvent(QKeyEvent *event) void DisassemblyWidget::keyPressEvent(QKeyEvent *event)
{ {
if (event->key() == Qt::Key_Return) { if (event->key() == Qt::Key_Shift) {
qDebug() << "shift key pressed";
mDisasTextEdit->setMultiLineSelection(true);
} else if (event->key() == Qt::Key_Return) {
const QTextCursor cursor = mDisasTextEdit->textCursor(); const QTextCursor cursor = mDisasTextEdit->textCursor();
jumpToOffsetUnderCursor(cursor); jumpToOffsetUnderCursor(cursor);
} }
@ -669,6 +697,16 @@ void DisassemblyWidget::keyPressEvent(QKeyEvent *event)
MemoryDockWidget::keyPressEvent(event); MemoryDockWidget::keyPressEvent(event);
} }
void DisassemblyWidget::keyReleaseEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Shift) {
qDebug() << "shift key released";
mDisasTextEdit->setMultiLineSelection(false);
}
MemoryDockWidget::keyReleaseEvent(event);
}
QString DisassemblyWidget::getWindowTitle() const QString DisassemblyWidget::getWindowTitle() const
{ {
return tr("Disassembly"); return tr("Disassembly");
@ -788,9 +826,64 @@ void DisassemblyTextEdit::keyPressEvent(QKeyEvent *event)
Q_UNUSED(event) Q_UNUSED(event)
// QPlainTextEdit::keyPressEvent(event); // QPlainTextEdit::keyPressEvent(event);
} }
void DisassemblyTextEdit::mousePressEvent(QMouseEvent *event) void DisassemblyTextEdit::mousePressEvent(QMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton && !multiLineSelection) {
multilineSelections.clear();
}
// Check for left button click and multiline individual selection mode (shift key pressed)
if (event->button() == Qt::LeftButton && multiLineSelection) {
// Use cursorForPosition to set the cursor to the exact click position
QTextCursor cursor = cursorForPosition(event->pos());
setTextCursor(cursor); // Update the text cursor to this position
int startPos = cursor.selectionStart();
int endPos = cursor.selectionEnd();
// Format selection
QTextEdit::ExtraSelection selection;
selection.format.setBackground(QColor("green"));
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
// Move cursor to start of the line
cursor.movePosition(QTextCursor::StartOfLine);
startPos = cursor.position();
// Extend cursor to the end of the line
cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
endPos = cursor.position();
// Debug log
qDebug() << "Offset of line added: " << startPos << "-" << endPos;
// Check if line is already selected
auto it = std::find_if(multilineSelections.begin(), multilineSelections.end(),
[startPos, endPos](const QTextEdit::ExtraSelection &s) {
return s.cursor.selectionStart() == startPos
&& s.cursor.selectionEnd() == endPos;
});
if (it != multilineSelections.end()) {
// Deselect if already selected
multilineSelections.erase(it);
} else {
// Add this line to the selections if not already selected
selection.cursor = cursor;
multilineSelections.append(selection);
}
// Apply the selections
setExtraSelections(multilineSelections);
// Debug log
qDebug() << "Multiline selections:";
for (const auto &selection : multilineSelections) {
qDebug() << "Start:" << selection.cursor.selectionStart()
<< "End:" << selection.cursor.selectionEnd();
}
}
QPlainTextEdit::mousePressEvent(event); QPlainTextEdit::mousePressEvent(event);
if (event->button() == Qt::RightButton && !textCursor().hasSelection()) { if (event->button() == Qt::RightButton && !textCursor().hasSelection()) {

View File

@ -41,6 +41,7 @@ public slots:
* overrides all previous highlighting. * overrides all previous highlighting.
*/ */
void highlightPCLine(); void highlightPCLine();
void highlightMultiLineSelections();
void showDisasContextMenu(const QPoint &pt); void showDisasContextMenu(const QPoint &pt);
void fontsUpdatedSlot(); void fontsUpdatedSlot();
void colorsUpdatedSlot(); void colorsUpdatedSlot();
@ -86,6 +87,7 @@ private:
RVA readCurrentDisassemblyOffset(); RVA readCurrentDisassemblyOffset();
bool eventFilter(QObject *obj, QEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override;
void keyPressEvent(QKeyEvent *event) override; void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
QString getWindowTitle() const override; QString getWindowTitle() const override;
int topOffsetHistoryPos = 0; int topOffsetHistoryPos = 0;
@ -129,11 +131,16 @@ class DisassemblyTextEdit : public QPlainTextEdit
public: public:
explicit DisassemblyTextEdit(QWidget *parent = nullptr) explicit DisassemblyTextEdit(QWidget *parent = nullptr)
: QPlainTextEdit(parent), lockScroll(false) : QPlainTextEdit(parent), lockScroll(false), multiLineSelection(false)
{ {
} }
void setLockScroll(bool lock) { this->lockScroll = lock; } void setLockScroll(bool lock) { this->lockScroll = lock; }
void setMultiLineSelection(bool multiLineSelection) { this->multiLineSelection = multiLineSelection; }
void setMultiLineSelections(const QList<QTextEdit::ExtraSelection> &selections) { multilineSelections = selections; }
bool getMultiLineSelection() const { return multiLineSelection; }
QList<QTextEdit::ExtraSelection> getMultiLineSelections() const { return multilineSelections; }
qreal textOffset() const; qreal textOffset() const;
@ -145,6 +152,8 @@ protected:
private: private:
bool lockScroll; bool lockScroll;
bool multiLineSelection;
QList<QTextEdit::ExtraSelection> multilineSelections;
}; };
/** /**