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" );
126 b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
128 settings->endGroup( );
135 /**************************
136 * UI and Widgets design
137 **************************/
138 setVLCWindowsTitle();
143 QVLCMenu::createMenuBar( this, p_intf );
144 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
145 this, destroyPopupMenu() );
147 createMainWidget( settings );
148 /*********************************
149 * Create the Systray Management *
150 *********************************/
153 /********************
155 ********************/
156 MainInputManager::getInstance( p_intf );
161 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
164 /************************************************************
165 * Connect the input manager to the GUI elements it manages *
166 ************************************************************/
168 * Connects on nameChanged()
169 * Those connects are different because options can impeach them to trigger.
171 /* Main Interface statusbar */
172 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
173 this, setName( const QString& ) );
178 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
179 this, updateSystrayTooltipName( const QString& ) );
182 /* and title of the Main Interface*/
183 if( var_InheritBool( p_intf, "qt-name-in-title" ) )
185 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
186 this, setVLCWindowsTitle( const QString& ) );
190 * CONNECTS on PLAY_STATUS
192 /* Status on the systray */
196 CONNECT( THEMIM->getIM(), statusChanged( int ),
197 this, updateSystrayTooltipStatus( int ) );
201 /* END CONNECTS ON IM */
203 /* VideoWidget connects for asynchronous calls */
204 b_videoFullScreen = false;
205 b_videoOnTop = false;
206 connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
207 this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
208 Qt::BlockingQueuedConnection );
209 connect( this, SIGNAL(askReleaseVideo( void )),
210 this, SLOT(releaseVideoSlot( void )),
211 Qt::BlockingQueuedConnection );
212 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
218 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
219 this, setVideoSize( unsigned int, unsigned int ) );
220 CONNECT( videoWidget, sizeChanged( int, int ),
221 this, resizeStack( int, int ) );
223 CONNECT( this, askVideoSetFullScreen( bool ),
224 this, setVideoFullScreen( bool ) );
227 CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
229 CONNECT( this, askToQuit(), THEDP, quit() );
231 /** END of CONNECTS**/
237 var_AddCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
239 /* Register callback for the intf-popupmenu variable */
240 var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
243 int i_plVis = settings->value( "MainWindow/playlist-visible", false ).toBool();
245 if( i_plVis ) togglePlaylist();
247 /**** FINAL SIZING and placement of interface */
248 settings->beginGroup( "MainWindow" );
249 QVLCTools::restoreWidgetPosition( settings, this, QSize(400, 100) );
250 settings->endGroup();
252 b_interfaceFullScreen = isFullScreen();
254 /* Final sizing and showing */
255 setVisible( !b_hideAfterCreation );
257 computeMinimumSize();
259 /* Switch to minimal view if needed, must be called after the show() */
261 toggleMinimalView( true );
264 MainInterface::~MainInterface()
266 /* Unsure we hide the videoWidget before destroying it */
267 if( stackCentralOldWidget == videoWidget )
275 ImageList_Destroy( himl );
277 p_taskbl->vt->Release(p_taskbl);
281 /* Be sure to kill the actionsManager... Only used in the MI and control */
282 ActionsManager::killInstance();
285 ExtensionsManager::killInstance();
287 /* Delete the FSC controller */
288 delete fullscreenControls;
291 settings->beginGroup( "MainWindow" );
293 settings->setValue( "pl-dock-status", b_plDocked );
294 /* Save playlist state */
296 settings->setValue( "playlist-visible", playlistVisible );
298 settings->setValue( "adv-controls",
299 getControlsVisibilityStatus() & CONTROLS_ADVANCED );
301 /* Save the stackCentralW sizes */
302 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
303 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
306 QVLCTools::saveWidgetPosition(settings, this);
308 settings->endGroup();
310 /* Save undocked playlist size */
311 if( playlistWidget && !isPlDocked() )
312 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
314 delete playlistWidget;
318 /* Unregister callbacks */
319 var_DelCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
320 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
322 p_intf->p_sys->p_mi = NULL;
325 void MainInterface::computeMinimumSize()
328 if( menuBar()->isVisible() )
329 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
331 setMinimumWidth( minWidth );
334 /*****************************
336 *****************************/
337 void MainInterface::recreateToolbars()
339 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
341 settings->beginGroup( "MainWindow" );
345 controls = new ControlsWidget( p_intf, b_adv, this );
346 inputC = new InputControlsWidget( p_intf, this );
348 if( fullscreenControls )
350 delete fullscreenControls;
351 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
352 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
353 this, handleKeyPress( QKeyEvent * ) );
355 mainLayout->insertWidget( 2, inputC );
356 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
358 settings->endGroup();
361 void MainInterface::createMainWidget( QSettings *settings )
363 /* Create the main Widget and the mainLayout */
364 QWidget *main = new QWidget;
365 setCentralWidget( main );
366 mainLayout = new QVBoxLayout( main );
367 main->setContentsMargins( 0, 0, 0, 0 );
368 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
371 stackCentralW = new QVLCStackedWidget( main );
374 bgWidget = new BackgroundWidget( p_intf );
375 stackCentralW->addWidget( bgWidget );
376 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
377 bgWidget->setWithArt( false );
379 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
380 bgWidget->setExpandstoHeight( true );
382 /* And video Outputs */
383 if( b_videoEmbedded )
385 videoWidget = new VideoWidget( p_intf );
386 stackCentralW->addWidget( videoWidget );
388 mainLayout->insertWidget( 1, stackCentralW );
390 settings->beginGroup( "MainWindow" );
391 stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 400, 0 ) ).toSize();
392 /* Resize even if no-auto-resize, because we are at creation */
393 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
395 /* Create the CONTROLS Widget */
396 controls = new ControlsWidget( p_intf,
397 settings->value( "adv-controls", false ).toBool(), this );
398 inputC = new InputControlsWidget( p_intf, this );
400 mainLayout->insertWidget( 2, inputC );
401 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
404 /* Visualisation, disabled for now, they SUCK */
406 visualSelector = new VisualSelector( p_intf );
407 mainLayout->insertWidget( 0, visualSelector );
408 visualSelector->hide();
411 settings->endGroup();
413 /* Enable the popup menu in the MI */
414 main->setContextMenuPolicy( Qt::CustomContextMenu );
415 CONNECT( main, customContextMenuRequested( const QPoint& ),
416 this, popupMenu( const QPoint& ) );
418 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
419 /* Create the FULLSCREEN CONTROLS Widget */
420 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
422 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
423 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
424 this, handleKeyPress( QKeyEvent * ) );
428 inline void MainInterface::initSystray()
431 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
432 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
434 if( var_InheritBool( p_intf, "qt-start-minimized") )
436 if( b_systrayAvailable )
438 b_systrayWanted = true;
439 b_hideAfterCreation = true;
442 msg_Err( p_intf, "cannot start minimized without system tray bar" );
445 if( b_systrayAvailable && b_systrayWanted )
450 inline void MainInterface::createStatusBar()
455 /* Widgets Creation*/
456 QStatusBar *statusBarr = statusBar();
458 TimeLabel *timeLabel = new TimeLabel( p_intf );
459 nameLabel = new QLabel( this );
460 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
461 | Qt::TextSelectableByKeyboard );
462 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
464 /* Styling those labels */
465 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
466 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
467 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
468 timeLabel->setStyleSheet(
469 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
470 speedLabel->setStyleSheet(
471 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
472 /* pad both label and its tooltip */
473 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
475 /* and adding those */
476 statusBarr->addWidget( nameLabel, 8 );
477 statusBarr->addPermanentWidget( speedLabel, 0 );
478 statusBarr->addPermanentWidget( timeLabel, 0 );
480 /* timeLabel behaviour:
481 - double clicking opens the goto time dialog
482 - right-clicking and clicking just toggle between remaining and
484 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
486 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
487 this, showCryptedLabel( bool ) );
489 CONNECT( THEMIM->getIM(), seekRequested( float ),
490 timeLabel, setDisplayPosition( float ) );
492 /* This shouldn't be necessary, but for somehow reason, the statusBarr
493 starts at height of 20px and when a text is shown it needs more space.
494 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
495 geometry, we need to force a height. If you have a better idea, please
498 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
501 /**********************************************************************
502 * Handling of sizing of the components
503 **********************************************************************/
505 void MainInterface::debug()
508 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
509 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
510 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
512 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
513 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
514 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
518 inline void MainInterface::showVideo() { showTab( videoWidget ); }
519 inline void MainInterface::restoreStackOldWidget()
520 { showTab( stackCentralOldWidget ); }
522 inline void MainInterface::showTab( QWidget *widget )
525 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
528 stackCentralOldWidget = stackCentralW->currentWidget();
529 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
531 stackCentralW->setCurrentWidget( widget );
533 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
536 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
537 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
541 void MainInterface::destroyPopupMenu()
543 QVLCMenu::PopupMenu( p_intf, false );
546 void MainInterface::popupMenu( const QPoint &p )
548 QVLCMenu::PopupMenu( p_intf, true );
551 void MainInterface::toggleFSC()
553 if( !fullscreenControls ) return;
555 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type, 0 );
556 QApplication::postEvent( fullscreenControls, eShow );
559 /****************************************************************************
561 ****************************************************************************/
565 * You must not change the state of this object or other Qt4 UI objects,
566 * from the video output thread - only from the Qt4 UI main loop thread.
567 * All window provider queries must be handled through signals or events.
568 * That's why we have all those emit statements...
570 WId MainInterface::getVideo( int *pi_x, int *pi_y,
571 unsigned int *pi_width, unsigned int *pi_height )
576 /* This is a blocking call signal. Results are returned through pointers.
577 * Beware of deadlocks! */
579 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
583 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
584 unsigned *pi_width, unsigned *pi_height )
586 /* Request the videoWidget */
587 WId ret = videoWidget->request( pi_x, pi_y,
588 pi_width, pi_height, !b_autoresize );
590 if( ret ) /* The videoWidget is available */
592 /* Consider the video active now */
595 /* Ask videoWidget to resize correctly, if we are in normal mode */
596 if( !isFullScreen() && !isMaximized() && b_autoresize )
597 videoWidget->SetSizing( *pi_width, *pi_height );
601 /* Asynchronous call from the WindowClose function */
602 void MainInterface::releaseVideo( void )
604 emit askReleaseVideo();
607 /* Function that is CONNECTED to the previous emit */
608 void MainInterface::releaseVideoSlot( void )
610 /* This function is called when the embedded video window is destroyed,
611 * or in the rare case that the embedded window is still here but the
612 * Qt4 interface exits. */
613 assert( videoWidget );
614 videoWidget->release();
615 setVideoOnTop( false );
616 setVideoFullScreen( false );
618 if( stackCentralW->currentWidget() == videoWidget )
619 restoreStackOldWidget();
621 /* We don't want to have a blank video to popup */
622 stackCentralOldWidget = bgWidget;
625 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
627 if( !isFullScreen() && !isMaximized() )
628 videoWidget->SetSizing( w, h );
631 void MainInterface::setVideoFullScreen( bool fs )
633 b_videoFullScreen = fs;
636 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
637 /* if user hasn't defined screennumber, or screennumber that is bigger
638 * than current number of screens, take screennumber where current interface
641 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
642 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
644 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
646 /* To be sure window is on proper-screen in xinerama */
647 if( !screenres.contains( pos() ) )
649 msg_Dbg( p_intf, "Moving video to correct screen");
650 move( QPoint( screenres.x(), screenres.y() ) );
652 setMinimalView( true );
653 setInterfaceFullScreen( true );
657 /* TODO do we want to restore screen and position ? (when
658 * qt-fullscreen-screennumber is forced) */
659 setMinimalView( b_minimalView );
660 setInterfaceFullScreen( b_interfaceFullScreen );
665 /* Slot to change the video always-on-top flag.
666 * Emit askVideoOnTop() to invoke this from other thread. */
667 void MainInterface::setVideoOnTop( bool on_top )
669 b_videoOnTop = on_top;
671 Qt::WindowFlags oldflags = windowFlags(), newflags;
674 newflags = oldflags | Qt::WindowStaysOnTopHint;
676 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
678 if( newflags != oldflags )
680 setWindowFlags( newflags );
681 show(); /* necessary to apply window flags */
685 /* Asynchronous call from WindowControl function */
686 int MainInterface::controlVideo( int i_query, va_list args )
690 case VOUT_WINDOW_SET_SIZE:
692 unsigned int i_width = va_arg( args, unsigned int );
693 unsigned int i_height = va_arg( args, unsigned int );
695 emit askVideoToResize( i_width, i_height );
698 case VOUT_WINDOW_SET_STATE:
700 unsigned i_arg = va_arg( args, unsigned );
701 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
703 emit askVideoOnTop( on_top != 0 );
706 case VOUT_WINDOW_SET_FULLSCREEN:
708 bool b_fs = va_arg( args, int );
710 emit askVideoSetFullScreen( b_fs );
714 msg_Warn( p_intf, "unsupported control query" );
719 /*****************************************************************************
720 * Playlist, Visualisation and Menus handling
721 *****************************************************************************/
723 * Toggle the playlist widget or dialog
725 void MainInterface::createPlaylist()
727 playlistWidget = new PlaylistWidget( p_intf, this );
731 stackCentralW->addWidget( playlistWidget );
732 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 500, 250 ) ).toSize();
737 playlistWidget->setParent( NULL );
739 playlistWidget->setWindowFlags( Qt::Window );
741 /* This will restore the geometry but will not work for position,
742 because of parenting */
743 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
744 playlistWidget, QSize( 600, 300 ) );
748 void MainInterface::togglePlaylist()
750 if( !playlistWidget )
757 /* Playlist is not visible, show it */
758 if( stackCentralW->currentWidget() != playlistWidget )
760 showTab( playlistWidget );
764 restoreStackOldWidget();
766 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
771 playlistWidget->setParent( NULL );
773 playlistWidget->setWindowFlags( Qt::Window );
774 playlistVisible = !playlistVisible;
775 playlistWidget->setVisible( playlistVisible );
780 void MainInterface::dockPlaylist( bool p_docked )
782 if( b_plDocked == p_docked ) return;
783 b_plDocked = p_docked;
785 if( !playlistWidget ) return; /* Playlist wasn't created yet */
788 stackCentralW->removeWidget( playlistWidget );
790 playlistWidget->setParent( NULL );
792 playlistWidget->setWindowFlags( Qt::Window );
793 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
794 playlistWidget, QSize( 600, 300 ) );
795 playlistWidget->show();
796 restoreStackOldWidget();
800 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
801 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
802 // It would be logical that QStackWidget::addWidget reset the flags...
803 stackCentralW->addWidget( playlistWidget );
804 showTab( playlistWidget );
806 playlistVisible = true;
810 * setMinimalView is the private function used by
811 * the SLOT toggleMinimalView and setVideoFullScreen
813 void MainInterface::setMinimalView( bool b_minimal )
815 menuBar()->setVisible( !b_minimal );
816 controls->setVisible( !b_minimal );
817 statusBar()->setVisible( !b_minimal );
818 inputC->setVisible( !b_minimal );
822 * This public SLOT is used for moving to minimal View Mode
824 * If b_minimal is false, then we are normalView
826 void MainInterface::toggleMinimalView( bool b_minimal )
828 if( !b_minimalView && b_autoresize ) /* Normal mode */
830 if( stackCentralW->currentWidget() == bgWidget )
832 if( stackCentralW->height() < 16 )
834 resizeStack( stackCentralW->width(), 100 );
838 b_minimalView = b_minimal;
839 if( !b_videoFullScreen )
841 setMinimalView( b_minimalView );
842 computeMinimumSize();
845 emit minimalViewToggled( b_minimalView );
848 /* toggling advanced controls buttons */
849 void MainInterface::toggleAdvancedButtons()
851 controls->toggleAdvanced();
852 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
855 /* Get the visibility status of the controls (hidden or not, advanced or not) */
856 int MainInterface::getControlsVisibilityStatus()
858 if( !controls ) return 0;
859 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
860 + CONTROLS_ADVANCED * controls->b_advancedVisible );
864 void MainInterface::visual()
866 if( !VISIBLE( visualSelector) )
868 visualSelector->show();
869 if( !THEMIM->getIM()->hasVideo() )
871 /* Show the background widget */
873 visualSelectorEnabled = true;
877 /* Stop any currently running visualization */
878 visualSelector->hide();
879 visualSelectorEnabled = false;
884 /************************************************************************
886 ************************************************************************/
887 void MainInterface::setName( const QString& name )
889 input_name = name; /* store it for the QSystray use */
890 /* Display it in the status bar, but also as a Tooltip in case it doesn't
892 nameLabel->setText( name );
893 nameLabel->setToolTip( name );
897 * Give the decorations of the Main Window a correct Name.
898 * If nothing is given, set it to VLC...
900 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
902 if( aTitle.isEmpty() )
904 setWindowTitle( qtr( "VLC media player" ) );
908 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
912 void MainInterface::showCryptedLabel( bool b_show )
914 if( cryptedLabel == NULL )
916 cryptedLabel = new QLabel;
917 // The lock icon is not the right one for DRM protection/scrambled.
918 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
919 cryptedLabel->setText( "DRM" );
920 statusBar()->addWidget( cryptedLabel );
923 cryptedLabel->setVisible( b_show );
926 void MainInterface::showBuffering( float f_cache )
928 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
929 statusBar()->showMessage( amount, 1000 );
932 /*****************************************************************************
933 * Systray Icon and Systray Menu
934 *****************************************************************************/
937 * Create a SystemTray icon and a menu that would go with it.
938 * Connects to a click handler on the icon.
940 void MainInterface::createSystray()
943 if( QDate::currentDate().dayOfYear() >= QT_CHRISTMAS_TROLL_DAY )
944 iconVLC = QIcon( ":/logo/vlc128-christmas.png" );
946 iconVLC = QIcon( ":/logo/vlc128.png" );
947 sysTray = new QSystemTrayIcon( iconVLC, this );
948 sysTray->setToolTip( qtr( "VLC media player" ));
950 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
951 systrayMenu->setIcon( iconVLC );
953 QVLCMenu::updateSystrayMenu( this, p_intf, true );
956 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
957 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
961 * Updates the Systray Icon's menu and toggle the main interface
963 void MainInterface::toggleUpdateSystrayMenu()
965 /* If hidden, show it */
971 else if( isMinimized() )
979 /* Visible (possibly under other windows) */
981 /* check if any visible window is above vlc in the z-order,
982 * but ignore the ones always on top
983 * and the ones which can't be activated */
986 wi.cbSize = sizeof( WINDOWINFO );
987 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
988 hwnd && ( !IsWindowVisible( hwnd ) ||
989 ( GetWindowInfo( hwnd, &wi ) &&
990 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
991 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
992 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
993 (wi.dwExStyle&WS_EX_TOPMOST) )
1005 QVLCMenu::updateSystrayMenu( this, p_intf );
1008 void MainInterface::showUpdateSystrayMenu()
1016 QVLCMenu::updateSystrayMenu( this, p_intf );
1019 void MainInterface::hideUpdateSystrayMenu()
1022 QVLCMenu::updateSystrayMenu( this, p_intf );
1025 void MainInterface::handleSystrayClick(
1026 QSystemTrayIcon::ActivationReason reason )
1030 case QSystemTrayIcon::Trigger:
1031 case QSystemTrayIcon::DoubleClick:
1033 QVLCMenu::updateSystrayMenu( this, p_intf );
1035 toggleUpdateSystrayMenu();
1038 case QSystemTrayIcon::MiddleClick:
1039 sysTray->showMessage( qtr( "VLC media player" ),
1040 qtr( "Control menu for the player" ),
1041 QSystemTrayIcon::Information, 3000 );
1049 * Updates the name of the systray Icon tooltip.
1050 * Doesn't check if the systray exists, check before you call it.
1052 void MainInterface::updateSystrayTooltipName( const QString& name )
1054 if( name.isEmpty() )
1056 sysTray->setToolTip( qtr( "VLC media player" ) );
1060 sysTray->setToolTip( name );
1061 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1063 sysTray->showMessage( qtr( "VLC media player" ), name,
1064 QSystemTrayIcon::NoIcon, 3000 );
1068 QVLCMenu::updateSystrayMenu( this, p_intf );
1072 * Updates the status of the systray Icon tooltip.
1073 * Doesn't check if the systray exists, check before you call it.
1075 void MainInterface::updateSystrayTooltipStatus( int i_status )
1080 sysTray->setToolTip( input_name );
1083 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1086 sysTray->setToolTip( qtr( "VLC media player" ) );
1089 QVLCMenu::updateSystrayMenu( this, p_intf );
1093 /************************************************************************
1095 ************************************************************************/
1096 void MainInterface::dropEvent(QDropEvent *event)
1098 dropEventPlay( event, true );
1101 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1103 if( event->possibleActions() & Qt::CopyAction )
1104 event->setDropAction( Qt::CopyAction );
1108 const QMimeData *mimeData = event->mimeData();
1110 /* D&D of a subtitles file, add it on the fly */
1111 if( mimeData->urls().size() == 1 && THEMIM->getIM()->hasInput() )
1113 if( !input_AddSubtitle( THEMIM->getInput(),
1114 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1122 bool first = b_play;
1123 foreach( const QUrl &url, mimeData->urls() )
1127 QString mrl = toURI( url.toEncoded().constData() );
1128 playlist_Add( THEPL, qtu(mrl), NULL,
1129 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1130 PLAYLIST_END, true, pl_Unlocked );
1132 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1136 /* Browsers give content as text if you dnd the addressbar,
1137 so check if mimedata has valid url in text and use it
1138 if we didn't get any normal Urls()*/
1139 if( !mimeData->hasUrls() && mimeData->hasText() &&
1140 QUrl(mimeData->text()).isValid() )
1142 QString mrl = toURI( mimeData->text() );
1143 playlist_Add( THEPL, qtu(mrl), NULL,
1144 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1145 PLAYLIST_END, true, pl_Unlocked );
1149 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1151 event->acceptProposedAction();
1153 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1155 event->acceptProposedAction();
1157 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1162 /************************************************************************
1164 ************************************************************************/
1165 void MainInterface::keyPressEvent( QKeyEvent *e )
1167 handleKeyPress( e );
1170 void MainInterface::handleKeyPress( QKeyEvent *e )
1172 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1174 toggleMinimalView( !b_minimalView );
1178 int i_vlck = qtEventToVLCKey( e );
1181 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1188 void MainInterface::wheelEvent( QWheelEvent *e )
1190 int i_vlckey = qtWheelEventToVLCKey( e );
1191 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1195 void MainInterface::closeEvent( QCloseEvent *e )
1197 e->ignore(); /* Do not quit */
1199 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1202 void MainInterface::setInterfaceFullScreen( bool fs )
1205 setWindowState( windowState() | Qt::WindowFullScreen );
1207 setWindowState( windowState() & ~Qt::WindowFullScreen );
1209 void MainInterface::toggleInterfaceFullScreen()
1211 b_interfaceFullScreen = !b_interfaceFullScreen;
1212 if( !b_videoFullScreen )
1213 setInterfaceFullScreen( b_interfaceFullScreen );
1214 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1217 /*****************************************************************************
1218 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1219 * We don't show the menu directly here because we don't want the
1220 * caller to block for a too long time.
1221 *****************************************************************************/
1222 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1223 vlc_value_t old_val, vlc_value_t new_val, void *param )
1225 intf_thread_t *p_intf = (intf_thread_t *)param;
1227 if( p_intf->pf_show_dialog )
1229 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1230 new_val.b_bool, NULL );
1236 /*****************************************************************************
1237 * IntfShowCB: callback triggered by the intf-show libvlc variable.
1238 *****************************************************************************/
1239 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1240 vlc_value_t old_val, vlc_value_t new_val, void *param )
1242 intf_thread_t *p_intf = (intf_thread_t *)param;
1243 p_intf->p_sys->p_mi->toggleFSC();