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 );
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 );
74 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
76 /* Variables initialisation */
79 playlistWidget = NULL;
80 stackCentralOldWidget= NULL;
84 fullscreenControls = NULL;
89 b_hideAfterCreation = false; // --qt-start-minimized
90 playlistVisible = false;
92 b_interfaceFullScreen= false;
96 FirstRun::CheckAndRun( this, p_intf );
99 * Configuration and settings
100 * Pre-building of interface
103 setFocusPolicy( Qt::StrongFocus );
104 setAcceptDrops( true );
105 setWindowRole( "vlc-main" );
106 setWindowIcon( QApplication::windowIcon() );
107 setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
109 setAttribute( Qt::WA_MacBrushedMetal );
112 /* Is video in embedded in the UI or not */
113 b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
115 /* Does the interface resize to video size or the opposite */
116 b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
118 /* Are we in the enhanced always-video mode or not ? */
119 b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
121 /* Do we want anoying popups or not */
122 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
125 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
127 /* Set the other interface settings */
128 settings = getSettings();
129 settings->beginGroup( "MainWindow" );
133 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
137 b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
139 settings->endGroup( );
141 /**************************
142 * UI and Widgets design
143 **************************/
144 setVLCWindowsTitle();
149 QVLCMenu::createMenuBar( this, p_intf );
150 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
151 this, destroyPopupMenu() );
153 createMainWidget( settings );
159 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
161 /********************
163 ********************/
164 MainInputManager::getInstance( p_intf );
169 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
172 /*********************************
173 * Create the Systray Management *
174 *********************************/
177 /************************************************************
178 * Connect the input manager to the GUI elements it manages *
179 ************************************************************/
181 * Connects on nameChanged()
182 * Those connects are different because options can impeach them to trigger.
184 /* Main Interface statusbar */
185 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
186 this, setName( const QString& ) );
191 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
192 this, updateSystrayTooltipName( const QString& ) );
195 /* and title of the Main Interface*/
196 if( var_InheritBool( p_intf, "qt-name-in-title" ) )
198 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
199 this, setVLCWindowsTitle( const QString& ) );
203 * CONNECTS on PLAY_STATUS
205 /* Status on the systray */
209 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
210 this, updateSystrayTooltipStatus( int ) );
214 /* END CONNECTS ON IM */
216 /* VideoWidget connects for asynchronous calls */
217 b_videoFullScreen = false;
218 connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
219 this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
220 Qt::BlockingQueuedConnection );
221 connect( this, SIGNAL(askReleaseVideo( void )),
222 this, SLOT(releaseVideoSlot( void )),
223 Qt::BlockingQueuedConnection );
224 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
230 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
231 this, setVideoSize( unsigned int, unsigned int ) );
232 CONNECT( videoWidget, sizeChanged( int, int ),
233 this, resizeStack( int, int ) );
235 CONNECT( this, askVideoSetFullScreen( bool ),
236 this, setVideoFullScreen( bool ) );
239 CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
241 CONNECT( this, askToQuit(), THEDP, quit() );
243 CONNECT( this, askBoss(), this, setBoss() );
245 /** END of CONNECTS**/
251 var_AddCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
252 var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
254 /* Register callback for the intf-popupmenu variable */
255 var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
258 int i_plVis = settings->value( "MainWindow/playlist-visible", false ).toBool();
260 if( i_plVis ) togglePlaylist();
262 /**** FINAL SIZING and placement of interface */
263 settings->beginGroup( "MainWindow" );
264 QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
265 settings->endGroup();
267 b_interfaceFullScreen = isFullScreen();
269 /* Final sizing and showing */
270 setVisible( !b_hideAfterCreation );
272 computeMinimumSize();
274 /* Switch to minimal view if needed, must be called after the show() */
276 toggleMinimalView( true );
278 b_hasPausedWhenMinimized = false;
281 MainInterface::~MainInterface()
283 /* Unsure we hide the videoWidget before destroying it */
284 if( stackCentralOldWidget == videoWidget )
292 ImageList_Destroy( himl );
294 p_taskbl->vt->Release(p_taskbl);
298 /* Be sure to kill the actionsManager... Only used in the MI and control */
299 ActionsManager::killInstance();
302 ExtensionsManager::killInstance();
304 /* Delete the FSC controller */
305 delete fullscreenControls;
308 settings->beginGroup( "MainWindow" );
310 settings->setValue( "pl-dock-status", b_plDocked );
311 /* Save playlist state */
313 settings->setValue( "playlist-visible", playlistVisible );
315 settings->setValue( "adv-controls",
316 getControlsVisibilityStatus() & CONTROLS_ADVANCED );
317 settings->setValue( "status-bar-visible", b_statusbarVisible );
319 /* Save the stackCentralW sizes */
320 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
321 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
324 QVLCTools::saveWidgetPosition(settings, this);
326 settings->endGroup();
328 /* Save undocked playlist size */
329 if( playlistWidget && !isPlDocked() )
330 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
332 delete playlistWidget;
336 /* Unregister callbacks */
337 var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
338 var_DelCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
339 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
341 p_intf->p_sys->p_mi = NULL;
344 void MainInterface::computeMinimumSize()
347 if( menuBar()->isVisible() )
348 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
350 setMinimumWidth( minWidth );
353 /*****************************
355 *****************************/
356 void MainInterface::recreateToolbars()
358 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
360 settings->beginGroup( "MainWindow" );
364 controls = new ControlsWidget( p_intf, b_adv, this );
365 inputC = new InputControlsWidget( p_intf, this );
367 if( fullscreenControls )
369 delete fullscreenControls;
370 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
371 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
372 this, handleKeyPress( QKeyEvent * ) );
374 mainLayout->insertWidget( 2, inputC );
375 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
377 settings->endGroup();
380 void MainInterface::reloadPrefs()
382 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
383 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
385 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
387 if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
389 delete fullscreenControls;
390 fullscreenControls = NULL;
394 void MainInterface::createMainWidget( QSettings *settings )
396 /* Create the main Widget and the mainLayout */
397 QWidget *main = new QWidget;
398 setCentralWidget( main );
399 mainLayout = new QVBoxLayout( main );
400 main->setContentsMargins( 0, 0, 0, 0 );
401 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
404 stackCentralW = new QVLCStackedWidget( main );
407 bgWidget = new BackgroundWidget( p_intf );
408 stackCentralW->addWidget( bgWidget );
409 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
410 bgWidget->setWithArt( false );
412 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
413 bgWidget->setExpandstoHeight( true );
415 /* And video Outputs */
416 if( b_videoEmbedded )
418 videoWidget = new VideoWidget( p_intf );
419 stackCentralW->addWidget( videoWidget );
421 mainLayout->insertWidget( 1, stackCentralW );
423 settings->beginGroup( "MainWindow" );
424 stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 600, 0 ) ).toSize();
425 /* Resize even if no-auto-resize, because we are at creation */
426 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
428 /* Create the CONTROLS Widget */
429 controls = new ControlsWidget( p_intf,
430 settings->value( "adv-controls", false ).toBool(), this );
431 inputC = new InputControlsWidget( p_intf, this );
433 mainLayout->insertWidget( 2, inputC );
434 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
437 /* Visualisation, disabled for now, they SUCK */
439 visualSelector = new VisualSelector( p_intf );
440 mainLayout->insertWidget( 0, visualSelector );
441 visualSelector->hide();
444 settings->endGroup();
446 /* Enable the popup menu in the MI */
447 main->setContextMenuPolicy( Qt::CustomContextMenu );
448 CONNECT( main, customContextMenuRequested( const QPoint& ),
449 this, popupMenu( const QPoint& ) );
451 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
452 /* Create the FULLSCREEN CONTROLS Widget */
453 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
455 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
456 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
457 this, handleKeyPress( QKeyEvent * ) );
461 inline void MainInterface::initSystray()
464 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
465 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
467 if( var_InheritBool( p_intf, "qt-start-minimized") )
469 if( b_systrayAvailable )
471 b_systrayWanted = true;
472 b_hideAfterCreation = true;
475 msg_Err( p_intf, "cannot start minimized without system tray bar" );
478 if( b_systrayAvailable && b_systrayWanted )
483 inline void MainInterface::createStatusBar()
488 /* Widgets Creation*/
489 QStatusBar *statusBarr = statusBar();
491 TimeLabel *timeLabel = new TimeLabel( p_intf );
492 nameLabel = new QLabel( this );
493 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
494 | Qt::TextSelectableByKeyboard );
495 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
497 /* Styling those labels */
498 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
499 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
500 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
501 timeLabel->setStyleSheet(
502 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
503 speedLabel->setStyleSheet(
504 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
505 /* pad both label and its tooltip */
506 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
508 /* and adding those */
509 statusBarr->addWidget( nameLabel, 8 );
510 statusBarr->addPermanentWidget( speedLabel, 0 );
511 statusBarr->addPermanentWidget( timeLabel, 0 );
513 /* timeLabel behaviour:
514 - double clicking opens the goto time dialog
515 - right-clicking and clicking just toggle between remaining and
517 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
519 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
520 this, showCryptedLabel( bool ) );
522 CONNECT( THEMIM->getIM(), seekRequested( float ),
523 timeLabel, setDisplayPosition( float ) );
525 /* This shouldn't be necessary, but for somehow reason, the statusBarr
526 starts at height of 20px and when a text is shown it needs more space.
527 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
528 geometry, we need to force a height. If you have a better idea, please
531 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
534 /**********************************************************************
535 * Handling of sizing of the components
536 **********************************************************************/
538 void MainInterface::debug()
541 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
542 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
543 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
545 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
546 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
547 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
551 inline void MainInterface::showVideo() { showTab( videoWidget ); }
552 inline void MainInterface::restoreStackOldWidget()
553 { showTab( stackCentralOldWidget ); }
555 inline void MainInterface::showTab( QWidget *widget )
558 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
561 stackCentralOldWidget = stackCentralW->currentWidget();
562 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
564 stackCentralW->setCurrentWidget( widget );
566 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
569 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
570 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
574 void MainInterface::destroyPopupMenu()
576 QVLCMenu::PopupMenu( p_intf, false );
579 void MainInterface::popupMenu( const QPoint & )
581 QVLCMenu::PopupMenu( p_intf, true );
584 void MainInterface::toggleFSC()
586 if( !fullscreenControls ) return;
588 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
589 QApplication::postEvent( fullscreenControls, eShow );
592 /****************************************************************************
594 ****************************************************************************/
598 * You must not change the state of this object or other Qt4 UI objects,
599 * from the video output thread - only from the Qt4 UI main loop thread.
600 * All window provider queries must be handled through signals or events.
601 * That's why we have all those emit statements...
603 WId MainInterface::getVideo( int *pi_x, int *pi_y,
604 unsigned int *pi_width, unsigned int *pi_height )
609 /* This is a blocking call signal. Results are returned through pointers.
610 * Beware of deadlocks! */
612 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
616 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
617 unsigned *pi_width, unsigned *pi_height )
619 /* Hidden or minimized, activate */
620 if( isHidden() || isMinimized() )
621 toggleUpdateSystrayMenu();
623 /* Request the videoWidget */
624 WId ret = videoWidget->request( pi_x, pi_y,
625 pi_width, pi_height, !b_autoresize );
627 if( ret ) /* The videoWidget is available */
629 /* Consider the video active now */
632 /* Ask videoWidget to resize correctly, if we are in normal mode */
633 if( !isFullScreen() && !isMaximized() && b_autoresize )
634 videoWidget->SetSizing( *pi_width, *pi_height );
638 /* Asynchronous call from the WindowClose function */
639 void MainInterface::releaseVideo( void )
641 emit askReleaseVideo();
644 /* Function that is CONNECTED to the previous emit */
645 void MainInterface::releaseVideoSlot( void )
647 /* This function is called when the embedded video window is destroyed,
648 * or in the rare case that the embedded window is still here but the
649 * Qt4 interface exits. */
650 assert( videoWidget );
651 videoWidget->release();
652 setVideoOnTop( false );
653 setVideoFullScreen( false );
655 if( stackCentralW->currentWidget() == videoWidget )
656 restoreStackOldWidget();
658 /* We don't want to have a blank video to popup */
659 stackCentralOldWidget = bgWidget;
662 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
664 if( !isFullScreen() && !isMaximized() )
665 videoWidget->SetSizing( w, h );
668 void MainInterface::setVideoFullScreen( bool fs )
670 b_videoFullScreen = fs;
673 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
674 /* if user hasn't defined screennumber, or screennumber that is bigger
675 * than current number of screens, take screennumber where current interface
678 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
679 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
681 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
683 /* To be sure window is on proper-screen in xinerama */
684 if( !screenres.contains( pos() ) )
686 msg_Dbg( p_intf, "Moving video to correct screen");
687 move( QPoint( screenres.x(), screenres.y() ) );
689 setMinimalView( true );
690 setInterfaceFullScreen( true );
694 /* TODO do we want to restore screen and position ? (when
695 * qt-fullscreen-screennumber is forced) */
696 setMinimalView( b_minimalView );
697 setInterfaceFullScreen( b_interfaceFullScreen );
702 /* Slot to change the video always-on-top flag.
703 * Emit askVideoOnTop() to invoke this from other thread. */
704 void MainInterface::setVideoOnTop( bool on_top )
706 Qt::WindowFlags oldflags = windowFlags(), newflags;
709 newflags = oldflags | Qt::WindowStaysOnTopHint;
711 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
712 if( newflags != oldflags && !b_videoFullScreen )
715 setWindowFlags( newflags );
716 show(); /* necessary to apply window flags */
720 /* Asynchronous call from WindowControl function */
721 int MainInterface::controlVideo( int i_query, va_list args )
725 case VOUT_WINDOW_SET_SIZE:
727 unsigned int i_width = va_arg( args, unsigned int );
728 unsigned int i_height = va_arg( args, unsigned int );
730 emit askVideoToResize( i_width, i_height );
733 case VOUT_WINDOW_SET_STATE:
735 unsigned i_arg = va_arg( args, unsigned );
736 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
738 emit askVideoOnTop( on_top != 0 );
741 case VOUT_WINDOW_SET_FULLSCREEN:
743 bool b_fs = va_arg( args, int );
745 emit askVideoSetFullScreen( b_fs );
749 msg_Warn( p_intf, "unsupported control query" );
754 /*****************************************************************************
755 * Playlist, Visualisation and Menus handling
756 *****************************************************************************/
758 * Toggle the playlist widget or dialog
760 void MainInterface::createPlaylist()
762 playlistWidget = new PlaylistWidget( p_intf, this );
766 stackCentralW->addWidget( playlistWidget );
767 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
772 playlistWidget->setParent( NULL );
774 playlistWidget->setWindowFlags( Qt::Window );
776 /* This will restore the geometry but will not work for position,
777 because of parenting */
778 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
779 playlistWidget, QSize( 600, 300 ) );
783 void MainInterface::togglePlaylist()
785 if( !playlistWidget )
792 /* Playlist is not visible, show it */
793 if( stackCentralW->currentWidget() != playlistWidget )
795 showTab( playlistWidget );
799 restoreStackOldWidget();
801 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
806 playlistWidget->setParent( NULL );
808 playlistWidget->setWindowFlags( Qt::Window );
809 playlistVisible = !playlistVisible;
810 playlistWidget->setVisible( playlistVisible );
815 void MainInterface::dockPlaylist( bool p_docked )
817 if( b_plDocked == p_docked ) return;
818 b_plDocked = p_docked;
820 if( !playlistWidget ) return; /* Playlist wasn't created yet */
823 stackCentralW->removeWidget( playlistWidget );
825 playlistWidget->setParent( NULL );
827 playlistWidget->setWindowFlags( Qt::Window );
828 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
829 playlistWidget, QSize( 600, 300 ) );
830 playlistWidget->show();
831 restoreStackOldWidget();
835 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
836 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
837 // It would be logical that QStackWidget::addWidget reset the flags...
838 stackCentralW->addWidget( playlistWidget );
839 showTab( playlistWidget );
841 playlistVisible = true;
845 * setMinimalView is the private function used by
846 * the SLOT toggleMinimalView and setVideoFullScreen
848 void MainInterface::setMinimalView( bool b_minimal )
850 menuBar()->setVisible( !b_minimal );
851 controls->setVisible( !b_minimal );
852 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
853 inputC->setVisible( !b_minimal );
857 * This public SLOT is used for moving to minimal View Mode
859 * If b_minimal is false, then we are normalView
861 void MainInterface::toggleMinimalView( bool b_minimal )
863 if( !b_minimalView && b_autoresize ) /* Normal mode */
865 if( stackCentralW->currentWidget() == bgWidget )
867 if( stackCentralW->height() < 16 )
869 resizeStack( stackCentralW->width(), 100 );
873 b_minimalView = b_minimal;
874 if( !b_videoFullScreen )
876 setMinimalView( b_minimalView );
877 computeMinimumSize();
880 emit minimalViewToggled( b_minimalView );
883 /* toggling advanced controls buttons */
884 void MainInterface::toggleAdvancedButtons()
886 controls->toggleAdvanced();
887 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
890 /* Get the visibility status of the controls (hidden or not, advanced or not) */
891 int MainInterface::getControlsVisibilityStatus()
893 if( !controls ) return 0;
894 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
895 + CONTROLS_ADVANCED * controls->b_advancedVisible );
898 void MainInterface::setStatusBarVisibility( bool b_visible )
900 statusBar()->setVisible( b_visible );
901 b_statusbarVisible = b_visible;
902 if( controls ) controls->setGripVisible( !b_statusbarVisible );
906 void MainInterface::visual()
908 if( !VISIBLE( visualSelector) )
910 visualSelector->show();
911 if( !THEMIM->getIM()->hasVideo() )
913 /* Show the background widget */
915 visualSelectorEnabled = true;
919 /* Stop any currently running visualization */
920 visualSelector->hide();
921 visualSelectorEnabled = false;
926 /************************************************************************
928 ************************************************************************/
929 void MainInterface::setName( const QString& name )
931 input_name = name; /* store it for the QSystray use */
932 /* Display it in the status bar, but also as a Tooltip in case it doesn't
934 nameLabel->setText( name );
935 nameLabel->setToolTip( name );
939 * Give the decorations of the Main Window a correct Name.
940 * If nothing is given, set it to VLC...
942 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
944 if( aTitle.isEmpty() )
946 setWindowTitle( qtr( "VLC media player" ) );
950 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
954 void MainInterface::showCryptedLabel( bool b_show )
956 if( cryptedLabel == NULL )
958 cryptedLabel = new QLabel;
959 // The lock icon is not the right one for DRM protection/scrambled.
960 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
961 cryptedLabel->setText( "DRM" );
962 statusBar()->addWidget( cryptedLabel );
965 cryptedLabel->setVisible( b_show );
968 void MainInterface::showBuffering( float f_cache )
970 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
971 statusBar()->showMessage( amount, 1000 );
974 /*****************************************************************************
975 * Systray Icon and Systray Menu
976 *****************************************************************************/
979 * Create a SystemTray icon and a menu that would go with it.
980 * Connects to a click handler on the icon.
982 void MainInterface::createSystray()
985 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
986 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
988 iconVLC = QIcon( ":/logo/vlc128.png" );
989 sysTray = new QSystemTrayIcon( iconVLC, this );
990 sysTray->setToolTip( qtr( "VLC media player" ));
992 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
993 systrayMenu->setIcon( iconVLC );
995 QVLCMenu::updateSystrayMenu( this, p_intf, true );
998 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
999 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
1003 * Updates the Systray Icon's menu and toggle the main interface
1005 void MainInterface::toggleUpdateSystrayMenu()
1007 /* If hidden, show it */
1013 else if( isMinimized() )
1021 /* Visible (possibly under other windows) */
1023 /* check if any visible window is above vlc in the z-order,
1024 * but ignore the ones always on top
1025 * and the ones which can't be activated */
1028 wi.cbSize = sizeof( WINDOWINFO );
1029 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1030 hwnd && ( !IsWindowVisible( hwnd ) ||
1031 ( GetWindowInfo( hwnd, &wi ) &&
1032 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1033 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1034 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1035 (wi.dwExStyle&WS_EX_TOPMOST) )
1048 QVLCMenu::updateSystrayMenu( this, p_intf );
1051 /* First Item of the systray menu */
1052 void MainInterface::showUpdateSystrayMenu()
1060 QVLCMenu::updateSystrayMenu( this, p_intf );
1063 /* First Item of the systray menu */
1064 void MainInterface::hideUpdateSystrayMenu()
1067 QVLCMenu::updateSystrayMenu( this, p_intf );
1070 /* Click on systray Icon */
1071 void MainInterface::handleSystrayClick(
1072 QSystemTrayIcon::ActivationReason reason )
1076 case QSystemTrayIcon::Trigger:
1077 case QSystemTrayIcon::DoubleClick:
1079 QVLCMenu::updateSystrayMenu( this, p_intf );
1081 toggleUpdateSystrayMenu();
1084 case QSystemTrayIcon::MiddleClick:
1085 sysTray->showMessage( qtr( "VLC media player" ),
1086 qtr( "Control menu for the player" ),
1087 QSystemTrayIcon::Information, 3000 );
1095 * Updates the name of the systray Icon tooltip.
1096 * Doesn't check if the systray exists, check before you call it.
1098 void MainInterface::updateSystrayTooltipName( const QString& name )
1100 if( name.isEmpty() )
1102 sysTray->setToolTip( qtr( "VLC media player" ) );
1106 sysTray->setToolTip( name );
1107 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1109 sysTray->showMessage( qtr( "VLC media player" ), name,
1110 QSystemTrayIcon::NoIcon, 3000 );
1114 QVLCMenu::updateSystrayMenu( this, p_intf );
1118 * Updates the status of the systray Icon tooltip.
1119 * Doesn't check if the systray exists, check before you call it.
1121 void MainInterface::updateSystrayTooltipStatus( int i_status )
1126 sysTray->setToolTip( input_name );
1129 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1132 sysTray->setToolTip( qtr( "VLC media player" ) );
1135 QVLCMenu::updateSystrayMenu( this, p_intf );
1139 void MainInterface::changeEvent(QEvent *event)
1141 if( event->type() == QEvent::WindowStateChange )
1143 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1144 Qt::WindowStates newState = windowState();
1145 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1147 if( newState & Qt::WindowMinimized )
1149 b_hasPausedWhenMinimized = false;
1151 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1152 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1155 b_hasPausedWhenMinimized = true;
1159 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1161 if( b_hasPausedWhenMinimized )
1168 QWidget::changeEvent(event);
1171 /************************************************************************
1173 ************************************************************************/
1174 void MainInterface::dropEvent(QDropEvent *event)
1176 dropEventPlay( event, true );
1179 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1181 if( event->possibleActions() & Qt::CopyAction )
1182 event->setDropAction( Qt::CopyAction );
1186 const QMimeData *mimeData = event->mimeData();
1188 /* D&D of a subtitles file, add it on the fly */
1189 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1191 if( !input_AddSubtitle( THEMIM->getInput(),
1192 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1200 bool first = b_play;
1201 foreach( const QUrl &url, mimeData->urls() )
1205 QString mrl = toURI( url.toEncoded().constData() );
1206 playlist_Add( THEPL, qtu(mrl), NULL,
1207 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1208 PLAYLIST_END, true, pl_Unlocked );
1210 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1214 /* Browsers give content as text if you dnd the addressbar,
1215 so check if mimedata has valid url in text and use it
1216 if we didn't get any normal Urls()*/
1217 if( !mimeData->hasUrls() && mimeData->hasText() &&
1218 QUrl(mimeData->text()).isValid() )
1220 QString mrl = toURI( mimeData->text() );
1221 playlist_Add( THEPL, qtu(mrl), NULL,
1222 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1223 PLAYLIST_END, true, pl_Unlocked );
1227 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1229 event->acceptProposedAction();
1231 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1233 event->acceptProposedAction();
1235 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1240 /************************************************************************
1242 ************************************************************************/
1243 void MainInterface::keyPressEvent( QKeyEvent *e )
1245 handleKeyPress( e );
1248 void MainInterface::handleKeyPress( QKeyEvent *e )
1250 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1252 toggleMinimalView( !b_minimalView );
1256 int i_vlck = qtEventToVLCKey( e );
1259 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1266 void MainInterface::wheelEvent( QWheelEvent *e )
1268 int i_vlckey = qtWheelEventToVLCKey( e );
1269 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1273 void MainInterface::closeEvent( QCloseEvent *e )
1276 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1277 /* Accept session quit. Otherwise we break the desktop mamager. */
1281 void MainInterface::setInterfaceFullScreen( bool fs )
1284 setWindowState( windowState() | Qt::WindowFullScreen );
1286 setWindowState( windowState() & ~Qt::WindowFullScreen );
1288 void MainInterface::toggleInterfaceFullScreen()
1290 b_interfaceFullScreen = !b_interfaceFullScreen;
1291 if( !b_videoFullScreen )
1292 setInterfaceFullScreen( b_interfaceFullScreen );
1293 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1296 void MainInterface::emitBoss()
1300 void MainInterface::setBoss()
1315 /*****************************************************************************
1316 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1317 * We don't show the menu directly here because we don't want the
1318 * caller to block for a too long time.
1319 *****************************************************************************/
1320 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1321 vlc_value_t old_val, vlc_value_t new_val, void *param )
1323 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1325 intf_thread_t *p_intf = (intf_thread_t *)param;
1327 if( p_intf->pf_show_dialog )
1329 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1330 new_val.b_bool, NULL );
1336 /*****************************************************************************
1337 * IntfShowCB: callback triggered by the intf-show libvlc variable.
1338 *****************************************************************************/
1339 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1340 vlc_value_t old_val, vlc_value_t new_val, void *param )
1342 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1343 VLC_UNUSED( new_val );
1345 intf_thread_t *p_intf = (intf_thread_t *)param;
1346 p_intf->p_sys->p_mi->toggleFSC();
1352 /*****************************************************************************
1353 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1354 *****************************************************************************/
1355 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1356 vlc_value_t old_val, vlc_value_t new_val, void *param )
1358 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1359 VLC_UNUSED( new_val );
1361 intf_thread_t *p_intf = (intf_thread_t *)param;
1362 p_intf->p_sys->p_mi->emitBoss();