make MemoryQueryMaker use new matcher classes instead of old private ones
[amarok.git] / src / filebrowser.cpp
blob1851e5effcbf625184e1ef6c0f9216587832de71
1 /* This file is part of the KDE project
2 Copyright (C) 2004 Mark Kretschmann <markey@web.de>
3 Copyright (C) 2003 Alexander Dymo <cloudtemple@mksat.net>
4 Copyright (C) 2003 Roberto Raggi <roberto@kdevelop.org>
5 Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
6 Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
7 Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License version 2 as published by the Free Software Foundation.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
24 #include "filebrowser.h"
26 #include "amarok.h"
27 #include "browserToolBar.h"
28 #include "collectiondb.h"
29 #include "collection/CollectionManager.h"
30 #include "debug.h"
31 #include "enginecontroller.h"
32 #include "k3bexporter.h"
33 #include "kbookmarkhandler.h"
34 #include "MainWindow.h"
35 #include "mediabrowser.h"
36 #include "medium.h"
37 #include "mydirlister.h"
38 #include "mydiroperator.h"
40 #include "playlist/PlaylistModel.h"
41 #include "statusbar.h"
42 #include "tagdialog.h"
43 #include "TheInstances.h"
45 #include <k3listview.h>
46 #include <k3urldrag.h>
47 #include <KAction>
48 #include <KActionMenu>
49 #include <KActionCollection>
50 #include <KConfigGroup>
51 #include <KDirOperator>
52 #include <KHBox>
53 #include <KIconLoader>
54 #include <KIO/NetAccess>
55 #include <KLineEdit>
56 #include <KLocale>
57 #include <KMenu>
58 #include <KPushButton> ///@see SearchPane
59 #include <KUrlComboBox> ///@see ctor
60 #include <KUrlCompletion>
62 #include <q3iconview.h>
63 #include <QAbstractItemView>
64 #include <QDir>
65 #include <QLabel>
66 #include <QTimer>
67 #include <QToolButton>
68 #include <QToolTip>
71 //BEGIN Constructor/destructor
73 FileBrowser::FileBrowser( const char * name, Medium * medium )
74 : KVBox( 0 )
76 KActionCollection *actionCollection;
77 SearchPane *searchPane;
78 setObjectName( name );
80 KUrl location;
82 // Try to keep filebrowser working even if not in a medium context
83 // so if a medium object not passed in, keep earlier behavior
84 if (!medium) {
85 m_medium = 0;
86 location = KUrl( Amarok::config( "Filebrowser" ).readEntry( "Location", QDir::homePath() ) );
87 KFileItem *currentFolder = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, location );
88 //KIO sucks, NetAccess::exists puts up a dialog and has annoying error message boxes
89 //if there is a problem so there is no point in using it anyways.
90 //so... setting the diroperator to ~ is the least sucky option
91 if ( !location.isLocalFile() || !currentFolder->isReadable() ) {
92 location = KUrl( QDir::homePath() ) ;
95 else{
96 m_medium = medium;
97 location = KUrl( m_medium->mountPoint() );
100 KActionCollection* ac = new KActionCollection( this );
101 KStandardAction::selectAll( this, SLOT( selectAll() ), ac );
103 KToolBar *toolbar = new Browser::ToolBar( this );
104 toolbar->setToolButtonStyle( Qt::ToolButtonIconOnly );
106 { //Filter LineEdit
107 // KToolBar* searchToolBar = new Browser::ToolBar( this );
109 m_filter = new KLineEdit( 0 );
110 toolbar->addWidget(m_filter);
111 m_filter->setClearButtonShown( true );
112 m_filter->setClickMessage( i18n( "Enter search terms here" ) );
114 m_filter->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);
116 m_filter->setToolTip( i18n( "Enter space-separated terms to search in the directory-listing" ) );
119 { //Directory Listing
120 KVBox *container; KHBox *box;
122 container = new KVBox( this );
123 container->setFrameStyle( m_filter->frameStyle() );
124 container->setMargin( 3 );
125 container->setSpacing( 2 );
126 container->setBackgroundMode( Qt::PaletteBase );
128 box = new KHBox( container );
129 box->setMargin( 3 );
130 box->setBackgroundMode( Qt::PaletteBase );
132 //folder selection combo box
133 m_combo = new KUrlComboBox( KUrlComboBox::Directories, true, box );
134 m_combo->setObjectName( "path combo" );
136 if (!m_medium){
137 m_combo->setCompletionObject( new KUrlCompletion( KUrlCompletion::DirCompletion ) );
138 m_combo->setAutoDeleteCompletionObject( true );
140 m_combo->setMaxItems( 9 );
141 m_combo->setUrls( Amarok::config( "Filebrowser" ).readEntry( "Dir History", QStringList() ) );
143 if (!m_medium)
144 m_combo->lineEdit()->setText( location.path() );
145 else
146 m_combo->lineEdit()->setText( "/" );
148 //The main widget with file listings and that
149 m_dir = new MyDirOperator( location, container, m_medium );
150 m_dir->setEnableDirHighlighting( true );
151 m_dir->setMode( KFile::Mode((int)KFile::Files | (int)KFile::Directory) ); //allow selection of multiple files + dirs
152 m_dir->setOnlyDoubleClickSelectsFiles( true ); //Amarok type settings
153 KConfigGroup cg(Amarok::config( "Filebrowser" ));
154 m_dir->readConfig( cg );
155 m_dir->setView( KFile::Default ); //will set userconfigured view, will load URL
156 m_dir->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding );
157 m_dir->setAcceptDrops( true );
158 //Automatically open folder after hovering above it...probably a good thing
159 //but easily disabled by commenting this line out
160 //Disabled for now because can't show . and .. folders.
161 //TODO: Find out a way to fix this?
162 //m_dir->setDropOptions( KFileView::AutoOpenDirs );
164 static_cast<QFrame*>(m_dir->viewWidget())->setFrameStyle( QFrame::NoFrame );
165 static_cast<Q3IconView*>(m_dir->viewWidget())->setSpacing( 1 );
167 actionCollection = m_dir->actionCollection();
169 searchPane = new SearchPane( this );
171 setStretchFactor( container, 2 );
175 KMenu* const menu = static_cast<KActionMenu*>(actionCollection->action("popupMenu"))->menu();
177 menu->clear();
178 m_createPlaylistAction = menu->addAction( KIcon( Amarok::icon( "files" ) ), i18n( "&Load" ), this, SLOT( slotCreatePlaylist() ) );
180 menu->addAction( KIcon( Amarok::icon( "add_playlist" ) ), i18n( "&Append to Playlist" ), this, SLOT( slotAppendToPlaylist() ) );
182 m_queueTracksAction = menu->addAction( KIcon( Amarok::icon( "queue_track" ) ), i18n( "&Queue Track" ), this, SLOT( slotQueueTrack() ) );
184 menu->addAction( KIcon( Amarok::icon( "save" ) ), i18n( "&Save as Playlist..." ), this, SLOT( slotSavePlaylist() ) );
185 menu->addSeparator();
187 m_mediaDeviceAction = 0; // sanity
188 if( !m_medium )
189 m_mediaDeviceAction = menu->addAction( KIcon( Amarok::icon( "device" ) ), i18n( "&Transfer to Media Device" ), this, SLOT( slotMediaDevice() ) );
191 m_organizeFilesAction = menu->addAction( KIcon( Amarok::icon( "collection" ) ), i18n( "&Organize Files..." ), this, SLOT( slotOrganizeFiles() ) );
192 m_copyToCollectionAction = menu->addAction( KIcon( Amarok::icon( "collection" ) ), i18n( "&Copy Files to Collection..." ), this, SLOT( slotCopyToCollection() ) );
193 m_moveToCollectionAction = menu->addAction( KIcon( Amarok::icon( "collection" ) ), i18n( "&Move Files to Collection..." ), this, SLOT( slotMoveToCollection() ) );
195 QAction *burnAction = menu->addAction( KIcon( Amarok::icon( "burn" ) ), i18n("Burn to CD..."), this, SLOT( slotBurnCd() ) );
196 burnAction->setEnabled( K3bExporter::isAvailable() );
198 menu->addSeparator();
199 menu->addAction( i18n( "&Select All Files" ), this, SLOT( selectAll() ) );
200 menu->addSeparator();
202 QAction *deleteAction = actionCollection->action( "delete" );
203 deleteAction->setIcon( KIcon( Amarok::icon( "remove" ) ) );
204 menu->addAction( deleteAction );
206 menu->addSeparator();
207 menu->addAction( KIcon( Amarok::icon( "info" ) ), i18nc( "[only-singular]", "Edit Track &Information..." ), this, SLOT( slotEditTags() ) );
208 menu->addAction( actionCollection->action( "properties" ) );
210 connect( menu, SIGNAL(aboutToShow()), SLOT(prepareContextMenu()) );
214 KActionMenu *a;
216 a = static_cast<KActionMenu*>( actionCollection->action( "sorting menu" ) );
217 a->setIcon( KIcon( Amarok::icon( "configure" ) ) );
218 a->setDelayed( false ); //TODO should be done by KDirOperator
220 static_cast<KAction*>(actionCollection->action( "delete" ))->setShortcut( KShortcut( Qt::ShiftModifier + Qt::Key_Delete ) );
222 a = new KActionMenu( this );
224 a->setText( i18n("Bookmarks") );
225 a->setIcon(KIcon("bookmark-toolbar"));
226 actionCollection->addAction( "bookmarks", a );
228 a->setDelayed( false );
230 new KBookmarkHandler( m_dir, a->menu() );
234 if ( QAction *a = actionCollection->action( "up" ) )
235 toolbar->addAction(a);
236 if ( QAction *a = actionCollection->action( "back" ) )
237 toolbar->addAction(a);
238 if ( QAction *a = actionCollection->action( "forward" ) )
239 toolbar->addAction(a);
240 if ( QAction *a = actionCollection->action( "home" ) )
241 toolbar->addAction(a);
242 if ( QAction *a = actionCollection->action( "reload" ) ) {
243 a->setIcon( KIcon(Amarok::icon( "refresh" )) );
244 toolbar->addAction(a);
247 toolbar->addSeparator();
249 if ( QAction *a = actionCollection->action( "short view" ) )
250 toolbar->addAction(a);
251 if ( QAction *a = actionCollection->action( "detailed view" ) )
252 toolbar->addAction(a);
254 toolbar->addSeparator();
256 if ( QAction *a = actionCollection->action( "sorting menu" ) )
257 toolbar->addAction(a);
258 if ( QAction *a = actionCollection->action( "bookmarks" ) )
259 toolbar->addAction(a);
262 KAction *gotoCurrent = new KAction( i18n("Go To Current Track Folder"), this );
263 actionCollection->addAction("Go To Current Track Folder", gotoCurrent);
264 gotoCurrent->setIcon( KIcon(Amarok::icon( "music" )) );
265 connect( gotoCurrent, SIGNAL( triggered() ), this, SLOT( gotoCurrentFolder() ) );
267 toolbar->addAction(gotoCurrent);
269 //disconnect( actionCollection->action( "up" ), SIGNAL( triggered() ), m_dir, SLOT( cdUp() ) );
270 //connect( actionCollection->action( "up" ), SIGNAL( triggered() ), m_dir, SLOT( myCdUp() ) );
271 //disconnect( actionCollection->action( "home" ), SIGNAL( triggered() ), m_dir, SLOT( home() ) );
272 //connect( actionCollection->action( "home" ), SIGNAL( triggered() ), m_dir, SLOT( myHome() ) );
275 connect( m_filter, SIGNAL(textChanged( const QString& )), SLOT(setFilter( const QString& )) );
276 connect( m_combo, SIGNAL(urlActivated( const KUrl& )), SLOT(setUrl( const KUrl& )) );
277 connect( m_combo, SIGNAL(returnPressed( const QString& )), SLOT(setUrl( const QString& )) );
278 connect( m_dir, SIGNAL(viewChanged( KFileView* )), SLOT(slotViewChanged( KFileView* )) );
279 connect( m_dir, SIGNAL(fileSelected( const KFileItem* )), SLOT(activate( const KFileItem* )) );
280 connect( m_dir, SIGNAL(urlEntered( const KUrl& )), SLOT(urlChanged( const KUrl& )) );
281 connect( m_dir, SIGNAL(urlEntered( const KUrl& )), searchPane, SLOT(urlChanged( const KUrl& )) );
282 connect( m_dir, SIGNAL(dropped( const KFileItem*, QDropEvent*, const KUrl::List& )),
283 SLOT(dropped( const KFileItem*, QDropEvent*, const KUrl::List& )) );
285 setSpacing( 4 );
286 setFocusProxy( m_dir ); //so the dirOperator is focused when we get focus events
287 // Toolbar is more than 250px wide, SideBar doesn't allow that. -> Resizing issues.
288 setMinimumWidth( 250 /* toolbar->sizeHint().width() */ );
292 FileBrowser::~FileBrowser()
294 KConfigGroup c = Amarok::config( "Filebrowser" );
296 c.writeEntry( "Location", m_dir->url().url() );
297 c.writeEntry( "Dir History", m_combo->urls() );
300 //END Constructor/Destructor
302 void FileBrowser::setUrl( const KUrl &url )
304 m_dir->setFocus();
305 if (!m_medium)
306 m_dir->setUrl( url, true );
307 else {
308 QString urlpath = url.isLocalFile() ? url.path() : url.prettyUrl();
309 KUrl newURL( urlpath.prepend( m_medium->mountPoint() ).remove("..") );
310 //debug() << "set-url-kurl: changing to: " << newURL.path();
311 m_dir->setUrl( newURL, true );
315 void FileBrowser::setUrl( const QString &url )
317 if (!m_medium)
318 m_dir->setUrl( KUrl(url), true );
319 else{
320 KUrl newURL( QString(url).prepend( m_medium->mountPoint() ).remove("..") );
321 //debug() << "set-url-qstring: changing to: " << newURL.path();
322 m_dir->setUrl( newURL, true );
326 //BEGIN Private Methods
328 Meta::TrackList FileBrowser::selectedItems()
330 Meta::TrackList list;
332 QList<KFileItem> source;
333 if ( m_dir->selectedItems().count() )
334 source = m_dir->selectedItems();
335 else {
336 //FIXME: not that simplw to do with the new api
337 //get all items...,
338 //source = m_dir->view()->omdel()->items();
341 for( QList<KFileItem>::const_iterator it = source.begin(); it != source.end(); ++it )
342 list.append( CollectionManager::instance()->trackForUrl( (*it).url() ) );
344 return list;
347 void FileBrowser::playlistFromURLs( const KUrl::List &urls )
349 QString suggestion;
350 if( urls.count() == 1 && QFileInfo( urls.first().path() ).isDir() )
351 suggestion = urls.first().fileName();
352 else
353 suggestion = i18n( "Untitled" );
354 //PORT 2.0 const QString path = PlaylistDialog::getSaveFileName( suggestion );
355 // if( path.isEmpty() )
356 // return;
358 //PORT 2.0 if( PlaylistBrowser::savePlaylist( path, urls ) )
359 // {
360 // Amarok::StatusBar::instance()->shortMessage( "Playlist saved to playlist browser" );
361 // }
365 //END Private Methods
368 //BEGIN Public Slots
370 void
371 FileBrowser::setFilter( const QString &text )
373 if ( text.isEmpty() )
374 m_dir->clearFilter();
376 else {
377 QString filter;
379 const QStringList terms = text.split( ' ', QString::SkipEmptyParts );
380 foreach( QString it, terms )
382 filter += '*';
383 filter += it;
385 filter += '*';
387 m_dir->setNameFilter( filter );
390 m_dir->updateDir();
393 void
394 FileBrowser::dropped( const KFileItem* /*item*/, QDropEvent* event, const KUrl::List &urls)
396 //Do nothing right now
397 event->ignore();
398 //Run into const problems iterating over the list, so copy it to a malleable one
399 //(besides, need to filter for local giles)
400 KUrl::List list(urls);
402 for ( KUrl::List::iterator it = list.begin(); it != list.end(); ){
403 if ( m_medium && !(*it).isLocalFile() )
404 it = list.erase( it );
405 else{
406 debug() << "Dropped: " << (*it);
407 it++;
412 //END Public Slots
415 //BEGIN Private Slots
417 inline void
418 FileBrowser::urlChanged( const KUrl &u )
420 //the DirOperator's URL has changed
422 QString url = u.isLocalFile() ? u.path() : u.prettyUrl();
424 if( m_medium ){
425 //remove the leading mountPoint value
426 url.remove( 0, m_medium->mountPoint().length() );
429 QStringList urls = m_combo->urls();
430 urls.removeAll( url );
431 urls.prepend( url );
433 m_combo->setUrls( urls, KUrlComboBox::RemoveBottom );
436 inline void
437 FileBrowser::slotViewChanged( KFileView *view )
439 if( view->widget()->inherits( "K3ListView" ) )
441 using namespace Amarok::ColorScheme;
443 static_cast<K3ListView*>(view->widget())->setAlternateBackground( AltBase );
447 inline void
448 FileBrowser::activate( const KFileItem *item )
450 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( item->url() );
451 The::playlistModel()->insertOptioned( track, Playlist::AppendAndPlay );
454 inline void
455 FileBrowser::prepareContextMenu()
457 const QList<KFileItem> items = m_dir->selectedItems();
458 m_createPlaylistAction->setVisible( items.count() > 1 || ( items.count() == 1 && items.first().isDir() ) );
460 if( items.count() == 1 )
461 m_queueTracksAction->setText( i18n( "Queue Track" ) );
462 else if( items.count() > 1 )
463 m_queueTracksAction->setText( i18n( "Queue Tracks" ) );
465 m_queueTracksAction->setVisible( items.count() > 0 );
466 m_mediaDeviceAction->setVisible( MediaBrowser::isAvailable() );
467 m_copyToCollectionAction->setVisible( CollectionDB::instance()->isDirInCollection( url().path() ) );
468 m_moveToCollectionAction->setVisible( CollectionDB::instance()->isDirInCollection( url().path() ) );
469 m_organizeFilesAction->setVisible( CollectionDB::instance()->isDirInCollection( url().path() ) );
472 inline void
473 FileBrowser::slotCreatePlaylist()
475 The::playlistModel()->insertOptioned( selectedItems(), Playlist::Replace );
478 inline void
479 FileBrowser::slotSavePlaylist()
481 //PORT 2.0 playlistFromURLs( selectedItems() );
484 inline void
485 FileBrowser::slotAppendToPlaylist()
487 The::playlistModel()->insertOptioned( selectedItems(), Playlist::Append );
490 inline void
491 FileBrowser::slotQueueTracks()
493 The::playlistModel()->insertOptioned( selectedItems(), Playlist::Queue );
496 inline void
497 FileBrowser::slotEditTags()
500 KUrl::List list = Amarok::recursiveUrlExpand( selectedItems() );
501 TagDialog *dialog = 0;
503 if( list.count() == 1 )
504 dialog = new TagDialog( list.first(), this );
505 else
506 dialog = new TagDialog( list, this );
507 dialog->show();
511 inline void
512 FileBrowser::slotCopyToCollection()
514 //PORT 2.0 CollectionView::instance()->organizeFiles( selectedItems(), i18n( "Copy Files To Collection" ), true );
517 inline void
518 FileBrowser::slotMoveToCollection()
520 //PORT 2.0 CollectionView::instance()->organizeFiles( selectedItems(), i18n( "Move Files To Collection" ), false );
523 inline void
524 FileBrowser::slotOrganizeFiles()
526 //PORT 2.0 CollectionView::instance()->organizeFiles( selectedItems(), i18n( "Organize Collection Files" ), false );
529 inline void
530 FileBrowser::slotMediaDevice()
532 //PORT 2.0 MediaBrowser::queue()->addUrls( selectedItems() );
535 inline void
536 FileBrowser::slotBurnCd()
538 //PORT 2.0 K3bExporter::instance()->exportTracks( selectedItems() );
541 inline void
542 FileBrowser::gotoCurrentFolder()
544 Meta::TrackPtr track = EngineController::instance()->currentTrack();
545 if( !track )
546 return;
547 const KUrl &url = track->playableUrl();
548 KUrl dirURL = KUrl( url.directory() );
550 m_combo->setUrl( dirURL );
551 setUrl( dirURL );
554 //END Private Slots
556 void
557 FileBrowser::selectAll()
560 //FIME: B0rked with the new KDirOpperator API
561 /*KFileItemList list( *m_dir->view()->items() );
563 // Select all items which represent files
564 for( KFileItemList::const_iterator it = list.begin(); it != list.end(); ++it)
565 m_dir->view()->setSelected( *it, (*it)->isFile() );
569 #include <QPainter>
570 #include <q3simplerichtext.h>
572 class KURLView : public K3ListView
574 public:
575 KURLView( QWidget *parent ) : K3ListView( parent )
577 reinterpret_cast<QWidget*>(header())->hide();
578 addColumn( QString() );
579 setResizeMode( K3ListView::LastColumn );
580 setDragEnabled( true );
581 setSelectionMode( Q3ListView::Extended );
584 class Item : public K3ListViewItem {
585 public:
586 Item( const KUrl &url, KURLView *parent ) : K3ListViewItem( parent, url.fileName() ), m_url( url ) {}
587 KUrl m_url;
590 virtual Q3DragObject *dragObject()
592 QList<Q3ListViewItem*> items = selectedItems();
593 KUrl::List urls;
594 for( QList<Q3ListViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it) {
595 urls += ( static_cast<Item*>(*it) )->m_url;
598 return new K3URLDrag( urls, this );
601 virtual void viewportPaintEvent( QPaintEvent *e )
603 K3ListView::viewportPaintEvent( e );
605 if ( childCount() == 0 ) {
606 QPainter p( viewport() );
608 if ( m_text.isEmpty() ) {
609 //TODO Perhaps it's time to put this in some header, as we use it in three places now
610 Q3SimpleRichText t( i18n(
611 "<div align=center>"
612 "Enter a search term above; you can use wildcards like * and ?"
613 "</div>" ), font() );
615 t.setWidth( width() - 50 );
617 const uint w = t.width() + 20;
618 const uint h = t.height() + 20;
620 p.setBrush( colorGroup().background() );
621 p.drawRoundRect( 15, 15, w, h, (8*200)/w, (8*200)/h );
622 t.draw( &p, 20, 20, QRect(), colorGroup() );
624 else {
625 p.setPen( palette().color( QPalette::Disabled, QColorGroup::Text ) );
626 p.drawText( rect(), Qt::AlignCenter | Qt::TextWordWrap, m_text );
631 void unsetText() { setText( QString() ); }
632 void setText( const QString &text ) { m_text = text; viewport()->update(); }
634 private:
635 QString m_text;
640 SearchPane::SearchPane( FileBrowser *parent )
641 : KVBox( parent )
642 , m_lineEdit( 0 )
643 , m_listView( 0 )
644 , m_lister( 0 )
646 KVBox *container = new KVBox( this );
647 container->setObjectName( "container" );
648 container->hide();
651 KHBox *box = new KHBox( container );
652 //box->setMargin( 5 );
653 box->setBackgroundMode( Qt::PaletteBase );
655 m_lineEdit = new KLineEdit( box );
656 m_lineEdit->setClickMessage( i18n("Search here...") );
657 connect( m_lineEdit, SIGNAL(textChanged( const QString& )), SLOT(searchTextChanged( const QString& )) );
659 m_listView = new KURLView( container );
661 container->setFrameStyle( m_listView->frameStyle() );
662 //container->setMargin( 5 );
663 container->setBackgroundMode( Qt::PaletteBase );
665 m_listView->setFrameStyle( QFrame::NoFrame );
666 connect( m_listView, SIGNAL(executed( Q3ListViewItem* )), SLOT(activate( Q3ListViewItem* )) );
669 KPushButton *button = new KPushButton( KGuiItem( i18n("&Show Search Panel"), "find" ), this );
670 button->setToggleButton( true );
671 connect( button, SIGNAL(toggled( bool )), SLOT(toggle( bool )) );
673 m_lister = new MyDirLister( true /*delay mimetypes*/ );
674 m_lister->setParent( this );
675 connect( m_lister, SIGNAL(newItems( const KFileItemList& )), SLOT(searchMatches( const KFileItemList& )) );
676 connect( m_lister, SIGNAL(completed()), SLOT(searchComplete()) );
679 void
680 SearchPane::toggle( bool toggled )
682 if ( toggled )
683 m_lineEdit->setFocus();
685 findChild<QWidget*>("container")->setVisible( toggled );
688 void
689 SearchPane::urlChanged( const KUrl& )
691 searchTextChanged( m_lineEdit->text() );
694 void
695 SearchPane::searchTextChanged( const QString &text )
697 //TODO if user changes search directory then we need to update the search too
699 m_lister->stop();
700 m_listView->clear();
701 m_dirs.clear();
703 if ( text.isEmpty() ) {
704 m_listView->unsetText();
705 return;
708 m_filter = QRegExp( text.contains( "*" ) ? text : '*'+text+'*', false, true );
710 m_lister->openUrl( searchURL() );
712 m_listView->setText( i18n( "Searching..." ) );
715 void
716 SearchPane::searchMatches( const KFileItemList &list )
718 for( KFileItemList::ConstIterator it = list.begin(), end = list.end(); it != end; ++it ) {
719 if( (*it)->isDir() )
720 m_dirs += (*it)->url();
721 else if( m_filter.exactMatch( (*it)->name() ) )
722 new KURLView::Item( (*it)->url(), static_cast<KURLView*>( m_listView ) );
726 void
727 SearchPane::searchComplete()
729 //KDirLister crashes if you call openUrl() from a slot
730 //connected to KDirLister::complete()
731 //TODO fix crappy KDElibs
733 QTimer::singleShot( 0, this, SLOT(_searchComplete()) );
736 void
737 SearchPane::_searchComplete()
739 if ( !m_dirs.isEmpty() ) {
740 KUrl url = m_dirs.first();
741 m_dirs.pop_front();
742 m_lister->openUrl( url );
744 else
745 m_listView->setText( i18n("No results found") ); //only displayed if the listview is empty
748 void
749 SearchPane::activate( Q3ListViewItem *item )
751 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( static_cast<KURLView::Item*>(item)->m_url );
752 The::playlistModel()->insertOptioned( track, Playlist::DirectPlay );
755 #include "filebrowser.moc"