1 /*****************************************************************************
2 * main_interface.cpp : Main interface
3 ****************************************************************************
4 * Copyright (C) 2006-2010 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 );
74 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
76 /* Variables initialisation */
79 playlistWidget = NULL;
80 stackCentralOldWidget= NULL;
84 fullscreenControls = NULL;
89 b_hideAfterCreation = false; // --qt-start-minimized
90 playlistVisible = false;
92 b_interfaceFullScreen= false;
96 FirstRun::CheckAndRun( this, p_intf );
99 * Configuration and settings
100 * Pre-building of interface
103 setFocusPolicy( Qt::StrongFocus );
104 setAcceptDrops( true );
105 setWindowRole( "vlc-main" );
106 setWindowIcon( QApplication::windowIcon() );
107 setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
109 setAttribute( Qt::WA_MacBrushedMetal );
112 /* Is video in embedded in the UI or not */
113 b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
115 /* Does the interface resize to video size or the opposite */
116 b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
118 /* Are we in the enhanced always-video mode or not ? */
119 b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
121 /* Do we want anoying popups or not */
122 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
124 /* Set the other interface settings */
125 settings = getSettings();
126 settings->beginGroup( "MainWindow" );
130 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
134 b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
136 settings->endGroup( );
138 /*********************************
139 * Create the Systray Management *
140 *********************************/
143 /**************************
144 * UI and Widgets design
145 **************************/
146 setVLCWindowsTitle();
151 QVLCMenu::createMenuBar( this, p_intf );
152 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
153 this, destroyPopupMenu() );
155 createMainWidget( settings );
161 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
163 /********************
165 ********************/
166 MainInputManager::getInstance( p_intf );
171 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
174 /************************************************************
175 * Connect the input manager to the GUI elements it manages *
176 ************************************************************/
178 * Connects on nameChanged()
179 * Those connects are different because options can impeach them to trigger.
181 /* Main Interface statusbar */
182 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
183 this, setName( const QString& ) );
188 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
189 this, updateSystrayTooltipName( const QString& ) );
192 /* and title of the Main Interface*/
193 if( var_InheritBool( p_intf, "qt-name-in-title" ) )
195 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
196 this, setVLCWindowsTitle( const QString& ) );
200 * CONNECTS on PLAY_STATUS
202 /* Status on the systray */
206 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
207 this, updateSystrayTooltipStatus( int ) );
211 /* END CONNECTS ON IM */
213 /* VideoWidget connects for asynchronous calls */
214 b_videoFullScreen = false;
215 connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
216 this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
217 Qt::BlockingQueuedConnection );
218 connect( this, SIGNAL(askReleaseVideo( void )),
219 this, SLOT(releaseVideoSlot( void )),
220 Qt::BlockingQueuedConnection );
221 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
227 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
228 this, setVideoSize( unsigned int, unsigned int ) );
229 CONNECT( videoWidget, sizeChanged( int, int ),
230 this, resizeStack( int, int ) );
232 CONNECT( this, askVideoSetFullScreen( bool ),
233 this, setVideoFullScreen( bool ) );
236 CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
238 CONNECT( this, askToQuit(), THEDP, quit() );
240 CONNECT( this, askBoss(), this, setBoss() );
242 /** END of CONNECTS**/
248 var_AddCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
249 var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
251 /* Register callback for the intf-popupmenu variable */
252 var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
255 int i_plVis = settings->value( "MainWindow/playlist-visible", false ).toBool();
257 if( i_plVis ) togglePlaylist();
259 /**** FINAL SIZING and placement of interface */
260 settings->beginGroup( "MainWindow" );
261 QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
262 settings->endGroup();
264 b_interfaceFullScreen = isFullScreen();
266 /* Final sizing and showing */
267 setVisible( !b_hideAfterCreation );
269 computeMinimumSize();
271 /* Switch to minimal view if needed, must be called after the show() */
273 toggleMinimalView( true );
275 b_hasPausedWhenMinimized = false;
278 MainInterface::~MainInterface()
280 /* Unsure we hide the videoWidget before destroying it */
281 if( stackCentralOldWidget == videoWidget )
289 ImageList_Destroy( himl );
291 p_taskbl->vt->Release(p_taskbl);
295 /* Be sure to kill the actionsManager... Only used in the MI and control */
296 ActionsManager::killInstance();
299 ExtensionsManager::killInstance();
301 /* Delete the FSC controller */
302 delete fullscreenControls;
305 settings->beginGroup( "MainWindow" );
307 settings->setValue( "pl-dock-status", b_plDocked );
308 /* Save playlist state */
310 settings->setValue( "playlist-visible", playlistVisible );
312 settings->setValue( "adv-controls",
313 getControlsVisibilityStatus() & CONTROLS_ADVANCED );
314 settings->setValue( "status-bar-visible", b_statusbarVisible );
316 /* Save the stackCentralW sizes */
317 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
318 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
321 QVLCTools::saveWidgetPosition(settings, this);
323 settings->endGroup();
325 /* Save undocked playlist size */
326 if( playlistWidget && !isPlDocked() )
327 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
329 delete playlistWidget;
333 /* Unregister callbacks */
334 var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
335 var_DelCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
336 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
338 p_intf->p_sys->p_mi = NULL;
341 void MainInterface::computeMinimumSize()
344 if( menuBar()->isVisible() )
345 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
347 setMinimumWidth( minWidth );
350 /*****************************
352 *****************************/
353 void MainInterface::recreateToolbars()
355 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
357 settings->beginGroup( "MainWindow" );
361 controls = new ControlsWidget( p_intf, b_adv, this );
362 inputC = new InputControlsWidget( p_intf, this );
364 if( fullscreenControls )
366 delete fullscreenControls;
367 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
368 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
369 this, handleKeyPress( QKeyEvent * ) );
371 mainLayout->insertWidget( 2, inputC );
372 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
374 settings->endGroup();
377 void MainInterface::createMainWidget( QSettings *settings )
379 /* Create the main Widget and the mainLayout */
380 QWidget *main = new QWidget;
381 setCentralWidget( main );
382 mainLayout = new QVBoxLayout( main );
383 main->setContentsMargins( 0, 0, 0, 0 );
384 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
387 stackCentralW = new QVLCStackedWidget( main );
390 bgWidget = new BackgroundWidget( p_intf );
391 stackCentralW->addWidget( bgWidget );
392 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
393 bgWidget->setWithArt( false );
395 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
396 bgWidget->setExpandstoHeight( true );
398 /* And video Outputs */
399 if( b_videoEmbedded )
401 videoWidget = new VideoWidget( p_intf );
402 stackCentralW->addWidget( videoWidget );
404 mainLayout->insertWidget( 1, stackCentralW );
406 settings->beginGroup( "MainWindow" );
407 stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 600, 0 ) ).toSize();
408 /* Resize even if no-auto-resize, because we are at creation */
409 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
411 /* Create the CONTROLS Widget */
412 controls = new ControlsWidget( p_intf,
413 settings->value( "adv-controls", false ).toBool(), this );
414 inputC = new InputControlsWidget( p_intf, this );
416 mainLayout->insertWidget( 2, inputC );
417 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
420 /* Visualisation, disabled for now, they SUCK */
422 visualSelector = new VisualSelector( p_intf );
423 mainLayout->insertWidget( 0, visualSelector );
424 visualSelector->hide();
427 settings->endGroup();
429 /* Enable the popup menu in the MI */
430 main->setContextMenuPolicy( Qt::CustomContextMenu );
431 CONNECT( main, customContextMenuRequested( const QPoint& ),
432 this, popupMenu( const QPoint& ) );
434 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
435 /* Create the FULLSCREEN CONTROLS Widget */
436 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
438 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
439 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
440 this, handleKeyPress( QKeyEvent * ) );
444 inline void MainInterface::initSystray()
447 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
448 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
450 if( var_InheritBool( p_intf, "qt-start-minimized") )
452 if( b_systrayAvailable )
454 b_systrayWanted = true;
455 b_hideAfterCreation = true;
458 msg_Err( p_intf, "cannot start minimized without system tray bar" );
461 if( b_systrayAvailable && b_systrayWanted )
466 inline void MainInterface::createStatusBar()
471 /* Widgets Creation*/
472 QStatusBar *statusBarr = statusBar();
474 TimeLabel *timeLabel = new TimeLabel( p_intf );
475 nameLabel = new QLabel( this );
476 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
477 | Qt::TextSelectableByKeyboard );
478 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
480 /* Styling those labels */
481 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
482 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
483 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
484 timeLabel->setStyleSheet(
485 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
486 speedLabel->setStyleSheet(
487 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
488 /* pad both label and its tooltip */
489 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
491 /* and adding those */
492 statusBarr->addWidget( nameLabel, 8 );
493 statusBarr->addPermanentWidget( speedLabel, 0 );
494 statusBarr->addPermanentWidget( timeLabel, 0 );
496 /* timeLabel behaviour:
497 - double clicking opens the goto time dialog
498 - right-clicking and clicking just toggle between remaining and
500 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
502 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
503 this, showCryptedLabel( bool ) );
505 CONNECT( THEMIM->getIM(), seekRequested( float ),
506 timeLabel, setDisplayPosition( float ) );
508 /* This shouldn't be necessary, but for somehow reason, the statusBarr
509 starts at height of 20px and when a text is shown it needs more space.
510 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
511 geometry, we need to force a height. If you have a better idea, please
514 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
517 /**********************************************************************
518 * Handling of sizing of the components
519 **********************************************************************/
521 void MainInterface::debug()
524 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
525 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
526 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
528 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
529 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
530 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
534 inline void MainInterface::showVideo() { showTab( videoWidget ); }
535 inline void MainInterface::restoreStackOldWidget()
536 { showTab( stackCentralOldWidget ); }
538 inline void MainInterface::showTab( QWidget *widget )
541 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
544 stackCentralOldWidget = stackCentralW->currentWidget();
545 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
547 stackCentralW->setCurrentWidget( widget );
549 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
552 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
553 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
557 void MainInterface::destroyPopupMenu()
559 QVLCMenu::PopupMenu( p_intf, false );
562 void MainInterface::popupMenu( const QPoint & )
564 QVLCMenu::PopupMenu( p_intf, true );
567 void MainInterface::toggleFSC()
569 if( !fullscreenControls ) return;
571 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
572 QApplication::postEvent( fullscreenControls, eShow );
575 /****************************************************************************
577 ****************************************************************************/
581 * You must not change the state of this object or other Qt4 UI objects,
582 * from the video output thread - only from the Qt4 UI main loop thread.
583 * All window provider queries must be handled through signals or events.
584 * That's why we have all those emit statements...
586 WId MainInterface::getVideo( int *pi_x, int *pi_y,
587 unsigned int *pi_width, unsigned int *pi_height )
592 /* This is a blocking call signal. Results are returned through pointers.
593 * Beware of deadlocks! */
595 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
599 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
600 unsigned *pi_width, unsigned *pi_height )
602 /* Hidden or minimized, activate */
603 if( isHidden() || isMinimized() )
604 toggleUpdateSystrayMenu();
606 /* Request the videoWidget */
607 WId ret = videoWidget->request( pi_x, pi_y,
608 pi_width, pi_height, !b_autoresize );
610 if( ret ) /* The videoWidget is available */
612 /* Consider the video active now */
615 /* Ask videoWidget to resize correctly, if we are in normal mode */
616 if( !isFullScreen() && !isMaximized() && b_autoresize )
617 videoWidget->SetSizing( *pi_width, *pi_height );
621 /* Asynchronous call from the WindowClose function */
622 void MainInterface::releaseVideo( void )
624 emit askReleaseVideo();
627 /* Function that is CONNECTED to the previous emit */
628 void MainInterface::releaseVideoSlot( void )
630 /* This function is called when the embedded video window is destroyed,
631 * or in the rare case that the embedded window is still here but the
632 * Qt4 interface exits. */
633 assert( videoWidget );
634 videoWidget->release();
635 setVideoOnTop( false );
636 setVideoFullScreen( false );
638 if( stackCentralW->currentWidget() == videoWidget )
639 restoreStackOldWidget();
641 /* We don't want to have a blank video to popup */
642 stackCentralOldWidget = bgWidget;
645 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
647 if( !isFullScreen() && !isMaximized() )
648 videoWidget->SetSizing( w, h );
651 void MainInterface::setVideoFullScreen( bool fs )
653 b_videoFullScreen = fs;
656 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
657 /* if user hasn't defined screennumber, or screennumber that is bigger
658 * than current number of screens, take screennumber where current interface
661 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
662 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
664 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
666 /* To be sure window is on proper-screen in xinerama */
667 if( !screenres.contains( pos() ) )
669 msg_Dbg( p_intf, "Moving video to correct screen");
670 move( QPoint( screenres.x(), screenres.y() ) );
672 setMinimalView( true );
673 setInterfaceFullScreen( true );
677 /* TODO do we want to restore screen and position ? (when
678 * qt-fullscreen-screennumber is forced) */
679 setMinimalView( b_minimalView );
680 setInterfaceFullScreen( b_interfaceFullScreen );
685 /* Slot to change the video always-on-top flag.
686 * Emit askVideoOnTop() to invoke this from other thread. */
687 void MainInterface::setVideoOnTop( bool on_top )
689 Qt::WindowFlags oldflags = windowFlags(), newflags;
692 newflags = oldflags | Qt::WindowStaysOnTopHint;
694 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
695 if( newflags != oldflags && !b_videoFullScreen )
698 setWindowFlags( newflags );
699 show(); /* necessary to apply window flags */
703 /* Asynchronous call from WindowControl function */
704 int MainInterface::controlVideo( int i_query, va_list args )
708 case VOUT_WINDOW_SET_SIZE:
710 unsigned int i_width = va_arg( args, unsigned int );
711 unsigned int i_height = va_arg( args, unsigned int );
713 emit askVideoToResize( i_width, i_height );
716 case VOUT_WINDOW_SET_STATE:
718 unsigned i_arg = va_arg( args, unsigned );
719 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
721 emit askVideoOnTop( on_top != 0 );
724 case VOUT_WINDOW_SET_FULLSCREEN:
726 bool b_fs = va_arg( args, int );
728 emit askVideoSetFullScreen( b_fs );
732 msg_Warn( p_intf, "unsupported control query" );
737 /*****************************************************************************
738 * Playlist, Visualisation and Menus handling
739 *****************************************************************************/
741 * Toggle the playlist widget or dialog
743 void MainInterface::createPlaylist()
745 playlistWidget = new PlaylistWidget( p_intf, this );
749 stackCentralW->addWidget( playlistWidget );
750 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
755 playlistWidget->setParent( NULL );
757 playlistWidget->setWindowFlags( Qt::Window );
759 /* This will restore the geometry but will not work for position,
760 because of parenting */
761 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
762 playlistWidget, QSize( 600, 300 ) );
766 void MainInterface::togglePlaylist()
768 if( !playlistWidget )
775 /* Playlist is not visible, show it */
776 if( stackCentralW->currentWidget() != playlistWidget )
778 showTab( playlistWidget );
782 restoreStackOldWidget();
784 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
789 playlistWidget->setParent( NULL );
791 playlistWidget->setWindowFlags( Qt::Window );
792 playlistVisible = !playlistVisible;
793 playlistWidget->setVisible( playlistVisible );
798 void MainInterface::dockPlaylist( bool p_docked )
800 if( b_plDocked == p_docked ) return;
801 b_plDocked = p_docked;
803 if( !playlistWidget ) return; /* Playlist wasn't created yet */
806 stackCentralW->removeWidget( playlistWidget );
808 playlistWidget->setParent( NULL );
810 playlistWidget->setWindowFlags( Qt::Window );
811 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
812 playlistWidget, QSize( 600, 300 ) );
813 playlistWidget->show();
814 restoreStackOldWidget();
818 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
819 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
820 // It would be logical that QStackWidget::addWidget reset the flags...
821 stackCentralW->addWidget( playlistWidget );
822 showTab( playlistWidget );
824 playlistVisible = true;
828 * setMinimalView is the private function used by
829 * the SLOT toggleMinimalView and setVideoFullScreen
831 void MainInterface::setMinimalView( bool b_minimal )
833 menuBar()->setVisible( !b_minimal );
834 controls->setVisible( !b_minimal );
835 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
836 inputC->setVisible( !b_minimal );
840 * This public SLOT is used for moving to minimal View Mode
842 * If b_minimal is false, then we are normalView
844 void MainInterface::toggleMinimalView( bool b_minimal )
846 if( !b_minimalView && b_autoresize ) /* Normal mode */
848 if( stackCentralW->currentWidget() == bgWidget )
850 if( stackCentralW->height() < 16 )
852 resizeStack( stackCentralW->width(), 100 );
856 b_minimalView = b_minimal;
857 if( !b_videoFullScreen )
859 setMinimalView( b_minimalView );
860 computeMinimumSize();
863 emit minimalViewToggled( b_minimalView );
866 /* toggling advanced controls buttons */
867 void MainInterface::toggleAdvancedButtons()
869 controls->toggleAdvanced();
870 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
873 /* Get the visibility status of the controls (hidden or not, advanced or not) */
874 int MainInterface::getControlsVisibilityStatus()
876 if( !controls ) return 0;
877 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
878 + CONTROLS_ADVANCED * controls->b_advancedVisible );
881 void MainInterface::setStatusBarVisibility( bool b_visible )
883 statusBar()->setVisible( b_visible );
884 b_statusbarVisible = b_visible;
885 if( controls ) controls->setGripVisible( !b_statusbarVisible );
889 void MainInterface::visual()
891 if( !VISIBLE( visualSelector) )
893 visualSelector->show();
894 if( !THEMIM->getIM()->hasVideo() )
896 /* Show the background widget */
898 visualSelectorEnabled = true;
902 /* Stop any currently running visualization */
903 visualSelector->hide();
904 visualSelectorEnabled = false;
909 /************************************************************************
911 ************************************************************************/
912 void MainInterface::setName( const QString& name )
914 input_name = name; /* store it for the QSystray use */
915 /* Display it in the status bar, but also as a Tooltip in case it doesn't
917 nameLabel->setText( name );
918 nameLabel->setToolTip( name );
922 * Give the decorations of the Main Window a correct Name.
923 * If nothing is given, set it to VLC...
925 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
927 if( aTitle.isEmpty() )
929 setWindowTitle( qtr( "VLC media player" ) );
933 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
937 void MainInterface::showCryptedLabel( bool b_show )
939 if( cryptedLabel == NULL )
941 cryptedLabel = new QLabel;
942 // The lock icon is not the right one for DRM protection/scrambled.
943 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
944 cryptedLabel->setText( "DRM" );
945 statusBar()->addWidget( cryptedLabel );
948 cryptedLabel->setVisible( b_show );
951 void MainInterface::showBuffering( float f_cache )
953 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
954 statusBar()->showMessage( amount, 1000 );
957 /*****************************************************************************
958 * Systray Icon and Systray Menu
959 *****************************************************************************/
962 * Create a SystemTray icon and a menu that would go with it.
963 * Connects to a click handler on the icon.
965 void MainInterface::createSystray()
968 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
969 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
971 iconVLC = QIcon( ":/logo/vlc128.png" );
972 sysTray = new QSystemTrayIcon( iconVLC, this );
973 sysTray->setToolTip( qtr( "VLC media player" ));
975 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
976 systrayMenu->setIcon( iconVLC );
978 QVLCMenu::updateSystrayMenu( this, p_intf, true );
981 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
982 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
986 * Updates the Systray Icon's menu and toggle the main interface
988 void MainInterface::toggleUpdateSystrayMenu()
990 /* If hidden, show it */
996 else if( isMinimized() )
1004 /* Visible (possibly under other windows) */
1006 /* check if any visible window is above vlc in the z-order,
1007 * but ignore the ones always on top
1008 * and the ones which can't be activated */
1011 wi.cbSize = sizeof( WINDOWINFO );
1012 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1013 hwnd && ( !IsWindowVisible( hwnd ) ||
1014 ( GetWindowInfo( hwnd, &wi ) &&
1015 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1016 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1017 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1018 (wi.dwExStyle&WS_EX_TOPMOST) )
1030 QVLCMenu::updateSystrayMenu( this, p_intf );
1033 void MainInterface::showUpdateSystrayMenu()
1041 QVLCMenu::updateSystrayMenu( this, p_intf );
1044 void MainInterface::hideUpdateSystrayMenu()
1047 QVLCMenu::updateSystrayMenu( this, p_intf );
1050 void MainInterface::handleSystrayClick(
1051 QSystemTrayIcon::ActivationReason reason )
1055 case QSystemTrayIcon::Trigger:
1056 case QSystemTrayIcon::DoubleClick:
1058 QVLCMenu::updateSystrayMenu( this, p_intf );
1060 toggleUpdateSystrayMenu();
1063 case QSystemTrayIcon::MiddleClick:
1064 sysTray->showMessage( qtr( "VLC media player" ),
1065 qtr( "Control menu for the player" ),
1066 QSystemTrayIcon::Information, 3000 );
1074 * Updates the name of the systray Icon tooltip.
1075 * Doesn't check if the systray exists, check before you call it.
1077 void MainInterface::updateSystrayTooltipName( const QString& name )
1079 if( name.isEmpty() )
1081 sysTray->setToolTip( qtr( "VLC media player" ) );
1085 sysTray->setToolTip( name );
1086 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1088 sysTray->showMessage( qtr( "VLC media player" ), name,
1089 QSystemTrayIcon::NoIcon, 3000 );
1093 QVLCMenu::updateSystrayMenu( this, p_intf );
1097 * Updates the status of the systray Icon tooltip.
1098 * Doesn't check if the systray exists, check before you call it.
1100 void MainInterface::updateSystrayTooltipStatus( int i_status )
1105 sysTray->setToolTip( input_name );
1108 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1111 sysTray->setToolTip( qtr( "VLC media player" ) );
1114 QVLCMenu::updateSystrayMenu( this, p_intf );
1118 void MainInterface::changeEvent(QEvent *event)
1120 if( event->type() == QEvent::WindowStateChange )
1122 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1123 Qt::WindowStates newState = windowState();
1124 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1126 if( newState & Qt::WindowMinimized )
1128 b_hasPausedWhenMinimized = false;
1130 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1131 THEMIM->getIM()->hasVideo() &&
1132 !THEMIM->getIM()->hasVisualisation() &&
1133 var_InheritBool( p_intf, "qt-pause-minimized" ) )
1135 b_hasPausedWhenMinimized = true;
1139 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1141 if( b_hasPausedWhenMinimized )
1148 QWidget::changeEvent(event);
1151 /************************************************************************
1153 ************************************************************************/
1154 void MainInterface::dropEvent(QDropEvent *event)
1156 dropEventPlay( event, true );
1159 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1161 if( event->possibleActions() & Qt::CopyAction )
1162 event->setDropAction( Qt::CopyAction );
1166 const QMimeData *mimeData = event->mimeData();
1168 /* D&D of a subtitles file, add it on the fly */
1169 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1171 if( !input_AddSubtitle( THEMIM->getInput(),
1172 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1180 bool first = b_play;
1181 foreach( const QUrl &url, mimeData->urls() )
1185 QString mrl = toURI( url.toEncoded().constData() );
1186 playlist_Add( THEPL, qtu(mrl), NULL,
1187 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1188 PLAYLIST_END, true, pl_Unlocked );
1190 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1194 /* Browsers give content as text if you dnd the addressbar,
1195 so check if mimedata has valid url in text and use it
1196 if we didn't get any normal Urls()*/
1197 if( !mimeData->hasUrls() && mimeData->hasText() &&
1198 QUrl(mimeData->text()).isValid() )
1200 QString mrl = toURI( mimeData->text() );
1201 playlist_Add( THEPL, qtu(mrl), NULL,
1202 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1203 PLAYLIST_END, true, pl_Unlocked );
1207 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1209 event->acceptProposedAction();
1211 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1213 event->acceptProposedAction();
1215 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1220 /************************************************************************
1222 ************************************************************************/
1223 void MainInterface::keyPressEvent( QKeyEvent *e )
1225 handleKeyPress( e );
1228 void MainInterface::handleKeyPress( QKeyEvent *e )
1230 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1232 toggleMinimalView( !b_minimalView );
1236 int i_vlck = qtEventToVLCKey( e );
1239 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1246 void MainInterface::wheelEvent( QWheelEvent *e )
1248 int i_vlckey = qtWheelEventToVLCKey( e );
1249 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1253 void MainInterface::closeEvent( QCloseEvent *e )
1256 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1257 /* Accept session quit. Otherwise we break the desktop mamager. */
1261 void MainInterface::setInterfaceFullScreen( bool fs )
1264 setWindowState( windowState() | Qt::WindowFullScreen );
1266 setWindowState( windowState() & ~Qt::WindowFullScreen );
1268 void MainInterface::toggleInterfaceFullScreen()
1270 b_interfaceFullScreen = !b_interfaceFullScreen;
1271 if( !b_videoFullScreen )
1272 setInterfaceFullScreen( b_interfaceFullScreen );
1273 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1276 void MainInterface::emitBoss()
1280 void MainInterface::setBoss()
1295 /*****************************************************************************
1296 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1297 * We don't show the menu directly here because we don't want the
1298 * caller to block for a too long time.
1299 *****************************************************************************/
1300 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1301 vlc_value_t old_val, vlc_value_t new_val, void *param )
1303 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1305 intf_thread_t *p_intf = (intf_thread_t *)param;
1307 if( p_intf->pf_show_dialog )
1309 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1310 new_val.b_bool, NULL );
1316 /*****************************************************************************
1317 * IntfShowCB: callback triggered by the intf-show libvlc variable.
1318 *****************************************************************************/
1319 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1320 vlc_value_t old_val, vlc_value_t new_val, void *param )
1322 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1323 VLC_UNUSED( new_val );
1325 intf_thread_t *p_intf = (intf_thread_t *)param;
1326 p_intf->p_sys->p_mi->toggleFSC();
1332 /*****************************************************************************
1333 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1334 *****************************************************************************/
1335 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1336 vlc_value_t old_val, vlc_value_t new_val, void *param )
1338 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1339 VLC_UNUSED( new_val );
1341 intf_thread_t *p_intf = (intf_thread_t *)param;
1342 p_intf->p_sys->p_mi->emitBoss();