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;
93 FirstRun::CheckAndRun( this, p_intf );
96 * Configuration and settings
97 * Pre-building of interface
100 setFocusPolicy( Qt::StrongFocus );
101 setAcceptDrops( true );
102 setWindowRole( "vlc-main" );
103 setWindowIcon( QApplication::windowIcon() );
104 setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
106 setAttribute( Qt::WA_MacBrushedMetal );
109 /* Is video in embedded in the UI or not */
110 b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
112 /* Does the interface resize to video size or the opposite */
113 b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
115 /* Are we in the enhanced always-video mode or not ? */
116 b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
118 /* Do we want anoying popups or not */
119 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
121 /* Set the other interface settings */
122 settings = getSettings();
123 settings->beginGroup( "MainWindow" );
127 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
131 b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
133 settings->endGroup( );
139 b_statusbarVisible = getSettings()->value( "status-bar-visible", false ).toBool();
140 statusBar()->setVisible( b_statusbarVisible );
142 /**************************
143 * UI and Widgets design
144 **************************/
145 setVLCWindowsTitle();
150 QVLCMenu::createMenuBar( this, p_intf );
151 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
152 this, destroyPopupMenu() );
154 createMainWidget( settings );
155 /*********************************
156 * Create the Systray Management *
157 *********************************/
160 /********************
162 ********************/
163 MainInputManager::getInstance( p_intf );
168 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
171 /************************************************************
172 * Connect the input manager to the GUI elements it manages *
173 ************************************************************/
175 * Connects on nameChanged()
176 * Those connects are different because options can impeach them to trigger.
178 /* Main Interface statusbar */
179 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
180 this, setName( const QString& ) );
185 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
186 this, updateSystrayTooltipName( const QString& ) );
189 /* and title of the Main Interface*/
190 if( var_InheritBool( p_intf, "qt-name-in-title" ) )
192 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
193 this, setVLCWindowsTitle( const QString& ) );
197 * CONNECTS on PLAY_STATUS
199 /* Status on the systray */
203 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
204 this, updateSystrayTooltipStatus( int ) );
208 /* END CONNECTS ON IM */
210 /* VideoWidget connects for asynchronous calls */
211 b_videoFullScreen = false;
212 b_videoOnTop = 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(400, 100) );
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( 400, 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 &p )
558 QVLCMenu::PopupMenu( p_intf, true );
561 void MainInterface::toggleFSC()
563 if( !fullscreenControls ) return;
565 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type, 0 );
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 /* Request the videoWidget */
597 WId ret = videoWidget->request( pi_x, pi_y,
598 pi_width, pi_height, !b_autoresize );
600 if( ret ) /* The videoWidget is available */
602 /* Consider the video active now */
605 /* Ask videoWidget to resize correctly, if we are in normal mode */
606 if( !isFullScreen() && !isMaximized() && b_autoresize )
607 videoWidget->SetSizing( *pi_width, *pi_height );
611 /* Asynchronous call from the WindowClose function */
612 void MainInterface::releaseVideo( void )
614 emit askReleaseVideo();
617 /* Function that is CONNECTED to the previous emit */
618 void MainInterface::releaseVideoSlot( void )
620 /* This function is called when the embedded video window is destroyed,
621 * or in the rare case that the embedded window is still here but the
622 * Qt4 interface exits. */
623 assert( videoWidget );
624 videoWidget->release();
625 setVideoOnTop( false );
626 setVideoFullScreen( false );
628 if( stackCentralW->currentWidget() == videoWidget )
629 restoreStackOldWidget();
631 /* We don't want to have a blank video to popup */
632 stackCentralOldWidget = bgWidget;
635 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
637 if( !isFullScreen() && !isMaximized() )
638 videoWidget->SetSizing( w, h );
641 void MainInterface::setVideoFullScreen( bool fs )
643 b_videoFullScreen = fs;
646 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
647 /* if user hasn't defined screennumber, or screennumber that is bigger
648 * than current number of screens, take screennumber where current interface
651 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
652 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
654 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
656 /* To be sure window is on proper-screen in xinerama */
657 if( !screenres.contains( pos() ) )
659 msg_Dbg( p_intf, "Moving video to correct screen");
660 move( QPoint( screenres.x(), screenres.y() ) );
662 setMinimalView( true );
663 setInterfaceFullScreen( true );
667 /* TODO do we want to restore screen and position ? (when
668 * qt-fullscreen-screennumber is forced) */
669 setMinimalView( b_minimalView );
670 setInterfaceFullScreen( b_interfaceFullScreen );
675 /* Slot to change the video always-on-top flag.
676 * Emit askVideoOnTop() to invoke this from other thread. */
677 void MainInterface::setVideoOnTop( bool on_top )
679 b_videoOnTop = on_top;
681 Qt::WindowFlags oldflags = windowFlags(), newflags;
684 newflags = oldflags | Qt::WindowStaysOnTopHint;
686 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
688 if( newflags != oldflags )
690 setWindowFlags( newflags );
691 show(); /* necessary to apply window flags */
695 /* Asynchronous call from WindowControl function */
696 int MainInterface::controlVideo( int i_query, va_list args )
700 case VOUT_WINDOW_SET_SIZE:
702 unsigned int i_width = va_arg( args, unsigned int );
703 unsigned int i_height = va_arg( args, unsigned int );
705 emit askVideoToResize( i_width, i_height );
708 case VOUT_WINDOW_SET_STATE:
710 unsigned i_arg = va_arg( args, unsigned );
711 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
713 emit askVideoOnTop( on_top != 0 );
716 case VOUT_WINDOW_SET_FULLSCREEN:
718 bool b_fs = va_arg( args, int );
720 emit askVideoSetFullScreen( b_fs );
724 msg_Warn( p_intf, "unsupported control query" );
729 /*****************************************************************************
730 * Playlist, Visualisation and Menus handling
731 *****************************************************************************/
733 * Toggle the playlist widget or dialog
735 void MainInterface::createPlaylist()
737 playlistWidget = new PlaylistWidget( p_intf, this );
741 stackCentralW->addWidget( playlistWidget );
742 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 500, 250 ) ).toSize();
747 playlistWidget->setParent( NULL );
749 playlistWidget->setWindowFlags( Qt::Window );
751 /* This will restore the geometry but will not work for position,
752 because of parenting */
753 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
754 playlistWidget, QSize( 600, 300 ) );
758 void MainInterface::togglePlaylist()
760 if( !playlistWidget )
767 /* Playlist is not visible, show it */
768 if( stackCentralW->currentWidget() != playlistWidget )
770 showTab( playlistWidget );
774 restoreStackOldWidget();
776 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
781 playlistWidget->setParent( NULL );
783 playlistWidget->setWindowFlags( Qt::Window );
784 playlistVisible = !playlistVisible;
785 playlistWidget->setVisible( playlistVisible );
790 void MainInterface::dockPlaylist( bool p_docked )
792 if( b_plDocked == p_docked ) return;
793 b_plDocked = p_docked;
795 if( !playlistWidget ) return; /* Playlist wasn't created yet */
798 stackCentralW->removeWidget( playlistWidget );
800 playlistWidget->setParent( NULL );
802 playlistWidget->setWindowFlags( Qt::Window );
803 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
804 playlistWidget, QSize( 600, 300 ) );
805 playlistWidget->show();
806 restoreStackOldWidget();
810 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
811 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
812 // It would be logical that QStackWidget::addWidget reset the flags...
813 stackCentralW->addWidget( playlistWidget );
814 showTab( playlistWidget );
816 playlistVisible = true;
820 * setMinimalView is the private function used by
821 * the SLOT toggleMinimalView and setVideoFullScreen
823 void MainInterface::setMinimalView( bool b_minimal )
825 menuBar()->setVisible( !b_minimal );
826 controls->setVisible( !b_minimal );
827 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
828 inputC->setVisible( !b_minimal );
832 * This public SLOT is used for moving to minimal View Mode
834 * If b_minimal is false, then we are normalView
836 void MainInterface::toggleMinimalView( bool b_minimal )
838 if( !b_minimalView && b_autoresize ) /* Normal mode */
840 if( stackCentralW->currentWidget() == bgWidget )
842 if( stackCentralW->height() < 16 )
844 resizeStack( stackCentralW->width(), 100 );
848 b_minimalView = b_minimal;
849 if( !b_videoFullScreen )
851 setMinimalView( b_minimalView );
852 computeMinimumSize();
855 emit minimalViewToggled( b_minimalView );
858 /* toggling advanced controls buttons */
859 void MainInterface::toggleAdvancedButtons()
861 controls->toggleAdvanced();
862 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
865 /* Get the visibility status of the controls (hidden or not, advanced or not) */
866 int MainInterface::getControlsVisibilityStatus()
868 if( !controls ) return 0;
869 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
870 + CONTROLS_ADVANCED * controls->b_advancedVisible );
873 void MainInterface::setStatusBarVisibility( bool b_visible )
875 statusBar()->setVisible( b_visible );
876 b_statusbarVisible = b_visible;
880 void MainInterface::visual()
882 if( !VISIBLE( visualSelector) )
884 visualSelector->show();
885 if( !THEMIM->getIM()->hasVideo() )
887 /* Show the background widget */
889 visualSelectorEnabled = true;
893 /* Stop any currently running visualization */
894 visualSelector->hide();
895 visualSelectorEnabled = false;
900 /************************************************************************
902 ************************************************************************/
903 void MainInterface::setName( const QString& name )
905 input_name = name; /* store it for the QSystray use */
906 /* Display it in the status bar, but also as a Tooltip in case it doesn't
908 nameLabel->setText( name );
909 nameLabel->setToolTip( name );
913 * Give the decorations of the Main Window a correct Name.
914 * If nothing is given, set it to VLC...
916 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
918 if( aTitle.isEmpty() )
920 setWindowTitle( qtr( "VLC media player" ) );
924 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
928 void MainInterface::showCryptedLabel( bool b_show )
930 if( cryptedLabel == NULL )
932 cryptedLabel = new QLabel;
933 // The lock icon is not the right one for DRM protection/scrambled.
934 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
935 cryptedLabel->setText( "DRM" );
936 statusBar()->addWidget( cryptedLabel );
939 cryptedLabel->setVisible( b_show );
942 void MainInterface::showBuffering( float f_cache )
944 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
945 statusBar()->showMessage( amount, 1000 );
948 /*****************************************************************************
949 * Systray Icon and Systray Menu
950 *****************************************************************************/
953 * Create a SystemTray icon and a menu that would go with it.
954 * Connects to a click handler on the icon.
956 void MainInterface::createSystray()
959 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
960 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
962 iconVLC = QIcon( ":/logo/vlc128.png" );
963 sysTray = new QSystemTrayIcon( iconVLC, this );
964 sysTray->setToolTip( qtr( "VLC media player" ));
966 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
967 systrayMenu->setIcon( iconVLC );
969 QVLCMenu::updateSystrayMenu( this, p_intf, true );
972 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
973 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
977 * Updates the Systray Icon's menu and toggle the main interface
979 void MainInterface::toggleUpdateSystrayMenu()
981 /* If hidden, show it */
987 else if( isMinimized() )
995 /* Visible (possibly under other windows) */
997 /* check if any visible window is above vlc in the z-order,
998 * but ignore the ones always on top
999 * and the ones which can't be activated */
1002 wi.cbSize = sizeof( WINDOWINFO );
1003 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1004 hwnd && ( !IsWindowVisible( hwnd ) ||
1005 ( GetWindowInfo( hwnd, &wi ) &&
1006 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1007 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1008 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1009 (wi.dwExStyle&WS_EX_TOPMOST) )
1021 QVLCMenu::updateSystrayMenu( this, p_intf );
1024 void MainInterface::showUpdateSystrayMenu()
1032 QVLCMenu::updateSystrayMenu( this, p_intf );
1035 void MainInterface::hideUpdateSystrayMenu()
1038 QVLCMenu::updateSystrayMenu( this, p_intf );
1041 void MainInterface::handleSystrayClick(
1042 QSystemTrayIcon::ActivationReason reason )
1046 case QSystemTrayIcon::Trigger:
1047 case QSystemTrayIcon::DoubleClick:
1049 QVLCMenu::updateSystrayMenu( this, p_intf );
1051 toggleUpdateSystrayMenu();
1054 case QSystemTrayIcon::MiddleClick:
1055 sysTray->showMessage( qtr( "VLC media player" ),
1056 qtr( "Control menu for the player" ),
1057 QSystemTrayIcon::Information, 3000 );
1065 * Updates the name of the systray Icon tooltip.
1066 * Doesn't check if the systray exists, check before you call it.
1068 void MainInterface::updateSystrayTooltipName( const QString& name )
1070 if( name.isEmpty() )
1072 sysTray->setToolTip( qtr( "VLC media player" ) );
1076 sysTray->setToolTip( name );
1077 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1079 sysTray->showMessage( qtr( "VLC media player" ), name,
1080 QSystemTrayIcon::NoIcon, 3000 );
1084 QVLCMenu::updateSystrayMenu( this, p_intf );
1088 * Updates the status of the systray Icon tooltip.
1089 * Doesn't check if the systray exists, check before you call it.
1091 void MainInterface::updateSystrayTooltipStatus( int i_status )
1096 sysTray->setToolTip( input_name );
1099 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1102 sysTray->setToolTip( qtr( "VLC media player" ) );
1105 QVLCMenu::updateSystrayMenu( this, p_intf );
1109 void MainInterface::changeEvent(QEvent *event)
1111 if( event->type() == QEvent::WindowStateChange )
1113 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1114 Qt::WindowStates newState = windowState();
1115 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1117 if( newState & Qt::WindowMinimized )
1119 b_hasPausedWhenMinimized = false;
1121 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1122 THEMIM->getIM()->hasVideo() &&
1123 !THEMIM->getIM()->hasVisualisation() &&
1124 var_InheritBool( p_intf, "qt-pause-minimized" ) )
1126 b_hasPausedWhenMinimized = true;
1130 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1132 if( b_hasPausedWhenMinimized )
1139 QWidget::changeEvent(event);
1142 /************************************************************************
1144 ************************************************************************/
1145 void MainInterface::dropEvent(QDropEvent *event)
1147 dropEventPlay( event, true );
1150 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1152 if( event->possibleActions() & Qt::CopyAction )
1153 event->setDropAction( Qt::CopyAction );
1157 const QMimeData *mimeData = event->mimeData();
1159 /* D&D of a subtitles file, add it on the fly */
1160 if( mimeData->urls().size() == 1 && THEMIM->getIM()->hasInput() )
1162 if( !input_AddSubtitle( THEMIM->getInput(),
1163 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1171 bool first = b_play;
1172 foreach( const QUrl &url, mimeData->urls() )
1176 QString mrl = toURI( url.toEncoded().constData() );
1177 playlist_Add( THEPL, qtu(mrl), NULL,
1178 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1179 PLAYLIST_END, true, pl_Unlocked );
1181 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1185 /* Browsers give content as text if you dnd the addressbar,
1186 so check if mimedata has valid url in text and use it
1187 if we didn't get any normal Urls()*/
1188 if( !mimeData->hasUrls() && mimeData->hasText() &&
1189 QUrl(mimeData->text()).isValid() )
1191 QString mrl = toURI( mimeData->text() );
1192 playlist_Add( THEPL, qtu(mrl), NULL,
1193 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1194 PLAYLIST_END, true, pl_Unlocked );
1198 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1200 event->acceptProposedAction();
1202 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1204 event->acceptProposedAction();
1206 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1211 /************************************************************************
1213 ************************************************************************/
1214 void MainInterface::keyPressEvent( QKeyEvent *e )
1216 handleKeyPress( e );
1219 void MainInterface::handleKeyPress( QKeyEvent *e )
1221 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1223 toggleMinimalView( !b_minimalView );
1227 int i_vlck = qtEventToVLCKey( e );
1230 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1237 void MainInterface::wheelEvent( QWheelEvent *e )
1239 int i_vlckey = qtWheelEventToVLCKey( e );
1240 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1244 void MainInterface::closeEvent( QCloseEvent *e )
1246 e->ignore(); /* Do not quit */
1248 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1251 void MainInterface::setInterfaceFullScreen( bool fs )
1254 setWindowState( windowState() | Qt::WindowFullScreen );
1256 setWindowState( windowState() & ~Qt::WindowFullScreen );
1258 void MainInterface::toggleInterfaceFullScreen()
1260 b_interfaceFullScreen = !b_interfaceFullScreen;
1261 if( !b_videoFullScreen )
1262 setInterfaceFullScreen( b_interfaceFullScreen );
1263 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1266 /*****************************************************************************
1267 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1268 * We don't show the menu directly here because we don't want the
1269 * caller to block for a too long time.
1270 *****************************************************************************/
1271 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1272 vlc_value_t old_val, vlc_value_t new_val, void *param )
1274 intf_thread_t *p_intf = (intf_thread_t *)param;
1276 if( p_intf->pf_show_dialog )
1278 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1279 new_val.b_bool, NULL );
1285 /*****************************************************************************
1286 * IntfShowCB: callback triggered by the intf-show libvlc variable.
1287 *****************************************************************************/
1288 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1289 vlc_value_t old_val, vlc_value_t new_val, void *param )
1291 intf_thread_t *p_intf = (intf_thread_t *)param;
1292 p_intf->p_sys->p_mi->toggleFSC();