From 7d749140f7cdb9b559d35e4c3bf130f894a2f6f8 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 3 Aug 2023 21:35:37 +0200 Subject: [PATCH] Enhancements for macro editor's search and replace: replace single wasn't working properly and now there is find next and previous --- src/icons/icons.qrc | 4 + src/icons/images/find_next_16px.png | Bin 0 -> 689 bytes src/icons/images/find_next_16px@2x.png | Bin 0 -> 1534 bytes src/icons/images/find_prev_16px.png | Bin 0 -> 702 bytes src/icons/images/find_prev_16px@2x.png | Bin 0 -> 1514 bytes src/icons/svg/find_next_16px.svg | 231 +++++++++++++++++++++++++ src/icons/svg/find_prev_16px.svg | 231 +++++++++++++++++++++++++ src/lay/lay/MacroEditorDialog.ui | 23 ++- src/lay/lay/layMacroEditorDialog.cc | 21 ++- src/lay/lay/layMacroEditorDialog.h | 2 +- src/lay/lay/layMacroEditorPage.cc | 65 +++++-- src/lay/lay/layMacroEditorPage.h | 3 +- 12 files changed, 555 insertions(+), 25 deletions(-) create mode 100644 src/icons/images/find_next_16px.png create mode 100644 src/icons/images/find_next_16px@2x.png create mode 100644 src/icons/images/find_prev_16px.png create mode 100644 src/icons/images/find_prev_16px@2x.png create mode 100644 src/icons/svg/find_next_16px.svg create mode 100644 src/icons/svg/find_prev_16px.svg diff --git a/src/icons/icons.qrc b/src/icons/icons.qrc index 7067e958d..e7c2d7a30 100644 --- a/src/icons/icons.qrc +++ b/src/icons/icons.qrc @@ -284,5 +284,9 @@ images/bookmark_16px@2x.png images/bookmark_24px.png images/bookmark_24px@2x.png + images/find_next_16px.png + images/find_next_16px@2x.png + images/find_prev_16px.png + images/find_prev_16px@2x.png diff --git a/src/icons/images/find_next_16px.png b/src/icons/images/find_next_16px.png new file mode 100644 index 0000000000000000000000000000000000000000..aeb6b16f7be7e1eb249febe55b6f58df5d35aca4 GIT binary patch literal 689 zcmV;i0#5yjP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10zOGZ zK~y-6g^)i>TTvW_-+MhVVlZTjB*EnhibE~EToLZR^9ah$isVlgo^Gz0+1<#JF;q1|p{Z*R{} zCX-*Mr>8#y_+l7F{U6Ef?CkeaslPU;ryCD^Wh54*}F}1xUWoT3_z$?1ZDEqs(M7-D6o6H#avKhGFD+-s?LT zB>9TuWu;OHEz9b{TU%QUf`AJP3$$%}!?x|1*-Ky;#wP&tQp#v~c{z&5<5*f+ilmgf zTrR_PT>uE~Y;dE=8(}CeR5XQ6I_j zv3+!&-+j+>-edSbOTEdY3l}a}*=)AMFpO5ElxVG&8yXrG#>dC2?-d}GN)1|;b=9`* zr0cq2(=?9&c%JvFR4T1itJSZ4-~aW)hY$b$P67J*`oga3-ibsasg{jvX$&=l#>vH7C5t7Ly(P)%l zFo^H_Y;0_>xVXs7%naFVmQtz2%F4=gxm^BiYHDiktpWP_`of`5=!?^*Pj?4{K~kv{ zU0q#RmIZ+C`}n?JfBI6X#N)@0nV6WMSS+%k5BobpiJw4wI zg+g4sc#%`5P7w?S2?PSzwvA<3oH%iUXf%pp7!->|nwpx3L?S$W`V_};n)CVmcNP~H zZ|}PTsZ?sPy}kX9$z-ze+_`h~_V!}iHnwe3%Yg6uM5EDqMPM@*wfEZCFbu7f5?}-P z9Js2Kn%xbczLMiOzdCm8SmV*7N9pP5!M1H2#~~01)D1-h)7()slv0QYN~!H2hEhrc zA>hZr1rZtC4Z?uUbM81!!nSQXJ3Fx~3(KdBL@{HC)$4M9^CAfO*&E zb%2J3hJ{=%_p)3rH!mzK5Q#+U+h7<*9pHV)02m)1uX>*Mb*WV1$&)7(3I&SAB85T$ ztu?V&jPCC41DlD+f{6T1MB+OD0JPS>U0q$xzIgG1OeRC2P{8+ndU|?jY;1h({J*7Q zz|Vj$MdbJnfQgBTFLJqDx>Bi-PN$ihn_gKu zxpCtLhGB5|@@1x`rViwI`0!y&(Toy=Th)Ip-cwUkbDrl7E-fwn`O%|CC4f*U z#PIO&fr1#1$7O76Ot-YO)V>qEyo44tmJ9l{Y>>16?&9!N| zzUF=aY7&v}0lx==0Q2+nYG`Q41Q;6|)5&B~06fn#u3x`yXsuaUSz&2uiJ6(1ue8=5 zPfkv*zBRxW#P_!#9Dv!`S*4U>TR1DvpFjV_(9qB?`}_O*j~_qIg9i`3T3=tUn;!^Z z3*tw>UBLdvPZi*&N~u2$3=A}yrui4gaVQiDJIvpSMC2n8`Dg8PY>hwKK4)NHps^OZ k_a+f(5s{W}pSe^20WR2>OICg0!2kdN07*qoM6N<$f=Dp$lmGw# literal 0 HcmV?d00001 diff --git a/src/icons/images/find_prev_16px.png b/src/icons/images/find_prev_16px.png new file mode 100644 index 0000000000000000000000000000000000000000..cf9d4b6a47af2ae46794823da596989f9e4aff66 GIT binary patch literal 702 zcmV;v0zv(WP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10!v9m zK~y-6b&^d>8(|cMpG+ok5dCFNYhU848#Agfv)RnB9ZtqIXO8$J3E^g z9v;T?JSvq6rfD{+)v6hW;qzW5DnL9Qe>*)rJ)h6#6aD@D0BD-V`1m+eQ&WkHi;Jfx zCnxKMVZ7?O#nRH!&#kR3IX^!a%d*6>EUDM)(!%xiwFE&RzVE+&C|0uBY$_Iujipkl z4k8Ew01U%mW@ZM%Fo;H@A4Q~N3&n99X*QcUj)QI6TwY${x-Nr*gY50?vAVj7<2V$H zMNHFFfOQdh*)}*jI{Ix{R`vAsl&h;Nf*@dMXoym&#Paeox3{+dIF7^0$_l%?yHVhi zh`az$0J*uj+1T0HY1p<+I-Tb5@Q}sD#kRNw*L5iti|p_3M}f~G@;C~RPN%=ywmmm7 zG4V)5qJ=_%Mx)UyaD3lqb90kiE~ku+j#k=)uIuXB+S&)-_rq5DBO@bS?;e^WlIfZt zA{p0pO%V}I(>lbOrb!S4a(sOJr&g=YwKC{Dib$l~*Vp&;u71cNA{-nXBo`JI-efYF zSeL;an!OCdFhoR1CX)aj+?{d{Yy)1kT8%vt<807*qoM6N<$g4>lm%K!iX literal 0 HcmV?d00001 diff --git a/src/icons/images/find_prev_16px@2x.png b/src/icons/images/find_prev_16px@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe78865c343d38eac5a04dfc05cbde2f77c31779 GIT binary patch literal 1514 zcmV2N>f#&4N@g46)1KML2N70Ux2!; zS~mR)-L+j*y)R&aL?lFo96K1IAQB}ICN{Ps8|Px?e&%$M%qS*KY(p>a>dZH1zW15) zog45!i>as6$&)9!VzJoCvTO&#Fq9CI4F-eq=;)~RuL6X_;X#h$zT|nnTau&}kH^yt z0ES^KX_~fZS=Ov=+h2{1js5kH0`&Lyw@8xoV;~R+x3{L|Y}>}l$_g@> z3?4mtgkrG>P1BIi=O=YtKQlf)KJ&@|{r&wdKA-Q-p+krIL{UUI9LE0r`@wM>0Km3w z*tYHdy{2iHn3zB!k$|eI$Y!&XhG7gQlgXue0X*v;y1Kf4K6vopyFQ-}!^6WkaNqz$ zQG_4};CUV#$6?>TeF%j@U|ANbs-m^E6@fqixm*rSO-*e}OG|HOGMOJ59)WN;Jh*Gu zuHU-5yLTKvejJAn9|q6!;CUX-9I$O0?d|R0c^&{zDwU8FEK-ao{)(JkP`H^+J*)NRkAv*9+4$p{nYJM00a44y z0D$Lt7QpY6($jST6pO`9pU>9<0HIK*);B1Z%N5VEEF%($AQFi{mSra_0QiYg`e97~ zkH_<-AP9a!2t-k=Sm(N~LseC%stR4#!7vPh!JwNUlgS_&jpEs}XKp*4PCKt90Dn+Q zKiCog00jM59qmPfu?)vPh@Xh{a;a z<#JA_3BV0X>H8Z1Mn^|2!!TwwO~b>751}ZEYYqT=_wI$qv$|(3FE3+cWCT-FQ=6JQ znwy)$`Sa(I&*z=c8(1yJI~4!`KnVG|P$(1^78a07rQBif>+5qjo|Tmq#9}c_Oia`? zcl6}Rlb0dlgF+{G@H$xPALJ0)YU4)pb8IGJ;ep)v&pv+1XjdVlfnpMJF`8 z0U(u1E$X^{CY#Mpnx+ZMvY;pmE?>TkWHR~6=8mSOrVx!r@%;I7H&*pRGB7aE?D2TM zzjp1~@X*kZw_2Z_J9pM)x^6#sS-&t0^C?^HO){BWipS$0-@SYH;)@qAjB0%trmpKG zD5cfHB>-1}IxeM@(jH3bw*XEt3?n)5&dyE{LTUoYvg|Hl+qO$A%iaQTm0_4^0N`pR zU>Ifwz$a@k1^|97UekQ-8@GMp#EC4W^oy~vF?V;WT7s?eHQ2vG9*?KbvaFj&j~;c8 z+*by0w&hx~ZQE_LEDMg~-m)y~=D@(fj{h8>t*y;zx|63-fMuuA=o}z~!0-2iVVDOj z%YK+lCJR6vlkg?o0`M6CjE|3Rw!|tViXwp3dx9*>4+tTydBdWV_EJhqv_a{*POe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/icons/svg/find_prev_16px.svg b/src/icons/svg/find_prev_16px.svg new file mode 100644 index 000000000..51d796955 --- /dev/null +++ b/src/icons/svg/find_prev_16px.svg @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lay/lay/MacroEditorDialog.ui b/src/lay/lay/MacroEditorDialog.ui index 80f62e53c..fa02c8421 100644 --- a/src/lay/lay/MacroEditorDialog.ui +++ b/src/lay/lay/MacroEditorDialog.ui @@ -463,10 +463,6 @@ ... - - - :/breakpoint_16px.png:/breakpoint_16px.png - F9 @@ -636,7 +632,7 @@ - :/find_16px.png:/find_16px.png + :/find_next_16px.png:/find_next_16px.png Ctrl+F @@ -646,6 +642,23 @@ + + + + ... + + + + :/find_prev_16px.png:/find_prev_16px.png + + + Ctrl+Shift+F + + + true + + + diff --git a/src/lay/lay/layMacroEditorDialog.cc b/src/lay/lay/layMacroEditorDialog.cc index e75c60dfa..bf8c9ed03 100644 --- a/src/lay/lay/layMacroEditorDialog.cc +++ b/src/lay/lay/layMacroEditorDialog.cc @@ -493,6 +493,7 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection 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 ())); + connect (findPrevButton, SIGNAL (clicked ()), this, SLOT (find_prev_button_clicked ())); connect (replaceAllButton, SIGNAL (clicked ()), this, SLOT (replace_all_button_clicked ())); connect (allVariables, SIGNAL (clicked (bool)), variableList, SLOT (set_show_all (bool))); @@ -2021,7 +2022,7 @@ MacroEditorDialog::replace_all_button_clicked () } void -MacroEditorDialog::search_requested (const QString &s) +MacroEditorDialog::search_requested (const QString &s, bool prev) { if (! s.isNull ()) { searchEditBox->setText (s); @@ -2029,7 +2030,21 @@ MacroEditorDialog::search_requested (const QString &s) searchEditBox->selectAll (); } searchEditBox->setFocus (); - search_editing (); + + MacroEditorPage *page = dynamic_cast (tabWidget->currentWidget ()); + if (! page) { + return; + } + + apply_search (); + page->find_reset (); // search from the initial position + if (! page->has_multi_block_selection ()) { + if (! prev) { + page->find_next (); + } else { + page->find_prev (); + } + } } void @@ -3511,7 +3526,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 (search_requested (const QString &, bool)), this, SLOT (search_requested (const QString &, bool))); 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 54d9428df..24bd3eccf 100644 --- a/src/lay/lay/layMacroEditorDialog.h +++ b/src/lay/lay/layMacroEditorDialog.h @@ -222,7 +222,7 @@ private slots: void find_next_button_clicked (); void find_prev_button_clicked (); void help_requested (const QString &s); - void search_requested (const QString &s); + void search_requested (const QString &s, bool prev); void macro_changed (lym::Macro *macro); void macro_deleted (lym::Macro *macro); void macro_collection_deleted (lym::MacroCollection *collection); diff --git a/src/lay/lay/layMacroEditorPage.cc b/src/lay/lay/layMacroEditorPage.cc index 408949cd2..3abaa328b 100644 --- a/src/lay/lay/layMacroEditorPage.cc +++ b/src/lay/lay/layMacroEditorPage.cc @@ -1077,12 +1077,10 @@ MacroEditorPage::find_prev () first = false; int i = -1; - int l = 0; int p = 0; while (true) { int ii = m_current_search.indexIn (b.text (), p); if (ii >= 0 && (o < 0 || ii < o)) { - l = m_current_search.matchedLength (); i = ii; p = ii + 1; } else { @@ -1091,8 +1089,7 @@ MacroEditorPage::find_prev () } if (i >= 0) { QTextCursor newc (b); - newc.setPosition (i + b.position () + l); - newc.setPosition (i + b.position (), QTextCursor::KeepAnchor); + newc.setPosition (i + b.position ()); m_ignore_cursor_changed_event = true; mp_text->setTextCursor (newc); m_ignore_cursor_changed_event = false; @@ -1136,8 +1133,7 @@ MacroEditorPage::find_next () int i = m_current_search.indexIn (b.text (), o); if (i >= 0) { QTextCursor newc (b); - newc.setPosition (i + b.position () + m_current_search.matchedLength ()); - newc.setPosition (i + b.position (), QTextCursor::KeepAnchor); + newc.setPosition (i + b.position ()); m_ignore_cursor_changed_event = true; mp_text->setTextCursor (newc); m_ignore_cursor_changed_event = false; @@ -1158,6 +1154,39 @@ MacroEditorPage::find_next () return false; } +bool +MacroEditorPage::select_match_here () +{ + if (m_current_search == QRegExp ()) { + return false; + } + + QTextCursor c = mp_text->textCursor (); + if (c.isNull ()) { + return false; + } + + if (c.hasSelection ()) { + return true; + } + + QTextBlock b = c.block (); + int pos = c.position () - b.position (); + int i = m_current_search.indexIn (b.text (), pos); + if (i == pos) { + 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; + } else { + return false; + } +} + void MacroEditorPage::set_editor_focus () { @@ -1196,7 +1225,9 @@ MacroEditorPage::replace_and_find_next (const QString &replace) return; } - replace_in_selection (replace, true); + if (select_match_here ()) { + replace_in_selection (replace, true); + } find_next (); } @@ -1280,12 +1311,8 @@ MacroEditorPage::replace_in_selection (const QString &replace, bool first) o = i + r.size (); if (first) { - - // in single-selection mode, put cursor past substitution - c.setPosition (i + b.position ()); has_selection = false; done = true; - } else if (b == be) { pe += int (r.size ()) - int (m_current_search.matchedLength ()); } @@ -1734,6 +1761,11 @@ static bool is_find_key (QKeyEvent *ke) return ke->key () == Qt::Key_F && (ke->modifiers () & Qt::ControlModifier) != 0; } +static bool is_find_backwards_key (QKeyEvent *ke) +{ + return ke->key () == Qt::Key_F && (ke->modifiers () & Qt::ControlModifier) != 0 && (ke->modifiers () & Qt::ShiftModifier) != 0; +} + static bool is_up_key (QKeyEvent *ke) { return ke->key () == Qt::Key_Up; @@ -1755,6 +1787,7 @@ static bool is_any_known_key (QKeyEvent *ke) is_help_key (ke) || is_find_next_key (ke) || is_find_key (ke) || + is_find_backwards_key (ke) || is_up_key (ke) || is_down_key (ke); } @@ -1848,19 +1881,21 @@ MacroEditorPage::eventFilter (QObject *watched, QEvent *event) QApplication::sendEvent (mp_completer_list, event); return true; - } else if (is_find_key (ke)) { + } else if (is_find_key (ke) || is_find_backwards_key (ke)) { + + bool prev = is_find_backwards_key (ke); QTextCursor c = mp_text->textCursor (); if (c.selectionStart () != c.selectionEnd ()) { QTextBlock s = mp_text->document ()->findBlock (c.selectionStart ()); QTextBlock e = mp_text->document ()->findBlock (c.selectionEnd ()); if (e == s) { - emit search_requested (c.selectedText ()); + emit search_requested (c.selectedText (), prev); } else { - emit search_requested (QString ()); + emit search_requested (QString (), prev); } } else { - emit search_requested (QString ()); + emit search_requested (QString (), prev); } return true; diff --git a/src/lay/lay/layMacroEditorPage.h b/src/lay/lay/layMacroEditorPage.h index a689aefe5..c298a32b4 100644 --- a/src/lay/lay/layMacroEditorPage.h +++ b/src/lay/lay/layMacroEditorPage.h @@ -271,7 +271,7 @@ public: signals: void help_requested (const QString &s); - void search_requested (const QString &s); + void search_requested (const QString &s, bool backward); void edit_trace (bool); public slots: @@ -314,6 +314,7 @@ private: void fill_completer_list (); void complete (); QTextCursor get_completer_cursor (int &pos0, int &pos); + bool select_match_here (); void replace_in_selection (const QString &replace, bool first); bool eventFilter (QObject *watched, QEvent *event);