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 );
72 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
74 /* Variables initialisation */
77 playlistWidget = NULL;
78 stackCentralOldWidget= NULL;
82 fullscreenControls = NULL;
87 b_hideAfterCreation = false; // --qt-start-minimized
88 playlistVisible = false;
90 b_interfaceFullScreen= false;
94 FirstRun::CheckAndRun( this, p_intf );
97 * Configuration and settings
98 * Pre-building of interface
101 setFocusPolicy( Qt::StrongFocus );
102 setAcceptDrops( true );
103 setWindowRole( "vlc-main" );
104 setWindowIcon( QApplication::windowIcon() );
105 setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
107 setAttribute( Qt::WA_MacBrushedMetal );
110 /* Is video in embedded in the UI or not */
111 b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
113 /* Does the interface resize to video size or the opposite */
114 b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
116 /* Are we in the enhanced always-video mode or not ? */
117 b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
119 /* Do we want anoying popups or not */
120 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
122 /* Set the other interface settings */
123 settings = getSettings();
124 settings->beginGroup( "MainWindow" );
128 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
132 b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
134 settings->endGroup( );
136 /*********************************
137 * Create the Systray Management *
138 *********************************/
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 * Connect the input manager to the GUI elements it manages *
174 ************************************************************/
176 * Connects on nameChanged()
177 * Those connects are different because options can impeach them to trigger.
179 /* Main Interface statusbar */
180 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
181 this, setName( const QString& ) );
186 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
187 this, updateSystrayTooltipName( const QString& ) );
190 /* and title of the Main Interface*/
191 if( var_InheritBool( p_intf, "qt-name-in-title" ) )
193 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
194 this, setVLCWindowsTitle( const QString& ) );
198 * CONNECTS on PLAY_STATUS
200 /* Status on the systray */
204 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
205 this, updateSystrayTooltipStatus( int ) );
209 /* END CONNECTS ON IM */
211 /* VideoWidget connects for asynchronous calls */
212 b_videoFullScreen = false;
213 connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
214 this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
215 Qt::BlockingQueuedConnection );
216 connect( this, SIGNAL(askReleaseVideo( void )),
217 this, SLOT(releaseVideoSlot( void )),
218 Qt::BlockingQueuedConnection );
219 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
225 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
226 this, setVideoSize( unsigned int, unsigned int ) );
227 CONNECT( videoWidget, sizeChanged( int, int ),
228 this, resizeStack( int, int ) );
230 CONNECT( this, askVideoSetFullScreen( bool ),
231 this, setVideoFullScreen( bool ) );
234 CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
236 CONNECT( this, askToQuit(), THEDP, quit() );
238 /** END of CONNECTS**/
244 var_AddCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
246 /* Register callback for the intf-popupmenu variable */
247 var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
250 int i_plVis = settings->value( "MainWindow/playlist-visible", false ).toBool();
252 if( i_plVis ) togglePlaylist();
254 /**** FINAL SIZING and placement of interface */
255 settings->beginGroup( "MainWindow" );
256 QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
257 settings->endGroup();
259 b_interfaceFullScreen = isFullScreen();
261 /* Final sizing and showing */
262 setVisible( !b_hideAfterCreation );
264 computeMinimumSize();
266 /* Switch to minimal view if needed, must be called after the show() */
268 toggleMinimalView( true );
270 b_hasPausedWhenMinimized = false;
273 MainInterface::~MainInterface()
275 /* Unsure we hide the videoWidget before destroying it */
276 if( stackCentralOldWidget == videoWidget )
284 ImageList_Destroy( himl );
286 p_taskbl->vt->Release(p_taskbl);
290 /* Be sure to kill the actionsManager... Only used in the MI and control */
291 ActionsManager::killInstance();
294 ExtensionsManager::killInstance();
296 /* Delete the FSC controller */
297 delete fullscreenControls;
300 settings->beginGroup( "MainWindow" );
302 settings->setValue( "pl-dock-status", b_plDocked );
303 /* Save playlist state */
305 settings->setValue( "playlist-visible", playlistVisible );
307 settings->setValue( "adv-controls",
308 getControlsVisibilityStatus() & CONTROLS_ADVANCED );
309 settings->setValue( "status-bar-visible", b_statusbarVisible );
311 /* Save the stackCentralW sizes */
312 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
313 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
316 QVLCTools::saveWidgetPosition(settings, this);
318 settings->endGroup();
320 /* Save undocked playlist size */
321 if( playlistWidget && !isPlDocked() )
322 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
324 delete playlistWidget;
328 /* Unregister callbacks */
329 var_DelCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
330 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
332 p_intf->p_sys->p_mi = NULL;
335 void MainInterface::computeMinimumSize()
338 if( menuBar()->isVisible() )
339 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
341 setMinimumWidth( minWidth );
344 /*****************************
346 *****************************/
347 void MainInterface::recreateToolbars()
349 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
351 settings->beginGroup( "MainWindow" );
355 controls = new ControlsWidget( p_intf, b_adv, this );
356 inputC = new InputControlsWidget( p_intf, this );
358 if( fullscreenControls )
360 delete fullscreenControls;
361 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
362 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
363 this, handleKeyPress( QKeyEvent * ) );
365 mainLayout->insertWidget( 2, inputC );
366 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
368 settings->endGroup();
371 void MainInterface::createMainWidget( QSettings *settings )
373 /* Create the main Widget and the mainLayout */
374 QWidget *main = new QWidget;
375 setCentralWidget( main );
376 mainLayout = new QVBoxLayout( main );
377 main->setContentsMargins( 0, 0, 0, 0 );
378 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
381 stackCentralW = new QVLCStackedWidget( main );
384 bgWidget = new BackgroundWidget( p_intf );
385 stackCentralW->addWidget( bgWidget );
386 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
387 bgWidget->setWithArt( false );
389 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
390 bgWidget->setExpandstoHeight( true );
392 /* And video Outputs */
393 if( b_videoEmbedded )
395 videoWidget = new VideoWidget( p_intf );
396 stackCentralW->addWidget( videoWidget );
398 mainLayout->insertWidget( 1, stackCentralW );
400 settings->beginGroup( "MainWindow" );
401 stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 600, 0 ) ).toSize();
402 /* Resize even if no-auto-resize, because we are at creation */
403 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
405 /* Create the CONTROLS Widget */
406 controls = new ControlsWidget( p_intf,
407 settings->value( "adv-controls", false ).toBool(), this );
408 inputC = new InputControlsWidget( p_intf, this );
410 mainLayout->insertWidget( 2, inputC );
411 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
414 /* Visualisation, disabled for now, they SUCK */
416 visualSelector = new VisualSelector( p_intf );
417 mainLayout->insertWidget( 0, visualSelector );
418 visualSelector->hide();
421 settings->endGroup();
423 /* Enable the popup menu in the MI */
424 main->setContextMenuPolicy( Qt::CustomContextMenu );
425 CONNECT( main, customContextMenuRequested( const QPoint& ),
426 this, popupMenu( const QPoint& ) );
428 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
429 /* Create the FULLSCREEN CONTROLS Widget */
430 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
432 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
433 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
434 this, handleKeyPress( QKeyEvent * ) );
438 inline void MainInterface::initSystray()
441 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
442 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
444 if( var_InheritBool( p_intf, "qt-start-minimized") )
446 if( b_systrayAvailable )
448 b_systrayWanted = true;
449 b_hideAfterCreation = true;
452 msg_Err( p_intf, "cannot start minimized without system tray bar" );
455 if( b_systrayAvailable && b_systrayWanted )
460 inline void MainInterface::createStatusBar()
465 /* Widgets Creation*/
466 QStatusBar *statusBarr = statusBar();
468 TimeLabel *timeLabel = new TimeLabel( p_intf );
469 nameLabel = new QLabel( this );
470 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
471 | Qt::TextSelectableByKeyboard );
472 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
474 /* Styling those labels */
475 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
476 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
477 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
478 timeLabel->setStyleSheet(
479 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
480 speedLabel->setStyleSheet(
481 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
482 /* pad both label and its tooltip */
483 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
485 /* and adding those */
486 statusBarr->addWidget( nameLabel, 8 );
487 statusBarr->addPermanentWidget( speedLabel, 0 );
488 statusBarr->addPermanentWidget( timeLabel, 0 );
490 /* timeLabel behaviour:
491 - double clicking opens the goto time dialog
492 - right-clicking and clicking just toggle between remaining and
494 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
496 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
497 this, showCryptedLabel( bool ) );
499 CONNECT( THEMIM->getIM(), seekRequested( float ),
500 timeLabel, setDisplayPosition( float ) );
502 /* This shouldn't be necessary, but for somehow reason, the statusBarr
503 starts at height of 20px and when a text is shown it needs more space.
504 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
505 geometry, we need to force a height. If you have a better idea, please
508 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
511 /**********************************************************************
512 * Handling of sizing of the components
513 **********************************************************************/
515 void MainInterface::debug()
518 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
519 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
520 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
522 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
523 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
524 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
528 inline void MainInterface::showVideo() { showTab( videoWidget ); }
529 inline void MainInterface::restoreStackOldWidget()
530 { showTab( stackCentralOldWidget ); }
532 inline void MainInterface::showTab( QWidget *widget )
535 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
538 stackCentralOldWidget = stackCentralW->currentWidget();
539 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
541 stackCentralW->setCurrentWidget( widget );
543 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
546 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
547 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
551 void MainInterface::destroyPopupMenu()
553 QVLCMenu::PopupMenu( p_intf, false );
556 void MainInterface::popupMenu( const QPoint & )
558 QVLCMenu::PopupMenu( p_intf, true );
561 void MainInterface::toggleFSC()
563 if( !fullscreenControls ) return;
565 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
566 QApplication::postEvent( fullscreenControls, eShow );
569 /****************************************************************************
571 ****************************************************************************/
575 * You must not change the state of this object or other Qt4 UI objects,
576 * from the video output thread - only from the Qt4 UI main loop thread.
577 * All window provider queries must be handled through signals or events.
578 * That's why we have all those emit statements...
580 WId MainInterface::getVideo( int *pi_x, int *pi_y,
581 unsigned int *pi_width, unsigned int *pi_height )
586 /* This is a blocking call signal. Results are returned through pointers.
587 * Beware of deadlocks! */
589 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
593 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
594 unsigned *pi_width, unsigned *pi_height )
596 /* Hidden or minimized, activate */
597 if( isHidden() || isMinimized() )
598 toggleUpdateSystrayMenu();
600 /* Request the videoWidget */
601 WId ret = videoWidget->request( pi_x, pi_y,
602 pi_width, pi_height, !b_autoresize );
604 if( ret ) /* The videoWidget is available */
606 /* Consider the video active now */
609 /* Ask videoWidget to resize correctly, if we are in normal mode */
610 if( !isFullScreen() && !isMaximized() && b_autoresize )
611 videoWidget->SetSizing( *pi_width, *pi_height );
615 /* Asynchronous call from the WindowClose function */
616 void MainInterface::releaseVideo( void )
618 emit askReleaseVideo();
621 /* Function that is CONNECTED to the previous emit */
622 void MainInterface::releaseVideoSlot( void )
624 /* This function is called when the embedded video window is destroyed,
625 * or in the rare case that the embedded window is still here but the
626 * Qt4 interface exits. */
627 assert( videoWidget );
628 videoWidget->release();
629 setVideoOnTop( false );
630 setVideoFullScreen( false );
632 if( stackCentralW->currentWidget() == videoWidget )
633 restoreStackOldWidget();
635 /* We don't want to have a blank video to popup */
636 stackCentralOldWidget = bgWidget;
639 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
641 if( !isFullScreen() && !isMaximized() )
642 videoWidget->SetSizing( w, h );
645 void MainInterface::setVideoFullScreen( bool fs )
647 b_videoFullScreen = fs;
650 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
651 /* if user hasn't defined screennumber, or screennumber that is bigger
652 * than current number of screens, take screennumber where current interface
655 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
656 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
658 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
660 /* To be sure window is on proper-screen in xinerama */
661 if( !screenres.contains( pos() ) )
663 msg_Dbg( p_intf, "Moving video to correct screen");
664 move( QPoint( screenres.x(), screenres.y() ) );
666 setMinimalView( true );
667 setInterfaceFullScreen( true );
671 /* TODO do we want to restore screen and position ? (when
672 * qt-fullscreen-screennumber is forced) */
673 setMinimalView( b_minimalView );
674 setInterfaceFullScreen( b_interfaceFullScreen );
679 /* Slot to change the video always-on-top flag.
680 * Emit askVideoOnTop() to invoke this from other thread. */
681 void MainInterface::setVideoOnTop( bool on_top )
683 Qt::WindowFlags oldflags = windowFlags(), newflags;
686 newflags = oldflags | Qt::WindowStaysOnTopHint;
688 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
689 if( newflags != oldflags && !b_videoFullScreen )
692 setWindowFlags( newflags );
693 show(); /* necessary to apply window flags */
697 /* Asynchronous call from WindowControl function */
698 int MainInterface::controlVideo( int i_query, va_list args )
702 case VOUT_WINDOW_SET_SIZE:
704 unsigned int i_width = va_arg( args, unsigned int );
705 unsigned int i_height = va_arg( args, unsigned int );
707 emit askVideoToResize( i_width, i_height );
710 case VOUT_WINDOW_SET_STATE:
712 unsigned i_arg = va_arg( args, unsigned );
713 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
715 emit askVideoOnTop( on_top != 0 );
718 case VOUT_WINDOW_SET_FULLSCREEN:
720 bool b_fs = va_arg( args, int );
722 emit askVideoSetFullScreen( b_fs );
726 msg_Warn( p_intf, "unsupported control query" );
731 /*****************************************************************************
732 * Playlist, Visualisation and Menus handling
733 *****************************************************************************/
735 * Toggle the playlist widget or dialog
737 void MainInterface::createPlaylist()
739 playlistWidget = new PlaylistWidget( p_intf, this );
743 stackCentralW->addWidget( playlistWidget );
744 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
749 playlistWidget->setParent( NULL );
751 playlistWidget->setWindowFlags( Qt::Window );
753 /* This will restore the geometry but will not work for position,
754 because of parenting */
755 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
756 playlistWidget, QSize( 600, 300 ) );
760 void MainInterface::togglePlaylist()
762 if( !playlistWidget )
769 /* Playlist is not visible, show it */
770 if( stackCentralW->currentWidget() != playlistWidget )
772 showTab( playlistWidget );
776 restoreStackOldWidget();
778 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
783 playlistWidget->setParent( NULL );
785 playlistWidget->setWindowFlags( Qt::Window );
786 playlistVisible = !playlistVisible;
787 playlistWidget->setVisible( playlistVisible );
792 void MainInterface::dockPlaylist( bool p_docked )
794 if( b_plDocked == p_docked ) return;
795 b_plDocked = p_docked;
797 if( !playlistWidget ) return; /* Playlist wasn't created yet */
800 stackCentralW->removeWidget( playlistWidget );
802 playlistWidget->setParent( NULL );
804 playlistWidget->setWindowFlags( Qt::Window );
805 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
806 playlistWidget, QSize( 600, 300 ) );
807 playlistWidget->show();
808 restoreStackOldWidget();
812 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
813 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
814 // It would be logical that QStackWidget::addWidget reset the flags...
815 stackCentralW->addWidget( playlistWidget );
816 showTab( playlistWidget );
818 playlistVisible = true;
822 * setMinimalView is the private function used by
823 * the SLOT toggleMinimalView and setVideoFullScreen
825 void MainInterface::setMinimalView( bool b_minimal )
827 menuBar()->setVisible( !b_minimal );
828 controls->setVisible( !b_minimal );
829 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
830 inputC->setVisible( !b_minimal );
834 * This public SLOT is used for moving to minimal View Mode
836 * If b_minimal is false, then we are normalView
838 void MainInterface::toggleMinimalView( bool b_minimal )
840 if( !b_minimalView && b_autoresize ) /* Normal mode */
842 if( stackCentralW->currentWidget() == bgWidget )
844 if( stackCentralW->height() < 16 )
846 resizeStack( stackCentralW->width(), 100 );
850 b_minimalView = b_minimal;
851 if( !b_videoFullScreen )
853 setMinimalView( b_minimalView );
854 computeMinimumSize();
857 emit minimalViewToggled( b_minimalView );
860 /* toggling advanced controls buttons */
861 void MainInterface::toggleAdvancedButtons()
863 controls->toggleAdvanced();
864 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
867 /* Get the visibility status of the controls (hidden or not, advanced or not) */
868 int MainInterface::getControlsVisibilityStatus()
870 if( !controls ) return 0;
871 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
872 + CONTROLS_ADVANCED * controls->b_advancedVisible );
875 void MainInterface::setStatusBarVisibility( bool b_visible )
877 statusBar()->setVisible( b_visible );
878 b_statusbarVisible = b_visible;
879 if( controls ) controls->setGripVisible( !b_statusbarVisible );
883 void MainInterface::visual()
885 if( !VISIBLE( visualSelector) )
887 visualSelector->show();
888 if( !THEMIM->getIM()->hasVideo() )
890 /* Show the background widget */
892 visualSelectorEnabled = true;
896 /* Stop any currently running visualization */
897 visualSelector->hide();
898 visualSelectorEnabled = false;
903 /************************************************************************
905 ************************************************************************/
906 void MainInterface::setName( const QString& name )
908 input_name = name; /* store it for the QSystray use */
909 /* Display it in the status bar, but also as a Tooltip in case it doesn't
911 nameLabel->setText( name );
912 nameLabel->setToolTip( name );
916 * Give the decorations of the Main Window a correct Name.
917 * If nothing is given, set it to VLC...
919 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
921 if( aTitle.isEmpty() )
923 setWindowTitle( qtr( "VLC media player" ) );
927 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
931 void MainInterface::showCryptedLabel( bool b_show )
933 if( cryptedLabel == NULL )
935 cryptedLabel = new QLabel;
936 // The lock icon is not the right one for DRM protection/scrambled.
937 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
938 cryptedLabel->setText( "DRM" );
939 statusBar()->addWidget( cryptedLabel );
942 cryptedLabel->setVisible( b_show );
945 void MainInterface::showBuffering( float f_cache )
947 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
948 statusBar()->showMessage( amount, 1000 );
951 /*****************************************************************************
952 * Systray Icon and Systray Menu
953 *****************************************************************************/
956 * Create a SystemTray icon and a menu that would go with it.
957 * Connects to a click handler on the icon.
959 void MainInterface::createSystray()
962 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
963 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
965 iconVLC = QIcon( ":/logo/vlc128.png" );
966 sysTray = new QSystemTrayIcon( iconVLC, this );
967 sysTray->setToolTip( qtr( "VLC media player" ));
969 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
970 systrayMenu->setIcon( iconVLC );
972 QVLCMenu::updateSystrayMenu( this, p_intf, true );
975 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
976 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
980 * Updates the Systray Icon's menu and toggle the main interface
982 void MainInterface::toggleUpdateSystrayMenu()
984 /* If hidden, show it */
990 else if( isMinimized() )
998 /* Visible (possibly under other windows) */
1000 /* check if any visible window is above vlc in the z-order,
1001 * but ignore the ones always on top
1002 * and the ones which can't be activated */
1005 wi.cbSize = sizeof( WINDOWINFO );
1006 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1007 hwnd && ( !IsWindowVisible( hwnd ) ||
1008 ( GetWindowInfo( hwnd, &wi ) &&
1009 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1010 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1011 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1012 (wi.dwExStyle&WS_EX_TOPMOST) )
1024 QVLCMenu::updateSystrayMenu( this, p_intf );
1027 void MainInterface::showUpdateSystrayMenu()
1035 QVLCMenu::updateSystrayMenu( this, p_intf );
1038 void MainInterface::hideUpdateSystrayMenu()
1041 QVLCMenu::updateSystrayMenu( this, p_intf );
1044 void MainInterface::handleSystrayClick(
1045 QSystemTrayIcon::ActivationReason reason )
1049 case QSystemTrayIcon::Trigger:
1050 case QSystemTrayIcon::DoubleClick:
1052 QVLCMenu::updateSystrayMenu( this, p_intf );
1054 toggleUpdateSystrayMenu();
1057 case QSystemTrayIcon::MiddleClick:
1058 sysTray->showMessage( qtr( "VLC media player" ),
1059 qtr( "Control menu for the player" ),
1060 QSystemTrayIcon::Information, 3000 );
1068 * Updates the name of the systray Icon tooltip.
1069 * Doesn't check if the systray exists, check before you call it.
1071 void MainInterface::updateSystrayTooltipName( const QString& name )
1073 if( name.isEmpty() )
1075 sysTray->setToolTip( qtr( "VLC media player" ) );
1079 sysTray->setToolTip( name );
1080 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1082 sysTray->showMessage( qtr( "VLC media player" ), name,
1083 QSystemTrayIcon::NoIcon, 3000 );
1087 QVLCMenu::updateSystrayMenu( this, p_intf );
1091 * Updates the status of the systray Icon tooltip.
1092 * Doesn't check if the systray exists, check before you call it.
1094 void MainInterface::updateSystrayTooltipStatus( int i_status )
1099 sysTray->setToolTip( input_name );
1102 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1105 sysTray->setToolTip( qtr( "VLC media player" ) );
1108 QVLCMenu::updateSystrayMenu( this, p_intf );
1112 void MainInterface::changeEvent(QEvent *event)
1114 if( event->type() == QEvent::WindowStateChange )
1116 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1117 Qt::WindowStates newState = windowState();
1118 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1120 if( newState & Qt::WindowMinimized )
1122 b_hasPausedWhenMinimized = false;
1124 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1125 THEMIM->getIM()->hasVideo() &&
1126 !THEMIM->getIM()->hasVisualisation() &&
1127 var_InheritBool( p_intf, "qt-pause-minimized" ) )
1129 b_hasPausedWhenMinimized = true;
1133 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1135 if( b_hasPausedWhenMinimized )
1142 QWidget::changeEvent(event);
1145 /************************************************************************
1147 ************************************************************************/
1148 void MainInterface::dropEvent(QDropEvent *event)
1150 dropEventPlay( event, true );
1153 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1155 if( event->possibleActions() & Qt::CopyAction )
1156 event->setDropAction( Qt::CopyAction );
1160 const QMimeData *mimeData = event->mimeData();
1162 /* D&D of a subtitles file, add it on the fly */
1163 if( mimeData->urls().size() == 1 && THEMIM->getIM()->hasInput() )
1165 if( !input_AddSubtitle( THEMIM->getInput(),
1166 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1174 bool first = b_play;
1175 foreach( const QUrl &url, mimeData->urls() )
1179 QString mrl = toURI( url.toEncoded().constData() );
1180 playlist_Add( THEPL, qtu(mrl), NULL,
1181 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1182 PLAYLIST_END, true, pl_Unlocked );
1184 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1188 /* Browsers give content as text if you dnd the addressbar,
1189 so check if mimedata has valid url in text and use it
1190 if we didn't get any normal Urls()*/
1191 if( !mimeData->hasUrls() && mimeData->hasText() &&
1192 QUrl(mimeData->text()).isValid() )
1194 QString mrl = toURI( mimeData->text() );
1195 playlist_Add( THEPL, qtu(mrl), NULL,
1196 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1197 PLAYLIST_END, true, pl_Unlocked );
1201 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1203 event->acceptProposedAction();
1205 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1207 event->acceptProposedAction();
1209 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1214 /************************************************************************
1216 ************************************************************************/
1217 void MainInterface::keyPressEvent( QKeyEvent *e )
1219 handleKeyPress( e );
1222 void MainInterface::handleKeyPress( QKeyEvent *e )
1224 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1226 toggleMinimalView( !b_minimalView );
1230 int i_vlck = qtEventToVLCKey( e );
1233 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1240 void MainInterface::wheelEvent( QWheelEvent *e )
1242 int i_vlckey = qtWheelEventToVLCKey( e );
1243 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1247 void MainInterface::closeEvent( QCloseEvent *e )
1249 e->ignore(); /* Do not quit */
1251 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1254 void MainInterface::setInterfaceFullScreen( bool fs )
1257 setWindowState( windowState() | Qt::WindowFullScreen );
1259 setWindowState( windowState() & ~Qt::WindowFullScreen );
1261 void MainInterface::toggleInterfaceFullScreen()
1263 b_interfaceFullScreen = !b_interfaceFullScreen;
1264 if( !b_videoFullScreen )
1265 setInterfaceFullScreen( b_interfaceFullScreen );
1266 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1269 /*****************************************************************************
1270 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1271 * We don't show the menu directly here because we don't want the
1272 * caller to block for a too long time.
1273 *****************************************************************************/
1274 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1275 vlc_value_t old_val, vlc_value_t new_val, void *param )
1277 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1279 intf_thread_t *p_intf = (intf_thread_t *)param;
1281 if( p_intf->pf_show_dialog )
1283 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1284 new_val.b_bool, NULL );
1290 /*****************************************************************************
1291 * IntfShowCB: callback triggered by the intf-show libvlc variable.
1292 *****************************************************************************/
1293 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1294 vlc_value_t old_val, vlc_value_t new_val, void *param )
1296 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1297 VLC_UNUSED( new_val );
1299 intf_thread_t *p_intf = (intf_thread_t *)param;
1300 p_intf->p_sys->p_mi->toggleFSC();