'Pluginize' Ampache
[amarok.git] / src / MainWindow.cpp
blob8c1235cd775a3c60c0da41f1def77ab756794e9b
1 /***************************************************************************
2 begin : Fre Nov 15 2002
3 copyright : (C) Mark Kretschmann <markey@web.de>
4 : (C) Max Howell <max.howell@methylblue.com>
5 : (C) G??bor Lehel <illissius@gmail.com>
6 ***************************************************************************/
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
17 #include "config-amarok.h" //HAVE_LIBVISUAL definition
19 #include "actionclasses.h" //see toolbar construction
20 #include "amarokconfig.h"
21 #include "amarok.h"
22 #include "analyzerwidget.h"
23 #include "collection/CollectionManager.h"
24 #include "collectionbrowser/CollectionWidget.h"
25 #include "context/CoverBling.h"
26 #include "context/ContextView.h"
27 #include "context/DataEngineManager.h"
28 #include "covermanager.h" // for actions
29 #include "debug.h"
30 #include "editfilterdialog.h"
31 #include "enginecontroller.h" //for actions in ctor
32 #include "filebrowserwidget.h"
33 #include "k3bexporter.h"
34 #include "lastfm.h" //check credentials when adding lastfm streams
35 #include "MainWindow.h"
36 #include "mediabrowser.h"
37 #include "playlist/PlaylistModel.h"
38 #include "playlist/PlaylistWidget.h"
39 #include "progressslider.h"
40 #include "scriptmanager.h"
41 #include "searchwidget.h"
42 #include "servicebrowser/ServicePluginManager.h"
43 #include "servicebrowser/scriptableservice/scriptableservice.h"
44 #include "servicebrowser/servicebrowser.h"
45 #include "servicebrowser/shoutcast/ShoutcastService.h"
46 #include "servicebrowser/mp3tunes/mp3tunesservice.h"
47 #include "Sidebar.h"
48 #include "Sidebar.moc"
49 #include "socketserver.h"
50 #include "Statistics.h"
51 #include "ContextStatusBar.h"
52 #include "TheInstances.h"
53 #include "threadmanager.h"
54 #include "volumewidget.h"
55 #include "PodcastCollection.h"
56 #include "playlistmanager/PlaylistManager.h"
58 #include "playlistbrowser/PlaylistBrowser.h"
60 #include "queuemanager/QueueManager.h"
62 #include <QFont>
63 #include <QHeaderView>
64 #include <QLabel> //search filter label
65 #include <QList>
66 #include <QPaintEngine>
67 #include <QPainter> //dynamic title
68 #include <QPen>
69 #include <QTimer> //search filter timer
70 #include <QToolTip> //QToolTip::add()
71 #include <QVBoxLayout>
73 #include <KAction> //m_actionCollection
74 #include <KActionCollection>
75 #include <KActionMenu>
76 #include <kapplication.h> //kapp
77 #include <kfiledialog.h> //savePlaylist(), openPlaylist()
78 #include <kglobal.h>
79 #include <kinputdialog.h> //slotAddStream()
80 #include <klocale.h>
81 #include <kmenubar.h>
82 #include <kmessagebox.h> //savePlaylist()
83 #include <kmenu.h>
84 #include <kpushbutton.h>
85 #include <ktoolbar.h>
86 #include <fixx11h.h>
88 class ContextWidget : public KVBox
90 // Set a useful size default of the center tab.
91 public:
92 ContextWidget( QWidget *parent ) : KVBox( parent ) {}
93 QSize sizeHint() const { return QSize( 400, 300 ); }
96 MainWindow *MainWindow::s_instance = 0;
98 MainWindow::MainWindow()
99 :KXmlGuiWindow( 0, Qt::WGroupLeader )
100 , m_lastBrowser( 0 )
102 setObjectName("MainWindow");
103 s_instance = this;
105 new Playlist::Model( this );
107 // Sets caption and icon correctly (needed e.g. for GNOME)
108 kapp->setTopWidget( this );
110 createActions();
112 //new K3bExporter();
114 if( AmarokConfig::mainWindowSize().isValid() )
116 // if first ever run, use sizeHint(), and let
117 // KWindowSystem place us otherwise use the stored values
118 resize( AmarokConfig::mainWindowSize() );
119 move( AmarokConfig::mainWindowPos() );
121 m_browsers = new SideBar( this, new KVBox );
124 MainWindow::~MainWindow()
126 DEBUG_BLOCK
127 AmarokConfig::setMainWindowPos( pos() ); //TODO de XT?
128 AmarokConfig::setMainWindowSize( size() ); //TODO de XT?
132 ///////// public interface
135 * This function will initialize the playlist window.
137 void MainWindow::init()
139 layout()->setContentsMargins( 0, 0, 0, 0 );
140 DEBUG_BLOCK
142 //this function is necessary because Amarok::actionCollection() returns our actionCollection
143 //via the App::m_pMainWindow pointer since App::m_pMainWindow is not defined until
144 //the above ctor returns it causes a crash unless we do the initialisation in 2 stages.
145 Playlist::Widget *playlistWidget = new Playlist::Widget( this );
148 m_controlBar = new MainToolbar( this );
149 m_controlBar->setMaximumSize( 20000, 62 );
150 m_controlBar->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
152 AnalyzerWidget *aw = new AnalyzerWidget( m_controlBar );
153 aw->setMinimumSize( 200, 30 );
155 m_controlBar->layout()->setAlignment( aw, Qt::AlignLeft );
157 KVBox *aVBox = new KVBox( m_controlBar );
158 aVBox->setMaximumSize( 50000, 60 );
160 KHBox *insideBox = new KHBox( aVBox );
161 insideBox->setMaximumSize( 600000, 45 );
163 KToolBar *playerControlsToolbar = new Amarok::ToolBar( insideBox );
165 playerControlsToolbar->setMinimumSize( 180, 45 );
166 insideBox->layout()->setAlignment( playerControlsToolbar, Qt::AlignCenter );
168 QWidget * spacer = new QWidget( m_controlBar );
169 spacer->setMinimumSize( 50, 30 );
170 m_controlBar->layout()->setAlignment( spacer, Qt::AlignRight );
172 VolumeWidget *vw = new VolumeWidget( m_controlBar );
173 vw->setMinimumSize( 150, 30 );
174 m_controlBar->layout()->setAlignment( vw, Qt::AlignRight | Qt::AlignVCenter);
176 ProgressWidget *pWidget = new ProgressWidget( aVBox );
177 pWidget->setMinimumSize( 400, 17 );
178 pWidget->setMaximumSize( 600000, 17 );
180 playerControlsToolbar->setToolButtonStyle( Qt::ToolButtonIconOnly );
181 playerControlsToolbar->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
182 playerControlsToolbar->setIconDimensions( 32 );
183 playerControlsToolbar->setMovable( false );
184 playerControlsToolbar->addAction( actionCollection()->action( "prev" ) );
185 playerControlsToolbar->addAction( actionCollection()->action( "play_pause" ) );
186 playerControlsToolbar->addAction( actionCollection()->action( "stop" ) );
187 playerControlsToolbar->addAction( actionCollection()->action( "next" ) );
190 QPalette p;
191 QColor bottomColor;
192 QColor topColor = bottomColor = palette().highlight().color().dark( 150 );
193 bottomColor = bottomColor.dark( 100 );
194 topColor.setAlpha( 75 );
195 bottomColor.setAlpha( 130 );
197 createMenus();
199 ContextWidget *contextWidget = new ContextWidget( this );
200 contextWidget->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
201 new Context::ContextView( contextWidget );
203 new Amarok::ContextStatusBar( contextWidget );
205 if( AmarokConfig::useCoverBling() && QGLFormat::hasOpenGL() )
206 new CoverBling( contextWidget );
209 connect( m_browsers, SIGNAL( widgetActivated( int ) ), SLOT( slotShrinkBrowsers( int ) ) );
211 QVBoxLayout *mainLayout = new QVBoxLayout;
212 mainLayout->setContentsMargins( 1, 1, 1, 1 );
214 QWidget *centralWidget = new QWidget( this );
215 centralWidget->setLayout( mainLayout );
217 m_splitter = new QSplitter( Qt::Horizontal, centralWidget );
218 m_splitter->setHandleWidth( 0 );
219 m_splitter->addWidget( m_browsers );
220 m_splitter->addWidget( contextWidget );
221 m_splitter->addWidget( playlistWidget );
223 mainLayout->addWidget( m_controlBar );
224 mainLayout->addWidget( m_splitter );
225 setCentralWidget( centralWidget );
227 //<Browsers>
229 Debug::Block block( "Creating browsers. Please report long start times!" );
231 #define addBrowserMacro( Type, name, text, icon ) { \
232 Debug::Block block( name ); \
233 m_browsers->addWidget( KIcon( icon ), text, new Type( name ) ); \
234 m_browserNames.append( name ); }
236 #define addInstBrowserMacro( Type, name, text, icon ) { \
237 m_browsers->addWidget( KIcon( icon ), text, Type::instance() ); \
238 m_browserNames.append( name ); }
240 addBrowserMacro( CollectionWidget, "CollectionBrowser", i18n("Collection"), Amarok::icon( "collection" ) )
242 addBrowserMacro( PlaylistBrowserNS::PlaylistBrowser, "NeoPlaylistBrowser", i18n("Playlists"), Amarok::icon( "playlist" ) )
244 PodcastCollection *podcastCollection = new PodcastCollection();
245 The::playlistManager()->addProvider( podcastCollection->channelProvider(), PlaylistManager::PodcastChannel );
247 addBrowserMacro( FileBrowserWidget, "FileBrowserWidget", i18n("Files"), Amarok::icon( "files" ) );
249 //DEBUG: Comment out the addBrowserMacro line and uncomment the m_browsers line (passing in a vfat device name) to see the "virtual root" functionality
253 //FIXME:
254 //addBrowserMacro( FileBrowser, "FileBrowser", i18n("Files"), Amarok::icon( "files" ) )
256 //cant use macros here since we need access to the browsers directly
258 ServiceBrowser * internetContentServiceBrowser = new ServiceBrowser(this, "Internet Content" );;
259 m_browsers->addWidget( KIcon( Amarok::icon( "magnatune" ) ), i18n("Internet"), internetContentServiceBrowser );
260 m_browserNames.append( "Internet" );
263 //create a plugin manager
265 ServicePluginManager * servicePluginManager = new ServicePluginManager( internetContentServiceBrowser );
266 servicePluginManager->init();
268 debug() << "Add me dammit!!!!!";
269 internetContentServiceBrowser->setScriptableServiceManager( new ScriptableServiceManager( 0 ) );
271 //internetContentServiceBrowser->addService( new MagnatuneStore( "Magnatune Store" ) );
273 //internetContentServiceBrowser->addService( new JamendoService( "Jamendo.com" ) );
275 internetContentServiceBrowser->addService( new ShoutcastService( "Shoutcasst Directory" ) );
277 internetContentServiceBrowser->addService( new Mp3tunesService( "Mp3Tunes Locker" ) );
279 //internetContentServiceBrowser->addService( new AmpacheService( "Ampache" ) );
281 new MediaBrowser( "MediaBrowser" );
282 if( MediaBrowser::isAvailable() )
284 addInstBrowserMacro( MediaBrowser, "MediaBrowser", i18n("Devices"), Amarok::icon( "device" ) )
286 #undef addBrowserMacro
287 #undef addInstBrowserMacro
289 //</Browsers>
292 kapp->installEventFilter( this ); // keyboards shortcuts for the browsers
294 Amarok::MessageQueue::instance()->sendMessages();
297 void MainWindow::deleteBrowsers()
299 m_browsers->deleteBrowsers();
302 void MainWindow::slotSetFilter( const QString &filter ) //SLOT
304 Q_UNUSED( filter );
305 // m_lineEdit->setText( filter );
308 void MainWindow::slotShrinkBrowsers( int index ) const
310 // Because QSplitter sucks and will not recompute sizes if a pane is shrunk and not hidden.
311 if( index == -1 )
313 QList<int> sizes;
314 sizes << m_browsers->sideBarWidget()->width()
315 << m_splitter->sizes()[1] + m_splitter->sizes()[0] - m_browsers->sideBarWidget()->width()
316 << m_splitter->sizes()[2];
317 m_splitter->setSizes( sizes );
321 // void MainWindow::slotEditFilter() //SLOT
322 // {
323 // EditFilterDialog *fd = new EditFilterDialog( this, true, "" );
324 // connect( fd, SIGNAL(filterChanged(const QString &)), SLOT(slotSetFilter(const QString &)) );
325 // if( fd->exec() )
326 // m_searchWidget->lineEdit()->setText( fd->filter() );
327 // delete fd;
328 // }
330 void MainWindow::addBrowser( const QString &name, QWidget *browser, const QString &text, const QString &icon )
332 if( !m_browserNames.contains( name ) )
334 m_browsers->addWidget( KIcon(Amarok::icon( icon )), text, browser );
335 m_browserNames.append( name );
339 void MainWindow::showBrowser( const QString &name )
341 const int index = m_browserNames.indexOf( name );
342 if( index >= 0 )
343 m_browsers->showWidget( index );
348 * @param o The object
349 * @param e The event
351 * Here we filter some events for the Playlist Search LineEdit and the Playlist. @n
352 * this makes life easier since we have more useful functions available from this class
354 bool MainWindow::eventFilter( QObject *o, QEvent *e )
356 typedef Q3ListViewItemIterator It;
358 switch( e->type() )
360 case 6/*QEvent::KeyPress*/:
362 //there are a few keypresses that we intercept
364 #define e static_cast<QKeyEvent*>(e)
366 //TODO:PORT ME
367 // if( e->key() == Qt::Key_F2 )
368 // {
369 // // currentItem is ALWAYS visible.
370 // Q3ListViewItem *item = pl->currentItem();
372 // // intercept F2 for inline tag renaming
373 // // NOTE: tab will move to the next tag
374 // // NOTE: if item is still null don't select first item in playlist, user wouldn't want that. It's silly.
375 // // TODO: berkus has solved the "inability to cancel" issue with K3ListView, but it's not in kdelibs yet..
377 // // item may still be null, but this is safe
378 // // NOTE: column 0 cannot be edited currently, hence we pick column 1
379 // pl->rename( item, 1 ); //TODO what if this column is hidden?
381 // return true;
382 // }
385 // if( o == m_searchWidget->lineEdit() ) //the search lineedit
386 // {
387 // Q3ListViewItem *item;
388 // switch( e->key() )
389 // {
390 // case Qt::Key_Up:
391 // case Qt::Key_Down:
392 // case Qt::Key_PageDown:
393 // case Qt::Key_PageUp:
394 // pl->setFocus();
395 // QApplication::sendEvent( pl, e );
396 // return true;
398 // case Qt::Key_Return:
399 // case Qt::Key_Enter:
400 // item = *It( pl, It::Visible );
401 // //m_lineEdit->clear();
402 // pl->m_filtertimer->stop(); //HACK HACK HACK
404 // if( e->modifiers() & Qt::ControlModifier )
405 // {
406 // QList<PlaylistItem*> in, out;
407 // if( e->modifiers() & Qt::ShiftModifier )
408 // for( It it( pl, It::Visible ); PlaylistItem *x = static_cast<PlaylistItem*>( *it ); ++it )
409 // {
410 // pl->queue( x, true );
411 // ( pl->m_nextTracks.contains( x ) ? in : out ).append( x );
412 // }
413 // else
414 // {
415 // It it( pl, It::Visible );
416 // pl->activate( *it );
417 // ++it;
418 // for( int i = 0; PlaylistItem *x = static_cast<PlaylistItem*>( *it ); ++i, ++it )
419 // {
420 // in.append( x );
421 // pl->m_nextTracks.insert( i, x );
422 // }
423 // }
424 // if( !in.isEmpty() || !out.isEmpty() )
425 // emit pl->queueChanged( in, out );
426 // pl->setFilter( "" );
427 // pl->ensureItemCentered( ( e->modifiers() & Qt::ShiftModifier ) ? item : pl->currentTrack() );
428 // }
429 // else
430 // {
431 // pl->setFilter( "" );
432 // if( ( e->modifiers() & Qt::ShiftModifier ) && item )
433 // {
434 // pl->queue( item );
435 // pl->ensureItemCentered( item );
436 // }
437 // else
438 // {
439 // pl->activate( item );
440 // pl->showCurrentTrack();
441 // }
442 // }
443 // return true;
445 // case Qt::Key_Escape:
446 // m_searchWidget->lineEdit()->clear();
447 // return true;
449 // default:
450 // return false;
451 // }
452 // }
454 //following are for Playlist::instance() only
455 //we don't handle these in the playlist because often we manipulate the lineEdit too
457 #undef e
458 break;
460 default:
461 break;
464 return QWidget::eventFilter( o, e );
468 void MainWindow::closeEvent( QCloseEvent *e )
470 #ifdef Q_WS_MAC
471 Q_UNUSED( e );
472 hide();
473 #else
475 //KDE policy states we should hide to tray and not quit() when the
476 //close window button is pushed for the main widget
478 e->accept(); //if we don't do this the info box appears on quit()!
480 if( AmarokConfig::showTrayIcon() && e->spontaneous() && !kapp->sessionSaving() )
482 KMessageBox::information( this,
483 i18n( "<qt>Closing the main-window will keep Amarok running in the System Tray. "
484 "Use <B>Quit</B> from the menu, or the Amarok tray-icon to exit the application.</qt>" ),
485 i18n( "Docking in System Tray" ), "hideOnCloseInfo" );
487 else
488 kapp->quit();
489 #endif
493 void MainWindow::showEvent( QShowEvent* )
495 //PORT 2.0
496 // static bool firstTime = true;
497 // if( firstTime )
498 // Playlist::instance()->setFocus();
499 // firstTime = false;
502 #include <qdesktopwidget.h>
503 QSize MainWindow::sizeHint() const
505 return QApplication::desktop()->screenGeometry( (QWidget*)this ).size() / 1.5;
509 void MainWindow::savePlaylist() const //SLOT
511 QString playlistName = KFileDialog::getSaveFileName();
512 The::playlistModel()->saveM3U( playlistName );
516 void MainWindow::slotBurnPlaylist() const //SLOT
518 K3bExporter::instance()->exportCurrentPlaylist();
521 void MainWindow::slotShowCoverManager() const //SLOT
523 CoverManager::showOnce();
526 void MainWindow::slotPlayMedia() //SLOT
528 // Request location and immediately start playback
529 slotAddLocation( true );
533 void MainWindow::slotAddLocation( bool directPlay ) //SLOT
535 // open a file selector to add media to the playlist
536 KUrl::List files;
537 KFileDialog dlg( KUrl(QString()), QString("*.*|"), this );
538 dlg.setCaption( directPlay ? i18n("Play Media (Files or URLs)") : i18n("Add Media (Files or URLs)") );
539 dlg.setMode( KFile::Files | KFile::Directory );
540 dlg.exec();
541 files = dlg.selectedUrls();
542 if( files.isEmpty() ) return;
543 const int options = directPlay ? Playlist::Append | Playlist::DirectPlay : Playlist::Append;
545 Meta::TrackList tracks = CollectionManager::instance()->tracksForUrls( files );
547 The::playlistModel()->insertOptioned( tracks.takeFirst(), options );
549 foreach( Meta::TrackPtr track, tracks )
551 The::playlistModel()->insertOptioned( track, Playlist::Append );
555 void MainWindow::slotAddStream() //SLOT
557 bool ok;
558 QString url = KInputDialog::getText( i18n("Add Stream"), i18n("URL"), QString(), &ok, this );
560 if ( !ok ) return;
562 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( KUrl( url ) );
564 The::playlistModel()->insertOptioned( track, Playlist::Append|Playlist::DirectPlay );
568 void MainWindow::playLastfmPersonal() //SLOT
570 if( !LastFm::Controller::checkCredentials() ) return;
572 const KUrl url( QString( "lastfm://user/%1/personal" )
573 .arg( AmarokConfig::scrobblerUsername() ) );
575 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( url );
577 The::playlistModel()->insertOptioned( track, Playlist::Append|Playlist::DirectPlay );
581 void MainWindow::addLastfmPersonal() //SLOT
583 if( !LastFm::Controller::checkCredentials() ) return;
585 const KUrl url( QString( "lastfm://user/%1/personal" )
586 .arg( AmarokConfig::scrobblerUsername() ) );
588 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( url );
590 The::playlistModel()->insertOptioned( track, Playlist::Append );
594 void MainWindow::playLastfmNeighbor() //SLOT
596 if( !LastFm::Controller::checkCredentials() ) return;
598 const KUrl url( QString( "lastfm://user/%1/neighbours" )
599 .arg( AmarokConfig::scrobblerUsername() ) );
601 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( url );
603 The::playlistModel()->insertOptioned( track, Playlist::Append );
607 void MainWindow::addLastfmNeighbor() //SLOT
609 if( !LastFm::Controller::checkCredentials() ) return;
611 const KUrl url( QString( "lastfm://user/%1/neighbours" )
612 .arg( AmarokConfig::scrobblerUsername() ) );
614 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( url );
616 The::playlistModel()->insertOptioned( track, Playlist::Append );
620 void MainWindow::playLastfmCustom() //SLOT
622 const QString token = LastFm::Controller::createCustomStation();
623 if( token.isEmpty() ) return;
625 const KUrl url( "lastfm://artist/" + token + "/similarartists" );
626 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( url );
628 The::playlistModel()->insertOptioned( track, Playlist::Append|Playlist::DirectPlay );
632 void MainWindow::addLastfmCustom() //SLOT
634 const QString token = LastFm::Controller::createCustomStation();
635 if( token.isEmpty() ) return;
637 const KUrl url( "lastfm://artist/" + token + "/similarartists" );
638 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( url );
640 The::playlistModel()->insertOptioned( track, Playlist::Append );
644 void MainWindow::playLastfmGlobaltag() //SLOT
646 if( !LastFm::Controller::checkCredentials() ) return;
648 KAction *action = dynamic_cast<KAction*>( sender() );
649 if( !action ) return;
651 const QString tag = action->text();
652 const KUrl url( "lastfm://globaltags/" + tag );
653 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( url );
655 The::playlistModel()->insertOptioned( track, Playlist::Append|Playlist::DirectPlay );
659 void MainWindow::addLastfmGlobaltag() //SLOT
661 if( !LastFm::Controller::checkCredentials() ) return;
663 KAction *action = dynamic_cast<KAction*>( sender() );
664 if( !action ) return;
666 const QString tag = action->text();
667 const KUrl url( "lastfm://globaltags/" + tag );
668 Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( url );
670 The::playlistModel()->insertOptioned( track, Playlist::Append );
674 void MainWindow::playAudioCD() //SLOT
676 KUrl::List urls;
677 if( EngineController::engine()->getAudioCDContents(QString(), urls) )
679 Meta::TrackList tracks = CollectionManager::instance()->tracksForUrls( urls );
680 if( !tracks.isEmpty() )
681 The::playlistModel()->insertOptioned( tracks, Playlist::Replace );
683 else
684 { // Default behaviour
685 showBrowser( "FileBrowser" );
689 void MainWindow::showScriptSelector() //SLOT
691 ScriptManager::instance()->show();
692 ScriptManager::instance()->raise();
695 void MainWindow::showQueueManager() //SLOT
697 if( QueueManagerNS::QueueManager::instance() )
699 QueueManagerNS::QueueManager::instance()->raise();
700 return;
703 QueueManagerNS::QueueManager dialog;
704 if( dialog.exec() == QDialog::Accepted )
706 // TODO: alter queue
710 void MainWindow::showStatistics() //SLOT
712 if( Statistics::instance() ) {
713 Statistics::instance()->raise();
714 return;
716 Statistics dialog;
717 dialog.exec();
720 void MainWindow::slotToggleFocus() //SLOT
722 //Port 2.0
723 // if( m_browsers->currentWidget() && ( Playlist::instance()->hasFocus() /*|| m_searchWidget->lineEdit()->hasFocus()*/ ) )
724 // m_browsers->currentWidget()->setFocus();
727 void MainWindow::slotToggleToolbar() //SLOT
729 m_controlBar->setVisible( !m_controlBar->isHidden() );
730 AmarokConfig::setShowToolbar( !AmarokConfig::showToolbar() );
731 Amarok::actionCollection()->action( "toggle_toolbar" )->setText( !m_controlBar->isHidden() ? i18n("Hide Toolbar") : i18n("Show Toolbar") );
734 void MainWindow::toolsMenuAboutToShow() //SLOT
736 Amarok::actionCollection()->action( "equalizer" )->setEnabled( !EngineController::hasEngineProperty( "HasEqualizer" ) );
737 Amarok::actionCollection()->action( "rescan_collection" )->setEnabled( !ThreadManager::instance()->isJobPending( "CollectionScanner" ) );
741 #include <kwindowsystem.h>
743 * Show/hide playlist global shortcut and PlayerWindow PlaylistButton connect to this slot
744 * RULES:
745 * 1. hidden & iconified -> deiconify & show @n
746 * 2. hidden & deiconified -> show @n
747 * 3. shown & iconified -> deiconify @n
748 * 4. shown & deiconified -> hide @n
749 * 5. don't hide if there is no tray icon or playerWindow. todo (I can't be arsed) @n
751 * @note isMinimized() can only be true if the window isVisible()
752 * this has taken me hours to get right, change at your peril!
753 * there are more contingencies than you can believe
755 void MainWindow::showHide() //SLOT
757 #ifdef Q_WS_X11
758 const KWindowInfo info = KWindowSystem::windowInfo( winId(), 0, 0 );
759 const uint desktop = KWindowSystem::currentDesktop();
760 const bool isOnThisDesktop = info.isOnDesktop( desktop );
761 const bool isShaded = false;
763 if( isShaded )
765 KWindowSystem::clearState( winId(), NET::Shaded );
766 setVisible( true );
769 if( !isOnThisDesktop )
771 KWindowSystem::setOnDesktop( winId(), desktop );
772 setVisible( true );
774 else if( !info.isMinimized() && !isShaded ) setVisible( !isVisible() );
776 if( isVisible() ) KWindowSystem::unminimizeWindow( winId() );
777 #else
778 setVisible( !isVisible() );
779 #endif
782 void MainWindow::activate()
784 #ifdef Q_WS_X11
785 const KWindowInfo info = KWindowSystem::windowInfo( winId(), 0, 0 );
787 if( KWindowSystem::activeWindow() != winId())
788 setVisible( true );
789 else if( !info.isMinimized() )
790 setVisible( true );
791 if( !isHidden() )
792 KWindowSystem::activateWindow( winId() );
793 #else
794 setVisible( true );
795 #endif
798 bool MainWindow::isReallyShown() const
800 #ifdef Q_WS_X11
801 const KWindowInfo info = KWindowSystem::windowInfo( winId(), 0, 0 );
802 return !isHidden() && !info.isMinimized() && info.isOnDesktop( KWindowSystem::currentDesktop() );
803 #else
804 return isHidden();
805 #endif
808 void MainWindow::createActions()
810 KActionCollection* const ac = actionCollection();
811 const EngineController* const ec = EngineController::instance();
813 KStandardAction::keyBindings( kapp, SLOT( slotConfigShortcuts() ), ac );
814 KStandardAction::preferences( kapp, SLOT( slotConfigAmarok() ), ac );
815 ac->action(KStandardAction::name(KStandardAction::KeyBindings))->setIcon( KIcon( Amarok::icon( "configure" ) ) );
816 ac->action(KStandardAction::name(KStandardAction::Preferences))->setIcon( KIcon( Amarok::icon( "configure" ) ) );
818 KStandardAction::quit( kapp, SLOT( quit() ), ac );
820 KAction *action = new KAction( KIcon( Amarok::icon( "files" ) ), i18n("&Add Media..."), this );
821 connect( action, SIGNAL( triggered(bool) ), this, SLOT( slotAddLocation() ) );
822 ac->addAction( "playlist_add", action );
824 action = new KAction( KIcon( Amarok::icon( "playlist_clear" ) ), i18nc( "clear playlist", "&Clear" ), this );
825 connect( action, SIGNAL( triggered( bool ) ), The::playlistModel(), SLOT( clear() ) );
826 ac->addAction( "playlist_clear", action );
828 action = new KAction( KIcon( Amarok::icon( "files" ) ), i18n("&Add Stream..."), this );
829 connect( action, SIGNAL( triggered(bool) ), this, SLOT( slotAddStream() ) );
830 ac->addAction( "stream_add", action );
832 action = new KAction( KIcon( Amarok::icon( "save" ) ), i18n("&Save Playlist As..."), this );
833 connect( action, SIGNAL( triggered(bool) ), this, SLOT( savePlaylist() ) );
834 ac->addAction( "playlist_save", action );
836 KAction *burn = new KAction( KIcon(Amarok::icon( "burn" )), i18n( "Burn Current Playlist" ), this );
837 connect( burn, SIGNAL( triggered(bool) ), SLOT( slotBurnPlaylist() ) );
838 burn->setEnabled( K3bExporter::isAvailable() );
839 ac->addAction( "playlist_burn", burn );
841 KAction *covermanager = new KAction( KIcon(Amarok::icon( "covermanager" )), i18n( "Cover Manager" ), this );
842 connect( covermanager, SIGNAL( triggered(bool) ), SLOT( slotShowCoverManager() ) );
843 ac->addAction( "cover_manager", covermanager );
845 KAction *visuals = new KAction( KIcon( Amarok::icon("visualizations") ), i18n("&Visualizations"), this );
846 // connect( visuals, SIGNAL( triggered(bool) ), Vis::Selector::instance(), SLOT( show() ) );
847 ac->addAction( "visualizations", visuals );
849 KAction *equalizer = new KAction( KIcon( Amarok::icon( "equalizer" ) ), i18n( "E&qualizer"), this );
850 connect( equalizer, SIGNAL( triggered(bool) ), kapp, SLOT( slotConfigEqualizer() ) );
851 ac->addAction( "equalizer", equalizer );
853 KAction *toggleToolbar = new KAction( this );
854 toggleToolbar->setText( i18n("Hide Toolbar") );
856 //FIXME m_controlBar is initialised after the actions are created so we need to change the text of this action
857 //when the menu is shown
858 //toggleToolbar->setText( !m_controlBar->isHidden() ? i18n("Hide Toolbar") : i18n("Show Toolbar") );
859 connect( toggleToolbar, SIGNAL( triggered(bool) ), SLOT( slotToggleToolbar() ) );
860 ac->addAction( "toggle_toolbar", toggleToolbar );
862 // KAction *update_podcasts = new KAction( this );
863 // update_podcasts->setText( i18n( "Update Podcasts" ) );
864 // //update_podcasts->setIcon( KIcon(Amarok::icon( "refresh" )) );
865 // ac->addAction( "podcasts_update", update_podcasts );
866 // connect(update_podcasts, SIGNAL(triggered(bool)),
867 // The::podcastCollection(), SLOT(slotUpdateAll()));
869 KAction *playact = new KAction( KIcon(Amarok::icon( "files" )), i18n("Play Media..."), this );
870 connect(playact, SIGNAL(triggered(bool)), SLOT(slotPlayMedia()));
871 ac->addAction( "playlist_playmedia", playact );
873 KAction *acd = new KAction( KIcon( Amarok::icon( "album" ) ), i18n("Play Audio CD"), this );
874 connect(acd, SIGNAL(triggered(bool)), SLOT(playAudioCD()));
875 ac->addAction( "play_audiocd", acd );
877 KAction *script = new KAction( KIcon(Amarok::icon( "scripts" )), i18n("Script Manager"), this );
878 connect(script, SIGNAL(triggered(bool)), SLOT(showScriptSelector()));
879 ac->addAction( "script_manager", script );
881 KAction *queue = new KAction( KIcon( Amarok::icon( "queue" )), i18n( "Queue Manager" ), this );
882 connect(queue, SIGNAL(triggered(bool)), SLOT(showQueueManager()));
883 ac->addAction( "queue_manager", queue );
885 KAction *seekForward = new KAction( KIcon( Amarok::icon( "fastforward" ) ), i18n("&Seek Forward"), this );
886 seekForward->setShortcut( Qt::Key_Right );
887 connect(seekForward, SIGNAL(triggered(bool)), ec, SLOT(seekForward()));
888 ac->addAction( "seek_forward", seekForward );
890 KAction *seekBackward = new KAction( KIcon( Amarok::icon( "rewind" ) ), i18n("&Seek Backward"), this );
891 seekForward->setShortcut( Qt::Key_Left );
892 connect(seekForward, SIGNAL(triggered(bool)), ec, SLOT(seekBackward()));
893 ac->addAction( "seek_backward", seekBackward );
895 KAction *statistics = new KAction( KIcon(Amarok::icon( "info" )), i18n( "Statistics" ), this );
896 connect(statistics, SIGNAL(triggered(bool)), SLOT(showStatistics()));
897 ac->addAction( "statistics", statistics );
899 KAction *update = new KAction( KIcon(Amarok::icon( "refresh")), i18n( "Update Collection" ), this );
900 connect(update, SIGNAL(triggered(bool)), CollectionManager::instance(), SLOT(checkCollectionChanges()));
901 ac->addAction( "update_collection", update );
903 KAction *rescan = new KAction( KIcon(Amarok::icon( "rescan")), i18n( "Rescan Collection" ), this );
904 connect(rescan, SIGNAL(triggered(bool)), CollectionManager::instance(), SLOT(startFullScan()));
905 rescan->setEnabled( !ThreadManager::instance()->isJobPending( "CollectionScanner" ) );
906 ac->addAction( "rescan_collection", rescan );
908 m_lastfmTags << "Alternative" << "Ambient" << "Chill Out" << "Classical" << "Dance"
909 << "Electronica" << "Favorites" << "Heavy Metal" << "Hip Hop" << "Indie Rock"
910 << "Industrial" << "Japanese" << "Pop" << "Psytrance" << "Rap" << "Rock"
911 << "Soundtrack" << "Techno" << "Trance";
913 KMenu* playTagRadioMenu = new KMenu( this );
914 playTagRadioMenu->setTitle( i18n( "Global Tag Radio" ) );
915 foreach( const QString &lastfmTag, m_lastfmTags )
917 KAction *lastfmAction = new KAction( lastfmTag, this );
918 connect( lastfmAction, SIGNAL( triggered(bool) ), SLOT( playLastfmGlobaltag() ) );
919 playTagRadioMenu->addAction( lastfmAction );
922 KMenu* addTagRadioMenu = new KMenu( this );
923 addTagRadioMenu->setTitle( i18n( "Global Tag Radio" ) );
924 foreach( const QString &lastfmTag, m_lastfmTags )
926 KAction *lastfmAction = new KAction( lastfmTag, this );
927 connect( lastfmAction, SIGNAL( triggered(bool) ), SLOT( addLastfmGlobaltag() ) );
928 addTagRadioMenu->addAction( lastfmAction );
931 KActionMenu* playLastfm = new KActionMenu( KIcon(Amarok::icon("audioscrobbler")), i18n( "Play las&t.fm Stream" ), ac);
932 KMenu* playLastfmMenu = playLastfm->menu();
933 playLastfmMenu->addAction( i18n( "Personal Radio" ), this, SLOT( playLastfmPersonal() ) );
934 playLastfmMenu->addAction( i18n( "Neighbor Radio" ), this, SLOT( playLastfmNeighbor() ) );
935 playLastfmMenu->addAction( i18n( "Custom Station" ), this, SLOT( playLastfmCustom() ) );
936 playLastfmMenu->addMenu( playTagRadioMenu );
937 ac->addAction( "lastfm_play", playLastfm );
939 KActionMenu* addLastfm = new KActionMenu( KIcon(Amarok::icon("audioscrobbler")), i18n( "Add las&t.fm Stream" ), ac);
940 KMenu* addLastfmMenu = addLastfm->menu();
941 addLastfmMenu->addAction( i18n( "Personal Radio" ), this, SLOT( addLastfmPersonal() ) );
942 addLastfmMenu->addAction( i18n( "Neighbor Radio" ), this, SLOT( addLastfmNeighbor() ) );
943 addLastfmMenu->addAction( i18n( "Custom Station" ), this, SLOT( addLastfmCustom() ) );
944 addLastfmMenu->addMenu( addTagRadioMenu );
945 ac->addAction( "lastfm_add", addLastfm );
947 KAction *previous = new KAction( this );
948 previous->setIcon( KIcon(Amarok::icon( "back" )) );
949 previous->setText( i18n( "Previous Track" ) );
950 ac->addAction( "prev", previous );
951 connect( previous, SIGNAL(triggered(bool)), The::playlistModel(), SLOT( back() ) );
953 KAction *play = new KAction( this );
954 play->setIcon( KIcon(Amarok::icon( "play" )) );
955 play->setText( i18n( "Play" ) );
956 ac->addAction( "play", play );
957 connect( play, SIGNAL(triggered(bool)), ec, SLOT( play() ));
959 KAction *pause = new KAction( this );
960 pause->setIcon( KIcon(Amarok::icon( "pause" )) );
961 pause->setText( i18n( "Pause" ));
962 ac->addAction( "pause", pause );
963 connect( pause, SIGNAL(triggered(bool)), ec, SLOT( pause() ) );
965 KAction *next = new KAction( this );
966 next->setIcon( KIcon(Amarok::icon( "next" )) );
967 next->setText( i18n( "Next Track" ) );
968 ac->addAction( "next", next );
969 connect( next, SIGNAL(triggered(bool)), The::playlistModel(), SLOT( next() ) );
971 KAction *toggleFocus = new KAction(i18n( "Toggle Focus" ), ac);
972 toggleFocus->setShortcut( Qt::ControlModifier + Qt::Key_Tab );
973 connect( toggleFocus, SIGNAL(triggered(bool)), SLOT( slotToggleFocus() ));
975 new Amarok::MenuAction( ac );
976 new Amarok::StopAction( ac );
977 new Amarok::PlayPauseAction( ac );
978 new Amarok::RepeatAction( ac );
979 new Amarok::RandomAction( ac );
980 new Amarok::FavorAction( ac );
982 if( K3bExporter::isAvailable() )
983 new Amarok::BurnMenuAction( ac );
985 ac->associateWidget( this );
988 void MainWindow::createMenus()
990 m_menubar = menuBar();//new MenuBar( this );
992 //BEGIN Actions menu
993 KMenu *actionsMenu = new KMenu( m_menubar );
994 actionsMenu->setTitle( i18n("&Amarok") );
995 actionsMenu->addAction( actionCollection()->action("playlist_playmedia") );
996 actionsMenu->addAction( actionCollection()->action("lastfm_play") );
997 actionsMenu->addAction( actionCollection()->action("play_audiocd") );
998 actionsMenu->addSeparator();
999 actionsMenu->addAction( actionCollection()->action("prev") );
1000 actionsMenu->addAction( actionCollection()->action("play_pause") );
1001 actionsMenu->addAction( actionCollection()->action("stop") );
1002 actionsMenu->addAction( actionCollection()->action("next") );
1003 actionsMenu->addSeparator();
1004 actionsMenu->addAction( actionCollection()->action(KStandardAction::name(KStandardAction::Quit)) );
1005 //END Actions menu
1007 //BEGIN Playlist menu
1008 KMenu *playlistMenu = new KMenu( m_menubar );
1009 playlistMenu->setTitle( i18n("&Playlist") );
1010 playlistMenu->addAction( actionCollection()->action("playlist_add") );
1011 playlistMenu->addAction( actionCollection()->action("stream_add") );
1012 playlistMenu->addAction( actionCollection()->action("lastfm_add") );
1013 playlistMenu->addAction( actionCollection()->action("playlist_save") );
1014 playlistMenu->addAction( actionCollection()->action("playlist_burn") );
1015 playlistMenu->addAction( actionCollection()->action("podcasts_update") );
1016 playlistMenu->addSeparator();
1017 playlistMenu->addAction( actionCollection()->action("playlist_undo") );
1018 playlistMenu->addAction( actionCollection()->action("playlist_redo") );
1019 playlistMenu->addSeparator();
1020 playlistMenu->addAction( actionCollection()->action("playlist_clear") );
1021 playlistMenu->addAction( actionCollection()->action("playlist_shuffle") );
1023 playlistMenu->addSeparator();
1024 playlistMenu->addAction( actionCollection()->action("queue_selected") );
1025 playlistMenu->addAction( actionCollection()->action("playlist_remove_duplicates") );
1026 playlistMenu->addAction( actionCollection()->action("playlist_select_all") );
1028 //END Playlist menu
1030 //BEGIN Mode menu
1031 KMenu *modeMenu = new KMenu( m_menubar );
1032 modeMenu->setTitle( i18n("&Mode") );
1033 QAction *repeat = actionCollection()->action("repeat");
1034 connect( repeat, SIGNAL(triggered( int ) ), The::playlistModel(), SLOT(playlistRepeatMode(int) ) );
1035 modeMenu->addAction( repeat );
1036 KSelectAction *random = static_cast<KSelectAction*>( actionCollection()->action("random_mode") );
1037 modeMenu->addAction( random );
1038 random->menu()->addSeparator();
1039 random->menu()->addAction( actionCollection()->action("favor_tracks") );
1040 //END Mode menu
1042 //BEGIN Tools menu
1043 m_toolsMenu = new KMenu( m_menubar );
1044 m_toolsMenu->setTitle( i18n("&Tools") );
1045 m_toolsMenu->addAction( actionCollection()->action("cover_manager") );
1046 m_toolsMenu->addAction( actionCollection()->action("queue_manager") );
1047 m_toolsMenu->addAction( actionCollection()->action("visualizations") );
1048 m_toolsMenu->addAction( actionCollection()->action("equalizer") );
1049 m_toolsMenu->addAction( actionCollection()->action("script_manager") );
1050 m_toolsMenu->addAction( actionCollection()->action("statistics") );
1051 m_toolsMenu->addSeparator();
1052 m_toolsMenu->addAction( actionCollection()->action("update_collection") );
1053 m_toolsMenu->addAction( actionCollection()->action("rescan_collection") );
1055 #ifndef HAVE_LIBVISUAL
1056 actionCollection()->action( "visualizations" )->setEnabled( false );
1057 #endif
1059 connect( m_toolsMenu, SIGNAL( aboutToShow() ), SLOT( toolsMenuAboutToShow() ) );
1060 connect( m_toolsMenu, SIGNAL( activated(int) ), SLOT( slotMenuActivated(int) ) );
1061 //END Tools menu
1063 //BEGIN Settings menu
1064 m_settingsMenu = new KMenu( m_menubar );
1065 m_settingsMenu->setTitle( i18n("&Settings") );
1066 //TODO use KStandardAction or KXmlGuiWindow
1067 #ifndef Q_WS_MAC
1068 m_settingsMenu->addAction( actionCollection()->action( "toggle_toolbar" ) );
1069 m_settingsMenu->addSeparator();
1070 #endif
1072 #ifdef Q_WS_MAC
1073 // plug it first, as this item will be moved to the applications first menu
1074 m_settingsMenu->addAction( actionCollection()->action(KStandardAction::name(KStandardAction::Preferences)) );
1075 #endif
1076 // m_settingsMenu->addAction( actionCollection()->action("options_configure_globals") );
1077 m_settingsMenu->addAction( actionCollection()->action(KStandardAction::name(KStandardAction::KeyBindings)) );
1078 m_settingsMenu->addAction( actionCollection()->action(KStandardAction::name(KStandardAction::ConfigureToolbars)) );
1079 m_settingsMenu->addAction( actionCollection()->action(KStandardAction::name(KStandardAction::Preferences)) );
1081 connect( m_settingsMenu, SIGNAL( activated(int) ), SLOT( slotMenuActivated(int) ) );
1082 //END Settings menu
1084 m_menubar->addMenu( actionsMenu );
1085 m_menubar->addMenu( playlistMenu );
1086 m_menubar->addMenu( modeMenu );
1087 m_menubar->addMenu( m_toolsMenu );
1088 m_menubar->addMenu( m_settingsMenu );
1089 m_menubar->addMenu( Amarok::Menu::helpMenu() );
1094 #include "MainWindow.moc"