Header cleanup
[amarok.git] / src / filebrowser.cpp
blob196af123bd1e07ed3e9308f81275c55a05b3b931
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 Steet, Fifth Floor,
21 Boston, MA 02110-1301, USA.
24 #include "amarok.h"
25 #include "browserToolBar.h"
26 #include "enginecontroller.h"
27 #include "filebrowser.h"
28 #include "k3bexporter.h"
30 #include <kaction.h>
31 #include <kapplication.h>
32 #include "kbookmarkhandler.h"
33 #include <kdiroperator.h>
34 #include <kiconloader.h>
35 #include <kio/netaccess.h>
36 #include <k3listview.h>
37 #include <k3urldrag.h>
38 #include <klocale.h>
39 #include <kconfiggroup.h>
40 #include <kmenu.h>
41 #include <kpushbutton.h> ///@see SearchPane
42 ///@see ctor
43 #include <kurlcombobox.h>
44 #include <kurlcompletion.h>
45 #include <klineedit.h>
47 #include "mediabrowser.h"
48 #include "medium.h"
49 #include "mydirlister.h"
50 #include "mydiroperator.h"
51 #include "playlist.h"
52 #include "playlistbrowser.h"
53 #include "playlistloader.h"
54 #include "playlistwindow.h"
55 #include "collectionbrowser.h"
56 #include "statusbar.h"
57 #include "tagdialog.h"
59 #include <QDir>
60 #include <khbox.h>
61 #include <q3iconview.h>
62 #include <QLabel>
63 #include <QTimer>
64 #include <QToolTip>
65 #include <QToolButton>
66 //Added by qt3to4:
67 #include <Q3PtrList>
68 #include <QDropEvent>
69 #include <Q3PopupMenu>
70 #include <QPaintEvent>
74 //BEGIN Constructor/destructor
76 FileBrowser::FileBrowser( const char * name, Medium * medium )
77 : KVBox( 0 )
79 KActionCollection *actionCollection;
80 SearchPane *searchPane;
82 KUrl *location;
84 // Try to keep filebrowser working even if not in a medium context
85 // so if a medium object not passed in, keep earlier behavior
86 if (!medium) {
87 m_medium = 0;
88 location = new KUrl( Amarok::config( "Filebrowser" ).readEntry( "Location", QDir::homePath() ) );
89 KFileItem *currentFolder = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, *location );
90 //KIO sucks, NetAccess::exists puts up a dialog and has annoying error message boxes
91 //if there is a problem so there is no point in using it anyways.
92 //so... setting the diroperator to ~ is the least sucky option
93 if ( !location->isLocalFile() || !currentFolder->isReadable() ) {
94 delete location;
95 location = new KUrl( QDir::homePath() ) ;
98 else{
99 m_medium = medium;
100 location = new KUrl( m_medium->mountPoint() );
103 KActionCollection* ac = new KActionCollection( this );
104 KStandardAction::selectAll( this, SLOT( selectAll() ), ac );
106 KToolBar *toolbar = new Browser::ToolBar( this );
107 toolbar->setToolButtonStyle( Qt::ToolButtonIconOnly );
109 { //Filter LineEdit
110 // KToolBar* searchToolBar = new Browser::ToolBar( this );
112 m_filter = new KLineEdit( 0 );
113 toolbar->addWidget(m_filter);
114 m_filter->setClearButtonShown( true );
115 m_filter->setClickMessage( i18n( "Enter search terms here" ) );
117 m_filter->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);
119 m_filter->setToolTip( i18n( "Enter space-separated terms to search in the directory-listing" ) );
122 { //Directory Listing
123 KVBox *container; KHBox *box;
125 container = new KVBox( this );
126 container->setFrameStyle( m_filter->frameStyle() );
127 container->setMargin( 3 );
128 container->setSpacing( 2 );
129 container->setBackgroundMode( Qt::PaletteBase );
131 box = new KHBox( container );
132 box->setMargin( 3 );
133 box->setBackgroundMode( Qt::PaletteBase );
135 //folder selection combo box
136 m_combo = new KUrlComboBox( KUrlComboBox::Directories, true, box );
137 m_combo->setObjectName( "path combo" );
139 if (!m_medium){
140 m_combo->setCompletionObject( new KUrlCompletion( KUrlCompletion::DirCompletion ) );
141 m_combo->setAutoDeleteCompletionObject( true );
143 m_combo->setMaxItems( 9 );
144 m_combo->setUrls( Amarok::config( "Filebrowser" ).readEntry( "Dir History", QStringList() ) );
146 if (!m_medium)
147 m_combo->lineEdit()->setText( location->path() );
148 else
149 m_combo->lineEdit()->setText( "/" );
151 //The main widget with file listings and that
152 m_dir = new MyDirOperator( *location, container, m_medium );
153 m_dir->setEnableDirHighlighting( true );
154 m_dir->setMode( KFile::Mode((int)KFile::Files | (int)KFile::Directory) ); //allow selection of multiple files + dirs
155 m_dir->setOnlyDoubleClickSelectsFiles( true ); //Amarok type settings
156 KConfigGroup cg(Amarok::config( "Filebrowser" ));
157 m_dir->readConfig( cg );
158 m_dir->setView( KFile::Default ); //will set userconfigured view, will load URL
159 m_dir->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding );
160 m_dir->setAcceptDrops( true );
161 //Automatically open folder after hovering above it...probably a good thing
162 //but easily disabled by commenting this line out
163 //Disabled for now because can't show . and .. folders.
164 //TODO: Find out a way to fix this?
165 //m_dir->setDropOptions( KFileView::AutoOpenDirs );
167 static_cast<QFrame*>(m_dir->viewWidget())->setFrameStyle( QFrame::NoFrame );
168 static_cast<Q3IconView*>(m_dir->viewWidget())->setSpacing( 1 );
170 actionCollection = m_dir->actionCollection();
172 searchPane = new SearchPane( this );
174 setStretchFactor( container, 2 );
178 KMenu* const menu = static_cast<KActionMenu*>(actionCollection->action("popupMenu"))->popupMenu();
180 menu->clear();
181 menu->insertItem( KIcon( Amarok::icon( "files" ) ), i18n( "&Load" ), MakePlaylist );
182 menu->insertItem( KIcon( Amarok::icon( "add_playlist" ) ), i18n( "&Append to Playlist" ), AppendToPlaylist );
183 menu->insertItem( KIcon( Amarok::icon( "queue_track" ) ), i18n( "&Queue Track" ), QueueTrack );
184 menu->insertItem( KIcon( Amarok::icon( "queue_track" ) ), i18n( "&Queue Tracks" ), QueueTracks );
186 menu->insertItem( KIcon( Amarok::icon( "save" ) ), i18n( "&Save as Playlist..." ), SavePlaylist );
187 menu->insertSeparator();
189 if (!m_medium)
190 menu->insertItem( KIcon( Amarok::icon( "device" ) ), i18n( "&Transfer to Media Device" ), MediaDevice );
192 menu->insertItem( KIcon( Amarok::icon( "collection" ) ), i18n( "&Organize Files..." ), OrganizeFiles );
193 menu->insertItem( KIcon( Amarok::icon( "collection" ) ), i18n( "&Copy Files to Collection..." ), CopyToCollection );
194 menu->insertItem( KIcon( Amarok::icon( "collection" ) ), i18n( "&Move Files to Collection..." ), MoveToCollection );
195 menu->insertItem( KIcon( Amarok::icon( "burn" ) ), i18n("Burn to CD..."), BurnCd );
196 menu->insertSeparator();
197 menu->insertItem( i18n( "&Select All Files" ), SelectAllFiles );
198 menu->insertSeparator();
199 actionCollection->action( "delete" )->setIcon( KIcon( Amarok::icon( "remove" ) ) );
200 menu->addAction( actionCollection->action( "delete" ) );
201 menu->insertSeparator();
202 menu->insertItem( KIcon( Amarok::icon( "info" ) ), i18n( "Edit Track &Information..." ), EditTags );
203 menu->addAction( actionCollection->action( "properties" ) );
205 menu->setItemEnabled( BurnCd, K3bExporter::isAvailable() );
207 connect( menu, SIGNAL(aboutToShow()), SLOT(prepareContextMenu()) );
208 connect( menu, SIGNAL(activated( int )), SLOT(contextMenuActivated( int )) );
212 KActionMenu *a;
214 a = static_cast<KActionMenu*>( actionCollection->action( "sorting menu" ) );
215 a->setIcon( KIcon( Amarok::icon( "configure" ) ) );
216 a->setDelayed( false ); //TODO should be done by KDirOperator
218 static_cast<KAction*>(actionCollection->action( "delete" ))->setShortcut( KShortcut( Qt::ShiftModifier + Qt::Key_Delete ) );
220 a = new KActionMenu( this );
222 a->setText( i18n("Bookmarks") );
223 a->setIcon(KIcon("bookmark-toolbar"));
224 actionCollection->addAction( "bookmarks", a );
226 a->setDelayed( false );
228 new KBookmarkHandler( m_dir, a->popupMenu() );
232 if ( QAction *a = actionCollection->action( "up" ) )
233 toolbar->addAction(a);
234 if ( QAction *a = actionCollection->action( "back" ) )
235 toolbar->addAction(a);
236 if ( QAction *a = actionCollection->action( "forward" ) )
237 toolbar->addAction(a);
238 if ( QAction *a = actionCollection->action( "home" ) )
239 toolbar->addAction(a);
240 if ( QAction *a = actionCollection->action( "reload" ) ) {
241 a->setIcon( KIcon(Amarok::icon( "refresh" )) );
242 toolbar->addAction(a);
245 toolbar->addSeparator();
247 if ( QAction *a = actionCollection->action( "short view" ) )
248 toolbar->addAction(a);
249 if ( QAction *a = actionCollection->action( "detailed view" ) )
250 toolbar->addAction(a);
252 toolbar->addSeparator();
254 if ( QAction *a = actionCollection->action( "sorting menu" ) )
255 toolbar->addAction(a);
256 if ( QAction *a = actionCollection->action( "bookmarks" ) )
257 toolbar->addAction(a);
260 KAction *gotoCurrent = new KAction( i18n("Go To Current Track Folder"), this );
261 actionCollection->addAction("Go To Current Track Folder", gotoCurrent);
262 gotoCurrent->setIcon( KIcon(Amarok::icon( "music" )) );
263 connect( gotoCurrent, SIGNAL( triggered() ), this, SLOT( gotoCurrentFolder() ) );
265 toolbar->addAction(gotoCurrent);
267 //disconnect( actionCollection->action( "up" ), SIGNAL( triggered() ), m_dir, SLOT( cdUp() ) );
268 //connect( actionCollection->action( "up" ), SIGNAL( triggered() ), m_dir, SLOT( myCdUp() ) );
269 //disconnect( actionCollection->action( "home" ), SIGNAL( triggered() ), m_dir, SLOT( home() ) );
270 //connect( actionCollection->action( "home" ), SIGNAL( triggered() ), m_dir, SLOT( myHome() ) );
273 connect( m_filter, SIGNAL(textChanged( const QString& )), SLOT(setFilter( const QString& )) );
274 connect( m_combo, SIGNAL(urlActivated( const KUrl& )), SLOT(setUrl( const KUrl& )) );
275 connect( m_combo, SIGNAL(returnPressed( const QString& )), SLOT(setUrl( const QString& )) );
276 connect( m_dir, SIGNAL(viewChanged( KFileView* )), SLOT(slotViewChanged( KFileView* )) );
277 connect( m_dir, SIGNAL(fileSelected( const KFileItem* )), SLOT(activate( const KFileItem* )) );
278 connect( m_dir, SIGNAL(urlEntered( const KUrl& )), SLOT(urlChanged( const KUrl& )) );
279 connect( m_dir, SIGNAL(urlEntered( const KUrl& )), searchPane, SLOT(urlChanged( const KUrl& )) );
280 connect( m_dir, SIGNAL(dropped( const KFileItem*, QDropEvent*, const KUrl::List& )),
281 SLOT(dropped( const KFileItem*, QDropEvent*, const KUrl::List& )) );
283 setSpacing( 4 );
284 setFocusProxy( m_dir ); //so the dirOperator is focused when we get focus events
285 // Toolbar is more than 250px wide, BrowserBar doesn't allow that. -> Resizing issues.
286 setMinimumWidth( 250 /* toolbar->sizeHint().width() */ );
290 FileBrowser::~FileBrowser()
292 KConfigGroup c = Amarok::config( "Filebrowser" );
294 c.writeEntry( "Location", m_dir->url().url() );
295 c.writeEntry( "Dir History", m_combo->urls() );
298 //END Constructor/Destructor
300 void FileBrowser::setUrl( const KUrl &url )
302 m_dir->setFocus();
303 if (!m_medium)
304 m_dir->setUrl( url, true );
305 else {
306 QString urlpath = url.isLocalFile() ? url.path() : url.prettyUrl();
307 KUrl newURL( urlpath.prepend( m_medium->mountPoint() ).remove("..") );
308 //debug() << "set-url-kurl: changing to: " << newURL.path() << endl;
309 m_dir->setUrl( newURL, true );
313 void FileBrowser::setUrl( const QString &url )
315 if (!m_medium)
316 m_dir->setUrl( KUrl(url), true );
317 else{
318 KUrl newURL( QString(url).prepend( m_medium->mountPoint() ).remove("..") );
319 //debug() << "set-url-qstring: changing to: " << newURL.path() << endl;
320 m_dir->setUrl( newURL, true );
324 //BEGIN Private Methods
326 KUrl::List FileBrowser::selectedItems()
328 KUrl::List list;
329 const KFileItemList &source = m_dir->selectedItems()->count() ? *m_dir->selectedItems() : *m_dir->view()->items();
330 for( KFileItemList::const_iterator it = source.begin(); it != source.end(); ++it )
331 list.append( (*it)->url() );
333 return list;
336 void FileBrowser::playlistFromURLs( const KUrl::List &urls )
338 QString suggestion;
339 if( urls.count() == 1 && QFileInfo( urls.first().path() ).isDir() )
340 suggestion = urls.first().fileName();
341 else
342 suggestion = i18n( "Untitled" );
343 const QString path = PlaylistDialog::getSaveFileName( suggestion );
344 if( path.isEmpty() )
345 return;
347 if( PlaylistBrowser::savePlaylist( path, urls ) )
349 Amarok::StatusBar::instance()->shortMessage( "Playlist saved to playlist browser" );
354 //END Private Methods
357 //BEGIN Public Slots
359 void
360 FileBrowser::setFilter( const QString &text )
362 if ( text.isEmpty() )
363 m_dir->clearFilter();
365 else {
366 QString filter;
368 const QStringList terms = QStringList::split( ' ', text );
369 oldForeach( terms ) {
370 filter += '*';
371 filter += *it;
373 filter += '*';
375 m_dir->setNameFilter( filter );
378 m_dir->updateDir();
381 void
382 FileBrowser::dropped( const KFileItem* /*item*/, QDropEvent* event, const KUrl::List &urls){
383 //Do nothing right now
384 event->ignore();
385 //Run into const problems iterating over the list, so copy it to a malleable one
386 //(besides, need to filter for local giles)
387 KUrl::List list(urls);
389 for ( KUrl::List::iterator it = list.begin(); it != list.end(); ){
390 if ( m_medium && !(*it).isLocalFile() )
391 it = list.erase( it );
392 else{
393 debug() << "Dropped: " << (*it) << endl;
394 it++;
399 //END Public Slots
402 //BEGIN Private Slots
404 inline void
405 FileBrowser::urlChanged( const KUrl &u )
407 //the DirOperator's URL has changed
409 QString url = u.isLocalFile() ? u.path() : u.prettyUrl();
411 if( m_medium ){
412 //remove the leading mountPoint value
413 url.remove( 0, m_medium->mountPoint().length() );
416 QStringList urls = m_combo->urls();
417 urls.remove( url );
418 urls.prepend( url );
420 m_combo->setUrls( urls, KUrlComboBox::RemoveBottom );
423 inline void
424 FileBrowser::slotViewChanged( KFileView *view )
426 if( view->widget()->inherits( "K3ListView" ) )
428 using namespace Amarok::ColorScheme;
430 static_cast<K3ListView*>(view->widget())->setAlternateBackground( AltBase );
434 inline void
435 FileBrowser::activate( const KFileItem *item )
437 Playlist::instance()->insertMedia( item->url(), Playlist::DefaultOptions );
440 inline void
441 FileBrowser::prepareContextMenu()
443 const KFileItemList &items = *m_dir->selectedItems();
444 static_cast<KActionMenu*>(m_dir->actionCollection()->action("popupMenu"))->popupMenu()->setItemVisible( SavePlaylist,
445 items.count() > 1 || ( items.count() == 1 && items.first()->isDir() ) );
446 static_cast<KActionMenu*>(m_dir->actionCollection()->action("popupMenu"))->popupMenu()->setItemVisible( QueueTrack,
447 items.count() == 1 );
448 static_cast<KActionMenu*>(m_dir->actionCollection()->action("popupMenu"))->popupMenu()->setItemVisible( QueueTracks,
449 items.count() > 1 );
450 static_cast<KActionMenu*>(m_dir->actionCollection()->action("popupMenu"))->popupMenu()->setItemVisible( MediaDevice,
451 MediaBrowser::isAvailable() );
452 static_cast<KActionMenu*>(m_dir->actionCollection()->action("popupMenu"))->popupMenu()->setItemVisible( MoveToCollection, !CollectionDB::instance()->isDirInCollection( url().path() ) );
453 static_cast<KActionMenu*>(m_dir->actionCollection()->action("popupMenu"))->popupMenu()->setItemVisible( CopyToCollection, !CollectionDB::instance()->isDirInCollection( url().path() ) );
454 static_cast<KActionMenu*>(m_dir->actionCollection()->action("popupMenu"))->popupMenu()->setItemVisible( OrganizeFiles, CollectionDB::instance()->isDirInCollection( url().path() ) );
457 inline void
458 FileBrowser::contextMenuActivated( int id )
460 switch( id )
462 case MakePlaylist:
463 Playlist::instance()->insertMedia( selectedItems(), Playlist::Replace );
464 break;
466 case SavePlaylist:
467 playlistFromURLs( selectedItems() );
468 break;
470 case AppendToPlaylist:
471 Playlist::instance()->insertMedia( selectedItems() );
472 break;
474 case QueueTrack:
475 case QueueTracks:
476 Playlist::instance()->insertMedia( selectedItems(), Playlist::Queue );
477 break;
479 case EditTags:
481 KUrl::List list = Amarok::recursiveUrlExpand( selectedItems() );
482 TagDialog *dialog = NULL;
483 if( list.count() == 1 )
485 dialog = new TagDialog( list.first(), this );
487 else
489 dialog = new TagDialog( list, this );
491 dialog->show();
493 break;
495 case CopyToCollection:
496 CollectionView::instance()->organizeFiles( selectedItems(), i18n( "Copy Files To Collection" ), true );
497 break;
499 case MoveToCollection:
500 CollectionView::instance()->organizeFiles( selectedItems(), i18n( "Move Files To Collection" ), false );
501 break;
503 case OrganizeFiles:
504 CollectionView::instance()->organizeFiles( selectedItems(), i18n( "Organize Collection Files" ), false );
505 break;
507 case MediaDevice:
508 MediaBrowser::queue()->addUrls( selectedItems() );
509 break;
511 case SelectAllFiles:
512 selectAll();
513 break;
515 case BurnCd:
516 K3bExporter::instance()->exportTracks( selectedItems() );
517 break;
521 inline void
522 FileBrowser::gotoCurrentFolder()
524 const KUrl &url = EngineController::instance()->bundle().url();
525 KUrl dirURL = KUrl( url.directory() );
527 m_combo->setUrl( dirURL );
528 setUrl( dirURL );
531 //END Private Slots
533 void
534 FileBrowser::selectAll()
536 KFileItemList list( *m_dir->view()->items() );
538 // Select all items which represent files
539 for( KFileItemList::const_iterator it = list.begin(); it != list.end(); ++it)
540 m_dir->view()->setSelected( *it, (*it)->isFile() );
543 #include <QPainter>
544 #include <q3simplerichtext.h>
546 class KURLView : public K3ListView
548 public:
549 KURLView( QWidget *parent ) : K3ListView( parent )
551 reinterpret_cast<QWidget*>(header())->hide();
552 addColumn( QString() );
553 setResizeMode( K3ListView::LastColumn );
554 setDragEnabled( true );
555 setSelectionMode( Q3ListView::Extended );
558 class Item : public K3ListViewItem {
559 public:
560 Item( const KUrl &url, KURLView *parent ) : K3ListViewItem( parent, url.fileName() ), m_url( url ) {}
561 KUrl m_url;
564 virtual Q3DragObject *dragObject()
566 QList<Q3ListViewItem*> items = selectedItems();
567 KUrl::List urls;
568 for( QList<Q3ListViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it) {
569 urls += ( static_cast<Item*>(*it) )->m_url;
572 return new K3URLDrag( urls, this );
575 virtual void viewportPaintEvent( QPaintEvent *e )
577 K3ListView::viewportPaintEvent( e );
579 if ( childCount() == 0 ) {
580 QPainter p( viewport() );
582 if ( m_text.isEmpty() ) {
583 //TODO Perhaps it's time to put this in some header, as we use it in three places now
584 Q3SimpleRichText t( i18n(
585 "<div align=center>"
586 "Enter a search term above; you can use wildcards like * and ?"
587 "</div>" ), font() );
589 t.setWidth( width() - 50 );
591 const uint w = t.width() + 20;
592 const uint h = t.height() + 20;
594 p.setBrush( colorGroup().background() );
595 p.drawRoundRect( 15, 15, w, h, (8*200)/w, (8*200)/h );
596 t.draw( &p, 20, 20, QRect(), colorGroup() );
598 else {
599 p.setPen( palette().color( QPalette::Disabled, QColorGroup::Text ) );
600 p.drawText( rect(), Qt::AlignCenter | Qt::TextWordWrap, m_text );
605 void unsetText() { setText( QString() ); }
606 void setText( const QString &text ) { m_text = text; viewport()->update(); }
608 private:
609 QString m_text;
614 SearchPane::SearchPane( FileBrowser *parent )
615 : KVBox( parent )
616 , m_lineEdit( 0 )
617 , m_listView( 0 )
618 , m_lister( 0 )
620 KVBox *container = new KVBox( this );
621 container->setObjectName( "container" );
622 container->hide();
625 KHBox *box = new KHBox( container );
626 //box->setMargin( 5 );
627 box->setBackgroundMode( Qt::PaletteBase );
629 m_lineEdit = new KLineEdit( box );
630 m_lineEdit->setClickMessage( i18n("Search here...") );
631 connect( m_lineEdit, SIGNAL(textChanged( const QString& )), SLOT(searchTextChanged( const QString& )) );
633 m_listView = new KURLView( container );
635 container->setFrameStyle( m_listView->frameStyle() );
636 //container->setMargin( 5 );
637 container->setBackgroundMode( Qt::PaletteBase );
639 m_listView->setFrameStyle( QFrame::NoFrame );
640 connect( m_listView, SIGNAL(executed( Q3ListViewItem* )), SLOT(activate( Q3ListViewItem* )) );
643 KPushButton *button = new KPushButton( KGuiItem( i18n("&Show Search Panel"), "find" ), this );
644 button->setToggleButton( true );
645 connect( button, SIGNAL(toggled( bool )), SLOT(toggle( bool )) );
647 m_lister = new MyDirLister( true /*delay mimetypes*/ );
648 insertChild( m_lister );
649 connect( m_lister, SIGNAL(newItems( const KFileItemList& )), SLOT(searchMatches( const KFileItemList& )) );
650 connect( m_lister, SIGNAL(completed()), SLOT(searchComplete()) );
653 void
654 SearchPane::toggle( bool toggled )
656 if ( toggled )
657 m_lineEdit->setFocus();
659 findChild<QWidget*>("container")->setShown( toggled );
662 void
663 SearchPane::urlChanged( const KUrl& )
665 searchTextChanged( m_lineEdit->text() );
668 void
669 SearchPane::searchTextChanged( const QString &text )
671 //TODO if user changes search directory then we need to update the search too
673 m_lister->stop();
674 m_listView->clear();
675 m_dirs.clear();
677 if ( text.isEmpty() ) {
678 m_listView->unsetText();
679 return;
682 m_filter = QRegExp( text.contains( "*" ) ? text : '*'+text+'*', false, true );
684 m_lister->openUrl( searchURL() );
686 m_listView->setText( i18n( "Searching..." ) );
689 void
690 SearchPane::searchMatches( const KFileItemList &list )
692 for( KFileItemList::ConstIterator it = list.begin(), end = list.end(); it != end; ++it ) {
693 if( (*it)->isDir() )
694 m_dirs += (*it)->url();
695 else if( m_filter.exactMatch( (*it)->name() ) )
696 new KURLView::Item( (*it)->url(), static_cast<KURLView*>( m_listView ) );
700 void
701 SearchPane::searchComplete()
703 //KDirLister crashes if you call openUrl() from a slot
704 //connected to KDirLister::complete()
705 //TODO fix crappy KDElibs
707 QTimer::singleShot( 0, this, SLOT(_searchComplete()) );
710 void
711 SearchPane::_searchComplete()
713 if ( !m_dirs.isEmpty() ) {
714 KUrl url = m_dirs.first();
715 m_dirs.pop_front();
716 m_lister->openUrl( url );
718 else
719 m_listView->setText( i18n("No results found") ); //only displayed if the listview is empty
722 void
723 SearchPane::activate( Q3ListViewItem *item )
725 Playlist::instance()->insertMedia( static_cast<KURLView::Item*>(item)->m_url, Playlist::DirectPlay );
728 #include "filebrowser.moc"