1 // Find dialog derived from an example from Qt Toolkit (license below (**))
2 
3 ////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2009-2021 The Octave Project Developers
6 //
7 // See the file COPYRIGHT.md in the top-level directory of this
8 // or <https://octave.org/copyright/>.
9 //
10 //  All rights reserved.
11 //  Contact: Nokia Corporation (qt-info@nokia.com)
12 //
13 // This file is part of Octave.
14 //
15 // Octave is free software: you can redistribute it and/or modify it
16 // under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 // Octave is distributed in the hope that it will be useful, but
21 // WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 // GNU General Public License for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with Octave; see the file COPYING.  If not, see
27 // <https://www.gnu.org/licenses/>.
28 //
29 // ** This file is part of the examples of the Qt Toolkit.
30 // **
31 // ** $QT_BEGIN_LICENSE:LGPL$
32 // ** Commercial Usage
33 // ** Licensees holding valid Qt Commercial licenses may use this file in
34 // ** accordance with the Qt Commercial License Agreement provided with the
35 // ** Software or, alternatively, in accordance with the terms contained in
36 // ** a written agreement between you and Nokia.
37 // **
38 // ** GNU Lesser General Public License Usage
39 // ** Alternatively, this file may be used under the terms of the GNU Lesser
40 // ** General Public License version 2.1 as published by the Free Software
41 // ** Foundation and appearing in the file LICENSE.LGPL included in the
42 // ** packaging of this file.  Please review the following information to
43 // ** ensure the GNU Lesser General Public License version 2.1 requirements
44 // ** will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
45 // **
46 // ** In addition, as a special exception, Nokia gives you certain additional
47 // ** rights.  These rights are described in the Nokia Qt LGPL Exception
48 // ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
49 // **
50 // ** GNU General Public License Usage
51 // ** Alternatively, this file may be used under the terms of the GNU
52 // ** General Public License version 3.0 as published by the Free Software
53 // ** Foundation and appearing in the file LICENSE.GPL included in the
54 // ** packaging of this file.  Please review the following information to
55 // ** ensure the GNU General Public License version 3.0 requirements will be
56 // ** met: https://www.gnu.org/copyleft/gpl.html.
57 // **
58 // ** If you have questions regarding the use of this file, please contact
59 // ** Nokia at qt-info@nokia.com.
60 // ** $QT_END_LICENSE$
61 //
62 ////////////////////////////////////////////////////////////////////////
63 
64 #if defined (HAVE_CONFIG_H)
65 #  include "config.h"
66 #endif
67 
68 #if defined (HAVE_QSCINTILLA)
69 
70 #include <QApplication>
71 #include <QCheckBox>
72 #include <QCheckBox>
73 #include <QCompleter>
74 #include <QDesktopWidget>
75 #include <QDialogButtonBox>
76 #include <QGridLayout>
77 #include <QIcon>
78 #include <QLabel>
79 #include <QLineEdit>
80 #include <QMessageBox>
81 #include <QPushButton>
82 #include <QVBoxLayout>
83 
84 #include "find-dialog.h"
85 #include "gui-preferences-ed.h"
86 #include "resource-manager.h"
87 #include "octave-qobject.h"
88 
89 namespace octave
90 {
find_dialog(base_qobject & oct_qobj,octave_dock_widget * ed,QWidget * p)91   find_dialog::find_dialog (base_qobject& oct_qobj,
92                             octave_dock_widget *ed, QWidget *p)
93     : QDialog (p), m_octave_qobj (oct_qobj), m_editor (ed),
94       m_in_sel (false), m_sel_beg (-1), m_sel_end (-1)
95   {
96     setWindowTitle (tr ("Editor: Find and Replace"));
97     setWindowIcon (QIcon (":/actions/icons/find.png"));
98 
99     _search_label = new QLabel (tr ("Find &what:"));
100     _search_line_edit = new QComboBox (this);
101     _search_line_edit->setToolTip (tr ("Enter text to search for"));
102     _search_line_edit->setEditable (true);
103     _search_line_edit->setMaxCount (m_mru_length);
104     _search_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive);
105     _search_label->setBuddy (_search_line_edit);
106 
107     _replace_label = new QLabel (tr ("Re&place with:"));
108     _replace_line_edit = new QComboBox (this);
109     _replace_line_edit->setToolTip (tr ("Enter new text replacing search hits"));
110     _replace_line_edit->setEditable (true);
111     _replace_line_edit->setMaxCount (m_mru_length);
112     _replace_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive);
113     _replace_label->setBuddy (_replace_line_edit);
114 
115      int width = QFontMetrics (_search_line_edit->font ()).averageCharWidth();
116      _search_line_edit->setFixedWidth (20*width);
117      _replace_line_edit->setFixedWidth (20*width);
118 
119     _case_check_box = new QCheckBox (tr ("Match &case"));
120     _from_start_check_box = new QCheckBox (tr ("Search from &start"));
121     _wrap_check_box = new QCheckBox (tr ("&Wrap while searching"));
122     _wrap_check_box->setChecked (true);
123     _find_next_button = new QPushButton (tr ("&Find Next"));
124     _find_prev_button = new QPushButton (tr ("Find &Previous"));
125     _replace_button = new QPushButton (tr ("&Replace"));
126     _replace_all_button = new QPushButton (tr ("Replace &All"));
127 
128     _more_button = new QPushButton (tr ("&More..."));
129     _more_button->setCheckable (true);
130     _more_button->setAutoDefault (false);
131 
132     _button_box = new QDialogButtonBox (Qt::Vertical);
133     _button_box->addButton (_find_next_button, QDialogButtonBox::ActionRole);
134     _button_box->addButton (_find_prev_button, QDialogButtonBox::ActionRole);
135     _button_box->addButton (_replace_button, QDialogButtonBox::ActionRole);
136     _button_box->addButton (_replace_all_button, QDialogButtonBox::ActionRole);
137     _button_box->addButton (_more_button, QDialogButtonBox::ActionRole);
138     _button_box->addButton (QDialogButtonBox::Close);
139 
140     _extension = new QWidget (this);
141     _whole_words_check_box = new QCheckBox (tr ("&Whole words"));
142     _regex_check_box = new QCheckBox (tr ("Regular E&xpressions"));
143     _backward_check_box = new QCheckBox (tr ("Search &backward"));
144     _search_selection_check_box = new QCheckBox (tr ("Search se&lection"));
145     _search_selection_check_box->setCheckable (true);
146 
147     connect (_find_next_button,   SIGNAL (clicked ()),
148              this,                SLOT (find_next ()));
149     connect (_find_prev_button,   SIGNAL (clicked ()),
150              this,                SLOT (find_prev ()));
151     connect (_more_button,        SIGNAL (toggled (bool)),
152              _extension,          SLOT (setVisible (bool)));
153     connect (_replace_button,     SIGNAL (clicked ()),
154              this,                SLOT (replace ()));
155     connect (_replace_all_button, SIGNAL (clicked ()),
156              this,                SLOT (replace_all ()));
157     connect (_backward_check_box, SIGNAL (stateChanged (int)),
158              this,                SLOT (handle_backward_search_changed (int)));
159     connect (_button_box,         SIGNAL (rejected ()),
160              this,                SLOT (close ()));
161 
162     connect (_search_selection_check_box, SIGNAL (stateChanged (int)),
163              this,                        SLOT (handle_sel_search_changed (int)));
164 
165     QVBoxLayout *extension_layout = new QVBoxLayout ();
166     extension_layout->setMargin (0);
167     extension_layout->addWidget (_whole_words_check_box);
168     extension_layout->addWidget (_backward_check_box);
169     extension_layout->addWidget (_search_selection_check_box);
170     _extension->setLayout (extension_layout);
171 
172     QGridLayout *top_left_layout = new QGridLayout;
173     top_left_layout->addWidget (_search_label, 1, 1);
174     top_left_layout->addWidget (_search_line_edit, 1, 2);
175     top_left_layout->addWidget (_replace_label, 2, 1);
176     top_left_layout->addWidget (_replace_line_edit, 2, 2);
177 
178     QVBoxLayout *left_layout = new QVBoxLayout;
179     left_layout->addLayout (top_left_layout);
180     left_layout->insertStretch (1, 5);
181     left_layout->addWidget (_case_check_box);
182     left_layout->addWidget (_from_start_check_box);
183     left_layout->addWidget (_wrap_check_box);
184     left_layout->addWidget (_regex_check_box);
185 
186     QGridLayout *main_layout = new QGridLayout;
187     main_layout->setSizeConstraint (QLayout::SetFixedSize);
188     main_layout->addLayout (left_layout, 0, 0);
189     main_layout->addWidget (_button_box, 0, 1);
190     main_layout->addWidget (_extension, 1, 0);
191     setLayout (main_layout);
192 
193     _extension->hide ();
194     _find_next_button->setDefault (true);
195     _find_result_available = false;
196     _rep_all = 0;
197     _rep_active = false;
198 
199     // Connect required external signals
200     connect (ed, SIGNAL (edit_area_changed (octave_qscintilla*)),
201              this, SLOT (update_edit_area (octave_qscintilla*)));
202 
203     setWindowModality (Qt::NonModal);
204 
205     setAttribute(Qt::WA_ShowWithoutActivating);
206     setAttribute(Qt::WA_DeleteOnClose);
207   }
208 
209   // The edit_area has changed: update relevant data of the file dialog
update_edit_area(octave_qscintilla * edit_area)210   void find_dialog::update_edit_area (octave_qscintilla* edit_area)
211   {
212     _edit_area = edit_area;
213     _search_selection_check_box->setEnabled (edit_area->hasSelectedText ());
214 
215     connect (_edit_area, SIGNAL (copyAvailable (bool)),
216              this,       SLOT (handle_selection_changed (bool)),
217              Qt::UniqueConnection);
218   }
219 
save_settings()220   void find_dialog::save_settings ()
221   {
222     resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
223     gui_settings *s = rmgr.get_settings ();
224 
225     // Save position
226     QPoint dlg_pos = pos ();
227 
228 #if defined (Q_OS_WIN32)
229     int y = dlg_pos.y ();
230 #else
231     int y = dlg_pos.y () - geometry ().height () + frameGeometry ().height ();
232 #endif
233 
234     m_last_position = QPoint (dlg_pos.x (), y);
235 
236     s->setValue (ed_fdlg_pos.key, m_last_position);
237 
238     // Is current search/replace text in the mru list?
239     mru_update (_search_line_edit);
240     mru_update (_replace_line_edit);
241 
242     // Store mru lists
243     QStringList mru;
244     for (int i = 0; i < _search_line_edit->count (); i++)
245       mru.append (_search_line_edit->itemText (i));
246     s->setValue (ed_fdlg_search.key, mru);
247 
248     mru.clear ();
249     for (int i = 0; i < _replace_line_edit->count (); i++)
250       mru.append (_replace_line_edit->itemText (i));
251     s->setValue (ed_fdlg_replace.key, mru);
252 
253     // Store dialog's options
254     int opts = 0
255                + _extension->isVisible () * FIND_DLG_MORE
256                + _case_check_box->isChecked () * FIND_DLG_CASE
257                + _from_start_check_box->isChecked () * FIND_DLG_START
258                + _wrap_check_box->isChecked () * FIND_DLG_WRAP
259                + _regex_check_box->isChecked () * FIND_DLG_REGX
260                + _whole_words_check_box->isChecked () * FIND_DLG_WORDS
261                + _backward_check_box->isChecked () * FIND_DLG_BACK
262                + _search_selection_check_box->isChecked () * FIND_DLG_SEL;
263     s->setValue (ed_fdlg_opts.key, opts);
264 
265     s->sync ();
266   }
267 
restore_settings(QPoint ed_bottom_right)268   void find_dialog::restore_settings (QPoint ed_bottom_right)
269   {
270     resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
271     gui_settings *s = rmgr.get_settings ();
272 
273     // Get mru lists for search and replace text
274     QStringList mru = s->value (ed_fdlg_search.key).toStringList ();
275     while (mru.length () > m_mru_length)
276       mru.removeLast ();
277     _search_line_edit->addItems (mru);
278 
279     mru = s->value (ed_fdlg_replace.key).toStringList ();
280     while (mru.length () > m_mru_length)
281       mru.removeLast ();
282     _replace_line_edit->addItems (mru);
283 
284     // Get the dialog's options
285     int opts = s->value (ed_fdlg_opts.key, ed_fdlg_opts.def).toInt ();
286 
287     _extension->setVisible (FIND_DLG_MORE & opts);
288     _case_check_box->setChecked (FIND_DLG_CASE & opts);
289     _from_start_check_box->setChecked (FIND_DLG_START & opts);
290     _wrap_check_box->setChecked (FIND_DLG_WRAP & opts);
291     _regex_check_box->setChecked (FIND_DLG_REGX & opts);
292     _whole_words_check_box->setChecked (FIND_DLG_WORDS & opts);
293     _backward_check_box->setChecked (FIND_DLG_BACK & opts);
294     _search_selection_check_box->setChecked (FIND_DLG_SEL & opts);
295 
296     // Position:  lower right of editor's position
297     int xp = ed_bottom_right.x () - sizeHint ().width ();
298     int yp = ed_bottom_right.y () - sizeHint ().height ();
299 
300     m_last_position = s->value (ed_fdlg_pos.key, QPoint (xp,yp)).toPoint ();
301     move (m_last_position);
302 
303     if (QApplication::desktop ()->screenNumber (this) == -1)
304       {
305         // Last used position is not on screen anymore, use default pos.
306         m_last_position = QPoint (xp,yp);
307         move (m_last_position);
308 
309         if (QApplication::desktop ()->screenNumber (this) == -1)
310           {
311             // Default position is not on screen, last resort
312             m_last_position = QPoint (50,100);  // upper left
313             move (m_last_position);
314           }
315       }
316 
317   }
318 
319   // set text of "search from start" depending on backward search
handle_backward_search_changed(int backward)320   void find_dialog::handle_backward_search_changed (int backward)
321   {
322     if (backward)
323       _from_start_check_box->setText (tr ("Search from end"));
324     else
325       _from_start_check_box->setText (tr ("Search from start"));
326   }
327 
328   // search text has changed: reset the search
handle_search_text_changed(void)329   void find_dialog::handle_search_text_changed (void)
330   {
331     // Return if nothing has changed
332     if (_search_line_edit->currentText () == _search_line_edit->itemText (0))
333       return;
334 
335     if (_search_selection_check_box->isChecked ())
336       _find_result_available = false;
337 
338     mru_update (_search_line_edit);
339   }
340 
341   // replaced text has changed: reset the search
handle_replace_text_changed(void)342   void find_dialog::handle_replace_text_changed (void)
343   {
344     // Return if nothing has changed
345     if (_replace_line_edit->currentText () == _replace_line_edit->itemText (0))
346       return;
347 
348     mru_update (_replace_line_edit);
349   }
350 
351   // Update the mru list
mru_update(QComboBox * mru)352   void find_dialog::mru_update (QComboBox *mru)
353   {
354     // Remove possible empty entries from the mru list
355     int index;
356     while ((index = mru->findText (QString ())) >= 0)
357       mru->removeItem (index);
358 
359     // Get current text and return if it is empty
360     QString text = mru->currentText ();
361 
362     if (text.isEmpty ())
363       return;
364 
365     // Remove occurrences of the current text in the mru list
366     while ((index = mru->findText (text)) >= 0)
367       mru->removeItem (index);
368 
369     // Remove the last entry from the end if the list is full
370     if (mru->count () == m_mru_length)
371       mru->removeItem (m_mru_length -1);
372 
373     // Insert new item at the beginning and set it as current item
374     mru->insertItem (0, text);
375     mru->setCurrentIndex (0);
376   }
377 
handle_sel_search_changed(int selected)378   void find_dialog::handle_sel_search_changed (int selected)
379   {
380     _from_start_check_box->setEnabled (! selected);
381     _find_result_available = false;
382   }
383 
handle_selection_changed(bool has_selected)384   void find_dialog::handle_selection_changed (bool has_selected)
385   {
386     if (_rep_active)
387       return;
388 
389     _search_selection_check_box->setEnabled (has_selected);
390     _find_result_available = false;
391   }
392 
393   // initialize search text with selected text if this is in one single line
init_search_text(void)394   void find_dialog::init_search_text (void)
395   {
396     if (_edit_area && _edit_area->hasSelectedText ())
397       {
398         int lbeg, lend, cbeg, cend;
399         _edit_area->getSelection (&lbeg,&cbeg,&lend,&cend);
400         if (lbeg == lend)
401 #if defined (HAVE_QCOMBOBOX_SETCURRENTTEXT)
402           _search_line_edit->setCurrentText (_edit_area->selectedText ());
403 #else
404           if (_search_line_edit->isEditable ())
405             {
406               _search_line_edit->setEditText (_edit_area->selectedText ());
407             }
408           else
409             {
410               int i = _search_line_edit->findText (_edit_area->selectedText ());
411 
412               if (i > -1)
413                 _search_line_edit->setCurrentIndex (i);
414             }
415 #endif
416       }
417 
418     // set focus to "Find what" and select all text
419     _search_line_edit->setFocus ();
420     _search_line_edit->lineEdit ()->selectAll ();
421 
422     // Default to "find" next time.
423     // Otherwise, it defaults to the last action, which may be "replace all".
424     _find_next_button->setDefault (true);
425   }
426 
find_next(void)427   void find_dialog::find_next (void)
428   {
429     find (! _backward_check_box->isChecked ());
430   }
431 
find_prev(void)432   void find_dialog::find_prev (void)
433   {
434     find (_backward_check_box->isChecked ());
435   }
436 
find(bool forward)437   void find_dialog::find (bool forward)
438   {
439     if (! _edit_area)
440       return;
441 
442     handle_search_text_changed ();
443 
444     // line adn col: -1 means search starts at current position
445     int line = -1, col = -1;
446 
447     bool do_wrap = _wrap_check_box->isChecked ();
448     bool do_forward = forward;
449 
450     // Initialize the selection begin and end if it is the first search
451     if (! _find_result_available)
452       {
453         if (_search_selection_check_box->isChecked ()
454             && _edit_area->hasSelectedText ())
455           {
456             int l1, c1, l2, c2;
457             _edit_area->getSelection (&l1, &c1, &l2, &c2);
458 
459             // Store the position of the selection
460             m_sel_beg = _edit_area->positionFromLineIndex (l1, c1);
461             m_sel_end = _edit_area->positionFromLineIndex (l2, c2);
462             m_in_sel = true;
463           }
464         else
465           m_in_sel = false;
466       }
467 
468     // Get the correct line/col for beginning the search
469     if (_rep_all)
470       {
471         // Replace All
472         if (_rep_all == 1)
473           {
474             // Start at the beginning of file/sel if it is the first try
475             if (m_in_sel)
476               _edit_area->lineIndexFromPosition (m_sel_beg, &line, &col);
477             else
478               {
479                 line = 0;
480                 col = 0;
481               }
482           }
483         do_wrap = false;  // Never wrap when replacing all
484       }
485     else
486       {
487         // Normal search (not replace all): calculate start position of
488         // search (in file or selection)
489         if (_from_start_check_box->isChecked ()
490             || (m_in_sel && (! _find_result_available)))
491           {
492             // From the beginning or the end of file/sel
493             if (do_forward)
494               {
495                 // From the beginning
496                 if (m_in_sel)
497                   _edit_area->lineIndexFromPosition (m_sel_beg, &line, &col);
498                 else
499                   {
500                     line = 0;
501                     col = 0;
502                   }
503               }
504             else
505               {
506                 // From the end
507                 if (m_in_sel)
508                   _edit_area->lineIndexFromPosition (m_sel_end, &line, &col);
509                 else
510                   {
511                     line = _edit_area->lines () - 1;
512                     col  = _edit_area->text (line).length () - 1;
513                     if (col == -1)
514                       col = 0;
515                   }
516               }
517           }
518         else if (! do_forward)
519           {
520             // Start from where the cursor is.  Fix QScintilla's cursor
521             // positioning
522             _edit_area->getCursorPosition (&line,&col);
523             if (_find_result_available && _edit_area->hasSelectedText ())
524               {
525                 int currpos = _edit_area->positionFromLineIndex (line,col);
526                 currpos -= (_search_line_edit->currentText ().length ());
527                 if (currpos < 0)
528                   currpos = 0;
529                 _edit_area->lineIndexFromPosition (currpos, &line, &col);
530               }
531           }
532       }
533 
534     // Do the search
535     _find_result_available
536       = _edit_area->findFirst (_search_line_edit->currentText (),
537                                _regex_check_box->isChecked (),
538                                _case_check_box->isChecked (),
539                                _whole_words_check_box->isChecked (),
540                                do_wrap,
541                                do_forward,
542                                line,col,
543                                true
544 #if defined (HAVE_QSCI_VERSION_2_6_0)
545                                , true
546 #endif
547                               );
548 
549     if (_find_result_available)
550       {
551         // Search successful: reset search-from-start box and check for
552         // the current selection
553         _from_start_check_box->setChecked (0);
554 
555         if (m_in_sel)
556           {
557             _edit_area->getCursorPosition (&line,&col);
558             int pos = _edit_area->positionFromLineIndex (line, col);
559 
560             int l1, c1, l2, c2;
561             _edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1);
562             _edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2);
563             _edit_area->show_selection_markers (l1, c1, l2, c2);
564 
565             // Check if new start position is still within the selection
566             _find_result_available =  pos >= m_sel_beg && pos <= m_sel_end;
567           }
568       }
569 
570     // No more search hits
571     if (! _find_result_available)
572       {
573         if (m_in_sel)
574           {
575             // Restore real selection and remove marker for selection
576             int l1, c1, l2, c2;
577             _edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1);
578             _edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2);
579             _edit_area->setSelection (l1, c1, l2, c2);
580             _edit_area->clear_selection_markers ();
581           }
582 
583         // Display message if not replace all
584         if (! _rep_all)
585           no_matches_message ();
586       }
587 
588   }
589 
do_replace(void)590   void find_dialog::do_replace (void)
591   {
592     if (_edit_area)
593       {
594         _rep_active = true;  // changes in selection not made by the user
595 
596         _edit_area->replace (_replace_line_edit->currentText ());
597         if (m_in_sel)
598           {
599             // Update the length of the selection
600             m_sel_end = m_sel_end
601                         - _search_line_edit->currentText ().toUtf8 ().size ()
602                         + _replace_line_edit->currentText ().toUtf8 ().size ();
603           }
604 
605         _rep_active = false;
606       }
607   }
608 
replace(void)609   void find_dialog::replace (void)
610   {
611     if (_edit_area)
612       {
613         handle_replace_text_changed ();
614 
615         // Do the replace if we have selected text
616         if (_find_result_available && _edit_area->hasSelectedText ())
617           do_replace ();
618 
619         find_next ();
620       }
621   }
622 
replace_all(void)623   void find_dialog::replace_all (void)
624   {
625     int line, col;
626 
627     if (_edit_area)
628       {
629         handle_replace_text_changed ();
630 
631         _edit_area->getCursorPosition (&line,&col);
632 
633         _rep_all = 1;
634         find_next ();  // find first occurrence (forward)
635 
636         _edit_area->beginUndoAction ();
637         while (_find_result_available)   // while search string is found
638           {
639             do_replace ();
640             _rep_all++;                                          // inc counter
641             find_next ();                                        // find next
642           }
643         _edit_area->endUndoAction ();
644 
645         QMessageBox msg_box (QMessageBox::Information, tr ("Replace Result"),
646                              tr ("%1 items replaced").arg (_rep_all-1),
647                              QMessageBox::Ok, this);
648         msg_box.exec ();
649 
650         _rep_all = 0;
651         _find_result_available = false;
652 
653         if (! _search_selection_check_box->isChecked ())
654           _edit_area->setCursorPosition (line,col);
655       }
656   }
657 
no_matches_message(void)658   void find_dialog::no_matches_message (void)
659   {
660     QMessageBox msg_box (QMessageBox::Information, tr ("Find Result"),
661                          tr ("No more matches found"), QMessageBox::Ok, this);
662     msg_box.exec ();
663   }
664 
reject()665   void find_dialog::reject ()
666   {
667     close ();
668   }
669 
closeEvent(QCloseEvent * e)670   void find_dialog::closeEvent (QCloseEvent *e)
671   {
672     save_settings ();
673     e->accept ();
674   }
675 
676   // Show and hide with (re-)storing position, otherwise there is always
677   // a small shift each time the dialog is shown again
set_visible(bool visible)678   void find_dialog::set_visible (bool visible)
679   {
680     if (visible)
681       {
682         show ();
683         move (m_last_position);
684       }
685     else
686       {
687         m_last_position = pos ();
688         hide ();
689       }
690   }
691 
692 }
693 #endif
694