1 /*****************************************************************************
2 * main_interface.cpp : Main interface
3 ****************************************************************************
4 * Copyright (C) 2006-2011 VideoLAN and AUTHORS
7 * Authors: Clément Stenac <zorglub@videolan.org>
8 * Jean-Baptiste Kempf <jb@videolan.org>
9 * Ilkka Ollakka <ileoo@videolan.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
32 #include "main_interface.hpp"
33 #include "input_manager.hpp" // Creation
34 #include "actions_manager.hpp" // killInstance
35 #include "extensions_manager.hpp" // killInstance
37 #include "util/customwidgets.hpp" // qtEventToVLCKey, QVLCStackedWidget
38 #include "util/qt_dirs.hpp" // toNativeSeparators
40 #include "components/interface_widgets.hpp" // bgWidget, videoWidget
41 #include "components/controller.hpp" // controllers
42 #include "components/playlist/playlist.hpp" // plWidget
43 #include "dialogs/firstrun.hpp" // First Run
45 #include "menus.hpp" // Menu creation
46 #include "recents.hpp" // RecentItems when DnD
48 #include <QCloseEvent>
59 #include <QStackedWidget>
61 #include <vlc_keys.h> /* Wheel event */
62 #include <vlc_vout_display.h> /* vout_thread_t and VOUT_ events */
66 /* Callback prototypes */
67 static int PopupMenuCB( vlc_object_t
*p_this
, const char *psz_variable
,
68 vlc_value_t old_val
, vlc_value_t new_val
, void *param
);
69 static int IntfShowCB( vlc_object_t
*p_this
, const char *psz_variable
,
70 vlc_value_t old_val
, vlc_value_t new_val
, void *param
);
71 static int IntfBossCB( vlc_object_t
*p_this
, const char *psz_variable
,
72 vlc_value_t old_val
, vlc_value_t new_val
, void *param
);
73 static int IntfRaiseMainCB( vlc_object_t
*p_this
, const char *psz_variable
,
74 vlc_value_t old_val
, vlc_value_t new_val
,
77 MainInterface::MainInterface( intf_thread_t
*_p_intf
) : QVLCMW( _p_intf
)
79 /* Variables initialisation */
82 playlistWidget
= NULL
;
83 stackCentralOldWidget
= NULL
;
85 fullscreenControls
= NULL
;
90 b_hideAfterCreation
= false; // --qt-start-minimized
91 playlistVisible
= false;
93 b_interfaceFullScreen
= false;
94 b_hasPausedWhenMinimized
= false;
98 FirstRun::CheckAndRun( this, p_intf
);
101 * Configuration and settings
102 * Pre-building of interface
105 setFocusPolicy( Qt::StrongFocus
);
106 setAcceptDrops( true );
107 setWindowRole( "vlc-main" );
108 setWindowIcon( QApplication::windowIcon() );
109 setWindowOpacity( var_InheritFloat( p_intf
, "qt-opacity" ) );
111 setAttribute( Qt::WA_MacBrushedMetal
);
114 /* Is video in embedded in the UI or not */
115 b_videoEmbedded
= var_InheritBool( p_intf
, "embedded-video" );
117 /* Does the interface resize to video size or the opposite */
118 b_autoresize
= var_InheritBool( p_intf
, "qt-video-autoresize" );
120 /* Are we in the enhanced always-video mode or not ? */
121 b_minimalView
= var_InheritBool( p_intf
, "qt-minimal-view" );
123 /* Do we want anoying popups or not */
124 b_notificationEnabled
= var_InheritBool( p_intf
, "qt-notification" );
127 b_pauseOnMinimize
= var_InheritBool( p_intf
, "qt-pause-minimized" );
129 /* Set the other interface settings */
130 settings
= getSettings();
134 p_intf
->p_sys
->disable_volume_keys
= var_InheritBool( p_intf
, "qt-disable-volume-keys" );
138 b_plDocked
= getSettings()->value( "MainWindow/pl-dock-status", true ).toBool();
141 /**************************
142 * UI and Widgets design
143 **************************/
144 setVLCWindowsTitle();
149 VLCMenuBar::createMenuBar( this, p_intf
);
150 CONNECT( THEMIM
->getIM(), voutListChanged( vout_thread_t
**, int ),
151 this, destroyPopupMenu() );
153 createMainWidget( settings
);
159 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
161 /********************
163 ********************/
164 MainInputManager::getInstance( p_intf
);
169 taskbar_wmsg
= RegisterWindowMessage("TaskbarButtonCreated");
172 /*********************************
173 * Create the Systray Management *
174 *********************************/
177 /*************************************************************
178 * Connect the input manager to the GUI elements it manages *
179 * Beware initSystray did some connects on input manager too *
180 *************************************************************/
182 * Connects on nameChanged()
183 * Those connects are different because options can impeach them to trigger.
185 /* Main Interface statusbar */
186 CONNECT( THEMIM
->getIM(), nameChanged( const QString
& ),
187 this, setName( const QString
& ) );
188 /* and title of the Main Interface*/
189 if( var_InheritBool( p_intf
, "qt-name-in-title" ) )
191 CONNECT( THEMIM
->getIM(), nameChanged( const QString
& ),
192 this, setVLCWindowsTitle( const QString
& ) );
194 /* END CONNECTS ON IM */
196 /* VideoWidget connects for asynchronous calls */
197 b_videoFullScreen
= false;
198 connect( this, SIGNAL(askGetVideo(WId
*,int*,int*,unsigned*,unsigned *)),
199 this, SLOT(getVideoSlot(WId
*,int*,int*,unsigned*,unsigned*)),
200 Qt::BlockingQueuedConnection
);
201 connect( this, SIGNAL(askReleaseVideo( void )),
202 this, SLOT(releaseVideoSlot( void )),
203 Qt::BlockingQueuedConnection
);
204 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
210 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
211 this, setVideoSize( unsigned int, unsigned int ) );
212 CONNECT( videoWidget
, sizeChanged( int, int ),
213 this, resizeStack( int, int ) );
215 CONNECT( this, askVideoSetFullScreen( bool ),
216 this, setVideoFullScreen( bool ) );
219 CONNECT( THEDP
, toolBarConfUpdated(), this, recreateToolbars() );
221 CONNECT( this, askToQuit(), THEDP
, quit() );
223 CONNECT( this, askBoss(), this, setBoss() );
224 CONNECT( this, askRaise(), this, setRaise() );
226 /** END of CONNECTS**/
232 var_AddCallback( p_intf
->p_libvlc
, "intf-toggle-fscontrol", IntfShowCB
, p_intf
);
233 var_AddCallback( p_intf
->p_libvlc
, "intf-boss", IntfBossCB
, p_intf
);
234 var_AddCallback( p_intf
->p_libvlc
, "intf-show", IntfRaiseMainCB
, p_intf
);
236 /* Register callback for the intf-popupmenu variable */
237 var_AddCallback( p_intf
->p_libvlc
, "intf-popupmenu", PopupMenuCB
, p_intf
);
240 /* Final Sizing, restoration and placement of the interface */
241 if( settings
->value( "MainWindow/playlist-visible", false ).toBool() )
244 QVLCTools::restoreWidgetPosition( settings
, this, QSize(600, 420) );
246 b_interfaceFullScreen
= isFullScreen();
248 setVisible( !b_hideAfterCreation
);
250 computeMinimumSize();
252 /* Switch to minimal view if needed, must be called after the show() */
254 toggleMinimalView( true );
257 MainInterface::~MainInterface()
259 /* Unsure we hide the videoWidget before destroying it */
260 if( stackCentralOldWidget
== videoWidget
)
268 ImageList_Destroy( himl
);
270 p_taskbl
->vt
->Release(p_taskbl
);
274 /* Be sure to kill the actionsManager... Only used in the MI and control */
275 ActionsManager::killInstance();
278 ExtensionsManager::killInstance();
280 /* Delete the FSC controller */
281 delete fullscreenControls
;
285 settings
->beginGroup("MainWindow");
286 settings
->setValue( "pl-dock-status", b_plDocked
);
287 /* Save playlist state */
289 settings
->setValue( "playlist-visible", playlistVisible
);
291 settings
->setValue( "adv-controls",
292 getControlsVisibilityStatus() & CONTROLS_ADVANCED
);
293 settings
->setValue( "status-bar-visible", b_statusbarVisible
);
295 /* Save the stackCentralW sizes */
296 settings
->setValue( "bgSize", stackWidgetsSizes
[bgWidget
] );
297 settings
->setValue( "playlistSize", stackWidgetsSizes
[playlistWidget
] );
298 settings
->endGroup();
301 QVLCTools::saveWidgetPosition(settings
, this);
303 /* Save undocked playlist size */
304 if( playlistWidget
&& !isPlDocked() )
305 QVLCTools::saveWidgetPosition( p_intf
, "Playlist", playlistWidget
);
307 delete playlistWidget
;
311 /* Unregister callbacks */
312 var_DelCallback( p_intf
->p_libvlc
, "intf-boss", IntfBossCB
, p_intf
);
313 var_DelCallback( p_intf
->p_libvlc
, "intf-show", IntfRaiseMainCB
, p_intf
);
314 var_DelCallback( p_intf
->p_libvlc
, "intf-toggle-fscontrol", IntfShowCB
, p_intf
);
315 var_DelCallback( p_intf
->p_libvlc
, "intf-popupmenu", PopupMenuCB
, p_intf
);
317 p_intf
->p_sys
->p_mi
= NULL
;
320 void MainInterface::computeMinimumSize()
323 if( menuBar()->isVisible() )
324 minWidth
+= __MAX( controls
->sizeHint().width(), menuBar()->sizeHint().width() );
326 setMinimumWidth( minWidth
);
329 /*****************************
331 *****************************/
332 void MainInterface::recreateToolbars()
334 bool b_adv
= getControlsVisibilityStatus() & CONTROLS_ADVANCED
;
339 controls
= new ControlsWidget( p_intf
, b_adv
, this );
340 inputC
= new InputControlsWidget( p_intf
, this );
341 mainLayout
->insertWidget( 2, inputC
);
342 mainLayout
->insertWidget( settings
->value( "MainWindow/ToolbarPos", 0 ).toInt() ? 0: 3,
345 if( fullscreenControls
)
347 delete fullscreenControls
;
348 fullscreenControls
= new FullscreenControllerWidget( p_intf
, this );
349 CONNECT( fullscreenControls
, keyPressed( QKeyEvent
* ),
350 this, handleKeyPress( QKeyEvent
* ) );
354 void MainInterface::reloadPrefs()
356 b_notificationEnabled
= var_InheritBool( p_intf
, "qt-notification" );
357 b_pauseOnMinimize
= var_InheritBool( p_intf
, "qt-pause-minimized" );
359 p_intf
->p_sys
->disable_volume_keys
= var_InheritBool( p_intf
, "qt-disable-volume-keys" );
361 if( !var_InheritBool( p_intf
, "qt-fs-controller" ) && fullscreenControls
)
363 delete fullscreenControls
;
364 fullscreenControls
= NULL
;
368 void MainInterface::createMainWidget( QSettings
*settings
)
370 /* Create the main Widget and the mainLayout */
371 QWidget
*main
= new QWidget
;
372 setCentralWidget( main
);
373 mainLayout
= new QVBoxLayout( main
);
374 main
->setContentsMargins( 0, 0, 0, 0 );
375 mainLayout
->setSpacing( 0 ); mainLayout
->setMargin( 0 );
378 stackCentralW
= new QVLCStackedWidget( main
);
381 bgWidget
= new BackgroundWidget( p_intf
);
382 stackCentralW
->addWidget( bgWidget
);
383 if ( !var_InheritBool( p_intf
, "qt-bgcone" ) )
384 bgWidget
->setWithArt( false );
386 if ( var_InheritBool( p_intf
, "qt-bgcone-expands" ) )
387 bgWidget
->setExpandstoHeight( true );
389 /* And video Outputs */
390 if( b_videoEmbedded
)
392 videoWidget
= new VideoWidget( p_intf
);
393 stackCentralW
->addWidget( videoWidget
);
395 mainLayout
->insertWidget( 1, stackCentralW
);
397 stackWidgetsSizes
[bgWidget
] = settings
->value( "MainWindow/bgSize", QSize( 600, 0 ) ).toSize();
398 /* Resize even if no-auto-resize, because we are at creation */
399 resizeStack( stackWidgetsSizes
[bgWidget
].width(), stackWidgetsSizes
[bgWidget
].height() );
401 /* Create the CONTROLS Widget */
402 controls
= new ControlsWidget( p_intf
,
403 settings
->value( "MainWindow/adv-controls", false ).toBool(), this );
404 inputC
= new InputControlsWidget( p_intf
, this );
406 mainLayout
->insertWidget( 2, inputC
);
407 mainLayout
->insertWidget( settings
->value( "MainWindow/ToolbarPos", 0 ).toInt() ? 0: 3,
410 /* Visualisation, disabled for now, they SUCK */
412 visualSelector
= new VisualSelector( p_intf
);
413 mainLayout
->insertWidget( 0, visualSelector
);
414 visualSelector
->hide();
418 /* Enable the popup menu in the MI */
419 main
->setContextMenuPolicy( Qt::CustomContextMenu
);
420 CONNECT( main
, customContextMenuRequested( const QPoint
& ),
421 this, popupMenu( const QPoint
& ) );
423 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
424 /* Create the FULLSCREEN CONTROLS Widget */
425 if( var_InheritBool( p_intf
, "qt-fs-controller" ) )
427 fullscreenControls
= new FullscreenControllerWidget( p_intf
, this );
428 CONNECT( fullscreenControls
, keyPressed( QKeyEvent
* ),
429 this, handleKeyPress( QKeyEvent
* ) );
433 inline void MainInterface::initSystray()
435 bool b_systrayAvailable
= QSystemTrayIcon::isSystemTrayAvailable();
436 bool b_systrayWanted
= var_InheritBool( p_intf
, "qt-system-tray" );
438 if( var_InheritBool( p_intf
, "qt-start-minimized") )
440 if( b_systrayAvailable
)
442 b_systrayWanted
= true;
443 b_hideAfterCreation
= true;
446 msg_Err( p_intf
, "cannot start minimized without system tray bar" );
449 if( b_systrayAvailable
&& b_systrayWanted
)
453 inline void MainInterface::createStatusBar()
458 /* Widgets Creation*/
459 QStatusBar
*statusBarr
= statusBar();
461 TimeLabel
*timeLabel
= new TimeLabel( p_intf
);
462 nameLabel
= new QLabel( this );
463 nameLabel
->setTextInteractionFlags( Qt::TextSelectableByMouse
464 | Qt::TextSelectableByKeyboard
);
465 SpeedLabel
*speedLabel
= new SpeedLabel( p_intf
, this );
467 /* Styling those labels */
468 timeLabel
->setFrameStyle( QFrame::Sunken
| QFrame::Panel
);
469 speedLabel
->setFrameStyle( QFrame::Sunken
| QFrame::Panel
);
470 nameLabel
->setFrameStyle( QFrame::Sunken
| QFrame::StyledPanel
);
471 timeLabel
->setStyleSheet(
472 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
473 speedLabel
->setStyleSheet(
474 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
475 /* pad both label and its tooltip */
476 nameLabel
->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
478 /* and adding those */
479 statusBarr
->addWidget( nameLabel
, 8 );
480 statusBarr
->addPermanentWidget( speedLabel
, 0 );
481 statusBarr
->addPermanentWidget( timeLabel
, 0 );
483 /* timeLabel behaviour:
484 - double clicking opens the goto time dialog
485 - right-clicking and clicking just toggle between remaining and
487 CONNECT( timeLabel
, timeLabelDoubleClicked(), THEDP
, gotoTimeDialog() );
489 CONNECT( THEMIM
->getIM(), encryptionChanged( bool ),
490 this, showCryptedLabel( bool ) );
492 CONNECT( THEMIM
->getIM(), seekRequested( float ),
493 timeLabel
, setDisplayPosition( float ) );
495 /* This shouldn't be necessary, but for somehow reason, the statusBarr
496 starts at height of 20px and when a text is shown it needs more space.
497 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
498 geometry, we need to force a height. If you have a better idea, please
501 statusBarr
->setFixedHeight( statusBarr
->sizeHint().height() + 2 );
504 /**********************************************************************
505 * Handling of sizing of the components
506 **********************************************************************/
508 void MainInterface::debug()
511 msg_Dbg( p_intf
, "size: %i - %i", size().height(), size().width() );
512 msg_Dbg( p_intf
, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
513 msg_Dbg( p_intf
, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
515 msg_Dbg( p_intf
, "Stack size: %i - %i", stackCentralW
->size().height(), stackCentralW
->size().width() );
516 msg_Dbg( p_intf
, "Stack sizeHint: %i - %i", stackCentralW
->sizeHint().height(), stackCentralW
->sizeHint().width() );
517 msg_Dbg( p_intf
, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
521 inline void MainInterface::showVideo() { showTab( videoWidget
); }
522 inline void MainInterface::restoreStackOldWidget()
523 { showTab( stackCentralOldWidget
); }
525 inline void MainInterface::showTab( QWidget
*widget
)
528 msg_Warn( p_intf
, "Old stackCentralOldWidget %i", stackCentralW
->indexOf( stackCentralOldWidget
) );
531 stackCentralOldWidget
= stackCentralW
->currentWidget();
532 stackWidgetsSizes
[stackCentralOldWidget
] = stackCentralW
->size();
534 /* If we are playing video, embedded */
535 if( videoWidget
&& THEMIM
->getIM()->hasVideo() )
537 /* Video -> Playlist */
538 if( videoWidget
== stackCentralOldWidget
&& widget
== playlistWidget
)
540 stackCentralW
->removeWidget( videoWidget
);
541 videoWidget
->show(); videoWidget
->raise();
544 /* Playlist -> Video */
545 if( playlistWidget
== stackCentralOldWidget
&& widget
== videoWidget
)
547 playlistWidget
->artContainer
->removeWidget( videoWidget
);
548 videoWidget
->show(); videoWidget
->raise();
549 stackCentralW
->addWidget( videoWidget
);
553 stackCentralW
->setCurrentWidget( widget
);
555 resizeStack( stackWidgetsSizes
[widget
].width(), stackWidgetsSizes
[widget
].height() );
558 msg_Warn( p_intf
, "State change %i", stackCentralW
->currentIndex() );
559 msg_Warn( p_intf
, "New stackCentralOldWidget %i", stackCentralW
->indexOf( stackCentralOldWidget
) );
562 /* This part is done later, to account for the new pl size */
563 if( videoWidget
&& THEMIM
->getIM()->hasVideo() &&
564 videoWidget
== stackCentralOldWidget
&& widget
== playlistWidget
)
566 playlistWidget
->artContainer
->addWidget( videoWidget
);
567 playlistWidget
->artContainer
->setCurrentWidget( videoWidget
);
571 void MainInterface::destroyPopupMenu()
573 VLCMenuBar::PopupMenu( p_intf
, false );
576 void MainInterface::popupMenu( const QPoint
& )
578 VLCMenuBar::PopupMenu( p_intf
, true );
581 void MainInterface::toggleFSC()
583 if( !fullscreenControls
) return;
585 IMEvent
*eShow
= new IMEvent( FullscreenControlToggle_Type
);
586 QApplication::postEvent( fullscreenControls
, eShow
);
589 /****************************************************************************
591 ****************************************************************************/
595 * You must not change the state of this object or other Qt4 UI objects,
596 * from the video output thread - only from the Qt4 UI main loop thread.
597 * All window provider queries must be handled through signals or events.
598 * That's why we have all those emit statements...
600 WId
MainInterface::getVideo( int *pi_x
, int *pi_y
,
601 unsigned int *pi_width
, unsigned int *pi_height
)
606 /* This is a blocking call signal. Results are returned through pointers.
607 * Beware of deadlocks! */
609 emit
askGetVideo( &id
, pi_x
, pi_y
, pi_width
, pi_height
);
613 void MainInterface::getVideoSlot( WId
*p_id
, int *pi_x
, int *pi_y
,
614 unsigned *pi_width
, unsigned *pi_height
)
616 /* Hidden or minimized, activate */
617 if( isHidden() || isMinimized() )
618 toggleUpdateSystrayMenu();
620 /* Request the videoWidget */
621 WId ret
= videoWidget
->request( pi_x
, pi_y
,
622 pi_width
, pi_height
, !b_autoresize
);
624 if( ret
) /* The videoWidget is available */
626 /* Consider the video active now */
629 /* Ask videoWidget to resize correctly, if we are in normal mode */
630 if( !isFullScreen() && !isMaximized() && b_autoresize
)
631 videoWidget
->SetSizing( *pi_width
, *pi_height
);
635 /* Asynchronous call from the WindowClose function */
636 void MainInterface::releaseVideo( void )
638 emit
askReleaseVideo();
641 /* Function that is CONNECTED to the previous emit */
642 void MainInterface::releaseVideoSlot( void )
644 /* This function is called when the embedded video window is destroyed,
645 * or in the rare case that the embedded window is still here but the
646 * Qt4 interface exits. */
647 assert( videoWidget
);
648 videoWidget
->release();
649 setVideoOnTop( false );
650 setVideoFullScreen( false );
652 if( stackCentralW
->currentWidget() == videoWidget
)
653 restoreStackOldWidget();
654 else if( playlistWidget
&&
655 playlistWidget
->artContainer
->currentWidget() == videoWidget
)
657 playlistWidget
->artContainer
->setCurrentIndex( 0 );
658 stackCentralW
->addWidget( videoWidget
);
661 /* We don't want to have a blank video to popup */
662 stackCentralOldWidget
= bgWidget
;
665 void MainInterface::setVideoSize( unsigned int w
, unsigned int h
)
667 if( !isFullScreen() && !isMaximized() )
668 videoWidget
->SetSizing( w
, h
);
671 void MainInterface::setVideoFullScreen( bool fs
)
673 b_videoFullScreen
= fs
;
676 int numscreen
= var_InheritInteger( p_intf
, "qt-fullscreen-screennumber" );
677 /* if user hasn't defined screennumber, or screennumber that is bigger
678 * than current number of screens, take screennumber where current interface
681 if( numscreen
== -1 || numscreen
> QApplication::desktop()->numScreens() )
682 numscreen
= QApplication::desktop()->screenNumber( p_intf
->p_sys
->p_mi
);
684 QRect screenres
= QApplication::desktop()->screenGeometry( numscreen
);
686 /* To be sure window is on proper-screen in xinerama */
687 if( !screenres
.contains( pos() ) )
689 msg_Dbg( p_intf
, "Moving video to correct screen");
690 move( QPoint( screenres
.x(), screenres
.y() ) );
694 if( playlistWidget
!= NULL
&& playlistWidget
->artContainer
->currentWidget() == videoWidget
)
696 showTab( videoWidget
);
700 setMinimalView( true );
701 setInterfaceFullScreen( true );
705 /* TODO do we want to restore screen and position ? (when
706 * qt-fullscreen-screennumber is forced) */
707 setMinimalView( b_minimalView
);
708 setInterfaceFullScreen( b_interfaceFullScreen
);
713 /* Slot to change the video always-on-top flag.
714 * Emit askVideoOnTop() to invoke this from other thread. */
715 void MainInterface::setVideoOnTop( bool on_top
)
717 Qt::WindowFlags oldflags
= windowFlags(), newflags
;
720 newflags
= oldflags
| Qt::WindowStaysOnTopHint
;
722 newflags
= oldflags
& ~Qt::WindowStaysOnTopHint
;
723 if( newflags
!= oldflags
&& !b_videoFullScreen
)
726 setWindowFlags( newflags
);
727 show(); /* necessary to apply window flags */
731 /* Asynchronous call from WindowControl function */
732 int MainInterface::controlVideo( int i_query
, va_list args
)
736 case VOUT_WINDOW_SET_SIZE
:
738 unsigned int i_width
= va_arg( args
, unsigned int );
739 unsigned int i_height
= va_arg( args
, unsigned int );
741 emit
askVideoToResize( i_width
, i_height
);
744 case VOUT_WINDOW_SET_STATE
:
746 unsigned i_arg
= va_arg( args
, unsigned );
747 unsigned on_top
= i_arg
& VOUT_WINDOW_STATE_ABOVE
;
749 emit
askVideoOnTop( on_top
!= 0 );
752 case VOUT_WINDOW_SET_FULLSCREEN
:
754 bool b_fs
= va_arg( args
, int );
756 emit
askVideoSetFullScreen( b_fs
);
760 msg_Warn( p_intf
, "unsupported control query" );
765 /*****************************************************************************
766 * Playlist, Visualisation and Menus handling
767 *****************************************************************************/
769 * Toggle the playlist widget or dialog
771 void MainInterface::createPlaylist()
773 playlistWidget
= new PlaylistWidget( p_intf
, this );
777 stackCentralW
->addWidget( playlistWidget
);
778 stackWidgetsSizes
[playlistWidget
] = settings
->value( "playlistSize", QSize( 600, 300 ) ).toSize();
783 playlistWidget
->setParent( NULL
);
785 playlistWidget
->setWindowFlags( Qt::Window
);
787 /* This will restore the geometry but will not work for position,
788 because of parenting */
789 QVLCTools::restoreWidgetPosition( p_intf
, "Playlist",
790 playlistWidget
, QSize( 600, 300 ) );
794 void MainInterface::togglePlaylist()
796 if( !playlistWidget
)
803 /* Playlist is not visible, show it */
804 if( stackCentralW
->currentWidget() != playlistWidget
)
806 showTab( playlistWidget
);
810 restoreStackOldWidget();
812 playlistVisible
= ( stackCentralW
->currentWidget() == playlistWidget
);
817 playlistWidget
->setParent( NULL
);
819 playlistWidget
->setWindowFlags( Qt::Window
);
820 playlistVisible
= !playlistVisible
;
821 playlistWidget
->setVisible( playlistVisible
);
826 void MainInterface::dockPlaylist( bool p_docked
)
828 if( b_plDocked
== p_docked
) return;
829 b_plDocked
= p_docked
;
831 if( !playlistWidget
) return; /* Playlist wasn't created yet */
834 stackCentralW
->removeWidget( playlistWidget
);
836 playlistWidget
->setParent( NULL
);
838 playlistWidget
->setWindowFlags( Qt::Window
);
839 QVLCTools::restoreWidgetPosition( p_intf
, "Playlist",
840 playlistWidget
, QSize( 600, 300 ) );
841 playlistWidget
->show();
842 restoreStackOldWidget();
846 QVLCTools::saveWidgetPosition( p_intf
, "Playlist", playlistWidget
);
847 playlistWidget
->setWindowFlags( Qt::Widget
); // Probably a Qt bug here
848 // It would be logical that QStackWidget::addWidget reset the flags...
849 stackCentralW
->addWidget( playlistWidget
);
850 showTab( playlistWidget
);
852 playlistVisible
= true;
856 * setMinimalView is the private function used by
857 * the SLOT toggleMinimalView and setVideoFullScreen
859 void MainInterface::setMinimalView( bool b_minimal
)
861 menuBar()->setVisible( !b_minimal
);
862 controls
->setVisible( !b_minimal
);
863 statusBar()->setVisible( !b_minimal
&& b_statusbarVisible
);
864 inputC
->setVisible( !b_minimal
);
868 * This public SLOT is used for moving to minimal View Mode
870 * If b_minimal is false, then we are normalView
872 void MainInterface::toggleMinimalView( bool b_minimal
)
874 if( !b_minimalView
&& b_autoresize
) /* Normal mode */
876 if( stackCentralW
->currentWidget() == bgWidget
)
878 if( stackCentralW
->height() < 16 )
880 resizeStack( stackCentralW
->width(), 100 );
884 b_minimalView
= b_minimal
;
885 if( !b_videoFullScreen
)
887 setMinimalView( b_minimalView
);
888 computeMinimumSize();
891 emit
minimalViewToggled( b_minimalView
);
894 /* toggling advanced controls buttons */
895 void MainInterface::toggleAdvancedButtons()
897 controls
->toggleAdvanced();
898 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
901 /* Get the visibility status of the controls (hidden or not, advanced or not) */
902 int MainInterface::getControlsVisibilityStatus()
904 if( !controls
) return 0;
905 return( (controls
->isVisible() ? CONTROLS_VISIBLE
: CONTROLS_HIDDEN
)
906 + CONTROLS_ADVANCED
* controls
->b_advancedVisible
);
909 void MainInterface::setStatusBarVisibility( bool b_visible
)
911 statusBar()->setVisible( b_visible
);
912 b_statusbarVisible
= b_visible
;
913 if( controls
) controls
->setGripVisible( !b_statusbarVisible
);
917 void MainInterface::visual()
919 if( !VISIBLE( visualSelector
) )
921 visualSelector
->show();
922 if( !THEMIM
->getIM()->hasVideo() )
924 /* Show the background widget */
926 visualSelectorEnabled
= true;
930 /* Stop any currently running visualization */
931 visualSelector
->hide();
932 visualSelectorEnabled
= false;
937 /************************************************************************
939 ************************************************************************/
940 void MainInterface::setName( const QString
& name
)
942 input_name
= name
; /* store it for the QSystray use */
943 /* Display it in the status bar, but also as a Tooltip in case it doesn't
945 nameLabel
->setText( name
);
946 nameLabel
->setToolTip( name
);
950 * Give the decorations of the Main Window a correct Name.
951 * If nothing is given, set it to VLC...
953 void MainInterface::setVLCWindowsTitle( const QString
& aTitle
)
955 if( aTitle
.isEmpty() )
957 setWindowTitle( qtr( "VLC media player" ) );
961 setWindowTitle( aTitle
+ " - " + qtr( "VLC media player" ) );
965 void MainInterface::showCryptedLabel( bool b_show
)
967 if( cryptedLabel
== NULL
)
969 cryptedLabel
= new QLabel
;
970 // The lock icon is not the right one for DRM protection/scrambled.
971 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
972 cryptedLabel
->setText( "DRM" );
973 statusBar()->addWidget( cryptedLabel
);
976 cryptedLabel
->setVisible( b_show
);
979 void MainInterface::showBuffering( float f_cache
)
981 QString amount
= QString("Buffering: %1%").arg( (int)(100*f_cache
) );
982 statusBar()->showMessage( amount
, 1000 );
985 /*****************************************************************************
986 * Systray Icon and Systray Menu
987 *****************************************************************************/
989 * Create a SystemTray icon and a menu that would go with it.
990 * Connects to a click handler on the icon.
992 void MainInterface::createSystray()
995 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY
&& var_InheritBool( p_intf
, "qt-icon-change" ) )
996 iconVLC
= QIcon( ":/logo/vlc128-xmas.png" );
998 iconVLC
= QIcon( ":/logo/vlc128.png" );
999 sysTray
= new QSystemTrayIcon( iconVLC
, this );
1000 sysTray
->setToolTip( qtr( "VLC media player" ));
1002 systrayMenu
= new QMenu( qtr( "VLC media player" ), this );
1003 systrayMenu
->setIcon( iconVLC
);
1005 VLCMenuBar::updateSystrayMenu( this, p_intf
, true );
1008 CONNECT( sysTray
, activated( QSystemTrayIcon::ActivationReason
),
1009 this, handleSystrayClick( QSystemTrayIcon::ActivationReason
) );
1011 /* Connects on nameChanged() */
1012 CONNECT( THEMIM
->getIM(), nameChanged( const QString
& ),
1013 this, updateSystrayTooltipName( const QString
& ) );
1014 /* Connect PLAY_STATUS on the systray */
1015 CONNECT( THEMIM
->getIM(), playingStatusChanged( int ),
1016 this, updateSystrayTooltipStatus( int ) );
1020 * Updates the Systray Icon's menu and toggle the main interface
1022 void MainInterface::toggleUpdateSystrayMenu()
1024 /* If hidden, show it */
1030 else if( isMinimized() )
1038 /* Visible (possibly under other windows) */
1040 /* check if any visible window is above vlc in the z-order,
1041 * but ignore the ones always on top
1042 * and the ones which can't be activated */
1045 wi
.cbSize
= sizeof( WINDOWINFO
);
1046 for( hwnd
= GetNextWindow( internalWinId(), GW_HWNDPREV
);
1047 hwnd
&& ( !IsWindowVisible( hwnd
) ||
1048 ( GetWindowInfo( hwnd
, &wi
) &&
1049 (wi
.dwExStyle
&WS_EX_NOACTIVATE
) ) );
1050 hwnd
= GetNextWindow( hwnd
, GW_HWNDPREV
) );
1051 if( !hwnd
|| !GetWindowInfo( hwnd
, &wi
) ||
1052 (wi
.dwExStyle
&WS_EX_TOPMOST
) )
1065 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1068 /* First Item of the systray menu */
1069 void MainInterface::showUpdateSystrayMenu()
1077 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1080 /* First Item of the systray menu */
1081 void MainInterface::hideUpdateSystrayMenu()
1084 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1087 /* Click on systray Icon */
1088 void MainInterface::handleSystrayClick(
1089 QSystemTrayIcon::ActivationReason reason
)
1093 case QSystemTrayIcon::Trigger
:
1094 case QSystemTrayIcon::DoubleClick
:
1096 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1098 toggleUpdateSystrayMenu();
1101 case QSystemTrayIcon::MiddleClick
:
1102 sysTray
->showMessage( qtr( "VLC media player" ),
1103 qtr( "Control menu for the player" ),
1104 QSystemTrayIcon::Information
, 3000 );
1112 * Updates the name of the systray Icon tooltip.
1113 * Doesn't check if the systray exists, check before you call it.
1115 void MainInterface::updateSystrayTooltipName( const QString
& name
)
1117 if( name
.isEmpty() )
1119 sysTray
->setToolTip( qtr( "VLC media player" ) );
1123 sysTray
->setToolTip( name
);
1124 if( b_notificationEnabled
&& ( isHidden() || isMinimized() ) )
1126 sysTray
->showMessage( qtr( "VLC media player" ), name
,
1127 QSystemTrayIcon::NoIcon
, 3000 );
1131 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1135 * Updates the status of the systray Icon tooltip.
1136 * Doesn't check if the systray exists, check before you call it.
1138 void MainInterface::updateSystrayTooltipStatus( int i_status
)
1143 sysTray
->setToolTip( input_name
);
1146 sysTray
->setToolTip( input_name
+ " - " + qtr( "Paused") );
1149 sysTray
->setToolTip( qtr( "VLC media player" ) );
1152 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1155 void MainInterface::changeEvent(QEvent
*event
)
1157 if( event
->type() == QEvent::WindowStateChange
)
1159 QWindowStateChangeEvent
*windowStateChangeEvent
= static_cast<QWindowStateChangeEvent
*>(event
);
1160 Qt::WindowStates newState
= windowState();
1161 Qt::WindowStates oldState
= windowStateChangeEvent
->oldState();
1163 if( newState
& Qt::WindowMinimized
)
1165 b_hasPausedWhenMinimized
= false;
1167 if( THEMIM
->getIM()->playingStatus() == PLAYING_S
&&
1168 THEMIM
->getIM()->hasVideo() && !THEMIM
->getIM()->hasVisualisation() &&
1171 b_hasPausedWhenMinimized
= true;
1175 else if( oldState
& Qt::WindowMinimized
&& !( newState
& Qt::WindowMinimized
) )
1177 if( b_hasPausedWhenMinimized
)
1184 QWidget::changeEvent(event
);
1187 /************************************************************************
1189 ************************************************************************/
1190 void MainInterface::dropEvent(QDropEvent
*event
)
1192 dropEventPlay( event
, true );
1198 * Event called if something is dropped onto a VLC window
1199 * \param event the event in question
1200 * \param b_play whether to play the file immediately
1201 * \param b_playlist true to add to playlist, false to add to media library
1204 void MainInterface::dropEventPlay( QDropEvent
*event
, bool b_play
, bool b_playlist
)
1206 if( event
->possibleActions() & ( Qt::CopyAction
| Qt::MoveAction
) )
1207 event
->setDropAction( Qt::CopyAction
);
1211 const QMimeData
*mimeData
= event
->mimeData();
1213 /* D&D of a subtitles file, add it on the fly */
1214 if( mimeData
->urls().count() == 1 && THEMIM
->getIM()->hasInput() )
1216 if( !input_AddSubtitle( THEMIM
->getInput(),
1217 qtu( toNativeSeparators( mimeData
->urls()[0].toLocalFile() ) ),
1225 bool first
= b_play
;
1226 foreach( const QUrl
&url
, mimeData
->urls() )
1230 QString mrl
= toURI( url
.toEncoded().constData() );
1231 playlist_Add( THEPL
, qtu(mrl
), NULL
,
1232 PLAYLIST_APPEND
| (first
? PLAYLIST_GO
: PLAYLIST_PREPARSE
),
1233 PLAYLIST_END
, b_playlist
, pl_Unlocked
);
1235 RecentsMRL::getInstance( p_intf
)->addRecent( mrl
);
1239 /* Browsers give content as text if you dnd the addressbar,
1240 so check if mimedata has valid url in text and use it
1241 if we didn't get any normal Urls()*/
1242 if( !mimeData
->hasUrls() && mimeData
->hasText() &&
1243 QUrl(mimeData
->text()).isValid() )
1245 QString mrl
= toURI( mimeData
->text() );
1246 playlist_Add( THEPL
, qtu(mrl
), NULL
,
1247 PLAYLIST_APPEND
| (first
? PLAYLIST_GO
: PLAYLIST_PREPARSE
),
1248 PLAYLIST_END
, b_playlist
, pl_Unlocked
);
1252 void MainInterface::dragEnterEvent(QDragEnterEvent
*event
)
1254 event
->acceptProposedAction();
1256 void MainInterface::dragMoveEvent(QDragMoveEvent
*event
)
1258 event
->acceptProposedAction();
1260 void MainInterface::dragLeaveEvent(QDragLeaveEvent
*event
)
1265 /************************************************************************
1267 ************************************************************************/
1268 void MainInterface::keyPressEvent( QKeyEvent
*e
)
1270 handleKeyPress( e
);
1273 void MainInterface::handleKeyPress( QKeyEvent
*e
)
1275 if( ( e
->modifiers() & Qt::ControlModifier
) && ( e
->key() == Qt::Key_H
) )
1277 toggleMinimalView( !b_minimalView
);
1281 int i_vlck
= qtEventToVLCKey( e
);
1284 var_SetInteger( p_intf
->p_libvlc
, "key-pressed", i_vlck
);
1291 void MainInterface::wheelEvent( QWheelEvent
*e
)
1293 int i_vlckey
= qtWheelEventToVLCKey( e
);
1294 var_SetInteger( p_intf
->p_libvlc
, "key-pressed", i_vlckey
);
1298 void MainInterface::closeEvent( QCloseEvent
*e
)
1301 emit
askToQuit(); /* ask THEDP to quit, so we have a unique method */
1302 /* Accept session quit. Otherwise we break the desktop mamager. */
1306 void MainInterface::setInterfaceFullScreen( bool fs
)
1309 setWindowState( windowState() | Qt::WindowFullScreen
);
1311 setWindowState( windowState() & ~Qt::WindowFullScreen
);
1313 void MainInterface::toggleInterfaceFullScreen()
1315 b_interfaceFullScreen
= !b_interfaceFullScreen
;
1316 if( !b_videoFullScreen
)
1317 setInterfaceFullScreen( b_interfaceFullScreen
);
1318 emit
fullscreenInterfaceToggled( b_interfaceFullScreen
);
1321 void MainInterface::emitBoss()
1325 void MainInterface::setBoss()
1338 void MainInterface::emitRaise()
1342 void MainInterface::setRaise()
1348 /*****************************************************************************
1349 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1350 * We don't show the menu directly here because we don't want the
1351 * caller to block for a too long time.
1352 *****************************************************************************/
1353 static int PopupMenuCB( vlc_object_t
*p_this
, const char *psz_variable
,
1354 vlc_value_t old_val
, vlc_value_t new_val
, void *param
)
1356 VLC_UNUSED( p_this
); VLC_UNUSED( psz_variable
); VLC_UNUSED( old_val
);
1358 intf_thread_t
*p_intf
= (intf_thread_t
*)param
;
1360 if( p_intf
->pf_show_dialog
)
1362 p_intf
->pf_show_dialog( p_intf
, INTF_DIALOG_POPUPMENU
,
1363 new_val
.b_bool
, NULL
);
1369 /*****************************************************************************
1370 * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1371 *****************************************************************************/
1372 static int IntfShowCB( vlc_object_t
*p_this
, const char *psz_variable
,
1373 vlc_value_t old_val
, vlc_value_t new_val
, void *param
)
1375 VLC_UNUSED( p_this
); VLC_UNUSED( psz_variable
); VLC_UNUSED( old_val
);
1376 VLC_UNUSED( new_val
);
1378 intf_thread_t
*p_intf
= (intf_thread_t
*)param
;
1379 p_intf
->p_sys
->p_mi
->toggleFSC();
1385 /*****************************************************************************
1386 * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1387 *****************************************************************************/
1388 static int IntfRaiseMainCB( vlc_object_t
*p_this
, const char *psz_variable
,
1389 vlc_value_t old_val
, vlc_value_t new_val
, void *param
)
1391 VLC_UNUSED( p_this
); VLC_UNUSED( psz_variable
); VLC_UNUSED( old_val
);
1392 VLC_UNUSED( new_val
);
1394 intf_thread_t
*p_intf
= (intf_thread_t
*)param
;
1395 p_intf
->p_sys
->p_mi
->emitRaise();
1400 /*****************************************************************************
1401 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1402 *****************************************************************************/
1403 static int IntfBossCB( vlc_object_t
*p_this
, const char *psz_variable
,
1404 vlc_value_t old_val
, vlc_value_t new_val
, void *param
)
1406 VLC_UNUSED( p_this
); VLC_UNUSED( psz_variable
); VLC_UNUSED( old_val
);
1407 VLC_UNUSED( new_val
);
1409 intf_thread_t
*p_intf
= (intf_thread_t
*)param
;
1410 p_intf
->p_sys
->p_mi
->emitBoss();