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