1 /*****************************************************************************
2 * main_interface.cpp : Main interface
3 ****************************************************************************
4 * Copyright (C) 2006-2011 VideoLAN and AUTHORS
7 * Authors: Clément Stenac <zorglub@videolan.org>
8 * Jean-Baptiste Kempf <jb@videolan.org>
9 * Ilkka Ollakka <ileoo@videolan.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
32 #include "main_interface.hpp"
33 #include "input_manager.hpp" // Creation
34 #include "actions_manager.hpp" // killInstance
35 #include "extensions_manager.hpp" // killInstance
37 #include "util/customwidgets.hpp" // qtEventToVLCKey, QVLCStackedWidget
38 #include "util/qt_dirs.hpp" // toNativeSeparators
40 #include "components/interface_widgets.hpp" // bgWidget, videoWidget
41 #include "components/controller.hpp" // controllers
42 #include "components/playlist/playlist.hpp" // plWidget
43 #include "dialogs/firstrun.hpp" // First Run
45 #include "menus.hpp" // Menu creation
46 #include "recents.hpp" // RecentItems when DnD
48 #include <QCloseEvent>
59 #include <QStackedWidget>
61 #include <vlc_keys.h> /* Wheel event */
62 #include <vlc_vout_display.h> /* vout_thread_t and VOUT_ events */
66 /* Callback prototypes */
67 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
68 vlc_value_t old_val, vlc_value_t new_val, void *param );
69 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
70 vlc_value_t old_val, vlc_value_t new_val, void *param );
71 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
72 vlc_value_t old_val, vlc_value_t new_val, void *param );
73 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
74 vlc_value_t old_val, vlc_value_t new_val,
77 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
79 /* Variables initialisation */
82 playlistWidget = NULL;
83 stackCentralOldWidget= NULL;
87 fullscreenControls = NULL;
92 b_hideAfterCreation = false; // --qt-start-minimized
93 playlistVisible = false;
95 b_interfaceFullScreen= false;
96 b_hasPausedWhenMinimized = false;
100 FirstRun::CheckAndRun( this, p_intf );
103 * Configuration and settings
104 * Pre-building of interface
107 setFocusPolicy( Qt::StrongFocus );
108 setAcceptDrops( true );
109 setWindowRole( "vlc-main" );
110 setWindowIcon( QApplication::windowIcon() );
111 setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
113 setAttribute( Qt::WA_MacBrushedMetal );
116 /* Is video in embedded in the UI or not */
117 b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
119 /* Does the interface resize to video size or the opposite */
120 b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
122 /* Are we in the enhanced always-video mode or not ? */
123 b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
125 /* Do we want anoying popups or not */
126 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
129 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
131 /* Set the other interface settings */
132 settings = getSettings();
133 settings->beginGroup( "MainWindow" );
137 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
141 b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
143 settings->endGroup( );
145 /**************************
146 * UI and Widgets design
147 **************************/
148 setVLCWindowsTitle();
153 QVLCMenu::createMenuBar( this, p_intf );
154 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
155 this, destroyPopupMenu() );
157 createMainWidget( settings );
163 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
165 /********************
167 ********************/
168 MainInputManager::getInstance( p_intf );
173 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
176 /*********************************
177 * Create the Systray Management *
178 *********************************/
181 /*************************************************************
182 * Connect the input manager to the GUI elements it manages *
183 * Beware initSystray did some connects on input manager too *
184 *************************************************************/
186 * Connects on nameChanged()
187 * Those connects are different because options can impeach them to trigger.
189 /* Main Interface statusbar */
190 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
191 this, setName( const QString& ) );
192 /* and title of the Main Interface*/
193 if( var_InheritBool( p_intf, "qt-name-in-title" ) )
195 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
196 this, setVLCWindowsTitle( const QString& ) );
198 /* END CONNECTS ON IM */
200 /* VideoWidget connects for asynchronous calls */
201 b_videoFullScreen = false;
202 connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
203 this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
204 Qt::BlockingQueuedConnection );
205 connect( this, SIGNAL(askReleaseVideo( void )),
206 this, SLOT(releaseVideoSlot( void )),
207 Qt::BlockingQueuedConnection );
208 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
214 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
215 this, setVideoSize( unsigned int, unsigned int ) );
216 CONNECT( videoWidget, sizeChanged( int, int ),
217 this, resizeStack( int, int ) );
219 CONNECT( this, askVideoSetFullScreen( bool ),
220 this, setVideoFullScreen( bool ) );
223 CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
225 CONNECT( this, askToQuit(), THEDP, quit() );
227 CONNECT( this, askBoss(), this, setBoss() );
228 CONNECT( this, askRaise(), this, setRaise() );
230 /** END of CONNECTS**/
236 var_AddCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
237 var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
238 var_AddCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
240 /* Register callback for the intf-popupmenu variable */
241 var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
244 /* Final Sizing, restoration and placement of the interface */
245 settings->beginGroup( "MainWindow" );
247 if( settings->value( "playlist-visible", false ).toBool() )
250 QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
251 settings->endGroup();
253 b_interfaceFullScreen = isFullScreen();
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 );
300 settings->setValue( "status-bar-visible", b_statusbarVisible );
302 /* Save the stackCentralW sizes */
303 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
304 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
307 QVLCTools::saveWidgetPosition(settings, this);
309 settings->endGroup();
311 /* Save undocked playlist size */
312 if( playlistWidget && !isPlDocked() )
313 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
315 delete playlistWidget;
319 /* Unregister callbacks */
320 var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
321 var_DelCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
322 var_DelCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
323 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
325 p_intf->p_sys->p_mi = NULL;
328 void MainInterface::computeMinimumSize()
331 if( menuBar()->isVisible() )
332 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
334 setMinimumWidth( minWidth );
337 /*****************************
339 *****************************/
340 void MainInterface::recreateToolbars()
342 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
344 settings->beginGroup( "MainWindow" );
348 controls = new ControlsWidget( p_intf, b_adv, this );
349 inputC = new InputControlsWidget( p_intf, this );
350 mainLayout->insertWidget( 2, inputC );
351 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
354 if( fullscreenControls )
356 delete fullscreenControls;
357 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
358 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
359 this, handleKeyPress( QKeyEvent * ) );
361 settings->endGroup();
364 void MainInterface::reloadPrefs()
366 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
367 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
369 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
371 if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
373 delete fullscreenControls;
374 fullscreenControls = NULL;
378 void MainInterface::createMainWidget( QSettings *settings )
380 /* Create the main Widget and the mainLayout */
381 QWidget *main = new QWidget;
382 setCentralWidget( main );
383 mainLayout = new QVBoxLayout( main );
384 main->setContentsMargins( 0, 0, 0, 0 );
385 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
388 stackCentralW = new QVLCStackedWidget( main );
391 bgWidget = new BackgroundWidget( p_intf );
392 stackCentralW->addWidget( bgWidget );
393 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
394 bgWidget->setWithArt( false );
396 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
397 bgWidget->setExpandstoHeight( true );
399 /* And video Outputs */
400 if( b_videoEmbedded )
402 videoWidget = new VideoWidget( p_intf );
403 stackCentralW->addWidget( videoWidget );
405 mainLayout->insertWidget( 1, stackCentralW );
407 settings->beginGroup( "MainWindow" );
408 stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 600, 0 ) ).toSize();
409 /* Resize even if no-auto-resize, because we are at creation */
410 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
412 /* Create the CONTROLS Widget */
413 controls = new ControlsWidget( p_intf,
414 settings->value( "adv-controls", false ).toBool(), this );
415 inputC = new InputControlsWidget( p_intf, this );
417 mainLayout->insertWidget( 2, inputC );
418 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
421 /* Visualisation, disabled for now, they SUCK */
423 visualSelector = new VisualSelector( p_intf );
424 mainLayout->insertWidget( 0, visualSelector );
425 visualSelector->hide();
428 settings->endGroup();
430 /* Enable the popup menu in the MI */
431 main->setContextMenuPolicy( Qt::CustomContextMenu );
432 CONNECT( main, customContextMenuRequested( const QPoint& ),
433 this, popupMenu( const QPoint& ) );
435 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
436 /* Create the FULLSCREEN CONTROLS Widget */
437 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
439 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
440 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
441 this, handleKeyPress( QKeyEvent * ) );
445 inline void MainInterface::initSystray()
448 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
449 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
451 if( var_InheritBool( p_intf, "qt-start-minimized") )
453 if( b_systrayAvailable )
455 b_systrayWanted = true;
456 b_hideAfterCreation = true;
459 msg_Err( p_intf, "cannot start minimized without system tray bar" );
462 if( b_systrayAvailable && b_systrayWanted )
467 inline void MainInterface::createStatusBar()
472 /* Widgets Creation*/
473 QStatusBar *statusBarr = statusBar();
475 TimeLabel *timeLabel = new TimeLabel( p_intf );
476 nameLabel = new QLabel( this );
477 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
478 | Qt::TextSelectableByKeyboard );
479 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
481 /* Styling those labels */
482 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
483 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
484 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
485 timeLabel->setStyleSheet(
486 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
487 speedLabel->setStyleSheet(
488 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
489 /* pad both label and its tooltip */
490 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
492 /* and adding those */
493 statusBarr->addWidget( nameLabel, 8 );
494 statusBarr->addPermanentWidget( speedLabel, 0 );
495 statusBarr->addPermanentWidget( timeLabel, 0 );
497 /* timeLabel behaviour:
498 - double clicking opens the goto time dialog
499 - right-clicking and clicking just toggle between remaining and
501 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
503 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
504 this, showCryptedLabel( bool ) );
506 CONNECT( THEMIM->getIM(), seekRequested( float ),
507 timeLabel, setDisplayPosition( float ) );
509 /* This shouldn't be necessary, but for somehow reason, the statusBarr
510 starts at height of 20px and when a text is shown it needs more space.
511 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
512 geometry, we need to force a height. If you have a better idea, please
515 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
518 /**********************************************************************
519 * Handling of sizing of the components
520 **********************************************************************/
522 void MainInterface::debug()
525 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
526 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
527 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
529 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
530 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
531 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
535 inline void MainInterface::showVideo() { showTab( videoWidget ); }
536 inline void MainInterface::restoreStackOldWidget()
537 { showTab( stackCentralOldWidget ); }
539 inline void MainInterface::showTab( QWidget *widget )
542 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
545 stackCentralOldWidget = stackCentralW->currentWidget();
546 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
548 stackCentralW->setCurrentWidget( widget );
550 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
553 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
554 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
558 void MainInterface::destroyPopupMenu()
560 QVLCMenu::PopupMenu( p_intf, false );
563 void MainInterface::popupMenu( const QPoint & )
565 QVLCMenu::PopupMenu( p_intf, true );
568 void MainInterface::toggleFSC()
570 if( !fullscreenControls ) return;
572 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
573 QApplication::postEvent( fullscreenControls, eShow );
576 /****************************************************************************
578 ****************************************************************************/
582 * You must not change the state of this object or other Qt4 UI objects,
583 * from the video output thread - only from the Qt4 UI main loop thread.
584 * All window provider queries must be handled through signals or events.
585 * That's why we have all those emit statements...
587 WId MainInterface::getVideo( int *pi_x, int *pi_y,
588 unsigned int *pi_width, unsigned int *pi_height )
593 /* This is a blocking call signal. Results are returned through pointers.
594 * Beware of deadlocks! */
596 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
600 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
601 unsigned *pi_width, unsigned *pi_height )
603 /* Hidden or minimized, activate */
604 if( isHidden() || isMinimized() )
605 toggleUpdateSystrayMenu();
607 /* Request the videoWidget */
608 WId ret = videoWidget->request( pi_x, pi_y,
609 pi_width, pi_height, !b_autoresize );
611 if( ret ) /* The videoWidget is available */
613 /* Consider the video active now */
616 /* Ask videoWidget to resize correctly, if we are in normal mode */
617 if( !isFullScreen() && !isMaximized() && b_autoresize )
618 videoWidget->SetSizing( *pi_width, *pi_height );
622 /* Asynchronous call from the WindowClose function */
623 void MainInterface::releaseVideo( void )
625 emit askReleaseVideo();
628 /* Function that is CONNECTED to the previous emit */
629 void MainInterface::releaseVideoSlot( void )
631 /* This function is called when the embedded video window is destroyed,
632 * or in the rare case that the embedded window is still here but the
633 * Qt4 interface exits. */
634 assert( videoWidget );
635 videoWidget->release();
636 setVideoOnTop( false );
637 setVideoFullScreen( false );
639 if( stackCentralW->currentWidget() == videoWidget )
640 restoreStackOldWidget();
642 /* We don't want to have a blank video to popup */
643 stackCentralOldWidget = bgWidget;
646 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
648 if( !isFullScreen() && !isMaximized() )
649 videoWidget->SetSizing( w, h );
652 void MainInterface::setVideoFullScreen( bool fs )
654 b_videoFullScreen = fs;
657 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
658 /* if user hasn't defined screennumber, or screennumber that is bigger
659 * than current number of screens, take screennumber where current interface
662 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
663 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
665 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
667 /* To be sure window is on proper-screen in xinerama */
668 if( !screenres.contains( pos() ) )
670 msg_Dbg( p_intf, "Moving video to correct screen");
671 move( QPoint( screenres.x(), screenres.y() ) );
673 setMinimalView( true );
674 setInterfaceFullScreen( true );
678 /* TODO do we want to restore screen and position ? (when
679 * qt-fullscreen-screennumber is forced) */
680 setMinimalView( b_minimalView );
681 setInterfaceFullScreen( b_interfaceFullScreen );
686 /* Slot to change the video always-on-top flag.
687 * Emit askVideoOnTop() to invoke this from other thread. */
688 void MainInterface::setVideoOnTop( bool on_top )
690 Qt::WindowFlags oldflags = windowFlags(), newflags;
693 newflags = oldflags | Qt::WindowStaysOnTopHint;
695 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
696 if( newflags != oldflags && !b_videoFullScreen )
699 setWindowFlags( newflags );
700 show(); /* necessary to apply window flags */
704 /* Asynchronous call from WindowControl function */
705 int MainInterface::controlVideo( int i_query, va_list args )
709 case VOUT_WINDOW_SET_SIZE:
711 unsigned int i_width = va_arg( args, unsigned int );
712 unsigned int i_height = va_arg( args, unsigned int );
714 emit askVideoToResize( i_width, i_height );
717 case VOUT_WINDOW_SET_STATE:
719 unsigned i_arg = va_arg( args, unsigned );
720 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
722 emit askVideoOnTop( on_top != 0 );
725 case VOUT_WINDOW_SET_FULLSCREEN:
727 bool b_fs = va_arg( args, int );
729 emit askVideoSetFullScreen( b_fs );
733 msg_Warn( p_intf, "unsupported control query" );
738 /*****************************************************************************
739 * Playlist, Visualisation and Menus handling
740 *****************************************************************************/
742 * Toggle the playlist widget or dialog
744 void MainInterface::createPlaylist()
746 playlistWidget = new PlaylistWidget( p_intf, this );
750 stackCentralW->addWidget( playlistWidget );
751 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
756 playlistWidget->setParent( NULL );
758 playlistWidget->setWindowFlags( Qt::Window );
760 /* This will restore the geometry but will not work for position,
761 because of parenting */
762 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
763 playlistWidget, QSize( 600, 300 ) );
767 void MainInterface::togglePlaylist()
769 if( !playlistWidget )
776 /* Playlist is not visible, show it */
777 if( stackCentralW->currentWidget() != playlistWidget )
779 showTab( playlistWidget );
783 restoreStackOldWidget();
785 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
790 playlistWidget->setParent( NULL );
792 playlistWidget->setWindowFlags( Qt::Window );
793 playlistVisible = !playlistVisible;
794 playlistWidget->setVisible( playlistVisible );
799 void MainInterface::dockPlaylist( bool p_docked )
801 if( b_plDocked == p_docked ) return;
802 b_plDocked = p_docked;
804 if( !playlistWidget ) return; /* Playlist wasn't created yet */
807 stackCentralW->removeWidget( playlistWidget );
809 playlistWidget->setParent( NULL );
811 playlistWidget->setWindowFlags( Qt::Window );
812 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
813 playlistWidget, QSize( 600, 300 ) );
814 playlistWidget->show();
815 restoreStackOldWidget();
819 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
820 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
821 // It would be logical that QStackWidget::addWidget reset the flags...
822 stackCentralW->addWidget( playlistWidget );
823 showTab( playlistWidget );
825 playlistVisible = true;
829 * setMinimalView is the private function used by
830 * the SLOT toggleMinimalView and setVideoFullScreen
832 void MainInterface::setMinimalView( bool b_minimal )
834 menuBar()->setVisible( !b_minimal );
835 controls->setVisible( !b_minimal );
836 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
837 inputC->setVisible( !b_minimal );
841 * This public SLOT is used for moving to minimal View Mode
843 * If b_minimal is false, then we are normalView
845 void MainInterface::toggleMinimalView( bool b_minimal )
847 if( !b_minimalView && b_autoresize ) /* Normal mode */
849 if( stackCentralW->currentWidget() == bgWidget )
851 if( stackCentralW->height() < 16 )
853 resizeStack( stackCentralW->width(), 100 );
857 b_minimalView = b_minimal;
858 if( !b_videoFullScreen )
860 setMinimalView( b_minimalView );
861 computeMinimumSize();
864 emit minimalViewToggled( b_minimalView );
867 /* toggling advanced controls buttons */
868 void MainInterface::toggleAdvancedButtons()
870 controls->toggleAdvanced();
871 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
874 /* Get the visibility status of the controls (hidden or not, advanced or not) */
875 int MainInterface::getControlsVisibilityStatus()
877 if( !controls ) return 0;
878 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
879 + CONTROLS_ADVANCED * controls->b_advancedVisible );
882 void MainInterface::setStatusBarVisibility( bool b_visible )
884 statusBar()->setVisible( b_visible );
885 b_statusbarVisible = b_visible;
886 if( controls ) controls->setGripVisible( !b_statusbarVisible );
890 void MainInterface::visual()
892 if( !VISIBLE( visualSelector) )
894 visualSelector->show();
895 if( !THEMIM->getIM()->hasVideo() )
897 /* Show the background widget */
899 visualSelectorEnabled = true;
903 /* Stop any currently running visualization */
904 visualSelector->hide();
905 visualSelectorEnabled = false;
910 /************************************************************************
912 ************************************************************************/
913 void MainInterface::setName( const QString& name )
915 input_name = name; /* store it for the QSystray use */
916 /* Display it in the status bar, but also as a Tooltip in case it doesn't
918 nameLabel->setText( name );
919 nameLabel->setToolTip( name );
923 * Give the decorations of the Main Window a correct Name.
924 * If nothing is given, set it to VLC...
926 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
928 if( aTitle.isEmpty() )
930 setWindowTitle( qtr( "VLC media player" ) );
934 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
938 void MainInterface::showCryptedLabel( bool b_show )
940 if( cryptedLabel == NULL )
942 cryptedLabel = new QLabel;
943 // The lock icon is not the right one for DRM protection/scrambled.
944 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
945 cryptedLabel->setText( "DRM" );
946 statusBar()->addWidget( cryptedLabel );
949 cryptedLabel->setVisible( b_show );
952 void MainInterface::showBuffering( float f_cache )
954 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
955 statusBar()->showMessage( amount, 1000 );
958 /*****************************************************************************
959 * Systray Icon and Systray Menu
960 *****************************************************************************/
963 * Create a SystemTray icon and a menu that would go with it.
964 * Connects to a click handler on the icon.
966 void MainInterface::createSystray()
969 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
970 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
972 iconVLC = QIcon( ":/logo/vlc128.png" );
973 sysTray = new QSystemTrayIcon( iconVLC, this );
974 sysTray->setToolTip( qtr( "VLC media player" ));
976 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
977 systrayMenu->setIcon( iconVLC );
979 QVLCMenu::updateSystrayMenu( this, p_intf, true );
982 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
983 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
985 /* Connects on nameChanged() */
986 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
987 this, updateSystrayTooltipName( const QString& ) );
988 /* Connect PLAY_STATUS on the systray */
989 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
990 this, updateSystrayTooltipStatus( int ) );
994 * Updates the Systray Icon's menu and toggle the main interface
996 void MainInterface::toggleUpdateSystrayMenu()
998 /* If hidden, show it */
1004 else if( isMinimized() )
1012 /* Visible (possibly under other windows) */
1014 /* check if any visible window is above vlc in the z-order,
1015 * but ignore the ones always on top
1016 * and the ones which can't be activated */
1019 wi.cbSize = sizeof( WINDOWINFO );
1020 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1021 hwnd && ( !IsWindowVisible( hwnd ) ||
1022 ( GetWindowInfo( hwnd, &wi ) &&
1023 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1024 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1025 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1026 (wi.dwExStyle&WS_EX_TOPMOST) )
1039 QVLCMenu::updateSystrayMenu( this, p_intf );
1042 /* First Item of the systray menu */
1043 void MainInterface::showUpdateSystrayMenu()
1051 QVLCMenu::updateSystrayMenu( this, p_intf );
1054 /* First Item of the systray menu */
1055 void MainInterface::hideUpdateSystrayMenu()
1058 QVLCMenu::updateSystrayMenu( this, p_intf );
1061 /* Click on systray Icon */
1062 void MainInterface::handleSystrayClick(
1063 QSystemTrayIcon::ActivationReason reason )
1067 case QSystemTrayIcon::Trigger:
1068 case QSystemTrayIcon::DoubleClick:
1070 QVLCMenu::updateSystrayMenu( this, p_intf );
1072 toggleUpdateSystrayMenu();
1075 case QSystemTrayIcon::MiddleClick:
1076 sysTray->showMessage( qtr( "VLC media player" ),
1077 qtr( "Control menu for the player" ),
1078 QSystemTrayIcon::Information, 3000 );
1086 * Updates the name of the systray Icon tooltip.
1087 * Doesn't check if the systray exists, check before you call it.
1089 void MainInterface::updateSystrayTooltipName( const QString& name )
1091 if( name.isEmpty() )
1093 sysTray->setToolTip( qtr( "VLC media player" ) );
1097 sysTray->setToolTip( name );
1098 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1100 sysTray->showMessage( qtr( "VLC media player" ), name,
1101 QSystemTrayIcon::NoIcon, 3000 );
1105 QVLCMenu::updateSystrayMenu( this, p_intf );
1109 * Updates the status of the systray Icon tooltip.
1110 * Doesn't check if the systray exists, check before you call it.
1112 void MainInterface::updateSystrayTooltipStatus( int i_status )
1117 sysTray->setToolTip( input_name );
1120 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1123 sysTray->setToolTip( qtr( "VLC media player" ) );
1126 QVLCMenu::updateSystrayMenu( this, p_intf );
1130 void MainInterface::changeEvent(QEvent *event)
1132 if( event->type() == QEvent::WindowStateChange )
1134 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1135 Qt::WindowStates newState = windowState();
1136 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1138 if( newState & Qt::WindowMinimized )
1140 b_hasPausedWhenMinimized = false;
1142 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1143 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1146 b_hasPausedWhenMinimized = true;
1150 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1152 if( b_hasPausedWhenMinimized )
1159 QWidget::changeEvent(event);
1162 /************************************************************************
1164 ************************************************************************/
1165 void MainInterface::dropEvent(QDropEvent *event)
1167 dropEventPlay( event, true );
1170 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1172 if( event->possibleActions() & Qt::CopyAction )
1173 event->setDropAction( Qt::CopyAction );
1177 const QMimeData *mimeData = event->mimeData();
1179 /* D&D of a subtitles file, add it on the fly */
1180 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1182 if( !input_AddSubtitle( THEMIM->getInput(),
1183 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1191 bool first = b_play;
1192 foreach( const QUrl &url, mimeData->urls() )
1196 QString mrl = toURI( url.toEncoded().constData() );
1197 playlist_Add( THEPL, qtu(mrl), NULL,
1198 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1199 PLAYLIST_END, true, pl_Unlocked );
1201 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1205 /* Browsers give content as text if you dnd the addressbar,
1206 so check if mimedata has valid url in text and use it
1207 if we didn't get any normal Urls()*/
1208 if( !mimeData->hasUrls() && mimeData->hasText() &&
1209 QUrl(mimeData->text()).isValid() )
1211 QString mrl = toURI( mimeData->text() );
1212 playlist_Add( THEPL, qtu(mrl), NULL,
1213 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1214 PLAYLIST_END, true, pl_Unlocked );
1218 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1220 event->acceptProposedAction();
1222 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1224 event->acceptProposedAction();
1226 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1231 /************************************************************************
1233 ************************************************************************/
1234 void MainInterface::keyPressEvent( QKeyEvent *e )
1236 handleKeyPress( e );
1239 void MainInterface::handleKeyPress( QKeyEvent *e )
1241 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1243 toggleMinimalView( !b_minimalView );
1247 int i_vlck = qtEventToVLCKey( e );
1250 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1257 void MainInterface::wheelEvent( QWheelEvent *e )
1259 int i_vlckey = qtWheelEventToVLCKey( e );
1260 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1264 void MainInterface::closeEvent( QCloseEvent *e )
1267 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1268 /* Accept session quit. Otherwise we break the desktop mamager. */
1272 void MainInterface::setInterfaceFullScreen( bool fs )
1275 setWindowState( windowState() | Qt::WindowFullScreen );
1277 setWindowState( windowState() & ~Qt::WindowFullScreen );
1279 void MainInterface::toggleInterfaceFullScreen()
1281 b_interfaceFullScreen = !b_interfaceFullScreen;
1282 if( !b_videoFullScreen )
1283 setInterfaceFullScreen( b_interfaceFullScreen );
1284 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1287 void MainInterface::emitBoss()
1291 void MainInterface::setBoss()
1306 void MainInterface::emitRaise()
1310 void MainInterface::setRaise()
1316 /*****************************************************************************
1317 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1318 * We don't show the menu directly here because we don't want the
1319 * caller to block for a too long time.
1320 *****************************************************************************/
1321 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1322 vlc_value_t old_val, vlc_value_t new_val, void *param )
1324 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1326 intf_thread_t *p_intf = (intf_thread_t *)param;
1328 if( p_intf->pf_show_dialog )
1330 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1331 new_val.b_bool, NULL );
1337 /*****************************************************************************
1338 * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1339 *****************************************************************************/
1340 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1341 vlc_value_t old_val, vlc_value_t new_val, void *param )
1343 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1344 VLC_UNUSED( new_val );
1346 intf_thread_t *p_intf = (intf_thread_t *)param;
1347 p_intf->p_sys->p_mi->toggleFSC();
1353 /*****************************************************************************
1354 * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1355 *****************************************************************************/
1356 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
1357 vlc_value_t old_val, vlc_value_t new_val, void *param )
1359 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1360 VLC_UNUSED( new_val );
1362 intf_thread_t *p_intf = (intf_thread_t *)param;
1363 p_intf->p_sys->p_mi->emitRaise();
1368 /*****************************************************************************
1369 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1370 *****************************************************************************/
1371 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1372 vlc_value_t old_val, vlc_value_t new_val, void *param )
1374 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1375 VLC_UNUSED( new_val );
1377 intf_thread_t *p_intf = (intf_thread_t *)param;
1378 p_intf->p_sys->p_mi->emitBoss();