qt: move the main interface to its own folder
[vlc.git] / modules / gui / qt / menus / menus.cpp
blob3ca0ebdc7a03cab718b93803acdde3aa2dc79de7
1 /*****************************************************************************
2 * menus.cpp : Qt menus
3 *****************************************************************************
4 * Copyright © 2006-2011 the VideoLAN team
6 * Authors: Clément Stenac <zorglub@videolan.org>
7 * Jean-Baptiste Kempf <jb@videolan.org>
8 * Jean-Philippe André <jpeg@videolan.org>
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.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /** \todo
26 * - Remove static currentGroup
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
33 #include <vlc_common.h>
34 #include <vlc_intf_strings.h>
35 #include <vlc_aout.h> /* audio_output_t */
36 #include <vlc_player.h>
38 #include "menus.hpp"
40 #include "maininterface/main_interface.hpp" /* View modifications */
41 #include "dialogs/dialogs_provider.hpp" /* Dialogs display */
42 #include "player/player_controller.hpp" /* Input Management */
43 #include "playlist/playlist_controller.hpp"
44 #include "recents.hpp" /* Recent Items */
45 #include "dialogs/extensions/extensions_manager.hpp" /* Extensions menu */
46 #include "dialogs/extended/extended_panels.hpp"
47 #include "util/varchoicemodel.hpp"
49 #include <QMenu>
50 #include <QMenuBar>
51 #include <QAction>
52 #include <QActionGroup>
53 #include <QSignalMapper>
54 #include <QStatusBar>
56 using namespace vlc::playlist;
59 This file defines the main menus and the pop-up menu (right-click menu)
60 and the systray menu (in that order in the file)
62 There are 4 menus that have to be rebuilt everytime there are called:
63 Audio, Video, Navigation, view
64 4 functions are building those menus: AudioMenu, VideoMenu, NavigMenu, View
68 QMenu *VLCMenuBar::recentsMenu = NULL;
69 RendererMenu *VLCMenuBar::rendererMenu = NULL;
71 /**
72 * @brief Add static entries to DP in menus
73 **/
74 QAction *addDPStaticEntry( QMenu *menu,
75 const QString& text,
76 const char *icon,
77 const char *member,
78 const char *shortcut = NULL,
79 QAction::MenuRole role = QAction::NoRole
82 QAction *action = NULL;
83 #ifndef __APPLE__ /* We don't set icons in menus in MacOS X */
84 if( !EMPTY_STR( icon ) )
86 if( !EMPTY_STR( shortcut ) )
87 action = menu->addAction( QIcon( icon ), text, THEDP,
88 member, qtr( shortcut ) );
89 else
90 action = menu->addAction( QIcon( icon ), text, THEDP, member );
92 else
93 #endif
95 if( !EMPTY_STR( shortcut ) )
96 action = menu->addAction( text, THEDP, member, qtr( shortcut ) );
97 else
98 action = menu->addAction( text, THEDP, member );
100 #ifdef __APPLE__
101 action->setMenuRole( role );
102 #else
103 Q_UNUSED( role );
104 #endif
105 return action;
109 * @brief Add static entries to MIM in menus
111 template<typename Fun>
112 static QAction* addMIMStaticEntry( intf_thread_t *p_intf,
113 QMenu *menu,
114 const QString& text,
115 const char *icon,
116 Fun member )
118 QAction *action;
119 #ifndef __APPLE__ /* We don't set icons in menus in MacOS X */
120 if( !EMPTY_STR( icon ) )
122 action = menu->addAction( text, THEMIM, member );
123 action->setIcon( QIcon( icon ) );
125 else
126 #endif
128 action = menu->addAction( text, THEMIM, member );
130 return action;
133 template<typename Fun>
134 static QAction* addMPLStaticEntry( intf_thread_t *p_intf,
135 QMenu *menu,
136 const QString& text,
137 const char *icon,
138 Fun member )
140 QAction *action;
141 #ifndef __APPLE__ /* We don't set icons in menus in MacOS X */
142 if( !EMPTY_STR( icon ) )
144 action = menu->addAction( text, THEMPL, member );
145 action->setIcon( QIcon( icon ) );
147 else
148 #endif
150 action = menu->addAction( text, THEMPL, member );
152 return action;
155 /*****************************************************************************
156 * All normal menus
157 * Simple Code
158 *****************************************************************************/
160 // Static menu
161 static inline void addMenuToMainbar( QMenu *func, QString title, QMenuBar *bar ) {
162 func->setTitle( title );
163 bar->addMenu( func);
166 * Main Menu Bar Creation
168 void VLCMenuBar::createMenuBar( MainInterface *mi,
169 intf_thread_t *p_intf )
171 /* QMainWindows->menuBar()
172 gives the QProcess::destroyed timeout issue on Cleanlooks style with
173 setDesktopAware set to false */
174 QMenuBar *bar = mi->menuBar();
176 addMenuToMainbar( FileMenu( p_intf, bar, mi ), qtr( "&Media" ), bar );
178 /* Dynamic menus, rebuilt before being showed */
179 addMenuToMainbar( NavigMenu( p_intf, bar ), qtr( "P&layback" ), bar);
180 addMenuToMainbar( AudioMenu( p_intf, bar ), qtr( "&Audio" ), bar );
181 addMenuToMainbar( VideoMenu( p_intf, bar ), qtr( "&Video" ), bar );
182 addMenuToMainbar( SubtitleMenu( p_intf, bar ), qtr( "Subti&tle" ), bar );
184 addMenuToMainbar( ToolsMenu( p_intf, bar ), qtr( "Tool&s" ), bar );
186 /* View menu, a bit different */
187 addMenuToMainbar( ViewMenu( p_intf, NULL, mi ), qtr( "V&iew" ), bar );
189 addMenuToMainbar( HelpMenu( bar ), qtr( "&Help" ), bar );
194 * Media ( File ) Menu
195 * Opening, streaming and quit
197 QMenu *VLCMenuBar::FileMenu( intf_thread_t *p_intf, QWidget *parent, MainInterface *mi )
199 QMenu *menu = new QMenu( parent );
200 QAction *action;
202 addDPStaticEntry( menu, qtr( "Open &File..." ),
203 ":/type/file-asym.svg", SLOT( simpleOpenDialog() ), "Ctrl+O" );
204 addDPStaticEntry( menu, qtr( "&Open Multiple Files..." ),
205 ":/type/file-asym.svg", SLOT( openFileDialog() ), "Ctrl+Shift+O" );
206 addDPStaticEntry( menu, qtr( I_OP_OPDIR ),
207 ":/type/folder-grey.svg", SLOT( PLOpenDir() ), "Ctrl+F" );
208 addDPStaticEntry( menu, qtr( "Open &Disc..." ),
209 ":/type/disc.svg", SLOT( openDiscDialog() ), "Ctrl+D" );
210 addDPStaticEntry( menu, qtr( "Open &Network Stream..." ),
211 ":/type/network.svg", SLOT( openNetDialog() ), "Ctrl+N" );
212 addDPStaticEntry( menu, qtr( "Open &Capture Device..." ),
213 ":/type/capture-card.svg", SLOT( openCaptureDialog() ), "Ctrl+C" );
215 addDPStaticEntry( menu, qtr( "Open &Location from clipboard" ),
216 NULL, SLOT( openUrlDialog() ), "Ctrl+V" );
218 if( !recentsMenu && var_InheritBool( p_intf, "qt-recentplay" ) )
219 recentsMenu = new QMenu( qtr( "Open &Recent Media" ) );
221 if( recentsMenu )
223 updateRecents( p_intf );
224 menu->addMenu( recentsMenu );
226 menu->addSeparator();
228 addDPStaticEntry( menu, qtr( I_PL_SAVE ), "", SLOT( savePlayingToPlaylist() ),
229 "Ctrl+Y" );
231 #ifdef ENABLE_SOUT
232 addDPStaticEntry( menu, qtr( "Conve&rt / Save..." ), "",
233 SLOT( openAndTranscodingDialogs() ), "Ctrl+R" );
234 addDPStaticEntry( menu, qtr( "&Stream..." ),
235 ":/menu/stream.svg", SLOT( openAndStreamingDialogs() ), "Ctrl+S" );
236 menu->addSeparator();
237 #endif
239 action = addMPLStaticEntry( p_intf, menu, qtr( "Quit at the end of playlist" ), "",
240 &PlaylistControllerModel::playAndExitChanged );
241 action->setCheckable( true );
242 action->setChecked( THEMPL->isPlayAndExit() );
244 if( mi && mi->getSysTray() )
246 action = menu->addAction( qtr( "Close to systray"), mi,
247 SLOT( toggleUpdateSystrayMenu() ) );
250 addDPStaticEntry( menu, qtr( "&Quit" ) ,
251 ":/menu/exit.svg", SLOT( quit() ), "Ctrl+Q" );
252 return menu;
256 * Tools, like Media Information, Preferences or Messages
258 QMenu *VLCMenuBar::ToolsMenu( intf_thread_t *p_intf, QMenu *menu )
260 addDPStaticEntry( menu, qtr( "&Effects and Filters"), ":/menu/settings.svg",
261 SLOT( extendedDialog() ), "Ctrl+E" );
263 addDPStaticEntry( menu, qtr( "&Track Synchronization"), ":/menu/setting.svgs",
264 SLOT( synchroDialog() ), "" );
266 addDPStaticEntry( menu, qtr( I_MENU_INFO ) , ":/menu/info.svg",
267 SLOT( mediaInfoDialog() ), "Ctrl+I" );
268 addDPStaticEntry( menu, qtr( I_MENU_CODECINFO ) ,
269 ":/menu/info.svg", SLOT( mediaCodecDialog() ), "Ctrl+J" );
271 #ifdef ENABLE_VLM
272 addDPStaticEntry( menu, qtr( I_MENU_VLM ), "", SLOT( vlmDialog() ),
273 "Ctrl+Shift+W" );
274 #endif
276 addDPStaticEntry( menu, qtr( "Program Guide" ), "", SLOT( epgDialog() ),
277 "" );
279 addDPStaticEntry( menu, qtr( I_MENU_MSG ),
280 ":/menu/messages.svg", SLOT( messagesDialog() ), "Ctrl+M" );
282 addDPStaticEntry( menu, qtr( "Plu&gins and extensions" ),
283 "", SLOT( pluginDialog() ) );
284 menu->addSeparator();
286 if( !p_intf->p_sys->b_isDialogProvider )
287 addDPStaticEntry( menu, qtr( "Customi&ze Interface..." ),
288 ":/menu/preferences.svg", SLOT( toolbarDialog() ) );
290 addDPStaticEntry( menu, qtr( "&Preferences" ),
291 ":/menu/preferences.svg", SLOT( prefsDialog() ), "Ctrl+P", QAction::PreferencesRole );
293 return menu;
297 * View Menu
298 * Interface modification, load other interfaces, activate Extensions
299 * \param current, set to NULL for menu creation, else for menu update
301 QMenu *VLCMenuBar::ViewMenu( intf_thread_t *p_intf, QMenu *current, MainInterface *_mi )
303 QAction *action;
304 QMenu *menu;
306 MainInterface *mi = _mi ? _mi : p_intf->p_sys->p_mi;
307 assert( mi );
309 if( !current )
311 menu = new QMenu( qtr( "&View" ), mi );
313 else
315 menu = current;
316 //menu->clear();
317 //HACK menu->clear() does not delete submenus
318 QList<QAction*> actions = menu->actions();
319 foreach( QAction *a, actions )
321 QMenu *m = a->menu();
322 if( a->parent() == menu ) delete a;
323 else menu->removeAction( a );
324 if( m && m->parent() == menu ) delete m;
328 menu->addAction(
329 #ifndef __APPLE__
330 QIcon( ":/menu/playlist_menu.svg" ),
331 #endif
332 qtr( "Play&list" ), mi,
333 SLOT( togglePlaylist() ), qtr( "Ctrl+L" ) );
335 /* Docked Playlist */
336 action = menu->addAction( qtr( "Docked Playlist" ) );
337 action->setCheckable( true );
338 CONNECT( action, triggered( bool ), mi, dockPlaylist( bool ) );
340 menu->addSeparator();
342 action = menu->addAction( qtr( "Always on &top" ) );
343 action->setCheckable( true );
344 action->setChecked( mi->isInterfaceAlwaysOnTop() );
345 CONNECT( action, triggered( bool ), mi, setInterfaceAlwaysOnTop( bool ) );
347 menu->addSeparator();
349 /* Minimal View */
350 action = menu->addAction( qtr( "Mi&nimal Interface" ) );
351 action->setShortcut( qtr( "Ctrl+H" ) );
352 action->setCheckable( true );
355 CONNECT( action, triggered( bool ), mi, toggleMinimalView( bool ) );
356 CONNECT( mi, minimalViewToggled( bool ), action, setChecked( bool ) );
358 /* FullScreen View */
359 action = menu->addAction( qtr( "&Fullscreen Interface" ), mi,
360 SLOT( toggleInterfaceFullScreen() ), QString( "F11" ) );
361 action->setCheckable( true );
362 action->setChecked( mi->isInterfaceFullScreen() );
363 CONNECT( mi, fullscreenInterfaceToggled( bool ),
364 action, setChecked( bool ) );
366 /* Advanced Controls */
367 action = menu->addAction( qtr( "&Advanced Controls" ), mi,
368 SLOT( toggleAdvancedButtons() ) );
369 action->setCheckable( true );
371 action = menu->addAction( qtr( "Status Bar" ) );
372 action->setCheckable( true );
373 action->setChecked( mi->statusBar()->isVisible() );
374 CONNECT( action, triggered( bool ), mi, setStatusBarVisibility( bool) );
375 #if 0 /* For Visualisations. Not yet working */
376 adv = menu->addAction( qtr( "Visualizations selector" ), mi,
377 SLOT( visual() ) );
378 adv->setCheckable( true );
379 if( visual_selector_enabled ) adv->setChecked( true );
380 #endif
382 menu->addSeparator();
384 InterfacesMenu( p_intf, menu );
385 menu->addSeparator();
387 /* Extensions */
388 ExtensionsMenu( p_intf, menu );
390 return menu;
394 * Interface Sub-Menu, to list extras interface and skins
396 QMenu *VLCMenuBar::InterfacesMenu( intf_thread_t *p_intf, QMenu *current )
398 assert(current);
399 VLCVarChoiceModel* model = new VLCVarChoiceModel(VLC_OBJECT(p_intf), "intf-add", current);
400 CheckableListMenu* submenu = new CheckableListMenu(qtr("Interfaces"), model, current);
401 current->addMenu(submenu);
402 return current;
406 * Extensions menu: populate the current menu with extensions
408 void VLCMenuBar::ExtensionsMenu( intf_thread_t *p_intf, QMenu *extMenu )
410 /* Get ExtensionsManager and load extensions if needed */
411 ExtensionsManager *extMgr = ExtensionsManager::getInstance( p_intf );
413 if( !var_InheritBool( p_intf, "qt-autoload-extensions")
414 && !extMgr->isLoaded() )
416 return;
419 if( !extMgr->isLoaded() && !extMgr->cannotLoad() )
421 extMgr->loadExtensions();
424 /* Let the ExtensionsManager build itself the menu */
425 extMenu->addSeparator();
426 extMgr->menu( extMenu );
429 static inline void VolumeEntries( intf_thread_t *p_intf, QMenu *current )
431 current->addSeparator();
433 current->addAction( QIcon( ":/toolbar/volume-high.svg" ), qtr( "&Increase Volume" ), THEMIM, &PlayerController::setVolumeUp );
434 current->addAction( QIcon( ":/toolbar/volume-low.svg" ), qtr( "D&ecrease Volume" ), THEMIM, &PlayerController::setVolumeDown );
435 current->addAction( QIcon( ":/toolbar/volume-muted.svg" ), qtr( "&Mute" ), THEMIM, &PlayerController::toggleMuted );
439 * Main Audio Menu
441 QMenu *VLCMenuBar::AudioMenu( intf_thread_t *p_intf, QMenu * current )
443 if( current->isEmpty() )
445 current->addMenu(new CheckableListMenu(qtr( "Audio &Track" ), THEMIM->getAudioTracks(), current));
447 QAction *audioDeviceAction = new QAction( qtr( "Audio &Device" ), current );
448 QMenu *audioDeviceSubmenu = new QMenu( current );
449 audioDeviceAction->setMenu( audioDeviceSubmenu );
450 current->addAction( audioDeviceAction );
451 connect(audioDeviceSubmenu, &QMenu::aboutToShow, [=]() {
452 updateAudioDevice( p_intf, audioDeviceSubmenu );
455 current->addMenu( new CheckableListMenu(qtr( "&Stereo Mode" ), THEMIM->getAudioStereoMode(), current) );
456 current->addSeparator();
458 current->addMenu( new CheckableListMenu(qtr( "&Visualizations" ), THEMIM->getAudioVisualizations(), current) );
459 VolumeEntries( p_intf, current );
462 return current;
465 /* Subtitles */
466 QMenu *VLCMenuBar::SubtitleMenu( intf_thread_t *p_intf, QMenu *current, bool b_popup )
468 if( current->isEmpty() || b_popup )
470 addDPStaticEntry( current, qtr( "Add &Subtitle File..." ), "",
471 SLOT( loadSubtitlesFile() ) );
472 current->addMenu(new CheckableListMenu(qtr( "Sub &Track" ), THEMIM->getSubtitleTracks(), current));
473 current->addSeparator();
475 return current;
479 * Main Video Menu
480 * Subtitles are part of Video.
482 QMenu *VLCMenuBar::VideoMenu( intf_thread_t *p_intf, QMenu *current )
484 if( current->isEmpty() )
486 current->addMenu(new CheckableListMenu(qtr( "Video &Track" ), THEMIM->getVideoTracks(), current));
488 current->addSeparator();
489 /* Surface modifiers */
490 current->addAction(new BooleanPropertyAction(qtr( "&Fullscreen"), THEMIM, "fullscreen", current));
491 QAction* action = new BooleanPropertyAction(qtr( "Always Fit &Window"), THEMIM, "autoscale", current);
492 action->setEnabled( THEMIM->hasVideoOutput() );
493 connect(THEMIM, &PlayerController::hasVideoOutputChanged, action, &QAction::setEnabled);
494 current->addAction(action);
495 current->addAction(new BooleanPropertyAction(qtr( "Set as Wall&paper"), THEMIM, "wallpaperMode", current));
497 current->addSeparator();
498 /* Size modifiers */
499 current->addMenu( new CheckableListMenu(qtr( "&Zoom" ), THEMIM->getZoom(), current) );
500 current->addMenu( new CheckableListMenu(qtr( "&Aspect Ratio" ), THEMIM->getAspectRatio(), current) );
501 current->addMenu( new CheckableListMenu(qtr( "&Crop" ), THEMIM->getCrop(), current) );
503 current->addSeparator();
504 /* Rendering modifiers */
505 current->addMenu( new CheckableListMenu(qtr( "&Deinterlace" ), THEMIM->getDeinterlace(), current) );
506 current->addMenu( new CheckableListMenu(qtr( "&Deinterlace mode" ), THEMIM->getDeinterlaceMode(), current) );
508 current->addSeparator();
509 /* Other actions */
510 QAction* snapshotAction = new QAction(qtr( "Take &Snapshot" ), current);
511 connect(snapshotAction, &QAction::triggered, THEMIM, &PlayerController::snapshot);
512 current->addAction(snapshotAction);
515 return current;
519 * Navigation Menu
520 * For DVD, MP4, MOV and other chapter based format
522 QMenu *VLCMenuBar::NavigMenu( intf_thread_t *p_intf, QMenu *menu )
524 QAction *action;
525 QMenu *submenu;
527 menu->addMenu( new CheckableListMenu( qtr( "T&itle" ), THEMIM->getTitles(), menu) );
528 submenu = new CheckableListMenu( qtr( "&Chapter" ), THEMIM->getChapters(), menu );
529 submenu->setTearOffEnabled( true );
530 menu->addMenu( submenu );
531 menu->addMenu( new CheckableListMenu( qtr("&Program") , THEMIM->getPrograms(), menu) );
533 submenu = new QMenu( qtr( I_MENU_BOOKMARK ), menu );
534 submenu->setTearOffEnabled( true );
535 addDPStaticEntry( submenu, qtr( "&Manage" ), "",
536 SLOT( bookmarksDialog() ), "Ctrl+B" );
537 submenu->addSeparator();
538 action = menu->addMenu( submenu );
539 action->setData( "bookmark" );
541 menu->addSeparator();
543 if ( !VLCMenuBar::rendererMenu )
544 VLCMenuBar::rendererMenu = new RendererMenu( NULL, p_intf );
546 menu->addMenu( VLCMenuBar::rendererMenu );
547 menu->addSeparator();
550 PopupMenuControlEntries( menu, p_intf );
552 return RebuildNavigMenu( p_intf, menu );
555 QMenu *VLCMenuBar::RebuildNavigMenu( intf_thread_t *p_intf, QMenu *menu )
557 QAction* action;
559 #define ADD_ACTION( title, slot, visibleSignal, visible ) \
560 action = menu->addAction( title, THEMIM, slot ); \
561 if (! visible)\
562 action->setVisible(false); \
563 connect( THEMIM, visibleSignal, action, &QAction::setVisible );
565 ADD_ACTION( qtr("Previous Title"), &PlayerController::titlePrev, &PlayerController::hasTitlesChanged, THEMIM->hasTitles() );
566 ADD_ACTION( qtr("Next Title"), &PlayerController::titleNext, &PlayerController::hasTitlesChanged, THEMIM->hasTitles() );
567 ADD_ACTION( qtr("Previous Chapter"), &PlayerController::chapterPrev, &PlayerController::hasChaptersChanged, THEMIM->hasChapters() );
568 ADD_ACTION( qtr("Next Chapter"), &PlayerController::chapterNext, &PlayerController::hasChaptersChanged, THEMIM->hasChapters() );
570 #undef ADD_ACTION
572 PopupMenuPlaylistEntries( menu, p_intf );
574 return menu;
578 * Help/About Menu
580 QMenu *VLCMenuBar::HelpMenu( QWidget *parent )
582 QMenu *menu = new QMenu( parent );
583 addDPStaticEntry( menu, qtr( "&Help" ) ,
584 ":/menu/help.svg", SLOT( helpDialog() ), "F1" );
585 #ifdef UPDATE_CHECK
586 addDPStaticEntry( menu, qtr( "Check for &Updates..." ) , "",
587 SLOT( updateDialog() ) );
588 #endif
589 menu->addSeparator();
590 addDPStaticEntry( menu, qtr( I_MENU_ABOUT ), ":/menu/info.svg",
591 SLOT( aboutDialog() ), "Shift+F1", QAction::AboutRole );
592 return menu;
595 /*****************************************************************************
596 * Popup menus - Right Click menus *
597 *****************************************************************************/
598 #define POPUP_BOILERPLATE \
599 QMenu* menu;
601 #define CREATE_POPUP \
602 menu = new QMenu(); \
603 if( show ) \
604 menu->popup( QCursor::pos() ); \
606 void VLCMenuBar::PopupMenuPlaylistEntries( QMenu *menu, intf_thread_t *p_intf )
608 QAction *action;
609 bool hasInput = THEMIM->hasInput();
611 /* Play or Pause action and icon */
612 if( !hasInput || THEMIM->getPlayingState() != PlayerController::PLAYING_STATE_PLAYING )
614 action = menu->addAction( qtr( "&Play" ), [p_intf]() {
615 if ( THEMPL->isEmpty() )
616 THEDP->openFileDialog();
617 else
618 THEMPL->togglePlayPause();
620 #ifndef __APPLE__ /* No icons in menus in Mac */
621 action->setIcon( QIcon( ":/toolbar/play_b.svg" ) );
622 #endif
624 else
626 action = addMPLStaticEntry( p_intf, menu, qtr( "Pause" ),
627 ":/toolbar/pause_b.svg", &PlaylistControllerModel::togglePlayPause );
630 /* Stop */
631 action = addMPLStaticEntry( p_intf, menu, qtr( "&Stop" ),
632 ":/toolbar/stop_b.svg", &PlaylistControllerModel::stop );
633 if( !hasInput )
634 action->setEnabled( false );
636 /* Next / Previous */
637 bool bPlaylistEmpty = THEMPL->isEmpty();
638 QAction* previousAction = addMPLStaticEntry( p_intf, menu, qtr( "Pre&vious" ),
639 ":/toolbar/previous_b.svg", &PlaylistControllerModel::prev );
640 previousAction->setEnabled( !bPlaylistEmpty );
641 connect( THEMPL, &PlaylistControllerModel::isEmptyChanged, previousAction, &QAction::setDisabled);
643 QAction* nextAction = addMPLStaticEntry( p_intf, menu, qtr( "Ne&xt" ),
644 ":/toolbar/next_b.svg", &PlaylistControllerModel::next );
645 nextAction->setEnabled( !bPlaylistEmpty );
646 connect( THEMPL, &PlaylistControllerModel::isEmptyChanged, nextAction, &QAction::setDisabled);
648 action = menu->addAction( qtr( "Record" ), THEMIM, &PlayerController::toggleRecord );
649 action->setIcon( QIcon( ":/toolbar/record.svg" ) );
650 if( !hasInput )
651 action->setEnabled( false );
652 menu->addSeparator();
655 void VLCMenuBar::PopupMenuControlEntries( QMenu *menu, intf_thread_t *p_intf,
656 bool b_normal )
658 QAction *action;
659 QMenu *rateMenu = new QMenu( qtr( "Sp&eed" ), menu );
660 rateMenu->setTearOffEnabled( true );
662 if( b_normal )
664 /* Faster/Slower */
665 action = rateMenu->addAction( qtr( "&Faster" ), THEMIM,
666 &PlayerController::faster );
667 #ifndef __APPLE__ /* No icons in menus in Mac */
668 action->setIcon( QIcon( ":/toolbar/faster2.svg") );
669 #endif
672 action = rateMenu->addAction( QIcon( ":/toolbar/faster2.svg" ), qtr( "Faster (fine)" ), THEMIM,
673 &PlayerController::littlefaster );
675 action = rateMenu->addAction( qtr( "N&ormal Speed" ), THEMIM,
676 &PlayerController::normalRate );
678 action = rateMenu->addAction( QIcon( ":/toolbar/slower2.svg" ), qtr( "Slower (fine)" ), THEMIM,
679 &PlayerController::littleslower );
681 if( b_normal )
683 action = rateMenu->addAction( qtr( "Slo&wer" ), THEMIM,
684 &PlayerController::slower );
685 #ifndef __APPLE__ /* No icons in menus in Mac */
686 action->setIcon( QIcon( ":/toolbar/slower2.svg") );
687 #endif
690 action = menu->addMenu( rateMenu );
692 menu->addSeparator();
694 if( !b_normal ) return;
696 action = menu->addAction( qtr( "&Jump Forward" ), THEMIM,
697 &PlayerController::jumpFwd );
698 #ifndef __APPLE__ /* No icons in menus in Mac */
699 action->setIcon( QIcon( ":/toolbar/skip_fw.svg") );
700 #endif
702 action = menu->addAction( qtr( "Jump Bac&kward" ), THEMIM,
703 &PlayerController::jumpBwd );
704 #ifndef __APPLE__ /* No icons in menus in Mac */
705 action->setIcon( QIcon( ":/toolbar/skip_back.svg") );
706 #endif
708 action = menu->addAction( qtr( I_MENU_GOTOTIME ), THEDP, &DialogsProvider::gotoTimeDialog, qtr( "Ctrl+T" ) );
710 menu->addSeparator();
713 void VLCMenuBar::PopupMenuStaticEntries( QMenu *menu )
715 QMenu *openmenu = new QMenu( qtr( "Open Media" ), menu );
716 addDPStaticEntry( openmenu, qtr( I_OP_OPF ),
717 ":/type/file-asym.svg", SLOT( openFileDialog() ) );
718 addDPStaticEntry( openmenu, qtr( I_OP_OPDIR ),
719 ":/type/folder-grey.svg", SLOT( PLOpenDir() ) );
720 addDPStaticEntry( openmenu, qtr( "Open &Disc..." ),
721 ":/type/disc.svg", SLOT( openDiscDialog() ) );
722 addDPStaticEntry( openmenu, qtr( "Open &Network..." ),
723 ":/type/network.svg", SLOT( openNetDialog() ) );
724 addDPStaticEntry( openmenu, qtr( "Open &Capture Device..." ),
725 ":/type/capture-card.svg", SLOT( openCaptureDialog() ) );
726 menu->addMenu( openmenu );
728 menu->addSeparator();
729 #if 0
730 QMenu *helpmenu = HelpMenu( menu );
731 helpmenu->setTitle( qtr( "Help" ) );
732 menu->addMenu( helpmenu );
733 #endif
735 addDPStaticEntry( menu, qtr( "Quit" ), ":/menu/exit.svg",
736 SLOT( quit() ), "Ctrl+Q", QAction::QuitRole );
739 /* Video Tracks and Subtitles tracks */
740 QMenu* VLCMenuBar::VideoPopupMenu( intf_thread_t *p_intf, bool show )
742 QMenu* menu = new QMenu();
743 VideoMenu(p_intf, menu);
744 if( show )
745 menu->popup( QCursor::pos() );
746 return menu;
749 /* Audio Tracks */
750 QMenu* VLCMenuBar::AudioPopupMenu( intf_thread_t *p_intf, bool show )
752 QMenu* menu = new QMenu();
753 AudioMenu(p_intf, menu);
754 if( show )
755 menu->popup( QCursor::pos() );
756 return menu;
759 /* Navigation stuff, and general menus ( open ), used only for skins */
760 QMenu* VLCMenuBar::MiscPopupMenu( intf_thread_t *p_intf, bool show )
762 QMenu* menu = new QMenu();
764 menu->addSeparator();
765 PopupMenuPlaylistEntries( menu, p_intf );
767 menu->addSeparator();
768 PopupMenuControlEntries( menu, p_intf );
770 menu->addSeparator();
771 PopupMenuStaticEntries( menu );
773 if( show )
774 menu->popup( QCursor::pos() );
775 return menu;
778 /* Main Menu that sticks everything together */
779 QMenu* VLCMenuBar::PopupMenu( intf_thread_t *p_intf, bool show )
781 /* */
782 QMenu* menu = new QMenu();
783 input_item_t* p_input = THEMIM->getInput();
784 QAction *action;
785 bool b_isFullscreen = false;
786 MainInterface *mi = p_intf->p_sys->p_mi;
788 PopupMenuPlaylistEntries( menu, p_intf );
789 menu->addSeparator();
791 if( p_input )
793 QMenu *submenu;
794 PlayerController::VoutPtr p_vout = THEMIM->getVout();
796 /* Add a fullscreen switch button, since it is the most used function */
797 if( p_vout )
799 b_isFullscreen = THEMIM->isFullscreen();
800 if (b_isFullscreen)
801 menu->addAction(new BooleanPropertyAction(qtr( "Leave Fullscreen" ), THEMIM, "fullscreen", menu) );
802 else
803 menu->addAction(new BooleanPropertyAction(qtr( "&Fullscreen" ), THEMIM, "fullscreen", menu) );
805 menu->addSeparator();
808 /* Input menu */
810 /* Audio menu */
811 submenu = new QMenu( menu );
812 action = menu->addMenu( AudioMenu( p_intf, submenu ) );
813 action->setText( qtr( "&Audio" ) );
814 if( action->menu()->isEmpty() )
815 action->setEnabled( false );
817 /* Video menu */
818 submenu = new QMenu( menu );
819 action = menu->addMenu( VideoMenu( p_intf, submenu ) );
820 action->setText( qtr( "&Video" ) );
821 if( action->menu()->isEmpty() )
822 action->setEnabled( false );
824 /* Subtitles menu */
825 submenu = new QMenu( menu );
826 action = menu->addMenu( SubtitleMenu( p_intf, submenu, true ) );
827 action->setText( qtr( "Subti&tle") );
829 /* Playback menu for chapters */
830 submenu = new QMenu( menu );
831 action = menu->addMenu( NavigMenu( p_intf, submenu ) );
832 action->setText( qtr( "&Playback" ) );
833 if( action->menu()->isEmpty() )
834 action->setEnabled( false );
837 menu->addSeparator();
839 /* Add some special entries for windowed mode: Interface Menu */
840 if( !b_isFullscreen )
842 QMenu *submenu = new QMenu( qtr( "Tool&s" ), menu );
843 /*QMenu *tools =*/ ToolsMenu( p_intf, submenu );
844 submenu->addSeparator();
846 if( mi )
848 QMenu* viewMenu = ViewMenu( p_intf, NULL, mi );
849 viewMenu->setTitle( qtr( "V&iew" ) );
850 submenu->addMenu( viewMenu );
853 /* In skins interface, append some items */
854 if( p_intf->p_sys->b_isDialogProvider )
856 vlc_object_t* p_object = vlc_object_parent(p_intf);
857 submenu->setTitle( qtr( "Interface" ) );
859 /* Open skin dialog box */
860 if (var_Type(p_object, "intf-skins-interactive") & VLC_VAR_ISCOMMAND)
862 QAction* openSkinAction = new QAction(qtr("Open skin..."));
863 openSkinAction->setShortcut( QKeySequence( "Ctrl+Shift+S" ));
864 connect(openSkinAction, &QAction::triggered, [=]() {
865 var_TriggerCallback(p_object, "intf-skins-interactive");
867 submenu->addAction(openSkinAction);
870 VLCVarChoiceModel* skinmodel = new VLCVarChoiceModel(p_object, "intf-skins", submenu);
871 CheckableListMenu* skinsubmenu = new CheckableListMenu(qtr("Interface"), skinmodel, submenu);
872 submenu->addMenu(skinsubmenu);
874 submenu->addSeparator();
876 /* list of extensions */
877 ExtensionsMenu( p_intf, submenu );
880 menu->addMenu( submenu );
883 /* Static entries for ending, like open */
884 if( p_intf->p_sys->b_isDialogProvider )
886 QMenu *openmenu = FileMenu( p_intf, menu );
887 openmenu->setTitle( qtr( "Open Media" ) );
888 menu->addMenu( openmenu );
890 menu->addSeparator();
892 QMenu *helpmenu = HelpMenu( menu );
893 helpmenu->setTitle( qtr( "Help" ) );
894 menu->addMenu( helpmenu );
896 addDPStaticEntry( menu, qtr( "Quit" ), ":/menu/exit.svg",
897 SLOT( quit() ), "Ctrl+Q", QAction::QuitRole );
899 else
900 PopupMenuStaticEntries( menu );
902 if( show )
903 menu->popup( QCursor::pos() );
904 return menu;
907 #undef CREATE_POPUP
908 #undef POPUP_BOILERPLATE
909 #undef BAR_DADD
911 /************************************************************************
912 * Systray Menu *
913 ************************************************************************/
915 void VLCMenuBar::updateSystrayMenu( MainInterface *mi,
916 intf_thread_t *p_intf,
917 bool b_force_visible )
919 /* Get the systray menu and clean it */
920 QMenu *sysMenu = mi->getSysTrayMenu();
921 sysMenu->clear();
923 #ifndef Q_OS_MAC
924 /* Hide / Show VLC and cone */
925 if( mi->isVisible() || b_force_visible )
927 sysMenu->addAction( QIcon( ":/logo/vlc16.png" ),
928 qtr( "&Hide VLC media player in taskbar" ), mi,
929 SLOT( hideUpdateSystrayMenu() ) );
931 else
933 sysMenu->addAction( QIcon( ":/logo/vlc16.png" ),
934 qtr( "Sho&w VLC media player" ), mi,
935 SLOT( showUpdateSystrayMenu() ) );
937 sysMenu->addSeparator();
938 #endif
940 PopupMenuPlaylistEntries( sysMenu, p_intf );
941 PopupMenuControlEntries( sysMenu, p_intf, false );
943 VolumeEntries( p_intf, sysMenu );
944 sysMenu->addSeparator();
945 addDPStaticEntry( sysMenu, qtr( "&Open Media" ),
946 ":/type/file-wide.svg", SLOT( openFileDialog() ) );
947 addDPStaticEntry( sysMenu, qtr( "&Quit" ) ,
948 ":/menu/exit.svg", SLOT( quit() ) );
950 /* Set the menu */
951 mi->getSysTray()->setContextMenu( sysMenu );
956 /*****************************************************************************
957 * Private methods.
958 *****************************************************************************/
960 void VLCMenuBar::updateAudioDevice( intf_thread_t * p_intf, QMenu *current )
962 char **ids, **names;
963 char *selected;
965 if( !current )
966 return;
968 current->clear();
969 PlayerController::AoutPtr aout = THEMIM->getAout();
970 if (!aout)
971 return;
973 int i_result = aout_DevicesList( aout.get(), &ids, &names);
974 if( i_result < 0 )
975 return;
977 selected = aout_DeviceGet( aout.get() );
979 QActionGroup *actionGroup = new QActionGroup(current);
980 QAction *action;
982 for( int i = 0; i < i_result; i++ )
984 action = new QAction( qfue( names[i] ), actionGroup );
985 action->setData( ids[i] );
986 action->setCheckable( true );
987 if( (selected && !strcmp( ids[i], selected ) ) ||
988 (selected == NULL && ids[i] && ids[i][0] == '\0' ) )
989 action->setChecked( true );
990 actionGroup->addAction( action );
991 current->addAction( action );
992 connect(action, &QAction::triggered, THEMIM->menusAudioMapper, QOverload<>::of(&QSignalMapper::map));
993 THEMIM->menusAudioMapper->setMapping(action, ids[i]);
994 free( ids[i] );
995 free( names[i] );
997 free( ids );
998 free( names );
999 free( selected );
1002 void VLCMenuBar::updateRecents( intf_thread_t *p_intf )
1004 if( recentsMenu )
1006 QAction* action;
1007 RecentsMRL* rmrl = RecentsMRL::getInstance( p_intf );
1008 QStringList l = rmrl->recentList();
1010 recentsMenu->clear();
1012 if( !l.count() )
1014 recentsMenu->setEnabled( false );
1016 else
1018 for( int i = 0; i < __MIN( l.count(), 10) ; ++i )
1020 QString mrl = l.at( i );
1021 char *psz = vlc_uri_decode_duplicate( qtu( mrl ) );
1022 QString text = qfu( psz );
1024 text.replace("&", "&&");
1025 #ifdef _WIN32
1026 # define FILE_SCHEME "file:///"
1027 #else
1028 # define FILE_SCHEME "file://"
1029 #endif
1030 if ( text.startsWith( FILE_SCHEME ) )
1031 text.remove( 0, strlen( FILE_SCHEME ) );
1032 #undef FILE_SCHEME
1034 free( psz );
1035 action = recentsMenu->addAction(
1036 QString( i < 9 ? "&%1: ": "%1: " ).arg( i + 1 ) +
1037 QApplication::fontMetrics().elidedText( text,
1038 Qt::ElideLeft, 400 ),
1039 rmrl->signalMapper, SLOT( map() ),
1040 i < 9 ? QString( "Ctrl+%1" ).arg( i + 1 ) : "" );
1041 rmrl->signalMapper->setMapping( action, l.at( i ) );
1044 recentsMenu->addSeparator();
1045 recentsMenu->addAction( qtr("&Clear"), rmrl, SLOT( clear() ) );
1046 recentsMenu->setEnabled( true );