Revert previous commit, was incorrect
[amarok.git] / src / filebrowser.cpp
blobe10daa5707a360836349258b910fe3850ae0547f
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 "kbookmarkhandler.h"
33 #include "MainWindow.h"
34 #include "mediabrowser.h"
35 #include "medium.h"
36 #include "mydirlister.h"
37 #include "mydiroperator.h"
39 #include "playlist/PlaylistModel.h"
40 #include "ContextStatusBar.h"
41 #include "tagdialog.h"
42 #include "TheInstances.h"
44 #include <k3listview.h>
45 #include <k3urldrag.h>
46 #include <KAction>
47 #include <KActionMenu>
48 #include <KActionCollection>
49 #include <KConfigGroup>
50 #include <KDirOperator>
51 #include <KHBox>
52 #include <KIconLoader>
53 #include <KIO/NetAccess>
54 #include <KLineEdit>
55 #include <KLocale>
56 #include <KMenu>
57 #include <KPushButton> ///@see SearchPane
58 #include <KUrlComboBox> ///@see ctor
59 #include <KUrlCompletion>
61 #include <q3iconview.h>
62 #include <QAbstractItemView>
63 #include <QDir>
64 #include <QLabel>
65 #include <QTimer>
66 #include <QToolButton>
67 #include <QToolTip>
70 //BEGIN Constructor/destructor
72 FileBrowser::FileBrowser( const char * name, Medium * medium )
73 : KVBox( 0 )
75 KActionCollection *actionCollection;
76 SearchPane *searchPane;
77 setObjectName( name );
79 KUrl location;
81 // Try to keep filebrowser working even if not in a medium context
82 // so if a medium object not passed in, keep earlier behavior
83 if (!medium) {
84 m_medium = 0;
85 location = KUrl( Amarok::config( "Filebrowser" ).readEntry( "Location", QDir::homePath() ) );
86 KFileItem *currentFolder = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, location );
87 //KIO sucks, NetAccess::exists puts up a dialog and has annoying error message boxes
88 //if there is a problem so there is no point in using it anyways.
89 //so... setting the diroperator to ~ is the least sucky option
90 if ( !location.isLocalFile() || !currentFolder->isReadable() ) {
91 location = KUrl( QDir::homePath() ) ;
94 else{
95 m_medium = medium;
96 location = KUrl( m_medium->mountPoint() );
99 KActionCollection* ac = new KActionCollection( this );
100 KStandardAction::selectAll( this, SLOT( selectAll() ), ac );
102 KToolBar *toolbar = new Browser::ToolBar( this );
103 toolbar->setToolButtonStyle( Qt::ToolButtonIconOnly );
105 { //Filter LineEdit
106 // KToolBar* searchToolBar = new Browser::ToolBar( this );
108 m_filter = new KLineEdit( 0 );
109 toolbar->addWidget(m_filter);
110 m_filter->setClearButtonShown( true );
111 m_filter->setClickMessage( i18n( "Enter search terms here" ) );
113 m_filter->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);
115 m_filter->setToolTip( i18n( "Enter space-separated terms to search in the directory-listing" ) );
118 { //Directory Listing
119 KVBox *container; KHBox *box;
121 container = new KVBox( this );
122 container->setFrameStyle( m_filter->frameStyle() );
123 container->setMargin( 3 );
124 container->setSpacing( 2 );
125 container->setBackgroundMode( Qt::PaletteBase );
127 box = new KHBox( container );
128 box->setMargin( 3 );
129 box->setBackgroundMode( Qt::PaletteBase );
131 //folder selection combo box
132 m_combo = new KUrlComboBox( KUrlComboBox::Directories, true, box );
133 m_combo->setObjectName( "path combo" );
135 if (!m_medium){
136 m_combo->setCompletionObject( new KUrlCompletion( KUrlCompletion::DirCompletion ) );
137 m_combo->setAutoDeleteCompletionObject( true );
139 m_combo->setMaxItems( 9 );
140 m_combo->setUrls( Amarok::config( "Filebrowser" ).readEntry( "Dir History", QStringList() ) );
142 if (!m_medium)
143 m_combo->lineEdit()->setText( location.path() );
144 else
145 m_combo->lineEdit()->setText( "/" );
147 //The main widget with file listings and that
148 m_dir = new MyDirOperator( location, container, m_medium );
149 m_dir->setEnableDirHighlighting( true );
150 m_dir->setMode( KFile::Mode((int)KFile::Files | (int)KFile::Directory) ); //allow selection of multiple files + dirs
151 m_dir->setOnlyDoubleClickSelectsFiles( true ); //Amarok type settings
152 KConfigGroup cg(Amarok::config( "Filebrowser" ));
153 m_dir->readConfig( cg );
154 m_dir->setView( KFile::Default ); //will set userconfigured view, will load URL
155 m_dir->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding );
156 m_dir->setAcceptDrops( true );
157 //Automatically open folder after hovering above it...probably a good thing
158 //but easily disabled by commenting this line out
159 //Disabled for now because can't show . and .. folders.
160 //TODO: Find out a way to fix this?
161 //m_dir->setDropOptions( KFileView::AutoOpenDirs );
163 #if 0 // TODO port
164 static_cast<QFrame*>(m_dir->viewWidget())->setFrameStyle( QFrame::NoFrame );
165 static_cast<Q3IconView*>(m_dir->viewWidget())->setSpacing( 1 );
166 #endif
168 actionCollection = m_dir->actionCollection();
170 searchPane = new SearchPane( this );
172 setStretchFactor( container, 2 );
176 KMenu* const menu = static_cast<KActionMenu*>(actionCollection->action("popupMenu"))->menu();
178 menu->clear();
179 m_createPlaylistAction = menu->addAction( KIcon( Amarok::icon( "files" ) ), i18n( "&Load" ), this, SLOT( slotCreatePlaylist() ) );
181 menu->addAction( KIcon( Amarok::icon( "add_playlist" ) ), i18n( "&Append to Playlist" ), this, SLOT( slotAppendToPlaylist() ) );
183 m_queueTracksAction = menu->addAction( KIcon( Amarok::icon( "queue_track" ) ), i18n( "&Queue Track" ), this, SLOT( slotQueueTrack() ) );
185 menu->addAction( KIcon( Amarok::icon( "save" ) ), i18n( "&Save as Playlist..." ), this, SLOT( slotSavePlaylist() ) );
186 menu->addSeparator();
188 m_mediaDeviceAction = 0; // sanity
189 if( !m_medium )
190 m_mediaDeviceAction = menu->addAction( KIcon( Amarok::icon( "device" ) ), i18n( "&Transfer to Media Device" ), this, SLOT( slotMediaDevice() ) );
192 m_organizeFilesAction = menu->addAction( KIcon( Amarok::icon( "collection" ) ), i18n( "&Organize Files..." ), this, SLOT( slotOrganizeFiles() ) );
193 m_copyToCollectionAction = menu->addAction( KIcon( Amarok::icon( "collection" ) ), i18n( "&Copy Files to Collection..." ), this, SLOT( slotCopyToCollection() ) );
194 m_moveToCollectionAction = menu->addAction( KIcon( Amarok::icon( "collection" ) ), i18n( "&Move Files to Collection..." ), this, SLOT( slotMoveToCollection() ) );
196 QAction *burnAction = menu->addAction( KIcon( Amarok::icon( "burn" ) ), i18n("Burn to CD..."), this, SLOT( slotBurnCd() ) );
197 // burnAction->setEnabled( K3bExporter::isAvailable() );
199 menu->addSeparator();
200 menu->addAction( i18n( "&Select All Files" ), this, SLOT( selectAll() ) );
201 menu->addSeparator();
203 QAction *deleteAction = actionCollection->action( "delete" );
204 deleteAction->setIcon( KIcon( Amarok::icon( "remove" ) ) );
205 menu->addAction( deleteAction );
207 menu->addSeparator();
208 menu->addAction( KIcon( Amarok::icon( "info" ) ), i18nc( "[only-singular]", "Edit Track &Information..." ), this, SLOT( slotEditTags() ) );
209 menu->addAction( actionCollection->action( "properties" ) );
211 connect( menu, SIGNAL(aboutToShow()), SLOT(prepareContextMenu()) );
215 KActionMenu *a;
217 a = static_cast<KActionMenu*>( actionCollection->action( "sorting menu" ) );
218 a->setIcon( KIcon( Amarok::icon( "configure" ) ) );
219 a->setDelayed( false ); //TODO should be done by KDirOperator
221 static_cast<KAction*>(actionCollection->action( "delete" ))->setShortcut( KShortcut( Qt::ShiftModifier + Qt::Key_Delete ) );
223 a = new KActionMenu( this );
225 a->setText( i18n("Bookmarks") );
226 a->setIcon(KIcon("bookmark-toolbar"));
227 actionCollection->addAction( "bookmarks", a );
229 a->setDelayed( false );
231 new KBookmarkHandler( m_dir, a->menu() );
235 if ( QAction *a = actionCollection->action( "up" ) )
236 toolbar->addAction(a);
237 if ( QAction *a = actionCollection->action( "back" ) )
238 toolbar->addAction(a);
239 if ( QAction *a = actionCollection->action( "forward" ) )
240 toolbar->addAction(a);
241 if ( QAction *a = actionCollection->action( "home" ) )
242 toolbar->addAction(a);
243 if ( QAction *a = actionCollection->action( "reload" ) ) {
244 a->setIcon( KIcon(Amarok::icon( "refresh" )) );
245 toolbar->addAction(a);
248 toolbar->addSeparator();
250 if ( QAction *a = actionCollection->action( "short view" ) )
251 toolbar->addAction(a);
252 if ( QAction *a = actionCollection->action( "detailed view" ) )
253 toolbar->addAction(a);
255 toolbar->addSeparator();
257 if ( QAction *a = actionCollection->action( "sorting menu" ) )
258 toolbar->addAction(a);
259 if ( QAction *a = actionCollection->action( "bookmarks" ) )
260 toolbar->addAction(a);
263 KAction *gotoCurrent = new KAction( i18n("Go To Current Track Folder"), this );
264 actionCollection->addAction("Go To Current Track Folder", gotoCurrent);
265 gotoCurrent->setIcon( KIcon(Amarok::icon( "music" )) );
266 connect( gotoCurrent, SIGNAL( triggered() ), this, SLOT( gotoCurrentFolder() ) );
268 toolbar->addAction(gotoCurrent);
270 //disconnect( actionCollection->action( "up" ), SIGNAL( triggered() ), m_dir, SLOT( cdUp() ) );
271 //connect( actionCollection->action( "up" ), SIGNAL( triggered() ), m_dir, SLOT( myCdUp() ) );
272 //disconnect( actionCollection->action( "home" ), SIGNAL( triggered() ), m_dir, SLOT( home() ) );
273 //connect( actionCollection->action( "home" ), SIGNAL( triggered() ), m_dir, SLOT( myHome() ) );
276 connect( m_filter, SIGNAL(textChanged( const QString& )), SLOT(setFilter( const QString& )) );
277 connect( m_combo, SIGNAL(urlActivated( const KUrl& )), SLOT(setUrl( const KUrl& )) );
278 connect( m_combo, SIGNAL(returnPressed( const QString& )), SLOT(setUrl( const QString& )) );
279 connect( m_dir, SIGNAL(viewChanged( KFileView* )), SLOT(slotViewChanged( KFileView* )) );
280 connect( m_dir, SIGNAL(fileSelected( const KFileItem* )), SLOT(activate( const KFileItem* )) );
281 connect( m_dir, SIGNAL(urlEntered( const KUrl& )), SLOT(urlChanged( const KUrl& )) );
282 connect( m_dir, SIGNAL(urlEntered( const KUrl& )), searchPane, SLOT(urlChanged( const KUrl& )) );
283 connect( m_dir, SIGNAL(dropped( const KFileItem*, QDropEvent*, const KUrl::List& )),
284 SLOT(dropped( const KFileItem*, QDropEvent*, const KUrl::List& )) );
286 setSpacing( 4 );
287 setFocusProxy( m_dir ); //so the dirOperator is focused when we get focus events
288 // Toolbar is more than 250px wide, SideBar doesn't allow that. -> Resizing issues.
289 setMinimumWidth( 250 /* toolbar->sizeHint().width() */ );
293 FileBrowser::~FileBrowser()
295 KConfigGroup c = Amarok::config( "Filebrowser" );
297 c.writeEntry( "Location", m_dir->url().url() );
298 c.writeEntry( "Dir History", m_combo->urls() );
301 //END Constructor/Destructor
303 void FileBrowser::setUrl( const KUrl &url )
305 m_dir->setFocus();
306 if (!m_medium)
307 m_dir->setUrl( url, true );
308 else {
309 QString urlpath = url.isLocalFile() ? url.path() : url.prettyUrl();
310 KUrl newURL( urlpath.prepend( m_medium->mountPoint() ).remove("..") );
311 //debug() << "set-url-kurl: changing to: " << newURL.path();
312 m_dir->setUrl( newURL, true );
316 void FileBrowser::setUrl( const QString &url )
318 if (!m_medium)
319 m_dir->setUrl( KUrl(url), true );
320 else{
321 KUrl newURL( QString(url).prepend( m_medium->mountPoint() ).remove("..") );
322 //debug() << "set-url-qstring: changing to: " << newURL.path();
323 m_dir->setUrl( newURL, true );
327 //BEGIN Private Methods
329 Meta::TrackList FileBrowser::selectedItems()
331 Meta::TrackList list;
333 KFileItemList source;
334 if ( m_dir->selectedItems().count() )
335 source = m_dir->selectedItems();
336 else {
337 //FIXME: not that simplw to do with the new api
338 //get all items... DF: you can get them from the KDirLister
339 //source = m_dir->view()->model()->items();
342 for( KFileItemList::const_iterator it = source.begin(); it != source.end(); ++it )
343 list.append( CollectionManager::instance()->trackForUrl( (*it).url() ) );
345 return list;
348 void FileBrowser::playlistFromURLs( const KUrl::List &urls )
350 QString suggestion;
351 if( urls.count() == 1 && QFileInfo( urls.first().path() ).isDir() )
352 suggestion = urls.first().fileName();
353 else
354 suggestion = i18n( "Untitled" );
355 //PORT 2.0 const QString path = PlaylistDialog::getSaveFileName( suggestion );
356 // if( path.isEmpty() )
357 // return;
359 //PORT 2.0 if( PlaylistBrowser::savePlaylist( path, urls ) )
360 // {
361 // Amarok::ContextStatusBar::instance()->shortMessage( "Playlist saved to playlist browser" );
362 // }
366 //END Private Methods
369 //BEGIN Public Slots
371 void
372 FileBrowser::setFilter( const QString &text )
374 if ( text.isEmpty() )
375 m_dir->clearFilter();
377 else {
378 QString filter;
380 const QStringList terms = text.split( ' ', QString::SkipEmptyParts );
381 foreach( QString it, terms )
383 filter += '*';
384 filter += it;
386 filter += '*';
388 m_dir->setNameFilter( filter );
391 m_dir->updateDir();
394 void
395 FileBrowser::dropped( const KFileItem* /*item*/, QDropEvent* event, const KUrl::List &urls)
397 //Do nothing right now
398 event->ignore();
399 //Run into const problems iterating over the list, so copy it to a malleable one
400 //(besides, need to filter for local giles)
401 KUrl::List list(urls);
403 for ( KUrl::List::iterator it = list.begin(); it != list.end(); ){
404 if ( m_medium && !(*it).isLocalFile() )
405 it = list.erase( it );
406 else{
407 debug() << "Dropped: " << (*it);
408 it++;
413 //END Public Slots
416 //BEGIN Private Slots
418 inline void
419 FileBrowser::urlChanged( const KUrl &u )
421 //the DirOperator's URL has changed
423 QString url = u.isLocalFile() ? u.path() : u.prettyUrl();
425 if( m_medium ){
426 //remove the leading mountPoint value
427 url.remove( 0, m_medium->mountPoint().length() );
430 QStringList urls = m_combo->urls();
431 urls.removeAll( url );
432 urls.prepend( url );
434 m_combo->setUrls( urls, KUrlComboBox::RemoveBottom );
437 inline void
438 FileBrowser::slotViewChanged( KFileView *view )
440 if( view->widget()->inherits( "K3ListView" ) )
442 using namespace Amarok::ColorScheme;
444 static_cast<K3ListView*>(view->widget())->setAlternateBackground( AltBase );
448 inline void
449 FileBrowser::activate( const KFileItem *item )
451 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( item->url() );
452 The::playlistModel()->insertOptioned( track, Playlist::AppendAndPlay );
455 inline void
456 FileBrowser::prepareContextMenu()
458 const KFileItemList items = m_dir->selectedItems();
459 // m_createPlaylistAction->setVisible( items.count() > 1 || ( items.count() == 1 && items.first().isDir() ) );
461 if( items.count() == 1 )
462 m_queueTracksAction->setText( i18n( "Queue Track" ) );
463 else if( items.count() > 1 )
464 m_queueTracksAction->setText( i18n( "Queue Tracks" ) );
466 m_queueTracksAction->setVisible( items.count() > 0 );
467 m_mediaDeviceAction->setVisible( MediaBrowser::isAvailable() );
468 m_copyToCollectionAction->setVisible( CollectionDB::instance()->isDirInCollection( url().path() ) );
469 m_moveToCollectionAction->setVisible( CollectionDB::instance()->isDirInCollection( url().path() ) );
470 m_organizeFilesAction->setVisible( CollectionDB::instance()->isDirInCollection( url().path() ) );
473 inline void
474 FileBrowser::slotCreatePlaylist()
476 The::playlistModel()->insertOptioned( selectedItems(), Playlist::Replace );
479 inline void
480 FileBrowser::slotSavePlaylist()
482 //PORT 2.0 playlistFromURLs( selectedItems() );
485 inline void
486 FileBrowser::slotAppendToPlaylist()
488 The::playlistModel()->insertOptioned( selectedItems(), Playlist::Append );
491 inline void
492 FileBrowser::slotQueueTracks()
494 The::playlistModel()->insertOptioned( selectedItems(), Playlist::Queue );
497 inline void
498 FileBrowser::slotEditTags()
501 KUrl::List list = Amarok::recursiveUrlExpand( selectedItems() );
502 TagDialog *dialog = 0;
504 if( list.count() == 1 )
505 dialog = new TagDialog( list.first(), this );
506 else
507 dialog = new TagDialog( list, this );
508 dialog->show();
512 inline void
513 FileBrowser::slotCopyToCollection()
515 //PORT 2.0 CollectionView::instance()->organizeFiles( selectedItems(), i18n( "Copy Files To Collection" ), true );
518 inline void
519 FileBrowser::slotMoveToCollection()
521 //PORT 2.0 CollectionView::instance()->organizeFiles( selectedItems(), i18n( "Move Files To Collection" ), false );
524 inline void
525 FileBrowser::slotOrganizeFiles()
527 //PORT 2.0 CollectionView::instance()->organizeFiles( selectedItems(), i18n( "Organize Collection Files" ), false );
530 inline void
531 FileBrowser::slotMediaDevice()
533 //PORT 2.0 MediaBrowser::queue()->addUrls( selectedItems() );
536 inline void
537 FileBrowser::slotBurnCd()
539 //PORT 2.0 K3bExporter::instance()->exportTracks( selectedItems() );
542 inline void
543 FileBrowser::gotoCurrentFolder()
545 Meta::TrackPtr track = EngineController::instance()->currentTrack();
546 if( !track )
547 return;
548 const KUrl &url = track->playableUrl();
549 KUrl dirURL = KUrl( url.directory() );
551 m_combo->setUrl( dirURL );
552 setUrl( dirURL );
555 //END Private Slots
557 void
558 FileBrowser::selectAll()
561 //FIME: B0rked with the new KDirOpperator API
562 /*KFileItemList list( *m_dir->view()->items() );
564 // Select all items which represent files
565 for( KFileItemList::const_iterator it = list.begin(); it != list.end(); ++it)
566 m_dir->view()->setSelected( *it, (*it)->isFile() );
570 #include <QPainter>
571 #include <q3simplerichtext.h>
573 class KURLView : public K3ListView
575 public:
576 KURLView( QWidget *parent ) : K3ListView( parent )
578 reinterpret_cast<QWidget*>(header())->hide();
579 addColumn( QString() );
580 setResizeMode( K3ListView::LastColumn );
581 setDragEnabled( true );
582 setSelectionMode( Q3ListView::Extended );
585 class Item : public K3ListViewItem {
586 public:
587 Item( const KUrl &url, KURLView *parent ) : K3ListViewItem( parent, url.fileName() ), m_url( url ) {}
588 KUrl m_url;
591 virtual Q3DragObject *dragObject()
593 QList<Q3ListViewItem*> items = selectedItems();
594 KUrl::List urls;
595 for( QList<Q3ListViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it) {
596 urls += ( static_cast<Item*>(*it) )->m_url;
599 return new K3URLDrag( urls, this );
602 virtual void viewportPaintEvent( QPaintEvent *e )
604 K3ListView::viewportPaintEvent( e );
606 if ( childCount() == 0 ) {
607 QPainter p( viewport() );
609 if ( m_text.isEmpty() ) {
610 //TODO Perhaps it's time to put this in some header, as we use it in three places now
611 Q3SimpleRichText t( i18n(
612 "<div align=center>"
613 "Enter a search term above; you can use wildcards like * and ?"
614 "</div>" ), font() );
616 t.setWidth( width() - 50 );
618 const uint w = t.width() + 20;
619 const uint h = t.height() + 20;
621 p.setBrush( colorGroup().background() );
622 p.drawRoundRect( 15, 15, w, h, (8*200)/w, (8*200)/h );
623 t.draw( &p, 20, 20, QRect(), colorGroup() );
625 else {
626 p.setPen( palette().color( QPalette::Disabled, QColorGroup::Text ) );
627 p.drawText( rect(), Qt::AlignCenter | Qt::TextWordWrap, m_text );
632 void unsetText() { setText( QString() ); }
633 void setText( const QString &text ) { m_text = text; viewport()->update(); }
635 private:
636 QString m_text;
641 SearchPane::SearchPane( FileBrowser *parent )
642 : KVBox( parent )
643 , m_lineEdit( 0 )
644 , m_listView( 0 )
645 , m_lister( 0 )
647 KVBox *container = new KVBox( this );
648 container->setObjectName( "container" );
649 container->hide();
652 KHBox *box = new KHBox( container );
653 //box->setMargin( 5 );
654 box->setBackgroundMode( Qt::PaletteBase );
656 m_lineEdit = new KLineEdit( box );
657 m_lineEdit->setClickMessage( i18n("Search here...") );
658 connect( m_lineEdit, SIGNAL(textChanged( const QString& )), SLOT(searchTextChanged( const QString& )) );
660 m_listView = new KURLView( container );
662 container->setFrameStyle( m_listView->frameStyle() );
663 //container->setMargin( 5 );
664 container->setBackgroundMode( Qt::PaletteBase );
666 m_listView->setFrameStyle( QFrame::NoFrame );
667 connect( m_listView, SIGNAL(executed( Q3ListViewItem* )), SLOT(activate( Q3ListViewItem* )) );
670 KPushButton *button = new KPushButton( KGuiItem( i18n("&Show Search Panel"), "find" ), this );
671 button->setToggleButton( true );
672 connect( button, SIGNAL(toggled( bool )), SLOT(toggle( bool )) );
674 m_lister = new MyDirLister( true /*delay mimetypes*/ );
675 m_lister->setParent( this );
676 connect( m_lister, SIGNAL(newItems( const KFileItemList& )), SLOT(searchMatches( const KFileItemList& )) );
677 connect( m_lister, SIGNAL(completed()), SLOT(searchComplete()) );
680 void
681 SearchPane::toggle( bool toggled )
683 if ( toggled )
684 m_lineEdit->setFocus();
686 findChild<QWidget*>("container")->setVisible( toggled );
689 void
690 SearchPane::urlChanged( const KUrl& )
692 searchTextChanged( m_lineEdit->text() );
695 void
696 SearchPane::searchTextChanged( const QString &text )
698 //TODO if user changes search directory then we need to update the search too
700 m_lister->stop();
701 m_listView->clear();
702 m_dirs.clear();
704 if ( text.isEmpty() ) {
705 m_listView->unsetText();
706 return;
709 m_filter = QRegExp( text.contains( "*" ) ? text : '*'+text+'*', false, true );
711 m_lister->openUrl( searchURL() );
713 m_listView->setText( i18n( "Searching..." ) );
716 void
717 SearchPane::searchMatches( const KFileItemList &list )
719 for( KFileItemList::ConstIterator it = list.begin(), end = list.end(); it != end; ++it ) {
720 if( (*it).isDir() )
721 m_dirs += (*it).url();
722 else if( m_filter.exactMatch( (*it).name() ) )
723 new KURLView::Item( (*it).url(), static_cast<KURLView*>( m_listView ) );
727 void
728 SearchPane::searchComplete()
730 //KDirLister crashes if you call openUrl() from a slot
731 //connected to KDirLister::complete()
732 //TODO fix crappy KDElibs
734 QTimer::singleShot( 0, this, SLOT(_searchComplete()) );
737 void
738 SearchPane::_searchComplete()
740 if ( !m_dirs.isEmpty() ) {
741 KUrl url = m_dirs.first();
742 m_dirs.pop_front();
743 m_lister->openUrl( url );
745 else
746 m_listView->setText( i18n("No results found") ); //only displayed if the listview is empty
749 void
750 SearchPane::activate( Q3ListViewItem *item )
752 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( static_cast<KURLView::Item*>(item)->m_url );
753 The::playlistModel()->insertOptioned( track, Playlist::DirectPlay );
756 #include "filebrowser.moc"