ready to start develop block selection

This commit is contained in:
2020-09-21 20:34:06 +03:00
parent 22b9abfcb4
commit ca020b0319
2 changed files with 108 additions and 18 deletions

View File

@@ -21,18 +21,46 @@
Q_DECLARE_METATYPE(QTextCursor) Q_DECLARE_METATYPE(QTextCursor)
Q_DECLARE_METATYPE(QCodeEdit::ACEntry) Q_DECLARE_METATYPE(QCodeEdit::ACEntry)
class _QCE_Viewport: public QWidget {
public:
_QCE_Viewport(QWidget * p = 0): QWidget(p) {
setObjectName("__qcodeedit_viewport__");
//setCursor(Qt::IBeamCursor);
}
void paintEvent(QPaintEvent * e) override {
//qDebug() << "paint" << geometry();
//QPainter p(this);
//p.fillRect(rect(), Qt::red);
//QWidget::paintEvent(e);
ce->drawCursor();
}
bool event(QEvent * e) override {
//qDebug() << "event" << e;
return QWidget::event(e);
}
QCodeEdit * ce;
};
QCodeEdit::QCodeEdit(QWidget * parent): QWidget(parent) { QCodeEdit::QCodeEdit(QWidget * parent): QWidget(parent) {
overlay = 0;
prev_lc = auto_comp_pl = cur_search_ind = pos_press = pos_el_press = -1;
timer_parse = 0;
_ignore_focus_out = _destructor = _replacing = cursor_state = false;
_first = true;
qRegisterMetaType<QTextCursor>(); qRegisterMetaType<QTextCursor>();
qRegisterMetaType<QCodeEdit::ACEntry>(); qRegisterMetaType<QCodeEdit::ACEntry>();
ui = new Ui::QCodeEdit(); ui = new Ui::QCodeEdit();
ui->setupUi(this); ui->setupUi(this);
overlay = new _QCE_Viewport(ui->textCode->viewport());
overlay->ce = this;
overlay->show();
ui->widgetSearch->hide(); ui->widgetSearch->hide();
ui->comboSearch->installEventFilter(this); ui->comboSearch->installEventFilter(this);
ui->comboReplace->installEventFilter(this); ui->comboReplace->installEventFilter(this);
prev_lc = auto_comp_pl = cur_search_ind = pos_press = pos_el_press = -1;
timer = 0;
_ignore_focus_out = _destructor = _replacing = false;
_first = true;
es_line.format.setBackground(QColor(240, 245, 240)); es_line.format.setBackground(QColor(240, 245, 240));
es_line.format.setProperty(QTextFormat::FullWidthSelection, true); es_line.format.setProperty(QTextFormat::FullWidthSelection, true);
es_cursor.format.setBackground(QColor(220, 255, 200)); es_cursor.format.setBackground(QColor(220, 255, 200));
@@ -62,7 +90,8 @@ QCodeEdit::QCodeEdit(QWidget * parent): QWidget(parent) {
help_visible = true; help_visible = true;
completer = new QCodeEditCompleter(); completer = new QCodeEditCompleter();
ui->textCode->setCursorWidth(qMax<int>(qRound(fontHeight() / 10.), 1)); cursor_width = qMax<int>(qRound(fontHeight() / 10.), 1);
ui->textCode->setCursorWidth(0);
ui->textCode->viewport()->setMouseTracking(true); ui->textCode->viewport()->setMouseTracking(true);
ui->textLines->viewport()->setAutoFillBackground(false); ui->textLines->viewport()->setAutoFillBackground(false);
ui->textLines->viewport()->setCursor(Qt::ArrowCursor); ui->textLines->viewport()->setCursor(Qt::ArrowCursor);
@@ -122,6 +151,8 @@ QCodeEdit::QCodeEdit(QWidget * parent): QWidget(parent) {
connect(completer, SIGNAL(gotoHRef(QCodeEdit::ACEntry)), this, SLOT(gotoHelpHRef(QCodeEdit::ACEntry))); connect(completer, SIGNAL(gotoHRef(QCodeEdit::ACEntry)), this, SLOT(gotoHelpHRef(QCodeEdit::ACEntry)));
connect(ui->textCode->verticalScrollBar(), SIGNAL(valueChanged(int)), ui->textLines->verticalScrollBar(), SLOT(setValue(int))); connect(ui->textCode->verticalScrollBar(), SIGNAL(valueChanged(int)), ui->textLines->verticalScrollBar(), SLOT(setValue(int)));
connect(ui->textCode->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(hideHelp())); connect(ui->textCode->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(hideHelp()));
connect(ui->textCode->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(resizeOverlay()));
connect(ui->textCode->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(resizeOverlay()));
connect(ui->textCode, SIGNAL(textChanged()), this, SLOT(textEdit_textChanged())); connect(ui->textCode, SIGNAL(textChanged()), this, SLOT(textEdit_textChanged()));
connect(ui->textCode, SIGNAL(textChanged()), this, SIGNAL(textChanged())); connect(ui->textCode, SIGNAL(textChanged()), this, SIGNAL(textChanged()));
connect(ui->textCode, SIGNAL(cursorPositionChanged()), this, SLOT(textEdit_cursorPositionChanged())); connect(ui->textCode, SIGNAL(cursorPositionChanged()), this, SLOT(textEdit_cursorPositionChanged()));
@@ -132,7 +163,8 @@ QCodeEdit::QCodeEdit(QWidget * parent): QWidget(parent) {
connect(qApp, &QGuiApplication::focusWindowChanged, this, [this](QWindow*w){if (w == 0) {hideHelp(); completer->hide();}}); connect(qApp, &QGuiApplication::focusWindowChanged, this, [this](QWindow*w){if (w == 0) {hideHelp(); completer->hide();}});
#endif #endif
updateLines(); updateLines();
timer_blink = startTimer(QApplication::cursorFlashTime() / 2);
registerAutoCompletitionClass(-1, QCodeEdit::Keyword, "Words", QIcon(":/icons/code-word.png")); registerAutoCompletitionClass(-1, QCodeEdit::Keyword, "Words", QIcon(":/icons/code-word.png"));
} }
@@ -173,7 +205,8 @@ void QCodeEdit::setDocument(QTextDocument * doc) {
if (!qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout())) if (!qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout()))
doc->setDocumentLayout(new QPlainTextDocumentLayout(doc)); doc->setDocumentLayout(new QPlainTextDocumentLayout(doc));
ui->textCode->setDocument(doc); ui->textCode->setDocument(doc);
ui->textCode->setCursorWidth(qMax<int>(qRound(fontHeight() / 10.), 1)); cursor_width = qMax<int>(qRound(fontHeight() / 10.), 1);
//ui->textCode->setCursorWidth(qMax<int>(qRound(fontHeight() / 10.), 1));
setShowSpaces(spaces_); setShowSpaces(spaces_);
if (doc->property("_cursor").isValid()) { if (doc->property("_cursor").isValid()) {
setTextCursor(doc->property("_cursor").value<QTextCursor>()); setTextCursor(doc->property("_cursor").value<QTextCursor>());
@@ -436,6 +469,9 @@ bool QCodeEdit::eventFilter(QObject * o, QEvent * e) {
gotoLink(); gotoLink();
} }
} }
if (e->type() == QEvent::Paint) {
resizeOverlay();
}
return QWidget::eventFilter(o, e); return QWidget::eventFilter(o, e);
} }
if (o == ui->textCode) { if (o == ui->textCode) {
@@ -592,11 +628,17 @@ void QCodeEdit::showEvent(QShowEvent * ) {
} }
void QCodeEdit::timerEvent(QTimerEvent * ) { void QCodeEdit::timerEvent(QTimerEvent * e) {
parse(); if (e->timerId() == timer_parse) {
emit parseRequest(); parse();
killTimer(timer); emit parseRequest();
timer = 0; killTimer(timer_parse);
timer_parse = 0;
}
if (e->timerId() == timer_blink) {
cursor_state = !cursor_state;
repaintCursor();
}
} }
@@ -705,6 +747,37 @@ int QCodeEdit::searchIndFromCursor() {
} }
void QCodeEdit::repaintCursor() {
QRect r = ui->textCode->cursorRect(ui->textCode->textCursor());
r.setWidth(cursor_width);
//r.translate(-cursor_width, 0);
overlay->update(r);
}
void QCodeEdit::drawCursor() {
QPainter p(overlay);
QTextCursor tc = textCursor();
if (cursor_state && ui->textCode->hasFocus()) {
QTextLayout * lay = tc.block().layout();
if (lay) {
//QTextLine l = lay->lineForTextPosition(tc.positionInBlock());
//int x = l.cursorToX(tc.position(), QTextLine::Trailing);
p.setPen(Qt::black);
QRect r = ui->textCode->cursorRect(tc);
r.setWidth(cursor_width);
r.adjust(0, 1, 0, -1);
//r.translate(-cursor_width, 0);
p.setCompositionMode(QPainter::CompositionMode_Difference);
p.fillRect(r, Qt::white);
//p.fillRect(p.viewport(), Qt::red);
//qDebug() << x << l.y() << cursor_width << l.height();
//p.fillRect(x, l.y(), cursor_width, l.height(), Qt::black);
}
}
}
void QCodeEdit::searchAll() { void QCodeEdit::searchAll() {
QString st = ui->comboSearch->currentText(); QString st = ui->comboSearch->currentText();
es_search_list.clear(); es_search_list.clear();
@@ -1014,7 +1087,7 @@ void QCodeEdit::showLink() {
return; return;
} }
es_link.cursor = tc; es_link.cursor = tc;
ui->textCode->viewport()->setCursor(tc.isNull() ? Qt::IBeamCursor : Qt::PointingHandCursor); overlay->setCursor(tc.isNull() ? Qt::IBeamCursor : Qt::PointingHandCursor);
applyExtraSelection(); applyExtraSelection();
//qDebug() << "showLink" << tc.selectedText() << link_entry.type << link_entry.name; //qDebug() << "showLink" << tc.selectedText() << link_entry.type << link_entry.name;
} }
@@ -1022,7 +1095,7 @@ void QCodeEdit::showLink() {
void QCodeEdit::hideLink() { void QCodeEdit::hideLink() {
es_link.cursor = QTextCursor(); es_link.cursor = QTextCursor();
ui->textCode->viewport()->setCursor(Qt::IBeamCursor); overlay->setCursor(Qt::IBeamCursor);
link_entry = ACEntry(); link_entry = ACEntry();
applyExtraSelection(); applyExtraSelection();
//qDebug() << "hideLink"; //qDebug() << "hideLink";
@@ -1074,8 +1147,8 @@ void QCodeEdit::setText(const QString & t) {
void QCodeEdit::updateLines() { void QCodeEdit::updateLines() {
if (timer > 0) killTimer(timer); if (timer_parse > 0) killTimer(timer_parse);
timer = startTimer(500); timer_parse = startTimer(500);
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
# if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) # if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
ui->textCode->setTabStopDistance(ui->textCode->fontMetrics().horizontalAdvance(" ")); ui->textCode->setTabStopDistance(ui->textCode->fontMetrics().horizontalAdvance(" "));
@@ -1205,6 +1278,12 @@ void QCodeEdit::gotoHelpHRef(QCodeEdit::ACEntry e) {
} }
void QCodeEdit::resizeOverlay() {
if (overlay)
overlay->setGeometry(ui->textCode->viewport()->geometry());
}
void QCodeEdit::hideHelp() { void QCodeEdit::hideHelp() {
help_entry = ACEntry(); help_entry = ACEntry();
widget_help->hide(); widget_help->hide();
@@ -1414,6 +1493,10 @@ void QCodeEdit::textEdit_cursorPositionChanged() {
es_line.cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); es_line.cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
highlightBrackets(); highlightBrackets();
applyExtraSelection(); applyExtraSelection();
if (timer_blink) killTimer(timer_blink);
timer_blink = startTimer(QApplication::cursorFlashTime() / 2);
cursor_state = true;
repaintCursor();
} }

View File

@@ -32,6 +32,7 @@ namespace Ui {
} }
class QCodeEditCompleter; class QCodeEditCompleter;
class _QCE_Viewport;
class QAD_WIDGETS_EXPORT QCodeEdit: public QWidget class QAD_WIDGETS_EXPORT QCodeEdit: public QWidget
@@ -44,6 +45,7 @@ class QAD_WIDGETS_EXPORT QCodeEdit: public QWidget
Q_PROPERTY(QFont editorFont READ editorFont WRITE setEditorFont) Q_PROPERTY(QFont editorFont READ editorFont WRITE setEditorFont)
friend class QCodeEditCompleter; friend class QCodeEditCompleter;
friend class _QCE_Viewport;
public: public:
QCodeEdit(QWidget * parent = 0); QCodeEdit(QWidget * parent = 0);
@@ -139,14 +141,16 @@ private:
QCodeEditCompleter * completer; QCodeEditCompleter * completer;
IconedLabel * lbl_help[3]; IconedLabel * lbl_help[3];
QFrame * widget_help; QFrame * widget_help;
_QCE_Viewport * overlay;
QTextEdit::ExtraSelection es_line, es_cursor, es_bracket, es_range, es_search, es_link; 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;
QMap<int, ACClass> ac_classes; QMap<int, ACClass> ac_classes;
QStringList cursor_scope; QStringList cursor_scope;
ACEntry link_entry, help_entry; ACEntry link_entry, help_entry;
int prev_lc, auto_comp_pl, timer, cur_search_ind, pos_press, pos_el_press; 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; bool spaces_, _ignore_focus_out, _first, _destructor, _replacing;
bool word_complete, help_visible; bool word_complete, help_visible, cursor_state;
bool eventFilter(QObject * o, QEvent * e) override; bool eventFilter(QObject * o, QEvent * e) override;
void showEvent(QShowEvent * ) override; void showEvent(QShowEvent * ) override;
@@ -158,11 +162,14 @@ private:
void clearSearch(); void clearSearch();
void moveToSearch(); void moveToSearch();
int searchIndFromCursor(); int searchIndFromCursor();
void repaintCursor();
void drawCursor();
ACEntry findEntryOnCursor(QTextCursor tc, int arg = -1, ACClass * acc = 0, QPair<QStringList, QString> * scope = 0); ACEntry findEntryOnCursor(QTextCursor tc, int arg = -1, ACClass * acc = 0, QPair<QStringList, QString> * scope = 0);
private slots: private slots:
void _activateLink(QCodeEdit::ACEntry e) {linkClicked(e);} void _activateLink(QCodeEdit::ACEntry e) {linkClicked(e);}
void gotoHelpHRef(QCodeEdit::ACEntry e); void gotoHelpHRef(QCodeEdit::ACEntry e);
void resizeOverlay();
void syncScrolls(); void syncScrolls();
void scrollUp(); void scrollUp();
void scrollDown(); void scrollDown();