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 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
126 /* Set the other interface settings */
127 settings = getSettings();
128 settings->beginGroup( "MainWindow" );
132 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
136 b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
138 settings->endGroup( );
140 /*********************************
141 * Create the Systray Management *
142 *********************************/
145 /**************************
146 * UI and Widgets design
147 **************************/
148 setVLCWindowsTitle();
153 QVLCMenu::createMenuBar( this, p_intf );
154 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
155 this, destroyPopupMenu() );
157 createMainWidget( settings );
163 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
165 /********************
167 ********************/
168 MainInputManager::getInstance( p_intf );
173 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
176 /************************************************************
177 * Connect the input manager to the GUI elements it manages *
178 ************************************************************/
180 * Connects on nameChanged()
181 * Those connects are different because options can impeach them to trigger.
183 /* Main Interface statusbar */
184 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
185 this, setName( const QString& ) );
190 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
191 this, updateSystrayTooltipName( const QString& ) );
194 /* and title of the Main Interface*/
195 if( var_InheritBool( p_intf, "qt-name-in-title" ) )
197 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
198 this, setVLCWindowsTitle( const QString& ) );
202 * CONNECTS on PLAY_STATUS
204 /* Status on the systray */
208 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
209 this, updateSystrayTooltipStatus( int ) );
213 /* END CONNECTS ON IM */
215 /* VideoWidget connects for asynchronous calls */
216 b_videoFullScreen = false;
217 connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
218 this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
219 Qt::BlockingQueuedConnection );
220 connect( this, SIGNAL(askReleaseVideo( void )),
221 this, SLOT(releaseVideoSlot( void )),
222 Qt::BlockingQueuedConnection );
223 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
229 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
230 this, setVideoSize( unsigned int, unsigned int ) );
231 CONNECT( videoWidget, sizeChanged( int, int ),
232 this, resizeStack( int, int ) );
234 CONNECT( this, askVideoSetFullScreen( bool ),
235 this, setVideoFullScreen( bool ) );
238 CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
240 CONNECT( this, askToQuit(), THEDP, quit() );
242 CONNECT( this, askBoss(), this, setBoss() );
244 /** END of CONNECTS**/
250 var_AddCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
251 var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
253 /* Register callback for the intf-popupmenu variable */
254 var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
257 int i_plVis = settings->value( "MainWindow/playlist-visible", false ).toBool();
259 if( i_plVis ) togglePlaylist();
261 /**** FINAL SIZING and placement of interface */
262 settings->beginGroup( "MainWindow" );
263 QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
264 settings->endGroup();
266 b_interfaceFullScreen = isFullScreen();
268 /* Final sizing and showing */
269 setVisible( !b_hideAfterCreation );
271 computeMinimumSize();
273 /* Switch to minimal view if needed, must be called after the show() */
275 toggleMinimalView( true );
277 b_hasPausedWhenMinimized = false;
280 MainInterface::~MainInterface()
282 /* Unsure we hide the videoWidget before destroying it */
283 if( stackCentralOldWidget == videoWidget )
291 ImageList_Destroy( himl );
293 p_taskbl->vt->Release(p_taskbl);
297 /* Be sure to kill the actionsManager... Only used in the MI and control */
298 ActionsManager::killInstance();
301 ExtensionsManager::killInstance();
303 /* Delete the FSC controller */
304 delete fullscreenControls;
307 settings->beginGroup( "MainWindow" );
309 settings->setValue( "pl-dock-status", b_plDocked );
310 /* Save playlist state */
312 settings->setValue( "playlist-visible", playlistVisible );
314 settings->setValue( "adv-controls",
315 getControlsVisibilityStatus() & CONTROLS_ADVANCED );
316 settings->setValue( "status-bar-visible", b_statusbarVisible );
318 /* Save the stackCentralW sizes */
319 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
320 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
323 QVLCTools::saveWidgetPosition(settings, this);
325 settings->endGroup();
327 /* Save undocked playlist size */
328 if( playlistWidget && !isPlDocked() )
329 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
331 delete playlistWidget;
335 /* Unregister callbacks */
336 var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
337 var_DelCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
338 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
340 p_intf->p_sys->p_mi = NULL;
343 void MainInterface::computeMinimumSize()
346 if( menuBar()->isVisible() )
347 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
349 setMinimumWidth( minWidth );
352 /*****************************
354 *****************************/
355 void MainInterface::recreateToolbars()
357 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
359 settings->beginGroup( "MainWindow" );
363 controls = new ControlsWidget( p_intf, b_adv, this );
364 inputC = new InputControlsWidget( p_intf, this );
366 if( fullscreenControls )
368 delete fullscreenControls;
369 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
370 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
371 this, handleKeyPress( QKeyEvent * ) );
373 mainLayout->insertWidget( 2, inputC );
374 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
376 settings->endGroup();
379 void MainInterface::createMainWidget( QSettings *settings )
381 /* Create the main Widget and the mainLayout */
382 QWidget *main = new QWidget;
383 setCentralWidget( main );
384 mainLayout = new QVBoxLayout( main );
385 main->setContentsMargins( 0, 0, 0, 0 );
386 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
389 stackCentralW = new QVLCStackedWidget( main );
392 bgWidget = new BackgroundWidget( p_intf );
393 stackCentralW->addWidget( bgWidget );
394 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
395 bgWidget->setWithArt( false );
397 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
398 bgWidget->setExpandstoHeight( true );
400 /* And video Outputs */
401 if( b_videoEmbedded )
403 videoWidget = new VideoWidget( p_intf );
404 stackCentralW->addWidget( videoWidget );
406 mainLayout->insertWidget( 1, stackCentralW );
408 settings->beginGroup( "MainWindow" );
409 stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 600, 0 ) ).toSize();
410 /* Resize even if no-auto-resize, because we are at creation */
411 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
413 /* Create the CONTROLS Widget */
414 controls = new ControlsWidget( p_intf,
415 settings->value( "adv-controls", false ).toBool(), this );
416 inputC = new InputControlsWidget( p_intf, this );
418 mainLayout->insertWidget( 2, inputC );
419 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
422 /* Visualisation, disabled for now, they SUCK */
424 visualSelector = new VisualSelector( p_intf );
425 mainLayout->insertWidget( 0, visualSelector );
426 visualSelector->hide();
429 settings->endGroup();
431 /* Enable the popup menu in the MI */
432 main->setContextMenuPolicy( Qt::CustomContextMenu );
433 CONNECT( main, customContextMenuRequested( const QPoint& ),
434 this, popupMenu( const QPoint& ) );
436 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
437 /* Create the FULLSCREEN CONTROLS Widget */
438 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
440 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
441 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
442 this, handleKeyPress( QKeyEvent * ) );
446 inline void MainInterface::initSystray()
449 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
450 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
452 if( var_InheritBool( p_intf, "qt-start-minimized") )
454 if( b_systrayAvailable )
456 b_systrayWanted = true;
457 b_hideAfterCreation = true;
460 msg_Err( p_intf, "cannot start minimized without system tray bar" );
463 if( b_systrayAvailable && b_systrayWanted )
468 inline void MainInterface::createStatusBar()
473 /* Widgets Creation*/
474 QStatusBar *statusBarr = statusBar();
476 TimeLabel *timeLabel = new TimeLabel( p_intf );
477 nameLabel = new QLabel( this );
478 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
479 | Qt::TextSelectableByKeyboard );
480 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
482 /* Styling those labels */
483 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
484 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
485 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
486 timeLabel->setStyleSheet(
487 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
488 speedLabel->setStyleSheet(
489 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
490 /* pad both label and its tooltip */
491 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
493 /* and adding those */
494 statusBarr->addWidget( nameLabel, 8 );
495 statusBarr->addPermanentWidget( speedLabel, 0 );
496 statusBarr->addPermanentWidget( timeLabel, 0 );
498 /* timeLabel behaviour:
499 - double clicking opens the goto time dialog
500 - right-clicking and clicking just toggle between remaining and
502 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
504 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
505 this, showCryptedLabel( bool ) );
507 CONNECT( THEMIM->getIM(), seekRequested( float ),
508 timeLabel, setDisplayPosition( float ) );
510 /* This shouldn't be necessary, but for somehow reason, the statusBarr
511 starts at height of 20px and when a text is shown it needs more space.
512 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
513 geometry, we need to force a height. If you have a better idea, please
516 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
519 /**********************************************************************
520 * Handling of sizing of the components
521 **********************************************************************/
523 void MainInterface::debug()
526 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
527 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
528 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
530 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
531 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
532 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
536 inline void MainInterface::showVideo() { showTab( videoWidget ); }
537 inline void MainInterface::restoreStackOldWidget()
538 { showTab( stackCentralOldWidget ); }
540 inline void MainInterface::showTab( QWidget *widget )
543 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
546 stackCentralOldWidget = stackCentralW->currentWidget();
547 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
549 stackCentralW->setCurrentWidget( widget );
551 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
554 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
555 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
559 void MainInterface::destroyPopupMenu()
561 QVLCMenu::PopupMenu( p_intf, false );
564 void MainInterface::popupMenu( const QPoint & )
566 QVLCMenu::PopupMenu( p_intf, true );
569 void MainInterface::toggleFSC()
571 if( !fullscreenControls ) return;
573 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
574 QApplication::postEvent( fullscreenControls, eShow );
577 /****************************************************************************
579 ****************************************************************************/
583 * You must not change the state of this object or other Qt4 UI objects,
584 * from the video output thread - only from the Qt4 UI main loop thread.
585 * All window provider queries must be handled through signals or events.
586 * That's why we have all those emit statements...
588 WId MainInterface::getVideo( int *pi_x, int *pi_y,
589 unsigned int *pi_width, unsigned int *pi_height )
594 /* This is a blocking call signal. Results are returned through pointers.
595 * Beware of deadlocks! */
597 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
601 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
602 unsigned *pi_width, unsigned *pi_height )
604 /* Hidden or minimized, activate */
605 if( isHidden() || isMinimized() )
606 toggleUpdateSystrayMenu();
608 /* Request the videoWidget */
609 WId ret = videoWidget->request( pi_x, pi_y,
610 pi_width, pi_height, !b_autoresize );
612 if( ret ) /* The videoWidget is available */
614 /* Consider the video active now */
617 /* Ask videoWidget to resize correctly, if we are in normal mode */
618 if( !isFullScreen() && !isMaximized() && b_autoresize )
619 videoWidget->SetSizing( *pi_width, *pi_height );
623 /* Asynchronous call from the WindowClose function */
624 void MainInterface::releaseVideo( void )
626 emit askReleaseVideo();
629 /* Function that is CONNECTED to the previous emit */
630 void MainInterface::releaseVideoSlot( void )
632 /* This function is called when the embedded video window is destroyed,
633 * or in the rare case that the embedded window is still here but the
634 * Qt4 interface exits. */
635 assert( videoWidget );
636 videoWidget->release();
637 setVideoOnTop( false );
638 setVideoFullScreen( false );
640 if( stackCentralW->currentWidget() == videoWidget )
641 restoreStackOldWidget();
643 /* We don't want to have a blank video to popup */
644 stackCentralOldWidget = bgWidget;
647 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
649 if( !isFullScreen() && !isMaximized() )
650 videoWidget->SetSizing( w, h );
653 void MainInterface::setVideoFullScreen( bool fs )
655 b_videoFullScreen = fs;
658 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
659 /* if user hasn't defined screennumber, or screennumber that is bigger
660 * than current number of screens, take screennumber where current interface
663 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
664 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
666 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
668 /* To be sure window is on proper-screen in xinerama */
669 if( !screenres.contains( pos() ) )
671 msg_Dbg( p_intf, "Moving video to correct screen");
672 move( QPoint( screenres.x(), screenres.y() ) );
674 setMinimalView( true );
675 setInterfaceFullScreen( true );
679 /* TODO do we want to restore screen and position ? (when
680 * qt-fullscreen-screennumber is forced) */
681 setMinimalView( b_minimalView );
682 setInterfaceFullScreen( b_interfaceFullScreen );
687 /* Slot to change the video always-on-top flag.
688 * Emit askVideoOnTop() to invoke this from other thread. */
689 void MainInterface::setVideoOnTop( bool on_top )
691 Qt::WindowFlags oldflags = windowFlags(), newflags;
694 newflags = oldflags | Qt::WindowStaysOnTopHint;
696 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
697 if( newflags != oldflags && !b_videoFullScreen )
700 setWindowFlags( newflags );
701 show(); /* necessary to apply window flags */
705 /* Asynchronous call from WindowControl function */
706 int MainInterface::controlVideo( int i_query, va_list args )
710 case VOUT_WINDOW_SET_SIZE:
712 unsigned int i_width = va_arg( args, unsigned int );
713 unsigned int i_height = va_arg( args, unsigned int );
715 emit askVideoToResize( i_width, i_height );
718 case VOUT_WINDOW_SET_STATE:
720 unsigned i_arg = va_arg( args, unsigned );
721 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
723 emit askVideoOnTop( on_top != 0 );
726 case VOUT_WINDOW_SET_FULLSCREEN:
728 bool b_fs = va_arg( args, int );
730 emit askVideoSetFullScreen( b_fs );
734 msg_Warn( p_intf, "unsupported control query" );
739 /*****************************************************************************
740 * Playlist, Visualisation and Menus handling
741 *****************************************************************************/
743 * Toggle the playlist widget or dialog
745 void MainInterface::createPlaylist()
747 playlistWidget = new PlaylistWidget( p_intf, this );
751 stackCentralW->addWidget( playlistWidget );
752 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
757 playlistWidget->setParent( NULL );
759 playlistWidget->setWindowFlags( Qt::Window );
761 /* This will restore the geometry but will not work for position,
762 because of parenting */
763 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
764 playlistWidget, QSize( 600, 300 ) );
768 void MainInterface::togglePlaylist()
770 if( !playlistWidget )
777 /* Playlist is not visible, show it */
778 if( stackCentralW->currentWidget() != playlistWidget )
780 showTab( playlistWidget );
784 restoreStackOldWidget();
786 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
791 playlistWidget->setParent( NULL );
793 playlistWidget->setWindowFlags( Qt::Window );
794 playlistVisible = !playlistVisible;
795 playlistWidget->setVisible( playlistVisible );
800 void MainInterface::dockPlaylist( bool p_docked )
802 if( b_plDocked == p_docked ) return;
803 b_plDocked = p_docked;
805 if( !playlistWidget ) return; /* Playlist wasn't created yet */
808 stackCentralW->removeWidget( playlistWidget );
810 playlistWidget->setParent( NULL );
812 playlistWidget->setWindowFlags( Qt::Window );
813 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
814 playlistWidget, QSize( 600, 300 ) );
815 playlistWidget->show();
816 restoreStackOldWidget();
820 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
821 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
822 // It would be logical that QStackWidget::addWidget reset the flags...
823 stackCentralW->addWidget( playlistWidget );
824 showTab( playlistWidget );
826 playlistVisible = true;
830 * setMinimalView is the private function used by
831 * the SLOT toggleMinimalView and setVideoFullScreen
833 void MainInterface::setMinimalView( bool b_minimal )
835 menuBar()->setVisible( !b_minimal );
836 controls->setVisible( !b_minimal );
837 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
838 inputC->setVisible( !b_minimal );
842 * This public SLOT is used for moving to minimal View Mode
844 * If b_minimal is false, then we are normalView
846 void MainInterface::toggleMinimalView( bool b_minimal )
848 if( !b_minimalView && b_autoresize ) /* Normal mode */
850 if( stackCentralW->currentWidget() == bgWidget )
852 if( stackCentralW->height() < 16 )
854 resizeStack( stackCentralW->width(), 100 );
858 b_minimalView = b_minimal;
859 if( !b_videoFullScreen )
861 setMinimalView( b_minimalView );
862 computeMinimumSize();
865 emit minimalViewToggled( b_minimalView );
868 /* toggling advanced controls buttons */
869 void MainInterface::toggleAdvancedButtons()
871 controls->toggleAdvanced();
872 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
875 /* Get the visibility status of the controls (hidden or not, advanced or not) */
876 int MainInterface::getControlsVisibilityStatus()
878 if( !controls ) return 0;
879 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
880 + CONTROLS_ADVANCED * controls->b_advancedVisible );
883 void MainInterface::setStatusBarVisibility( bool b_visible )
885 statusBar()->setVisible( b_visible );
886 b_statusbarVisible = b_visible;
887 if( controls ) controls->setGripVisible( !b_statusbarVisible );
891 void MainInterface::visual()
893 if( !VISIBLE( visualSelector) )
895 visualSelector->show();
896 if( !THEMIM->getIM()->hasVideo() )
898 /* Show the background widget */
900 visualSelectorEnabled = true;
904 /* Stop any currently running visualization */
905 visualSelector->hide();
906 visualSelectorEnabled = false;
911 /************************************************************************
913 ************************************************************************/
914 void MainInterface::setName( const QString& name )
916 input_name = name; /* store it for the QSystray use */
917 /* Display it in the status bar, but also as a Tooltip in case it doesn't
919 nameLabel->setText( name );
920 nameLabel->setToolTip( name );
924 * Give the decorations of the Main Window a correct Name.
925 * If nothing is given, set it to VLC...
927 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
929 if( aTitle.isEmpty() )
931 setWindowTitle( qtr( "VLC media player" ) );
935 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
939 void MainInterface::showCryptedLabel( bool b_show )
941 if( cryptedLabel == NULL )
943 cryptedLabel = new QLabel;
944 // The lock icon is not the right one for DRM protection/scrambled.
945 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
946 cryptedLabel->setText( "DRM" );
947 statusBar()->addWidget( cryptedLabel );
950 cryptedLabel->setVisible( b_show );
953 void MainInterface::showBuffering( float f_cache )
955 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
956 statusBar()->showMessage( amount, 1000 );
959 /*****************************************************************************
960 * Systray Icon and Systray Menu
961 *****************************************************************************/
964 * Create a SystemTray icon and a menu that would go with it.
965 * Connects to a click handler on the icon.
967 void MainInterface::createSystray()
970 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
971 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
973 iconVLC = QIcon( ":/logo/vlc128.png" );
974 sysTray = new QSystemTrayIcon( iconVLC, this );
975 sysTray->setToolTip( qtr( "VLC media player" ));
977 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
978 systrayMenu->setIcon( iconVLC );
980 QVLCMenu::updateSystrayMenu( this, p_intf, true );
983 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
984 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
988 * Updates the Systray Icon's menu and toggle the main interface
990 void MainInterface::toggleUpdateSystrayMenu()
992 /* If hidden, show it */
998 else if( isMinimized() )
1006 /* Visible (possibly under other windows) */
1008 /* check if any visible window is above vlc in the z-order,
1009 * but ignore the ones always on top
1010 * and the ones which can't be activated */
1013 wi.cbSize = sizeof( WINDOWINFO );
1014 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1015 hwnd && ( !IsWindowVisible( hwnd ) ||
1016 ( GetWindowInfo( hwnd, &wi ) &&
1017 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1018 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1019 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1020 (wi.dwExStyle&WS_EX_TOPMOST) )
1032 QVLCMenu::updateSystrayMenu( this, p_intf );
1035 void MainInterface::showUpdateSystrayMenu()
1043 QVLCMenu::updateSystrayMenu( this, p_intf );
1046 void MainInterface::hideUpdateSystrayMenu()
1049 QVLCMenu::updateSystrayMenu( this, p_intf );
1052 void MainInterface::handleSystrayClick(
1053 QSystemTrayIcon::ActivationReason reason )
1057 case QSystemTrayIcon::Trigger:
1058 case QSystemTrayIcon::DoubleClick:
1060 QVLCMenu::updateSystrayMenu( this, p_intf );
1062 toggleUpdateSystrayMenu();
1065 case QSystemTrayIcon::MiddleClick:
1066 sysTray->showMessage( qtr( "VLC media player" ),
1067 qtr( "Control menu for the player" ),
1068 QSystemTrayIcon::Information, 3000 );
1076 * Updates the name of the systray Icon tooltip.
1077 * Doesn't check if the systray exists, check before you call it.
1079 void MainInterface::updateSystrayTooltipName( const QString& name )
1081 if( name.isEmpty() )
1083 sysTray->setToolTip( qtr( "VLC media player" ) );
1087 sysTray->setToolTip( name );
1088 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1090 sysTray->showMessage( qtr( "VLC media player" ), name,
1091 QSystemTrayIcon::NoIcon, 3000 );
1095 QVLCMenu::updateSystrayMenu( this, p_intf );
1099 * Updates the status of the systray Icon tooltip.
1100 * Doesn't check if the systray exists, check before you call it.
1102 void MainInterface::updateSystrayTooltipStatus( int i_status )
1107 sysTray->setToolTip( input_name );
1110 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1113 sysTray->setToolTip( qtr( "VLC media player" ) );
1116 QVLCMenu::updateSystrayMenu( this, p_intf );
1120 void MainInterface::changeEvent(QEvent *event)
1122 if( event->type() == QEvent::WindowStateChange )
1124 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1125 Qt::WindowStates newState = windowState();
1126 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1128 if( newState & Qt::WindowMinimized )
1130 b_hasPausedWhenMinimized = false;
1132 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1133 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1136 b_hasPausedWhenMinimized = true;
1140 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1142 if( b_hasPausedWhenMinimized )
1149 QWidget::changeEvent(event);
1152 /************************************************************************
1154 ************************************************************************/
1155 void MainInterface::dropEvent(QDropEvent *event)
1157 dropEventPlay( event, true );
1160 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1162 if( event->possibleActions() & Qt::CopyAction )
1163 event->setDropAction( Qt::CopyAction );
1167 const QMimeData *mimeData = event->mimeData();
1169 /* D&D of a subtitles file, add it on the fly */
1170 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1172 if( !input_AddSubtitle( THEMIM->getInput(),
1173 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1181 bool first = b_play;
1182 foreach( const QUrl &url, mimeData->urls() )
1186 QString mrl = toURI( url.toEncoded().constData() );
1187 playlist_Add( THEPL, qtu(mrl), NULL,
1188 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1189 PLAYLIST_END, true, pl_Unlocked );
1191 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1195 /* Browsers give content as text if you dnd the addressbar,
1196 so check if mimedata has valid url in text and use it
1197 if we didn't get any normal Urls()*/
1198 if( !mimeData->hasUrls() && mimeData->hasText() &&
1199 QUrl(mimeData->text()).isValid() )
1201 QString mrl = toURI( mimeData->text() );
1202 playlist_Add( THEPL, qtu(mrl), NULL,
1203 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1204 PLAYLIST_END, true, pl_Unlocked );
1208 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1210 event->acceptProposedAction();
1212 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1214 event->acceptProposedAction();
1216 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1221 /************************************************************************
1223 ************************************************************************/
1224 void MainInterface::keyPressEvent( QKeyEvent *e )
1226 handleKeyPress( e );
1229 void MainInterface::handleKeyPress( QKeyEvent *e )
1231 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1233 toggleMinimalView( !b_minimalView );
1237 int i_vlck = qtEventToVLCKey( e );
1240 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1247 void MainInterface::wheelEvent( QWheelEvent *e )
1249 int i_vlckey = qtWheelEventToVLCKey( e );
1250 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1254 void MainInterface::closeEvent( QCloseEvent *e )
1257 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1258 /* Accept session quit. Otherwise we break the desktop mamager. */
1262 void MainInterface::setInterfaceFullScreen( bool fs )
1265 setWindowState( windowState() | Qt::WindowFullScreen );
1267 setWindowState( windowState() & ~Qt::WindowFullScreen );
1269 void MainInterface::toggleInterfaceFullScreen()
1271 b_interfaceFullScreen = !b_interfaceFullScreen;
1272 if( !b_videoFullScreen )
1273 setInterfaceFullScreen( b_interfaceFullScreen );
1274 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1277 void MainInterface::emitBoss()
1281 void MainInterface::setBoss()
1296 /*****************************************************************************
1297 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1298 * We don't show the menu directly here because we don't want the
1299 * caller to block for a too long time.
1300 *****************************************************************************/
1301 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1302 vlc_value_t old_val, vlc_value_t new_val, void *param )
1304 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1306 intf_thread_t *p_intf = (intf_thread_t *)param;
1308 if( p_intf->pf_show_dialog )
1310 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1311 new_val.b_bool, NULL );
1317 /*****************************************************************************
1318 * IntfShowCB: callback triggered by the intf-show libvlc variable.
1319 *****************************************************************************/
1320 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1321 vlc_value_t old_val, vlc_value_t new_val, void *param )
1323 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1324 VLC_UNUSED( new_val );
1326 intf_thread_t *p_intf = (intf_thread_t *)param;
1327 p_intf->p_sys->p_mi->toggleFSC();
1333 /*****************************************************************************
1334 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1335 *****************************************************************************/
1336 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1337 vlc_value_t old_val, vlc_value_t new_val, void *param )
1339 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1340 VLC_UNUSED( new_val );
1342 intf_thread_t *p_intf = (intf_thread_t *)param;
1343 p_intf->p_sys->p_mi->emitBoss();