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 * Create the Systray Management *
143 *********************************/
146 /**************************
147 * UI and Widgets design
148 **************************/
149 setVLCWindowsTitle();
154 QVLCMenu::createMenuBar( this, p_intf );
155 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
156 this, destroyPopupMenu() );
158 createMainWidget( settings );
164 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
166 /********************
168 ********************/
169 MainInputManager::getInstance( p_intf );
174 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
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) )
1047 QVLCMenu::updateSystrayMenu( this, p_intf );
1050 void MainInterface::showUpdateSystrayMenu()
1058 QVLCMenu::updateSystrayMenu( this, p_intf );
1061 void MainInterface::hideUpdateSystrayMenu()
1064 QVLCMenu::updateSystrayMenu( this, p_intf );
1067 void MainInterface::handleSystrayClick(
1068 QSystemTrayIcon::ActivationReason reason )
1072 case QSystemTrayIcon::Trigger:
1073 case QSystemTrayIcon::DoubleClick:
1075 QVLCMenu::updateSystrayMenu( this, p_intf );
1077 toggleUpdateSystrayMenu();
1080 case QSystemTrayIcon::MiddleClick:
1081 sysTray->showMessage( qtr( "VLC media player" ),
1082 qtr( "Control menu for the player" ),
1083 QSystemTrayIcon::Information, 3000 );
1091 * Updates the name of the systray Icon tooltip.
1092 * Doesn't check if the systray exists, check before you call it.
1094 void MainInterface::updateSystrayTooltipName( const QString& name )
1096 if( name.isEmpty() )
1098 sysTray->setToolTip( qtr( "VLC media player" ) );
1102 sysTray->setToolTip( name );
1103 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1105 sysTray->showMessage( qtr( "VLC media player" ), name,
1106 QSystemTrayIcon::NoIcon, 3000 );
1110 QVLCMenu::updateSystrayMenu( this, p_intf );
1114 * Updates the status of the systray Icon tooltip.
1115 * Doesn't check if the systray exists, check before you call it.
1117 void MainInterface::updateSystrayTooltipStatus( int i_status )
1122 sysTray->setToolTip( input_name );
1125 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1128 sysTray->setToolTip( qtr( "VLC media player" ) );
1131 QVLCMenu::updateSystrayMenu( this, p_intf );
1135 void MainInterface::changeEvent(QEvent *event)
1137 if( event->type() == QEvent::WindowStateChange )
1139 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1140 Qt::WindowStates newState = windowState();
1141 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1143 if( newState & Qt::WindowMinimized )
1145 b_hasPausedWhenMinimized = false;
1147 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1148 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1151 b_hasPausedWhenMinimized = true;
1155 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1157 if( b_hasPausedWhenMinimized )
1164 QWidget::changeEvent(event);
1167 /************************************************************************
1169 ************************************************************************/
1170 void MainInterface::dropEvent(QDropEvent *event)
1172 dropEventPlay( event, true );
1175 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1177 if( event->possibleActions() & Qt::CopyAction )
1178 event->setDropAction( Qt::CopyAction );
1182 const QMimeData *mimeData = event->mimeData();
1184 /* D&D of a subtitles file, add it on the fly */
1185 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1187 if( !input_AddSubtitle( THEMIM->getInput(),
1188 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1196 bool first = b_play;
1197 foreach( const QUrl &url, mimeData->urls() )
1201 QString mrl = toURI( url.toEncoded().constData() );
1202 playlist_Add( THEPL, qtu(mrl), NULL,
1203 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1204 PLAYLIST_END, true, pl_Unlocked );
1206 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1210 /* Browsers give content as text if you dnd the addressbar,
1211 so check if mimedata has valid url in text and use it
1212 if we didn't get any normal Urls()*/
1213 if( !mimeData->hasUrls() && mimeData->hasText() &&
1214 QUrl(mimeData->text()).isValid() )
1216 QString mrl = toURI( mimeData->text() );
1217 playlist_Add( THEPL, qtu(mrl), NULL,
1218 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1219 PLAYLIST_END, true, pl_Unlocked );
1223 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1225 event->acceptProposedAction();
1227 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1229 event->acceptProposedAction();
1231 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1236 /************************************************************************
1238 ************************************************************************/
1239 void MainInterface::keyPressEvent( QKeyEvent *e )
1241 handleKeyPress( e );
1244 void MainInterface::handleKeyPress( QKeyEvent *e )
1246 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1248 toggleMinimalView( !b_minimalView );
1252 int i_vlck = qtEventToVLCKey( e );
1255 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1262 void MainInterface::wheelEvent( QWheelEvent *e )
1264 int i_vlckey = qtWheelEventToVLCKey( e );
1265 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1269 void MainInterface::closeEvent( QCloseEvent *e )
1272 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1273 /* Accept session quit. Otherwise we break the desktop mamager. */
1277 void MainInterface::setInterfaceFullScreen( bool fs )
1280 setWindowState( windowState() | Qt::WindowFullScreen );
1282 setWindowState( windowState() & ~Qt::WindowFullScreen );
1284 void MainInterface::toggleInterfaceFullScreen()
1286 b_interfaceFullScreen = !b_interfaceFullScreen;
1287 if( !b_videoFullScreen )
1288 setInterfaceFullScreen( b_interfaceFullScreen );
1289 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1292 void MainInterface::emitBoss()
1296 void MainInterface::setBoss()
1311 /*****************************************************************************
1312 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1313 * We don't show the menu directly here because we don't want the
1314 * caller to block for a too long time.
1315 *****************************************************************************/
1316 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1317 vlc_value_t old_val, vlc_value_t new_val, void *param )
1319 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1321 intf_thread_t *p_intf = (intf_thread_t *)param;
1323 if( p_intf->pf_show_dialog )
1325 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1326 new_val.b_bool, NULL );
1332 /*****************************************************************************
1333 * IntfShowCB: callback triggered by the intf-show libvlc variable.
1334 *****************************************************************************/
1335 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1336 vlc_value_t old_val, vlc_value_t new_val, void *param )
1338 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1339 VLC_UNUSED( new_val );
1341 intf_thread_t *p_intf = (intf_thread_t *)param;
1342 p_intf->p_sys->p_mi->toggleFSC();
1348 /*****************************************************************************
1349 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1350 *****************************************************************************/
1351 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1352 vlc_value_t old_val, vlc_value_t new_val, void *param )
1354 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1355 VLC_UNUSED( new_val );
1357 intf_thread_t *p_intf = (intf_thread_t *)param;
1358 p_intf->p_sys->p_mi->emitBoss();