From d8d3b660a6a96a18999fc10518a5b80fda4b4ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Mon, 18 Dec 2017 15:12:05 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/libs@341 a8b55f48-bf90-11e4-a774-851b48703e85 --- make_android.bat | 15 ++ qad/graphic/graphic.cpp | 9 +- qad/graphic/graphic.h | 1 + qad/widgets/qad_widgets.qrc | 86 +++---- qad/widgets/qcodeedit.cpp | 458 ++++++++++++++++++++++++++---------- qad/widgets/qcodeedit.h | 69 ++++-- qad/widgets/qcodeedit.ui | 389 ++++++++++++++++++++++++++++++ 7 files changed, 843 insertions(+), 184 deletions(-) create mode 100644 make_android.bat create mode 100644 qad/widgets/qcodeedit.ui diff --git a/make_android.bat b/make_android.bat new file mode 100644 index 0000000..9e67e1d --- /dev/null +++ b/make_android.bat @@ -0,0 +1,15 @@ +set Qt5_ROOT=d:\Qt\5.10.0\android_armv7\lib\cmake\ +set Qt5_DIR=%Qt5_ROOT%\Qt5 +set Qt5LinguistTools_DIR=%Qt5_ROOT%\Qt5LinguistTools +set Qt5UiPlugin_DIR=%Qt5_ROOT%\Qt5UiPlugin +set Qt5Widgets_DIR=%Qt5_ROOT%\Qt5Widgets +set Qt5Core_DIR=%Qt5_ROOT%\Qt5Core +set Qt5Gui_DIR=%Qt5_ROOT%\Qt5Gui +set Qt5Sql_DIR=%Qt5_ROOT%\Qt5Sql +set Qt5OpenGL_DIR=%Qt5_ROOT%\Qt5OpenGL +set Qt5Designer_DIR=%Qt5_ROOT%\Qt5Designer +set Qt5PrintSupport_DIR=%Qt5_ROOT%\Qt5PrintSupport +set Qt5Script_DIR=%Qt5_ROOT%\Qt5Script +cmake_mgw -Wno-dev -DCMAKE_TOOLCHAIN_FILE=d:\Distrib\Android\android-sdk-windows\ndk-bundle\build\cmake\android.toolchain.cmake -DANDROID_PLATFORM=android-24 -DICU=0 -DQt4=0 -DQt5=1 -DQGLVIEW=0 -DQt5_DIR=%Qt5_ROOT%\Qt5 -DQt5LinguistTools_DIR=%Qt5_ROOT%\Qt5LinguistTools -DQt5UiPlugin_DIR=%Qt5_ROOT%\Qt5UiPlugin -DQt5Widgets_DIR=%Qt5_ROOT%\Qt5Widgets -DQt5Core_DIR=%Qt5_ROOT%\Qt5Core -DQt5Gui_DIR=%Qt5_ROOT%\Qt5Gui -DQt5Sql_DIR=%Qt5_ROOT%\Qt5Sql -DQt5OpenGL_DIR=%Qt5_ROOT%\Qt5OpenGL -DQt5PrintSupport_DIR=%Qt5_ROOT%\Qt5PrintSupport -DQt5Script_DIR=%Qt5_ROOT%\Qt5Script ..\libs + +:cmake_mgw -Wno-dev -DCMAKE_TOOLCHAIN_FILE=d:\Distrib\Android\android-sdk-windows\ndk-bundle\build\cmake\android.toolchain.cmake -DANDROID_PLATFORM=android-24 -DICU=0 -DQt4=0 -DQt5=1 -DQt5_DIR=%Qt5_ROOT%\Qt5 ..\libs diff --git a/qad/graphic/graphic.cpp b/qad/graphic/graphic.cpp index 1954126..d13a94d 100644 --- a/qad/graphic/graphic.cpp +++ b/qad/graphic/graphic.cpp @@ -222,8 +222,13 @@ void Graphic::canvasPaintEvent() { gridborder += QPoint(font_sz.width(), font_sz.height()); if (hasLblY) gridborder += QPoint(font_sz.height(), 0); if (hasLblX) gridborder += QPoint(0, font_sz.height()); - drawGrid(); } + painter->setClipping(true); + painter->setClipRect(QRect(gridborder.x(), 0, wid - gridborder.x(), hei - gridborder.y())); + emit beforeGraphicPaintEvent(painter); + painter->setClipping(false); + if (grid) + drawGrid(); p.setRenderHint(QPainter::Antialiasing, aalias); if (isOGL) { #ifndef ANDROID @@ -236,7 +241,7 @@ void Graphic::canvasPaintEvent() { drawGraphics(); drawGuides(); if (pause_) drawPause(); - emit graphicPaintEvent(&p); + emit graphicPaintEvent(painter); p.end(); if (isOGL) return; p.begin(canvas); diff --git a/qad/graphic/graphic.h b/qad/graphic/graphic.h index f277e07..f8c3a29 100644 --- a/qad/graphic/graphic.h +++ b/qad/graphic/graphic.h @@ -403,6 +403,7 @@ protected slots: void leaveFullscreen(); signals: + void beforeGraphicPaintEvent(QPainter * ); void graphicPaintEvent(QPainter * ); void graphicMouseMoveEvent(QPointF point, int buttons); void graphicMousePressEvent(QPointF point, int buttons); diff --git a/qad/widgets/qad_widgets.qrc b/qad/widgets/qad_widgets.qrc index 2f32824..bc585b9 100644 --- a/qad/widgets/qad_widgets.qrc +++ b/qad/widgets/qad_widgets.qrc @@ -1,44 +1,46 @@ - - lang/qad_widgets_ru.ts - ../icons/dialog-close.png - ../icons/edit-clear.png - ../icons/edit-guides.png - ../icons/view-grid.png - ../icons/zoom-fit-best.png - ../icons/configure.png - ../icons/alpha.png - ../icons/document-save.png - ../icons/edit-clear-locationbar-rtl.png - ../icons/edit-find.png - ../icons/list-add.png - ../icons/edit-delete.png - ../icons/item-add.png - ../icons/item.png - ../icons/node-add.png - ../icons/node.png - ../icons/edit-copy.png - ../icons/edit-paste.png - ../icons/expand_s_x.png - ../icons/expand_s_y.png - ../icons/expand_x.png - ../icons/expand_y.png - ../icons/border-line.png - ../icons/legend.png - ../icons/chardialog.png - ../icons/clineedit.png - ../icons/colorbutton.png - ../icons/ecombobox.png - ../icons/qpiconsole.png - ../icons/spinslider.png - ../icons/etabwidget.png - ../icons/qcodeedit.png - ../icons/qvariantedit.png - ../icons/code-word.png - ../icons/f1.png - ../icons/dialog-ok-apply.png - ../icons/dialog-warning.png - ../icons/tools-wizard.png - ../icons/evalspinbox.png - + + ../icons/go-next.png + ../icons/go-previous.png + lang/qad_widgets_ru.ts + ../icons/dialog-close.png + ../icons/edit-clear.png + ../icons/edit-guides.png + ../icons/view-grid.png + ../icons/zoom-fit-best.png + ../icons/configure.png + ../icons/alpha.png + ../icons/document-save.png + ../icons/edit-clear-locationbar-rtl.png + ../icons/edit-find.png + ../icons/list-add.png + ../icons/edit-delete.png + ../icons/item-add.png + ../icons/item.png + ../icons/node-add.png + ../icons/node.png + ../icons/edit-copy.png + ../icons/edit-paste.png + ../icons/expand_s_x.png + ../icons/expand_s_y.png + ../icons/expand_x.png + ../icons/expand_y.png + ../icons/border-line.png + ../icons/legend.png + ../icons/chardialog.png + ../icons/clineedit.png + ../icons/colorbutton.png + ../icons/ecombobox.png + ../icons/qpiconsole.png + ../icons/spinslider.png + ../icons/etabwidget.png + ../icons/qcodeedit.png + ../icons/qvariantedit.png + ../icons/code-word.png + ../icons/f1.png + ../icons/dialog-ok-apply.png + ../icons/dialog-warning.png + ../icons/tools-wizard.png + ../icons/evalspinbox.png + diff --git a/qad/widgets/qcodeedit.cpp b/qad/widgets/qcodeedit.cpp index c54fa22..7cffc13 100644 --- a/qad/widgets/qcodeedit.cpp +++ b/qad/widgets/qcodeedit.cpp @@ -10,21 +10,25 @@ #include #include #include +#include "ecombobox.h" #include "qad_types.h" +#include "ui_qcodeedit.h" QCodeEdit::QCodeEdit(QWidget * parent): QWidget(parent) { - prev_lc = auto_comp_pl = -1; - textCode = textLines = 0; - + ui = new Ui::QCodeEdit(); + ui->setupUi(this); + ui->widgetSearch->hide(); + prev_lc = auto_comp_pl = cur_search_ind = -1; timer = 0; - _ignore_focus_out = _destructor = false; + _ignore_focus_out = _destructor = _replacing = false; _first = true; es_line.format.setBackground(QColor(240, 245, 240)); es_line.format.setProperty(QTextFormat::FullWidthSelection, true); es_cursor.format.setBackground(QColor(220, 255, 200)); es_bracket.format.setBackground(QColor(180, 238, 180)); es_bracket.format.setForeground(Qt::red); + es_search.format.setBackground(QColor(255, 240, 10)); es_range.format.setBackground(QColor(230, 246, 255)); es_range.format.setProperty(QTextFormat::FullWidthSelection, true); widget_help = new QFrame(); @@ -58,60 +62,51 @@ QCodeEdit::QCodeEdit(QWidget * parent): QWidget(parent) { #endif (QHeaderView::ResizeToContents); completer->header()->setStretchLastSection(true); - //completer->setColumnWidth(0, 180); - //completer->resize(500, 200); - textCode = new QPlainTextEdit(); - textLines = new QPlainTextEdit(); - textCode->setFrameShadow(QFrame::Plain); - textCode->setFrameShape(QFrame::NoFrame); - textCode->setLineWrapMode(QPlainTextEdit::NoWrap); - textCode->setTabChangesFocus(false); - textCode->setCursorWidth(qMax(qRound(fontHeight() / 10.), 1)); - textLines->setFrameShadow(QFrame::Plain); - textLines->setFrameShape(QFrame::NoFrame); - textLines->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); - textLines->setFocusPolicy(Qt::NoFocus); - textLines->setTextInteractionFlags(Qt::NoTextInteraction); - textLines->setLineWrapMode(QPlainTextEdit::NoWrap); - textLines->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - textLines->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - textLines->viewport()->setAutoFillBackground(false); - textLines->viewport()->setCursor(Qt::ArrowCursor); - textLines->setFixedWidth(textLines->fontMetrics().width(" ")); - setLayout(new QBoxLayout(QBoxLayout::BottomToTop)); - layout()->setContentsMargins(0, 0, 0, 0); - QFrame * frame = new QFrame(); - frame->setFrameShadow(QFrame::Sunken); - frame->setFrameShape(QFrame::StyledPanel); - frame->setLayout(new QBoxLayout(QBoxLayout::LeftToRight)); - frame->layout()->setContentsMargins(0, 0, 0, 0); - frame->layout()->setSpacing(0); - frame->layout()->addWidget(textLines); - frame->layout()->addWidget(textCode); - layout()->addWidget(frame); + + ui->textCode->setCursorWidth(qMax(qRound(fontHeight() / 10.), 1)); + ui->textLines->viewport()->setAutoFillBackground(false); + ui->textLines->viewport()->setCursor(Qt::ArrowCursor); + ui->textLines->setFixedWidth(ui->textLines->fontMetrics().width(" ")); QAction * a = new QAction(this); a->setShortcut(QKeySequence("Shift+Tab")); a->setShortcutContext(Qt::WidgetShortcut); connect(a, SIGNAL(triggered(bool)), this, SLOT(deindent())); - textCode->addAction(a); + ui->textCode->addAction(a); a = new QAction(this); a->setShortcut(QKeySequence("Ctrl+D")); a->setShortcutContext(Qt::WidgetShortcut); connect(a, SIGNAL(triggered(bool)), this, SLOT(deleteLine())); - textCode->addAction(a); - frame->setFocusProxy(textCode); - QTextOption to = textLines->document()->defaultTextOption(); + ui->textCode->addAction(a); + ui->frame->setFocusProxy(ui->textCode); + QTextOption to = ui->textLines->document()->defaultTextOption(); to.setAlignment(Qt::AlignTop | Qt::AlignRight); - textLines->document()->setDefaultTextOption(to); + ui->textLines->document()->setDefaultTextOption(to); + /*to = ui->textCode->document()->defaultTextOption(); + to.setFlags(QTextOption::SuppressColors); + ui->textCode->document()->setDefaultTextOption(to);*/ setShowSpaces(true); - + + a = new QAction(this); + a->setShortcut(QKeySequence("Ctrl+F")); + a->setShortcutContext(Qt::WidgetWithChildrenShortcut); + connect(a, SIGNAL(triggered(bool)), this, SLOT(search_triggered())); + addAction(a); + + a = new QAction(this); + a->setShortcut(QKeySequence("Esc")); + a->setShortcutContext(Qt::WidgetWithChildrenShortcut); + connect(a, SIGNAL(triggered(bool)), this, SLOT(hideSearch())); + addAction(a); + connect(completer, SIGNAL(itemDoubleClicked(QTreeWidgetItem * ,int)), this, SLOT(commitCompletition())); - connect(textCode->verticalScrollBar(), SIGNAL(valueChanged(int)), textLines->verticalScrollBar(), SLOT(setValue(int))); - connect(textCode, SIGNAL(textChanged()), this, SLOT(updateLines())); - connect(textCode, SIGNAL(textChanged()), this, SIGNAL(textChanged())); - connect(textCode, SIGNAL(cursorPositionChanged()), this, SLOT(textEdit_cursorPositionChanged())); - connect(textCode, SIGNAL(selectionChanged()), this, SLOT(textEdit_selectionChanged())); + connect(ui->textCode->verticalScrollBar(), SIGNAL(valueChanged(int)), ui->textLines->verticalScrollBar(), SLOT(setValue(int))); + connect(ui->textCode, SIGNAL(textChanged()), this, SLOT(textEdit_textChanged())); + 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->comboSearch->lineEdit(), SIGNAL(returnPressed()), this, SLOT(searchNext())); + connect(ui->comboReplace->lineEdit(), SIGNAL(returnPressed()), this, SLOT(on_buttonReplaceSearch_clicked())); updateLines(); registerAutoCompletitionClass(-1, QCodeEdit::Keyword, "Words", QIcon(":/icons/code-word.png")); @@ -120,12 +115,91 @@ QCodeEdit::QCodeEdit(QWidget * parent): QWidget(parent) { QCodeEdit::~QCodeEdit() { _destructor = true; - delete textCode; - delete textLines; delete completer; //for (int i = 0; i < 2; ++i) // delete lbl_help[i]; delete widget_help; + //delete ui; +} + + +QTextCursor QCodeEdit::textCursor() const { + return ui->textCode->textCursor(); +} + + +QTextDocument * QCodeEdit::document() const { + return ui->textCode->document(); +} + + +void QCodeEdit::setTextCursor(const QTextCursor & c) { + ui->textCode->setTextCursor(c); +} + + +void QCodeEdit::centerCursor() { + ui->textCode->centerCursor(); + updateLines(); +} + + +void QCodeEdit::insertText(const QString & text) { + ui->textCode->insertPlainText(text); + updateLines(); +} + + +void QCodeEdit::appendText(const QString & text) { + ui->textCode->appendPlainText(text); + updateLines(); +} + + +void QCodeEdit::setCustomExtraSelection(const QList & es) { + es_custom = es; + applyExtraSelection(); +} + + +QRect QCodeEdit::cursorRect() const { + return ui->textCode->cursorRect(); +} + + +QRect QCodeEdit::cursorRect(const QTextCursor & cursor) const { + return ui->textCode->cursorRect(cursor); +} + + +QString QCodeEdit::text() const { + return ui->textCode->toPlainText(); +} + + +QStringList QCodeEdit::cursorScope() const { + return cursor_scope; +} + + +bool QCodeEdit::showLineNumbers() const { + return ui->textLines->isVisible(); +} + + +void QCodeEdit::setEditorFont(QFont f) { + ui->textCode->setFont(f); + ui->textLines->setFont(f); +} + + +QFont QCodeEdit::editorFont() const { + return ui->textCode->font(); +} + + +QPlainTextEdit * QCodeEdit::textEdit() const { + return ui->textCode; } @@ -197,13 +271,13 @@ bool QCodeEdit::eventFilter(QObject * o, QEvent * e) { if (_destructor) return QWidget::eventFilter(o, e); if (e->type() == QEvent::Destroy) { completer->removeEventFilter(this); - textCode->removeEventFilter(this); - textCode->viewport()->removeEventFilter(this); - textLines->viewport()->removeEventFilter(this); + ui->textCode->removeEventFilter(this); + ui->textCode->viewport()->removeEventFilter(this); + ui->textLines->viewport()->removeEventFilter(this); return QWidget::eventFilter(o, e); } - if (textLines) { - if (o == textLines->viewport()) { + if (ui->textLines) { + if (o == ui->textLines->viewport()) { if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove || e->type() == QEvent::MouseButtonDblClick) { #if (QT_VERSION < 0x050000) @@ -211,11 +285,11 @@ bool QCodeEdit::eventFilter(QObject * o, QEvent * e) { #else const_cast(((QMouseEvent*)e)->localPos()) = QPointF(0, ((QMouseEvent*)e)->localPos().y()); #endif - QApplication::sendEvent(textCode->viewport(), e); + QApplication::sendEvent(ui->textCode->viewport(), e); return true; } if (e->type() == QEvent::Wheel) { - QApplication::sendEvent(textCode->viewport(), e); + QApplication::sendEvent(ui->textCode->viewport(), e); return true; } } @@ -227,20 +301,20 @@ bool QCodeEdit::eventFilter(QObject * o, QEvent * e) { //qDebug() << e; return QWidget::eventFilter(o, e); } - if (textCode) { - if (o == textCode->viewport()) { + if (ui->textCode) { + if (o == ui->textCode->viewport()) { if (e->type() == QEvent::MouseButtonPress) { completer->hide(); hideHelp(); } if (e->type() == QEvent::ToolTip) { - QTextCursor tc = textCode->cursorForPosition(((QHelpEvent*)e)->pos()); + QTextCursor tc = ui->textCode->cursorForPosition(((QHelpEvent*)e)->pos()); tc.select(QTextCursor::WordUnderCursor); raiseHelp(tc); } return QWidget::eventFilter(o, e); } - if (o == textCode) { + if (o == ui->textCode) { //qDebug() << o << e; QMetaObject::invokeMethod(this, "syncScrolls", Qt::QueuedConnection); QKeyEvent * ke; @@ -313,11 +387,11 @@ bool QCodeEdit::eventFilter(QObject * o, QEvent * e) { completer->hide(); return true; } - if (textCode->textCursor().selectedText().isEmpty()) + if (ui->textCode->textCursor().selectedText().isEmpty()) QMetaObject::invokeMethod(this, "autoIndent", Qt::QueuedConnection); break; case Qt::Key_Tab: - if (!textCode->textCursor().selectedText().isEmpty()) { + if (!ui->textCode->textCursor().selectedText().isEmpty()) { if (ke->modifiers().testFlag(Qt::ShiftModifier)) deindent(); else @@ -366,9 +440,9 @@ void QCodeEdit::showEvent(QShowEvent * ) { if (!_first) return; _first = false; completer->installEventFilter(this); - textCode->installEventFilter(this); - textCode->viewport()->installEventFilter(this); - textLines->viewport()->installEventFilter(this); + ui->textCode->installEventFilter(this); + ui->textCode->viewport()->installEventFilter(this); + ui->textLines->viewport()->installEventFilter(this); } @@ -380,6 +454,12 @@ void QCodeEdit::timerEvent(QTimerEvent * ) { } +void QCodeEdit::leaveEvent(QEvent * e) { + hideHelp(); + QWidget::leaveEvent(e); +} + + char antiBracket(char c) { switch (c) { case '(': return ')'; @@ -397,7 +477,7 @@ char antiBracket(char c) { void QCodeEdit::highlightBrackets() { es_brackets.clear(); - QTextCursor stc = textCode->textCursor(), tc; + QTextCursor stc = ui->textCode->textCursor(), tc; QTextEdit::ExtraSelection es; stc.setPosition(stc.position()); QTextCursor::MoveOperation mop[2] = {QTextCursor::Left, QTextCursor::Right}; @@ -436,7 +516,8 @@ void QCodeEdit::highlightBrackets() { void QCodeEdit::applyExtraSelection() { - textCode->setExtraSelections(QList() << es_line << es_selected << es_custom << es_brackets << es_cursor); + ui->textCode->setExtraSelections(QList() << es_line << es_selected + << es_custom << es_brackets << es_search_list << es_cursor); } @@ -464,13 +545,72 @@ void QCodeEdit::previousCompletition() { } +void QCodeEdit::clearSearch() { + es_search_list.clear(); + applyExtraSelection(); +} + + +void QCodeEdit::moveToSearch() { + if (es_search_list.isEmpty()) return; + if (cur_search_ind < 0) cur_search_ind += es_search_list.size(); + if (cur_search_ind >= es_search_list.size()) cur_search_ind = 0; + if (cur_search_ind < 0 || cur_search_ind >= es_search_list.size()) return; + ui->textCode->setTextCursor(es_search_list[cur_search_ind].cursor); +} + + +int QCodeEdit::searchIndFromCursor() { + if (es_search_list.isEmpty()) return -1; + int ci = ui->textCode->textCursor().anchor(); + for (int i = 0; i < es_search_list.size(); ++i) + if (es_search_list[i].cursor.anchor() > ci) + return i - 1; + return -1; +} + + +void QCodeEdit::searchAll() { + QString st = ui->comboSearch->currentText(); + es_search_list.clear(); + if (!st.isEmpty() && !ui->widgetSearch->isHidden()) { + QTextDocument::FindFlags ff = 0; + if (ui->buttonSearchCase->isChecked()) ff |= QTextDocument::FindCaseSensitively; + if (ui->buttonSearchWord->isChecked()) ff |= QTextDocument::FindWholeWords; + QTextCursor tc(ui->textCode->document()->begin()); + QTextEdit::ExtraSelection es = es_search; + while (true) { + tc = ui->textCode->document()->find(st, tc, ff); + if (tc.isNull()) break; + es.cursor = tc; + es_search_list << es; + } + } + applyExtraSelection(); + QString ss; + if (es_search_list.isEmpty()) + ss = "color: rgb(180, 0, 0);"; + ui->comboSearch->lineEdit()->setStyleSheet(ss); +} + + +void QCodeEdit::search_triggered() { + QString st = ui->textCode->textCursor().selectedText(); + search(st); + //QMetaObject::invokeMethod(ui->comboSearch->lineEdit(), "returnPressed"); + if (ui->comboSearch->findText(st) < 0) + ui->comboSearch->insertItem(0, st); +} + + void QCodeEdit::syncScrolls() { - textLines->verticalScrollBar()->setValue(textCode->verticalScrollBar()->value()); + ui->textLines->verticalScrollBar()->setValue(ui->textCode->verticalScrollBar()->value()); + hideHelp(); } void QCodeEdit::deleteLine() { - QTextCursor tc = textCode->textCursor(); + QTextCursor tc = ui->textCode->textCursor(); tc.movePosition(QTextCursor::EndOfLine); tc.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); bool md = true; @@ -483,12 +623,12 @@ void QCodeEdit::deleteLine() { tc.removeSelectedText(); tc.movePosition(QTextCursor::StartOfLine); if (md) tc.movePosition(QTextCursor::Down); - textCode->setTextCursor(tc); + ui->textCode->setTextCursor(tc); } void QCodeEdit::copyLineUp() { - QTextCursor tc = textCode->textCursor(); + QTextCursor tc = ui->textCode->textCursor(); int ss = tc.selectionStart(), ss_ = ss, se = tc.selectionEnd(), se_ = se; QString st_ = tc.selection().toPlainText(); if (st_.endsWith("\n")) { @@ -510,12 +650,12 @@ void QCodeEdit::copyLineUp() { tc.setPosition(ss_); tc.setPosition(se_, QTextCursor::KeepAnchor); tc.endEditBlock(); - textCode->setTextCursor(tc); + ui->textCode->setTextCursor(tc); } void QCodeEdit::copyLineDown() { - QTextCursor tc = textCode->textCursor(); + QTextCursor tc = ui->textCode->textCursor(); int ss = tc.selectionStart(), ss_ = ss, se = tc.selectionEnd(), se_ = se; QString st_ = tc.selection().toPlainText(); if (st_.endsWith("\n")) { @@ -540,12 +680,12 @@ void QCodeEdit::copyLineDown() { tc.setPosition(ss_); tc.setPosition(se_, QTextCursor::KeepAnchor); tc.endEditBlock(); - textCode->setTextCursor(tc); + ui->textCode->setTextCursor(tc); } void QCodeEdit::moveLineUp() { - QTextCursor tc = textCode->textCursor(); + QTextCursor tc = ui->textCode->textCursor(); int ss = tc.selectionStart(), ss_ = ss, se = tc.selectionEnd(), se_ = se; QString st_ = tc.selection().toPlainText(); if (st_.endsWith("\n")) { @@ -578,12 +718,12 @@ void QCodeEdit::moveLineUp() { tc.setPosition(ss_); tc.setPosition(se_, QTextCursor::KeepAnchor); tc.endEditBlock(); - textCode->setTextCursor(tc); + ui->textCode->setTextCursor(tc); } void QCodeEdit::moveLineDown() { - QTextCursor tc = textCode->textCursor(); + QTextCursor tc = ui->textCode->textCursor(); int ss = tc.selectionStart(), ss_ = ss, se = tc.selectionEnd(), se_ = se; QString st_ = tc.selection().toPlainText(); if (st_.endsWith("\n")) { @@ -616,12 +756,12 @@ void QCodeEdit::moveLineDown() { tc.setPosition(ss_); tc.setPosition(se_, QTextCursor::KeepAnchor); tc.endEditBlock(); - textCode->setTextCursor(tc); + ui->textCode->setTextCursor(tc); } void QCodeEdit::indent() { - QTextCursor tc = textCode->textCursor(); + QTextCursor tc = ui->textCode->textCursor(); int ss = tc.selectionStart(), ss_ = ss, se = tc.selectionEnd(), se_ = se; QString st_ = tc.selection().toPlainText(); if (st_.endsWith("\n")) { @@ -640,12 +780,12 @@ void QCodeEdit::indent() { } tc.setPosition(ss_ + 1); tc.setPosition(se_, QTextCursor::KeepAnchor); - textCode->setTextCursor(tc); + ui->textCode->setTextCursor(tc); } void QCodeEdit::deindent() { - QTextCursor tc = textCode->textCursor(); + QTextCursor tc = ui->textCode->textCursor(); int ss = tc.selectionStart(), ss_ = ss, se = tc.selectionEnd(), se_ = se; QString st_ = tc.selection().toPlainText(); if (st_.endsWith("\n")) { @@ -684,12 +824,12 @@ void QCodeEdit::deindent() { } tc.setPosition(ss_); tc.setPosition(se_, QTextCursor::KeepAnchor); - textCode->setTextCursor(tc); + ui->textCode->setTextCursor(tc); } void QCodeEdit::autoIndent() { - QTextCursor tc = textCode->textCursor(), stc = tc; + QTextCursor tc = ui->textCode->textCursor(), stc = tc; tc.movePosition(QTextCursor::StartOfLine); if (!tc.movePosition(QTextCursor::Up)) return; tc.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor); @@ -706,30 +846,40 @@ void QCodeEdit::autoIndent() { tabs.append(QString("\t").repeated(nt)); if (tabs.isEmpty()) return; stc.insertText(tabs); - textCode->setTextCursor(stc); + ui->textCode->setTextCursor(stc); } void QCodeEdit::scrollToTop() { prev_lc = -1; updateLines(); - textCode->verticalScrollBar()->setValue(0); - textLines->verticalScrollBar()->setValue(0); + ui->textCode->verticalScrollBar()->setValue(0); + ui->textLines->verticalScrollBar()->setValue(0); +} + + +void QCodeEdit::setFocus() { + ui->textCode->setFocus(); +} + + +void QCodeEdit::setText(const QString & t) { + ui->textCode->setPlainText(t); } void QCodeEdit::updateLines() { if (timer > 0) killTimer(timer); timer = startTimer(500); - textCode->setTabStopWidth(textCode->fontMetrics().width(" ")); - int lc = textCode->document()->lineCount(); + ui->textCode->setTabStopWidth(ui->textCode->fontMetrics().width(" ")); + int lc = ui->textCode->document()->lineCount(); if (prev_lc == lc) return; prev_lc = lc; - textLines->setFixedWidth(textLines->fontMetrics().width(QString(" %1").arg(lc))); - textLines->clear(); + ui->textLines->setFixedWidth(ui->textLines->fontMetrics().width(QString(" %1").arg(lc))); + ui->textLines->clear(); for (int i = 1; i <= lc; ++i) - textLines->appendPlainText(QString("%1").arg(i)); - textLines->verticalScrollBar()->setValue(textCode->verticalScrollBar()->value()); + ui->textLines->appendPlainText(QString("%1").arg(i)); + ui->textLines->verticalScrollBar()->setValue(ui->textCode->verticalScrollBar()->value()); } @@ -799,13 +949,13 @@ void QCodeEdit::raiseHelp(QTextCursor tc, int arg) { qApp->processEvents(); widget_help->resize(widget_help->sizeHint()); qApp->processEvents(); - QRect whr = textCode->cursorRect(tc); - whr.setWidth(textCode->fontMetrics().width(st)); + QRect whr = ui->textCode->cursorRect(tc); + whr.setWidth(ui->textCode->fontMetrics().width(st)); QPoint whp; whp.setX(whr.left() - whr.width() - (widget_help->width() - whr.width()) / 2); whp.setY(whr.top() - widget_help->height() - (fontHeight() / 3)); //qDebug() << whr << whp << widget_help->width() << ", " << st; - widget_help->move(textCode->viewport()->mapToGlobal(whp)); + widget_help->move(ui->textCode->viewport()->mapToGlobal(whp)); widget_help->show(); widget_help->raise(); cursor_scope = scope.first; @@ -823,7 +973,7 @@ void QCodeEdit::hideHelp() { QTextCursor QCodeEdit::functionStart(QTextCursor tc, int * arg) { - QString doc = textCode->toPlainText(); + QString doc = ui->textCode->toPlainText(); int bcnt = 0, a = 0, i = -1; for (i = tc.position() - 1; i >= 0; --i) { if (doc[i] == ')') bcnt++; @@ -838,7 +988,7 @@ QTextCursor QCodeEdit::functionStart(QTextCursor tc, int * arg) { } if (i < 0) return QTextCursor(); if (arg) *arg = a; - QTextCursor ret(textCode->document()); + QTextCursor ret(ui->textCode->document()); ret.setPosition(i); //qDebug() << "found" << i << a; return ret; @@ -848,11 +998,11 @@ QTextCursor QCodeEdit::functionStart(QTextCursor tc, int * arg) { QCodeEdit::ACList QCodeEdit::wordsCompletitionList(const QString & written) const { QCodeEdit::ACList ret; if (!written.isEmpty()) { - QTextCursor tc = QTextCursor(textCode->document()->begin()), stc; + QTextCursor tc = QTextCursor(ui->textCode->document()->begin()), stc; QStringList acwl; - tc = QTextCursor(textCode->document()->begin()); + tc = QTextCursor(ui->textCode->document()->begin()); while (true) { - tc = textCode->document()->find(written, tc); + tc = ui->textCode->document()->find(written, tc); if (tc.isNull()) break; stc = tc; stc.movePosition(QTextCursor::Left); @@ -888,7 +1038,7 @@ QPair QCodeEdit::getScope(QTextCursor tc, bool * ok) { return ret; } } - QString doc = textCode->toPlainText(); + QString doc = ui->textCode->toPlainText(); auto_comp_pl = line; completer->clear(); int spos = tc.position(), cpos = spos; @@ -928,13 +1078,13 @@ QPair QCodeEdit::getScope(QTextCursor tc, bool * ok) { void QCodeEdit::invokeAutoCompletition(bool force) { int arg = -1; - QTextCursor htc = functionStart(textCode->textCursor(), &arg); + QTextCursor htc = functionStart(ui->textCode->textCursor(), &arg); if (!htc.isNull()) { //qDebug() << "raise"; raiseHelp(htc, arg); } bool ok; - QPair scope = getScope(textCode->textCursor(), &ok); + QPair scope = getScope(ui->textCode->textCursor(), &ok); if (!ok) return; ACList acl(autoCompletitionList(scope.first, scope.second)); //qDebug() << written << scope << acl.size(); @@ -969,7 +1119,7 @@ void QCodeEdit::invokeAutoCompletition(bool force) { if (completer->topLevelItemCount() > 1) completer->setCurrentItem(completer->topLevelItem(1)); if (completer->isHidden()) - completer->move(textCode->mapToGlobal(textCode->cursorRect().bottomRight())); + completer->move(ui->textCode->mapToGlobal(ui->textCode->cursorRect().bottomRight())); if (completer->topLevelItemCount() > 0) { completer->setVisible(true); //qApp->processEvents(); @@ -986,7 +1136,7 @@ void QCodeEdit::commitCompletition() { if (completer->currentItem() == 0) return; if (!completer->currentItem()->flags().testFlag(Qt::ItemIsSelectable)) return; QString ins = completer->currentItem()->text(1), ret = completer->currentItem()->text(0); - QTextCursor tc = textCode->textCursor(), stc = tc; + QTextCursor tc = ui->textCode->textCursor(), stc = tc; tc.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); bool ins_br = true, shifted = false; if (!tc.selectedText().isEmpty()) { @@ -1014,29 +1164,29 @@ void QCodeEdit::commitCompletition() { if (shifted) tc.movePosition(QTextCursor::Right); } - textCode->setTextCursor(tc); - textCode->textCursor().insertText(ins); - tc = textCode->textCursor(); + ui->textCode->setTextCursor(tc); + ui->textCode->textCursor().insertText(ins); + tc = ui->textCode->textCursor(); if (ins_br) { if (ret == "void") { tc.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); if (tc.selectedText() != ";") { - textCode->textCursor().insertText(";"); + ui->textCode->textCursor().insertText(";"); tc.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 2); } } if (ins.endsWith(")") && !completer->currentItem()->text(1).endsWith("()")) { tc.movePosition(QTextCursor::Left); - textCode->setTextCursor(tc); + ui->textCode->setTextCursor(tc); } } else { if (completer->currentItem()->text(1).endsWith(")")) { tc.movePosition(QTextCursor::Right); - textCode->setTextCursor(tc); + ui->textCode->setTextCursor(tc); } if (completer->currentItem()->text(1).endsWith("()")) { tc.movePosition(QTextCursor::Right); - textCode->setTextCursor(tc); + ui->textCode->setTextCursor(tc); } } completer->hide(); @@ -1044,7 +1194,7 @@ void QCodeEdit::commitCompletition() { void QCodeEdit::textEdit_cursorPositionChanged() { - es_line.cursor = textCode->textCursor(); + es_line.cursor = ui->textCode->textCursor(); es_line.cursor.select(QTextCursor::LineUnderCursor); es_line.cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); highlightBrackets(); @@ -1053,22 +1203,24 @@ void QCodeEdit::textEdit_cursorPositionChanged() { void QCodeEdit::textEdit_textChanged() { + if (_replacing) return; + searchAll(); updateLines(); } void QCodeEdit::textEdit_selectionChanged() { es_selected.clear(); - QString sf = textCode->textCursor().selectedText(); + QString sf = ui->textCode->textCursor().selectedText(); if (sf.trimmed().isEmpty() || sf.contains("\n")) { applyExtraSelection(); return; } - QTextCursor tc(textCode->document()->begin()); + QTextCursor tc(ui->textCode->document()->begin()); QTextEdit::ExtraSelection es; es.format.setBackground(QColor(251, 250, 150)); while (true) { - tc = textCode->document()->find(sf, tc, QTextDocument::FindCaseSensitively | QTextDocument::FindWholeWords); + tc = ui->textCode->document()->find(sf, tc, QTextDocument::FindCaseSensitively | QTextDocument::FindWholeWords); if (tc.isNull()) break; es.cursor = tc; es_selected << es; @@ -1079,7 +1231,77 @@ void QCodeEdit::textEdit_selectionChanged() { void QCodeEdit::setShowSpaces(bool yes) { spaces_ = yes; - QTextOption to = textCode->document()->defaultTextOption(); - to.setFlags(yes ? QTextOption::ShowTabsAndSpaces : (QTextOption::Flags)0); - textCode->document()->setDefaultTextOption(to); + QTextOption to = ui->textCode->document()->defaultTextOption(); + QTextOption::Flags tof = to.flags(); + if (yes) tof |= QTextOption::ShowTabsAndSpaces; + else tof &= ~QTextOption::ShowTabsAndSpaces; + to.setFlags(tof); + ui->textCode->document()->setDefaultTextOption(to); +} + + +void QCodeEdit::setShowLineNumbers(bool yes) { + ui->textLines->setVisible(yes); +} + + +void QCodeEdit::search(const QString & t) { + ui->widgetSearch->show(); + ui->comboSearch->setEditText(QString()); + ui->comboSearch->setEditText(t); + ui->comboSearch->setFocus(); + //searchAll(); + searchNext(false); +} + + +void QCodeEdit::searchNext(bool next) { + if (es_search_list.isEmpty()) + return; + cur_search_ind = searchIndFromCursor() + (next ? 1 : 0); + moveToSearch(); +} + + +void QCodeEdit::searchPrevious() { + if (es_search_list.isEmpty()) + return; + cur_search_ind = searchIndFromCursor() - 1; + moveToSearch(); +} + + +void QCodeEdit::hideSearch() { + ui->widgetSearch->hide(); + searchAll(); +} + + +void QCodeEdit::on_comboSearch_currentTextChanged(const QString & t) { + searchAll(); + searchNext(false); +} + + +void QCodeEdit::on_buttonReplace_clicked() { + if (es_search_list.isEmpty() || cur_search_ind < 0 || cur_search_ind >= es_search_list.size()) return; + if (ui->textCode->textCursor() != es_search_list[cur_search_ind].cursor) return; + if (ui->textCode->textCursor().selectedText().size() != es_search_list[cur_search_ind].cursor.selectedText().size()) return; + ui->textCode->textCursor().insertText(ui->comboReplace->currentText()); +} + + +void QCodeEdit::on_buttonReplaceSearch_clicked() { + on_buttonReplace_clicked(); + searchNext(); +} + + +void QCodeEdit::on_buttonReplaceAll_clicked() { + _replacing = true; + QString rt = ui->comboReplace->currentText(); + for (int i = es_search_list.size() - 1; i >= 0; --i) + es_search_list[i].cursor.insertText(rt); + _replacing = false; + textEdit_textChanged(); } diff --git a/qad/widgets/qcodeedit.h b/qad/widgets/qcodeedit.h index 801ed99..744e347 100644 --- a/qad/widgets/qcodeedit.h +++ b/qad/widgets/qcodeedit.h @@ -11,12 +11,19 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE + +namespace Ui { + class QCodeEdit; +} + + class QCodeEdit: public QWidget { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText) Q_PROPERTY(bool showSpaces READ showSpaces WRITE setShowSpaces) Q_PROPERTY(bool showLineNumbers READ showLineNumbers WRITE setShowLineNumbers) + Q_PROPERTY(QFont editorFont READ editorFont WRITE setEditorFont) public: QCodeEdit(QWidget * parent = 0); @@ -28,21 +35,24 @@ public: Namespace }; - QTextCursor textCursor() const {return textCode->textCursor();} - QTextDocument * document() const {return textCode->document();} - void setTextCursor(const QTextCursor & c) {textCode->setTextCursor(c);} - void centerCursor() {textCode->centerCursor(); updateLines();} - void insertText(const QString & text) {textCode->insertPlainText(text); updateLines();} - void appendText(const QString & text) {textCode->appendPlainText(text); updateLines();} - void setCustomExtraSelection(const QList & es) {es_custom = es; applyExtraSelection();} - QRect cursorRect() const {return textCode->cursorRect();} - QRect cursorRect(const QTextCursor & cursor) const {return textCode->cursorRect(cursor);} - QString text() const {return textCode->toPlainText();} - QStringList cursorScope() const {return cursor_scope;} + QTextCursor textCursor() const; + QTextDocument * document() const; + void setTextCursor(const QTextCursor & c); + void centerCursor(); + void insertText(const QString & text); + void appendText(const QString & text); + void setCustomExtraSelection(const QList & es); + QRect cursorRect() const; + QRect cursorRect(const QTextCursor & cursor) const; + QString text() const; + QStringList cursorScope() const; bool showSpaces() const {return spaces_;} - bool showLineNumbers() const {return textLines->isVisible();} + bool showLineNumbers() const; + + void setEditorFont(QFont f); + QFont editorFont() const; - QPlainTextEdit * textEdit() const {return textCode;} + QPlainTextEdit * textEdit() const; void registerAutoCompletitionClass(int id, ACClassType ac_class, const QString & name, const QIcon & icon = QIcon()) {ac_classes[id] = ACClass(id, ac_class, name, icon);} @@ -64,6 +74,8 @@ protected: static bool matchWritten(QString s, QString w); static QChar pairChar(QChar c); + Ui::QCodeEdit * ui; + private: struct ACClass { ACClass(int i = -2, ACClassType c = QCodeEdit::Keyword, const QString & n = QString(), const QIcon & ic = QIcon()): id(i), class_(c), name(n), icon(ic) {} @@ -73,24 +85,27 @@ private: QIcon icon; }; - QPlainTextEdit * textCode, * textLines; QTreeWidget * completer; IconedLabel * lbl_help[2]; QFrame * widget_help; - QTextEdit::ExtraSelection es_line, es_cursor, es_bracket, es_range; - QList es_selected, es_custom, es_brackets; + QTextEdit::ExtraSelection es_line, es_cursor, es_bracket, es_range, es_search; + QList es_selected, es_custom, es_brackets, es_search_list; QMap ac_classes; QStringList cursor_scope; - int prev_lc, auto_comp_pl, timer; - bool spaces_, _ignore_focus_out, _first, _destructor; + int prev_lc, auto_comp_pl, timer, cur_search_ind; + bool spaces_, _ignore_focus_out, _first, _destructor, _replacing; bool eventFilter(QObject * o, QEvent * e); void showEvent(QShowEvent * ); void timerEvent(QTimerEvent * ); + void leaveEvent(QEvent * ); void highlightBrackets(); void applyExtraSelection(); void nextCompletition(); void previousCompletition(); + void clearSearch(); + void moveToSearch(); + int searchIndFromCursor(); private slots: void syncScrolls(); @@ -104,17 +119,27 @@ private slots: void autoIndent(); void invokeAutoCompletition(bool force = false); void commitCompletition(); + void searchAll(); + void search_triggered(); void textEdit_cursorPositionChanged(); void textEdit_textChanged(); void textEdit_selectionChanged(); - + void on_comboSearch_currentTextChanged(const QString & t); + void on_buttonReplace_clicked(); + void on_buttonReplaceSearch_clicked(); + void on_buttonReplaceAll_clicked(); + public slots: void updateLines(); void scrollToTop(); - void setFocus() {textCode->setFocus();} - void setText(const QString & t) {textCode->setPlainText(t);} + void setFocus(); + void setText(const QString & t); void setShowSpaces(bool yes); - void setShowLineNumbers(bool yes) {textLines->setVisible(yes);} + void setShowLineNumbers(bool yes); + void search(const QString & t); + void searchNext(bool next = true); + void searchPrevious(); + void hideSearch(); signals: void textChanged(); diff --git a/qad/widgets/qcodeedit.ui b/qad/widgets/qcodeedit.ui new file mode 100644 index 0000000..2c07725 --- /dev/null +++ b/qad/widgets/qcodeedit.ui @@ -0,0 +1,389 @@ + + + QCodeEdit + + + + 0 + 0 + 726 + 697 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + + 0 + 0 + + + + Qt::NoFocus + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QPlainTextEdit::NoWrap + + + Qt::NoTextInteraction + + + + + + + QFrame::NoFrame + + + false + + + QPlainTextEdit::NoWrap + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Search: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + 0 + 0 + + + + Case sensitive + + + Aa + + + true + + + + + + + + 0 + 0 + + + + Whole words + + + W + + + true + + + + + + + + 0 + 0 + + + + Previous + + + + :/icons/go-previous.png:/icons/go-previous.png + + + + + + + + 0 + 0 + + + + Next + + + + :/icons/go-next.png:/icons/go-next.png + + + + + + + + + Replace: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + 0 + 0 + + + + Replace + + + R + + + + + + + + 0 + 0 + + + + Replace and search + + + Rs + + + + + + + + 0 + 0 + + + + Replace all + + + Ra + + + + + + + + + + 0 + 0 + + + + true + + + QComboBox::InsertAtTop + + + + + + + + 0 + 0 + + + + true + + + QComboBox::InsertAtTop + + + + + + + + + + + + + + EComboBox + QComboBox +
ecombobox.h
+
+
+ + + + + + buttonSearchNext + clicked() + QCodeEdit + searchNext() + + + 723 + 670 + + + 731 + 578 + + + + + buttonSearchPrev + clicked() + QCodeEdit + searchPrevious() + + + 691 + 670 + + + 743 + 536 + + + + + buttonSearchCase + toggled(bool) + QCodeEdit + searchAll() + + + 612 + 654 + + + 740 + 499 + + + + + buttonSearchWord + toggled(bool) + QCodeEdit + searchAll() + + + 648 + 658 + + + 753 + 511 + + + + + + search(QString) + searchNext() + searchPrevious() + searchAll() + +