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 statusBar()->setVisible( getSettings()->value( "status-bar-visible", false ).toBool() );
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 );
154 /*********************************
155 * Create the Systray Management *
156 *********************************/
159 /********************
161 ********************/
162 MainInputManager::getInstance( p_intf );
167 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
170 /************************************************************
171 * Connect the input manager to the GUI elements it manages *
172 ************************************************************/
174 * Connects on nameChanged()
175 * Those connects are different because options can impeach them to trigger.
177 /* Main Interface statusbar */
178 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
179 this, setName( const QString& ) );
184 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
185 this, updateSystrayTooltipName( 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& ) );
196 * CONNECTS on PLAY_STATUS
198 /* Status on the systray */
202 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
203 this, updateSystrayTooltipStatus( int ) );
207 /* END CONNECTS ON IM */
209 /* VideoWidget connects for asynchronous calls */
210 b_videoFullScreen = false;
211 b_videoOnTop = false;
212 connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
213 this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
214 Qt::BlockingQueuedConnection );
215 connect( this, SIGNAL(askReleaseVideo( void )),
216 this, SLOT(releaseVideoSlot( void )),
217 Qt::BlockingQueuedConnection );
218 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
224 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
225 this, setVideoSize( unsigned int, unsigned int ) );
226 CONNECT( videoWidget, sizeChanged( int, int ),
227 this, resizeStack( int, int ) );
229 CONNECT( this, askVideoSetFullScreen( bool ),
230 this, setVideoFullScreen( bool ) );
233 CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
235 CONNECT( this, askToQuit(), THEDP, quit() );
237 /** END of CONNECTS**/
243 var_AddCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
245 /* Register callback for the intf-popupmenu variable */
246 var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
249 int i_plVis = settings->value( "MainWindow/playlist-visible", false ).toBool();
251 if( i_plVis ) togglePlaylist();
253 /**** FINAL SIZING and placement of interface */
254 settings->beginGroup( "MainWindow" );
255 QVLCTools::restoreWidgetPosition( settings, this, QSize(400, 100) );
256 settings->endGroup();
258 b_interfaceFullScreen = isFullScreen();
260 /* Final sizing and showing */
261 setVisible( !b_hideAfterCreation );
263 computeMinimumSize();
265 /* Switch to minimal view if needed, must be called after the show() */
267 toggleMinimalView( true );
269 b_hasPausedWhenMinimized = false;
272 MainInterface::~MainInterface()
274 /* Unsure we hide the videoWidget before destroying it */
275 if( stackCentralOldWidget == videoWidget )
283 ImageList_Destroy( himl );
285 p_taskbl->vt->Release(p_taskbl);
289 /* Be sure to kill the actionsManager... Only used in the MI and control */
290 ActionsManager::killInstance();
293 ExtensionsManager::killInstance();
295 /* Delete the FSC controller */
296 delete fullscreenControls;
299 settings->beginGroup( "MainWindow" );
301 settings->setValue( "pl-dock-status", b_plDocked );
302 /* Save playlist state */
304 settings->setValue( "playlist-visible", playlistVisible );
306 settings->setValue( "adv-controls",
307 getControlsVisibilityStatus() & CONTROLS_ADVANCED );
308 settings->setValue( "status-bar-visible", statusBar()->isVisible() );
310 /* Save the stackCentralW sizes */
311 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
312 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
315 QVLCTools::saveWidgetPosition(settings, this);
317 settings->endGroup();
319 /* Save undocked playlist size */
320 if( playlistWidget && !isPlDocked() )
321 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
323 delete playlistWidget;
327 /* Unregister callbacks */
328 var_DelCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
329 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
331 p_intf->p_sys->p_mi = NULL;
334 void MainInterface::computeMinimumSize()
337 if( menuBar()->isVisible() )
338 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
340 setMinimumWidth( minWidth );
343 /*****************************
345 *****************************/
346 void MainInterface::recreateToolbars()
348 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
350 settings->beginGroup( "MainWindow" );
354 controls = new ControlsWidget( p_intf, b_adv, this );
355 inputC = new InputControlsWidget( p_intf, this );
357 if( fullscreenControls )
359 delete fullscreenControls;
360 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
361 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
362 this, handleKeyPress( QKeyEvent * ) );
364 mainLayout->insertWidget( 2, inputC );
365 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
367 settings->endGroup();
370 void MainInterface::createMainWidget( QSettings *settings )
372 /* Create the main Widget and the mainLayout */
373 QWidget *main = new QWidget;
374 setCentralWidget( main );
375 mainLayout = new QVBoxLayout( main );
376 main->setContentsMargins( 0, 0, 0, 0 );
377 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
380 stackCentralW = new QVLCStackedWidget( main );
383 bgWidget = new BackgroundWidget( p_intf );
384 stackCentralW->addWidget( bgWidget );
385 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
386 bgWidget->setWithArt( false );
388 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
389 bgWidget->setExpandstoHeight( true );
391 /* And video Outputs */
392 if( b_videoEmbedded )
394 videoWidget = new VideoWidget( p_intf );
395 stackCentralW->addWidget( videoWidget );
397 mainLayout->insertWidget( 1, stackCentralW );
399 settings->beginGroup( "MainWindow" );
400 stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 400, 0 ) ).toSize();
401 /* Resize even if no-auto-resize, because we are at creation */
402 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
404 /* Create the CONTROLS Widget */
405 controls = new ControlsWidget( p_intf,
406 settings->value( "adv-controls", false ).toBool(), this );
407 inputC = new InputControlsWidget( p_intf, this );
409 mainLayout->insertWidget( 2, inputC );
410 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
413 /* Visualisation, disabled for now, they SUCK */
415 visualSelector = new VisualSelector( p_intf );
416 mainLayout->insertWidget( 0, visualSelector );
417 visualSelector->hide();
420 settings->endGroup();
422 /* Enable the popup menu in the MI */
423 main->setContextMenuPolicy( Qt::CustomContextMenu );
424 CONNECT( main, customContextMenuRequested( const QPoint& ),
425 this, popupMenu( const QPoint& ) );
427 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
428 /* Create the FULLSCREEN CONTROLS Widget */
429 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
431 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
432 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
433 this, handleKeyPress( QKeyEvent * ) );
437 inline void MainInterface::initSystray()
440 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
441 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
443 if( var_InheritBool( p_intf, "qt-start-minimized") )
445 if( b_systrayAvailable )
447 b_systrayWanted = true;
448 b_hideAfterCreation = true;
451 msg_Err( p_intf, "cannot start minimized without system tray bar" );
454 if( b_systrayAvailable && b_systrayWanted )
459 inline void MainInterface::createStatusBar()
464 /* Widgets Creation*/
465 QStatusBar *statusBarr = statusBar();
467 TimeLabel *timeLabel = new TimeLabel( p_intf );
468 nameLabel = new QLabel( this );
469 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
470 | Qt::TextSelectableByKeyboard );
471 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
473 /* Styling those labels */
474 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
475 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
476 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
477 timeLabel->setStyleSheet(
478 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
479 speedLabel->setStyleSheet(
480 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
481 /* pad both label and its tooltip */
482 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
484 /* and adding those */
485 statusBarr->addWidget( nameLabel, 8 );
486 statusBarr->addPermanentWidget( speedLabel, 0 );
487 statusBarr->addPermanentWidget( timeLabel, 0 );
489 /* timeLabel behaviour:
490 - double clicking opens the goto time dialog
491 - right-clicking and clicking just toggle between remaining and
493 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
495 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
496 this, showCryptedLabel( bool ) );
498 CONNECT( THEMIM->getIM(), seekRequested( float ),
499 timeLabel, setDisplayPosition( float ) );
501 /* This shouldn't be necessary, but for somehow reason, the statusBarr
502 starts at height of 20px and when a text is shown it needs more space.
503 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
504 geometry, we need to force a height. If you have a better idea, please
507 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
510 /**********************************************************************
511 * Handling of sizing of the components
512 **********************************************************************/
514 void MainInterface::debug()
517 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
518 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
519 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
521 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
522 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
523 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
527 inline void MainInterface::showVideo() { showTab( videoWidget ); }
528 inline void MainInterface::restoreStackOldWidget()
529 { showTab( stackCentralOldWidget ); }
531 inline void MainInterface::showTab( QWidget *widget )
534 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
537 stackCentralOldWidget = stackCentralW->currentWidget();
538 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
540 stackCentralW->setCurrentWidget( widget );
542 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
545 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
546 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
550 void MainInterface::destroyPopupMenu()
552 QVLCMenu::PopupMenu( p_intf, false );
555 void MainInterface::popupMenu( const QPoint &p )
557 QVLCMenu::PopupMenu( p_intf, true );
560 void MainInterface::toggleFSC()
562 if( !fullscreenControls ) return;
564 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type, 0 );
565 QApplication::postEvent( fullscreenControls, eShow );
568 /****************************************************************************
570 ****************************************************************************/
574 * You must not change the state of this object or other Qt4 UI objects,
575 * from the video output thread - only from the Qt4 UI main loop thread.
576 * All window provider queries must be handled through signals or events.
577 * That's why we have all those emit statements...
579 WId MainInterface::getVideo( int *pi_x, int *pi_y,
580 unsigned int *pi_width, unsigned int *pi_height )
585 /* This is a blocking call signal. Results are returned through pointers.
586 * Beware of deadlocks! */
588 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
592 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
593 unsigned *pi_width, unsigned *pi_height )
595 /* Request the videoWidget */
596 WId ret = videoWidget->request( pi_x, pi_y,
597 pi_width, pi_height, !b_autoresize );
599 if( ret ) /* The videoWidget is available */
601 /* Consider the video active now */
604 /* Ask videoWidget to resize correctly, if we are in normal mode */
605 if( !isFullScreen() && !isMaximized() && b_autoresize )
606 videoWidget->SetSizing( *pi_width, *pi_height );
610 /* Asynchronous call from the WindowClose function */
611 void MainInterface::releaseVideo( void )
613 emit askReleaseVideo();
616 /* Function that is CONNECTED to the previous emit */
617 void MainInterface::releaseVideoSlot( void )
619 /* This function is called when the embedded video window is destroyed,
620 * or in the rare case that the embedded window is still here but the
621 * Qt4 interface exits. */
622 assert( videoWidget );
623 videoWidget->release();
624 setVideoOnTop( false );
625 setVideoFullScreen( false );
627 if( stackCentralW->currentWidget() == videoWidget )
628 restoreStackOldWidget();
630 /* We don't want to have a blank video to popup */
631 stackCentralOldWidget = bgWidget;
634 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
636 if( !isFullScreen() && !isMaximized() )
637 videoWidget->SetSizing( w, h );
640 void MainInterface::setVideoFullScreen( bool fs )
642 b_videoFullScreen = fs;
645 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
646 /* if user hasn't defined screennumber, or screennumber that is bigger
647 * than current number of screens, take screennumber where current interface
650 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
651 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
653 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
655 /* To be sure window is on proper-screen in xinerama */
656 if( !screenres.contains( pos() ) )
658 msg_Dbg( p_intf, "Moving video to correct screen");
659 move( QPoint( screenres.x(), screenres.y() ) );
661 setMinimalView( true );
662 setInterfaceFullScreen( true );
666 /* TODO do we want to restore screen and position ? (when
667 * qt-fullscreen-screennumber is forced) */
668 setMinimalView( b_minimalView );
669 setInterfaceFullScreen( b_interfaceFullScreen );
674 /* Slot to change the video always-on-top flag.
675 * Emit askVideoOnTop() to invoke this from other thread. */
676 void MainInterface::setVideoOnTop( bool on_top )
678 b_videoOnTop = on_top;
680 Qt::WindowFlags oldflags = windowFlags(), newflags;
683 newflags = oldflags | Qt::WindowStaysOnTopHint;
685 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
687 if( newflags != oldflags )
689 setWindowFlags( newflags );
690 show(); /* necessary to apply window flags */
694 /* Asynchronous call from WindowControl function */
695 int MainInterface::controlVideo( int i_query, va_list args )
699 case VOUT_WINDOW_SET_SIZE:
701 unsigned int i_width = va_arg( args, unsigned int );
702 unsigned int i_height = va_arg( args, unsigned int );
704 emit askVideoToResize( i_width, i_height );
707 case VOUT_WINDOW_SET_STATE:
709 unsigned i_arg = va_arg( args, unsigned );
710 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
712 emit askVideoOnTop( on_top != 0 );
715 case VOUT_WINDOW_SET_FULLSCREEN:
717 bool b_fs = va_arg( args, int );
719 emit askVideoSetFullScreen( b_fs );
723 msg_Warn( p_intf, "unsupported control query" );
728 /*****************************************************************************
729 * Playlist, Visualisation and Menus handling
730 *****************************************************************************/
732 * Toggle the playlist widget or dialog
734 void MainInterface::createPlaylist()
736 playlistWidget = new PlaylistWidget( p_intf, this );
740 stackCentralW->addWidget( playlistWidget );
741 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 500, 250 ) ).toSize();
746 playlistWidget->setParent( NULL );
748 playlistWidget->setWindowFlags( Qt::Window );
750 /* This will restore the geometry but will not work for position,
751 because of parenting */
752 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
753 playlistWidget, QSize( 600, 300 ) );
757 void MainInterface::togglePlaylist()
759 if( !playlistWidget )
766 /* Playlist is not visible, show it */
767 if( stackCentralW->currentWidget() != playlistWidget )
769 showTab( playlistWidget );
773 restoreStackOldWidget();
775 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
780 playlistWidget->setParent( NULL );
782 playlistWidget->setWindowFlags( Qt::Window );
783 playlistVisible = !playlistVisible;
784 playlistWidget->setVisible( playlistVisible );
789 void MainInterface::dockPlaylist( bool p_docked )
791 if( b_plDocked == p_docked ) return;
792 b_plDocked = p_docked;
794 if( !playlistWidget ) return; /* Playlist wasn't created yet */
797 stackCentralW->removeWidget( playlistWidget );
799 playlistWidget->setParent( NULL );
801 playlistWidget->setWindowFlags( Qt::Window );
802 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
803 playlistWidget, QSize( 600, 300 ) );
804 playlistWidget->show();
805 restoreStackOldWidget();
809 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
810 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
811 // It would be logical that QStackWidget::addWidget reset the flags...
812 stackCentralW->addWidget( playlistWidget );
813 showTab( playlistWidget );
815 playlistVisible = true;
819 * setMinimalView is the private function used by
820 * the SLOT toggleMinimalView and setVideoFullScreen
822 void MainInterface::setMinimalView( bool b_minimal )
824 menuBar()->setVisible( !b_minimal );
825 controls->setVisible( !b_minimal );
826 statusBar()->setVisible( !b_minimal );
827 inputC->setVisible( !b_minimal );
831 * This public SLOT is used for moving to minimal View Mode
833 * If b_minimal is false, then we are normalView
835 void MainInterface::toggleMinimalView( bool b_minimal )
837 if( !b_minimalView && b_autoresize ) /* Normal mode */
839 if( stackCentralW->currentWidget() == bgWidget )
841 if( stackCentralW->height() < 16 )
843 resizeStack( stackCentralW->width(), 100 );
847 b_minimalView = b_minimal;
848 if( !b_videoFullScreen )
850 setMinimalView( b_minimalView );
851 computeMinimumSize();
854 emit minimalViewToggled( b_minimalView );
857 /* toggling advanced controls buttons */
858 void MainInterface::toggleAdvancedButtons()
860 controls->toggleAdvanced();
861 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
864 /* Get the visibility status of the controls (hidden or not, advanced or not) */
865 int MainInterface::getControlsVisibilityStatus()
867 if( !controls ) return 0;
868 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
869 + CONTROLS_ADVANCED * controls->b_advancedVisible );
872 void MainInterface::setStatusBarVisibility( bool b_visible )
874 statusBar()->setVisible( b_visible );
878 void MainInterface::visual()
880 if( !VISIBLE( visualSelector) )
882 visualSelector->show();
883 if( !THEMIM->getIM()->hasVideo() )
885 /* Show the background widget */
887 visualSelectorEnabled = true;
891 /* Stop any currently running visualization */
892 visualSelector->hide();
893 visualSelectorEnabled = false;
898 /************************************************************************
900 ************************************************************************/
901 void MainInterface::setName( const QString& name )
903 input_name = name; /* store it for the QSystray use */
904 /* Display it in the status bar, but also as a Tooltip in case it doesn't
906 nameLabel->setText( name );
907 nameLabel->setToolTip( name );
911 * Give the decorations of the Main Window a correct Name.
912 * If nothing is given, set it to VLC...
914 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
916 if( aTitle.isEmpty() )
918 setWindowTitle( qtr( "VLC media player" ) );
922 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
926 void MainInterface::showCryptedLabel( bool b_show )
928 if( cryptedLabel == NULL )
930 cryptedLabel = new QLabel;
931 // The lock icon is not the right one for DRM protection/scrambled.
932 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
933 cryptedLabel->setText( "DRM" );
934 statusBar()->addWidget( cryptedLabel );
937 cryptedLabel->setVisible( b_show );
940 void MainInterface::showBuffering( float f_cache )
942 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
943 statusBar()->showMessage( amount, 1000 );
946 /*****************************************************************************
947 * Systray Icon and Systray Menu
948 *****************************************************************************/
951 * Create a SystemTray icon and a menu that would go with it.
952 * Connects to a click handler on the icon.
954 void MainInterface::createSystray()
957 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
958 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
960 iconVLC = QIcon( ":/logo/vlc128.png" );
961 sysTray = new QSystemTrayIcon( iconVLC, this );
962 sysTray->setToolTip( qtr( "VLC media player" ));
964 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
965 systrayMenu->setIcon( iconVLC );
967 QVLCMenu::updateSystrayMenu( this, p_intf, true );
970 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
971 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
975 * Updates the Systray Icon's menu and toggle the main interface
977 void MainInterface::toggleUpdateSystrayMenu()
979 /* If hidden, show it */
985 else if( isMinimized() )
993 /* Visible (possibly under other windows) */
995 /* check if any visible window is above vlc in the z-order,
996 * but ignore the ones always on top
997 * and the ones which can't be activated */
1000 wi.cbSize = sizeof( WINDOWINFO );
1001 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1002 hwnd && ( !IsWindowVisible( hwnd ) ||
1003 ( GetWindowInfo( hwnd, &wi ) &&
1004 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1005 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1006 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1007 (wi.dwExStyle&WS_EX_TOPMOST) )
1019 QVLCMenu::updateSystrayMenu( this, p_intf );
1022 void MainInterface::showUpdateSystrayMenu()
1030 QVLCMenu::updateSystrayMenu( this, p_intf );
1033 void MainInterface::hideUpdateSystrayMenu()
1036 QVLCMenu::updateSystrayMenu( this, p_intf );
1039 void MainInterface::handleSystrayClick(
1040 QSystemTrayIcon::ActivationReason reason )
1044 case QSystemTrayIcon::Trigger:
1045 case QSystemTrayIcon::DoubleClick:
1047 QVLCMenu::updateSystrayMenu( this, p_intf );
1049 toggleUpdateSystrayMenu();
1052 case QSystemTrayIcon::MiddleClick:
1053 sysTray->showMessage( qtr( "VLC media player" ),
1054 qtr( "Control menu for the player" ),
1055 QSystemTrayIcon::Information, 3000 );
1063 * Updates the name of the systray Icon tooltip.
1064 * Doesn't check if the systray exists, check before you call it.
1066 void MainInterface::updateSystrayTooltipName( const QString& name )
1068 if( name.isEmpty() )
1070 sysTray->setToolTip( qtr( "VLC media player" ) );
1074 sysTray->setToolTip( name );
1075 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1077 sysTray->showMessage( qtr( "VLC media player" ), name,
1078 QSystemTrayIcon::NoIcon, 3000 );
1082 QVLCMenu::updateSystrayMenu( this, p_intf );
1086 * Updates the status of the systray Icon tooltip.
1087 * Doesn't check if the systray exists, check before you call it.
1089 void MainInterface::updateSystrayTooltipStatus( int i_status )
1094 sysTray->setToolTip( input_name );
1097 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1100 sysTray->setToolTip( qtr( "VLC media player" ) );
1103 QVLCMenu::updateSystrayMenu( this, p_intf );
1107 void MainInterface::changeEvent(QEvent *event)
1109 if( event->type() == QEvent::WindowStateChange )
1111 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1112 Qt::WindowStates newState = windowState();
1113 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1115 if( newState & Qt::WindowMinimized )
1117 b_hasPausedWhenMinimized = false;
1119 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1120 THEMIM->getIM()->hasVideo() &&
1121 !THEMIM->getIM()->hasVisualisation() &&
1122 var_InheritBool( p_intf, "qt-pause-minimized" ) )
1124 b_hasPausedWhenMinimized = true;
1128 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1130 if( b_hasPausedWhenMinimized )
1137 QWidget::changeEvent(event);
1140 /************************************************************************
1142 ************************************************************************/
1143 void MainInterface::dropEvent(QDropEvent *event)
1145 dropEventPlay( event, true );
1148 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1150 if( event->possibleActions() & Qt::CopyAction )
1151 event->setDropAction( Qt::CopyAction );
1155 const QMimeData *mimeData = event->mimeData();
1157 /* D&D of a subtitles file, add it on the fly */
1158 if( mimeData->urls().size() == 1 && THEMIM->getIM()->hasInput() )
1160 if( !input_AddSubtitle( THEMIM->getInput(),
1161 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1169 bool first = b_play;
1170 foreach( const QUrl &url, mimeData->urls() )
1174 QString mrl = toURI( url.toEncoded().constData() );
1175 playlist_Add( THEPL, qtu(mrl), NULL,
1176 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1177 PLAYLIST_END, true, pl_Unlocked );
1179 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1183 /* Browsers give content as text if you dnd the addressbar,
1184 so check if mimedata has valid url in text and use it
1185 if we didn't get any normal Urls()*/
1186 if( !mimeData->hasUrls() && mimeData->hasText() &&
1187 QUrl(mimeData->text()).isValid() )
1189 QString mrl = toURI( mimeData->text() );
1190 playlist_Add( THEPL, qtu(mrl), NULL,
1191 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1192 PLAYLIST_END, true, pl_Unlocked );
1196 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1198 event->acceptProposedAction();
1200 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1202 event->acceptProposedAction();
1204 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1209 /************************************************************************
1211 ************************************************************************/
1212 void MainInterface::keyPressEvent( QKeyEvent *e )
1214 handleKeyPress( e );
1217 void MainInterface::handleKeyPress( QKeyEvent *e )
1219 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1221 toggleMinimalView( !b_minimalView );
1225 int i_vlck = qtEventToVLCKey( e );
1228 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1235 void MainInterface::wheelEvent( QWheelEvent *e )
1237 int i_vlckey = qtWheelEventToVLCKey( e );
1238 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1242 void MainInterface::closeEvent( QCloseEvent *e )
1244 e->ignore(); /* Do not quit */
1246 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1249 void MainInterface::setInterfaceFullScreen( bool fs )
1252 setWindowState( windowState() | Qt::WindowFullScreen );
1254 setWindowState( windowState() & ~Qt::WindowFullScreen );
1256 void MainInterface::toggleInterfaceFullScreen()
1258 b_interfaceFullScreen = !b_interfaceFullScreen;
1259 if( !b_videoFullScreen )
1260 setInterfaceFullScreen( b_interfaceFullScreen );
1261 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1264 /*****************************************************************************
1265 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1266 * We don't show the menu directly here because we don't want the
1267 * caller to block for a too long time.
1268 *****************************************************************************/
1269 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1270 vlc_value_t old_val, vlc_value_t new_val, void *param )
1272 intf_thread_t *p_intf = (intf_thread_t *)param;
1274 if( p_intf->pf_show_dialog )
1276 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1277 new_val.b_bool, NULL );
1283 /*****************************************************************************
1284 * IntfShowCB: callback triggered by the intf-show libvlc variable.
1285 *****************************************************************************/
1286 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1287 vlc_value_t old_val, vlc_value_t new_val, void *param )
1289 intf_thread_t *p_intf = (intf_thread_t *)param;
1290 p_intf->p_sys->p_mi->toggleFSC();