- Ausrücken mit Shift-Tab implementiert
- RÜcksprung mit Backspace implementiert - Anzeige für veränderte Datei implementiert
This commit is contained in:
@@ -269,19 +269,77 @@ void CodeEditor::highlightCurrentLine()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Key handling – auto-indent + Tab → spaces
|
// Key handling – Tab/Shift+Tab, Smart-Backspace, Auto-Indent
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
void CodeEditor::keyPressEvent(QKeyEvent *event)
|
void CodeEditor::keyPressEvent(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
// Tab key: insert spaces instead of a real tab character
|
|
||||||
if (event->key() == Qt::Key_Tab && m_settings->useSpacesForTabs())
|
|
||||||
{
|
|
||||||
const int tabSize = m_settings->tabSize();
|
const int tabSize = m_settings->tabSize();
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// Shift+Tab: Einrückung zurückziehen
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
if (event->key() == Qt::Key_Backtab ||
|
||||||
|
(event->key() == Qt::Key_Tab && event->modifiers() & Qt::ShiftModifier))
|
||||||
|
{
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
|
||||||
|
QTextBlock startBlock = document()->findBlock(cursor.selectionStart());
|
||||||
|
QTextBlock endBlock = document()->findBlock(cursor.selectionEnd());
|
||||||
|
|
||||||
|
cursor.beginEditBlock();
|
||||||
|
for (QTextBlock b = startBlock; b != endBlock.next(); b = b.next())
|
||||||
|
{
|
||||||
|
const QString lineText = b.text();
|
||||||
|
int toRemove = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Einen führenden Tab entfernen
|
||||||
|
if (!lineText.isEmpty() && lineText[0] == '\t')
|
||||||
|
{
|
||||||
|
toRemove = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toRemove > 0)
|
||||||
|
{
|
||||||
|
QTextCursor lineCursor(b);
|
||||||
|
lineCursor.movePosition(QTextCursor::StartOfBlock);
|
||||||
|
lineCursor.movePosition(QTextCursor::Right,
|
||||||
|
QTextCursor::KeepAnchor,
|
||||||
|
toRemove);
|
||||||
|
lineCursor.removeSelectedText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor.endEditBlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// Tab: Einrücken (Leerzeichen oder echter Tab)
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
if (event->key() == Qt::Key_Tab)
|
||||||
|
{
|
||||||
QTextCursor cursor = textCursor();
|
QTextCursor cursor = textCursor();
|
||||||
|
|
||||||
if (cursor.hasSelection())
|
if (cursor.hasSelection())
|
||||||
{
|
{
|
||||||
// Indent selected lines
|
// Mehrere Zeilen einrücken
|
||||||
QTextBlock startBlock = document()->findBlock(cursor.selectionStart());
|
QTextBlock startBlock = document()->findBlock(cursor.selectionStart());
|
||||||
QTextBlock endBlock = document()->findBlock(cursor.selectionEnd());
|
QTextBlock endBlock = document()->findBlock(cursor.selectionEnd());
|
||||||
|
|
||||||
@@ -289,27 +347,76 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
|
|||||||
for (QTextBlock b = startBlock; b != endBlock.next(); b = b.next())
|
for (QTextBlock b = startBlock; b != endBlock.next(); b = b.next())
|
||||||
{
|
{
|
||||||
QTextCursor lineCursor(b);
|
QTextCursor lineCursor(b);
|
||||||
|
lineCursor.movePosition(QTextCursor::StartOfBlock);
|
||||||
|
if (m_settings->useSpacesForTabs())
|
||||||
|
{
|
||||||
lineCursor.insertText(QString(tabSize, ' '));
|
lineCursor.insertText(QString(tabSize, ' '));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lineCursor.insertText("\t");
|
||||||
|
}
|
||||||
|
}
|
||||||
cursor.endEditBlock();
|
cursor.endEditBlock();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Calculate spaces needed to reach next tab stop
|
if (m_settings->useSpacesForTabs())
|
||||||
|
{
|
||||||
|
// Zum nächsten Tab-Stop auffüllen
|
||||||
const int col = cursor.columnNumber();
|
const int col = cursor.columnNumber();
|
||||||
const int spacesNeeded = tabSize - (col % tabSize);
|
const int spacesNeeded = tabSize - (col % tabSize);
|
||||||
cursor.insertText(QString(spacesNeeded, ' '));
|
cursor.insertText(QString(spacesNeeded, ' '));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cursor.insertText("\t");
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter / Return: auto-indent
|
// -----------------------------------------------------------------------
|
||||||
|
// Smart Backspace: springt zur vorherigen Einrückungsstufe
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
if (event->key() == Qt::Key_Backspace
|
||||||
|
&& !textCursor().hasSelection()
|
||||||
|
&& m_settings->useSpacesForTabs())
|
||||||
|
{
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
const int col = cursor.columnNumber();
|
||||||
|
|
||||||
|
if (col > 0)
|
||||||
|
{
|
||||||
|
// Prüfen ob links vom Cursor nur Leerzeichen bis Zeilenbeginn stehen
|
||||||
|
const QString lineText = cursor.block().text();
|
||||||
|
const QString leftOfCursor = lineText.left(col);
|
||||||
|
const bool onlySpaces = leftOfCursor.trimmed().isEmpty();
|
||||||
|
|
||||||
|
if (onlySpaces && col > 0)
|
||||||
|
{
|
||||||
|
// Zur vorherigen Tab-Stop-Position springen
|
||||||
|
const int targetCol = ((col - 1) / tabSize) * tabSize;
|
||||||
|
const int toDelete = col - targetCol;
|
||||||
|
|
||||||
|
cursor.movePosition(QTextCursor::Left,
|
||||||
|
QTextCursor::KeepAnchor,
|
||||||
|
toDelete);
|
||||||
|
cursor.removeSelectedText();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// Enter / Return: Auto-Indent
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
||||||
{
|
{
|
||||||
QTextCursor cursor = textCursor();
|
QTextCursor cursor = textCursor();
|
||||||
const QString currentLine = cursor.block().text();
|
const QString currentLine = cursor.block().text();
|
||||||
|
|
||||||
// Count leading whitespace
|
// Führende Leerzeichen der aktuellen Zeile zählen
|
||||||
int leadingSpaces = 0;
|
int leadingSpaces = 0;
|
||||||
for (const QChar &ch : currentLine)
|
for (const QChar &ch : currentLine)
|
||||||
{
|
{
|
||||||
@@ -319,7 +426,7 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
|
|||||||
}
|
}
|
||||||
else if (ch == '\t')
|
else if (ch == '\t')
|
||||||
{
|
{
|
||||||
leadingSpaces += m_settings->tabSize();
|
leadingSpaces += tabSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -327,15 +434,13 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the base class insert the newline first
|
|
||||||
QPlainTextEdit::keyPressEvent(event);
|
QPlainTextEdit::keyPressEvent(event);
|
||||||
|
|
||||||
// Then re-indent
|
|
||||||
if (leadingSpaces > 0)
|
if (leadingSpaces > 0)
|
||||||
{
|
{
|
||||||
const QString indent = m_settings->useSpacesForTabs()
|
const QString indent = m_settings->useSpacesForTabs()
|
||||||
? QString(leadingSpaces, ' ')
|
? QString(leadingSpaces, ' ')
|
||||||
: QString(leadingSpaces / m_settings->tabSize(), '\t');
|
: QString(leadingSpaces / tabSize, '\t');
|
||||||
textCursor().insertText(indent);
|
textCursor().insertText(indent);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -343,3 +448,4 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
|
|||||||
|
|
||||||
QPlainTextEdit::keyPressEvent(event);
|
QPlainTextEdit::keyPressEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "SearchPanel.h"
|
#include "SearchPanel.h"
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QTextDocument>
|
||||||
|
|
||||||
EditorPanel::EditorPanel(Settings *settings, QWidget *parent)
|
EditorPanel::EditorPanel(Settings *settings, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
@@ -70,7 +71,20 @@ void EditorPanel::openFile(const QString &filePath)
|
|||||||
m_tabWidget->setTabToolTip(index, filePath);
|
m_tabWidget->setTabToolTip(index, filePath);
|
||||||
m_openTabs.insert(filePath, tab);
|
m_openTabs.insert(filePath, tab);
|
||||||
|
|
||||||
// Tab-Titel nach "Speichern unter" aktualisieren
|
// Änderungsindikator im Tab-Titel (● = ungespeichert)
|
||||||
|
connect(tab->editor()->document(), &QTextDocument::modificationChanged,
|
||||||
|
this, [this, tab](bool modified)
|
||||||
|
{
|
||||||
|
const int idx = m_tabWidget->indexOf(tab);
|
||||||
|
if (idx == -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QString name = QFileInfo(tab->filePath()).fileName();
|
||||||
|
m_tabWidget->setTabText(idx, modified ? "● " + name : name);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tab-Titel nach "Speichern unter" aktualisieren (neuer Dateiname, kein Punkt)
|
||||||
connect(tab->editor(), &CodeEditor::fileSaved, this, [this, tab](const QString &savedPath)
|
connect(tab->editor(), &CodeEditor::fileSaved, this, [this, tab](const QString &savedPath)
|
||||||
{
|
{
|
||||||
const int idx = m_tabWidget->indexOf(tab);
|
const int idx = m_tabWidget->indexOf(tab);
|
||||||
|
|||||||
Reference in New Issue
Block a user