diff --git a/libs/widgets/qcodeedit.cpp b/libs/widgets/qcodeedit.cpp index 2584bf2..2b98ac9 100644 --- a/libs/widgets/qcodeedit.cpp +++ b/libs/widgets/qcodeedit.cpp @@ -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() << 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(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(); diff --git a/libs/widgets/qcodeedit.h b/libs/widgets/qcodeedit.h index cc36f41..db295c3 100644 --- a/libs/widgets/qcodeedit.h +++ b/libs/widgets/qcodeedit.h @@ -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 es_selected, es_custom, es_brackets, es_search_list; + QList es_selected, es_custom, es_brackets, es_search_list, es_blockselection; QMap 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 * 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();