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-show", IntfRaiseMainCB, p_intf );
324 var_DelCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
325 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
327 p_intf->p_sys->p_mi = NULL;
330 void MainInterface::computeMinimumSize()
333 if( menuBar()->isVisible() )
334 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
336 setMinimumWidth( minWidth );
339 /*****************************
341 *****************************/
342 void MainInterface::recreateToolbars()
344 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
346 settings->beginGroup( "MainWindow" );
350 controls = new ControlsWidget( p_intf, b_adv, this );
351 inputC = new InputControlsWidget( p_intf, this );
353 if( fullscreenControls )
355 delete fullscreenControls;
356 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
357 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
358 this, handleKeyPress( QKeyEvent * ) );
360 mainLayout->insertWidget( 2, inputC );
361 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
363 settings->endGroup();
366 void MainInterface::reloadPrefs()
368 b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
369 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
371 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
373 if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
375 delete fullscreenControls;
376 fullscreenControls = NULL;
380 void MainInterface::createMainWidget( QSettings *settings )
382 /* Create the main Widget and the mainLayout */
383 QWidget *main = new QWidget;
384 setCentralWidget( main );
385 mainLayout = new QVBoxLayout( main );
386 main->setContentsMargins( 0, 0, 0, 0 );
387 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
390 stackCentralW = new QVLCStackedWidget( main );
393 bgWidget = new BackgroundWidget( p_intf );
394 stackCentralW->addWidget( bgWidget );
395 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
396 bgWidget->setWithArt( false );
398 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
399 bgWidget->setExpandstoHeight( true );
401 /* And video Outputs */
402 if( b_videoEmbedded )
404 videoWidget = new VideoWidget( p_intf );
405 stackCentralW->addWidget( videoWidget );
407 mainLayout->insertWidget( 1, stackCentralW );
409 settings->beginGroup( "MainWindow" );
410 stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 600, 0 ) ).toSize();
411 /* Resize even if no-auto-resize, because we are at creation */
412 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
414 /* Create the CONTROLS Widget */
415 controls = new ControlsWidget( p_intf,
416 settings->value( "adv-controls", false ).toBool(), this );
417 inputC = new InputControlsWidget( p_intf, this );
419 mainLayout->insertWidget( 2, inputC );
420 mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
423 /* Visualisation, disabled for now, they SUCK */
425 visualSelector = new VisualSelector( p_intf );
426 mainLayout->insertWidget( 0, visualSelector );
427 visualSelector->hide();
430 settings->endGroup();
432 /* Enable the popup menu in the MI */
433 main->setContextMenuPolicy( Qt::CustomContextMenu );
434 CONNECT( main, customContextMenuRequested( const QPoint& ),
435 this, popupMenu( const QPoint& ) );
437 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
438 /* Create the FULLSCREEN CONTROLS Widget */
439 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
441 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
442 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
443 this, handleKeyPress( QKeyEvent * ) );
447 inline void MainInterface::initSystray()
450 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
451 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
453 if( var_InheritBool( p_intf, "qt-start-minimized") )
455 if( b_systrayAvailable )
457 b_systrayWanted = true;
458 b_hideAfterCreation = true;
461 msg_Err( p_intf, "cannot start minimized without system tray bar" );
464 if( b_systrayAvailable && b_systrayWanted )
469 inline void MainInterface::createStatusBar()
474 /* Widgets Creation*/
475 QStatusBar *statusBarr = statusBar();
477 TimeLabel *timeLabel = new TimeLabel( p_intf );
478 nameLabel = new QLabel( this );
479 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
480 | Qt::TextSelectableByKeyboard );
481 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
483 /* Styling those labels */
484 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
485 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
486 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
487 timeLabel->setStyleSheet(
488 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
489 speedLabel->setStyleSheet(
490 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
491 /* pad both label and its tooltip */
492 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
494 /* and adding those */
495 statusBarr->addWidget( nameLabel, 8 );
496 statusBarr->addPermanentWidget( speedLabel, 0 );
497 statusBarr->addPermanentWidget( timeLabel, 0 );
499 /* timeLabel behaviour:
500 - double clicking opens the goto time dialog
501 - right-clicking and clicking just toggle between remaining and
503 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
505 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
506 this, showCryptedLabel( bool ) );
508 CONNECT( THEMIM->getIM(), seekRequested( float ),
509 timeLabel, setDisplayPosition( float ) );
511 /* This shouldn't be necessary, but for somehow reason, the statusBarr
512 starts at height of 20px and when a text is shown it needs more space.
513 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
514 geometry, we need to force a height. If you have a better idea, please
517 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
520 /**********************************************************************
521 * Handling of sizing of the components
522 **********************************************************************/
524 void MainInterface::debug()
527 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
528 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
529 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
531 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
532 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
533 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
537 inline void MainInterface::showVideo() { showTab( videoWidget ); }
538 inline void MainInterface::restoreStackOldWidget()
539 { showTab( stackCentralOldWidget ); }
541 inline void MainInterface::showTab( QWidget *widget )
544 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
547 stackCentralOldWidget = stackCentralW->currentWidget();
548 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
550 stackCentralW->setCurrentWidget( widget );
552 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
555 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
556 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
560 void MainInterface::destroyPopupMenu()
562 QVLCMenu::PopupMenu( p_intf, false );
565 void MainInterface::popupMenu( const QPoint & )
567 QVLCMenu::PopupMenu( p_intf, true );
570 void MainInterface::toggleFSC()
572 if( !fullscreenControls ) return;
574 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
575 QApplication::postEvent( fullscreenControls, eShow );
578 /****************************************************************************
580 ****************************************************************************/
584 * You must not change the state of this object or other Qt4 UI objects,
585 * from the video output thread - only from the Qt4 UI main loop thread.
586 * All window provider queries must be handled through signals or events.
587 * That's why we have all those emit statements...
589 WId MainInterface::getVideo( int *pi_x, int *pi_y,
590 unsigned int *pi_width, unsigned int *pi_height )
595 /* This is a blocking call signal. Results are returned through pointers.
596 * Beware of deadlocks! */
598 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
602 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
603 unsigned *pi_width, unsigned *pi_height )
605 /* Hidden or minimized, activate */
606 if( isHidden() || isMinimized() )
607 toggleUpdateSystrayMenu();
609 /* Request the videoWidget */
610 WId ret = videoWidget->request( pi_x, pi_y,
611 pi_width, pi_height, !b_autoresize );
613 if( ret ) /* The videoWidget is available */
615 /* Consider the video active now */
618 /* Ask videoWidget to resize correctly, if we are in normal mode */
619 if( !isFullScreen() && !isMaximized() && b_autoresize )
620 videoWidget->SetSizing( *pi_width, *pi_height );
624 /* Asynchronous call from the WindowClose function */
625 void MainInterface::releaseVideo( void )
627 emit askReleaseVideo();
630 /* Function that is CONNECTED to the previous emit */
631 void MainInterface::releaseVideoSlot( void )
633 /* This function is called when the embedded video window is destroyed,
634 * or in the rare case that the embedded window is still here but the
635 * Qt4 interface exits. */
636 assert( videoWidget );
637 videoWidget->release();
638 setVideoOnTop( false );
639 setVideoFullScreen( false );
641 if( stackCentralW->currentWidget() == videoWidget )
642 restoreStackOldWidget();
644 /* We don't want to have a blank video to popup */
645 stackCentralOldWidget = bgWidget;
648 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
650 if( !isFullScreen() && !isMaximized() )
651 videoWidget->SetSizing( w, h );
654 void MainInterface::setVideoFullScreen( bool fs )
656 b_videoFullScreen = fs;
659 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
660 /* if user hasn't defined screennumber, or screennumber that is bigger
661 * than current number of screens, take screennumber where current interface
664 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
665 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
667 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
669 /* To be sure window is on proper-screen in xinerama */
670 if( !screenres.contains( pos() ) )
672 msg_Dbg( p_intf, "Moving video to correct screen");
673 move( QPoint( screenres.x(), screenres.y() ) );
675 setMinimalView( true );
676 setInterfaceFullScreen( true );
680 /* TODO do we want to restore screen and position ? (when
681 * qt-fullscreen-screennumber is forced) */
682 setMinimalView( b_minimalView );
683 setInterfaceFullScreen( b_interfaceFullScreen );
688 /* Slot to change the video always-on-top flag.
689 * Emit askVideoOnTop() to invoke this from other thread. */
690 void MainInterface::setVideoOnTop( bool on_top )
692 Qt::WindowFlags oldflags = windowFlags(), newflags;
695 newflags = oldflags | Qt::WindowStaysOnTopHint;
697 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
698 if( newflags != oldflags && !b_videoFullScreen )
701 setWindowFlags( newflags );
702 show(); /* necessary to apply window flags */
706 /* Asynchronous call from WindowControl function */
707 int MainInterface::controlVideo( int i_query, va_list args )
711 case VOUT_WINDOW_SET_SIZE:
713 unsigned int i_width = va_arg( args, unsigned int );
714 unsigned int i_height = va_arg( args, unsigned int );
716 emit askVideoToResize( i_width, i_height );
719 case VOUT_WINDOW_SET_STATE:
721 unsigned i_arg = va_arg( args, unsigned );
722 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
724 emit askVideoOnTop( on_top != 0 );
727 case VOUT_WINDOW_SET_FULLSCREEN:
729 bool b_fs = va_arg( args, int );
731 emit askVideoSetFullScreen( b_fs );
735 msg_Warn( p_intf, "unsupported control query" );
740 /*****************************************************************************
741 * Playlist, Visualisation and Menus handling
742 *****************************************************************************/
744 * Toggle the playlist widget or dialog
746 void MainInterface::createPlaylist()
748 playlistWidget = new PlaylistWidget( p_intf, this );
752 stackCentralW->addWidget( playlistWidget );
753 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
758 playlistWidget->setParent( NULL );
760 playlistWidget->setWindowFlags( Qt::Window );
762 /* This will restore the geometry but will not work for position,
763 because of parenting */
764 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
765 playlistWidget, QSize( 600, 300 ) );
769 void MainInterface::togglePlaylist()
771 if( !playlistWidget )
778 /* Playlist is not visible, show it */
779 if( stackCentralW->currentWidget() != playlistWidget )
781 showTab( playlistWidget );
785 restoreStackOldWidget();
787 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
792 playlistWidget->setParent( NULL );
794 playlistWidget->setWindowFlags( Qt::Window );
795 playlistVisible = !playlistVisible;
796 playlistWidget->setVisible( playlistVisible );
801 void MainInterface::dockPlaylist( bool p_docked )
803 if( b_plDocked == p_docked ) return;
804 b_plDocked = p_docked;
806 if( !playlistWidget ) return; /* Playlist wasn't created yet */
809 stackCentralW->removeWidget( playlistWidget );
811 playlistWidget->setParent( NULL );
813 playlistWidget->setWindowFlags( Qt::Window );
814 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
815 playlistWidget, QSize( 600, 300 ) );
816 playlistWidget->show();
817 restoreStackOldWidget();
821 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
822 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
823 // It would be logical that QStackWidget::addWidget reset the flags...
824 stackCentralW->addWidget( playlistWidget );
825 showTab( playlistWidget );
827 playlistVisible = true;
831 * setMinimalView is the private function used by
832 * the SLOT toggleMinimalView and setVideoFullScreen
834 void MainInterface::setMinimalView( bool b_minimal )
836 menuBar()->setVisible( !b_minimal );
837 controls->setVisible( !b_minimal );
838 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
839 inputC->setVisible( !b_minimal );
843 * This public SLOT is used for moving to minimal View Mode
845 * If b_minimal is false, then we are normalView
847 void MainInterface::toggleMinimalView( bool b_minimal )
849 if( !b_minimalView && b_autoresize ) /* Normal mode */
851 if( stackCentralW->currentWidget() == bgWidget )
853 if( stackCentralW->height() < 16 )
855 resizeStack( stackCentralW->width(), 100 );
859 b_minimalView = b_minimal;
860 if( !b_videoFullScreen )
862 setMinimalView( b_minimalView );
863 computeMinimumSize();
866 emit minimalViewToggled( b_minimalView );
869 /* toggling advanced controls buttons */
870 void MainInterface::toggleAdvancedButtons()
872 controls->toggleAdvanced();
873 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
876 /* Get the visibility status of the controls (hidden or not, advanced or not) */
877 int MainInterface::getControlsVisibilityStatus()
879 if( !controls ) return 0;
880 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
881 + CONTROLS_ADVANCED * controls->b_advancedVisible );
884 void MainInterface::setStatusBarVisibility( bool b_visible )
886 statusBar()->setVisible( b_visible );
887 b_statusbarVisible = b_visible;
888 if( controls ) controls->setGripVisible( !b_statusbarVisible );
892 void MainInterface::visual()
894 if( !VISIBLE( visualSelector) )
896 visualSelector->show();
897 if( !THEMIM->getIM()->hasVideo() )
899 /* Show the background widget */
901 visualSelectorEnabled = true;
905 /* Stop any currently running visualization */
906 visualSelector->hide();
907 visualSelectorEnabled = false;
912 /************************************************************************
914 ************************************************************************/
915 void MainInterface::setName( const QString& name )
917 input_name = name; /* store it for the QSystray use */
918 /* Display it in the status bar, but also as a Tooltip in case it doesn't
920 nameLabel->setText( name );
921 nameLabel->setToolTip( name );
925 * Give the decorations of the Main Window a correct Name.
926 * If nothing is given, set it to VLC...
928 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
930 if( aTitle.isEmpty() )
932 setWindowTitle( qtr( "VLC media player" ) );
936 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
940 void MainInterface::showCryptedLabel( bool b_show )
942 if( cryptedLabel == NULL )
944 cryptedLabel = new QLabel;
945 // The lock icon is not the right one for DRM protection/scrambled.
946 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
947 cryptedLabel->setText( "DRM" );
948 statusBar()->addWidget( cryptedLabel );
951 cryptedLabel->setVisible( b_show );
954 void MainInterface::showBuffering( float f_cache )
956 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
957 statusBar()->showMessage( amount, 1000 );
960 /*****************************************************************************
961 * Systray Icon and Systray Menu
962 *****************************************************************************/
965 * Create a SystemTray icon and a menu that would go with it.
966 * Connects to a click handler on the icon.
968 void MainInterface::createSystray()
971 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
972 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
974 iconVLC = QIcon( ":/logo/vlc128.png" );
975 sysTray = new QSystemTrayIcon( iconVLC, this );
976 sysTray->setToolTip( qtr( "VLC media player" ));
978 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
979 systrayMenu->setIcon( iconVLC );
981 QVLCMenu::updateSystrayMenu( this, p_intf, true );
984 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
985 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
987 /* Connects on nameChanged() */
988 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
989 this, updateSystrayTooltipName( const QString& ) );
990 /* Connect PLAY_STATUS on the systray */
991 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
992 this, updateSystrayTooltipStatus( int ) );
996 * Updates the Systray Icon's menu and toggle the main interface
998 void MainInterface::toggleUpdateSystrayMenu()
1000 /* If hidden, show it */
1006 else if( isMinimized() )
1014 /* Visible (possibly under other windows) */
1016 /* check if any visible window is above vlc in the z-order,
1017 * but ignore the ones always on top
1018 * and the ones which can't be activated */
1021 wi.cbSize = sizeof( WINDOWINFO );
1022 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1023 hwnd && ( !IsWindowVisible( hwnd ) ||
1024 ( GetWindowInfo( hwnd, &wi ) &&
1025 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1026 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1027 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1028 (wi.dwExStyle&WS_EX_TOPMOST) )
1041 QVLCMenu::updateSystrayMenu( this, p_intf );
1044 /* First Item of the systray menu */
1045 void MainInterface::showUpdateSystrayMenu()
1053 QVLCMenu::updateSystrayMenu( this, p_intf );
1056 /* First Item of the systray menu */
1057 void MainInterface::hideUpdateSystrayMenu()
1060 QVLCMenu::updateSystrayMenu( this, p_intf );
1063 /* Click on systray Icon */
1064 void MainInterface::handleSystrayClick(
1065 QSystemTrayIcon::ActivationReason reason )
1069 case QSystemTrayIcon::Trigger:
1070 case QSystemTrayIcon::DoubleClick:
1072 QVLCMenu::updateSystrayMenu( this, p_intf );
1074 toggleUpdateSystrayMenu();
1077 case QSystemTrayIcon::MiddleClick:
1078 sysTray->showMessage( qtr( "VLC media player" ),
1079 qtr( "Control menu for the player" ),
1080 QSystemTrayIcon::Information, 3000 );
1088 * Updates the name of the systray Icon tooltip.
1089 * Doesn't check if the systray exists, check before you call it.
1091 void MainInterface::updateSystrayTooltipName( const QString& name )
1093 if( name.isEmpty() )
1095 sysTray->setToolTip( qtr( "VLC media player" ) );
1099 sysTray->setToolTip( name );
1100 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1102 sysTray->showMessage( qtr( "VLC media player" ), name,
1103 QSystemTrayIcon::NoIcon, 3000 );
1107 QVLCMenu::updateSystrayMenu( this, p_intf );
1111 * Updates the status of the systray Icon tooltip.
1112 * Doesn't check if the systray exists, check before you call it.
1114 void MainInterface::updateSystrayTooltipStatus( int i_status )
1119 sysTray->setToolTip( input_name );
1122 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1125 sysTray->setToolTip( qtr( "VLC media player" ) );
1128 QVLCMenu::updateSystrayMenu( this, p_intf );
1132 void MainInterface::changeEvent(QEvent *event)
1134 if( event->type() == QEvent::WindowStateChange )
1136 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1137 Qt::WindowStates newState = windowState();
1138 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1140 if( newState & Qt::WindowMinimized )
1142 b_hasPausedWhenMinimized = false;
1144 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1145 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1148 b_hasPausedWhenMinimized = true;
1152 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1154 if( b_hasPausedWhenMinimized )
1161 QWidget::changeEvent(event);
1164 /************************************************************************
1166 ************************************************************************/
1167 void MainInterface::dropEvent(QDropEvent *event)
1169 dropEventPlay( event, true );
1172 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1174 if( event->possibleActions() & Qt::CopyAction )
1175 event->setDropAction( Qt::CopyAction );
1179 const QMimeData *mimeData = event->mimeData();
1181 /* D&D of a subtitles file, add it on the fly */
1182 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1184 if( !input_AddSubtitle( THEMIM->getInput(),
1185 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1193 bool first = b_play;
1194 foreach( const QUrl &url, mimeData->urls() )
1198 QString mrl = toURI( url.toEncoded().constData() );
1199 playlist_Add( THEPL, qtu(mrl), NULL,
1200 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1201 PLAYLIST_END, true, pl_Unlocked );
1203 RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1207 /* Browsers give content as text if you dnd the addressbar,
1208 so check if mimedata has valid url in text and use it
1209 if we didn't get any normal Urls()*/
1210 if( !mimeData->hasUrls() && mimeData->hasText() &&
1211 QUrl(mimeData->text()).isValid() )
1213 QString mrl = toURI( mimeData->text() );
1214 playlist_Add( THEPL, qtu(mrl), NULL,
1215 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1216 PLAYLIST_END, true, pl_Unlocked );
1220 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1222 event->acceptProposedAction();
1224 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1226 event->acceptProposedAction();
1228 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1233 /************************************************************************
1235 ************************************************************************/
1236 void MainInterface::keyPressEvent( QKeyEvent *e )
1238 handleKeyPress( e );
1241 void MainInterface::handleKeyPress( QKeyEvent *e )
1243 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1245 toggleMinimalView( !b_minimalView );
1249 int i_vlck = qtEventToVLCKey( e );
1252 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1259 void MainInterface::wheelEvent( QWheelEvent *e )
1261 int i_vlckey = qtWheelEventToVLCKey( e );
1262 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1266 void MainInterface::closeEvent( QCloseEvent *e )
1269 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1270 /* Accept session quit. Otherwise we break the desktop mamager. */
1274 void MainInterface::setInterfaceFullScreen( bool fs )
1277 setWindowState( windowState() | Qt::WindowFullScreen );
1279 setWindowState( windowState() & ~Qt::WindowFullScreen );
1281 void MainInterface::toggleInterfaceFullScreen()
1283 b_interfaceFullScreen = !b_interfaceFullScreen;
1284 if( !b_videoFullScreen )
1285 setInterfaceFullScreen( b_interfaceFullScreen );
1286 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1289 void MainInterface::emitBoss()
1293 void MainInterface::setBoss()
1308 void MainInterface::emitRaise()
1312 void MainInterface::setRaise()
1318 /*****************************************************************************
1319 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1320 * We don't show the menu directly here because we don't want the
1321 * caller to block for a too long time.
1322 *****************************************************************************/
1323 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1324 vlc_value_t old_val, vlc_value_t new_val, void *param )
1326 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1328 intf_thread_t *p_intf = (intf_thread_t *)param;
1330 if( p_intf->pf_show_dialog )
1332 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1333 new_val.b_bool, NULL );
1339 /*****************************************************************************
1340 * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1341 *****************************************************************************/
1342 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1343 vlc_value_t old_val, vlc_value_t new_val, void *param )
1345 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1346 VLC_UNUSED( new_val );
1348 intf_thread_t *p_intf = (intf_thread_t *)param;
1349 p_intf->p_sys->p_mi->toggleFSC();
1355 /*****************************************************************************
1356 * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1357 *****************************************************************************/
1358 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
1359 vlc_value_t old_val, vlc_value_t new_val, void *param )
1361 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1362 VLC_UNUSED( new_val );
1364 intf_thread_t *p_intf = (intf_thread_t *)param;
1365 p_intf->p_sys->p_mi->emitRaise();
1370 /*****************************************************************************
1371 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1372 *****************************************************************************/
1373 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1374 vlc_value_t old_val, vlc_value_t new_val, void *param )
1376 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1377 VLC_UNUSED( new_val );
1379 intf_thread_t *p_intf = (intf_thread_t *)param;
1380 p_intf->p_sys->p_mi->emitBoss();