- Fehler in mehrzeiligen Kommentaren behoben
- Klammerpaare werden farblich hervorgehoben - Beim einrücken oder ausrücken eines markierten Blocks wird die Zeile, in der der Coursor steht, nicht mehr mitgerückt - Beim eintippen von Variablen wird eine Liste mit bereits deklarierten Variablen angezeigt
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "ColorIndicator.h"
|
||||
#include "SignatureHelper.h"
|
||||
#include "FunctionIndex.h"
|
||||
#include "VariableCompleter.h"
|
||||
|
||||
#include "core/Settings.h"
|
||||
#include "highlighter/HighlighterFactory.h"
|
||||
@@ -27,6 +28,7 @@ CodeEditor::CodeEditor(Settings *settings, QWidget *parent)
|
||||
m_lineNumberArea = new LineNumberArea(this);
|
||||
m_colorIndicator = new ColorIndicator(this);
|
||||
m_signatureHelper = new SignatureHelper(this);
|
||||
m_varCompleter = new VariableCompleter(this);
|
||||
setupEditor();
|
||||
|
||||
connect(this, &CodeEditor::blockCountChanged,
|
||||
@@ -390,7 +392,7 @@ void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Current line highlight
|
||||
// Current line highlight + Klammerzugehörigkeit
|
||||
// ---------------------------------------------------------------------------
|
||||
void CodeEditor::highlightCurrentLine()
|
||||
{
|
||||
@@ -398,20 +400,161 @@ void CodeEditor::highlightCurrentLine()
|
||||
|
||||
if (!isReadOnly())
|
||||
{
|
||||
QTextEdit::ExtraSelection selection;
|
||||
// Aktuelle Zeile hervorheben
|
||||
QTextEdit::ExtraSelection lineSelection;
|
||||
lineSelection.format.setBackground(palette().color(QPalette::AlternateBase));
|
||||
lineSelection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
||||
lineSelection.cursor = textCursor();
|
||||
lineSelection.cursor.clearSelection();
|
||||
extraSelections.append(lineSelection);
|
||||
|
||||
const QColor lineColor = palette().color(QPalette::AlternateBase);
|
||||
selection.format.setBackground(lineColor);
|
||||
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
||||
selection.cursor = textCursor();
|
||||
selection.cursor.clearSelection();
|
||||
|
||||
extraSelections.append(selection);
|
||||
// Klammerzugehörigkeit
|
||||
matchBrackets(extraSelections);
|
||||
}
|
||||
|
||||
setExtraSelections(extraSelections);
|
||||
}
|
||||
|
||||
void CodeEditor::matchBrackets(QList<QTextEdit::ExtraSelection> &selections)
|
||||
{
|
||||
static const QString openBrackets = "({[";
|
||||
static const QString closeBrackets = ")}]";
|
||||
|
||||
QTextCursor cursor = textCursor();
|
||||
const QString blockText = cursor.block().text();
|
||||
const int col = cursor.columnNumber();
|
||||
|
||||
// Zeichen unter oder links vom Cursor prüfen
|
||||
QChar ch;
|
||||
int charPos = -1;
|
||||
|
||||
// Zuerst Zeichen unter dem Cursor
|
||||
if (col < blockText.length())
|
||||
{
|
||||
ch = blockText[col];
|
||||
if (openBrackets.contains(ch) || closeBrackets.contains(ch))
|
||||
{
|
||||
charPos = col;
|
||||
}
|
||||
}
|
||||
|
||||
// Dann Zeichen links vom Cursor
|
||||
if (charPos == -1 && col > 0)
|
||||
{
|
||||
ch = blockText[col - 1];
|
||||
if (openBrackets.contains(ch) || closeBrackets.contains(ch))
|
||||
{
|
||||
charPos = col - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (charPos == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Passende Klammer suchen
|
||||
const bool isOpen = openBrackets.contains(ch);
|
||||
const int bracketIndex = isOpen
|
||||
? openBrackets.indexOf(ch)
|
||||
: closeBrackets.indexOf(ch);
|
||||
const QChar matchChar = isOpen
|
||||
? closeBrackets[bracketIndex]
|
||||
: openBrackets[bracketIndex];
|
||||
|
||||
// Dokumentposition der gefundenen Klammer
|
||||
const int startPos = cursor.block().position() + charPos;
|
||||
|
||||
// Passende Klammer suchen — vorwärts oder rückwärts
|
||||
int depth = 0;
|
||||
int matchPos = -1;
|
||||
|
||||
if (isOpen)
|
||||
{
|
||||
// Vorwärts suchen
|
||||
QTextCursor search(document());
|
||||
search.setPosition(startPos);
|
||||
|
||||
while (!search.atEnd())
|
||||
{
|
||||
search.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
|
||||
const QChar c = search.selectedText()[0];
|
||||
search.clearSelection();
|
||||
|
||||
if (c == ch) { ++depth; }
|
||||
else if (c == matchChar)
|
||||
{
|
||||
--depth;
|
||||
if (depth == 0)
|
||||
{
|
||||
matchPos = search.position() - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rückwärts suchen
|
||||
QTextCursor search(document());
|
||||
search.setPosition(startPos + 1);
|
||||
|
||||
while (search.position() > 0)
|
||||
{
|
||||
search.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
|
||||
const QChar c = search.selectedText()[0];
|
||||
search.clearSelection();
|
||||
|
||||
if (c == ch) { ++depth; }
|
||||
else if (c == matchChar)
|
||||
{
|
||||
--depth;
|
||||
if (depth == 0)
|
||||
{
|
||||
matchPos = search.position();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Formatierung
|
||||
QTextCharFormat matchFormat;
|
||||
if (matchPos >= 0)
|
||||
{
|
||||
// Gefunden — beide Klammern grün hervorheben
|
||||
matchFormat.setBackground(QColor("#1a5a1a"));
|
||||
matchFormat.setForeground(QColor("#88ff88"));
|
||||
matchFormat.setFontWeight(QFont::Bold);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Kein Match — rot markieren
|
||||
matchFormat.setBackground(QColor("#5a1a1a"));
|
||||
matchFormat.setForeground(QColor("#ff8888"));
|
||||
matchFormat.setFontWeight(QFont::Bold);
|
||||
}
|
||||
|
||||
// Öffnende / schließende Klammer markieren
|
||||
QTextEdit::ExtraSelection sel1;
|
||||
sel1.cursor = QTextCursor(document());
|
||||
sel1.cursor.setPosition(startPos);
|
||||
sel1.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
|
||||
sel1.format = matchFormat;
|
||||
selections.append(sel1);
|
||||
|
||||
// Passende Klammer markieren (nur wenn gefunden)
|
||||
if (matchPos >= 0)
|
||||
{
|
||||
QTextEdit::ExtraSelection sel2;
|
||||
sel2.cursor = QTextCursor(document());
|
||||
sel2.cursor.setPosition(matchPos);
|
||||
sel2.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
|
||||
sel2.format = matchFormat;
|
||||
selections.append(sel2);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Key handling – Tab/Shift+Tab, Smart-Backspace, Auto-Indent
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -430,6 +573,16 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
|
||||
QTextBlock startBlock = document()->findBlock(cursor.selectionStart());
|
||||
QTextBlock endBlock = document()->findBlock(cursor.selectionEnd());
|
||||
|
||||
// Wenn die Selektion genau am Anfang des letzten Blocks endet,
|
||||
// diesen Block nicht mit einbeziehen — der Cursor steht dort nur
|
||||
// mit Position 0, der Nutzer hat die Zeile nicht markiert
|
||||
if (cursor.hasSelection() &&
|
||||
cursor.selectionEnd() == endBlock.position() &&
|
||||
endBlock != startBlock)
|
||||
{
|
||||
endBlock = endBlock.previous();
|
||||
}
|
||||
|
||||
cursor.beginEditBlock();
|
||||
for (QTextBlock b = startBlock; b != endBlock.next(); b = b.next())
|
||||
{
|
||||
@@ -438,22 +591,14 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
|
||||
|
||||
if (m_settings->useSpacesForTabs())
|
||||
{
|
||||
// Bis zu tabSize führende Leerzeichen entfernen
|
||||
for (int i = 0; i < tabSize && i < lineText.length(); ++i)
|
||||
{
|
||||
if (lineText[i] == ' ')
|
||||
{
|
||||
++toRemove;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (lineText[i] == ' ') { ++toRemove; }
|
||||
else { break; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Einen führenden Tab entfernen
|
||||
if (!lineText.isEmpty() && lineText[0] == '\t')
|
||||
{
|
||||
toRemove = 1;
|
||||
@@ -483,10 +628,16 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
|
||||
|
||||
if (cursor.hasSelection())
|
||||
{
|
||||
// Mehrere Zeilen einrücken
|
||||
QTextBlock startBlock = document()->findBlock(cursor.selectionStart());
|
||||
QTextBlock endBlock = document()->findBlock(cursor.selectionEnd());
|
||||
|
||||
// Gleiche Korrektur: Cursor am Zeilenanfang → Zeile nicht einrücken
|
||||
if (cursor.selectionEnd() == endBlock.position() &&
|
||||
endBlock != startBlock)
|
||||
{
|
||||
endBlock = endBlock.previous();
|
||||
}
|
||||
|
||||
cursor.beginEditBlock();
|
||||
for (QTextBlock b = startBlock; b != endBlock.next(); b = b.next())
|
||||
{
|
||||
@@ -591,5 +742,8 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
|
||||
}
|
||||
|
||||
QPlainTextEdit::keyPressEvent(event);
|
||||
|
||||
// Variablen-Popup nach jedem Tastendruck aktualisieren
|
||||
m_varCompleter->handleKeyPress(event);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user