Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 43 additions & 22 deletions src/editor/dtextedit.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2011-2023 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2011 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand Down Expand Up @@ -1602,30 +1602,51 @@ void TextEdit::unindentText()
{
qDebug() << "Unindenting text";
QTextCursor cursor = this->textCursor();
cursor.movePosition(QTextCursor::StartOfBlock);
int pos = cursor.position();
cursor.setPosition(cursor.position() + 1, QTextCursor::KeepAnchor);

//the text in front of current line is '\t'.
if ("\t" == cursor.selectedText()) {
qDebug() << "Unindenting text with tab";
DeleteBackCommand *com = new DeleteBackCommand(cursor, this);
if (cursor.hasSelection()) {
qDebug() << "Unindenting text with selection";
//calculate the start postion and the end postion of current selection.
int pos1 = cursor.position();
int pos2 = cursor.anchor();
if (pos1 > pos2)
std::swap(pos1, pos2);

//calculate the start line and end line of current selection.
cursor.setPosition(pos1);
int line1 = cursor.blockNumber();
cursor.setPosition(pos2);
int line2 = cursor.blockNumber();

//do the unindent operation for multiple lines
auto com = new UnindentTextCommand(this, pos1, pos2, line1, line2, m_tabSpaceNumber);
m_pUndoStack->push(com);
}
//the text in front of current line is ' '.
else if (" " == cursor.selectedText()) {
qDebug() << "Unindenting text with space";
int startpos = pos;
int cnt = 0;
// calculate the number of ' '.
while (document()->characterAt(pos) == ' ' && cnt < m_tabSpaceNumber) {
pos++;
cnt++;
} else {
//single line unindent (original behavior)
cursor.movePosition(QTextCursor::StartOfBlock);
int pos = cursor.position();
cursor.setPosition(cursor.position() + 1, QTextCursor::KeepAnchor);

//the text in front of current line is '\t'.
if ("\t" == cursor.selectedText()) {
qDebug() << "Unindenting text with tab";
DeleteBackCommand *com = new DeleteBackCommand(cursor, this);
m_pUndoStack->push(com);
}
//the text in front of current line is ' '.
else if (" " == cursor.selectedText()) {
qDebug() << "Unindenting text with space";
int startpos = pos;
int cnt = 0;
// calculate the number of ' '.
while (document()->characterAt(pos) == ' ' && cnt < m_tabSpaceNumber) {
pos++;
cnt++;
}
cursor.setPosition(startpos);
cursor.setPosition(pos, QTextCursor::KeepAnchor);
DeleteBackCommand *com = new DeleteBackCommand(cursor, this);
m_pUndoStack->push(com);
}
cursor.setPosition(startpos);
cursor.setPosition(pos, QTextCursor::KeepAnchor);
DeleteBackCommand *com = new DeleteBackCommand(cursor, this);
m_pUndoStack->push(com);
}
qDebug() << "Unindenting text successfully";
}
Expand Down
128 changes: 127 additions & 1 deletion src/editor/indenttextcommond.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand Down Expand Up @@ -86,3 +86,129 @@ void IndentTextCommand::undo()
}
qDebug() << "IndentTextCommand undo exit";
}

UnindentTextCommand::UnindentTextCommand(TextEdit* edit,int startpos,int endpos,int startline,int endline,int tabSpaceNumber):
m_edit(edit),
m_startpos(startpos),
m_endpos(endpos),
m_startline(startline),
m_endline(endline),
m_tabSpaceNumber(tabSpaceNumber)
{
qDebug() << "UnindentTextCommand created - startpos:" << startpos
<< "endpos:" << endpos << "lines:" << startline << "-" << endline
<< "hasSelection:" << m_edit->textCursor().hasSelection();
m_hasselected = m_edit->textCursor().hasSelection();
m_removedChars.resize(endline - startline + 1);
}

UnindentTextCommand::~UnindentTextCommand()
{
qDebug() << "UnindentTextCommand destroyed";
}

void UnindentTextCommand::redo()
{
qInfo() << "UnindentTextCommand redo - removing indents from lines:"
<< m_startline << "-" << m_endline;
auto cursor = m_edit->textCursor();

//remove indentation from multiple lines.
cursor.setPosition(m_startpos);
int totalRemoved = 0;

for(int i=m_startline;i<=m_endline;i++){
cursor.movePosition(QTextCursor::StartOfBlock);
int lineStart = cursor.position();
int removed = 0;

//check if line starts with tab
if(m_edit->document()->characterAt(lineStart) == '\t'){
cursor.deleteChar();
removed = 1;
}
//check if line starts with spaces
else if(m_edit->document()->characterAt(lineStart) == ' '){
int cnt = 0;
int pos = lineStart;
while(m_edit->document()->characterAt(pos) == ' ' && cnt < m_tabSpaceNumber){
pos++;
cnt++;
}
if(cnt > 0){
cursor.setPosition(lineStart);
cursor.setPosition(pos, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
removed = cnt;
}
}

m_removedChars[i - m_startline] = removed;
totalRemoved += removed;
cursor.movePosition(QTextCursor::NextBlock);
}

//reset selection.
if(m_hasselected){
qDebug() << "UnindentTextCommand redo, m_hasselected, totalRemoved:" << totalRemoved;
if(m_startline == m_endline){
qDebug() << "UnindentTextCommand redo, m_startline == m_endline";
int newStartPos = m_startpos - m_removedChars[0];
if(newStartPos < 0) newStartPos = 0;
cursor.setPosition(newStartPos);
cursor.movePosition(QTextCursor::StartOfBlock);
cursor.movePosition(QTextCursor::EndOfBlock,QTextCursor::KeepAnchor);
m_edit->setTextCursor(cursor);
}
else{
qDebug() << "UnindentTextCommand redo, m_startline != m_endline";
int firstLineRemoved = m_removedChars[0];
int newStartPos = m_startpos - firstLineRemoved;
int newEndPos = m_endpos - totalRemoved;

//ensure positions are valid
if(newStartPos < 0) newStartPos = 0;
if(newEndPos < newStartPos) newEndPos = newStartPos;

cursor.setPosition(newStartPos);
cursor.setPosition(newEndPos, QTextCursor::KeepAnchor);
m_edit->setTextCursor(cursor);
}
}
qDebug() << "UnindentTextCommand redo exit";
}

void UnindentTextCommand::undo()
{
qInfo() << "UnindentTextCommand undo - restoring indents to lines:"
<< m_startline << "-" << m_endline;
auto cursor = m_edit->textCursor();

//restore indentation to multiple lines.
cursor.setPosition(m_startpos);
for(int i=m_startline;i<=m_endline;i++){
qDebug() << "UnindentTextCommand undo, i:" << i;
cursor.movePosition(QTextCursor::StartOfBlock);
int removed = m_removedChars[i - m_startline];

if(removed == 1){
//restore tab
cursor.insertText("\t");
}
else if(removed > 1){
//restore spaces
cursor.insertText(QString(removed, ' '));
}

cursor.movePosition(QTextCursor::NextBlock);
}

//reset selection
if(m_hasselected){
qDebug() << "UnindentTextCommand undo, m_hasselected";
cursor.setPosition(m_startpos);
cursor.setPosition(m_endpos, QTextCursor::KeepAnchor);
m_edit->setTextCursor(cursor);
}
qDebug() << "UnindentTextCommand undo exit";
}
30 changes: 29 additions & 1 deletion src/editor/indenttextcommond.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand Down Expand Up @@ -35,4 +35,32 @@ class IndentTextCommand:public QUndoCommand

};

//unindent text in front of multiple lines
class UnindentTextCommand:public QUndoCommand
{
public:
UnindentTextCommand(TextEdit* edit,int startpos,int endpos,int startline,int endline,int tabSpaceNumber);
virtual ~UnindentTextCommand();

virtual void redo();
virtual void undo();

private:

TextEdit* m_edit=nullptr;
//the start postion of selected text.
int m_startpos=0;
//the end postion of selected text.
int m_endpos=0;
//the start line of selected text.
int m_startline=0;
//the end line of selected text.
int m_endline=0;
bool m_hasselected=false;
int m_tabSpaceNumber=4;
//store the number of characters removed from each line
QVector<int> m_removedChars;

};

#endif // IndentTextCommand_H
Loading