xref: /glogg/src/quickfind.cpp (revision e85b29cce42703b1d8c343be8899be62c386c340)
1bb02e0acSNicolas Bonnefon /*
2*e85b29ccSNicolas Bonnefon  * Copyright (C) 2010, 2013, 2017 Nicolas Bonnefon and other contributors
3bb02e0acSNicolas Bonnefon  *
4bb02e0acSNicolas Bonnefon  * This file is part of glogg.
5bb02e0acSNicolas Bonnefon  *
6bb02e0acSNicolas Bonnefon  * glogg is free software: you can redistribute it and/or modify
7bb02e0acSNicolas Bonnefon  * it under the terms of the GNU General Public License as published by
8bb02e0acSNicolas Bonnefon  * the Free Software Foundation, either version 3 of the License, or
9bb02e0acSNicolas Bonnefon  * (at your option) any later version.
10bb02e0acSNicolas Bonnefon  *
11bb02e0acSNicolas Bonnefon  * glogg is distributed in the hope that it will be useful,
12bb02e0acSNicolas Bonnefon  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13bb02e0acSNicolas Bonnefon  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14bb02e0acSNicolas Bonnefon  * GNU General Public License for more details.
15bb02e0acSNicolas Bonnefon  *
16bb02e0acSNicolas Bonnefon  * You should have received a copy of the GNU General Public License
17bb02e0acSNicolas Bonnefon  * along with glogg.  If not, see <http://www.gnu.org/licenses/>.
18bb02e0acSNicolas Bonnefon  */
19bb02e0acSNicolas Bonnefon 
20bb02e0acSNicolas Bonnefon // This file implements QuickFind.
21bb02e0acSNicolas Bonnefon // This class implements the Quick Find mechanism using references
22bb02e0acSNicolas Bonnefon // to the logData, the QFP and the selection passed.
23bb02e0acSNicolas Bonnefon // Search is started just after the selection and the selection is updated
24bb02e0acSNicolas Bonnefon // if a match is found.
25bb02e0acSNicolas Bonnefon 
26bb02e0acSNicolas Bonnefon #include <QApplication>
27bb02e0acSNicolas Bonnefon 
28bb02e0acSNicolas Bonnefon #include "log.h"
29bb02e0acSNicolas Bonnefon #include "quickfindpattern.h"
30bb02e0acSNicolas Bonnefon #include "selection.h"
31bb02e0acSNicolas Bonnefon #include "data/abstractlogdata.h"
32bb02e0acSNicolas Bonnefon 
33bb02e0acSNicolas Bonnefon #include "quickfind.h"
34bb02e0acSNicolas Bonnefon 
reset()35bb02e0acSNicolas Bonnefon void SearchingNotifier::reset()
36bb02e0acSNicolas Bonnefon {
37bb02e0acSNicolas Bonnefon     dotToDisplay_ = 0;
38bb02e0acSNicolas Bonnefon     startTime_ = QTime::currentTime();
39bb02e0acSNicolas Bonnefon }
40bb02e0acSNicolas Bonnefon 
sendNotification(qint64 current_line,qint64 nb_lines)41bb02e0acSNicolas Bonnefon void SearchingNotifier::sendNotification( qint64 current_line, qint64 nb_lines )
42bb02e0acSNicolas Bonnefon {
43bb02e0acSNicolas Bonnefon     qint64 progress;
44bb02e0acSNicolas Bonnefon     if ( current_line < 0 )
45bb02e0acSNicolas Bonnefon         progress = ( nb_lines + current_line ) * 100 / nb_lines;
46bb02e0acSNicolas Bonnefon     else
47bb02e0acSNicolas Bonnefon         progress = current_line * 100 / nb_lines;
48bb02e0acSNicolas Bonnefon     emit notify( QFNotificationProgress( progress ) );
49bb02e0acSNicolas Bonnefon 
50bb02e0acSNicolas Bonnefon     QApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
51*e85b29ccSNicolas Bonnefon     startTime_ = QTime::currentTime();
52bb02e0acSNicolas Bonnefon }
53bb02e0acSNicolas Bonnefon 
set(int line,int column)54bb02e0acSNicolas Bonnefon void QuickFind::LastMatchPosition::set( int line, int column )
55bb02e0acSNicolas Bonnefon {
56bb02e0acSNicolas Bonnefon     if ( ( line_ == -1 ) ||
57bb02e0acSNicolas Bonnefon             ( ( line <= line_ ) && ( column < column_ ) ) )
58bb02e0acSNicolas Bonnefon     {
59bb02e0acSNicolas Bonnefon         line_ = line;
60bb02e0acSNicolas Bonnefon         column_ = column;
61bb02e0acSNicolas Bonnefon     }
62bb02e0acSNicolas Bonnefon }
63bb02e0acSNicolas Bonnefon 
set(const FilePosition & position)64bb02e0acSNicolas Bonnefon void QuickFind::LastMatchPosition::set( const FilePosition &position )
65bb02e0acSNicolas Bonnefon {
66bb02e0acSNicolas Bonnefon     set( position.line(), position.column() );
67bb02e0acSNicolas Bonnefon }
68bb02e0acSNicolas Bonnefon 
isLater(int line,int column) const69bb02e0acSNicolas Bonnefon bool QuickFind::LastMatchPosition::isLater( int line, int column ) const
70bb02e0acSNicolas Bonnefon {
71bb02e0acSNicolas Bonnefon     if ( line_ == -1 )
72bb02e0acSNicolas Bonnefon         return false;
73bb02e0acSNicolas Bonnefon     else if ( ( line == line_ ) && ( column >= column_ ) )
74bb02e0acSNicolas Bonnefon         return true;
75bb02e0acSNicolas Bonnefon     else if ( line > line_ )
76bb02e0acSNicolas Bonnefon         return true;
77bb02e0acSNicolas Bonnefon     else
78bb02e0acSNicolas Bonnefon         return false;
79bb02e0acSNicolas Bonnefon }
80bb02e0acSNicolas Bonnefon 
isLater(const FilePosition & position) const81bb02e0acSNicolas Bonnefon bool QuickFind::LastMatchPosition::isLater( const FilePosition &position ) const
82bb02e0acSNicolas Bonnefon {
83bb02e0acSNicolas Bonnefon     return isLater( position.line(), position.column() );
84bb02e0acSNicolas Bonnefon }
85bb02e0acSNicolas Bonnefon 
isSooner(int line,int column) const86bb02e0acSNicolas Bonnefon bool QuickFind::LastMatchPosition::isSooner( int line, int column ) const
87bb02e0acSNicolas Bonnefon {
88bb02e0acSNicolas Bonnefon     if ( line_ == -1 )
89bb02e0acSNicolas Bonnefon         return false;
90bb02e0acSNicolas Bonnefon     else if ( ( line == line_ ) && ( column <= column_ ) )
91bb02e0acSNicolas Bonnefon         return true;
92bb02e0acSNicolas Bonnefon     else if ( line < line_ )
93bb02e0acSNicolas Bonnefon         return true;
94bb02e0acSNicolas Bonnefon     else
95bb02e0acSNicolas Bonnefon         return false;
96bb02e0acSNicolas Bonnefon }
97bb02e0acSNicolas Bonnefon 
isSooner(const FilePosition & position) const98bb02e0acSNicolas Bonnefon bool QuickFind::LastMatchPosition::isSooner( const FilePosition &position ) const
99bb02e0acSNicolas Bonnefon {
100bb02e0acSNicolas Bonnefon     return isSooner( position.line(), position.column() );
101bb02e0acSNicolas Bonnefon }
102bb02e0acSNicolas Bonnefon 
QuickFind(const AbstractLogData * const logData,Selection * selection,const QuickFindPattern * const quickFindPattern)103bb02e0acSNicolas Bonnefon QuickFind::QuickFind( const AbstractLogData* const logData,
104bb02e0acSNicolas Bonnefon         Selection* selection,
105bb02e0acSNicolas Bonnefon         const QuickFindPattern* const quickFindPattern ) :
106bb02e0acSNicolas Bonnefon     logData_( logData ), selection_( selection ),
107bb02e0acSNicolas Bonnefon     quickFindPattern_( quickFindPattern ),
108bb02e0acSNicolas Bonnefon     lastMatch_(), firstMatch_(), searchingNotifier_(),
109bb02e0acSNicolas Bonnefon     incrementalSearchStatus_()
110bb02e0acSNicolas Bonnefon {
111bb02e0acSNicolas Bonnefon     connect( &searchingNotifier_, SIGNAL( notify( const QFNotification& ) ),
112bb02e0acSNicolas Bonnefon             this, SIGNAL( notify( const QFNotification& ) ) );
113bb02e0acSNicolas Bonnefon }
114bb02e0acSNicolas Bonnefon 
incrementalSearchStop()115bb02e0acSNicolas Bonnefon void QuickFind::incrementalSearchStop()
116bb02e0acSNicolas Bonnefon {
117bb02e0acSNicolas Bonnefon     if ( incrementalSearchStatus_.isOngoing() ) {
118bb02e0acSNicolas Bonnefon         if ( selection_->isEmpty() ) {
119bb02e0acSNicolas Bonnefon             // Nothing found?
120bb02e0acSNicolas Bonnefon             // We reset the selection to what it was
121bb02e0acSNicolas Bonnefon             *selection_ = incrementalSearchStatus_.initialSelection();
122bb02e0acSNicolas Bonnefon         }
123bb02e0acSNicolas Bonnefon 
124bb02e0acSNicolas Bonnefon         incrementalSearchStatus_ = IncrementalSearchStatus();
125bb02e0acSNicolas Bonnefon     }
126bb02e0acSNicolas Bonnefon }
127bb02e0acSNicolas Bonnefon 
incrementalSearchAbort()128bb02e0acSNicolas Bonnefon void QuickFind::incrementalSearchAbort()
129bb02e0acSNicolas Bonnefon {
130bb02e0acSNicolas Bonnefon     if ( incrementalSearchStatus_.isOngoing() ) {
131bb02e0acSNicolas Bonnefon         // We reset the selection to what it was
132bb02e0acSNicolas Bonnefon         *selection_ = incrementalSearchStatus_.initialSelection();
133bb02e0acSNicolas Bonnefon         incrementalSearchStatus_ = IncrementalSearchStatus();
134bb02e0acSNicolas Bonnefon     }
135bb02e0acSNicolas Bonnefon }
136bb02e0acSNicolas Bonnefon 
incrementallySearchForward()137bb02e0acSNicolas Bonnefon qint64 QuickFind::incrementallySearchForward()
138bb02e0acSNicolas Bonnefon {
139bb02e0acSNicolas Bonnefon     LOG( logDEBUG ) << "QuickFind::incrementallySearchForward";
140bb02e0acSNicolas Bonnefon 
141bb02e0acSNicolas Bonnefon     // Position where we start the search from
142bb02e0acSNicolas Bonnefon     FilePosition start_position = selection_->getNextPosition();
143bb02e0acSNicolas Bonnefon 
144bb02e0acSNicolas Bonnefon     if ( incrementalSearchStatus_.direction() == Forward ) {
145bb02e0acSNicolas Bonnefon         // An incremental search is active, we restart the search
146bb02e0acSNicolas Bonnefon         // from the initial point
147bb02e0acSNicolas Bonnefon         LOG( logDEBUG ) << "Restart search from initial point";
148bb02e0acSNicolas Bonnefon         start_position = incrementalSearchStatus_.position();
149bb02e0acSNicolas Bonnefon     }
150bb02e0acSNicolas Bonnefon     else {
151bb02e0acSNicolas Bonnefon         // It's a new search so we search from the selection
152bb02e0acSNicolas Bonnefon         incrementalSearchStatus_ = IncrementalSearchStatus(
153bb02e0acSNicolas Bonnefon                 Forward,
154bb02e0acSNicolas Bonnefon                 start_position,
155bb02e0acSNicolas Bonnefon                 *selection_ );
156bb02e0acSNicolas Bonnefon     }
157bb02e0acSNicolas Bonnefon 
158bb02e0acSNicolas Bonnefon     qint64 line_found = doSearchForward( start_position );
159bb02e0acSNicolas Bonnefon 
160bb02e0acSNicolas Bonnefon     if ( line_found >= 0 ) {
161bb02e0acSNicolas Bonnefon         // We have found a result...
162bb02e0acSNicolas Bonnefon         // ... the caller will jump to this line.
163bb02e0acSNicolas Bonnefon         return line_found;
164bb02e0acSNicolas Bonnefon     }
165bb02e0acSNicolas Bonnefon     else {
166bb02e0acSNicolas Bonnefon         // No result...
167bb02e0acSNicolas Bonnefon         // ... we want the client to show the initial line.
168bb02e0acSNicolas Bonnefon         selection_->clear();
169bb02e0acSNicolas Bonnefon         return incrementalSearchStatus_.position().line();
170bb02e0acSNicolas Bonnefon     }
171bb02e0acSNicolas Bonnefon }
172bb02e0acSNicolas Bonnefon 
incrementallySearchBackward()173bb02e0acSNicolas Bonnefon qint64 QuickFind::incrementallySearchBackward()
174bb02e0acSNicolas Bonnefon {
175bb02e0acSNicolas Bonnefon     LOG( logDEBUG ) << "QuickFind::incrementallySearchBackward";
176bb02e0acSNicolas Bonnefon 
177bb02e0acSNicolas Bonnefon     // Position where we start the search from
178bb02e0acSNicolas Bonnefon     FilePosition start_position = selection_->getPreviousPosition();
179bb02e0acSNicolas Bonnefon 
180bb02e0acSNicolas Bonnefon     if ( incrementalSearchStatus_.direction() == Backward ) {
181bb02e0acSNicolas Bonnefon         // An incremental search is active, we restart the search
182bb02e0acSNicolas Bonnefon         // from the initial point
183bb02e0acSNicolas Bonnefon         LOG( logDEBUG ) << "Restart search from initial point";
184bb02e0acSNicolas Bonnefon         start_position = incrementalSearchStatus_.position();
185bb02e0acSNicolas Bonnefon     }
186bb02e0acSNicolas Bonnefon     else {
187bb02e0acSNicolas Bonnefon         // It's a new search so we search from the selection
188bb02e0acSNicolas Bonnefon         incrementalSearchStatus_ = IncrementalSearchStatus(
189bb02e0acSNicolas Bonnefon                 Backward,
190bb02e0acSNicolas Bonnefon                 start_position,
191bb02e0acSNicolas Bonnefon                 *selection_ );
192bb02e0acSNicolas Bonnefon     }
193bb02e0acSNicolas Bonnefon 
194bb02e0acSNicolas Bonnefon     qint64 line_found = doSearchBackward( start_position );
195bb02e0acSNicolas Bonnefon 
196bb02e0acSNicolas Bonnefon     if ( line_found >= 0 ) {
197bb02e0acSNicolas Bonnefon         // We have found a result...
198bb02e0acSNicolas Bonnefon         // ... the caller will jump to this line.
199bb02e0acSNicolas Bonnefon         return line_found;
200bb02e0acSNicolas Bonnefon     }
201bb02e0acSNicolas Bonnefon     else {
202bb02e0acSNicolas Bonnefon         // No result...
203bb02e0acSNicolas Bonnefon         // ... we want the client to show the initial line.
204bb02e0acSNicolas Bonnefon         selection_->clear();
205bb02e0acSNicolas Bonnefon         return incrementalSearchStatus_.position().line();
206bb02e0acSNicolas Bonnefon     }
207bb02e0acSNicolas Bonnefon }
208bb02e0acSNicolas Bonnefon 
searchForward()209bb02e0acSNicolas Bonnefon qint64 QuickFind::searchForward()
210bb02e0acSNicolas Bonnefon {
211bb02e0acSNicolas Bonnefon     incrementalSearchStatus_ = IncrementalSearchStatus();
212bb02e0acSNicolas Bonnefon 
213bb02e0acSNicolas Bonnefon     // Position where we start the search from
214bb02e0acSNicolas Bonnefon     FilePosition start_position = selection_->getNextPosition();
215bb02e0acSNicolas Bonnefon 
216bb02e0acSNicolas Bonnefon     return doSearchForward( start_position );
217bb02e0acSNicolas Bonnefon }
218bb02e0acSNicolas Bonnefon 
219bb02e0acSNicolas Bonnefon 
searchBackward()220bb02e0acSNicolas Bonnefon qint64 QuickFind::searchBackward()
221bb02e0acSNicolas Bonnefon {
222bb02e0acSNicolas Bonnefon     incrementalSearchStatus_ = IncrementalSearchStatus();
223bb02e0acSNicolas Bonnefon 
224bb02e0acSNicolas Bonnefon     // Position where we start the search from
225bb02e0acSNicolas Bonnefon     FilePosition start_position = selection_->getPreviousPosition();
226bb02e0acSNicolas Bonnefon 
227bb02e0acSNicolas Bonnefon     return doSearchBackward( start_position );
228bb02e0acSNicolas Bonnefon }
229bb02e0acSNicolas Bonnefon 
230bb02e0acSNicolas Bonnefon // Internal implementation of forward search,
231bb02e0acSNicolas Bonnefon // returns the line where the pattern is found or -1 if not found.
232bb02e0acSNicolas Bonnefon // Parameters are the position the search shall start
doSearchForward(const FilePosition & start_position)233bb02e0acSNicolas Bonnefon qint64 QuickFind::doSearchForward( const FilePosition &start_position )
234bb02e0acSNicolas Bonnefon {
235bb02e0acSNicolas Bonnefon     bool found = false;
236bb02e0acSNicolas Bonnefon     int found_start_col;
237bb02e0acSNicolas Bonnefon     int found_end_col;
238bb02e0acSNicolas Bonnefon 
239*e85b29ccSNicolas Bonnefon     if ( searchState_ == SearchState::OnGoing ) {
240*e85b29ccSNicolas Bonnefon         // This happens if this function is re-entered via the notifier
241*e85b29ccSNicolas Bonnefon         // We want the top most call to restart the search
242*e85b29ccSNicolas Bonnefon         searchState_ = SearchState::RestartNeeded;
243*e85b29ccSNicolas Bonnefon         return -1;
244*e85b29ccSNicolas Bonnefon     }
245*e85b29ccSNicolas Bonnefon 
246bb02e0acSNicolas Bonnefon     if ( ! quickFindPattern_->isActive() )
247bb02e0acSNicolas Bonnefon         return -1;
248bb02e0acSNicolas Bonnefon 
249bb02e0acSNicolas Bonnefon     // Optimisation: if we are already after the last match,
250bb02e0acSNicolas Bonnefon     // we don't do any search at all.
251bb02e0acSNicolas Bonnefon     if ( lastMatch_.isLater( start_position ) ) {
252bb02e0acSNicolas Bonnefon         // Send a notification
253bb02e0acSNicolas Bonnefon         emit notify( QFNotificationReachedEndOfFile() );
254bb02e0acSNicolas Bonnefon 
255bb02e0acSNicolas Bonnefon         return -1;
256bb02e0acSNicolas Bonnefon     }
257bb02e0acSNicolas Bonnefon 
258bb02e0acSNicolas Bonnefon     qint64 line = start_position.line();
259bb02e0acSNicolas Bonnefon     LOG( logDEBUG ) << "Start searching at line " << line;
260bb02e0acSNicolas Bonnefon     // We look at the rest of the first line
261bb02e0acSNicolas Bonnefon     if ( quickFindPattern_->isLineMatching(
262bb02e0acSNicolas Bonnefon                 logData_->getExpandedLineString( line ),
263bb02e0acSNicolas Bonnefon                 start_position.column() ) ) {
264bb02e0acSNicolas Bonnefon         quickFindPattern_->getLastMatch( &found_start_col, &found_end_col );
265bb02e0acSNicolas Bonnefon         found = true;
266bb02e0acSNicolas Bonnefon     }
267bb02e0acSNicolas Bonnefon     else {
268bb02e0acSNicolas Bonnefon         searchingNotifier_.reset();
269*e85b29ccSNicolas Bonnefon         searchState_ = SearchState::OnGoing;
270bb02e0acSNicolas Bonnefon         // And then the rest of the file
271bb02e0acSNicolas Bonnefon         qint64 nb_lines = logData_->getNbLine();
272*e85b29ccSNicolas Bonnefon         int start_line = ++line;
273bb02e0acSNicolas Bonnefon         while ( line < nb_lines ) {
274*e85b29ccSNicolas Bonnefon             // Check if someone has changed the search within this loop
275*e85b29ccSNicolas Bonnefon             if ( searchState_ == SearchState::RestartNeeded ) {
276*e85b29ccSNicolas Bonnefon                 line = start_line;
277*e85b29ccSNicolas Bonnefon                 searchState_ = SearchState::OnGoing;
278*e85b29ccSNicolas Bonnefon                 LOG( logDEBUG ) << "QuickFind restarted at line " << line;
279*e85b29ccSNicolas Bonnefon             }
280*e85b29ccSNicolas Bonnefon 
281bb02e0acSNicolas Bonnefon             if ( quickFindPattern_->isLineMatching(
282bb02e0acSNicolas Bonnefon                         logData_->getExpandedLineString( line ) ) ) {
283bb02e0acSNicolas Bonnefon                 quickFindPattern_->getLastMatch(
284bb02e0acSNicolas Bonnefon                         &found_start_col, &found_end_col );
285bb02e0acSNicolas Bonnefon                 found = true;
286*e85b29ccSNicolas Bonnefon                 LOG( logDEBUG ) << "QuickFind found!";
287bb02e0acSNicolas Bonnefon                 break;
288bb02e0acSNicolas Bonnefon             }
289bb02e0acSNicolas Bonnefon             line++;
290bb02e0acSNicolas Bonnefon 
291bb02e0acSNicolas Bonnefon             // See if we need to notify of the ongoing search
292*e85b29ccSNicolas Bonnefon             // Note this could re-enter this function if the pattern is
293*e85b29ccSNicolas Bonnefon             // modified whilst the search is on-going, this is okay.
294bb02e0acSNicolas Bonnefon             searchingNotifier_.ping( line, nb_lines );
295bb02e0acSNicolas Bonnefon         }
296*e85b29ccSNicolas Bonnefon 
297*e85b29ccSNicolas Bonnefon         searchState_ = SearchState::Idle;
298bb02e0acSNicolas Bonnefon     }
299bb02e0acSNicolas Bonnefon 
300bb02e0acSNicolas Bonnefon     if ( found ) {
301bb02e0acSNicolas Bonnefon         selection_->selectPortion(
302bb02e0acSNicolas Bonnefon                 line, found_start_col, found_end_col );
303bb02e0acSNicolas Bonnefon 
304bb02e0acSNicolas Bonnefon         // Clear any notification
305bb02e0acSNicolas Bonnefon         emit clearNotification();
306bb02e0acSNicolas Bonnefon 
307bb02e0acSNicolas Bonnefon         return line;
308bb02e0acSNicolas Bonnefon     }
309bb02e0acSNicolas Bonnefon     else {
310bb02e0acSNicolas Bonnefon         // Update the position of the last match
311bb02e0acSNicolas Bonnefon         FilePosition last_match_position = selection_->getPreviousPosition();
312bb02e0acSNicolas Bonnefon         lastMatch_.set( last_match_position );
313bb02e0acSNicolas Bonnefon 
314bb02e0acSNicolas Bonnefon         // Send a notification
315bb02e0acSNicolas Bonnefon         emit notify( QFNotificationReachedEndOfFile() );
316bb02e0acSNicolas Bonnefon 
317bb02e0acSNicolas Bonnefon         return -1;
318bb02e0acSNicolas Bonnefon     }
319bb02e0acSNicolas Bonnefon }
320bb02e0acSNicolas Bonnefon 
321bb02e0acSNicolas Bonnefon // Internal implementation of backward search,
322bb02e0acSNicolas Bonnefon // returns the line where the pattern is found or -1 if not found.
323bb02e0acSNicolas Bonnefon // Parameters are the position the search shall start
doSearchBackward(const FilePosition & start_position)324bb02e0acSNicolas Bonnefon qint64 QuickFind::doSearchBackward( const FilePosition &start_position )
325bb02e0acSNicolas Bonnefon {
326bb02e0acSNicolas Bonnefon     bool found = false;
327bb02e0acSNicolas Bonnefon     int start_col;
328bb02e0acSNicolas Bonnefon     int end_col;
329bb02e0acSNicolas Bonnefon 
330bb02e0acSNicolas Bonnefon     if ( ! quickFindPattern_->isActive() )
331bb02e0acSNicolas Bonnefon         return -1;
332bb02e0acSNicolas Bonnefon 
333bb02e0acSNicolas Bonnefon     // Optimisation: if we are already before the first match,
334bb02e0acSNicolas Bonnefon     // we don't do any search at all.
335bb02e0acSNicolas Bonnefon     if ( firstMatch_.isSooner( start_position ) ) {
336bb02e0acSNicolas Bonnefon         // Send a notification
337bb02e0acSNicolas Bonnefon         emit notify( QFNotificationReachedBegininningOfFile() );
338bb02e0acSNicolas Bonnefon 
339bb02e0acSNicolas Bonnefon         return -1;
340bb02e0acSNicolas Bonnefon     }
341bb02e0acSNicolas Bonnefon 
342bb02e0acSNicolas Bonnefon     qint64 line = start_position.line();
343bb02e0acSNicolas Bonnefon     LOG( logDEBUG ) << "Start searching at line " << line;
344bb02e0acSNicolas Bonnefon     // We look at the beginning of the first line
345bb02e0acSNicolas Bonnefon     if (    ( start_position.column() > 0 )
346bb02e0acSNicolas Bonnefon          && ( quickFindPattern_->isLineMatchingBackward(
347bb02e0acSNicolas Bonnefon                  logData_->getExpandedLineString( line ),
348bb02e0acSNicolas Bonnefon                  start_position.column() ) )
349bb02e0acSNicolas Bonnefon        ) {
350bb02e0acSNicolas Bonnefon         quickFindPattern_->getLastMatch( &start_col, &end_col );
351bb02e0acSNicolas Bonnefon         found = true;
352bb02e0acSNicolas Bonnefon     }
353bb02e0acSNicolas Bonnefon     else {
354bb02e0acSNicolas Bonnefon         searchingNotifier_.reset();
355bb02e0acSNicolas Bonnefon         // And then the rest of the file
356bb02e0acSNicolas Bonnefon         qint64 nb_lines = logData_->getNbLine();
357bb02e0acSNicolas Bonnefon         line--;
358bb02e0acSNicolas Bonnefon         while ( line >= 0 ) {
359bb02e0acSNicolas Bonnefon             if ( quickFindPattern_->isLineMatchingBackward(
360bb02e0acSNicolas Bonnefon                         logData_->getExpandedLineString( line ) ) ) {
361bb02e0acSNicolas Bonnefon                 quickFindPattern_->getLastMatch( &start_col, &end_col );
362bb02e0acSNicolas Bonnefon                 found = true;
363bb02e0acSNicolas Bonnefon                 break;
364bb02e0acSNicolas Bonnefon             }
365bb02e0acSNicolas Bonnefon             line--;
366bb02e0acSNicolas Bonnefon 
367bb02e0acSNicolas Bonnefon             // See if we need to notify of the ongoing search
368bb02e0acSNicolas Bonnefon             searchingNotifier_.ping( -line, nb_lines );
369bb02e0acSNicolas Bonnefon         }
370bb02e0acSNicolas Bonnefon     }
371bb02e0acSNicolas Bonnefon 
372bb02e0acSNicolas Bonnefon     if ( found )
373bb02e0acSNicolas Bonnefon     {
374bb02e0acSNicolas Bonnefon         selection_->selectPortion( line, start_col, end_col );
375bb02e0acSNicolas Bonnefon 
376bb02e0acSNicolas Bonnefon         // Clear any notification
377bb02e0acSNicolas Bonnefon         emit clearNotification();
378bb02e0acSNicolas Bonnefon 
379bb02e0acSNicolas Bonnefon         return line;
380bb02e0acSNicolas Bonnefon     }
381bb02e0acSNicolas Bonnefon     else {
382bb02e0acSNicolas Bonnefon         // Update the position of the first match
383bb02e0acSNicolas Bonnefon         FilePosition first_match_position = selection_->getNextPosition();
384bb02e0acSNicolas Bonnefon         firstMatch_.set( first_match_position );
385bb02e0acSNicolas Bonnefon 
386bb02e0acSNicolas Bonnefon         // Send a notification
387b423cd88SNicolas Bonnefon         LOG( logDEBUG ) << "QF: Send BOF notification.";
388bb02e0acSNicolas Bonnefon         emit notify( QFNotificationReachedBegininningOfFile() );
389bb02e0acSNicolas Bonnefon 
390bb02e0acSNicolas Bonnefon         return -1;
391bb02e0acSNicolas Bonnefon     }
392bb02e0acSNicolas Bonnefon }
393bb02e0acSNicolas Bonnefon 
resetLimits()394bb02e0acSNicolas Bonnefon void QuickFind::resetLimits()
395bb02e0acSNicolas Bonnefon {
396bb02e0acSNicolas Bonnefon     lastMatch_.reset();
397bb02e0acSNicolas Bonnefon     firstMatch_.reset();
398bb02e0acSNicolas Bonnefon }
399