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;
99 FirstRun::CheckAndRun( this, p_intf );
102 * Configuration and settings
103 * Pre-building of interface
106 setFocusPolicy( Qt::StrongFocus );
107 setAcceptDrops( true );
108 setWindowRole( "vlc-main" );
109 setWindowIcon( QApplication::windowIcon() );
110 setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
112 setAttribute( Qt::WA_MacBrushedMetal );
115 /* Is video in embedded in the UI or not */
116 b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
118 /* Does the interface resize to video size or the opposite */
119 b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
121 /* Are we in the enhanced always-video mode or not ? */
122 b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
124 /* Do we want anoying popups or not */
125 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
128 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
130 /* Set the other interface settings */
131 settings = getSettings();
132 settings->beginGroup( "MainWindow" );
136 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
140 b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
142 settings->endGroup( );
144 /**************************
145 * UI and Widgets design
146 **************************/
147 setVLCWindowsTitle();
152 QVLCMenu::createMenuBar( this, p_intf );
153 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
154 this, destroyPopupMenu() );
156 createMainWidget( settings );
162 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
164 /********************
166 ********************/
167 MainInputManager::getInstance( p_intf );
172 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
175 /*********************************
176 * Create the Systray Management *
177 *********************************/
180 /*************************************************************
181 * Connect the input manager to the GUI elements it manages *
182 * Beware initSystray did some connects on input manager too *
183 *************************************************************/
185 * Connects on nameChanged()
186 * Those connects are different because options can impeach them to trigger.
188 /* Main Interface statusbar */
189 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
190 this, setName( const QString& ) );
191 /* and title of the Main Interface*/
192 if( var_InheritBool( p_intf, "qt-name-in-title" ) )
194 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
195 this, setVLCWindowsTitle( const QString& ) );
197 /* END CONNECTS ON IM */
199 /* VideoWidget connects for asynchronous calls */
200 b_videoFullScreen = false;
201 connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
202 this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
203 Qt::BlockingQueuedConnection );
204 connect( this, SIGNAL(askReleaseVideo( void )),
205 this, SLOT(releaseVideoSlot( void )),
206 Qt::BlockingQueuedConnection );
207 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
213 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
214 this, setVideoSize( unsigned int, unsigned int ) );
215 CONNECT( videoWidget, sizeChanged( int, int ),
216 this, resizeStack( int, int ) );
218 CONNECT( this, askVideoSetFullScreen( bool ),
219 this, setVideoFullScreen( bool ) );
222 CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
224 CONNECT( this, askToQuit(), THEDP, quit() );
226 CONNECT( this, askBoss(), this, setBoss() );
227 CONNECT( this, askRaise(), this, setRaise() );
229 /** END of CONNECTS**/
235 var_AddCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
236 var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
237 var_AddCallback( p_intf->p_libvlc,"intf-show", IntfRaiseMainCB, p_intf );
239 /* Register callback for the intf-popupmenu variable */
240 var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
243 int i_plVis = settings->value( "MainWindow/playlist-visible", false ).toBool();
245 if( i_plVis ) togglePlaylist();
247 /**** FINAL SIZING and placement of interface */
248 settings->beginGroup( "MainWindow" );
249 QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
250 settings->endGroup();
252 b_interfaceFullScreen = isFullScreen();
254 /* Final sizing and showing */
255 setVisible( !b_hideAfterCreation );
257 computeMinimumSize();
259 /* Switch to minimal view if needed, must be called after the show() */
261 toggleMinimalView( true );
263 b_hasPausedWhenMinimized = false;
266 MainInterface::~MainInterface()
268 /* Unsure we hide the videoWidget before destroying it */
269 if( stackCentralOldWidget == videoWidget )
277 ImageList_Destroy( himl );
279 p_taskbl->vt->Release(p_taskbl);
283 /* Be sure to kill the actionsManager... Only used in the MI and control */
284 ActionsManager::killInstance();
287 ExtensionsManager::killInstance();
289 /* Delete the FSC controller */
290 delete fullscreenControls;
293 settings->beginGroup( "MainWindow" );
295 settings->setValue( "pl-dock-status", b_plDocked );
296 /* Save playlist state */
298 settings->setValue( "playlist-visible", playlistVisible );
300 settings->setValue( "adv-controls",
301 getControlsVisibilityStatus() & CONTROLS_ADVANCED );
302 settings->setValue( "status-bar-visible", b_statusbarVisible );
304 /* Save the stackCentralW sizes */
305 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
306 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
309 QVLCTools::saveWidgetPosition(settings, this);
311 settings->endGroup();
313 /* Save undocked playlist size */
314 if( playlistWidget && !isPlDocked() )
315 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
317 delete playlistWidget;
321 /* Unregister callbacks */
322 var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
323 var_DelCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
324 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
326 p_intf->p_sys->p_mi = NULL;
329 void MainInterface::computeMinimumSize()
332 if( menuBar()->isVisible() )
333 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
335 setMinimumWidth( minWidth );
338 /*****************************
340 *****************************/
341 void MainInterface::recreateToolbars()
343 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
345 settings->beginGroup( "MainWindow" );
349 controls = new ControlsWidget( p_intf, b_adv, this );
350 inputC = new InputControlsWidget( p_intf, this );
352 if( fullscreenControls )
354 delete fullscreenControls;
355 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
356 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
357 this, handleKeyPress( QKeyEvent * ) );
359 mainLayout->insertWidget( 2, inputC );
360 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
362 settings->endGroup();
365 void MainInterface::reloadPrefs()
367 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
368 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
370 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
372 if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
374 delete fullscreenControls;
375 fullscreenControls = NULL;
379 void MainInterface::createMainWidget( QSettings *settings )
381 /* Create the main Widget and the mainLayout */
382 QWidget *main = new QWidget;
383 setCentralWidget( main );
384 mainLayout = new QVBoxLayout( main );
385 main->setContentsMargins( 0, 0, 0, 0 );
386 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
389 stackCentralW = new QVLCStackedWidget( main );
392 bgWidget = new BackgroundWidget( p_intf );
393 stackCentralW->addWidget( bgWidget );
394 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
395 bgWidget->setWithArt( false );
397 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
398 bgWidget->setExpandstoHeight( true );
400 /* And video Outputs */
401 if( b_videoEmbedded )
403 videoWidget = new VideoWidget( p_intf );
404 stackCentralW->addWidget( videoWidget );
406 mainLayout->insertWidget( 1, stackCentralW );
408 settings->beginGroup( "MainWindow" );
409 stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 600, 0 ) ).toSize();
410 /* Resize even if no-auto-resize, because we are at creation */
411 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
413 /* Create the CONTROLS Widget */
414 controls = new ControlsWidget( p_intf,
415 settings->value( "adv-controls", false ).toBool(), this );
416 inputC = new InputControlsWidget( p_intf, this );
418 mainLayout->insertWidget( 2, inputC );
419 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
422 /* Visualisation, disabled for now, they SUCK */
424 visualSelector = new VisualSelector( p_intf );
425 mainLayout->insertWidget( 0, visualSelector );
426 visualSelector->hide();
429 settings->endGroup();
431 /* Enable the popup menu in the MI */
432 main->setContextMenuPolicy( Qt::CustomContextMenu );
433 CONNECT( main, customContextMenuRequested( const QPoint& ),
434 this, popupMenu( const QPoint& ) );
436 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
437 /* Create the FULLSCREEN CONTROLS Widget */
438 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
440 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
441 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
442 this, handleKeyPress( QKeyEvent * ) );
446 inline void MainInterface::initSystray()
449 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
450 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
452 if( var_InheritBool( p_intf, "qt-start-minimized") )
454 if( b_systrayAvailable )
456 b_systrayWanted = true;
457 b_hideAfterCreation = true;
460 msg_Err( p_intf, "cannot start minimized without system tray bar" );
463 if( b_systrayAvailable && b_systrayWanted )
468 inline void MainInterface::createStatusBar()
473 /* Widgets Creation*/
474 QStatusBar *statusBarr = statusBar();
476 TimeLabel *timeLabel = new TimeLabel( p_intf );
477 nameLabel = new QLabel( this );
478 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
479 | Qt::TextSelectableByKeyboard );
480 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
482 /* Styling those labels */
483 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
484 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
485 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
486 timeLabel->setStyleSheet(
487 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
488 speedLabel->setStyleSheet(
489 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
490 /* pad both label and its tooltip */
491 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
493 /* and adding those */
494 statusBarr->addWidget( nameLabel, 8 );
495 statusBarr->addPermanentWidget( speedLabel, 0 );
496 statusBarr->addPermanentWidget( timeLabel, 0 );
498 /* timeLabel behaviour:
499 - double clicking opens the goto time dialog
500 - right-clicking and clicking just toggle between remaining and
502 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
504 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
505 this, showCryptedLabel( bool ) );
507 CONNECT( THEMIM->getIM(), seekRequested( float ),
508 timeLabel, setDisplayPosition( float ) );
510 /* This shouldn't be necessary, but for somehow reason, the statusBarr
511 starts at height of 20px and when a text is shown it needs more space.
512 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
513 geometry, we need to force a height. If you have a better idea, please
516 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
519 /**********************************************************************
520 * Handling of sizing of the components
521 **********************************************************************/
523 void MainInterface::debug()
526 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
527 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
528 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
530 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
531 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
532 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
536 inline void MainInterface::showVideo() { showTab( videoWidget ); }
537 inline void MainInterface::restoreStackOldWidget()
538 { showTab( stackCentralOldWidget ); }
540 inline void MainInterface::showTab( QWidget *widget )
543 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
546 stackCentralOldWidget = stackCentralW->currentWidget();
547 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
549 stackCentralW->setCurrentWidget( widget );
551 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
554 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
555 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
559 void MainInterface::destroyPopupMenu()
561 QVLCMenu::PopupMenu( p_intf, false );
564 void MainInterface::popupMenu( const QPoint & )
566 QVLCMenu::PopupMenu( p_intf, true );
569 void MainInterface::toggleFSC()
571 if( !fullscreenControls ) return;
573 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
574 QApplication::postEvent( fullscreenControls, eShow );
577 /****************************************************************************
579 ****************************************************************************/
583 * You must not change the state of this object or other Qt4 UI objects,
584 * from the video output thread - only from the Qt4 UI main loop thread.
585 * All window provider queries must be handled through signals or events.
586 * That's why we have all those emit statements...
588 WId MainInterface::getVideo( int *pi_x, int *pi_y,
589 unsigned int *pi_width, unsigned int *pi_height )
594 /* This is a blocking call signal. Results are returned through pointers.
595 * Beware of deadlocks! */
597 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
601 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
602 unsigned *pi_width, unsigned *pi_height )
604 /* Hidden or minimized, activate */
605 if( isHidden() || isMinimized() )
606 toggleUpdateSystrayMenu();
608 /* Request the videoWidget */
609 WId ret = videoWidget->request( pi_x, pi_y,
610 pi_width, pi_height, !b_autoresize );
612 if( ret ) /* The videoWidget is available */
614 /* Consider the video active now */
617 /* Ask videoWidget to resize correctly, if we are in normal mode */
618 if( !isFullScreen() && !isMaximized() && b_autoresize )
619 videoWidget->SetSizing( *pi_width, *pi_height );
623 /* Asynchronous call from the WindowClose function */
624 void MainInterface::releaseVideo( void )
626 emit askReleaseVideo();
629 /* Function that is CONNECTED to the previous emit */
630 void MainInterface::releaseVideoSlot( void )
632 /* This function is called when the embedded video window is destroyed,
633 * or in the rare case that the embedded window is still here but the
634 * Qt4 interface exits. */
635 assert( videoWidget );
636 videoWidget->release();
637 setVideoOnTop( false );
638 setVideoFullScreen( false );
640 if( stackCentralW->currentWidget() == videoWidget )
641 restoreStackOldWidget();
643 /* We don't want to have a blank video to popup */
644 stackCentralOldWidget = bgWidget;
647 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
649 if( !isFullScreen() && !isMaximized() )
650 videoWidget->SetSizing( w, h );
653 void MainInterface::setVideoFullScreen( bool fs )
655 b_videoFullScreen = fs;
658 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
659 /* if user hasn't defined screennumber, or screennumber that is bigger
660 * than current number of screens, take screennumber where current interface
663 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
664 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
666 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
668 /* To be sure window is on proper-screen in xinerama */
669 if( !screenres.contains( pos() ) )
671 msg_Dbg( p_intf, "Moving video to correct screen");
672 move( QPoint( screenres.x(), screenres.y() ) );
674 setMinimalView( true );
675 setInterfaceFullScreen( true );
679 /* TODO do we want to restore screen and position ? (when
680 * qt-fullscreen-screennumber is forced) */
681 setMinimalView( b_minimalView );
682 setInterfaceFullScreen( b_interfaceFullScreen );
687 /* Slot to change the video always-on-top flag.
688 * Emit askVideoOnTop() to invoke this from other thread. */
689 void MainInterface::setVideoOnTop( bool on_top )
691 Qt::WindowFlags oldflags = windowFlags(), newflags;
694 newflags = oldflags | Qt::WindowStaysOnTopHint;
696 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
697 if( newflags != oldflags && !b_videoFullScreen )
700 setWindowFlags( newflags );
701 show(); /* necessary to apply window flags */
705 /* Asynchronous call from WindowControl function */
706 int MainInterface::controlVideo( int i_query, va_list args )
710 case VOUT_WINDOW_SET_SIZE:
712 unsigned int i_width = va_arg( args, unsigned int );
713 unsigned int i_height = va_arg( args, unsigned int );
715 emit askVideoToResize( i_width, i_height );
718 case VOUT_WINDOW_SET_STATE:
720 unsigned i_arg = va_arg( args, unsigned );
721 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
723 emit askVideoOnTop( on_top != 0 );
726 case VOUT_WINDOW_SET_FULLSCREEN:
728 bool b_fs = va_arg( args, int );
730 emit askVideoSetFullScreen( b_fs );
734 msg_Warn( p_intf, "unsupported control query" );
739 /*****************************************************************************
740 * Playlist, Visualisation and Menus handling
741 *****************************************************************************/
743 * Toggle the playlist widget or dialog
745 void MainInterface::createPlaylist()
747 playlistWidget = new PlaylistWidget( p_intf, this );
751 stackCentralW->addWidget( playlistWidget );
752 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
757 playlistWidget->setParent( NULL );
759 playlistWidget->setWindowFlags( Qt::Window );
761 /* This will restore the geometry but will not work for position,
762 because of parenting */
763 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
764 playlistWidget, QSize( 600, 300 ) );
768 void MainInterface::togglePlaylist()
770 if( !playlistWidget )
777 /* Playlist is not visible, show it */
778 if( stackCentralW->currentWidget() != playlistWidget )
780 showTab( playlistWidget );
784 restoreStackOldWidget();
786 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
791 playlistWidget->setParent( NULL );
793 playlistWidget->setWindowFlags( Qt::Window );
794 playlistVisible = !playlistVisible;
795 playlistWidget->setVisible( playlistVisible );
800 void MainInterface::dockPlaylist( bool p_docked )
802 if( b_plDocked == p_docked ) return;
803 b_plDocked = p_docked;
805 if( !playlistWidget ) return; /* Playlist wasn't created yet */
808 stackCentralW->removeWidget( playlistWidget );
810 playlistWidget->setParent( NULL );
812 playlistWidget->setWindowFlags( Qt::Window );
813 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
814 playlistWidget, QSize( 600, 300 ) );
815 playlistWidget->show();
816 restoreStackOldWidget();
820 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
821 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
822 // It would be logical that QStackWidget::addWidget reset the flags...
823 stackCentralW->addWidget( playlistWidget );
824 showTab( playlistWidget );
826 playlistVisible = true;
830 * setMinimalView is the private function used by
831 * the SLOT toggleMinimalView and setVideoFullScreen
833 void MainInterface::setMinimalView( bool b_minimal )
835 menuBar()->setVisible( !b_minimal );
836 controls->setVisible( !b_minimal );
837 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
838 inputC->setVisible( !b_minimal );
842 * This public SLOT is used for moving to minimal View Mode
844 * If b_minimal is false, then we are normalView
846 void MainInterface::toggleMinimalView( bool b_minimal )
848 if( !b_minimalView && b_autoresize ) /* Normal mode */
850 if( stackCentralW->currentWidget() == bgWidget )
852 if( stackCentralW->height() < 16 )
854 resizeStack( stackCentralW->width(), 100 );
858 b_minimalView = b_minimal;
859 if( !b_videoFullScreen )
861 setMinimalView( b_minimalView );
862 computeMinimumSize();
865 emit minimalViewToggled( b_minimalView );
868 /* toggling advanced controls buttons */
869 void MainInterface::toggleAdvancedButtons()
871 controls->toggleAdvanced();
872 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
875 /* Get the visibility status of the controls (hidden or not, advanced or not) */
876 int MainInterface::getControlsVisibilityStatus()
878 if( !controls ) return 0;
879 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
880 + CONTROLS_ADVANCED * controls->b_advancedVisible );
883 void MainInterface::setStatusBarVisibility( bool b_visible )
885 statusBar()->setVisible( b_visible );
886 b_statusbarVisible = b_visible;
887 if( controls ) controls->setGripVisible( !b_statusbarVisible );
891 void MainInterface::visual()
893 if( !VISIBLE( visualSelector) )
895 visualSelector->show();
896 if( !THEMIM->getIM()->hasVideo() )
898 /* Show the background widget */
900 visualSelectorEnabled = true;
904 /* Stop any currently running visualization */
905 visualSelector->hide();
906 visualSelectorEnabled = false;
911 /************************************************************************
913 ************************************************************************/
914 void MainInterface::setName( const QString& name )
916 input_name = name; /* store it for the QSystray use */
917 /* Display it in the status bar, but also as a Tooltip in case it doesn't
919 nameLabel->setText( name );
920 nameLabel->setToolTip( name );
924 * Give the decorations of the Main Window a correct Name.
925 * If nothing is given, set it to VLC...
927 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
929 if( aTitle.isEmpty() )
931 setWindowTitle( qtr( "VLC media player" ) );
935 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
939 void MainInterface::showCryptedLabel( bool b_show )
941 if( cryptedLabel == NULL )
943 cryptedLabel = new QLabel;
944 // The lock icon is not the right one for DRM protection/scrambled.
945 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
946 cryptedLabel->setText( "DRM" );
947 statusBar()->addWidget( cryptedLabel );
950 cryptedLabel->setVisible( b_show );
953 void MainInterface::showBuffering( float f_cache )
955 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
956 statusBar()->showMessage( amount, 1000 );
959 /*****************************************************************************
960 * Systray Icon and Systray Menu
961 *****************************************************************************/
964 * Create a SystemTray icon and a menu that would go with it.
965 * Connects to a click handler on the icon.
967 void MainInterface::createSystray()
970 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
971 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
973 iconVLC = QIcon( ":/logo/vlc128.png" );
974 sysTray = new QSystemTrayIcon( iconVLC, this );
975 sysTray->setToolTip( qtr( "VLC media player" ));
977 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
978 systrayMenu->setIcon( iconVLC );
980 QVLCMenu::updateSystrayMenu( this, p_intf, true );
983 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
984 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
986 /* Connects on nameChanged() */
987 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
988 this, updateSystrayTooltipName( const QString& ) );
989 /* Connect PLAY_STATUS on the systray */
990 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
991 this, updateSystrayTooltipStatus( int ) );
995 * Updates the Systray Icon's menu and toggle the main interface
997 void MainInterface::toggleUpdateSystrayMenu()
999 /* If hidden, show it */
1005 else if( isMinimized() )
1013 /* Visible (possibly under other windows) */
1015 /* check if any visible window is above vlc in the z-order,
1016 * but ignore the ones always on top
1017 * and the ones which can't be activated */
1020 wi.cbSize = sizeof( WINDOWINFO );
1021 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1022 hwnd && ( !IsWindowVisible( hwnd ) ||
1023 ( GetWindowInfo( hwnd, &wi ) &&
1024 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1025 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1026 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1027 (wi.dwExStyle&WS_EX_TOPMOST) )
1040 QVLCMenu::updateSystrayMenu( this, p_intf );
1043 /* First Item of the systray menu */
1044 void MainInterface::showUpdateSystrayMenu()
1052 QVLCMenu::updateSystrayMenu( this, p_intf );
1055 /* First Item of the systray menu */
1056 void MainInterface::hideUpdateSystrayMenu()
1059 QVLCMenu::updateSystrayMenu( this, p_intf );
1062 /* Click on systray Icon */
1063 void MainInterface::handleSystrayClick(
1064 QSystemTrayIcon::ActivationReason reason )
1068 case QSystemTrayIcon::Trigger:
1069 case QSystemTrayIcon::DoubleClick:
1071 QVLCMenu::updateSystrayMenu( this, p_intf );
1073 toggleUpdateSystrayMenu();
1076 case QSystemTrayIcon::MiddleClick:
1077 sysTray->showMessage( qtr( "VLC media player" ),
1078 qtr( "Control menu for the player" ),
1079 QSystemTrayIcon::Information, 3000 );
1087 * Updates the name of the systray Icon tooltip.
1088 * Doesn't check if the systray exists, check before you call it.
1090 void MainInterface::updateSystrayTooltipName( const QString& name )
1092 if( name.isEmpty() )
1094 sysTray->setToolTip( qtr( "VLC media player" ) );
1098 sysTray->setToolTip( name );
1099 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1101 sysTray->showMessage( qtr( "VLC media player" ), name,
1102 QSystemTrayIcon::NoIcon, 3000 );
1106 QVLCMenu::updateSystrayMenu( this, p_intf );
1110 * Updates the status of the systray Icon tooltip.
1111 * Doesn't check if the systray exists, check before you call it.
1113 void MainInterface::updateSystrayTooltipStatus( int i_status )
1118 sysTray->setToolTip( input_name );
1121 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1124 sysTray->setToolTip( qtr( "VLC media player" ) );
1127 QVLCMenu::updateSystrayMenu( this, p_intf );
1131 void MainInterface::changeEvent(QEvent *event)
1133 if( event->type() == QEvent::WindowStateChange )
1135 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1136 Qt::WindowStates newState = windowState();
1137 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1139 if( newState & Qt::WindowMinimized )
1141 b_hasPausedWhenMinimized = false;
1143 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1144 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1147 b_hasPausedWhenMinimized = true;
1151 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1153 if( b_hasPausedWhenMinimized )
1160 QWidget::changeEvent(event);
1163 /************************************************************************
1165 ************************************************************************/
1166 void MainInterface::dropEvent(QDropEvent *event)
1168 dropEventPlay( event, true );
1171 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1173 if( event->possibleActions() & Qt::CopyAction )
1174 event->setDropAction( Qt::CopyAction );
1178 const QMimeData *mimeData = event->mimeData();
1180 /* D&D of a subtitles file, add it on the fly */
1181 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1183 if( !input_AddSubtitle( THEMIM->getInput(),
1184 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1192 bool first = b_play;
1193 foreach( const QUrl &url, mimeData->urls() )
1197 QString mrl = toURI( url.toEncoded().constData() );
1198 playlist_Add( THEPL, qtu(mrl), NULL,
1199 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1200 PLAYLIST_END, true, pl_Unlocked );
1202 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1206 /* Browsers give content as text if you dnd the addressbar,
1207 so check if mimedata has valid url in text and use it
1208 if we didn't get any normal Urls()*/
1209 if( !mimeData->hasUrls() && mimeData->hasText() &&
1210 QUrl(mimeData->text()).isValid() )
1212 QString mrl = toURI( mimeData->text() );
1213 playlist_Add( THEPL, qtu(mrl), NULL,
1214 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1215 PLAYLIST_END, true, pl_Unlocked );
1219 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1221 event->acceptProposedAction();
1223 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1225 event->acceptProposedAction();
1227 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1232 /************************************************************************
1234 ************************************************************************/
1235 void MainInterface::keyPressEvent( QKeyEvent *e )
1237 handleKeyPress( e );
1240 void MainInterface::handleKeyPress( QKeyEvent *e )
1242 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1244 toggleMinimalView( !b_minimalView );
1248 int i_vlck = qtEventToVLCKey( e );
1251 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1258 void MainInterface::wheelEvent( QWheelEvent *e )
1260 int i_vlckey = qtWheelEventToVLCKey( e );
1261 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1265 void MainInterface::closeEvent( QCloseEvent *e )
1268 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1269 /* Accept session quit. Otherwise we break the desktop mamager. */
1273 void MainInterface::setInterfaceFullScreen( bool fs )
1276 setWindowState( windowState() | Qt::WindowFullScreen );
1278 setWindowState( windowState() & ~Qt::WindowFullScreen );
1280 void MainInterface::toggleInterfaceFullScreen()
1282 b_interfaceFullScreen = !b_interfaceFullScreen;
1283 if( !b_videoFullScreen )
1284 setInterfaceFullScreen( b_interfaceFullScreen );
1285 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1288 void MainInterface::emitBoss()
1292 void MainInterface::setBoss()
1307 void MainInterface::emitRaise()
1311 void MainInterface::setRaise()
1317 /*****************************************************************************
1318 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1319 * We don't show the menu directly here because we don't want the
1320 * caller to block for a too long time.
1321 *****************************************************************************/
1322 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1323 vlc_value_t old_val, vlc_value_t new_val, void *param )
1325 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1327 intf_thread_t *p_intf = (intf_thread_t *)param;
1329 if( p_intf->pf_show_dialog )
1331 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1332 new_val.b_bool, NULL );
1338 /*****************************************************************************
1339 * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1340 *****************************************************************************/
1341 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1342 vlc_value_t old_val, vlc_value_t new_val, void *param )
1344 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1345 VLC_UNUSED( new_val );
1347 intf_thread_t *p_intf = (intf_thread_t *)param;
1348 p_intf->p_sys->p_mi->toggleFSC();
1354 /*****************************************************************************
1355 * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1356 *****************************************************************************/
1357 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
1358 vlc_value_t old_val, vlc_value_t new_val, void *param )
1360 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1361 VLC_UNUSED( new_val );
1363 intf_thread_t *p_intf = (intf_thread_t *)param;
1364 p_intf->p_sys->p_mi->emitRaise();
1369 /*****************************************************************************
1370 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1371 *****************************************************************************/
1372 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1373 vlc_value_t old_val, vlc_value_t new_val, void *param )
1375 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1376 VLC_UNUSED( new_val );
1378 intf_thread_t *p_intf = (intf_thread_t *)param;
1379 p_intf->p_sys->p_mi->emitBoss();