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 );
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" );
125 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
127 /* Set the other interface settings */
128 settings = getSettings();
129 settings->beginGroup( "MainWindow" );
133 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
137 b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
139 settings->endGroup( );
141 /**************************
142 * UI and Widgets design
143 **************************/
144 setVLCWindowsTitle();
149 QVLCMenu::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() );
225 /** END of CONNECTS**/
231 var_AddCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
232 var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
234 /* Register callback for the intf-popupmenu variable */
235 var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
238 int i_plVis = settings->value( "MainWindow/playlist-visible", false ).toBool();
240 if( i_plVis ) togglePlaylist();
242 /**** FINAL SIZING and placement of interface */
243 settings->beginGroup( "MainWindow" );
244 QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
245 settings->endGroup();
247 b_interfaceFullScreen = isFullScreen();
249 /* Final sizing and showing */
250 setVisible( !b_hideAfterCreation );
252 computeMinimumSize();
254 /* Switch to minimal view if needed, must be called after the show() */
256 toggleMinimalView( true );
258 b_hasPausedWhenMinimized = false;
261 MainInterface::~MainInterface()
263 /* Unsure we hide the videoWidget before destroying it */
264 if( stackCentralOldWidget == videoWidget )
272 ImageList_Destroy( himl );
274 p_taskbl->vt->Release(p_taskbl);
278 /* Be sure to kill the actionsManager... Only used in the MI and control */
279 ActionsManager::killInstance();
282 ExtensionsManager::killInstance();
284 /* Delete the FSC controller */
285 delete fullscreenControls;
288 settings->beginGroup( "MainWindow" );
290 settings->setValue( "pl-dock-status", b_plDocked );
291 /* Save playlist state */
293 settings->setValue( "playlist-visible", playlistVisible );
295 settings->setValue( "adv-controls",
296 getControlsVisibilityStatus() & CONTROLS_ADVANCED );
297 settings->setValue( "status-bar-visible", b_statusbarVisible );
299 /* Save the stackCentralW sizes */
300 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
301 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
304 QVLCTools::saveWidgetPosition(settings, this);
306 settings->endGroup();
308 /* Save undocked playlist size */
309 if( playlistWidget && !isPlDocked() )
310 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
312 delete playlistWidget;
316 /* Unregister callbacks */
317 var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
318 var_DelCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
319 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
321 p_intf->p_sys->p_mi = NULL;
324 void MainInterface::computeMinimumSize()
327 if( menuBar()->isVisible() )
328 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
330 setMinimumWidth( minWidth );
333 /*****************************
335 *****************************/
336 void MainInterface::recreateToolbars()
338 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
340 settings->beginGroup( "MainWindow" );
344 controls = new ControlsWidget( p_intf, b_adv, this );
345 inputC = new InputControlsWidget( p_intf, this );
347 if( fullscreenControls )
349 delete fullscreenControls;
350 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
351 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
352 this, handleKeyPress( QKeyEvent * ) );
354 mainLayout->insertWidget( 2, inputC );
355 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
357 settings->endGroup();
360 void MainInterface::reloadPrefs()
362 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
363 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
365 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
367 if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
369 delete fullscreenControls;
370 fullscreenControls = NULL;
374 void MainInterface::createMainWidget( QSettings *settings )
376 /* Create the main Widget and the mainLayout */
377 QWidget *main = new QWidget;
378 setCentralWidget( main );
379 mainLayout = new QVBoxLayout( main );
380 main->setContentsMargins( 0, 0, 0, 0 );
381 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
384 stackCentralW = new QVLCStackedWidget( main );
387 bgWidget = new BackgroundWidget( p_intf );
388 stackCentralW->addWidget( bgWidget );
389 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
390 bgWidget->setWithArt( false );
392 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
393 bgWidget->setExpandstoHeight( true );
395 /* And video Outputs */
396 if( b_videoEmbedded )
398 videoWidget = new VideoWidget( p_intf );
399 stackCentralW->addWidget( videoWidget );
401 mainLayout->insertWidget( 1, stackCentralW );
403 settings->beginGroup( "MainWindow" );
404 stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 600, 0 ) ).toSize();
405 /* Resize even if no-auto-resize, because we are at creation */
406 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
408 /* Create the CONTROLS Widget */
409 controls = new ControlsWidget( p_intf,
410 settings->value( "adv-controls", false ).toBool(), this );
411 inputC = new InputControlsWidget( p_intf, this );
413 mainLayout->insertWidget( 2, inputC );
414 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
417 /* Visualisation, disabled for now, they SUCK */
419 visualSelector = new VisualSelector( p_intf );
420 mainLayout->insertWidget( 0, visualSelector );
421 visualSelector->hide();
424 settings->endGroup();
426 /* Enable the popup menu in the MI */
427 main->setContextMenuPolicy( Qt::CustomContextMenu );
428 CONNECT( main, customContextMenuRequested( const QPoint& ),
429 this, popupMenu( const QPoint& ) );
431 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
432 /* Create the FULLSCREEN CONTROLS Widget */
433 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
435 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
436 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
437 this, handleKeyPress( QKeyEvent * ) );
441 inline void MainInterface::initSystray()
444 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
445 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
447 if( var_InheritBool( p_intf, "qt-start-minimized") )
449 if( b_systrayAvailable )
451 b_systrayWanted = true;
452 b_hideAfterCreation = true;
455 msg_Err( p_intf, "cannot start minimized without system tray bar" );
458 if( b_systrayAvailable && b_systrayWanted )
463 inline void MainInterface::createStatusBar()
468 /* Widgets Creation*/
469 QStatusBar *statusBarr = statusBar();
471 TimeLabel *timeLabel = new TimeLabel( p_intf );
472 nameLabel = new QLabel( this );
473 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
474 | Qt::TextSelectableByKeyboard );
475 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
477 /* Styling those labels */
478 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
479 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
480 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
481 timeLabel->setStyleSheet(
482 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
483 speedLabel->setStyleSheet(
484 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
485 /* pad both label and its tooltip */
486 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
488 /* and adding those */
489 statusBarr->addWidget( nameLabel, 8 );
490 statusBarr->addPermanentWidget( speedLabel, 0 );
491 statusBarr->addPermanentWidget( timeLabel, 0 );
493 /* timeLabel behaviour:
494 - double clicking opens the goto time dialog
495 - right-clicking and clicking just toggle between remaining and
497 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
499 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
500 this, showCryptedLabel( bool ) );
502 CONNECT( THEMIM->getIM(), seekRequested( float ),
503 timeLabel, setDisplayPosition( float ) );
505 /* This shouldn't be necessary, but for somehow reason, the statusBarr
506 starts at height of 20px and when a text is shown it needs more space.
507 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
508 geometry, we need to force a height. If you have a better idea, please
511 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
514 /**********************************************************************
515 * Handling of sizing of the components
516 **********************************************************************/
518 void MainInterface::debug()
521 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
522 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
523 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
525 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
526 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
527 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
531 inline void MainInterface::showVideo() { showTab( videoWidget ); }
532 inline void MainInterface::restoreStackOldWidget()
533 { showTab( stackCentralOldWidget ); }
535 inline void MainInterface::showTab( QWidget *widget )
538 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
541 stackCentralOldWidget = stackCentralW->currentWidget();
542 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
544 stackCentralW->setCurrentWidget( widget );
546 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
549 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
550 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
554 void MainInterface::destroyPopupMenu()
556 QVLCMenu::PopupMenu( p_intf, false );
559 void MainInterface::popupMenu( const QPoint & )
561 QVLCMenu::PopupMenu( p_intf, true );
564 void MainInterface::toggleFSC()
566 if( !fullscreenControls ) return;
568 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
569 QApplication::postEvent( fullscreenControls, eShow );
572 /****************************************************************************
574 ****************************************************************************/
578 * You must not change the state of this object or other Qt4 UI objects,
579 * from the video output thread - only from the Qt4 UI main loop thread.
580 * All window provider queries must be handled through signals or events.
581 * That's why we have all those emit statements...
583 WId MainInterface::getVideo( int *pi_x, int *pi_y,
584 unsigned int *pi_width, unsigned int *pi_height )
589 /* This is a blocking call signal. Results are returned through pointers.
590 * Beware of deadlocks! */
592 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
596 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
597 unsigned *pi_width, unsigned *pi_height )
599 /* Hidden or minimized, activate */
600 if( isHidden() || isMinimized() )
601 toggleUpdateSystrayMenu();
603 /* Request the videoWidget */
604 WId ret = videoWidget->request( pi_x, pi_y,
605 pi_width, pi_height, !b_autoresize );
607 if( ret ) /* The videoWidget is available */
609 /* Consider the video active now */
612 /* Ask videoWidget to resize correctly, if we are in normal mode */
613 if( !isFullScreen() && !isMaximized() && b_autoresize )
614 videoWidget->SetSizing( *pi_width, *pi_height );
618 /* Asynchronous call from the WindowClose function */
619 void MainInterface::releaseVideo( void )
621 emit askReleaseVideo();
624 /* Function that is CONNECTED to the previous emit */
625 void MainInterface::releaseVideoSlot( void )
627 /* This function is called when the embedded video window is destroyed,
628 * or in the rare case that the embedded window is still here but the
629 * Qt4 interface exits. */
630 assert( videoWidget );
631 videoWidget->release();
632 setVideoOnTop( false );
633 setVideoFullScreen( false );
635 if( stackCentralW->currentWidget() == videoWidget )
636 restoreStackOldWidget();
638 /* We don't want to have a blank video to popup */
639 stackCentralOldWidget = bgWidget;
642 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
644 if( !isFullScreen() && !isMaximized() )
645 videoWidget->SetSizing( w, h );
648 void MainInterface::setVideoFullScreen( bool fs )
650 b_videoFullScreen = fs;
653 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
654 /* if user hasn't defined screennumber, or screennumber that is bigger
655 * than current number of screens, take screennumber where current interface
658 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
659 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
661 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
663 /* To be sure window is on proper-screen in xinerama */
664 if( !screenres.contains( pos() ) )
666 msg_Dbg( p_intf, "Moving video to correct screen");
667 move( QPoint( screenres.x(), screenres.y() ) );
669 setMinimalView( true );
670 setInterfaceFullScreen( true );
674 /* TODO do we want to restore screen and position ? (when
675 * qt-fullscreen-screennumber is forced) */
676 setMinimalView( b_minimalView );
677 setInterfaceFullScreen( b_interfaceFullScreen );
682 /* Slot to change the video always-on-top flag.
683 * Emit askVideoOnTop() to invoke this from other thread. */
684 void MainInterface::setVideoOnTop( bool on_top )
686 Qt::WindowFlags oldflags = windowFlags(), newflags;
689 newflags = oldflags | Qt::WindowStaysOnTopHint;
691 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
692 if( newflags != oldflags && !b_videoFullScreen )
695 setWindowFlags( newflags );
696 show(); /* necessary to apply window flags */
700 /* Asynchronous call from WindowControl function */
701 int MainInterface::controlVideo( int i_query, va_list args )
705 case VOUT_WINDOW_SET_SIZE:
707 unsigned int i_width = va_arg( args, unsigned int );
708 unsigned int i_height = va_arg( args, unsigned int );
710 emit askVideoToResize( i_width, i_height );
713 case VOUT_WINDOW_SET_STATE:
715 unsigned i_arg = va_arg( args, unsigned );
716 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
718 emit askVideoOnTop( on_top != 0 );
721 case VOUT_WINDOW_SET_FULLSCREEN:
723 bool b_fs = va_arg( args, int );
725 emit askVideoSetFullScreen( b_fs );
729 msg_Warn( p_intf, "unsupported control query" );
734 /*****************************************************************************
735 * Playlist, Visualisation and Menus handling
736 *****************************************************************************/
738 * Toggle the playlist widget or dialog
740 void MainInterface::createPlaylist()
742 playlistWidget = new PlaylistWidget( p_intf, this );
746 stackCentralW->addWidget( playlistWidget );
747 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
752 playlistWidget->setParent( NULL );
754 playlistWidget->setWindowFlags( Qt::Window );
756 /* This will restore the geometry but will not work for position,
757 because of parenting */
758 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
759 playlistWidget, QSize( 600, 300 ) );
763 void MainInterface::togglePlaylist()
765 if( !playlistWidget )
772 /* Playlist is not visible, show it */
773 if( stackCentralW->currentWidget() != playlistWidget )
775 showTab( playlistWidget );
779 restoreStackOldWidget();
781 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
786 playlistWidget->setParent( NULL );
788 playlistWidget->setWindowFlags( Qt::Window );
789 playlistVisible = !playlistVisible;
790 playlistWidget->setVisible( playlistVisible );
795 void MainInterface::dockPlaylist( bool p_docked )
797 if( b_plDocked == p_docked ) return;
798 b_plDocked = p_docked;
800 if( !playlistWidget ) return; /* Playlist wasn't created yet */
803 stackCentralW->removeWidget( playlistWidget );
805 playlistWidget->setParent( NULL );
807 playlistWidget->setWindowFlags( Qt::Window );
808 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
809 playlistWidget, QSize( 600, 300 ) );
810 playlistWidget->show();
811 restoreStackOldWidget();
815 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
816 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
817 // It would be logical that QStackWidget::addWidget reset the flags...
818 stackCentralW->addWidget( playlistWidget );
819 showTab( playlistWidget );
821 playlistVisible = true;
825 * setMinimalView is the private function used by
826 * the SLOT toggleMinimalView and setVideoFullScreen
828 void MainInterface::setMinimalView( bool b_minimal )
830 menuBar()->setVisible( !b_minimal );
831 controls->setVisible( !b_minimal );
832 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
833 inputC->setVisible( !b_minimal );
837 * This public SLOT is used for moving to minimal View Mode
839 * If b_minimal is false, then we are normalView
841 void MainInterface::toggleMinimalView( bool b_minimal )
843 if( !b_minimalView && b_autoresize ) /* Normal mode */
845 if( stackCentralW->currentWidget() == bgWidget )
847 if( stackCentralW->height() < 16 )
849 resizeStack( stackCentralW->width(), 100 );
853 b_minimalView = b_minimal;
854 if( !b_videoFullScreen )
856 setMinimalView( b_minimalView );
857 computeMinimumSize();
860 emit minimalViewToggled( b_minimalView );
863 /* toggling advanced controls buttons */
864 void MainInterface::toggleAdvancedButtons()
866 controls->toggleAdvanced();
867 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
870 /* Get the visibility status of the controls (hidden or not, advanced or not) */
871 int MainInterface::getControlsVisibilityStatus()
873 if( !controls ) return 0;
874 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
875 + CONTROLS_ADVANCED * controls->b_advancedVisible );
878 void MainInterface::setStatusBarVisibility( bool b_visible )
880 statusBar()->setVisible( b_visible );
881 b_statusbarVisible = b_visible;
882 if( controls ) controls->setGripVisible( !b_statusbarVisible );
886 void MainInterface::visual()
888 if( !VISIBLE( visualSelector) )
890 visualSelector->show();
891 if( !THEMIM->getIM()->hasVideo() )
893 /* Show the background widget */
895 visualSelectorEnabled = true;
899 /* Stop any currently running visualization */
900 visualSelector->hide();
901 visualSelectorEnabled = false;
906 /************************************************************************
908 ************************************************************************/
909 void MainInterface::setName( const QString& name )
911 input_name = name; /* store it for the QSystray use */
912 /* Display it in the status bar, but also as a Tooltip in case it doesn't
914 nameLabel->setText( name );
915 nameLabel->setToolTip( name );
919 * Give the decorations of the Main Window a correct Name.
920 * If nothing is given, set it to VLC...
922 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
924 if( aTitle.isEmpty() )
926 setWindowTitle( qtr( "VLC media player" ) );
930 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
934 void MainInterface::showCryptedLabel( bool b_show )
936 if( cryptedLabel == NULL )
938 cryptedLabel = new QLabel;
939 // The lock icon is not the right one for DRM protection/scrambled.
940 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
941 cryptedLabel->setText( "DRM" );
942 statusBar()->addWidget( cryptedLabel );
945 cryptedLabel->setVisible( b_show );
948 void MainInterface::showBuffering( float f_cache )
950 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
951 statusBar()->showMessage( amount, 1000 );
954 /*****************************************************************************
955 * Systray Icon and Systray Menu
956 *****************************************************************************/
959 * Create a SystemTray icon and a menu that would go with it.
960 * Connects to a click handler on the icon.
962 void MainInterface::createSystray()
965 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
966 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
968 iconVLC = QIcon( ":/logo/vlc128.png" );
969 sysTray = new QSystemTrayIcon( iconVLC, this );
970 sysTray->setToolTip( qtr( "VLC media player" ));
972 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
973 systrayMenu->setIcon( iconVLC );
975 QVLCMenu::updateSystrayMenu( this, p_intf, true );
978 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
979 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
981 /* Connects on nameChanged() */
982 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
983 this, updateSystrayTooltipName( const QString& ) );
984 /* Connect PLAY_STATUS on the systray */
985 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
986 this, updateSystrayTooltipStatus( int ) );
990 * Updates the Systray Icon's menu and toggle the main interface
992 void MainInterface::toggleUpdateSystrayMenu()
994 /* If hidden, show it */
1000 else if( isMinimized() )
1008 /* Visible (possibly under other windows) */
1010 /* check if any visible window is above vlc in the z-order,
1011 * but ignore the ones always on top
1012 * and the ones which can't be activated */
1015 wi.cbSize = sizeof( WINDOWINFO );
1016 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1017 hwnd && ( !IsWindowVisible( hwnd ) ||
1018 ( GetWindowInfo( hwnd, &wi ) &&
1019 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1020 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1021 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1022 (wi.dwExStyle&WS_EX_TOPMOST) )
1035 QVLCMenu::updateSystrayMenu( this, p_intf );
1038 /* First Item of the systray menu */
1039 void MainInterface::showUpdateSystrayMenu()
1047 QVLCMenu::updateSystrayMenu( this, p_intf );
1050 /* First Item of the systray menu */
1051 void MainInterface::hideUpdateSystrayMenu()
1054 QVLCMenu::updateSystrayMenu( this, p_intf );
1057 /* Click on systray Icon */
1058 void MainInterface::handleSystrayClick(
1059 QSystemTrayIcon::ActivationReason reason )
1063 case QSystemTrayIcon::Trigger:
1064 case QSystemTrayIcon::DoubleClick:
1066 QVLCMenu::updateSystrayMenu( this, p_intf );
1068 toggleUpdateSystrayMenu();
1071 case QSystemTrayIcon::MiddleClick:
1072 sysTray->showMessage( qtr( "VLC media player" ),
1073 qtr( "Control menu for the player" ),
1074 QSystemTrayIcon::Information, 3000 );
1082 * Updates the name of the systray Icon tooltip.
1083 * Doesn't check if the systray exists, check before you call it.
1085 void MainInterface::updateSystrayTooltipName( const QString& name )
1087 if( name.isEmpty() )
1089 sysTray->setToolTip( qtr( "VLC media player" ) );
1093 sysTray->setToolTip( name );
1094 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1096 sysTray->showMessage( qtr( "VLC media player" ), name,
1097 QSystemTrayIcon::NoIcon, 3000 );
1101 QVLCMenu::updateSystrayMenu( this, p_intf );
1105 * Updates the status of the systray Icon tooltip.
1106 * Doesn't check if the systray exists, check before you call it.
1108 void MainInterface::updateSystrayTooltipStatus( int i_status )
1113 sysTray->setToolTip( input_name );
1116 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1119 sysTray->setToolTip( qtr( "VLC media player" ) );
1122 QVLCMenu::updateSystrayMenu( this, p_intf );
1126 void MainInterface::changeEvent(QEvent *event)
1128 if( event->type() == QEvent::WindowStateChange )
1130 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1131 Qt::WindowStates newState = windowState();
1132 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1134 if( newState & Qt::WindowMinimized )
1136 b_hasPausedWhenMinimized = false;
1138 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1139 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1142 b_hasPausedWhenMinimized = true;
1146 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1148 if( b_hasPausedWhenMinimized )
1155 QWidget::changeEvent(event);
1158 /************************************************************************
1160 ************************************************************************/
1161 void MainInterface::dropEvent(QDropEvent *event)
1163 dropEventPlay( event, true );
1166 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1168 if( event->possibleActions() & Qt::CopyAction )
1169 event->setDropAction( Qt::CopyAction );
1173 const QMimeData *mimeData = event->mimeData();
1175 /* D&D of a subtitles file, add it on the fly */
1176 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1178 if( !input_AddSubtitle( THEMIM->getInput(),
1179 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1187 bool first = b_play;
1188 foreach( const QUrl &url, mimeData->urls() )
1192 QString mrl = toURI( url.toEncoded().constData() );
1193 playlist_Add( THEPL, qtu(mrl), NULL,
1194 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1195 PLAYLIST_END, true, pl_Unlocked );
1197 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1201 /* Browsers give content as text if you dnd the addressbar,
1202 so check if mimedata has valid url in text and use it
1203 if we didn't get any normal Urls()*/
1204 if( !mimeData->hasUrls() && mimeData->hasText() &&
1205 QUrl(mimeData->text()).isValid() )
1207 QString mrl = toURI( mimeData->text() );
1208 playlist_Add( THEPL, qtu(mrl), NULL,
1209 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1210 PLAYLIST_END, true, pl_Unlocked );
1214 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1216 event->acceptProposedAction();
1218 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1220 event->acceptProposedAction();
1222 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1227 /************************************************************************
1229 ************************************************************************/
1230 void MainInterface::keyPressEvent( QKeyEvent *e )
1232 handleKeyPress( e );
1235 void MainInterface::handleKeyPress( QKeyEvent *e )
1237 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1239 toggleMinimalView( !b_minimalView );
1243 int i_vlck = qtEventToVLCKey( e );
1246 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1253 void MainInterface::wheelEvent( QWheelEvent *e )
1255 int i_vlckey = qtWheelEventToVLCKey( e );
1256 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1260 void MainInterface::closeEvent( QCloseEvent *e )
1263 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1264 /* Accept session quit. Otherwise we break the desktop mamager. */
1268 void MainInterface::setInterfaceFullScreen( bool fs )
1271 setWindowState( windowState() | Qt::WindowFullScreen );
1273 setWindowState( windowState() & ~Qt::WindowFullScreen );
1275 void MainInterface::toggleInterfaceFullScreen()
1277 b_interfaceFullScreen = !b_interfaceFullScreen;
1278 if( !b_videoFullScreen )
1279 setInterfaceFullScreen( b_interfaceFullScreen );
1280 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1283 void MainInterface::emitBoss()
1287 void MainInterface::setBoss()
1302 /*****************************************************************************
1303 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1304 * We don't show the menu directly here because we don't want the
1305 * caller to block for a too long time.
1306 *****************************************************************************/
1307 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1308 vlc_value_t old_val, vlc_value_t new_val, void *param )
1310 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1312 intf_thread_t *p_intf = (intf_thread_t *)param;
1314 if( p_intf->pf_show_dialog )
1316 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1317 new_val.b_bool, NULL );
1323 /*****************************************************************************
1324 * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1325 *****************************************************************************/
1326 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1327 vlc_value_t old_val, vlc_value_t new_val, void *param )
1329 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1330 VLC_UNUSED( new_val );
1332 intf_thread_t *p_intf = (intf_thread_t *)param;
1333 p_intf->p_sys->p_mi->toggleFSC();
1339 /*****************************************************************************
1340 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1341 *****************************************************************************/
1342 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1343 vlc_value_t old_val, vlc_value_t new_val, void *param )
1345 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1346 VLC_UNUSED( new_val );
1348 intf_thread_t *p_intf = (intf_thread_t *)param;
1349 p_intf->p_sys->p_mi->emitBoss();