From 92d36868bb8a9f82f3e89a419076563a6c23771c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 13 Feb 2021 19:13:22 +0100 Subject: [PATCH] Enhancements to search and replace in macro editor. --- src/lay/lay/MacroEditorDialog.ui | 76 +--- src/lay/lay/layMacroEditorDialog.cc | 121 +++++-- src/lay/lay/layMacroEditorDialog.h | 5 + src/lay/lay/layMacroEditorPage.cc | 532 ++++++++++++++++------------ src/lay/lay/layMacroEditorPage.h | 10 +- 5 files changed, 412 insertions(+), 332 deletions(-) diff --git a/src/lay/lay/MacroEditorDialog.ui b/src/lay/lay/MacroEditorDialog.ui index a166b21c9..5b2e83302 100644 --- a/src/lay/lay/MacroEditorDialog.ui +++ b/src/lay/lay/MacroEditorDialog.ui @@ -1383,63 +1383,6 @@ p, li { white-space: pre-wrap; } - - - - Qt::Horizontal - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Close - - - false - - - - - - @@ -1596,22 +1539,5 @@ p, li { white-space: pre-wrap; } - - - pushButton - clicked() - MacroEditorDialog - accept() - - - 905 - 694 - - - 929 - 696 - - - - + diff --git a/src/lay/lay/layMacroEditorDialog.cc b/src/lay/lay/layMacroEditorDialog.cc index c2b3377e4..7573154e0 100644 --- a/src/lay/lay/layMacroEditorDialog.cc +++ b/src/lay/lay/layMacroEditorDialog.cc @@ -355,8 +355,8 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection QMenu *m = new QMenu (searchEditBox); m->addAction (actionUseRegularExpressions); m->addAction (actionCaseSensitive); - connect (actionUseRegularExpressions, SIGNAL (triggered ()), this, SLOT (apply_search ())); - connect (actionCaseSensitive, SIGNAL (triggered ()), this, SLOT (apply_search ())); + connect (actionUseRegularExpressions, SIGNAL (triggered ()), this, SLOT (search_editing ())); + connect (actionCaseSensitive, SIGNAL (triggered ()), this, SLOT (search_editing ())); addAction (actionSearchReplace); connect (actionSearchReplace, SIGNAL (triggered ()), this, SLOT (search_replace ())); @@ -364,7 +364,11 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection searchEditBox->set_clear_button_enabled (true); searchEditBox->set_options_button_enabled (true); searchEditBox->set_options_menu (m); + searchEditBox->set_escape_signal_enabled (true); + searchEditBox->set_tab_signal_enabled (true); replaceText->set_clear_button_enabled (true); + replaceText->set_escape_signal_enabled (true); + replaceText->set_tab_signal_enabled (true); #if QT_VERSION >= 0x40700 searchEditBox->setPlaceholderText (tr ("Find text ...")); replaceText->setPlaceholderText (tr ("Replace text ...")); @@ -382,8 +386,6 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection tabWidget->setMovable (true); tabWidget->setTabsClosable (true); connect (tabWidget, SIGNAL (tabCloseRequested (int)), this, SLOT (tab_close_requested (int))); - closeButton->hide (); - closeButtonSeparator->hide (); #endif dbgOn->setEnabled (true); @@ -411,7 +413,6 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection connect (helpButton, SIGNAL (clicked ()), this, SLOT (help_button_clicked ())); connect (addButton, SIGNAL (clicked ()), this, SLOT (add_button_clicked ())); connect (actionAddMacro, SIGNAL (triggered ()), this, SLOT (add_button_clicked ())); - connect (closeButton, SIGNAL (clicked ()), this, SLOT (close_button_clicked ())); connect (deleteButton, SIGNAL (clicked ()), this, SLOT (delete_button_clicked ())); connect (actionDelete, SIGNAL (triggered ()), this, SLOT (delete_button_clicked ())); connect (renameButton, SIGNAL (clicked ()), this, SLOT (rename_button_clicked ())); @@ -438,9 +439,16 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection connect (callStack, SIGNAL (itemDoubleClicked (QListWidgetItem *)), this, SLOT (stack_element_double_clicked (QListWidgetItem *))); connect (singleStepButton, SIGNAL (clicked ()), this, SLOT (single_step_button_clicked ())); connect (nextStepButton, SIGNAL (clicked ()), this, SLOT (next_step_button_clicked ())); + connect (searchEditBox, SIGNAL (textEdited (const QString &)), this, SLOT (search_editing ())); connect (searchEditBox, SIGNAL (returnPressed ()), this, SLOT (search_edited ())); connect (searchEditBox, SIGNAL (editingFinished ()), this, SLOT (search_edited ())); - connect (searchEditBox, SIGNAL (textEdited (QString)), this, SLOT (apply_search ())); + connect (searchEditBox, SIGNAL (esc_pressed ()), this, SLOT (search_finished ())); + connect (searchEditBox, SIGNAL (tab_pressed ()), this, SLOT (find_next_button_clicked ())); + connect (searchEditBox, SIGNAL (backtab_pressed ()), this, SLOT (find_prev_button_clicked ())); + connect (replaceText, SIGNAL (esc_pressed ()), this, SLOT (search_finished ())); + connect (replaceText, SIGNAL (tab_pressed ()), this, SLOT (find_next_button_clicked ())); + connect (replaceText, SIGNAL (backtab_pressed ()), this, SLOT (find_prev_button_clicked ())); + connect (replaceText, SIGNAL (returnPressed ()), this, SLOT (replace_next_button_clicked ())); connect (replaceModeButton, SIGNAL (clicked ()), this, SLOT (replace_mode_button_clicked ())); connect (replaceNextButton, SIGNAL (clicked ()), this, SLOT (replace_next_button_clicked ())); connect (findNextButton, SIGNAL (clicked ()), this, SLOT (find_next_button_clicked ())); @@ -946,15 +954,13 @@ MacroEditorDialog::showEvent (QShowEvent *) void MacroEditorDialog::reject () { - closeEvent (0); - QDialog::reject (); + // .. ignore Esc .. } void MacroEditorDialog::accept () { - closeEvent (0); - QDialog::accept (); + // .. ignore Enter .. } void @@ -1105,12 +1111,6 @@ MacroEditorDialog::can_exit () return true; } -void -MacroEditorDialog::search_replace () -{ - searchEditBox->setFocus (Qt::TabFocusReason); -} - void MacroEditorDialog::add_edit_trace (bool compress) { @@ -1882,6 +1882,18 @@ BEGIN_PROTECTED END_PROTECTED } +void +MacroEditorDialog::set_editor_focus () +{ + MacroEditorPage *page = dynamic_cast (tabWidget->currentWidget ()); + if (! page) { + return; + } + + QSignalBlocker signal_blocker (searchEditBox); + page->set_editor_focus (); +} + void MacroEditorDialog::replace_mode_button_clicked () { @@ -1905,10 +1917,27 @@ MacroEditorDialog::find_next_button_clicked () apply_search (true); page->find_next (); - page->set_editor_focus (); + if (sender () != searchEditBox && sender () != replaceText) { + set_editor_focus (); + } } -void +void +MacroEditorDialog::find_prev_button_clicked () +{ + MacroEditorPage *page = dynamic_cast (tabWidget->currentWidget ()); + if (! page) { + return; + } + + apply_search (true); + page->find_prev (); + if (sender () != searchEditBox && sender () != replaceText) { + set_editor_focus (); + } +} + +void MacroEditorDialog::replace_next_button_clicked () { MacroEditorPage *page = dynamic_cast (tabWidget->currentWidget ()); @@ -1918,10 +1947,12 @@ MacroEditorDialog::replace_next_button_clicked () apply_search (true); page->replace_and_find_next (replaceText->text ()); - page->set_editor_focus (); + if (sender () != replaceText) { + set_editor_focus (); + } } -void +void MacroEditorDialog::replace_all_button_clicked () { MacroEditorPage *page = dynamic_cast (tabWidget->currentWidget ()); @@ -1931,7 +1962,34 @@ MacroEditorDialog::replace_all_button_clicked () apply_search (true); page->replace_all (replaceText->text ()); - page->set_editor_focus (); + set_editor_focus (); +} + +void +MacroEditorDialog::search_requested (const QString &s) +{ + searchEditBox->setText (s); + searchEditBox->setFocus (); + search_editing (); +} + +void +MacroEditorDialog::search_replace () +{ + searchEditBox->setFocus (Qt::TabFocusReason); +} + +void +MacroEditorDialog::search_editing () +{ + MacroEditorPage *page = dynamic_cast (tabWidget->currentWidget ()); + if (! page) { + return; + } + + apply_search (); + page->find_reset (); // search from the initial position + page->find_next (); } void @@ -1942,6 +2000,18 @@ MacroEditorDialog::search_edited () md_search_edited (); } +void +MacroEditorDialog::search_finished () +{ + MacroEditorPage *page = dynamic_cast (tabWidget->currentWidget ()); + if (! page) { + return; + } + + page->find_reset (); // search from the initial position + set_editor_focus (); +} + void MacroEditorDialog::do_search_edited () { @@ -1951,8 +2021,9 @@ MacroEditorDialog::do_search_edited () } apply_search (); + page->find_reset (); // search from the initial position page->find_next (); - page->set_editor_focus (); + set_editor_focus (); } void @@ -1963,7 +2034,7 @@ MacroEditorDialog::apply_search (bool if_needed) return; } - if (searchEditBox->text ().size () > 0) { + if (! searchEditBox->text ().isEmpty ()) { QRegExp re (searchEditBox->text (), actionCaseSensitive->isChecked () ? Qt::CaseSensitive : Qt::CaseInsensitive, actionUseRegularExpressions->isChecked () ? QRegExp::RegExp : QRegExp::FixedString); @@ -2080,7 +2151,7 @@ BEGIN_PROTECTED END_PROTECTED } -void +void MacroEditorDialog::help_requested(const QString &s) { lay::MainWindow::instance ()->show_assistant_topic (tl::to_string (s)); @@ -3172,7 +3243,6 @@ MacroEditorDialog::do_update_ui_to_run_mode () addButton->setEnabled (! m_in_exec); actionAddMacro->setEnabled (! m_in_exec); - closeButton->setEnabled (! m_in_exec); deleteButton->setEnabled (! m_in_exec); actionDelete->setEnabled (! m_in_exec); renameButton->setEnabled (! m_in_exec); @@ -3270,6 +3340,7 @@ MacroEditorDialog::create_page (lym::Macro *macro) editor->exec_model ()->set_run_mode (m_in_exec); editor->connect_macro (macro); connect (editor.get (), SIGNAL (help_requested (const QString &)), this, SLOT (help_requested (const QString &))); + connect (editor.get (), SIGNAL (search_requested (const QString &)), this, SLOT (search_requested (const QString &))); connect (editor.get (), SIGNAL (edit_trace (bool)), this, SLOT (add_edit_trace (bool))); return editor.release (); } diff --git a/src/lay/lay/layMacroEditorDialog.h b/src/lay/lay/layMacroEditorDialog.h index 75108d501..fd60dbb0b 100644 --- a/src/lay/lay/layMacroEditorDialog.h +++ b/src/lay/lay/layMacroEditorDialog.h @@ -209,12 +209,16 @@ private slots: void commit (); void stack_element_double_clicked (QListWidgetItem *item); void search_edited (); + void search_editing (); + void search_finished (); void tab_close_requested (int); void replace_mode_button_clicked (); void replace_next_button_clicked (); void replace_all_button_clicked (); void find_next_button_clicked (); + void find_prev_button_clicked (); void help_requested (const QString &s); + void search_requested (const QString &s); void macro_changed (lym::Macro *macro); void macro_deleted (lym::Macro *macro); void macro_collection_deleted (lym::MacroCollection *collection); @@ -288,6 +292,7 @@ private: void update_watches (); lym::Macro *new_macro (); void do_search_edited (); + void set_editor_focus (); void select_trace (size_t index); bool configure (const std::string &name, const std::string &value); void config_finalize (); diff --git a/src/lay/lay/layMacroEditorPage.cc b/src/lay/lay/layMacroEditorPage.cc index ad6d38f84..03c41abdc 100644 --- a/src/lay/lay/layMacroEditorPage.cc +++ b/src/lay/lay/layMacroEditorPage.cc @@ -475,7 +475,7 @@ void MacroEditorSidePanel::paintEvent (QPaintEvent *) // MacroEditorPage implementation MacroEditorPage::MacroEditorPage (QWidget * /*parent*/, MacroEditorHighlighters *highlighters) - : mp_macro (0), mp_highlighters (highlighters), mp_highlighter (0), m_error_line (-1), m_ntab (8), m_nindent (2) + : mp_macro (0), mp_highlighters (highlighters), mp_highlighter (0), m_error_line (-1), m_ntab (8), m_nindent (2), m_ignore_cursor_changed_event (false) { QVBoxLayout *layout = new QVBoxLayout (this); @@ -600,7 +600,12 @@ static bool valid_element (const SyntaxHighlighterElement &e) void MacroEditorPage::cursor_position_changed () { + if (m_ignore_cursor_changed_event) { + return; + } + QTextCursor cursor = mp_text->textCursor (); + m_edit_cursor = cursor; // prepare a format for the bracket highlights QTextCharFormat fmt; @@ -861,11 +866,23 @@ void MacroEditorPage::connect_macro (lym::Macro *macro) } } +void +MacroEditorPage::find_reset () +{ + m_ignore_cursor_changed_event = true; + mp_text->setTextCursor (m_edit_cursor); + m_ignore_cursor_changed_event = false; +} + bool MacroEditorPage::find_prev () { update_extra_selections (); + if (m_current_search == QRegExp ()) { + return false; + } + QTextCursor c = mp_text->textCursor (); bool first = true; @@ -891,7 +908,9 @@ MacroEditorPage::find_prev () QTextCursor newc (b); newc.setPosition (i + b.position () + l); newc.setPosition (i + b.position (), QTextCursor::KeepAnchor); + m_ignore_cursor_changed_event = true; mp_text->setTextCursor (newc); + m_ignore_cursor_changed_event = false; return true; } @@ -913,6 +932,10 @@ MacroEditorPage::find_next () { update_extra_selections (); + if (m_current_search == QRegExp ()) { + return false; + } + QTextCursor c = mp_text->textCursor (); bool first = true; @@ -926,7 +949,9 @@ MacroEditorPage::find_next () QTextCursor newc (b); newc.setPosition (i + b.position () + m_current_search.matchedLength ()); newc.setPosition (i + b.position (), QTextCursor::KeepAnchor); + m_ignore_cursor_changed_event = true; mp_text->setTextCursor (newc); + m_ignore_cursor_changed_event = false; emit edit_trace (false); return true; } @@ -1152,225 +1177,289 @@ MacroEditorPage::current_pos () const return mp_text->textCursor ().position () - mp_text->textCursor ().block ().position (); } +bool +MacroEditorPage::tab_key_pressed () +{ + if (mp_text->isReadOnly ()) { + return false; + } + + QTextBlock bs, be; + bool adjust_end = false; + + bool indent = false; + if (mp_text->textCursor ().hasSelection ()) { + bs = mp_text->document ()->findBlock (mp_text->textCursor ().selectionStart ()); + be = mp_text->document ()->findBlock (mp_text->textCursor ().selectionEnd ()); + if (be != bs) { + indent = true; + QTextCursor se (mp_text->document ()); + se.setPosition (mp_text->textCursor ().selectionEnd ()); + if (se.atBlockStart ()) { + be = be.previous (); + adjust_end = true; + } + } + } + + if (indent) { + + // tab out + QTextCursor c (mp_text->document ()); + c.setPosition (bs.position ()); + c.beginEditBlock (); + + for (QTextBlock b = bs; ; b = b.next()) { + + c.setPosition (b.position ()); + QString text = b.text (); + + bool has_tabs = false; + int p = 0; + int i = 0; + for (; i < text.length (); ++i) { + if (text [i] == QChar::fromLatin1 (' ')) { + ++p; + } else if (text [i] == QChar::fromLatin1 ('\t')) { + p = (p - p % m_ntab) + m_ntab; + has_tabs = true; + } else { + break; + } + } + + if (has_tabs) { + for ( ; i > 0; --i) { + c.deleteChar (); + } + c.insertText (QString (m_nindent + p, QChar::fromLatin1 (' '))); + } else { + c.insertText (QString (m_nindent, QChar::fromLatin1 (' '))); + } + + if (b == be) { + break; + } + + } + + c.endEditBlock (); + + c.setPosition (bs.position ()); + if (adjust_end) { + c.setPosition (be.next ().position (), QTextCursor::KeepAnchor); + } else { + c.setPosition (be.position () + be.text ().length (), QTextCursor::KeepAnchor); + } + mp_text->setTextCursor (c); + + } else { + + QTextCursor c = mp_text->textCursor (); + QString text = c.block ().text (); + int col = c.position () - c.block ().position (); + + int p = 0; + for (int i = 0; i < text.length () && i < col; ++i) { + if (text [i] == QChar::fromLatin1 ('\t')) { + p = (p - p % m_ntab) + m_ntab; + } else { + ++p; + } + } + + c.insertText (QString (m_nindent - p % m_nindent, QChar::fromLatin1 (' '))); + mp_text->setTextCursor (c); + + } + + return true; +} + +bool +MacroEditorPage::back_tab_key_pressed () +{ + if (!mp_text->textCursor ().hasSelection () || mp_text->isReadOnly ()) { + return false; + } + + // tab in + QTextBlock bs = mp_text->document ()->findBlock (mp_text->textCursor ().selectionStart ()); + QTextBlock be = mp_text->document ()->findBlock (mp_text->textCursor ().selectionEnd ()); + bool adjust_end = false; + if (be != bs) { + QTextCursor se (mp_text->document ()); + se.setPosition (mp_text->textCursor ().selectionEnd ()); + if (se.atBlockStart ()) { + be = be.previous (); + adjust_end = true; + } + } + + QTextCursor c (mp_text->document ()); + c.setPosition (bs.position ()); + c.beginEditBlock (); + + for (QTextBlock b = bs; ; b = b.next()) { + + c.setPosition (b.position ()); + QString text = b.text (); + int n = m_nindent; + int p = 0; + for (int i = 0; i < text.length () && n > 0; ++i) { + if (text [i] == QChar::fromLatin1 (' ')) { + ++p; + --n; + c.deleteChar (); + } else if (text [i] == QChar::fromLatin1 ('\t')) { + c.deleteChar (); + int pp = p; + p = (p - p % m_ntab) + m_ntab; + if (p - pp >= n) { + if (p - pp > n) { + c.insertText (QString (p - pp - n, QChar::fromLatin1 (' '))); + } + n = 0; + } else { + n -= p - pp; + } + } else { + break; + } + } + + if (b == be) { + break; + } + + } + + c.endEditBlock (); + + c.setPosition (bs.position ()); + if (adjust_end) { + c.setPosition (be.next ().position (), QTextCursor::KeepAnchor); + } else { + c.setPosition (be.position () + be.text ().length (), QTextCursor::KeepAnchor); + } + mp_text->setTextCursor (c); + + return true; +} + +bool +MacroEditorPage::backspace_pressed () +{ + if (mp_text->textCursor ().hasSelection () || mp_text->isReadOnly()) { + return false; + } + + QTextCursor c = mp_text->textCursor (); + QString text = c.block ().text (); + int col = c.position () - c.block ().position (); + if (col > 0) { + + int p = 0; + bool only_space_before = true; + + for (int i = 0; i < text.length () && i < col; ++i) { + if (text [i] == QChar::fromLatin1 ('\t')) { + p = (p - p % m_ntab) + m_ntab; + } else if (text [i] == QChar::fromLatin1 (' ')) { + ++p; + } else { + only_space_before = false; + } + } + + if (only_space_before) { + + for (int i = 0; i < col; ++i) { + c.deletePreviousChar (); + } + + c.insertText (QString (std::max (0, ((p - 1) / m_nindent) * m_nindent), QChar::fromLatin1 (' '))); + mp_text->setTextCursor (c); + + return true; + + } + + } + + return false; +} + +bool +MacroEditorPage::return_pressed () +{ + if (mp_text->isReadOnly ()) { + return false; + } + + // Implement auto-indent on return + + QTextCursor c = mp_text->textCursor (); + QTextBlock b = c.block (); + + c.insertBlock (); + + QString l; + if (b.isValid ()) { + QString text = b.text (); + for (int i = 0; i < text.length (); ++i) { + if (text [i] == QChar::fromLatin1 ('\t') || text [i] == QChar::fromLatin1 (' ')) { + l += text [i]; + } else { + break; + } + } + } + + c.insertText (l); + mp_text->setTextCursor (c); + + return true; +} + bool MacroEditorPage::eventFilter (QObject *watched, QEvent *event) { if (watched == mp_text) { - if (event->type () == QEvent::KeyPress) { + if (event->type () == QEvent::ShortcutOverride) { + + // override shortcuts + event->accept (); + return true; + + } else if (event->type () == QEvent::KeyPress) { m_error_line = -1; mp_text->setExtraSelections (QList ()); QKeyEvent *ke = dynamic_cast (event); - if (ke && ke->key () == Qt::Key_Tab && (ke->modifiers () & Qt::ShiftModifier) == 0) { + if (! ke) { + return false; // should not happen + } - if (!mp_text->isReadOnly ()) { + if (ke->key () == Qt::Key_Tab && (ke->modifiers () & Qt::ShiftModifier) == 0) { - QTextBlock bs, be; - bool adjust_end = false; + return tab_key_pressed (); - bool indent = false; - if (mp_text->textCursor ().hasSelection ()) { - bs = mp_text->document ()->findBlock (mp_text->textCursor ().selectionStart ()); - be = mp_text->document ()->findBlock (mp_text->textCursor ().selectionEnd ()); - if (be != bs) { - indent = true; - QTextCursor se (mp_text->document ()); - se.setPosition (mp_text->textCursor ().selectionEnd ()); - if (se.atBlockStart ()) { - be = be.previous (); - adjust_end = true; - } - } - } + } else if ((ke->key () == Qt::Key_Backtab || (ke->key () == Qt::Key_Tab && (ke->modifiers () & Qt::ShiftModifier) != 0))) { - if (indent) { + return back_tab_key_pressed (); - // tab out - QTextCursor c (mp_text->document ()); - c.setPosition (bs.position ()); - c.beginEditBlock (); + } else if (ke->key () == Qt::Key_Backspace) { - for (QTextBlock b = bs; ; b = b.next()) { + return backspace_pressed (); - c.setPosition (b.position ()); - QString text = b.text (); + } else if (ke->key () == Qt::Key_Escape) { - bool has_tabs = false; - int p = 0; - int i = 0; - for (; i < text.length (); ++i) { - if (text [i] == QChar::fromLatin1 (' ')) { - ++p; - } else if (text [i] == QChar::fromLatin1 ('\t')) { - p = (p - p % m_ntab) + m_ntab; - has_tabs = true; - } else { - break; - } - } + // Handle Esc to return to the before-find position and clear the selection - if (has_tabs) { - for ( ; i > 0; --i) { - c.deleteChar (); - } - c.insertText (QString (m_nindent + p, QChar::fromLatin1 (' '))); - } else { - c.insertText (QString (m_nindent, QChar::fromLatin1 (' '))); - } - - if (b == be) { - break; - } - - } - - c.endEditBlock (); - - c.setPosition (bs.position ()); - if (adjust_end) { - c.setPosition (be.next ().position (), QTextCursor::KeepAnchor); - } else { - c.setPosition (be.position () + be.text ().length (), QTextCursor::KeepAnchor); - } - mp_text->setTextCursor (c); - - } else { - - QTextCursor c = mp_text->textCursor (); - QString text = c.block ().text (); - int col = c.position () - c.block ().position (); - - int p = 0; - for (int i = 0; i < text.length () && i < col; ++i) { - if (text [i] == QChar::fromLatin1 ('\t')) { - p = (p - p % m_ntab) + m_ntab; - } else { - ++p; - } - } - - c.insertText (QString (m_nindent - p % m_nindent, QChar::fromLatin1 (' '))); - mp_text->setTextCursor (c); - - } - - } - - return true; - - } else if (ke && (ke->key () == Qt::Key_Backtab || (ke->key () == Qt::Key_Tab && (ke->modifiers () & Qt::ShiftModifier) != 0))) { - - if (mp_text->textCursor ().hasSelection () && !mp_text->isReadOnly ()) { - - // tab in - QTextBlock bs = mp_text->document ()->findBlock (mp_text->textCursor ().selectionStart ()); - QTextBlock be = mp_text->document ()->findBlock (mp_text->textCursor ().selectionEnd ()); - bool adjust_end = false; - if (be != bs) { - QTextCursor se (mp_text->document ()); - se.setPosition (mp_text->textCursor ().selectionEnd ()); - if (se.atBlockStart ()) { - be = be.previous (); - adjust_end = true; - } - } - - QTextCursor c (mp_text->document ()); - c.setPosition (bs.position ()); - c.beginEditBlock (); - - for (QTextBlock b = bs; ; b = b.next()) { - - c.setPosition (b.position ()); - QString text = b.text (); - int n = m_nindent; - int p = 0; - for (int i = 0; i < text.length () && n > 0; ++i) { - if (text [i] == QChar::fromLatin1 (' ')) { - ++p; - --n; - c.deleteChar (); - } else if (text [i] == QChar::fromLatin1 ('\t')) { - c.deleteChar (); - int pp = p; - p = (p - p % m_ntab) + m_ntab; - if (p - pp >= n) { - if (p - pp > n) { - c.insertText (QString (p - pp - n, QChar::fromLatin1 (' '))); - } - n = 0; - } else { - n -= p - pp; - } - } else { - break; - } - } - - if (b == be) { - break; - } - - } - - c.endEditBlock (); - - c.setPosition (bs.position ()); - if (adjust_end) { - c.setPosition (be.next ().position (), QTextCursor::KeepAnchor); - } else { - c.setPosition (be.position () + be.text ().length (), QTextCursor::KeepAnchor); - } - mp_text->setTextCursor (c); - - } - - return true; - - } else if (ke && ke->key () == Qt::Key_Backspace) { - - if (!mp_text->textCursor ().hasSelection () && !mp_text->isReadOnly()) { - - QTextCursor c = mp_text->textCursor (); - QString text = c.block ().text (); - int col = c.position () - c.block ().position (); - if (col > 0) { - - int p = 0; - bool only_space_before = true; - - for (int i = 0; i < text.length () && i < col; ++i) { - if (text [i] == QChar::fromLatin1 ('\t')) { - p = (p - p % m_ntab) + m_ntab; - } else if (text [i] == QChar::fromLatin1 (' ')) { - ++p; - } else { - only_space_before = false; - } - } - - if (only_space_before) { - - for (int i = 0; i < col; ++i) { - c.deletePreviousChar (); - } - - c.insertText (QString (std::max (0, ((p - 1) / m_nindent) * m_nindent), QChar::fromLatin1 (' '))); - mp_text->setTextCursor (c); - - return true; - - } - - } - - } - - } else if (ke && ke->key () == Qt::Key_Escape) { - - // Handle Esc to clear the selection + find_reset (); QTextCursor c = mp_text->textCursor (); c.clearSelection (); @@ -1378,37 +1467,11 @@ MacroEditorPage::eventFilter (QObject *watched, QEvent *event) return true; - } else if (ke && ke->key () == Qt::Key_Return) { + } else if (ke->key () == Qt::Key_Return) { - if (!mp_text->isReadOnly ()) { + return return_pressed (); - // Implement auto-indent on return - - QTextCursor c = mp_text->textCursor (); - QTextBlock b = c.block (); - - c.insertBlock (); - - QString l; - if (b.isValid ()) { - QString text = b.text (); - for (int i = 0; i < text.length (); ++i) { - if (text [i] == QChar::fromLatin1 ('\t') || text [i] == QChar::fromLatin1 (' ')) { - l += text [i]; - } else { - break; - } - } - } - - c.insertText (l); - mp_text->setTextCursor (c); - - return true; - - } - - } else if (ke && ke->key () == Qt::Key_F1) { + } else if (ke->key () == Qt::Key_F1) { QTextCursor c = mp_text->textCursor (); if (c.selectionStart () == c.selectionEnd ()) { @@ -1418,7 +1481,14 @@ MacroEditorPage::eventFilter (QObject *watched, QEvent *event) return true; - } else if (ke && ke->key () == Qt::Key_F3) { + } else if (ke->key () == Qt::Key_F && (ke->modifiers () & Qt::ControlModifier) != 0) { + + QTextCursor c = mp_text->textCursor (); + emit search_requested (c.selectedText ()); + + return true; + + } else if (ke->key () == Qt::Key_F3) { // Jump to the next occurence of the search string diff --git a/src/lay/lay/layMacroEditorPage.h b/src/lay/lay/layMacroEditorPage.h index dcf1c94e0..8eee34048 100644 --- a/src/lay/lay/layMacroEditorPage.h +++ b/src/lay/lay/layMacroEditorPage.h @@ -254,8 +254,8 @@ public: return m_current_search; } + void find_reset (); bool find_next (); - bool find_prev (); void replace_and_find_next (const QString &replace); @@ -268,6 +268,7 @@ public: signals: void help_requested (const QString &s); + void search_requested (const QString &s); void edit_trace (bool); public slots: @@ -294,8 +295,15 @@ private: int m_ntab, m_nindent; std::set m_breakpoints; QRegExp m_current_search; + QTextCursor m_edit_cursor; + bool m_ignore_cursor_changed_event; void update_extra_selections (); + bool return_pressed (); + bool backspace_pressed (); + bool back_tab_key_pressed (); + bool tab_key_pressed (); + bool eventFilter (QObject *watched, QEvent *event); };