]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/pkg/YQPkgSearchFilterView.cc
0bb5b126ad444dc103a317bb88d6d171cbba8871
[duncan/yast2-qt4.git] / src / pkg / YQPkgSearchFilterView.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQPkgSearchFilterView.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17   Textdomain "packages-qt"
18
19 /-*/
20
21 #include <qcheckbox.h>
22 #include <qcombobox.h>
23 #include <qlabel.h>
24 #include <qlayout.h>
25 #include <qpushbutton.h>
26 #include <qradiobutton.h>
27 #include <q3vgroupbox.h>
28 #include <q3progressdialog.h>
29 #include <qdatetime.h>
30 //Added by qt3to4:
31 #include <qevent.h>
32
33 #define y2log_component "qt-pkg"
34 #include <ycp/y2log.h>
35
36 #include "YQPkgSearchFilterView.h"
37 #include "QY2LayoutUtils.h"
38 #include "YQi18n.h"
39 #include "utf8.h"
40 #include "YQApplication.h"
41 #include "YQUI.h"
42
43 using std::list;
44 using std::string;
45
46
47 #define SPACING                 6       // between subwidgets
48 #define MARGIN                  4       // around the widget
49
50
51 YQPkgSearchFilterView::YQPkgSearchFilterView( QWidget * parent )
52     : Q3VBox( parent )
53 {
54     _matchCount = 0;
55     setMargin( MARGIN );
56     setSpacing( SPACING );
57
58     addVStretch( this );
59
60     // Headline
61     QLabel * label = new QLabel( _( "Searc&h:" ), this );
62     Q_CHECK_PTR( label );
63     label->setFont( YQUI::yqApp()->headingFont() );
64
65     // Input field ( combo box ) for search text
66     _searchText = new QComboBox( this );
67     Q_CHECK_PTR( _searchText );
68     _searchText->setEditable( true );
69     label->setBuddy( _searchText );
70
71
72     // Box for search button
73     Q3HBox * hbox = new Q3HBox( this );
74     Q_CHECK_PTR( hbox );
75
76     addHStretch( hbox );
77
78     // Search button
79     _searchButton = new QPushButton( _( "&Search" ), hbox );
80     Q_CHECK_PTR( _searchButton );
81
82     connect( _searchButton, SIGNAL( clicked() ),
83              this,          SLOT  ( filter()  ) );
84
85     addVStretch( this );
86
87     //
88     // Where to search
89     //
90
91     Q3VGroupBox * gbox = new Q3VGroupBox( _( "Search in" ), this );
92     Q_CHECK_PTR( gbox );
93
94
95     _searchInName        = new QCheckBox( _( "&Name"            ), gbox ); Q_CHECK_PTR( _searchInName        );
96     _searchInSummary     = new QCheckBox( _( "Su&mmary"         ), gbox ); Q_CHECK_PTR( _searchInSummary     );
97     _searchInDescription = new QCheckBox( _( "Descr&iption"     ), gbox ); Q_CHECK_PTR( _searchInDescription );
98
99     addVStretch( gbox );
100
101     // Intentionally NOT marking RPM tags for translation
102     _searchInProvides    = new QCheckBox(  "RPM \"&Provides\""   , gbox ); Q_CHECK_PTR( _searchInProvides    );
103     _searchInRequires    = new QCheckBox(  "RPM \"Re&quires\""   , gbox ); Q_CHECK_PTR( _searchInRequires    );
104
105     _searchInName->setChecked( true );
106     _searchInSummary->setChecked( true );
107
108     addVStretch( this );
109
110
111     //
112     // Search mode
113     //
114
115     label = new QLabel( _( "Search &Mode:" ), this );
116     Q_CHECK_PTR( label );
117
118     _searchMode = new QComboBox( this );
119     Q_CHECK_PTR( _searchMode );
120     _searchMode->setEditable( false );
121
122     label->setBuddy( _searchMode );
123
124     // Caution: combo box items must be inserted in the same order as enum SearchMode!
125     _searchMode->insertItem( _( "Contains"               ) );
126     _searchMode->insertItem( _( "Begins with"            ) );
127     _searchMode->insertItem( _( "Exact Match"            ) );
128     _searchMode->insertItem( _( "Use Wild Cards"         ) );
129     _searchMode->insertItem( _( "Use Regular Expression" ) );
130
131     _searchMode->setCurrentItem( Contains );
132
133
134     addVStretch( this );
135
136     _caseSensitive = new QCheckBox( _( "Case Sensiti&ve" ), this );
137     Q_CHECK_PTR( _caseSensitive );
138
139     for ( int i=0; i < 6; i++ )
140         addVStretch( this );
141 }
142
143
144 YQPkgSearchFilterView::~YQPkgSearchFilterView()
145 {
146     // NOP
147 }
148
149
150 void
151 YQPkgSearchFilterView::keyPressEvent( QKeyEvent * event )
152 {
153     if ( event )
154     {
155         if ( event->state() == 0 )      // No Ctrl / Alt / Shift etc. pressed
156         {
157             if ( event->key() == Qt::Key_Return ||
158                  event->key() == Qt::Key_Enter    )
159             {
160                 _searchButton->animateClick();
161                 return;
162             }
163         }
164
165     }
166
167     Q3VBox::keyPressEvent( event );
168 }
169
170
171 void
172 YQPkgSearchFilterView::setFocus()
173 {
174     _searchText->setFocus();
175 }
176
177
178 QSize
179 YQPkgSearchFilterView::minimumSizeHint() const
180 {
181     return QSize( 0, 0 );
182 }
183
184
185 void
186 YQPkgSearchFilterView::filterIfVisible()
187 {
188     if ( isVisible() )
189         filter();
190 }
191
192
193 void
194 YQPkgSearchFilterView::filter()
195 {
196     emit filterStart();
197     _matchCount = 0;
198
199     if ( ! _searchText->currentText().isEmpty() )
200     {
201         // Create a progress dialog that is only displayed if the search takes
202         // longer than a couple of seconds ( default: 4 ).
203
204         Q3ProgressDialog progress( _( "Searching..." ),                 // text
205                                   _( "&Cancel" ),                       // cancelButtonLabel
206 #ifdef FIXME
207                                   Y2PM::packageManager().size(),        // totalSteps
208 #else
209                                   1000,
210 #endif
211                                   this, 0,                              // parent, name
212                                   true );                               // modal
213         progress.setCaption( "" );
214         progress.setMinimumDuration( 2000 ); // millisec
215         QTime timer;
216
217         QRegExp regexp( _searchText->currentText() );
218         regexp.setCaseSensitive( _caseSensitive->isChecked() );
219         regexp.setWildcard( _searchMode->currentItem() == UseWildcards );
220
221         timer.start();
222
223
224         int count = 0;
225
226         for ( ZyppPoolIterator it = zyppPkgBegin();
227               it != zyppPkgEnd() && ! progress.wasCancelled();
228               ++it )
229         {
230             ZyppSel selectable = *it;
231
232             bool match =
233                 check( selectable, selectable->candidateObj(), regexp ) ||
234                 check( selectable, selectable->installedObj(), regexp );
235
236             // If there is neither an installed nor a candidate package, check
237             // any other instance.
238
239             if ( ! match                      &&
240                  ! selectable->candidateObj() &&
241                  ! selectable->installedObj()   )
242                 check( selectable, selectable->theObj(), regexp );
243
244
245             progress.setProgress( count++ );
246
247             if ( timer.elapsed() > 300 ) // milisec
248             {
249                 // Process events only every 300 milliseconds - this is very
250                 // expensive since both the progress dialog and the package
251                 // list change all the time, thus display updates are necessary
252                 // each time.
253
254                 qApp->processEvents();
255                 timer.restart();
256             }
257         }
258
259         if ( _matchCount == 0 )
260             emit message( _( "No Results." ) );
261     }
262
263     emit filterFinished();
264 }
265
266
267 bool
268 YQPkgSearchFilterView::check( ZyppSel   selectable,
269                               ZyppObj   zyppObj )
270 {
271     QRegExp regexp( _searchText->currentText() );
272     regexp.setCaseSensitive( _caseSensitive->isChecked() );
273     regexp.setWildcard( _searchMode->currentItem() == UseWildcards );
274
275     return check( selectable, zyppObj, regexp );
276 }
277
278
279 bool
280 YQPkgSearchFilterView::check( ZyppSel           selectable,
281                               ZyppObj           zyppObj,
282                               const QRegExp &   regexp )
283 {
284     if ( ! zyppObj )
285         return false;
286
287     bool match =
288         ( _searchInName->isChecked()        && check( zyppObj->name(),        regexp ) ) ||
289         ( _searchInSummary->isChecked()     && check( zyppObj->summary(),     regexp ) ) ||
290         ( _searchInDescription->isChecked() && check( zyppObj->description(), regexp ) ) ||
291         ( _searchInProvides->isChecked()    && check( zyppObj->dep( zypp::Dep::PROVIDES ), regexp ) ) ||
292         ( _searchInRequires->isChecked()    && check( zyppObj->dep( zypp::Dep::REQUIRES ), regexp ) );
293
294     if ( match )
295     {
296         ZyppPkg zyppPkg = tryCastToZyppPkg( zyppObj );
297
298         if ( zyppPkg )
299         {
300             _matchCount++;
301             emit filterMatch( selectable, zyppPkg );
302         }
303     }
304
305     return match;
306 }
307
308
309 bool
310 YQPkgSearchFilterView::check( const string &    attribute,
311                               const QRegExp &   regexp )
312 {
313     QString att         = fromUTF8( attribute );
314     QString searchText  = _searchText->currentText();
315     bool match          = false;
316
317     switch ( _searchMode->currentItem() )
318     {
319         case Contains:
320             match = att.contains( searchText, _caseSensitive->isChecked() );
321             break;
322
323         case BeginsWith:
324             match = att.startsWith( searchText );       // only case sensitive
325             break;
326
327         case ExactMatch:
328             match = ( att == searchText );
329             break;
330
331         case UseWildcards:
332         case UseRegExp:
333             // Both cases differ in how the regexp is set up during initialization
334             match = att.contains( regexp );
335             break;
336
337             // Intentionally omitting "default" branch - let gcc watch for unhandled enums
338     }
339
340     return match;
341 }
342
343
344 bool
345 YQPkgSearchFilterView::check( const zypp::CapSet & capSet, const QRegExp & regexp )
346 {
347     for ( zypp::CapSet::const_iterator it = capSet.begin();
348           it != capSet.end();
349           ++it )
350     {
351         if ( check( ( *it).index(), regexp ) )
352         {
353             // y2debug( "Match for %s", (*it).asString().c_str() );
354             return true;
355         }
356     }
357
358     return false;
359 }
360
361
362
363 #include "YQPkgSearchFilterView.moc"