You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

964 lines
33 KiB

/*****************************************************************************
* menus.cpp : Qt menus
*****************************************************************************
* Copyright © 2006-2011 the VideoLAN team
*
* Authors: Clément Stenac <zorglub@videolan.org>
* Jean-Baptiste Kempf <jb@videolan.org>
* Jean-Philippe André <jpeg@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* ( at your option ) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/** \todo
* - Remove static currentGroup
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_intf_strings.h>
#include <vlc_aout.h> /* audio_output_t */
#include <vlc_interface.h>
#include "menus.hpp"
#include "maininterface/mainctx.hpp" /* View modifications */
#include "dialogs/dialogs_provider.hpp" /* Dialogs display */
#include "player/player_controller.hpp" /* Input Management */
#include "playlist/playlist_controller.hpp"
#include "dialogs/extensions/extensions_manager.hpp" /* Extensions menu */
#include "dialogs/extended/extended_panels.hpp"
#include "util/varchoicemodel.hpp"
#include "medialibrary/medialib.hpp"
#include "medialibrary/mlrecentsmodel.hpp"
#include "medialibrary/mlbookmarkmodel.hpp"
#include <QMenu>
#include <QMenuBar>
#include <QAction>
#include <QActionGroup>
#include <QSignalMapper>
using namespace vlc::playlist;
/*
This file defines the main menus and the pop-up menu (right-click menu)
and the systray menu (in that order in the file)
There are 4 menus that have to be rebuilt every time there are called:
Audio, Video, Navigation, view
4 functions are building those menus: AudioMenu, VideoMenu, NavigMenu, View
*/
RendererMenu *VLCMenuBar::rendererMenu = NULL;
/**
* @brief Add static entries to DP in menus
**/
template<typename Functor>
QAction *addDPStaticEntry( QMenu *menu,
const QString& text,
const char *icon,
const Functor member,
const char *shortcut = NULL,
QAction::MenuRole role = QAction::NoRole
)
{
QAction *action = NULL;
#ifndef __APPLE__ /* We don't set icons in menus in MacOS X */
if( !EMPTY_STR( icon ) )
{
if( !EMPTY_STR( shortcut ) )
action = menu->addAction( QIcon( icon ), text, THEDP,
member, qfut( shortcut ) );
else
action = menu->addAction( QIcon( icon ), text, THEDP, member );
}
else
#endif
{
if( !EMPTY_STR( shortcut ) )
action = menu->addAction( text, THEDP, member, qfut( shortcut ) );
else
action = menu->addAction( text, THEDP, member );
}
#ifdef __APPLE__
action->setMenuRole( role );
#else
Q_UNUSED( role );
#endif
return action;
}
/**
* @brief Add static entries to MIM in menus
**/
template<typename Fun>
static QAction* addMIMStaticEntry( qt_intf_t *p_intf,
QMenu *menu,
const QString& text,
const char *icon,
Fun member )
{
QAction *action;
#ifndef __APPLE__ /* We don't set icons in menus in MacOS X */
if( !EMPTY_STR( icon ) )
{
action = menu->addAction( text, THEMIM, member );
action->setIcon( QIcon( icon ) );
}
else
#endif
{
action = menu->addAction( text, THEMIM, member );
}
return action;
}
template<typename Fun>
static QAction* addMPLStaticEntry( qt_intf_t *p_intf,
QMenu *menu,
const QString& text,
const char *icon,
Fun member )
{
QAction *action;
#ifndef __APPLE__ /* We don't set icons in menus in MacOS X */
if( !EMPTY_STR( icon ) )
{
action = menu->addAction( text, THEMPL, member );
action->setIcon( QIcon( icon ) );
}
else
#endif
{
action = menu->addAction( text, THEMPL, member );
}
return action;
}
/*****************************************************************************
* All normal menus
* Simple Code
*****************************************************************************/
/**
* Main Menu Bar Creation
**/
VLCMenuBar::VLCMenuBar(QObject* parent)
: QObject(parent)
{}
/**
* Media ( File ) Menu
* Opening, streaming and quit
**/
void VLCMenuBar::FileMenu(qt_intf_t *p_intf, QMenu *menu)
{
auto mi = p_intf->p_mi;
QAction *action;
//use a lambda here as the Triggrered signal is emiting and it will pass false (checked) as a first argument
addDPStaticEntry( menu, qtr( "Open &File..." ),
":/menu/file.svg", []() { THEDP->simpleOpenDialog(); } , "Ctrl+O" );
addDPStaticEntry( menu, qtr( "&Open Multiple Files..." ),
":/menu/file.svg", &DialogsProvider::openFileDialog, "Ctrl+Shift+O" );
addDPStaticEntry( menu, qfut( I_OP_OPDIR ),
":/menu/folder.svg", &DialogsProvider::PLOpenDir, "Ctrl+F" );
addDPStaticEntry( menu, qtr( "Open &Disc..." ),
":/menu/disc.svg", &DialogsProvider::openDiscDialog, "Ctrl+D" );
addDPStaticEntry( menu, qtr( "Open &Network Stream..." ),
":/menu/network.svg", &DialogsProvider::openNetDialog, "Ctrl+N" );
addDPStaticEntry( menu, qtr( "Open &Capture Device..." ),
":/menu/capture-card.svg", &DialogsProvider::openCaptureDialog, "Ctrl+C" );
addDPStaticEntry( menu, qtr( "Open &Location from clipboard" ),
NULL, &DialogsProvider::openUrlDialog, "Ctrl+V" );
if( mi && var_InheritBool( p_intf, "save-recentplay" ) && mi->hasMediaLibrary() )
{
MLRecentsModel* recentModel = new MLRecentsModel(nullptr);
recentModel->setMl(mi->getMediaLibrary());
recentModel->setLimit(10);
QMenu* recentsMenu = new RecentMenu(recentModel, mi->getMediaLibrary(), menu);
recentsMenu->setTitle(qtr( "Open &Recent Media" ) );
recentModel->setParent(recentsMenu);
menu->addMenu( recentsMenu );
}
menu->addSeparator();
addDPStaticEntry( menu, qfut( I_PL_SAVE ), "", &DialogsProvider::savePlayingToPlaylist,
"Ctrl+Y" );
addDPStaticEntry( menu, qtr( "Conve&rt / Save..." ), "",
&DialogsProvider::openAndTranscodingDialogs, "Ctrl+R" );
addDPStaticEntry( menu, qtr( "&Stream..." ),
":/menu/stream.svg", &DialogsProvider::openAndStreamingDialogs, "Ctrl+S" );
menu->addSeparator();
action = addMPLStaticEntry( p_intf, menu, qtr( "Quit at the end of playlist" ), "",
&PlaylistController::playAndExitChanged );
action->setCheckable( true );
action->setChecked( THEMPL->isPlayAndExit() );
if( mi && mi->getSysTray() )
{
action = menu->addAction( qtr( "Close to systray"), mi,
&MainCtx::toggleUpdateSystrayMenu );
}
addDPStaticEntry( menu, qtr( "&Quit" ) ,
":/menu/exit.svg", &DialogsProvider::quit, "Ctrl+Q" );
}
/**
* Tools, like Media Information, Preferences or Messages
**/
void VLCMenuBar::ToolsMenu( qt_intf_t *p_intf, QMenu *menu )
{
addDPStaticEntry( menu, qtr( "&Effects and Filters"), ":/menu/settings.svg",
&DialogsProvider::extendedDialog, "Ctrl+E" );
addDPStaticEntry( menu, qtr( "&Track Synchronization"), ":/menu/setting.svgs",
&DialogsProvider::synchroDialog, "" );
addDPStaticEntry( menu, qfut( I_MENU_INFO ) , ":/menu/info.svg",
QOverload<>::of(&DialogsProvider::mediaInfoDialog), "Ctrl+I" );
addDPStaticEntry( menu, qfut( I_MENU_CODECINFO ) ,
":/menu/info.svg", &DialogsProvider::mediaCodecDialog, "Ctrl+J" );
#ifdef ENABLE_VLM
addDPStaticEntry( menu, qfut( I_MENU_VLM ), "", &DialogsProvider::vlmDialog,
"Ctrl+Shift+W" );
#endif
addDPStaticEntry( menu, qtr( "Program Guide" ), "", &DialogsProvider::epgDialog,
"" );
addDPStaticEntry( menu, qfut( I_MENU_MSG ),
":/menu/messages.svg", &DialogsProvider::messagesDialog, "Ctrl+M" );
addDPStaticEntry( menu, qtr( "Plu&gins and extensions" ),
"", &DialogsProvider::pluginDialog );
menu->addSeparator();
if( !p_intf->b_isDialogProvider )
addDPStaticEntry( menu, qtr( "Customi&ze Interface..." ),
":/menu/preferences.svg", &DialogsProvider::showToolbarEditorDialog);
addDPStaticEntry( menu, qtr( "&Preferences" ),
":/menu/preferences.svg", &DialogsProvider::prefsDialog, "Ctrl+P", QAction::PreferencesRole );
}
/**
* View Menu
* Interface modification, load other interfaces, activate Extensions
* \param current, set to NULL for menu creation, else for menu update
**/
void VLCMenuBar::ViewMenu( qt_intf_t *p_intf, QMenu *menu )
{
QAction *action;
MainCtx *mi = p_intf->p_mi;
assert( mi );
assert(menu);
//menu->clear();
//HACK menu->clear() does not delete submenus
QList<QAction*> actions = menu->actions();
foreach( QAction *a, actions )
{
QMenu *m = a->menu();
if( a->parent() == menu ) delete a;
else menu->removeAction( a );
if( m && m->parent() == menu ) delete m;
}
QString title;
if (mi->hasMediaLibrary())
title = qtr("Media Library");
else
title = qtr("Browse and Discover");
action = menu->addAction(
#ifndef __APPLE__
QIcon( ":/menu/media_library.svg" ),
#endif
title);
action->setCheckable( true );
connect( action, &QAction::triggered, mi, &MainCtx::setMediaLibraryVisible );
action->setChecked( mi->isMediaLibraryVisible() );
action = menu->addAction(
#ifndef __APPLE__
QIcon( ":/menu/playlist.svg" ),
#endif
qtr( "Play&list" ));
action->setShortcut(QString( "Ctrl+L" ));
action->setCheckable( true );
connect( action, &QAction::triggered, mi, &MainCtx::setPlaylistVisible );
action->setChecked( mi->isPlaylistVisible() );
/* Docked Playlist */
action = menu->addAction( qtr( "Docked Playlist" ) );
action->setCheckable( true );
connect( action, &QAction::triggered, mi, &MainCtx::setPlaylistDocked );
action->setChecked( mi->isPlaylistDocked() );
menu->addSeparator();
action = menu->addAction( qtr( "Always on &top" ) );
action->setCheckable( true );
action->setChecked( mi->isInterfaceAlwaysOnTop() );
connect( action, &QAction::triggered, mi, &MainCtx::setInterfaceAlwaysOnTop );
menu->addSeparator();
/* FullScreen View */
action = menu->addAction( qtr( "&Fullscreen Interface" ), mi,
&MainCtx::toggleInterfaceFullScreen, QString( "F11" ) );
action->setCheckable( true );
action->setChecked( mi->isInterfaceFullScreen() );
action = menu->addAction( qtr( "&View Items as Grid" ), mi,
&MainCtx::setGridView );
action->setCheckable( true );
action->setChecked( mi->hasGridView() );
menu->addMenu( new CheckableListMenu(qtr( "&Color Scheme" ), mi->getColorScheme(), CheckableListMenu::GROUPED_EXLUSIVE, menu) );
menu->addSeparator();
InterfacesMenu( p_intf, menu );
menu->addSeparator();
/* Extensions */
ExtensionsMenu( p_intf, menu );
}
/**
* Interface Sub-Menu, to list extras interface and skins
**/
void VLCMenuBar::InterfacesMenu( qt_intf_t *p_intf, QMenu *current )
{
assert(current);
VLCVarChoiceModel* model = new VLCVarChoiceModel(VLC_OBJECT(p_intf->intf), "intf-add", current);
CheckableListMenu* submenu = new CheckableListMenu(qtr("Interfaces"), model, CheckableListMenu::UNGROUPED, current);
current->addMenu(submenu);
}
/**
* Extensions menu: populate the current menu with extensions
**/
void VLCMenuBar::ExtensionsMenu( qt_intf_t *p_intf, QMenu *extMenu )
{
/* Get ExtensionsManager and load extensions if needed */
ExtensionsManager *extMgr = ExtensionsManager::getInstance( p_intf );
if( !var_InheritBool( p_intf, "qt-autoload-extensions")
&& !extMgr->isLoaded() )
{
return;
}
if( !extMgr->isLoaded() && !extMgr->cannotLoad() )
{
extMgr->loadExtensions();
}
/* Let the ExtensionsManager build itself the menu */
extMenu->addSeparator();
extMgr->menu( extMenu );
}
static inline void VolumeEntries( qt_intf_t *p_intf, QMenu *current )
{
current->addSeparator();
current->addAction( QIcon( ":/menu/volume-high.svg" ), qtr( "&Increase Volume" ), THEMIM, &PlayerController::setVolumeUp );
current->addAction( QIcon( ":/menu/volume-low.svg" ), qtr( "&Decrease Volume" ), THEMIM, &PlayerController::setVolumeDown );
current->addAction( QIcon( ":/menu/volume-muted.svg" ), qtr( "&Mute" ), THEMIM, &PlayerController::toggleMuted );
}
/**
* Main Audio Menu
**/
void VLCMenuBar::AudioMenu( qt_intf_t *p_intf, QMenu * current )
{
if( current->isEmpty() )
{
current->addMenu(new CheckableListMenu(qtr( "Audio &Track" ), THEMIM->getAudioTracks(), CheckableListMenu::GROUPED_OPTIONAL, current));
QAction *audioDeviceAction = new QAction( qtr( "&Audio Device" ), current );
QMenu *audioDeviceSubmenu = new QMenu( current );
audioDeviceAction->setMenu( audioDeviceSubmenu );
current->addAction( audioDeviceAction );
connect(audioDeviceSubmenu, &QMenu::aboutToShow, [=]() {
updateAudioDevice( p_intf, audioDeviceSubmenu );
});
VLCVarChoiceModel *mix_mode = THEMIM->getAudioMixMode();
if (mix_mode->rowCount() == 0)
current->addMenu( new CheckableListMenu(qtr( "&Stereo Mode" ), THEMIM->getAudioStereoMode(), CheckableListMenu::GROUPED_EXLUSIVE, current) );
else
current->addMenu( new CheckableListMenu(qtr( "&Mix Mode" ), mix_mode, CheckableListMenu::GROUPED_EXLUSIVE, current) );
current->addSeparator();
current->addMenu( new CheckableListMenu(qtr( "&Visualizations" ), THEMIM->getAudioVisualizations(), CheckableListMenu::GROUPED_EXLUSIVE, current) );
VolumeEntries( p_intf, current );
}
}
/* Subtitles */
void VLCMenuBar::SubtitleMenu( qt_intf_t *p_intf, QMenu *current, bool b_popup )
{
if( current->isEmpty() || b_popup )
{
addDPStaticEntry( current, qtr( "Add &Subtitle File..." ), "",
&DialogsProvider::loadSubtitlesFile);
current->addMenu(new CheckableListMenu(qtr( "Sub &Track" ), THEMIM->getSubtitleTracks(), CheckableListMenu::GROUPED_OPTIONAL, current));
current->addSeparator();
}
}
/**
* Main Video Menu
* Subtitles are part of Video.
**/
void VLCMenuBar::VideoMenu( qt_intf_t *p_intf, QMenu *current )
{
if( current->isEmpty() )
{
current->addMenu(new CheckableListMenu(qtr( "Video &Track" ), THEMIM->getVideoTracks(), CheckableListMenu::GROUPED_OPTIONAL, current));
current->addSeparator();
/* Surface modifiers */
current->addAction(new BooleanPropertyAction(qtr( "&Fullscreen"), THEMIM, "fullscreen", current));
QAction* action = new BooleanPropertyAction(qtr( "Always Fit &Window"), THEMIM, "autoscale", current);
action->setEnabled( THEMIM->hasVideoOutput() );
connect(THEMIM, &PlayerController::hasVideoOutputChanged, action, &QAction::setEnabled);
current->addAction(action);
current->addAction(new BooleanPropertyAction(qtr( "Set as Wall&paper"), THEMIM, "wallpaperMode", current));
current->addSeparator();
/* Size modifiers */
current->addMenu( new CheckableListMenu(qtr( "&Zoom" ), THEMIM->getZoom(), CheckableListMenu::GROUPED_EXLUSIVE, current) );
current->addMenu( new CheckableListMenu(qtr( "&Aspect Ratio" ), THEMIM->getAspectRatio(), CheckableListMenu::GROUPED_EXLUSIVE, current) );
current->addMenu( new CheckableListMenu(qtr( "&Crop" ), THEMIM->getCrop(), CheckableListMenu::GROUPED_EXLUSIVE, current) );
current->addSeparator();
/* Rendering modifiers */
current->addMenu( new CheckableListMenu(qtr( "&Deinterlace" ), THEMIM->getDeinterlace(), CheckableListMenu::GROUPED_EXLUSIVE, current) );
current->addMenu( new CheckableListMenu(qtr( "&Deinterlace mode" ), THEMIM->getDeinterlaceMode(), CheckableListMenu::GROUPED_EXLUSIVE, current) );
current->addSeparator();
/* Other actions */
QAction* snapshotAction = new QAction(qtr( "Take &Snapshot" ), current);
connect(snapshotAction, &QAction::triggered, THEMIM, &PlayerController::snapshot);
current->addAction(snapshotAction);
}
}
/**
* Navigation Menu
* For DVD, MP4, MOV and other chapter based format
**/
void VLCMenuBar::NavigMenu( qt_intf_t *p_intf, QMenu *menu )
{
QAction *action;
QMenu *submenu;
menu->addMenu( new CheckableListMenu( qtr( "T&itle" ), THEMIM->getTitles(), CheckableListMenu::GROUPED_EXLUSIVE, menu) );
submenu = new CheckableListMenu( qtr( "&Chapter" ), THEMIM->getChapters(), CheckableListMenu::GROUPED_EXLUSIVE, menu );
submenu->setTearOffEnabled( true );
menu->addMenu( submenu );
menu->addMenu( new CheckableListMenu( qtr("&Program") , THEMIM->getPrograms(), CheckableListMenu::GROUPED_EXLUSIVE, menu) );
MainCtx * mi = p_intf->p_mi;
if (mi && p_intf->p_mi->hasMediaLibrary() )
{
MediaLib * mediaLib = mi->getMediaLibrary();
BookmarkMenu * bookmarks = new BookmarkMenu(mediaLib, p_intf->p_player, menu);
bookmarks->setTitle(qfut(I_MENU_BOOKMARK));
action = menu->addMenu(bookmarks);
action->setData("bookmark");
}
menu->addSeparator();
if ( !VLCMenuBar::rendererMenu )
VLCMenuBar::rendererMenu = new RendererMenu( NULL, p_intf );
menu->addMenu( VLCMenuBar::rendererMenu );
menu->addSeparator();
PopupMenuControlEntries( menu, p_intf );
RebuildNavigMenu( p_intf, menu );
}
void VLCMenuBar::RebuildNavigMenu( qt_intf_t *p_intf, QMenu *menu )
{
QAction* action;
#define ADD_ACTION( title, slot, visibleSignal, visible ) \
action = menu->addAction( title, THEMIM, slot ); \
if (! visible)\
action->setVisible(false); \
connect( THEMIM, visibleSignal, action, &QAction::setVisible );
ADD_ACTION( qtr("Previous Title"), &PlayerController::titlePrev, &PlayerController::hasTitlesChanged, THEMIM->hasTitles() );
ADD_ACTION( qtr("Next Title"), &PlayerController::titleNext, &PlayerController::hasTitlesChanged, THEMIM->hasTitles() );
ADD_ACTION( qtr("Previous Chapter"), &PlayerController::chapterPrev, &PlayerController::hasChaptersChanged, THEMIM->hasChapters() );
ADD_ACTION( qtr("Next Chapter"), &PlayerController::chapterNext, &PlayerController::hasChaptersChanged, THEMIM->hasChapters() );
#undef ADD_ACTION
PopupMenuPlaylistEntries( menu, p_intf );
}
/**
* Help/About Menu
**/
void VLCMenuBar::HelpMenu( QMenu *menu )
{
addDPStaticEntry( menu, qtr( "&Help" ) ,
":/menu/help.svg", &DialogsProvider::helpDialog, "F1" );
#ifdef UPDATE_CHECK
addDPStaticEntry( menu, qtr( "Check for &Updates..." ) , "",
&DialogsProvider::updateDialog);
#endif
menu->addSeparator();
addDPStaticEntry( menu, qfut( I_MENU_ABOUT ), ":/menu/info.svg",
&DialogsProvider::aboutDialog, "Shift+F1", QAction::AboutRole );
}
/*****************************************************************************
* Popup menus - Right Click menus *
*****************************************************************************/
void VLCMenuBar::PopupMenuPlaylistEntries( QMenu *menu, qt_intf_t *p_intf )
{
QAction *action;
bool hasInput = THEMIM->hasInput();
/* Play or Pause action and icon */
if( !hasInput || THEMIM->getPlayingState() != PlayerController::PLAYING_STATE_PLAYING )
{
action = menu->addAction( qtr( "&Play" ), [p_intf]() {
if ( THEMPL->isEmpty() )
THEDP->openFileDialog();
else
THEMPL->togglePlayPause();
});
#ifndef __APPLE__ /* No icons in menus in Mac */
action->setIcon( QIcon( ":/menu/ic_fluent_play_filled.svg" ) );
#endif
}
else
{
action = addMPLStaticEntry( p_intf, menu, qtr( "Pause" ),
":/menu/ic_pause_filled.svg", &PlaylistController::togglePlayPause );
}
/* Stop */
action = addMPLStaticEntry( p_intf, menu, qtr( "&Stop" ),
":/menu/stop.svg", &PlaylistController::stop );
if( !hasInput )
action->setEnabled( false );
/* Next / Previous */
bool bPlaylistEmpty = THEMPL->isEmpty();
QAction* previousAction = addMPLStaticEntry( p_intf, menu, qtr( "Pre&vious" ),
":/menu/ic_fluent_previous.svg", &PlaylistController::prev );
previousAction->setEnabled( !bPlaylistEmpty );
connect( THEMPL, &PlaylistController::isEmptyChanged, previousAction, &QAction::setDisabled);
QAction* nextAction = addMPLStaticEntry( p_intf, menu, qtr( "Ne&xt" ),
":/menu/ic_fluent_next.svg", &PlaylistController::next );
nextAction->setEnabled( !bPlaylistEmpty );
connect( THEMPL, &PlaylistController::isEmptyChanged, nextAction, &QAction::setDisabled);
action = menu->addAction( qtr( "Record" ), THEMIM, &PlayerController::toggleRecord );
action->setIcon( QIcon( ":/menu/record.svg" ) );
if( !hasInput )
action->setEnabled( false );
menu->addSeparator();
}
void VLCMenuBar::PopupMenuControlEntries( QMenu *menu, qt_intf_t *p_intf,
bool b_normal )
{
QAction *action;
QMenu *rateMenu = new QMenu( qtr( "Sp&eed" ), menu );
rateMenu->setTearOffEnabled( true );
if( b_normal )
{
/* Faster/Slower */
action = rateMenu->addAction( qtr( "&Faster" ), THEMIM,
&PlayerController::faster );
#ifndef __APPLE__ /* No icons in menus in Mac */
action->setIcon( QIcon( ":/menu/ic_fluent_fast_forward.svg") );
#endif
}
action = rateMenu->addAction( QIcon( ":/menu/ic_fluent_fast_forward.svg" ), qtr( "Faster (fine)" ), THEMIM,
&PlayerController::littlefaster );
action = rateMenu->addAction( qtr( "N&ormal Speed" ), THEMIM,
&PlayerController::normalRate );
action = rateMenu->addAction( QIcon( ":/menu/ic_fluent_rewind.svg" ), qtr( "Slower (fine)" ), THEMIM,
&PlayerController::littleslower );
if( b_normal )
{
action = rateMenu->addAction( qtr( "Slo&wer" ), THEMIM,
&PlayerController::slower );
#ifndef __APPLE__ /* No icons in menus in Mac */
action->setIcon( QIcon( ":/menu/ic_fluent_rewind.svg") );
#endif
}
action = menu->addMenu( rateMenu );
menu->addSeparator();
if( !b_normal ) return;
action = menu->addAction( qtr( "&Jump Forward" ), THEMIM,
&PlayerController::jumpFwd );
#ifndef __APPLE__ /* No icons in menus in Mac */
action->setIcon( QIcon( ":/menu/skip_fw.svg") );
#endif
action = menu->addAction( qtr( "Jump Bac&kward" ), THEMIM,
&PlayerController::jumpBwd );
#ifndef __APPLE__ /* No icons in menus in Mac */
action->setIcon( QIcon( ":/menu/skip_back.svg") );
#endif
action = menu->addAction( qfut( I_MENU_GOTOTIME ), THEDP, &DialogsProvider::gotoTimeDialog, qtr( "Ctrl+T" ) );
menu->addSeparator();
}
void VLCMenuBar::PopupMenuStaticEntries( QMenu *menu )
{
QMenu *openmenu = new QMenu( qtr( "Open Media" ), menu );
addDPStaticEntry( openmenu, qfut( I_OP_OPF ),
":/menu/file.svg", &DialogsProvider::openFileDialog);
addDPStaticEntry( openmenu, qfut( I_OP_OPDIR ),
":/menu/folder.svg", &DialogsProvider::PLOpenDir);
addDPStaticEntry( openmenu, qtr( "Open &Disc..." ),
":/menu/disc.svg", &DialogsProvider::openDiscDialog);
addDPStaticEntry( openmenu, qtr( "Open &Network..." ),
":/menu/network.svg", &DialogsProvider::openNetDialog);
addDPStaticEntry( openmenu, qtr( "Open &Capture Device..." ),
":/menu/capture-card.svg", &DialogsProvider::openCaptureDialog);
menu->addMenu( openmenu );
menu->addSeparator();
addDPStaticEntry( menu, qtr( "Quit" ), ":/menu/exit.svg",
&DialogsProvider::quit, "Ctrl+Q", QAction::QuitRole );
}
/* Video Tracks and Subtitles tracks */
QMenu* VLCMenuBar::VideoPopupMenu( qt_intf_t *p_intf, bool show )
{
QMenu* menu = new QMenu();
VideoMenu(p_intf, menu);
if( show )
menu->popup( QCursor::pos() );
return menu;
}
/* Audio Tracks */
QMenu* VLCMenuBar::AudioPopupMenu( qt_intf_t *p_intf, bool show )
{
QMenu* menu = new QMenu();
AudioMenu(p_intf, menu);
if( show )
menu->popup( QCursor::pos() );
return menu;
}
/* Navigation stuff, and general menus ( open ), used only for skins */
QMenu* VLCMenuBar::MiscPopupMenu( qt_intf_t *p_intf, bool show )
{
QMenu* menu = new QMenu();
menu->addSeparator();
PopupMenuPlaylistEntries( menu, p_intf );
menu->addSeparator();
PopupMenuControlEntries( menu, p_intf );
menu->addSeparator();
PopupMenuStaticEntries( menu );
if( show )
menu->popup( QCursor::pos() );
return menu;
}
/* Main Menu that sticks everything together */
QMenu* VLCMenuBar::PopupMenu( qt_intf_t *p_intf, bool show )
{
/* */
QMenu* menu = new QMenu();
input_item_t* p_input = THEMIM->getInput();
QAction *action;
bool b_isFullscreen = false;
PopupMenuPlaylistEntries( menu, p_intf );
menu->addSeparator();
if( p_input )
{
QMenu *submenu;
SharedVOutThread p_vout = THEMIM->getVout();
/* Add a fullscreen switch button, since it is the most used function */
if( p_vout )
{
b_isFullscreen = THEMIM->isFullscreen();
if (b_isFullscreen)
menu->addAction(new BooleanPropertyAction(qtr( "Leave Fullscreen" ), THEMIM, "fullscreen", menu) );
else
menu->addAction(new BooleanPropertyAction(qtr( "&Fullscreen" ), THEMIM, "fullscreen", menu) );
menu->addSeparator();
}
/* Input menu */
/* Audio menu */
submenu = new QMenu( menu );
AudioMenu( p_intf, submenu );
action = menu->addMenu( submenu );
action->setText( qtr( "&Audio" ) );
if( action->menu()->isEmpty() )
action->setEnabled( false );
/* Video menu */
submenu = new QMenu( menu );
VideoMenu( p_intf, submenu );
action = menu->addMenu( submenu );
action->setText( qtr( "&Video" ) );
if( action->menu()->isEmpty() )
action->setEnabled( false );
/* Subtitles menu */
submenu = new QMenu( menu );
SubtitleMenu( p_intf, submenu, true );
action = menu->addMenu( submenu );
action->setText( qtr( "Subti&tle") );
/* Playback menu for chapters */
submenu = new QMenu( menu );
NavigMenu( p_intf, submenu );
action = menu->addMenu( submenu );
action->setText( qtr( "&Playback" ) );
if( action->menu()->isEmpty() )
action->setEnabled( false );
}
menu->addSeparator();
/* Add some special entries for windowed mode: Interface Menu */
if( !b_isFullscreen )
{
if( p_intf->b_isDialogProvider )
{
// same as Tool menu but with extra entries
QMenu* submenu = new QMenu( qtr( "Interface" ), menu );
ToolsMenu( p_intf, submenu );
submenu->addSeparator();
vlc_object_t* p_object = vlc_object_parent(p_intf->intf);
/* Open skin dialog box */
if (var_Type(p_object, "intf-skins-interactive") & VLC_VAR_ISCOMMAND)
{
QAction* openSkinAction = new QAction(qtr("Open skin..."), menu);
openSkinAction->setShortcut( QKeySequence( "Ctrl+Shift+S" ));
connect(openSkinAction, &QAction::triggered, [=]() {
var_TriggerCallback(p_object, "intf-skins-interactive");
});
submenu->addAction(openSkinAction);
}
VLCVarChoiceModel* skinmodel = new VLCVarChoiceModel(p_object, "intf-skins", submenu);
CheckableListMenu* skinsubmenu = new CheckableListMenu(qtr("Interface"), skinmodel, CheckableListMenu::GROUPED_OPTIONAL, submenu);
submenu->addMenu(skinsubmenu);
submenu->addSeparator();
/* list of extensions */
ExtensionsMenu( p_intf, submenu );
menu->addMenu( submenu );
}
else
{
QMenu* toolsMenu = new QMenu( qtr( "Tool&s" ), menu );
ToolsMenu( p_intf, toolsMenu );
menu->addMenu( toolsMenu );
QMenu* viewMenu = new QMenu( qtr( "V&iew" ), menu );
ViewMenu( p_intf, viewMenu );
menu->addMenu( viewMenu );
}
}
/* Static entries for ending, like open */
if( p_intf->b_isDialogProvider )
{
QMenu* openmenu = new QMenu( qtr( "Open Media" ), menu );
FileMenu( p_intf, openmenu );
menu->addMenu( openmenu );
menu->addSeparator();
QMenu* helpmenu = new QMenu( qtr( "Help" ), menu );
HelpMenu( helpmenu );
menu->addMenu( helpmenu );
addDPStaticEntry( menu, qtr( "Quit" ), ":/menu/exit.svg",
&DialogsProvider::quit, "Ctrl+Q", QAction::QuitRole );
}
else
PopupMenuStaticEntries( menu );
if( show )
menu->popup( QCursor::pos() );
return menu;
}
/************************************************************************
* Systray Menu *
************************************************************************/
void VLCMenuBar::updateSystrayMenu( MainCtx *mi,
qt_intf_t *p_intf,
bool b_force_visible )
{
/* Get the systray menu and clean it */
QMenu *sysMenu = mi->getSysTrayMenu();
// explictly delete submenus, see QTBUG-11070
for (QAction *action : sysMenu->actions()) {
if (action->menu()) {
delete action->menu();
}
}
sysMenu->clear();
#ifndef Q_OS_MAC
/* Hide / Show VLC and cone */
if( mi->isInterfaceVisible() || b_force_visible )
{
sysMenu->addAction( QIcon( ":/logo/vlc16.png" ),
qtr( "&Hide VLC media player in taskbar" ), mi,
&MainCtx::hideUpdateSystrayMenu);
}
else
{
sysMenu->addAction( QIcon( ":/logo/vlc16.png" ),
qtr( "Sho&w VLC media player" ), mi,
&MainCtx::showUpdateSystrayMenu);
}
sysMenu->addSeparator();
#endif
PopupMenuPlaylistEntries( sysMenu, p_intf );
PopupMenuControlEntries( sysMenu, p_intf, false );
VolumeEntries( p_intf, sysMenu );
sysMenu->addSeparator();
addDPStaticEntry( sysMenu, qtr( "&Open Media" ),
":/menu/file.svg", &DialogsProvider::openFileDialog);
addDPStaticEntry( sysMenu, qtr( "&Quit" ) ,
":/menu/exit.svg", &DialogsProvider::quit);
/* Set the menu */
mi->getSysTray()->setContextMenu( sysMenu );
}
/*****************************************************************************
* Private methods.
*****************************************************************************/
void VLCMenuBar::updateAudioDevice( qt_intf_t * p_intf, QMenu *current )
{
char **ids, **names;
char *selected;
if( !current )
return;
current->clear();
SharedAOut aout = THEMIM->getAout();
if (!aout)
return;
int i_result = aout_DevicesList( aout.get(), &ids, &names);
if( i_result < 0 )
return;
selected = aout_DeviceGet( aout.get() );
QActionGroup *actionGroup = new QActionGroup(current);
QAction *action;
for( int i = 0; i < i_result; i++ )
{
action = new QAction( qfue( names[i] ), actionGroup );
action->setData( qfu(ids[i]) );
action->setCheckable( true );
if( (selected && !strcmp( ids[i], selected ) ) ||
(selected == NULL && ids[i] && ids[i][0] == '\0' ) )
action->setChecked( true );
actionGroup->addAction( action );
current->addAction( action );
connect(action, &QAction::triggered, THEMIM->menusAudioMapper, QOverload<>::of(&QSignalMapper::map));
THEMIM->menusAudioMapper->setMapping(action, ids[i]);
free( ids[i] );
free( names[i] );
}
free( ids );
free( names );
free( selected );
}