1 // Maintainer: Max Howell <max.howell@methylblue.com>, (C) 2004
2 // Copyright: See COPYING file that comes with this distribution
4 #include "actionclasses.h"
6 #include "config-amarok.h" //HAVE_LIBVISUAL definition
9 #include "amarokconfig.h"
12 #include "collectiondb.h"
13 #include "covermanager.h"
14 #include "enginecontroller.h"
15 #include "k3bexporter.h"
16 #include "MainWindow.h"
17 #include "mediumpluginmanager.h"
19 #include "socketserver.h" //Vis::Selector::showInstance()
20 #include "statusbar.h"
21 #include "threadmanager.h"
22 #include "timeLabel.h"
26 #include <KIconLoader>
29 #include <KPushButton>
30 #include <KStandardDirs>
33 #include <KAuthorized>
37 #include <Q3PopupMenu>
42 bool repeatNone() { return AmarokConfig::repeat() == AmarokConfig::EnumRepeat::Off
; }
43 bool repeatTrack() { return AmarokConfig::repeat() == AmarokConfig::EnumRepeat::Track
; }
44 bool repeatAlbum() { return AmarokConfig::repeat() == AmarokConfig::EnumRepeat::Album
; }
45 bool repeatPlaylist() { return AmarokConfig::repeat() == AmarokConfig::EnumRepeat::Playlist
; }
46 bool randomOff() { return AmarokConfig::randomMode() == AmarokConfig::EnumRandomMode::Off
; }
47 bool randomTracks() { return AmarokConfig::randomMode() == AmarokConfig::EnumRandomMode::Tracks
; }
48 bool randomAlbums() { return AmarokConfig::randomMode() == AmarokConfig::EnumRandomMode::Albums
; }
49 bool favorNone() { return AmarokConfig::favorTracks() == AmarokConfig::EnumFavorTracks::Off
; }
50 bool favorScores() { return AmarokConfig::favorTracks() == AmarokConfig::EnumFavorTracks::HigherScores
; }
51 bool favorRatings() { return AmarokConfig::favorTracks() == AmarokConfig::EnumFavorTracks::HigherRatings
; }
52 bool favorLastPlay() { return AmarokConfig::favorTracks() == AmarokConfig::EnumFavorTracks::LessRecentlyPlayed
; }
53 bool entireAlbums() { return repeatAlbum() || randomAlbums(); }
56 using namespace Amarok
;
58 KHelpMenu
*Menu::s_helpMenu
= 0;
61 safePlug( KActionCollection
*ac
, const char *name
, QWidget
*w
)
65 KAction
*a
= (KAction
*) ac
->action( name
);
66 if( a
&& w
) w
->addAction( a
);
71 //////////////////////////////////////////////////////////////////////////////////////////
73 // KActionMenu doesn't work very well, so we derived our own
74 //////////////////////////////////////////////////////////////////////////////////////////
76 MenuAction::MenuAction( KActionCollection
*ac
)
79 setText(i18n( "Amarok Menu" ));
80 ac
->addAction("amarok_menu", this);
81 setShortcutConfigurable ( false ); //FIXME disabled as it doesn't work, should use QCursor::pos()
85 MenuAction::plug( QWidget
*w
, int index
)
87 KToolBar
*bar
= dynamic_cast<KToolBar
*>(w
);
89 if( bar
&& KAuthorized::authorizeKAction( objectName() ) )
91 //const int id = KAction::getToolButtonID();
93 //addContainer( bar, id );
95 connect( bar
, SIGNAL( destroyed() ), SLOT( slotDestroyed() ) );
97 //TODO create menu on demand
98 //TODO create menu above and aligned within window
99 //TODO make the arrow point upwards!
100 //bar->insertButton( QString::null, id, true, i18n( "Menu" ), index );
101 //bar->alignItemRight( id );
103 //KToolBarButton* button = bar->getButton( id );
104 //button->setPopup( Amarok::Menu::instance() );
105 //button->setObjectName( "toolbutton_amarok_menu" );
106 //button->setIcon( "amarok" );
108 return associatedWidgets().count() - 1;
115 KActionCollection
*ac
= Amarok::actionCollection();
117 setCheckable( true );
119 safePlug( ac
, "repeat", this );
120 safePlug( ac
, "random_mode", this );
124 safePlug( ac
, "playlist_playmedia", this );
125 safePlug( ac
, "play_audiocd", this );
126 safePlug( ac
, "lastfm_play", this );
130 insertItem( KIcon( Amarok::icon( "covermanager" ) ), i18n( "C&over Manager" ), ID_SHOW_COVER_MANAGER
);
131 safePlug( ac
, "queue_manager", this );
132 insertItem( KIcon( Amarok::icon( "visualizations" ) ), i18n( "&Visualizations" ), ID_SHOW_VIS_SELECTOR
);
133 insertItem( KIcon( Amarok::icon( "equalizer" ) ), i18n( "E&qualizer" ), kapp
, SLOT( slotConfigEqualizer() ), 0, ID_CONFIGURE_EQUALIZER
);
134 safePlug( ac
, "script_manager", this );
135 safePlug( ac
, "statistics", this );
140 safePlug( ac
, "update_collection", this );
141 insertItem( KIcon( Amarok::icon( "rescan" ) ), i18n("&Rescan Collection"), ID_RESCAN_COLLECTION
);
142 setItemEnabled( ID_RESCAN_COLLECTION
, !ThreadManager::instance()->isJobPending( "CollectionScanner" ) );
147 safePlug( ac
, KStandardAction::name(KStandardAction::ShowMenubar
), this );
152 safePlug( ac
, KStandardAction::name(KStandardAction::ConfigureToolbars
), this );
153 safePlug( ac
, KStandardAction::name(KStandardAction::KeyBindings
), this );
154 // safePlug( ac, "options_configure_globals", this ); //we created this one
155 safePlug( ac
, KStandardAction::name(KStandardAction::Preferences
), this );
159 insertItem( KIcon("help"), i18n( "&Help" ), helpMenu( this ) );
163 safePlug( ac
, KStandardAction::name(KStandardAction::Quit
), this );
165 connect( this, SIGNAL( aboutToShow() ), SLOT( slotAboutToShow() ) );
166 connect( this, SIGNAL( activated(int) ), SLOT( slotActivated(int) ) );
168 setItemEnabled( ID_SHOW_VIS_SELECTOR
, false );
169 #ifdef HAVE_LIBVISUAL
170 setItemEnabled( ID_SHOW_VIS_SELECTOR
, true );
182 Menu::helpMenu( QWidget
*parent
) //STATIC
184 extern KAboutData aboutData
;
186 if ( s_helpMenu
== 0 )
187 s_helpMenu
= new KHelpMenu( parent
, &aboutData
, Amarok::actionCollection() );
189 return s_helpMenu
->menu();
193 Menu::slotAboutToShow()
195 setItemEnabled( ID_CONFIGURE_EQUALIZER
, EngineController::hasEngineProperty( "HasEqualizer" ) );
196 setItemEnabled( ID_CONF_DECODER
, EngineController::hasEngineProperty( "HasConfigure" ) );
200 Menu::slotActivated( int index
)
204 case ID_SHOW_COVER_MANAGER
:
205 CoverManager::showOnce();
207 case ID_SHOW_VIS_SELECTOR
:
208 Vis::Selector::instance()->show(); //doing it here means we delay creation of the widget
210 case ID_RESCAN_COLLECTION
:
211 CollectionDB::instance()->startScan();
216 //////////////////////////////////////////////////////////////////////////////////////////
218 //////////////////////////////////////////////////////////////////////////////////////////
220 PlayPauseAction::PlayPauseAction( KActionCollection
*ac
)
222 , EngineObserver( EngineController::instance() )
224 setText(i18n( "Play/Pause" ));
225 ac
->addAction("play_pause", this);
227 engineStateChanged( EngineController::engine()->state() );
229 connect( this, SIGNAL(triggered()), EngineController::instance(), SLOT(playPause()) );
233 PlayPauseAction::engineStateChanged( Engine::State state
, Engine::State
/*oldState*/ )
236 case Engine::Playing
:
238 setIcon( KIcon(Amarok::icon( "pause" )) );
239 setText( i18n( "Pause" ) );
243 setIcon( KIcon(Amarok::icon( "pause" )) );
244 setText( i18n( "Pause" ) );
248 setIcon( KIcon(Amarok::icon( "play" )) );
249 setText( i18n( "Play" ) );
255 //update menu texts for this special action
256 for( int x = 0; x < associatedWidgets().count(); ++x ) {
257 QWidget *w = associatedWidgets().value( x );
258 if( w->inherits( "QPopupMenu" ) )
259 static_cast<Q3PopupMenu*>(w)->changeItem( *this, text );
260 //TODO KToolBar sucks so much
261 // else if( w->inherits( "KToolBar" ) )
262 // static_cast<KToolBar*>(w)->getButton( itemId( x ) )->setText( text );
265 //////////////////////////////////////////////////////////////////////////////////////////
267 //////////////////////////////////////////////////////////////////////////////////////////
269 ToggleAction::ToggleAction( const QString
&text
, void ( *f
) ( bool ), KActionCollection
* const ac
, const char *name
)
274 ac
->addAction(name
, this);
277 void ToggleAction::setChecked( bool b
)
279 const bool announce
= b
!= isChecked();
282 KToggleAction::setChecked( b
);
283 AmarokConfig::self()->writeConfig(); //So we don't lose the setting when crashing
284 if( announce
) emit
toggled( b
); //KToggleAction doesn't do this for us. How gay!
287 void ToggleAction::setEnabled( bool b
)
289 const bool announce
= b
!= isEnabled();
293 KToggleAction::setEnabled( b
);
294 AmarokConfig::self()->writeConfig(); //So we don't lose the setting when crashing
295 if( announce
) emit
QAction::triggered( b
);
298 //////////////////////////////////////////////////////////////////////////////////////////
300 //////////////////////////////////////////////////////////////////////////////////////////
302 SelectAction::SelectAction( const QString
&text
, void ( *f
) ( int ), KActionCollection
* const ac
, const char *name
)
307 ac
->addAction(name
, this);
310 void SelectAction::setCurrentItem( int n
)
312 const bool announce
= n
!= currentItem();
315 KSelectAction::setCurrentItem( n
);
316 AmarokConfig::self()->writeConfig(); //So we don't lose the setting when crashing
317 if( announce
) emit
triggered( n
);
320 void SelectAction::setEnabled( bool b
)
322 const bool announce
= b
!= isEnabled();
326 KSelectAction::setEnabled( b
);
327 AmarokConfig::self()->writeConfig(); //So we don't lose the setting when crashing
328 if( announce
) emit
QAction::triggered( b
);
331 void SelectAction::setIcons( QStringList icons
)
334 for( int i
= 0, n
= items().count(); i
< n
; ++i
)
335 menu()->changeItem( i
, KIconLoader::global()->loadIconSet( icons
.at( i
), K3Icon::Small
), menu()->text( i
) );
338 QStringList
SelectAction::icons() const { return m_icons
; }
340 QString
SelectAction::currentIcon() const
342 if( m_icons
.count() )
343 return m_icons
.at( currentItem() );
347 QString
SelectAction::currentText() const {
348 return KSelectAction::currentText() + "<br /><br />" + i18n("Click to change");
351 //////////////////////////////////////////////////////////////////////////////////////////
353 //////////////////////////////////////////////////////////////////////////////////////////
354 RandomAction::RandomAction( KActionCollection
*ac
) :
355 SelectAction( i18n( "Ra&ndom" ), &AmarokConfig::setRandomMode
, ac
, "random_mode" )
357 setItems( QStringList() << i18n( "&Off" ) << i18n( "&Tracks" ) << i18n( "&Albums" ) );
358 setCurrentItem( AmarokConfig::randomMode() );
359 setIcons( QStringList() << Amarok::icon( "random_no" ) << Amarok::icon( "random_track" ) << Amarok::icon( "random_album" ) );
363 RandomAction::setCurrentItem( int n
)
366 //if( KAction *a = parentCollection()->action( "favor_tracks" ) )
367 // a->setEnabled( n );
368 SelectAction::setCurrentItem( n
);
372 //////////////////////////////////////////////////////////////////////////////////////////
374 //////////////////////////////////////////////////////////////////////////////////////////
375 FavorAction::FavorAction( KActionCollection
*ac
) :
376 SelectAction( i18n( "&Favor" ), &AmarokConfig::setFavorTracks
, ac
, "favor_tracks" )
378 setItems( QStringList() << i18n( "Off" )
379 << i18n( "Higher &Scores" )
380 << i18n( "Higher &Ratings" )
381 << i18n( "Not Recently &Played" ) );
383 setCurrentItem( AmarokConfig::favorTracks() );
384 setEnabled( AmarokConfig::randomMode() );
387 //////////////////////////////////////////////////////////////////////////////////////////
389 //////////////////////////////////////////////////////////////////////////////////////////
390 RepeatAction::RepeatAction( KActionCollection
*ac
) :
391 SelectAction( i18n( "&Repeat" ), &AmarokConfig::setRepeat
, ac
, "repeat" )
393 setItems( QStringList() << i18n( "&Off" ) << i18n( "&Track" )
394 << i18n( "&Album" ) << i18n( "&Playlist" ) );
395 setIcons( QStringList() << Amarok::icon( "repeat_no" ) << Amarok::icon( "repeat_track" ) << Amarok::icon( "repeat_album" ) << Amarok::icon( "repeat_playlist" ) );
396 setCurrentItem( AmarokConfig::repeat() );
399 //////////////////////////////////////////////////////////////////////////////////////////
401 //////////////////////////////////////////////////////////////////////////////////////////
402 BurnMenuAction::BurnMenuAction( KActionCollection
*ac
)
405 setText(i18n( "Burn" ));
406 ac
->addAction("burn_menu", this);
410 BurnMenuAction::createWidget( QWidget
*w
)
412 KToolBar
*bar
= dynamic_cast<KToolBar
*>(w
);
414 if( bar
&& KAuthorized::authorizeKAction( name() ) )
416 //const int id = KAction::getToolButtonID();
418 //addContainer( bar, id );
419 w
->addAction( this );
420 connect( bar
, SIGNAL( destroyed() ), SLOT( slotDestroyed() ) );
422 //bar->insertButton( QString::null, id, true, i18n( "Burn" ), index );
424 //KToolBarButton* button = bar->getButton( id );
425 //button->setPopup( Amarok::BurnMenu::instance() );
426 //button->setObjectName( "toolbutton_burn_menu" );
427 //button->setIcon( "k3b" );
429 //return associatedWidgets().count() - 1;
438 insertItem( i18n("Current Playlist"), CURRENT_PLAYLIST
);
439 insertItem( i18n("Selected Tracks"), SELECTED_TRACKS
);
440 //TODO add "album" and "all tracks by artist"
442 connect( this, SIGNAL( aboutToShow() ), SLOT( slotAboutToShow() ) );
443 connect( this, SIGNAL( activated(int) ), SLOT( slotActivated(int) ) );
449 static BurnMenu menu
;
454 BurnMenu::slotAboutToShow()
458 BurnMenu::slotActivated( int index
)
462 case CURRENT_PLAYLIST
:
463 K3bExporter::instance()->exportCurrentPlaylist();
466 case SELECTED_TRACKS
:
467 K3bExporter::instance()->exportSelectedTracks();
472 //////////////////////////////////////////////////////////////////////////////////////////
474 //////////////////////////////////////////////////////////////////////////////////////////
476 StopAction::StopAction( KActionCollection
*ac
)
479 setText(i18n( "Stop" ));
480 setIcon(KIcon(Amarok::icon( "stop" )));
481 connect( this, SIGNAL( triggered() ), EngineController::instance(), SLOT( stop() ) );
482 ac
->addAction("stop", this);
486 StopAction::plug( QWidget
*w
, int index
)
488 KToolBar
*bar
= dynamic_cast<KToolBar
*>(w
);
489 w
->addAction( this );
491 if( bar && KAuthorized::authorizeKAction( name() ) )
493 //const int id = KAction::getToolButtonID();
495 //addContainer( bar, id );
497 w->addAction( this );
498 connect( bar, SIGNAL( destroyed() ), SLOT( slotDestroyed() ) );
500 //bar->insertButton( QString::null, id, SIGNAL( clicked() ), EngineController::instance(), SLOT( stop() ),
501 // true, i18n( "Stop" ), index );
503 //KToolBarButton* button = bar->getButton( id );
504 //button->setDelayedPopup( Amarok::StopMenu::instance() );
505 //button->setObjectName( "toolbutton_stop_menu" );
506 //button->setIcon( Amarok::icon( "stop" ) );
507 //button->setEnabled( EngineController::instance()->engine()->loaded() ); // Disable button at startup
509 return associatedWidgets().count() - 1;
511 else return QAction::plug( w, index );
518 addTitle( i18n( "Stop" ) );
519 insertItem( i18n("Now"), NOW
);
520 insertItem( i18n("After Current Track"), AFTER_TRACK
);
521 insertItem( i18n("After Queue"), AFTER_QUEUE
);
523 connect( this, SIGNAL( aboutToShow() ), SLOT( slotAboutToShow() ) );
524 connect( this, SIGNAL( activated(int) ), SLOT( slotActivated(int) ) );
530 static StopMenu menu
;
535 StopMenu::slotAboutToShow()
537 Playlist
*pl
= Playlist::instance();
539 setItemEnabled( NOW
, Amarok::actionCollection()->action( "stop" )->isEnabled() );
541 setItemEnabled( AFTER_TRACK
, EngineController::engine()->loaded() );
542 setItemChecked( AFTER_TRACK
, pl
->stopAfterMode() == Playlist::StopAfterCurrent
);
544 setItemEnabled( AFTER_QUEUE
, pl
->nextTracks().count() );
545 setItemChecked( AFTER_QUEUE
, pl
->stopAfterMode() == Playlist::StopAfterQueue
);
549 StopMenu::slotActivated( int index
)
551 Playlist
* pl
= Playlist::instance();
552 const int mode
= pl
->stopAfterMode();
557 Amarok::actionCollection()->action( "stop" )->trigger();
558 if( mode
== Playlist::StopAfterCurrent
|| mode
== Playlist::StopAfterQueue
)
559 pl
->setStopAfterMode( Playlist::DoNotStop
);
562 pl
->setStopAfterMode( mode
== Playlist::StopAfterCurrent
563 ? Playlist::DoNotStop
564 : Playlist::StopAfterCurrent
);
567 pl
->setStopAfterMode( mode
== Playlist::StopAfterQueue
568 ? Playlist::DoNotStop
569 : Playlist::StopAfterQueue
);
575 #include "actionclasses.moc"