add check for role to data()
[amarok.git] / src / actionclasses.cpp
blobef4842f9ecf5a4dc0ec49ac32e2ac591d3d298d2
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
8 #include "amarok.h"
9 #include "amarokconfig.h"
10 #include "app.h"
11 #include "debug.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"
18 #include "playlist.h"
19 #include "socketserver.h" //Vis::Selector::showInstance()
20 #include "statusbar.h"
21 #include "threadmanager.h"
22 #include "timeLabel.h"
24 #include <KHBox>
25 #include <KHelpMenu>
26 #include <KIconLoader>
27 #include <KLineEdit>
28 #include <KLocale>
29 #include <KPushButton>
30 #include <KStandardDirs>
31 #include <KToolBar>
32 #include <KUrl>
33 #include <KAuthorized>
35 #include <QPixmap>
36 #include <QToolTip>
37 #include <Q3PopupMenu>
40 namespace Amarok
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;
60 static void
61 safePlug( KActionCollection *ac, const char *name, QWidget *w )
63 if( ac )
65 KAction *a = (KAction*) ac->action( name );
66 if( a && w ) w->addAction( a );
71 //////////////////////////////////////////////////////////////////////////////////////////
72 // MenuAction && Menu
73 // KActionMenu doesn't work very well, so we derived our own
74 //////////////////////////////////////////////////////////////////////////////////////////
76 MenuAction::MenuAction( KActionCollection *ac )
77 : KAction( 0 )
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()
84 int
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 );
94 w->addAction( this );
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;
110 else return -1;
113 Menu::Menu()
115 KActionCollection *ac = Amarok::actionCollection();
117 setCheckable( true );
119 safePlug( ac, "repeat", this );
120 safePlug( ac, "random_mode", this );
122 addSeparator();
124 safePlug( ac, "playlist_playmedia", this );
125 safePlug( ac, "play_audiocd", this );
126 safePlug( ac, "lastfm_play", this );
128 addSeparator();
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 );
137 addSeparator();
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" ) );
144 #ifndef Q_WS_MAC
145 addSeparator();
147 safePlug( ac, KStandardAction::name(KStandardAction::ShowMenubar), this );
148 #endif
150 addSeparator();
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 );
157 addSeparator();
159 insertItem( KIcon("help"), i18n( "&Help" ), helpMenu( this ) );
161 addSeparator();
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 );
171 #endif
174 Menu*
175 Menu::instance()
177 static Menu menu;
178 return &menu;
181 KMenu*
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();
192 void
193 Menu::slotAboutToShow()
195 setItemEnabled( ID_CONFIGURE_EQUALIZER, EngineController::hasEngineProperty( "HasEqualizer" ) );
196 setItemEnabled( ID_CONF_DECODER, EngineController::hasEngineProperty( "HasConfigure" ) );
199 void
200 Menu::slotActivated( int index )
202 switch( index )
204 case ID_SHOW_COVER_MANAGER:
205 CoverManager::showOnce();
206 break;
207 case ID_SHOW_VIS_SELECTOR:
208 Vis::Selector::instance()->show(); //doing it here means we delay creation of the widget
209 break;
210 case ID_RESCAN_COLLECTION:
211 CollectionDB::instance()->startScan();
212 break;
216 //////////////////////////////////////////////////////////////////////////////////////////
217 // PlayPauseAction
218 //////////////////////////////////////////////////////////////////////////////////////////
220 PlayPauseAction::PlayPauseAction( KActionCollection *ac )
221 : KToggleAction( 0 )
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()) );
232 void
233 PlayPauseAction::engineStateChanged( Engine::State state, Engine::State /*oldState*/ )
235 switch( state ) {
236 case Engine::Playing:
237 setChecked( false );
238 setIcon( KIcon(Amarok::icon( "pause" )) );
239 setText( i18n( "Pause" ) );
240 break;
241 case Engine::Paused:
242 setChecked( true );
243 setIcon( KIcon(Amarok::icon( "pause" )) );
244 setText( i18n( "Pause" ) );
245 break;
246 case Engine::Empty:
247 setChecked( false );
248 setIcon( KIcon(Amarok::icon( "play" )) );
249 setText( i18n( "Play" ) );
250 break;
251 case Engine::Idle:
252 return;
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 //////////////////////////////////////////////////////////////////////////////////////////
266 // ToggleAction
267 //////////////////////////////////////////////////////////////////////////////////////////
269 ToggleAction::ToggleAction( const QString &text, void ( *f ) ( bool ), KActionCollection* const ac, const char *name )
270 : KToggleAction( 0 )
271 , m_function( f )
273 setText(text);
274 ac->addAction(name, this);
277 void ToggleAction::setChecked( bool b )
279 const bool announce = b != isChecked();
281 m_function( b );
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();
291 if( !b )
292 setChecked( false );
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 //////////////////////////////////////////////////////////////////////////////////////////
299 // SelectAction
300 //////////////////////////////////////////////////////////////////////////////////////////
302 SelectAction::SelectAction( const QString &text, void ( *f ) ( int ), KActionCollection* const ac, const char *name )
303 : KSelectAction( 0 )
304 , m_function( f )
306 setText(text);
307 ac->addAction(name, this);
310 void SelectAction::setCurrentItem( int n )
312 const bool announce = n != currentItem();
314 m_function( n );
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();
324 if( !b )
325 setCurrentItem( 0 );
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 )
333 m_icons = 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() );
344 return QString();
347 QString SelectAction::currentText() const {
348 return KSelectAction::currentText() + "<br /><br />" + i18n("Click to change");
351 //////////////////////////////////////////////////////////////////////////////////////////
352 // RandomAction
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" ) );
362 void
363 RandomAction::setCurrentItem( int n )
365 // Porting
366 //if( KAction *a = parentCollection()->action( "favor_tracks" ) )
367 // a->setEnabled( n );
368 SelectAction::setCurrentItem( n );
372 //////////////////////////////////////////////////////////////////////////////////////////
373 // FavorAction
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 //////////////////////////////////////////////////////////////////////////////////////////
388 // RepeatAction
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 //////////////////////////////////////////////////////////////////////////////////////////
400 // BurnMenuAction
401 //////////////////////////////////////////////////////////////////////////////////////////
402 BurnMenuAction::BurnMenuAction( KActionCollection *ac )
403 : KAction( 0 )
405 setText(i18n( "Burn" ));
406 ac->addAction("burn_menu", this);
409 QWidget*
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;
430 return 0;
432 //else return -1;
433 else return 0;
436 BurnMenu::BurnMenu()
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) ) );
446 KMenu*
447 BurnMenu::instance()
449 static BurnMenu menu;
450 return &menu;
453 void
454 BurnMenu::slotAboutToShow()
457 void
458 BurnMenu::slotActivated( int index )
460 switch( index )
462 case CURRENT_PLAYLIST:
463 K3bExporter::instance()->exportCurrentPlaylist();
464 break;
466 case SELECTED_TRACKS:
467 K3bExporter::instance()->exportSelectedTracks();
468 break;
472 //////////////////////////////////////////////////////////////////////////////////////////
473 // StopMenuAction
474 //////////////////////////////////////////////////////////////////////////////////////////
476 StopAction::StopAction( KActionCollection *ac )
477 : KAction( 0 )
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 );
513 return 1;
516 StopMenu::StopMenu()
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) ) );
527 KMenu*
528 StopMenu::instance()
530 static StopMenu menu;
531 return &menu;
534 void
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 );
548 void
549 StopMenu::slotActivated( int index )
551 Playlist* pl = Playlist::instance();
552 const int mode = pl->stopAfterMode();
554 switch( index )
556 case NOW:
557 Amarok::actionCollection()->action( "stop" )->trigger();
558 if( mode == Playlist::StopAfterCurrent || mode == Playlist::StopAfterQueue )
559 pl->setStopAfterMode( Playlist::DoNotStop );
560 break;
561 case AFTER_TRACK:
562 pl->setStopAfterMode( mode == Playlist::StopAfterCurrent
563 ? Playlist::DoNotStop
564 : Playlist::StopAfterCurrent );
565 break;
566 case AFTER_QUEUE:
567 pl->setStopAfterMode( mode == Playlist::StopAfterQueue
568 ? Playlist::DoNotStop
569 : Playlist::StopAfterQueue );
570 break;
575 #include "actionclasses.moc"