vlc/modules/gui/qt/maininterface/mainctx.cpp

908 lines
27 KiB
C++

/*****************************************************************************
* main_interface.cpp : Main interface
****************************************************************************
* Copyright (C) 2006-2011 VideoLAN and AUTHORS
*
* Authors: Clément Stenac <zorglub@videolan.org>
* Jean-Baptiste Kempf <jb@videolan.org>
* Ilkka Ollakka <ileoo@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.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "qt.hpp"
#include "maininterface/mainctx.hpp"
#include "compositor.hpp"
#include "util/renderer_manager.hpp"
#include "widgets/native/customwidgets.hpp" // qtEventToVLCKey, QVLCStackedWidget
#include "util/qt_dirs.hpp" // toNativeSeparators
#include "widgets/native/interface_widgets.hpp" // bgWidget, videoWidget
#include "playlist/playlist_controller.hpp"
#include "dialogs/dialogs_provider.hpp"
#include "videosurface.hpp"
#include "menus/menus.hpp" // Menu creation
#include "dialogs/toolbar/controlbar_profile_model.hpp"
#include <QKeyEvent>
#include <QUrl>
#include <QDate>
#include <QMimeData>
#include <QQmlProperty>
#include <QQmlContext>
#include <QWindow>
#include <QScreen>
#ifdef _WIN32
#include <QFileInfo>
#endif
#define VLC_REFERENCE_SCALE_FACTOR 96.
using namespace vlc::playlist;
// #define DEBUG_INTF
/* Callback prototypes */
static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
vlc_value_t old_val, vlc_value_t new_val, void *param );
static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
vlc_value_t old_val, vlc_value_t new_val, void *param );
static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
vlc_value_t old_val, vlc_value_t new_val, void *param );
static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
vlc_value_t old_val, vlc_value_t new_val,
void *param );
const QEvent::Type MainCtx::ToolbarsNeedRebuild =
(QEvent::Type)QEvent::registerEventType();
namespace
{
template <typename T>
T loadVLCOption(vlc_object_t *obj, const char *name);
template <>
int loadVLCOption<int>(vlc_object_t *obj, const char *name)
{
return var_InheritInteger(obj, name);
}
template <>
bool loadVLCOption<bool>(vlc_object_t *obj, const char *name)
{
return var_InheritBool(obj, name);
}
}
MainCtx::MainCtx(qt_intf_t *_p_intf)
: p_intf(_p_intf)
{
/**
* Configuration and settings
* Pre-building of interface
**/
settings = getSettings();
m_colorScheme = new ColorSchemeModel(this);
loadPrefs(false);
loadFromSettingsImpl(false);
/* Get the available interfaces */
m_extraInterfaces = new VLCVarChoiceModel(VLC_OBJECT(p_intf->intf), "intf-add", this);
vlc_medialibrary_t* ml = vlc_ml_instance_get( p_intf );
b_hasMedialibrary = (ml != NULL);
if (b_hasMedialibrary) {
m_medialib = new MediaLib(p_intf);
}
/* Controlbar Profile Model Creation */
m_controlbarProfileModel = new ControlbarProfileModel(p_intf, this);
m_dialogFilepath = getSettings()->value( "filedialog-path", QVLCUserDir( VLC_HOME_DIR ) ).toString();
QString platformName = QGuiApplication::platformName();
#ifdef QT5_HAS_WAYLAND
b_hasWayland = platformName.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive);
#endif
/*********************************
* Create the Systray Management *
*********************************/
//postpone systray initialisation to speedup starting time
QMetaObject::invokeMethod(this, &MainCtx::initSystray, Qt::QueuedConnection);
/*************************************************************
* Connect the input manager to the GUI elements it manages *
* Beware initSystray did some connects on input manager too *
*************************************************************/
/**
* Connects on nameChanged()
* Those connects are different because options can impeach them to trigger.
**/
/* Main Interface statusbar */
/* and title of the Main Interface*/
connect( THEMIM, &PlayerController::inputChanged, this, &MainCtx::onInputChanged );
/* END CONNECTS ON IM */
/* VideoWidget connects for asynchronous calls */
connect( this, &MainCtx::askToQuit, THEDP, &DialogsProvider::quit, Qt::QueuedConnection );
QMetaObject::invokeMethod(this, [this]()
{
// *** HACKY ***
assert(p_intf->p_compositor->interfaceMainWindow());
connect(p_intf->p_compositor->interfaceMainWindow(), &QWindow::screenChanged,
this, &MainCtx::screenChanged);
}, Qt::QueuedConnection);
/** END of CONNECTS**/
/************
* Callbacks
************/
libvlc_int_t* libvlc = vlc_object_instance(p_intf);
var_AddCallback( libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
var_AddCallback( libvlc, "intf-boss", IntfBossCB, p_intf );
var_AddCallback( libvlc, "intf-show", IntfRaiseMainCB, p_intf );
/* Register callback for the intf-popupmenu variable */
var_AddCallback( libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
if( config_GetInt("qt-privacy-ask") )
{
//postpone dialog call, as composition might not be ready yet
QMetaObject::invokeMethod(this, [this](){
THEDP->firstRunDialog();
}, Qt::QueuedConnection);
}
}
MainCtx::~MainCtx()
{
RendererManager::killInstance();
/* Save states */
settings->beginGroup("MainWindow");
settings->setValue( "pl-dock-status", b_playlistDocked );
settings->setValue( "ShowRemainingTime", m_showRemainingTime );
settings->setValue( "interface-scale", m_intfUserScaleFactor );
settings->setValue( "pin-video-controls", m_pinVideoControls );
/* Save playlist state */
settings->setValue( "playlist-visible", playlistVisible );
settings->setValue( "playlist-width-factor", playlistWidthFactor);
settings->setValue( "grid-view", m_gridView );
settings->setValue( "grouping", m_grouping );
settings->setValue( "color-scheme", m_colorScheme->currentScheme() );
/* Save the stackCentralW sizes */
settings->endGroup();
if( var_InheritBool( p_intf, "save-recentplay" ) )
getSettings()->setValue( "filedialog-path", m_dialogFilepath );
else
getSettings()->remove( "filedialog-path" );
/* Unregister callbacks */
libvlc_int_t* libvlc = vlc_object_instance(p_intf);
var_DelCallback( libvlc, "intf-boss", IntfBossCB, p_intf );
var_DelCallback( libvlc, "intf-show", IntfRaiseMainCB, p_intf );
var_DelCallback( libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
var_DelCallback( libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
if (m_medialib)
m_medialib->destroy();
p_intf->p_mi = NULL;
}
bool MainCtx::hasVLM() const {
#ifdef ENABLE_VLM
return true;
#else
return false;
#endif
}
bool MainCtx::useClientSideDecoration() const
{
//don't show CSD when interface is fullscreen
return !m_windowTitlebar;
}
bool MainCtx::hasFirstrun() const {
return config_GetInt( "qt-privacy-ask" );
}
void MainCtx::setUseGlobalShortcuts( bool useShortcuts )
{
if (m_useGlobalShortcuts == useShortcuts)
return;
m_useGlobalShortcuts = useShortcuts;
emit useGlobalShortcutsChanged(m_useGlobalShortcuts);
}
/*****************************
* Main UI handling *
*****************************/
void MainCtx::loadPrefs(const bool callSignals)
{
const auto loadFromVLCOption = [this, callSignals](auto &variable, const char *name
, const std::function<void(MainCtx *)> signal)
{
using variableType = std::remove_reference_t<decltype(variable)>;
const auto value = loadVLCOption<variableType>(VLC_OBJECT(p_intf), name);
if (value == variable)
return;
variable = value;
if (callSignals && signal)
signal(this);
};
/* Are we in the enhanced always-video mode or not ? */
loadFromVLCOption(b_minimalView, "qt-minimal-view", nullptr);
/* Do we want annoying popups or not */
loadFromVLCOption(i_notificationSetting, "qt-notification", nullptr);
/* Should the UI stays on top of other windows */
loadFromVLCOption(b_interfaceOnTop, "video-on-top", [this](MainCtx *)
{
emit interfaceAlwaysOnTopChanged(b_interfaceOnTop);
});
loadFromVLCOption(m_hasToolbarMenu, "qt-menubar", &MainCtx::hasToolbarMenuChanged);
#if QT_CLIENT_SIDE_DECORATION_AVAILABLE
loadFromVLCOption(m_windowTitlebar, "qt-titlebar" , &MainCtx::useClientSideDecorationChanged);
#endif
loadFromVLCOption(m_smoothScroll, "qt-smooth-scrolling", &MainCtx::smoothScrollChanged);
loadFromVLCOption(m_maxVolume, "qt-max-volume", &MainCtx::maxVolumeChanged);
}
void MainCtx::loadFromSettingsImpl(const bool callSignals)
{
const auto loadFromSettings = [this, callSignals](auto &variable, const char *name
, const auto defaultValue, auto signal)
{
using variableType = std::remove_reference_t<decltype(variable)>;
const auto value = getSettings()->value(name, defaultValue).template value<variableType>();
if (value == variable)
return;
variable = value;
if (callSignals && signal)
(this->*signal)(variable);
};
loadFromSettings(b_playlistDocked, "MainWindow/pl-dock-status", true, &MainCtx::playlistDockedChanged);
loadFromSettings(playlistVisible, "MainWindow/playlist-visible", false, &MainCtx::playlistVisibleChanged);
loadFromSettings(playlistWidthFactor, "MainWindow/playlist-width-factor", 4.0 , &MainCtx::playlistWidthFactorChanged);
loadFromSettings(m_gridView, "MainWindow/grid-view", true, &MainCtx::gridViewChanged);
loadFromSettings(m_grouping, "MainWindow/grouping", GROUPING_NONE, &MainCtx::groupingChanged);
loadFromSettings(m_showRemainingTime, "MainWindow/ShowRemainingTime", false, &MainCtx::showRemainingTimeChanged);
loadFromSettings(m_pinVideoControls, "MainWindow/pin-video-controls", false, &MainCtx::pinVideoControlsChanged);
const auto colorScheme = static_cast<ColorSchemeModel::ColorScheme>(getSettings()->value( "MainWindow/color-scheme", ColorSchemeModel::System ).toInt());
if (m_colorScheme->currentScheme() != colorScheme)
m_colorScheme->setCurrentScheme(colorScheme);
/* user interface scale factor */
auto userIntfScaleFactor = var_InheritFloat(p_intf, "qt-interface-scale");
if (userIntfScaleFactor == -1)
userIntfScaleFactor = getSettings()->value( "MainWindow/interface-scale", 1.0).toDouble();
if (m_intfUserScaleFactor != userIntfScaleFactor)
{
m_intfUserScaleFactor = userIntfScaleFactor;
updateIntfScaleFactor();
}
}
void MainCtx::reloadPrefs()
{
loadPrefs(true);
}
void MainCtx::onInputChanged( bool hasInput )
{
if( hasInput == false )
return;
int autoRaise = var_InheritInteger( p_intf, "qt-auto-raise" );
if ( autoRaise == MainCtx::RAISE_NEVER )
return;
if( THEMIM->hasVideoOutput() == true )
{
if( ( autoRaise & MainCtx::RAISE_VIDEO ) == 0 )
return;
}
else if ( ( autoRaise & MainCtx::RAISE_AUDIO ) == 0 )
return;
emit askRaise();
}
#ifdef KeyPress
#undef KeyPress
#endif
void MainCtx::sendHotkey(Qt::Key key , Qt::KeyboardModifiers modifiers)
{
QKeyEvent event(QEvent::KeyPress, key, modifiers );
int vlckey = qtEventToVLCKey(&event);
var_SetInteger(vlc_object_instance(p_intf), "key-pressed", vlckey);
}
void MainCtx::updateIntfScaleFactor()
{
m_intfScaleFactor = m_intfUserScaleFactor;
if (QWindow* window = p_intf->p_compositor ? p_intf->p_compositor->interfaceMainWindow() : nullptr)
{
QScreen* screen = window->screen();
if (screen)
{
qreal dpi = screen->logicalDotsPerInch();
m_intfScaleFactor = m_intfUserScaleFactor * dpi / VLC_REFERENCE_SCALE_FACTOR;
}
}
emit intfScaleFactorChanged();
}
void MainCtx::onWindowVisibilityChanged(QWindow::Visibility visibility)
{
m_windowVisibility = visibility;
}
void MainCtx::setHasAcrylicSurface(const bool v)
{
if (m_hasAcrylicSurface == v)
return;
m_hasAcrylicSurface = v;
emit hasAcrylicSurfaceChanged();
}
void MainCtx::incrementIntfUserScaleFactor(bool increment)
{
if (increment)
setIntfUserScaleFactor(m_intfUserScaleFactor + 0.1);
else
setIntfUserScaleFactor(m_intfUserScaleFactor - 0.1);
}
void MainCtx::setIntfUserScaleFactor(double newValue)
{
m_intfUserScaleFactor = qBound(getMinIntfUserScaleFactor(), newValue, getMaxIntfUserScaleFactor());
updateIntfScaleFactor();
}
void MainCtx::setPinVideoControls(bool pinVideoControls)
{
if (m_pinVideoControls == pinVideoControls)
return;
m_pinVideoControls = pinVideoControls;
emit pinVideoControlsChanged(m_pinVideoControls);
}
inline void MainCtx::initSystray()
{
bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
if( var_InheritBool( p_intf, "qt-start-minimized") )
{
if( b_systrayAvailable )
{
b_systrayWanted = true;
b_hideAfterCreation = true;
}
else
msg_Err( p_intf, "cannot start minimized without system tray bar" );
}
if( b_systrayAvailable && b_systrayWanted )
createSystray();
}
void MainCtx::setPlaylistDocked( bool docked )
{
b_playlistDocked = docked;
emit playlistDockedChanged(docked);
}
void MainCtx::setPlaylistVisible( bool visible )
{
playlistVisible = visible;
emit playlistVisibleChanged(visible);
}
void MainCtx::setPlaylistWidthFactor( double factor )
{
if (factor > 0.0)
{
playlistWidthFactor = factor;
emit playlistWidthFactorChanged(factor);
}
}
void MainCtx::setShowRemainingTime( bool show )
{
m_showRemainingTime = show;
emit showRemainingTimeChanged(show);
}
void MainCtx::setGridView(bool asGrid)
{
m_gridView = asGrid;
emit gridViewChanged( asGrid );
}
void MainCtx::setGrouping(Grouping grouping)
{
m_grouping = grouping;
emit groupingChanged(grouping);
}
void MainCtx::setInterfaceAlwaysOnTop( bool on_top )
{
b_interfaceOnTop = on_top;
emit interfaceAlwaysOnTopChanged(on_top);
}
bool MainCtx::hasEmbededVideo() const
{
return m_videoSurfaceProvider && m_videoSurfaceProvider->hasVideoEmbed();
}
void MainCtx::setVideoSurfaceProvider(VideoSurfaceProvider* videoSurfaceProvider)
{
if (m_videoSurfaceProvider)
disconnect(m_videoSurfaceProvider, &VideoSurfaceProvider::hasVideoEmbedChanged, this, &MainCtx::hasEmbededVideoChanged);
m_videoSurfaceProvider = videoSurfaceProvider;
if (m_videoSurfaceProvider)
connect(m_videoSurfaceProvider, &VideoSurfaceProvider::hasVideoEmbedChanged,
this, &MainCtx::hasEmbededVideoChanged,
Qt::QueuedConnection);
emit hasEmbededVideoChanged(m_videoSurfaceProvider && m_videoSurfaceProvider->hasVideoEmbed());
}
VideoSurfaceProvider* MainCtx::getVideoSurfaceProvider() const
{
return m_videoSurfaceProvider;
}
/*****************************************************************************
* Systray Icon and Systray Menu
*****************************************************************************/
/**
* Create a SystemTray icon and a menu that would go with it.
* Connects to a click handler on the icon.
**/
void MainCtx::createSystray()
{
QIcon iconVLC;
if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
iconVLC = QIcon::fromTheme( "vlc-xmas", QIcon( ":/logo/vlc128-xmas.png" ) );
else
iconVLC = QIcon::fromTheme( "vlc", QIcon( ":/logo/vlc256.png" ) );
sysTray = new QSystemTrayIcon( iconVLC, this );
sysTray->setToolTip( qtr( "VLC media player" ));
systrayMenu.reset(new QMenu( qtr( "VLC media player") ));
systrayMenu->setIcon( iconVLC );
VLCMenuBar::updateSystrayMenu( this, p_intf, true );
sysTray->show();
connect( sysTray, &QSystemTrayIcon::activated,
this, &MainCtx::handleSystrayClick );
/* Connects on nameChanged() */
connect( THEMIM, &PlayerController::nameChanged,
this, &MainCtx::updateSystrayTooltipName );
/* Connect PLAY_STATUS on the systray */
connect( THEMIM, &PlayerController::playingStateChanged,
this, &MainCtx::updateSystrayTooltipStatus );
}
/**
* Updates the Systray Icon's menu and toggle the main interface
*/
void MainCtx::toggleUpdateSystrayMenu()
{
emit toggleWindowVisibility();
if( sysTray )
VLCMenuBar::updateSystrayMenu( this, p_intf );
}
/* First Item of the systray menu */
void MainCtx::showUpdateSystrayMenu()
{
emit setInterfaceVisibible(true);
VLCMenuBar::updateSystrayMenu( this, p_intf );
}
/* First Item of the systray menu */
void MainCtx::hideUpdateSystrayMenu()
{
emit setInterfaceVisibible(false);
VLCMenuBar::updateSystrayMenu( this, p_intf );
}
/* Click on systray Icon */
void MainCtx::handleSystrayClick(
QSystemTrayIcon::ActivationReason reason )
{
switch( reason )
{
case QSystemTrayIcon::Trigger:
case QSystemTrayIcon::DoubleClick:
#ifdef Q_OS_MAC
VLCMenuBar::updateSystrayMenu( this, p_intf );
#else
toggleUpdateSystrayMenu();
#endif
break;
case QSystemTrayIcon::MiddleClick:
sysTray->showMessage( qtr( "VLC media player" ),
qtr( "Control menu for the player" ),
QSystemTrayIcon::Information, 3000 );
break;
default:
break;
}
}
/**
* Updates the name of the systray Icon tooltip.
* Doesn't check if the systray exists, check before you call it.
**/
void MainCtx::updateSystrayTooltipName( const QString& name )
{
if( name.isEmpty() )
{
sysTray->setToolTip( qtr( "VLC media player" ) );
}
else
{
sysTray->setToolTip( name );
if( ( i_notificationSetting == NOTIFICATION_ALWAYS ) ||
( i_notificationSetting == NOTIFICATION_MINIMIZED && (m_windowVisibility == QWindow::Hidden || m_windowVisibility == QWindow::Minimized)))
{
sysTray->showMessage( qtr( "VLC media player" ), name,
QSystemTrayIcon::NoIcon, 3000 );
}
}
VLCMenuBar::updateSystrayMenu( this, p_intf );
}
/**
* Updates the status of the systray Icon tooltip.
* Doesn't check if the systray exists, check before you call it.
**/
void MainCtx::updateSystrayTooltipStatus( PlayerController::PlayingState )
{
VLCMenuBar::updateSystrayMenu( this, p_intf );
}
/************************************************************************
* D&D Events
************************************************************************/
/**
* dropEventPlay
*
* Event called if something is dropped onto a VLC window
* \param event the event in question
* \param b_play whether to play the file immediately
* \return nothing
*/
void MainCtx::dropEventPlay( QDropEvent *event, bool b_play )
{
if( event->possibleActions() & ( Qt::CopyAction | Qt::MoveAction | Qt::LinkAction ) )
event->setDropAction( Qt::CopyAction );
else
return;
const QMimeData *mimeData = event->mimeData();
/* D&D of a subtitles file, add it on the fly */
if( mimeData->urls().count() == 1 && THEMIM->hasInput() )
{
if( !THEMIM->AddAssociatedMedia(SPU_ES, mimeData->urls()[0].toString(), true, true, true) )
{
event->accept();
return;
}
}
QVector<vlc::playlist::Media> medias;
for( const QUrl &url: mimeData->urls() )
{
if( url.isValid() )
{
QString mrl = toURI( url.toEncoded().constData() );
#ifdef _WIN32
QFileInfo info( url.toLocalFile() );
if( info.exists() && info.isSymLink() )
{
QString target = info.symLinkTarget();
QUrl url;
if( QFile::exists( target ) )
{
url = QUrl::fromLocalFile( target );
}
else
{
url.setUrl( target );
}
mrl = toURI( url.toEncoded().constData() );
}
#endif
if( mrl.length() > 0 )
medias.push_back( vlc::playlist::Media{ mrl, QString {} });
}
}
/* Browsers give content as text if you dnd the addressbar,
so check if mimedata has valid url in text and use it
if we didn't get any normal Urls()*/
if( !mimeData->hasUrls() && mimeData->hasText() &&
QUrl(mimeData->text()).isValid() )
{
QString mrl = toURI( mimeData->text() );
medias.push_back( vlc::playlist::Media{ mrl, QString {} });
}
if (!medias.empty())
THEMPL->append(medias, b_play);
event->accept();
}
/************************************************************************
* Events stuff
************************************************************************/
bool MainCtx::onWindowClose( QWindow* )
{
PlaylistControllerModel* playlistController = p_intf->p_mainPlaylistController;
PlayerController* playerController = p_intf->p_mainPlayerController;
if (m_videoSurfaceProvider)
m_videoSurfaceProvider->onWindowClosed();
//We need to make sure that noting is playing anymore otherwise the vout will be closed
//after the main interface, and it requires (at least with OpenGL) that the OpenGL context
//from the main window is still valid.
//vlc_window_ReportClose is currently stubbed
if (playerController && playerController->hasVideoOutput()) {
connect(playerController, &PlayerController::playingStateChanged, [this](PlayerController::PlayingState state){
if (state == PlayerController::PLAYING_STATE_STOPPED) {
emit askToQuit();
}
});
playlistController->stop();
return false;
}
else
{
emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
return true;
}
}
void MainCtx::toggleInterfaceFullScreen()
{
emit setInterfaceFullScreen( m_windowVisibility != QWindow::FullScreen );
}
void MainCtx::emitBoss()
{
emit askBoss();
}
void MainCtx::emitShow()
{
emit askShow();
}
void MainCtx::emitRaise()
{
emit askRaise();
}
VLCVarChoiceModel* MainCtx::getExtraInterfaces()
{
return m_extraInterfaces;
}
/*****************************************************************************
* PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
* We don't show the menu directly here because we don't want the
* caller to block for a too long time.
*****************************************************************************/
static int PopupMenuCB( vlc_object_t *, const char *,
vlc_value_t, vlc_value_t new_val, void *param )
{
qt_intf_t *p_intf = (qt_intf_t *)param;
if( p_intf->pf_show_dialog )
{
p_intf->pf_show_dialog( p_intf->intf, INTF_DIALOG_POPUPMENU,
new_val.b_bool, NULL );
}
return VLC_SUCCESS;
}
/*****************************************************************************
* IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
*****************************************************************************/
static int IntfShowCB( vlc_object_t *, const char *,
vlc_value_t, vlc_value_t, void *param )
{
qt_intf_t *p_intf = (qt_intf_t *)param;
p_intf->p_mi->emitShow();
return VLC_SUCCESS;
}
/*****************************************************************************
* IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
*****************************************************************************/
static int IntfRaiseMainCB( vlc_object_t *, const char *,
vlc_value_t, vlc_value_t, void *param )
{
qt_intf_t *p_intf = (qt_intf_t *)param;
p_intf->p_mi->emitRaise();
return VLC_SUCCESS;
}
/*****************************************************************************
* IntfBossCB: callback triggered by the intf-boss libvlc variable.
*****************************************************************************/
static int IntfBossCB( vlc_object_t *, const char *,
vlc_value_t, vlc_value_t, void *param )
{
qt_intf_t *p_intf = (qt_intf_t *)param;
p_intf->p_mi->emitBoss();
return VLC_SUCCESS;
}
bool MainCtx::acrylicActive() const
{
return m_acrylicActive;
}
void MainCtx::setAcrylicActive(bool newAcrylicActive)
{
if (m_acrylicActive == newAcrylicActive)
return;
m_acrylicActive = newAcrylicActive;
emit acrylicActiveChanged();
}
bool MainCtx::preferHotkeys() const
{
return m_preferHotkeys;
}
void MainCtx::setPreferHotkeys(bool enable)
{
if (m_preferHotkeys == enable)
return;
m_preferHotkeys = enable;
emit preferHotkeysChanged();
}
QWindow *MainCtx::intfMainWindow() const
{
if (p_intf->p_compositor)
return p_intf->p_compositor->interfaceMainWindow();
else
return nullptr;
}
QVariant MainCtx::settingValue(const QString &key, const QVariant &defaultValue) const
{
return settings->value(key, defaultValue);
}
void MainCtx::setSettingValue(const QString &key, const QVariant &value)
{
settings->setValue(key, value);
}
void MainCtx::setAttachedToolTip(QObject *toolTip)
{
// See QQuickToolTipAttachedPrivate::instance(bool create)
assert(toolTip);
// Prevent possible invalid down-casting:
assert(toolTip->inherits("QQuickToolTip"));
QQmlEngine* const engine = qmlEngine(toolTip);
assert(engine);
assert(engine->objectOwnership(toolTip) == QQmlEngine::ObjectOwnership::JavaScriptOwnership);
// Dynamic internal property:
static const char* const name = "_q_QQuickToolTip";
if (const auto obj = engine->property(name).value<QObject *>())
{
if (engine->objectOwnership(obj) == QQmlEngine::ObjectOwnership::CppOwnership)
obj->deleteLater();
}
// setProperty() will return false, so there is no
// need to check the return value:
engine->setProperty(name, QVariant::fromValue(toolTip));
// Check if the attached tooltip is actually the
// one that is set
#ifndef NDEBUG
QQmlComponent component(engine);
component.setData(QByteArrayLiteral("import QtQuick 2.11; import QtQuick.Controls 2.4; Item { }"), {});
QObject* const obj = component.create();
assert(obj);
// Consider disabling setting of custom attached
// tooltip if the following assertion fails:
assert(QQmlProperty::read(obj, QStringLiteral("ToolTip.toolTip"), qmlContext(obj)).value<QObject*>() == toolTip);
obj->deleteLater();
#endif
}