1 /*
2  * Copyright (C) 2013, 2014 Nicolas Bonnefon and other contributors
3  *
4  * This file is part of glogg.
5  *
6  * glogg is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * glogg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with glogg.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "log.h"
21 
22 #include "persistentinfo.h"
23 #include "configuration.h"
24 #include "quickfindmux.h"
25 
26 #include "qfnotifications.h"
27 
QuickFindMux(std::shared_ptr<QuickFindPattern> pattern)28 QuickFindMux::QuickFindMux( std::shared_ptr<QuickFindPattern> pattern ) :
29     QObject(), pattern_( pattern ), registeredSearchables_()
30 {
31     selector_ = nullptr;
32 
33     // Forward the pattern's signal to our listeners
34     connect( pattern_.get(), SIGNAL( patternUpdated() ),
35              this, SLOT( notifyPatternChanged() ) );
36 }
37 
38 //
39 // Public member functions
40 //
registerSelector(const QuickFindMuxSelectorInterface * selector)41 void QuickFindMux::registerSelector(
42         const QuickFindMuxSelectorInterface* selector )
43 {
44     LOG(logDEBUG) << "QuickFindMux::registerSelector";
45 
46     // The selector object we will use when forwarding search requests
47     selector_ = selector;
48 
49     unregisterAllSearchables();
50 
51     if ( selector ) {
52         for ( auto i: selector_->getAllSearchables() )
53             registerSearchable( i );
54     }
55     else {
56         // null selector, all is well, we don't do anything.
57     }
58 }
59 
setDirection(QFDirection direction)60 void QuickFindMux::setDirection( QFDirection direction )
61 {
62     LOG(logDEBUG) << "QuickFindMux::setDirection: new direction: " << direction;
63     currentDirection_ = direction;
64 }
65 
66 //
67 // Public slots
68 //
searchNext()69 void QuickFindMux::searchNext()
70 {
71     LOG(logDEBUG) << "QuickFindMux::searchNext";
72     if ( currentDirection_ == Forward )
73         searchForward();
74     else
75         searchBackward();
76 }
77 
searchPrevious()78 void QuickFindMux::searchPrevious()
79 {
80     LOG(logDEBUG) << "QuickFindMux::searchPrevious";
81     if ( currentDirection_ == Forward )
82         searchBackward();
83     else
84         searchForward();
85 }
86 
searchForward()87 void QuickFindMux::searchForward()
88 {
89     LOG(logDEBUG) << "QuickFindMux::searchForward";
90 
91     if ( auto searchable = getSearchableWidget() )
92         searchable->searchForward();
93 }
94 
searchBackward()95 void QuickFindMux::searchBackward()
96 {
97     LOG(logDEBUG) << "QuickFindMux::searchBackward";
98 
99     if ( auto searchable = getSearchableWidget() )
100         searchable->searchBackward();
101 }
102 
setNewPattern(const QString & new_pattern,bool ignore_case)103 void QuickFindMux::setNewPattern(
104         const QString& new_pattern, bool ignore_case )
105 {
106     static std::shared_ptr<Configuration> config =
107         Persistent<Configuration>( "settings" );
108 
109     LOG(logDEBUG) << "QuickFindMux::setNewPattern";
110 
111     // If we must do an incremental search, we do it now
112     if ( config->isQuickfindIncremental() ) {
113         pattern_->changeSearchPattern( new_pattern, ignore_case );
114         if ( auto searchable = getSearchableWidget() ) {
115             if ( currentDirection_ == Forward )
116                 searchable->incrementallySearchForward();
117             else
118                 searchable->incrementallySearchBackward();
119         }
120     }
121 }
122 
confirmPattern(const QString & new_pattern,bool ignore_case)123 void QuickFindMux::confirmPattern(
124         const QString& new_pattern, bool ignore_case )
125 {
126     static std::shared_ptr<Configuration> config =
127         Persistent<Configuration>( "settings" );
128 
129     pattern_->changeSearchPattern( new_pattern, ignore_case );
130 
131     // if non-incremental, we perform the search now
132     if ( ! config->isQuickfindIncremental() ) {
133         searchNext();
134     }
135     else {
136         if ( auto searchable = getSearchableWidget() )
137             searchable->incrementalSearchStop();
138     }
139 }
140 
cancelSearch()141 void QuickFindMux::cancelSearch()
142 {
143     static std::shared_ptr<Configuration> config =
144         Persistent<Configuration>( "settings" );
145 
146     if ( config->isQuickfindIncremental() ) {
147         if ( auto searchable = getSearchableWidget() )
148             searchable->incrementalSearchAbort();
149     }
150 }
151 
152 //
153 // Private slots
154 //
changeQuickFind(const QString & new_pattern,QFDirection new_direction)155 void QuickFindMux::changeQuickFind(
156         const QString& new_pattern, QFDirection new_direction )
157 {
158     pattern_->changeSearchPattern( new_pattern );
159     setDirection( new_direction );
160 }
161 
notifyPatternChanged()162 void QuickFindMux::notifyPatternChanged()
163 {
164     emit patternChanged( pattern_->getPattern() );
165 }
166 
167 //
168 // Private member functions
169 //
170 
171 // Use the registered 'selector' to determine where to send the search requests.
getSearchableWidget() const172 SearchableWidgetInterface* QuickFindMux::getSearchableWidget() const
173 {
174     LOG(logDEBUG) << "QuickFindMux::getSearchableWidget";
175 
176     SearchableWidgetInterface* searchable = nullptr;
177 
178     if ( selector_ )
179         searchable = selector_->getActiveSearchable();
180     else
181         LOG(logWARNING) << "QuickFindMux::getActiveSearchable() no registered selector";
182 
183     return searchable;
184 }
185 
registerSearchable(QObject * searchable)186 void QuickFindMux::registerSearchable( QObject* searchable )
187 {
188     LOG(logDEBUG) << "QuickFindMux::registerSearchable";
189 
190     // The searchable can change our qf pattern
191     connect( searchable,
192              SIGNAL( changeQuickFind( const QString&, QuickFindMux::QFDirection ) ),
193              this, SLOT( changeQuickFind( const QString&, QuickFindMux::QFDirection ) ) );
194     // Send us notifications
195     connect( searchable, SIGNAL( notifyQuickFind( const QFNotification& ) ),
196              this, SIGNAL( notify( const QFNotification& ) ) );
197 
198     // And clear them
199     connect( searchable, SIGNAL( clearQuickFindNotification() ),
200              this, SIGNAL( clearNotification() ) );
201     // Search can be initiated by the view itself
202     connect( searchable, SIGNAL( searchNext() ),
203              this, SLOT( searchNext() ) );
204     connect( searchable, SIGNAL( searchPrevious() ),
205              this, SLOT( searchPrevious() ) );
206 
207     registeredSearchables_.push_back( searchable );
208 }
209 
unregisterAllSearchables()210 void QuickFindMux::unregisterAllSearchables()
211 {
212     for ( auto searchable: registeredSearchables_ )
213         disconnect( searchable, 0, this, 0 );
214 
215     registeredSearchables_.clear();
216 }
217