1
/***************************************************************************
2
* Copyright (c) 2008 Nikolaj Hald Nielsen <nhnFreespirit@gmail.com> *
4
* This program is free software; you can redistribute it and/or modify *
5
* it under the terms of the GNU General Public License as published by *
6
* the Free Software Foundation; either version 2 of the License, or *
7
* (at your option) any later version. *
9
* This program is distributed in the hope that it will be useful, *
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12
* GNU General Public License for more details. *
14
* You should have received a copy of the GNU General Public License *
15
* along with this program; if not, write to the *
16
* Free Software Foundation, Inc., *
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18
***************************************************************************/
20
#include "ProgressiveSearchWidget.h"
23
#include "playlist/PlaylistModel.h"
26
#include <KColorScheme>
34
#include <QToolButton>
36
ProgressiveSearchWidget::ProgressiveSearchWidget( QWidget * parent )
43
KHBox *searchBox = new KHBox( this );
44
m_warningLabel = new QLabel( i18n("Warning: tracks have been hidden in the playlist"), this );
45
hideHiddenTracksWarning();
47
m_searchEdit = new Amarok::LineEdit( searchBox );
48
m_searchEdit->setClickMessage( i18n( "Search playlist" ) );
49
m_searchEdit->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
50
m_searchEdit->setClearButtonShown( true );
51
m_searchEdit->setFrame( true );
52
m_searchEdit->setToolTip( i18n( "Start typing to progressively search through the playlist" ) );
53
m_searchEdit->setFocusPolicy( Qt::ClickFocus ); // Without this, the widget goes into text input mode directly on startup
55
connect( m_searchEdit, SIGNAL( textChanged( const QString & ) ), this, SLOT( slotFilterChanged( const QString & ) ) );
56
connect( m_searchEdit, SIGNAL( returnPressed( const QString & ) ), this, SIGNAL( activateFilterResult() ) );
57
connect( m_searchEdit, SIGNAL( downPressed() ), this, SIGNAL( downPressed() ) );
59
QToolBar *toolbar = new QToolBar( searchBox );
61
m_nextAction = new KAction( KIcon( "go-down" ), i18n( "&Next" ), this );
62
connect( m_nextAction, SIGNAL( triggered() ), this, SLOT( slotNext() ) );
64
m_previousAction = new KAction( KIcon( "go-up" ), i18n( "&Previous" ), this );
65
connect( m_previousAction, SIGNAL( triggered() ), this, SLOT( slotPrevious() ) );
67
toolbar->addAction( m_nextAction );
68
toolbar->addAction( m_previousAction );
70
m_nextAction->setEnabled( false );
71
m_previousAction->setEnabled( false );
73
m_menu = new QMenu( this );
75
KAction * searchTracksAction = new KAction( i18n( "Tracks" ), this );
76
searchTracksAction->setCheckable( true );
77
connect( searchTracksAction, SIGNAL( toggled( bool ) ), this, SLOT( slotSearchTracks( bool ) ) );
78
if( m_searchFieldsMask & Playlist::MatchTrack )
79
searchTracksAction->setChecked( true );
80
m_menu->addAction( searchTracksAction );
82
KAction * searchAlbumsAction = new KAction( i18n( "Albums" ), this );
83
searchAlbumsAction->setCheckable( true );
84
connect( searchAlbumsAction, SIGNAL( toggled( bool ) ), this, SLOT( slotSearchAlbums( bool ) ) );
85
if( m_searchFieldsMask & Playlist::MatchAlbum )
86
searchAlbumsAction->setChecked( true );
87
m_menu->addAction( searchAlbumsAction );
89
KAction * searchArtistsAction = new KAction( i18n( "Artists" ), this );
90
searchArtistsAction->setCheckable( true );
91
connect( searchArtistsAction, SIGNAL( toggled( bool ) ), this, SLOT( slotSearchArtists( bool ) ) );
92
if( m_searchFieldsMask & Playlist::MatchArtist )
93
searchArtistsAction->setChecked( true );
94
m_menu->addAction( searchArtistsAction );
96
KAction * searchGenreAction = new KAction( i18n( "Genre" ), this );
97
searchGenreAction->setCheckable( true );
98
connect( searchGenreAction, SIGNAL( toggled( bool ) ), this, SLOT( slotSearchGenre( bool ) ) );
99
if( m_searchFieldsMask & Playlist::MatchGenre )
100
searchGenreAction->setChecked( true );
101
m_menu->addAction( searchGenreAction );
103
KAction * searchComposersAction = new KAction( i18n( "Composers" ), this );
104
searchComposersAction->setCheckable( true );
105
connect( searchComposersAction, SIGNAL( toggled( bool ) ), this, SLOT( slotSearchComposers( bool ) ) );
106
if( m_searchFieldsMask & Playlist::MatchComposer )
107
searchComposersAction->setChecked( true );
108
m_menu->addAction( searchComposersAction );
110
KAction * searchYearsAction = new KAction( i18n( "Years" ), this );
111
searchYearsAction->setCheckable( true );
112
connect( searchYearsAction, SIGNAL( toggled( bool ) ), this, SLOT( slotSearchYears( bool ) ) );
113
if( m_searchFieldsMask & Playlist::MatchYear)
114
searchYearsAction->setChecked( true );
115
m_menu->addAction( searchYearsAction );
117
m_menu->addSeparator();
119
KAction * showOnlyMatchesAction = new KAction( i18n( "Show only matches" ), this );
120
showOnlyMatchesAction->setCheckable( true );
121
connect( showOnlyMatchesAction, SIGNAL( toggled( bool ) ), this, SLOT( slotShowOnlyMatches( bool ) ) );
123
showOnlyMatchesAction->setChecked( m_showOnlyMatches );
124
m_menu->addAction( showOnlyMatchesAction );
126
m_nextAction->setVisible( !m_showOnlyMatches );
127
m_previousAction->setVisible( !m_showOnlyMatches );
129
KAction *searchMenuAction = new KAction( KIcon( "preferences-other" ), i18n( "Search Preferences" ), this );
130
searchMenuAction->setMenu( m_menu );
131
toolbar->addAction( searchMenuAction );
133
QToolButton *tbutton = qobject_cast<QToolButton*>(toolbar->widgetForAction( searchMenuAction ) );
135
tbutton->setPopupMode( QToolButton::InstantPopup );
137
toolbar->setFixedHeight( m_searchEdit->sizeHint().height() );
139
//make sure that this edit is cleared when the playlist is cleared:
140
connect( Amarok::actionCollection()->action( "playlist_clear" ), SIGNAL( triggered() ), this, SLOT( slotFilterClear() ) );
144
ProgressiveSearchWidget::~ProgressiveSearchWidget()
147
void ProgressiveSearchWidget::slotFilterChanged( const QString & filter )
151
//when the clear button is pressed, we get 2 calls to this slot... filter this out as it messes with
152
//resetting the view:
153
if ( filter == m_lastFilter )
156
debug() << "New filter: " << filter;
158
m_lastFilter = filter;
160
if( filter.isEmpty() )
162
m_nextAction->setEnabled( false );
163
m_previousAction->setEnabled( false );
165
QPalette p = m_searchEdit->palette();
166
p.setColor( QPalette::Base, palette().color( QPalette::Base ) );
167
m_searchEdit->setPalette( p );
169
if( m_showOnlyMatches )
170
hideHiddenTracksWarning();
172
emit( filterCleared() );
177
emit( filterChanged( filter, m_searchFieldsMask, m_showOnlyMatches ) );
180
void ProgressiveSearchWidget::slotNext()
183
emit( next( m_searchEdit->text(), m_searchFieldsMask ) );
186
void ProgressiveSearchWidget::slotPrevious()
189
emit( previous( m_searchEdit->text(), m_searchFieldsMask ) );
192
void ProgressiveSearchWidget::match()
194
m_nextAction->setEnabled( true );
195
m_previousAction->setEnabled( true );
197
QPalette p = m_searchEdit->palette();
198
p.setColor( QPalette::Base, palette().color( QPalette::Base ) );
199
m_searchEdit->setPalette( p );
201
if( m_showOnlyMatches )
202
hideHiddenTracksWarning();
205
void ProgressiveSearchWidget::noMatch()
207
m_nextAction->setEnabled( false );
208
m_previousAction->setEnabled( false );
210
const KStatefulBrush backgroundBrush( KColorScheme::View, KColorScheme::NegativeBackground );
212
QPalette p = m_searchEdit->palette();
213
p.setColor( QPalette::Base, backgroundBrush.brush( m_searchEdit ).color() );
214
m_searchEdit->setPalette( p );
216
if( m_showOnlyMatches )
217
showHiddenTracksWarning();
220
void ProgressiveSearchWidget::showHiddenTracksWarning()
222
m_warningLabel->show();
225
void ProgressiveSearchWidget::hideHiddenTracksWarning()
227
m_warningLabel->hide();
230
void ProgressiveSearchWidget::slotSearchTracks( bool search )
233
m_searchFieldsMask |= Playlist::MatchTrack;
235
m_searchFieldsMask ^= Playlist::MatchTrack;
237
Amarok::config( "Playlist Search" ).writeEntry( "MatchTrack", search );
239
if( !m_searchEdit->text().isEmpty() )
240
emit( filterChanged( m_searchEdit->text(), m_searchFieldsMask, m_showOnlyMatches ) );
243
void ProgressiveSearchWidget::slotSearchArtists( bool search )
246
m_searchFieldsMask |= Playlist::MatchArtist;
248
m_searchFieldsMask ^= Playlist::MatchArtist;
250
Amarok::config( "Playlist Search" ).writeEntry( "MatchArtist", search );
252
if( !m_searchEdit->text().isEmpty() )
253
emit( filterChanged( m_searchEdit->text(), m_searchFieldsMask, m_showOnlyMatches ) );
256
void ProgressiveSearchWidget::slotSearchAlbums( bool search )
259
m_searchFieldsMask |= Playlist::MatchAlbum;
261
m_searchFieldsMask ^= Playlist::MatchAlbum;
263
Amarok::config( "Playlist Search" ).writeEntry( "MatchAlbum", search );
265
if( !m_searchEdit->text().isEmpty() )
266
emit( filterChanged( m_searchEdit->text(), m_searchFieldsMask, m_showOnlyMatches ) );
269
void ProgressiveSearchWidget::slotSearchGenre( bool search )
272
m_searchFieldsMask |= Playlist::MatchGenre;
274
m_searchFieldsMask ^= Playlist::MatchGenre;
276
Amarok::config( "Playlist Search" ).writeEntry( "MatchGenre", search );
278
if( !m_searchEdit->text().isEmpty() )
279
emit( filterChanged( m_searchEdit->text(), m_searchFieldsMask, m_showOnlyMatches ) );
282
void ProgressiveSearchWidget::slotSearchComposers( bool search )
285
m_searchFieldsMask |= Playlist::MatchComposer;
287
m_searchFieldsMask ^= Playlist::MatchComposer;
289
Amarok::config( "Playlist Search" ).writeEntry( "MatchComposer", search );
291
if( !m_searchEdit->text().isEmpty() )
292
emit( filterChanged( m_searchEdit->text(), m_searchFieldsMask, m_showOnlyMatches ) );
295
void ProgressiveSearchWidget::slotSearchYears( bool search )
298
m_searchFieldsMask |= Playlist::MatchYear;
300
m_searchFieldsMask ^= Playlist::MatchYear;
302
Amarok::config( "Playlist Search" ).writeEntry( "MatchYear", search );
304
if( !m_searchEdit->text().isEmpty() )
305
emit( filterChanged( m_searchEdit->text(), m_searchFieldsMask, m_showOnlyMatches ) );
308
void ProgressiveSearchWidget::readConfig()
310
m_searchFieldsMask = 0;
312
KConfigGroup config = Amarok::config("Playlist Search");
314
if( config.readEntry( "MatchTrack", true ) )
315
m_searchFieldsMask |= Playlist::MatchTrack;
316
if( config.readEntry( "MatchArtist", true ) )
317
m_searchFieldsMask |= Playlist::MatchArtist;
318
if( config.readEntry( "MatchAlbum", true ) )
319
m_searchFieldsMask |= Playlist::MatchAlbum;
320
if( config.readEntry( "MatchGenre", false ) )
321
m_searchFieldsMask |= Playlist::MatchGenre;
322
if( config.readEntry( "MatchComposer", false ) )
323
m_searchFieldsMask |= Playlist::MatchComposer;
324
if( config.readEntry( "MatchYear", false ) )
325
m_searchFieldsMask |= Playlist::MatchYear;
327
m_showOnlyMatches = config.readEntry( "ShowOnlyMatches", false );
330
void ProgressiveSearchWidget::slotShowOnlyMatches( bool onlyMatches )
332
KConfigGroup config = Amarok::config( "Playlist Search" );
333
config.writeEntry( "ShowOnlyMatches", onlyMatches );
335
m_showOnlyMatches = onlyMatches;
337
m_nextAction->setVisible( !onlyMatches );
338
m_previousAction->setVisible( !onlyMatches );
340
emit( showOnlyMatches( onlyMatches ) );
344
ProgressiveSearchWidget::keyPressEvent( QKeyEvent *event )
346
if( event->matches( QKeySequence::FindNext ) )
351
else if( event->matches( QKeySequence::FindPrevious ) )
359
KHBox::keyPressEvent( event );
363
void ProgressiveSearchWidget::slotFilterClear()
365
m_searchEdit->setText( QString() );
368
#include "ProgressiveSearchWidget.moc"