changeset 27837:6bbff502f89d

add mru lists for search/replace texts in editor find dialog (bug #57238) * find-dialog.cc (find_dialog): use a combo-box instead line edit for search and replace texts, do not use signal on text changes anymore; (save_settings): clean up mru lists and save them in the preferences file; (restore_settings): get mru lists from preferences file, clip length to its maximum length and add items to the combo-boxes (handle_search_text_changed): return if current text is the first in the mru list, update mru list; (handle_replace_text_changed): new method for updating replace mru list (mru_update): new method for doing the update of the desired mrulist, removing empty entries, removing the current text an inserting the current text at the beginning; (init_search_text): updates due to changing from line edit to combo-box; (find): call method for updating search text mru list with current text, updates due to changing from line edit to combo-box; (do_replace): updates due to changing from line edit to combo-box; (replace, replace_all): call method for updating replace mru list with current text; * find-dialog.h: handle_search_text_changed with no argiments, new method handle_replace_text_changed and mru_update, switched from line edit to combo-box, new const for mru max length
author Torsten Lilge <ttl-octave@mailbox.org>
date Sun, 15 Dec 2019 10:38:14 +0100
parents f426dd9750a3
children 659acfaaf0c9
files libgui/src/m-editor/find-dialog.cc libgui/src/m-editor/find-dialog.h
diffstat 2 files changed, 111 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/m-editor/find-dialog.cc	Sat Dec 14 07:12:55 2019 -0800
+++ b/libgui/src/m-editor/find-dialog.cc	Sun Dec 15 10:38:14 2019 +0100
@@ -67,6 +67,7 @@
 
 #include <QCheckBox>
 #include <QCheckBox>
+#include <QCompleter>
 #include <QDialogButtonBox>
 #include <QGridLayout>
 #include <QIcon>
@@ -92,12 +93,25 @@
     setWindowIcon (QIcon (":/actions/icons/find.png"));
 
     _search_label = new QLabel (tr ("Find &what:"));
-    _search_line_edit = new QLineEdit;
+    _search_line_edit = new QComboBox (this);
+    _search_line_edit->setToolTip (tr ("Enter text to search for"));
+    _search_line_edit->setEditable (true);
+    _search_line_edit->setMaxCount (m_mru_length);
+    _search_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive);
     _search_label->setBuddy (_search_line_edit);
+
     _replace_label = new QLabel (tr ("Re&place with:"));
-    _replace_line_edit = new QLineEdit;
+    _replace_line_edit = new QComboBox (this);
+    _replace_line_edit->setToolTip (tr ("Enter new text replacing search hits"));
+    _replace_line_edit->setEditable (true);
+    _replace_line_edit->setMaxCount (m_mru_length);
+    _replace_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive);
     _replace_label->setBuddy (_replace_line_edit);
 
+     int width = QFontMetrics (_search_line_edit->font ()).averageCharWidth();
+     _search_line_edit->setFixedWidth (20*width);
+     _replace_line_edit->setFixedWidth (20*width);
+
     _case_check_box = new QCheckBox (tr ("Match &case"));
     _from_start_check_box = new QCheckBox (tr ("Search from &start"));
     _wrap_check_box = new QCheckBox (tr ("&Wrap while searching"));
@@ -140,8 +154,6 @@
              this,                SLOT (handle_backward_search_changed (int)));
     connect (_button_box,         SIGNAL (rejected ()),
              this,                SLOT (close ()));
-    connect (_search_line_edit,   SIGNAL (textChanged (QString)),
-             this,                SLOT (handle_search_text_changed (QString)));
 
     connect (_search_selection_check_box, SIGNAL (stateChanged (int)),
              this,                        SLOT (handle_sel_search_changed (int)));
@@ -218,9 +230,22 @@
 
     s->setValue (ed_fdlg_pos.key, m_last_position);
 
-    s->setValue (ed_fdlg_search.key, _search_line_edit->text ());
-    s->setValue (ed_fdlg_replace.key, _replace_line_edit->text ());
+    // Is current search/replace text in the mru list?
+    mru_update (_search_line_edit);
+    mru_update (_replace_line_edit);
 
+    // Store mru lists
+    QStringList mru;
+    for (int i = 0; i < _search_line_edit->count (); i++)
+      mru.append (_search_line_edit->itemText (i));
+    s->setValue (ed_fdlg_search.key, mru);
+
+    mru.clear ();
+    for (int i = 0; i < _replace_line_edit->count (); i++)
+      mru.append (_replace_line_edit->itemText (i));
+    s->setValue (ed_fdlg_replace.key, mru);
+
+    // Store dialog's options
     int opts = 0
           + _extension->isVisible () * FIND_DLG_MORE
           + _case_check_box->isChecked () * FIND_DLG_CASE
@@ -240,9 +265,18 @@
     resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
     gui_settings *s = rmgr.get_settings ();
 
-    _search_line_edit->setText (s->value (ed_fdlg_search.key).toString ());
-    _replace_line_edit->setText (s->value (ed_fdlg_replace.key).toString ());
+    // Get mru lists for search and replace text
+    QStringList mru = s->value (ed_fdlg_search.key).toStringList ();
+    while (mru.length () > m_mru_length)
+      mru.removeLast ();
+    _search_line_edit->addItems (mru);
 
+    mru = s->value (ed_fdlg_replace.key).toStringList ();
+    while (mru.length () > m_mru_length)
+      mru.removeLast ();
+    _replace_line_edit->addItems (mru);
+
+    // Get the dialog's options
     int opts = s->value (ed_fdlg_opts.key, ed_fdlg_opts.def).toInt ();
 
     _extension->setVisible (FIND_DLG_MORE & opts);
@@ -273,10 +307,54 @@
   }
 
   // search text has changed: reset the search
-  void find_dialog::handle_search_text_changed (QString)
+  void find_dialog::handle_search_text_changed (void)
   {
+    // Return if nothing has changed
+    if (_search_line_edit->currentText () == _search_line_edit->itemText (0))
+      return;
+
     if (_search_selection_check_box->isChecked ())
       _find_result_available = false;
+
+    mru_update (_search_line_edit);
+  }
+
+  // replaced text has changed: reset the search
+  void find_dialog::handle_replace_text_changed (void)
+  {
+    // Return if nothing has changed
+    if (_replace_line_edit->currentText ()
+            == _replace_line_edit->itemText (0))
+      return;
+
+    mru_update (_replace_line_edit);
+  }
+
+  // Update the mru list
+  void find_dialog::mru_update (QComboBox *mru)
+  {
+    // Remove possible empty entries from the mru list
+    int index;
+    while ((index = mru->findText (QString ())) >= 0)
+      mru->removeItem (index);
+
+    // Get current text and return if it is empty
+    QString text = mru->currentText ();
+
+    if (text.isEmpty ())
+      return;
+
+    // Remove occurrences of the current text in the mru list
+    while ((index = mru->findText (text)) >= 0)
+      mru->removeItem (index);
+
+    // Remove the last entry from the end if the list is full
+    if (mru->count () == m_mru_length)
+      mru->removeItem (m_mru_length -1);
+
+    // Insert new item at the beginning and set it as current item
+    mru->insertItem (0, text);
+    mru->setCurrentIndex (0);
   }
 
   void find_dialog::handle_sel_search_changed (int selected)
@@ -302,12 +380,12 @@
         int lbeg, lend, cbeg, cend;
         _edit_area->getSelection (&lbeg,&cbeg,&lend,&cend);
         if (lbeg == lend)
-          _search_line_edit->setText (_edit_area->selectedText ());
+          _search_line_edit->setCurrentText (_edit_area->selectedText ());
       }
 
     // set focus to "Find what" and select all text
     _search_line_edit->setFocus ();
-    _search_line_edit->selectAll ();
+    _search_line_edit->lineEdit ()->selectAll ();
 
     // Default to "find" next time.
     // Otherwise, it defaults to the last action, which may be "replace all".
@@ -329,6 +407,8 @@
     if (! _edit_area)
       return;
 
+    handle_search_text_changed ();
+
     // line adn col: -1 means search starts at current position
     int line = -1, col = -1;
 
@@ -411,7 +491,7 @@
             if (_find_result_available && _edit_area->hasSelectedText ())
               {
                 int currpos = _edit_area->positionFromLineIndex (line,col);
-                currpos -= (_search_line_edit->text ().length ());
+                currpos -= (_search_line_edit->currentText ().length ());
                 if (currpos < 0)
                   currpos = 0;
                 _edit_area->lineIndexFromPosition (currpos, &line, &col);
@@ -421,7 +501,7 @@
 
     // Do the search
     _find_result_available
-      = _edit_area->findFirst (_search_line_edit->text (),
+      = _edit_area->findFirst (_search_line_edit->currentText (),
                                _regex_check_box->isChecked (),
                                _case_check_box->isChecked (),
                                _whole_words_check_box->isChecked (),
@@ -481,13 +561,13 @@
       {
         _rep_active = true;  // changes in selection not made by the user
 
-        _edit_area->replace (_replace_line_edit->text ());
+        _edit_area->replace (_replace_line_edit->currentText ());
         if (m_in_sel)
           {
             // Update the length of the selection
             m_sel_end = m_sel_end
-                        - _search_line_edit->text ().toUtf8 ().size ()
-                        + _replace_line_edit->text ().toUtf8 ().size ();
+                        - _search_line_edit->currentText ().toUtf8 ().size ()
+                        + _replace_line_edit->currentText ().toUtf8 ().size ();
           }
 
         _rep_active = false;
@@ -498,6 +578,8 @@
   {
     if (_edit_area)
       {
+        handle_replace_text_changed ();
+
         // Do the replace if we have selected text
         if (_find_result_available && _edit_area->hasSelectedText ())
           do_replace ();
@@ -512,6 +594,8 @@
 
     if (_edit_area)
       {
+        handle_replace_text_changed ();
+
         _edit_area->getCursorPosition (&line,&col);
 
         _rep_all = 1;
--- a/libgui/src/m-editor/find-dialog.h	Sat Dec 14 07:12:55 2019 -0800
+++ b/libgui/src/m-editor/find-dialog.h	Sun Dec 15 10:38:14 2019 +0100
@@ -63,6 +63,7 @@
 #define octave_find_dialog_h 1
 
 #include <QDialog>
+#include <QComboBox>
 
 #include "octave-qscintilla.h"
 #include "octave-dock-widget.h"
@@ -112,7 +113,6 @@
     void handle_selection_changed (bool has_selected);
 
     void handle_backward_search_changed (int);
-    void handle_search_text_changed (QString new_search_text);
 
     void find (bool forward = true);
     void replace (void);
@@ -131,15 +131,21 @@
     //! Reimplemented close event
     void closeEvent (QCloseEvent* e);
 
+    //! Update mru lists with new entry
+    void mru_update (QComboBox *mru);
+
     void no_matches_message (void);
     void do_replace (void);
 
+    void handle_search_text_changed (void);
+    void handle_replace_text_changed (void);
+
     octave_dock_widget *m_editor;
 
     QLabel            *_search_label;
-    QLineEdit         *_search_line_edit;
+    QComboBox         *_search_line_edit;
     QLabel            *_replace_label;
-    QLineEdit         *_replace_line_edit;
+    QComboBox         *_replace_line_edit;
     QCheckBox         *_case_check_box;
     QCheckBox         *_from_start_check_box;
     QCheckBox         *_wrap_check_box;
@@ -164,6 +170,8 @@
     int                m_sel_end;
 
     QPoint             m_last_position;
+
+    const int          m_mru_length = 10;
   };
 }