QCodeEdit blockselection patch, ready to use

This commit is contained in:
2020-09-23 22:14:13 +03:00
parent a89fb3d8f2
commit 577f20a110
2 changed files with 95 additions and 39 deletions

View File

@@ -30,18 +30,12 @@ public:
}
void paintEvent(QPaintEvent * e) override {
//qDebug() << "paint" << geometry();
//QPainter p(this);
//p.fillRect(rect(), Qt::red);
//QWidget::paintEvent(e);
if (!isEnabled()) return;
ce->drawCursor();
}
bool event(QEvent * e) override {
//qDebug() << "event" << e;
return QWidget::event(e);
}
QCodeEdit * ce;
};
@@ -157,6 +151,7 @@ QCodeEdit::QCodeEdit(QWidget * parent): QWidget(parent) {
connect(ui->textCode, SIGNAL(textChanged()), this, SIGNAL(textChanged()));
connect(ui->textCode, SIGNAL(cursorPositionChanged()), this, SLOT(textEdit_cursorPositionChanged()));
connect(ui->textCode, SIGNAL(selectionChanged()), this, SLOT(textEdit_selectionChanged()));
connect(ui->textCode, SIGNAL(redoAvailable(bool)), this, SLOT(textEdit_redoAvailable(bool)));
connect(ui->comboSearch->lineEdit(), SIGNAL(returnPressed()), this, SLOT(searchNext()));
connect(ui->comboReplace->lineEdit(), SIGNAL(returnPressed()), this, SLOT(on_buttonReplaceSearch_clicked()));
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
@@ -190,6 +185,7 @@ QTextDocument * QCodeEdit::document() const {
void QCodeEdit::setDocument(QTextDocument * doc) {
cancelBlockSelection();
if (document()) {
document()->setProperty("_cursor", QVariant::fromValue(textCursor()));
document()->setProperty("_vpos", textEdit()->verticalScrollBar()->value());
@@ -454,23 +450,36 @@ bool QCodeEdit::eventFilter(QObject * o, QEvent * e) {
}
if (ui->textCode) {
if (o == ui->textCode->viewport()) {
if (e->type() == QEvent::MouseButtonPress) {
switch (e->type()) {
case QEvent::MouseButtonPress: {
cancelBlockSelection();
completer->hide();
hideHelp();
QMouseEvent * me = (QMouseEvent*)e;
if (me->modifiers().testFlag(Qt::ControlModifier) && (me->button() == Qt::LeftButton)) {
if (me->modifiers().testFlag(Qt::ControlModifier) && (me->button() == Qt::LeftButton))
gotoLink();
}
}
if (e->type() == QEvent::MouseMove && completer->isHidden()) {
} break;
case QEvent::MouseMove: {
if (!completer->isHidden()) break;
QMouseEvent * me = (QMouseEvent*)e;
switchBlockSelection();
if (me->modifiers().testFlag(Qt::ControlModifier))
showLink();
}
if (e->type() == QEvent::Paint) {
} break;
case QEvent::Paint:
resizeOverlay();
break;
case QEvent::DragMove:
if (!isEnabled()) break;
drag_cursor = ui->textCode->cursorForPosition(((QDragMoveEvent*)e)->pos());
repaintCursor();
break;
case QEvent::MouseButtonRelease:
case QEvent::DragLeave:
case QEvent::Drop:
cancelDragCursor();
break;
default: break;
}
return QWidget::eventFilter(o, e);
}
@@ -498,6 +507,9 @@ bool QCodeEdit::eventFilter(QObject * o, QEvent * e) {
_ignore_focus_out = false;
break;
}
case QEvent::FocusIn:
createBlockSelection();
break;
case QEvent::Hide:
case QEvent::HideToParent:
hideLink();
@@ -636,7 +648,7 @@ bool QCodeEdit::codeKeyEvent(QKeyEvent * ke) {
case Qt::Key_Return:
if (hasBlockSelection()) {
cancelBlockSelection();
break;
return true;
}
if (completer->isVisible()) {
commitCompletition();
@@ -745,7 +757,8 @@ void QCodeEdit::highlightBrackets() {
void QCodeEdit::applyExtraSelection() {
ui->textCode->setExtraSelections(QList<QTextEdit::ExtraSelection>() << es_line << es_selected
<< es_custom << es_brackets << es_search_list << es_cursor << es_link);
<< es_custom << es_brackets << es_search_list << es_cursor
<< es_link << es_blockselection);
}
@@ -774,7 +787,7 @@ int QCodeEdit::searchIndFromCursor() {
}
QRect QCodeEdit::cursorRect(QRect * line) {
QRect QCodeEdit::cursorRect() {
QRect r = ui->textCode->cursorRect(textCursor()), lr = r;
if (hasBlockSelection()) {
r |= ui->textCode->cursorRect(block_start_cursor);
@@ -782,15 +795,14 @@ QRect QCodeEdit::cursorRect(QRect * line) {
lr.setHeight(r.height());
}
lr.setWidth(cursor_width);
if (line) *line = lr;
return (r | lr);
return lr;
}
QRect QCodeEdit::blockSelectionRect() {
QTextCursor tc = ui->textCode->textCursor();
QPoint ps(block_start_cursor.columnNumber(), block_start_cursor.blockNumber()),
pe(tc.columnNumber(), tc.blockNumber());
QPoint ps(block_start_cursor.positionInBlock(), block_start_cursor.blockNumber()),
pe(tc.positionInBlock(), tc.blockNumber());
QRect bsr(QPoint(qMin(ps.x(), pe.x()), qMin(ps.y(), pe.y())),
QSize(qAbs(ps.x() - pe.x()), qAbs(ps.y() - pe.y()) + 1));
return bsr;
@@ -803,20 +815,22 @@ void QCodeEdit::repaintCursor() {
void QCodeEdit::drawCursor() {
if (!isEnabled() || !ui->textCode->hasFocus()) return;
QPainter p(overlay);
QTextCursor tc = textCursor();
//qDebug() << block_start_cursor.position() << tc.position();
QRect line, all = cursorRect(&line);
if (hasBlockSelection() && (tc.columnNumber() != block_start_cursor.columnNumber())) {
p.setCompositionMode(QPainter::CompositionMode_Difference);
QColor hc = palette().color(QPalette::Highlight);
p.fillRect(all, QColor(255 - hc.red(), 255 - hc.green(), 255 - hc.blue()));
}
QRect line = cursorRect();
if (cursor_state && ui->textCode->hasFocus()) {
line.adjust(0, 1, 0, -1);
p.setCompositionMode(QPainter::CompositionMode_Difference);
p.fillRect(line, Qt::white);
}
if (!drag_cursor.isNull()) {
line = ui->textCode->cursorRect(drag_cursor);
line.setWidth(cursor_width);
p.setCompositionMode(QPainter::CompositionMode_Difference);
p.fillRect(line, Qt::white);
}
}
@@ -830,17 +844,20 @@ void QCodeEdit::startBlockSelection() {
QTextCursor tc = textCursor();
block_start_cursor = tc;
block_start_cursor.setPosition(tc.selectionStart());
}}
}
}
void QCodeEdit::cancelBlockSelection() {
block_start_cursor = QTextCursor();
es_blockselection.clear();
applyExtraSelection();
}
void QCodeEdit::switchBlockSelection(QKeyEvent * ke) {
bool alt = QApplication::keyboardModifiers().testFlag(Qt::AltModifier);
if (ke) alt = ke->modifiers().testFlag(Qt::AltModifier);
if (ke) alt = ke->modifiers().testFlag(Qt::AltModifier) && ke->modifiers().testFlag(Qt::ShiftModifier);
if (alt) {
startBlockSelection();
QTextCursor tc = ui->textCode->textCursor();
@@ -875,10 +892,10 @@ bool QCodeEdit::removeBlockSelection(bool is_del) {
//qDebug() << bsr;
for (int l = bsr.top(); l <= bsr.bottom(); ++l) {
QTextCursor ctc(ui->textCode->document()->findBlockByNumber(l));
ctc.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, bsr.left());
ctc.setPosition(ctc.block().position() + bsr.left(), QTextCursor::MoveAnchor);
if (l != ctc.blockNumber()) continue;
int pos = ctc.position();
ctc.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, bsr.width());
ctc.setPosition(ctc.block().position() + bsr.right() + 1, QTextCursor::KeepAnchor);
if (l != ctc.blockNumber()) {
ctc.setPosition(pos);
ctc.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
@@ -900,7 +917,7 @@ void QCodeEdit::insertBlockSelection(QString text) {
if (bsr.width() > 0) removeBlockSelection(false);
for (int l = bsr.top(); l <= bsr.bottom(); ++l) {
QTextCursor ctc(ui->textCode->document()->findBlockByNumber(l));
ctc.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, bsr.left());
ctc.setPosition(ctc.block().position() + bsr.left(), QTextCursor::MoveAnchor);
if (l != ctc.blockNumber()) {
ctc = QTextCursor(ui->textCode->document()->findBlockByNumber(l));
ctc.movePosition(QTextCursor::EndOfLine);
@@ -914,6 +931,36 @@ void QCodeEdit::insertBlockSelection(QString text) {
}
void QCodeEdit::createBlockSelection() {
if (!hasBlockSelection()) return;
es_blockselection.clear();
QTextEdit::ExtraSelection es;
es.format.setForeground(palette().brush(QPalette::HighlightedText));
es.format.setBackground(palette().brush(QPalette::Highlight));
QRect bsr = blockSelectionRect();
for (int l = bsr.top(); l <= bsr.bottom(); ++l) {
QTextCursor ctc(ui->textCode->document()->findBlockByNumber(l));
ctc.setPosition(ctc.block().position() + bsr.left(), QTextCursor::MoveAnchor);
if (l != ctc.blockNumber()) continue;
int pos = ctc.position();
ctc.setPosition(ctc.block().position() + bsr.right() + 1, QTextCursor::KeepAnchor);
if (l != ctc.blockNumber()) {
ctc.setPosition(pos);
ctc.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
}
es.cursor = ctc;
es_blockselection << es;
}
applyExtraSelection();
}
void QCodeEdit::cancelDragCursor() {
drag_cursor = QTextCursor();
overlay->update();
}
void QCodeEdit::searchAll() {
QString st = ui->comboSearch->currentText();
es_search_list.clear();
@@ -1206,7 +1253,6 @@ void QCodeEdit::autoIndent() {
QTextCursor tc = ui->textCode->textCursor(), stc = tc;
tc.movePosition(QTextCursor::StartOfLine);
if (!tc.movePosition(QTextCursor::Up)) return;
tc.beginEditBlock();
tc.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor);
QString line = tc.selectedText(), tabs;
int i = 0;
@@ -1220,9 +1266,10 @@ void QCodeEdit::autoIndent() {
int nt = qMax<int>(0, line.count(QChar('{')) - line.count(QChar('}')));
tabs.append(QString("\t").repeated(nt));
if (tabs.isEmpty()) return;
stc.beginEditBlock();
stc.insertText(tabs);
ui->textCode->setTextCursor(stc);
tc.endEditBlock();
stc.endEditBlock();
}
@@ -1641,6 +1688,7 @@ void QCodeEdit::commitCompletition() {
void QCodeEdit::textEdit_cursorPositionChanged() {
es_line.cursor = ui->textCode->textCursor();
//qDebug() << "cursorPositionChanged" << es_line.cursor.position();
es_line.cursor.select(QTextCursor::LineUnderCursor);
es_line.cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
highlightBrackets();
@@ -1648,7 +1696,7 @@ void QCodeEdit::textEdit_cursorPositionChanged() {
if (timer_blink) killTimer(timer_blink);
timer_blink = startTimer(QApplication::cursorFlashTime() / 2);
cursor_state = true;
repaintCursor();
createBlockSelection();
}
@@ -1690,6 +1738,11 @@ void QCodeEdit::textEdit_selectionChanged() {
}
void QCodeEdit::textEdit_redoAvailable(bool available) {
if (available) cancelBlockSelection();
}
void QCodeEdit::setShowSpaces(bool yes) {
spaces_ = yes;
QTextOption to = ui->textCode->document()->defaultTextOption();

View File

@@ -143,11 +143,11 @@ private:
QFrame * widget_help;
_QCE_Viewport * overlay;
QTextEdit::ExtraSelection es_line, es_cursor, es_bracket, es_range, es_search, es_link;
QList<QTextEdit::ExtraSelection> es_selected, es_custom, es_brackets, es_search_list;
QList<QTextEdit::ExtraSelection> es_selected, es_custom, es_brackets, es_search_list, es_blockselection;
QMap<int, ACClass> ac_classes;
QStringList cursor_scope;
ACEntry link_entry, help_entry;
QTextCursor block_start_cursor;
QTextCursor block_start_cursor, drag_cursor;
int prev_lc, auto_comp_pl, timer_parse, timer_blink, cur_search_ind, pos_press, pos_el_press;
int cursor_width;
bool spaces_, _ignore_focus_out, _first, _destructor, _replacing;
@@ -164,7 +164,7 @@ private:
void clearSearch();
void moveToSearch();
int searchIndFromCursor();
QRect cursorRect(QRect * line = 0);
QRect cursorRect();
QRect blockSelectionRect();
void repaintCursor();
void drawCursor();
@@ -174,6 +174,8 @@ private:
void switchBlockSelection(QKeyEvent * ke = 0);
bool removeBlockSelection(bool is_del);
void insertBlockSelection(QString text);
void createBlockSelection();
void cancelDragCursor();
ACEntry findEntryOnCursor(QTextCursor tc, int arg = -1, ACClass * acc = 0, QPair<QStringList, QString> * scope = 0);
private slots:
@@ -202,6 +204,7 @@ private slots:
void textEdit_cursorPositionChanged();
void textEdit_textChanged();
void textEdit_selectionChanged();
void textEdit_redoAvailable(bool available);
void on_comboSearch_currentTextChanged(const QString & t);
void on_buttonReplace_clicked();
void on_buttonReplaceSearch_clicked();