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
);
72 MainInterface::MainInterface( intf_thread_t
*_p_intf
) : QVLCMW( _p_intf
)
74 /* Variables initialisation */
77 playlistWidget
= NULL
;
78 stackCentralOldWidget
= NULL
;
82 fullscreenControls
= NULL
;
87 b_hideAfterCreation
= false; // --qt-start-minimized
88 playlistVisible
= false;
93 FirstRun::CheckAndRun( this, p_intf
);
96 * Configuration and settings
97 * Pre-building of interface
100 setFocusPolicy( Qt::StrongFocus
);
101 setAcceptDrops( true );
102 setWindowRole( "vlc-main" );
103 setWindowIcon( QApplication::windowIcon() );
104 setWindowOpacity( var_InheritFloat( p_intf
, "qt-opacity" ) );
106 setAttribute( Qt::WA_MacBrushedMetal
);
109 /* Is video in embedded in the UI or not */
110 b_videoEmbedded
= var_InheritBool( p_intf
, "embedded-video" );
112 /* Does the interface resize to video size or the opposite */
113 b_autoresize
= var_InheritBool( p_intf
, "qt-video-autoresize" );
115 /* Are we in the enhanced always-video mode or not ? */
116 b_minimalView
= var_InheritBool( p_intf
, "qt-minimal-view" );
118 /* Do we want anoying popups or not */
119 b_notificationEnabled
= var_InheritBool( p_intf
, "qt-notification" );
121 /* Set the other interface settings */
122 settings
= getSettings();
123 settings
->beginGroup( "MainWindow" );
127 p_intf
->p_sys
->disable_volume_keys
= var_InheritBool( p_intf
, "qt-disable-volume-keys" );
131 b_plDocked
= getSettings()->value( "pl-dock-status", true ).toBool();
133 settings
->endGroup( );
135 /*********************************
136 * Create the Systray Management *
137 *********************************/
140 /**************************
141 * UI and Widgets design
142 **************************/
143 setVLCWindowsTitle();
148 QVLCMenu::createMenuBar( this, p_intf
);
149 CONNECT( THEMIM
->getIM(), voutListChanged( vout_thread_t
**, int ),
150 this, destroyPopupMenu() );
152 createMainWidget( settings
);
158 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
160 /********************
162 ********************/
163 MainInputManager::getInstance( p_intf
);
168 taskbar_wmsg
= RegisterWindowMessage("TaskbarButtonCreated");
171 /************************************************************
172 * Connect the input manager to the GUI elements it manages *
173 ************************************************************/
175 * Connects on nameChanged()
176 * Those connects are different because options can impeach them to trigger.
178 /* Main Interface statusbar */
179 CONNECT( THEMIM
->getIM(), nameChanged( const QString
& ),
180 this, setName( const QString
& ) );
185 CONNECT( THEMIM
->getIM(), nameChanged( const QString
& ),
186 this, updateSystrayTooltipName( const QString
& ) );
189 /* and title of the Main Interface*/
190 if( var_InheritBool( p_intf
, "qt-name-in-title" ) )
192 CONNECT( THEMIM
->getIM(), nameChanged( const QString
& ),
193 this, setVLCWindowsTitle( const QString
& ) );
197 * CONNECTS on PLAY_STATUS
199 /* Status on the systray */
203 CONNECT( THEMIM
->getIM(), playingStatusChanged( int ),
204 this, updateSystrayTooltipStatus( int ) );
208 /* END CONNECTS ON IM */
210 /* VideoWidget connects for asynchronous calls */
211 b_videoFullScreen
= false;
212 b_videoOnTop
= false;
213 connect( this, SIGNAL(askGetVideo(WId
*,int*,int*,unsigned*,unsigned *)),
214 this, SLOT(getVideoSlot(WId
*,int*,int*,unsigned*,unsigned*)),
215 Qt::BlockingQueuedConnection
);
216 connect( this, SIGNAL(askReleaseVideo( void )),
217 this, SLOT(releaseVideoSlot( void )),
218 Qt::BlockingQueuedConnection
);
219 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
225 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
226 this, setVideoSize( unsigned int, unsigned int ) );
227 CONNECT( videoWidget
, sizeChanged( int, int ),
228 this, resizeStack( int, int ) );
230 CONNECT( this, askVideoSetFullScreen( bool ),
231 this, setVideoFullScreen( bool ) );
234 CONNECT( THEDP
, toolBarConfUpdated(), this, recreateToolbars() );
236 CONNECT( this, askToQuit(), THEDP
, quit() );
238 /** END of CONNECTS**/
244 var_AddCallback( p_intf
->p_libvlc
, "intf-show", IntfShowCB
, p_intf
);
246 /* Register callback for the intf-popupmenu variable */
247 var_AddCallback( p_intf
->p_libvlc
, "intf-popupmenu", PopupMenuCB
, p_intf
);
250 int i_plVis
= settings
->value( "MainWindow/playlist-visible", false ).toBool();
252 if( i_plVis
) togglePlaylist();
254 /**** FINAL SIZING and placement of interface */
255 settings
->beginGroup( "MainWindow" );
256 QVLCTools::restoreWidgetPosition( settings
, this, QSize(600, 420) );
257 settings
->endGroup();
259 b_interfaceFullScreen
= isFullScreen();
261 /* Final sizing and showing */
262 setVisible( !b_hideAfterCreation
);
264 computeMinimumSize();
266 /* Switch to minimal view if needed, must be called after the show() */
268 toggleMinimalView( true );
270 b_hasPausedWhenMinimized
= false;
273 MainInterface::~MainInterface()
275 /* Unsure we hide the videoWidget before destroying it */
276 if( stackCentralOldWidget
== videoWidget
)
284 ImageList_Destroy( himl
);
286 p_taskbl
->vt
->Release(p_taskbl
);
290 /* Be sure to kill the actionsManager... Only used in the MI and control */
291 ActionsManager::killInstance();
294 ExtensionsManager::killInstance();
296 /* Delete the FSC controller */
297 delete fullscreenControls
;
300 settings
->beginGroup( "MainWindow" );
302 settings
->setValue( "pl-dock-status", b_plDocked
);
303 /* Save playlist state */
305 settings
->setValue( "playlist-visible", playlistVisible
);
307 settings
->setValue( "adv-controls",
308 getControlsVisibilityStatus() & CONTROLS_ADVANCED
);
309 settings
->setValue( "status-bar-visible", b_statusbarVisible
);
311 /* Save the stackCentralW sizes */
312 settings
->setValue( "bgSize", stackWidgetsSizes
[bgWidget
] );
313 settings
->setValue( "playlistSize", stackWidgetsSizes
[playlistWidget
] );
316 QVLCTools::saveWidgetPosition(settings
, this);
318 settings
->endGroup();
320 /* Save undocked playlist size */
321 if( playlistWidget
&& !isPlDocked() )
322 QVLCTools::saveWidgetPosition( p_intf
, "Playlist", playlistWidget
);
324 delete playlistWidget
;
328 /* Unregister callbacks */
329 var_DelCallback( p_intf
->p_libvlc
, "intf-show", IntfShowCB
, p_intf
);
330 var_DelCallback( p_intf
->p_libvlc
, "intf-popupmenu", PopupMenuCB
, p_intf
);
332 p_intf
->p_sys
->p_mi
= NULL
;
335 void MainInterface::computeMinimumSize()
338 if( menuBar()->isVisible() )
339 minWidth
+= __MAX( controls
->sizeHint().width(), menuBar()->sizeHint().width() );
341 setMinimumWidth( minWidth
);
344 /*****************************
346 *****************************/
347 void MainInterface::recreateToolbars()
349 bool b_adv
= getControlsVisibilityStatus() & CONTROLS_ADVANCED
;
351 settings
->beginGroup( "MainWindow" );
355 controls
= new ControlsWidget( p_intf
, b_adv
, this );
356 inputC
= new InputControlsWidget( p_intf
, this );
358 if( fullscreenControls
)
360 delete fullscreenControls
;
361 fullscreenControls
= new FullscreenControllerWidget( p_intf
, this );
362 CONNECT( fullscreenControls
, keyPressed( QKeyEvent
* ),
363 this, handleKeyPress( QKeyEvent
* ) );
365 mainLayout
->insertWidget( 2, inputC
);
366 mainLayout
->insertWidget( settings
->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
368 settings
->endGroup();
371 void MainInterface::createMainWidget( QSettings
*settings
)
373 /* Create the main Widget and the mainLayout */
374 QWidget
*main
= new QWidget
;
375 setCentralWidget( main
);
376 mainLayout
= new QVBoxLayout( main
);
377 main
->setContentsMargins( 0, 0, 0, 0 );
378 mainLayout
->setSpacing( 0 ); mainLayout
->setMargin( 0 );
381 stackCentralW
= new QVLCStackedWidget( main
);
384 bgWidget
= new BackgroundWidget( p_intf
);
385 stackCentralW
->addWidget( bgWidget
);
386 if ( !var_InheritBool( p_intf
, "qt-bgcone" ) )
387 bgWidget
->setWithArt( false );
389 if ( var_InheritBool( p_intf
, "qt-bgcone-expands" ) )
390 bgWidget
->setExpandstoHeight( true );
392 /* And video Outputs */
393 if( b_videoEmbedded
)
395 videoWidget
= new VideoWidget( p_intf
);
396 stackCentralW
->addWidget( videoWidget
);
398 mainLayout
->insertWidget( 1, stackCentralW
);
400 settings
->beginGroup( "MainWindow" );
401 stackWidgetsSizes
[bgWidget
] = settings
->value( "bgSize", QSize( 600, 0 ) ).toSize();
402 /* Resize even if no-auto-resize, because we are at creation */
403 resizeStack( stackWidgetsSizes
[bgWidget
].width(), stackWidgetsSizes
[bgWidget
].height() );
405 /* Create the CONTROLS Widget */
406 controls
= new ControlsWidget( p_intf
,
407 settings
->value( "adv-controls", false ).toBool(), this );
408 inputC
= new InputControlsWidget( p_intf
, this );
410 mainLayout
->insertWidget( 2, inputC
);
411 mainLayout
->insertWidget( settings
->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
414 /* Visualisation, disabled for now, they SUCK */
416 visualSelector
= new VisualSelector( p_intf
);
417 mainLayout
->insertWidget( 0, visualSelector
);
418 visualSelector
->hide();
421 settings
->endGroup();
423 /* Enable the popup menu in the MI */
424 main
->setContextMenuPolicy( Qt::CustomContextMenu
);
425 CONNECT( main
, customContextMenuRequested( const QPoint
& ),
426 this, popupMenu( const QPoint
& ) );
428 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
429 /* Create the FULLSCREEN CONTROLS Widget */
430 if( var_InheritBool( p_intf
, "qt-fs-controller" ) )
432 fullscreenControls
= new FullscreenControllerWidget( p_intf
, this );
433 CONNECT( fullscreenControls
, keyPressed( QKeyEvent
* ),
434 this, handleKeyPress( QKeyEvent
* ) );
438 inline void MainInterface::initSystray()
441 bool b_systrayAvailable
= QSystemTrayIcon::isSystemTrayAvailable();
442 bool b_systrayWanted
= var_InheritBool( p_intf
, "qt-system-tray" );
444 if( var_InheritBool( p_intf
, "qt-start-minimized") )
446 if( b_systrayAvailable
)
448 b_systrayWanted
= true;
449 b_hideAfterCreation
= true;
452 msg_Err( p_intf
, "cannot start minimized without system tray bar" );
455 if( b_systrayAvailable
&& b_systrayWanted
)
460 inline void MainInterface::createStatusBar()
465 /* Widgets Creation*/
466 QStatusBar
*statusBarr
= statusBar();
468 TimeLabel
*timeLabel
= new TimeLabel( p_intf
);
469 nameLabel
= new QLabel( this );
470 nameLabel
->setTextInteractionFlags( Qt::TextSelectableByMouse
471 | Qt::TextSelectableByKeyboard
);
472 SpeedLabel
*speedLabel
= new SpeedLabel( p_intf
, this );
474 /* Styling those labels */
475 timeLabel
->setFrameStyle( QFrame::Sunken
| QFrame::Panel
);
476 speedLabel
->setFrameStyle( QFrame::Sunken
| QFrame::Panel
);
477 nameLabel
->setFrameStyle( QFrame::Sunken
| QFrame::StyledPanel
);
478 timeLabel
->setStyleSheet(
479 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
480 speedLabel
->setStyleSheet(
481 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
482 /* pad both label and its tooltip */
483 nameLabel
->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
485 /* and adding those */
486 statusBarr
->addWidget( nameLabel
, 8 );
487 statusBarr
->addPermanentWidget( speedLabel
, 0 );
488 statusBarr
->addPermanentWidget( timeLabel
, 0 );
490 /* timeLabel behaviour:
491 - double clicking opens the goto time dialog
492 - right-clicking and clicking just toggle between remaining and
494 CONNECT( timeLabel
, timeLabelDoubleClicked(), THEDP
, gotoTimeDialog() );
496 CONNECT( THEMIM
->getIM(), encryptionChanged( bool ),
497 this, showCryptedLabel( bool ) );
499 CONNECT( THEMIM
->getIM(), seekRequested( float ),
500 timeLabel
, setDisplayPosition( float ) );
502 /* This shouldn't be necessary, but for somehow reason, the statusBarr
503 starts at height of 20px and when a text is shown it needs more space.
504 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
505 geometry, we need to force a height. If you have a better idea, please
508 statusBarr
->setFixedHeight( statusBarr
->sizeHint().height() + 2 );
511 /**********************************************************************
512 * Handling of sizing of the components
513 **********************************************************************/
515 void MainInterface::debug()
518 msg_Dbg( p_intf
, "size: %i - %i", size().height(), size().width() );
519 msg_Dbg( p_intf
, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
520 msg_Dbg( p_intf
, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
522 msg_Dbg( p_intf
, "Stack size: %i - %i", stackCentralW
->size().height(), stackCentralW
->size().width() );
523 msg_Dbg( p_intf
, "Stack sizeHint: %i - %i", stackCentralW
->sizeHint().height(), stackCentralW
->sizeHint().width() );
524 msg_Dbg( p_intf
, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
528 inline void MainInterface::showVideo() { showTab( videoWidget
); }
529 inline void MainInterface::restoreStackOldWidget()
530 { showTab( stackCentralOldWidget
); }
532 inline void MainInterface::showTab( QWidget
*widget
)
535 msg_Warn( p_intf
, "Old stackCentralOldWidget %i", stackCentralW
->indexOf( stackCentralOldWidget
) );
538 stackCentralOldWidget
= stackCentralW
->currentWidget();
539 stackWidgetsSizes
[stackCentralOldWidget
] = stackCentralW
->size();
541 stackCentralW
->setCurrentWidget( widget
);
543 resizeStack( stackWidgetsSizes
[widget
].width(), stackWidgetsSizes
[widget
].height() );
546 msg_Warn( p_intf
, "State change %i", stackCentralW
->currentIndex() );
547 msg_Warn( p_intf
, "New stackCentralOldWidget %i", stackCentralW
->indexOf( stackCentralOldWidget
) );
551 void MainInterface::destroyPopupMenu()
553 QVLCMenu::PopupMenu( p_intf
, false );
556 void MainInterface::popupMenu( const QPoint
& )
558 QVLCMenu::PopupMenu( p_intf
, true );
561 void MainInterface::toggleFSC()
563 if( !fullscreenControls
) return;
565 IMEvent
*eShow
= new IMEvent( FullscreenControlToggle_Type
);
566 QApplication::postEvent( fullscreenControls
, eShow
);
569 /****************************************************************************
571 ****************************************************************************/
575 * You must not change the state of this object or other Qt4 UI objects,
576 * from the video output thread - only from the Qt4 UI main loop thread.
577 * All window provider queries must be handled through signals or events.
578 * That's why we have all those emit statements...
580 WId
MainInterface::getVideo( int *pi_x
, int *pi_y
,
581 unsigned int *pi_width
, unsigned int *pi_height
)
586 /* This is a blocking call signal. Results are returned through pointers.
587 * Beware of deadlocks! */
589 emit
askGetVideo( &id
, pi_x
, pi_y
, pi_width
, pi_height
);
593 void MainInterface::getVideoSlot( WId
*p_id
, int *pi_x
, int *pi_y
,
594 unsigned *pi_width
, unsigned *pi_height
)
596 /* Request the videoWidget */
597 WId ret
= videoWidget
->request( pi_x
, pi_y
,
598 pi_width
, pi_height
, !b_autoresize
);
600 if( ret
) /* The videoWidget is available */
602 /* Consider the video active now */
605 /* Ask videoWidget to resize correctly, if we are in normal mode */
606 if( !isFullScreen() && !isMaximized() && b_autoresize
)
607 videoWidget
->SetSizing( *pi_width
, *pi_height
);
611 /* Asynchronous call from the WindowClose function */
612 void MainInterface::releaseVideo( void )
614 emit
askReleaseVideo();
617 /* Function that is CONNECTED to the previous emit */
618 void MainInterface::releaseVideoSlot( void )
620 /* This function is called when the embedded video window is destroyed,
621 * or in the rare case that the embedded window is still here but the
622 * Qt4 interface exits. */
623 assert( videoWidget
);
624 videoWidget
->release();
625 setVideoOnTop( false );
626 setVideoFullScreen( false );
628 if( stackCentralW
->currentWidget() == videoWidget
)
629 restoreStackOldWidget();
631 /* We don't want to have a blank video to popup */
632 stackCentralOldWidget
= bgWidget
;
635 void MainInterface::setVideoSize( unsigned int w
, unsigned int h
)
637 if( !isFullScreen() && !isMaximized() )
638 videoWidget
->SetSizing( w
, h
);
641 void MainInterface::setVideoFullScreen( bool fs
)
643 b_videoFullScreen
= fs
;
646 int numscreen
= var_InheritInteger( p_intf
, "qt-fullscreen-screennumber" );
647 /* if user hasn't defined screennumber, or screennumber that is bigger
648 * than current number of screens, take screennumber where current interface
651 if( numscreen
== -1 || numscreen
> QApplication::desktop()->numScreens() )
652 numscreen
= QApplication::desktop()->screenNumber( p_intf
->p_sys
->p_mi
);
654 QRect screenres
= QApplication::desktop()->screenGeometry( numscreen
);
656 /* To be sure window is on proper-screen in xinerama */
657 if( !screenres
.contains( pos() ) )
659 msg_Dbg( p_intf
, "Moving video to correct screen");
660 move( QPoint( screenres
.x(), screenres
.y() ) );
662 setMinimalView( true );
663 setInterfaceFullScreen( true );
667 /* TODO do we want to restore screen and position ? (when
668 * qt-fullscreen-screennumber is forced) */
669 setMinimalView( b_minimalView
);
670 setInterfaceFullScreen( b_interfaceFullScreen
);
675 /* Slot to change the video always-on-top flag.
676 * Emit askVideoOnTop() to invoke this from other thread. */
677 void MainInterface::setVideoOnTop( bool on_top
)
679 b_videoOnTop
= on_top
;
681 Qt::WindowFlags oldflags
= windowFlags(), newflags
;
684 newflags
= oldflags
| Qt::WindowStaysOnTopHint
;
686 newflags
= oldflags
& ~Qt::WindowStaysOnTopHint
;
688 if( newflags
!= oldflags
)
690 setWindowFlags( newflags
);
691 show(); /* necessary to apply window flags */
695 /* Asynchronous call from WindowControl function */
696 int MainInterface::controlVideo( int i_query
, va_list args
)
700 case VOUT_WINDOW_SET_SIZE
:
702 unsigned int i_width
= va_arg( args
, unsigned int );
703 unsigned int i_height
= va_arg( args
, unsigned int );
705 emit
askVideoToResize( i_width
, i_height
);
708 case VOUT_WINDOW_SET_STATE
:
710 unsigned i_arg
= va_arg( args
, unsigned );
711 unsigned on_top
= i_arg
& VOUT_WINDOW_STATE_ABOVE
;
713 emit
askVideoOnTop( on_top
!= 0 );
716 case VOUT_WINDOW_SET_FULLSCREEN
:
718 bool b_fs
= va_arg( args
, int );
720 emit
askVideoSetFullScreen( b_fs
);
724 msg_Warn( p_intf
, "unsupported control query" );
729 /*****************************************************************************
730 * Playlist, Visualisation and Menus handling
731 *****************************************************************************/
733 * Toggle the playlist widget or dialog
735 void MainInterface::createPlaylist()
737 playlistWidget
= new PlaylistWidget( p_intf
, this );
741 stackCentralW
->addWidget( playlistWidget
);
742 stackWidgetsSizes
[playlistWidget
] = settings
->value( "playlistSize", QSize( 600, 300 ) ).toSize();
747 playlistWidget
->setParent( NULL
);
749 playlistWidget
->setWindowFlags( Qt::Window
);
751 /* This will restore the geometry but will not work for position,
752 because of parenting */
753 QVLCTools::restoreWidgetPosition( p_intf
, "Playlist",
754 playlistWidget
, QSize( 600, 300 ) );
758 void MainInterface::togglePlaylist()
760 if( !playlistWidget
)
767 /* Playlist is not visible, show it */
768 if( stackCentralW
->currentWidget() != playlistWidget
)
770 showTab( playlistWidget
);
774 restoreStackOldWidget();
776 playlistVisible
= ( stackCentralW
->currentWidget() == playlistWidget
);
781 playlistWidget
->setParent( NULL
);
783 playlistWidget
->setWindowFlags( Qt::Window
);
784 playlistVisible
= !playlistVisible
;
785 playlistWidget
->setVisible( playlistVisible
);
790 void MainInterface::dockPlaylist( bool p_docked
)
792 if( b_plDocked
== p_docked
) return;
793 b_plDocked
= p_docked
;
795 if( !playlistWidget
) return; /* Playlist wasn't created yet */
798 stackCentralW
->removeWidget( playlistWidget
);
800 playlistWidget
->setParent( NULL
);
802 playlistWidget
->setWindowFlags( Qt::Window
);
803 QVLCTools::restoreWidgetPosition( p_intf
, "Playlist",
804 playlistWidget
, QSize( 600, 300 ) );
805 playlistWidget
->show();
806 restoreStackOldWidget();
810 QVLCTools::saveWidgetPosition( p_intf
, "Playlist", playlistWidget
);
811 playlistWidget
->setWindowFlags( Qt::Widget
); // Probably a Qt bug here
812 // It would be logical that QStackWidget::addWidget reset the flags...
813 stackCentralW
->addWidget( playlistWidget
);
814 showTab( playlistWidget
);
816 playlistVisible
= true;
820 * setMinimalView is the private function used by
821 * the SLOT toggleMinimalView and setVideoFullScreen
823 void MainInterface::setMinimalView( bool b_minimal
)
825 menuBar()->setVisible( !b_minimal
);
826 controls
->setVisible( !b_minimal
);
827 statusBar()->setVisible( !b_minimal
&& b_statusbarVisible
);
828 inputC
->setVisible( !b_minimal
);
832 * This public SLOT is used for moving to minimal View Mode
834 * If b_minimal is false, then we are normalView
836 void MainInterface::toggleMinimalView( bool b_minimal
)
838 if( !b_minimalView
&& b_autoresize
) /* Normal mode */
840 if( stackCentralW
->currentWidget() == bgWidget
)
842 if( stackCentralW
->height() < 16 )
844 resizeStack( stackCentralW
->width(), 100 );
848 b_minimalView
= b_minimal
;
849 if( !b_videoFullScreen
)
851 setMinimalView( b_minimalView
);
852 computeMinimumSize();
855 emit
minimalViewToggled( b_minimalView
);
858 /* toggling advanced controls buttons */
859 void MainInterface::toggleAdvancedButtons()
861 controls
->toggleAdvanced();
862 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
865 /* Get the visibility status of the controls (hidden or not, advanced or not) */
866 int MainInterface::getControlsVisibilityStatus()
868 if( !controls
) return 0;
869 return( (controls
->isVisible() ? CONTROLS_VISIBLE
: CONTROLS_HIDDEN
)
870 + CONTROLS_ADVANCED
* controls
->b_advancedVisible
);
873 void MainInterface::setStatusBarVisibility( bool b_visible
)
875 statusBar()->setVisible( b_visible
);
876 b_statusbarVisible
= b_visible
;
877 if( controls
) controls
->setGripVisible( !b_statusbarVisible
);
881 void MainInterface::visual()
883 if( !VISIBLE( visualSelector
) )
885 visualSelector
->show();
886 if( !THEMIM
->getIM()->hasVideo() )
888 /* Show the background widget */
890 visualSelectorEnabled
= true;
894 /* Stop any currently running visualization */
895 visualSelector
->hide();
896 visualSelectorEnabled
= false;
901 /************************************************************************
903 ************************************************************************/
904 void MainInterface::setName( const QString
& name
)
906 input_name
= name
; /* store it for the QSystray use */
907 /* Display it in the status bar, but also as a Tooltip in case it doesn't
909 nameLabel
->setText( name
);
910 nameLabel
->setToolTip( name
);
914 * Give the decorations of the Main Window a correct Name.
915 * If nothing is given, set it to VLC...
917 void MainInterface::setVLCWindowsTitle( const QString
& aTitle
)
919 if( aTitle
.isEmpty() )
921 setWindowTitle( qtr( "VLC media player" ) );
925 setWindowTitle( aTitle
+ " - " + qtr( "VLC media player" ) );
929 void MainInterface::showCryptedLabel( bool b_show
)
931 if( cryptedLabel
== NULL
)
933 cryptedLabel
= new QLabel
;
934 // The lock icon is not the right one for DRM protection/scrambled.
935 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
936 cryptedLabel
->setText( "DRM" );
937 statusBar()->addWidget( cryptedLabel
);
940 cryptedLabel
->setVisible( b_show
);
943 void MainInterface::showBuffering( float f_cache
)
945 QString amount
= QString("Buffering: %1%").arg( (int)(100*f_cache
) );
946 statusBar()->showMessage( amount
, 1000 );
949 /*****************************************************************************
950 * Systray Icon and Systray Menu
951 *****************************************************************************/
954 * Create a SystemTray icon and a menu that would go with it.
955 * Connects to a click handler on the icon.
957 void MainInterface::createSystray()
960 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY
&& var_InheritBool( p_intf
, "qt-icon-change" ) )
961 iconVLC
= QIcon( ":/logo/vlc128-xmas.png" );
963 iconVLC
= QIcon( ":/logo/vlc128.png" );
964 sysTray
= new QSystemTrayIcon( iconVLC
, this );
965 sysTray
->setToolTip( qtr( "VLC media player" ));
967 systrayMenu
= new QMenu( qtr( "VLC media player" ), this );
968 systrayMenu
->setIcon( iconVLC
);
970 QVLCMenu::updateSystrayMenu( this, p_intf
, true );
973 CONNECT( sysTray
, activated( QSystemTrayIcon::ActivationReason
),
974 this, handleSystrayClick( QSystemTrayIcon::ActivationReason
) );
978 * Updates the Systray Icon's menu and toggle the main interface
980 void MainInterface::toggleUpdateSystrayMenu()
982 /* If hidden, show it */
988 else if( isMinimized() )
996 /* Visible (possibly under other windows) */
998 /* check if any visible window is above vlc in the z-order,
999 * but ignore the ones always on top
1000 * and the ones which can't be activated */
1003 wi
.cbSize
= sizeof( WINDOWINFO
);
1004 for( hwnd
= GetNextWindow( internalWinId(), GW_HWNDPREV
);
1005 hwnd
&& ( !IsWindowVisible( hwnd
) ||
1006 ( GetWindowInfo( hwnd
, &wi
) &&
1007 (wi
.dwExStyle
&WS_EX_NOACTIVATE
) ) );
1008 hwnd
= GetNextWindow( hwnd
, GW_HWNDPREV
) );
1009 if( !hwnd
|| !GetWindowInfo( hwnd
, &wi
) ||
1010 (wi
.dwExStyle
&WS_EX_TOPMOST
) )
1022 QVLCMenu::updateSystrayMenu( this, p_intf
);
1025 void MainInterface::showUpdateSystrayMenu()
1033 QVLCMenu::updateSystrayMenu( this, p_intf
);
1036 void MainInterface::hideUpdateSystrayMenu()
1039 QVLCMenu::updateSystrayMenu( this, p_intf
);
1042 void MainInterface::handleSystrayClick(
1043 QSystemTrayIcon::ActivationReason reason
)
1047 case QSystemTrayIcon::Trigger
:
1048 case QSystemTrayIcon::DoubleClick
:
1050 QVLCMenu::updateSystrayMenu( this, p_intf
);
1052 toggleUpdateSystrayMenu();
1055 case QSystemTrayIcon::MiddleClick
:
1056 sysTray
->showMessage( qtr( "VLC media player" ),
1057 qtr( "Control menu for the player" ),
1058 QSystemTrayIcon::Information
, 3000 );
1066 * Updates the name of the systray Icon tooltip.
1067 * Doesn't check if the systray exists, check before you call it.
1069 void MainInterface::updateSystrayTooltipName( const QString
& name
)
1071 if( name
.isEmpty() )
1073 sysTray
->setToolTip( qtr( "VLC media player" ) );
1077 sysTray
->setToolTip( name
);
1078 if( b_notificationEnabled
&& ( isHidden() || isMinimized() ) )
1080 sysTray
->showMessage( qtr( "VLC media player" ), name
,
1081 QSystemTrayIcon::NoIcon
, 3000 );
1085 QVLCMenu::updateSystrayMenu( this, p_intf
);
1089 * Updates the status of the systray Icon tooltip.
1090 * Doesn't check if the systray exists, check before you call it.
1092 void MainInterface::updateSystrayTooltipStatus( int i_status
)
1097 sysTray
->setToolTip( input_name
);
1100 sysTray
->setToolTip( input_name
+ " - " + qtr( "Paused") );
1103 sysTray
->setToolTip( qtr( "VLC media player" ) );
1106 QVLCMenu::updateSystrayMenu( this, p_intf
);
1110 void MainInterface::changeEvent(QEvent
*event
)
1112 if( event
->type() == QEvent::WindowStateChange
)
1114 QWindowStateChangeEvent
*windowStateChangeEvent
= static_cast<QWindowStateChangeEvent
*>(event
);
1115 Qt::WindowStates newState
= windowState();
1116 Qt::WindowStates oldState
= windowStateChangeEvent
->oldState();
1118 if( newState
& Qt::WindowMinimized
)
1120 b_hasPausedWhenMinimized
= false;
1122 if( THEMIM
->getIM()->playingStatus() == PLAYING_S
&&
1123 THEMIM
->getIM()->hasVideo() &&
1124 !THEMIM
->getIM()->hasVisualisation() &&
1125 var_InheritBool( p_intf
, "qt-pause-minimized" ) )
1127 b_hasPausedWhenMinimized
= true;
1131 else if( oldState
& Qt::WindowMinimized
&& !( newState
& Qt::WindowMinimized
) )
1133 if( b_hasPausedWhenMinimized
)
1140 QWidget::changeEvent(event
);
1143 /************************************************************************
1145 ************************************************************************/
1146 void MainInterface::dropEvent(QDropEvent
*event
)
1148 dropEventPlay( event
, true );
1151 void MainInterface::dropEventPlay( QDropEvent
*event
, bool b_play
)
1153 if( event
->possibleActions() & Qt::CopyAction
)
1154 event
->setDropAction( Qt::CopyAction
);
1158 const QMimeData
*mimeData
= event
->mimeData();
1160 /* D&D of a subtitles file, add it on the fly */
1161 if( mimeData
->urls().size() == 1 && THEMIM
->getIM()->hasInput() )
1163 if( !input_AddSubtitle( THEMIM
->getInput(),
1164 qtu( toNativeSeparators( mimeData
->urls()[0].toLocalFile() ) ),
1172 bool first
= b_play
;
1173 foreach( const QUrl
&url
, mimeData
->urls() )
1177 QString mrl
= toURI( url
.toEncoded().constData() );
1178 playlist_Add( THEPL
, qtu(mrl
), NULL
,
1179 PLAYLIST_APPEND
| (first
? PLAYLIST_GO
: PLAYLIST_PREPARSE
),
1180 PLAYLIST_END
, true, pl_Unlocked
);
1182 RecentsMRL::getInstance( p_intf
)->addRecent( url
.toString() );
1186 /* Browsers give content as text if you dnd the addressbar,
1187 so check if mimedata has valid url in text and use it
1188 if we didn't get any normal Urls()*/
1189 if( !mimeData
->hasUrls() && mimeData
->hasText() &&
1190 QUrl(mimeData
->text()).isValid() )
1192 QString mrl
= toURI( mimeData
->text() );
1193 playlist_Add( THEPL
, qtu(mrl
), NULL
,
1194 PLAYLIST_APPEND
| (first
? PLAYLIST_GO
: PLAYLIST_PREPARSE
),
1195 PLAYLIST_END
, true, pl_Unlocked
);
1199 void MainInterface::dragEnterEvent(QDragEnterEvent
*event
)
1201 event
->acceptProposedAction();
1203 void MainInterface::dragMoveEvent(QDragMoveEvent
*event
)
1205 event
->acceptProposedAction();
1207 void MainInterface::dragLeaveEvent(QDragLeaveEvent
*event
)
1212 /************************************************************************
1214 ************************************************************************/
1215 void MainInterface::keyPressEvent( QKeyEvent
*e
)
1217 handleKeyPress( e
);
1220 void MainInterface::handleKeyPress( QKeyEvent
*e
)
1222 if( ( e
->modifiers() & Qt::ControlModifier
) && ( e
->key() == Qt::Key_H
) )
1224 toggleMinimalView( !b_minimalView
);
1228 int i_vlck
= qtEventToVLCKey( e
);
1231 var_SetInteger( p_intf
->p_libvlc
, "key-pressed", i_vlck
);
1238 void MainInterface::wheelEvent( QWheelEvent
*e
)
1240 int i_vlckey
= qtWheelEventToVLCKey( e
);
1241 var_SetInteger( p_intf
->p_libvlc
, "key-pressed", i_vlckey
);
1245 void MainInterface::closeEvent( QCloseEvent
*e
)
1247 e
->ignore(); /* Do not quit */
1249 emit
askToQuit(); /* ask THEDP to quit, so we have a unique method */
1252 void MainInterface::setInterfaceFullScreen( bool fs
)
1255 setWindowState( windowState() | Qt::WindowFullScreen
);
1257 setWindowState( windowState() & ~Qt::WindowFullScreen
);
1259 void MainInterface::toggleInterfaceFullScreen()
1261 b_interfaceFullScreen
= !b_interfaceFullScreen
;
1262 if( !b_videoFullScreen
)
1263 setInterfaceFullScreen( b_interfaceFullScreen
);
1264 emit
fullscreenInterfaceToggled( b_interfaceFullScreen
);
1267 /*****************************************************************************
1268 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1269 * We don't show the menu directly here because we don't want the
1270 * caller to block for a too long time.
1271 *****************************************************************************/
1272 static int PopupMenuCB( vlc_object_t
*p_this
, const char *psz_variable
,
1273 vlc_value_t old_val
, vlc_value_t new_val
, void *param
)
1275 VLC_UNUSED( p_this
); VLC_UNUSED( psz_variable
); VLC_UNUSED( old_val
);
1277 intf_thread_t
*p_intf
= (intf_thread_t
*)param
;
1279 if( p_intf
->pf_show_dialog
)
1281 p_intf
->pf_show_dialog( p_intf
, INTF_DIALOG_POPUPMENU
,
1282 new_val
.b_bool
, NULL
);
1288 /*****************************************************************************
1289 * IntfShowCB: callback triggered by the intf-show libvlc variable.
1290 *****************************************************************************/
1291 static int IntfShowCB( vlc_object_t
*p_this
, const char *psz_variable
,
1292 vlc_value_t old_val
, vlc_value_t new_val
, void *param
)
1294 VLC_UNUSED( p_this
); VLC_UNUSED( psz_variable
); VLC_UNUSED( old_val
);
1295 VLC_UNUSED( new_val
);
1297 intf_thread_t
*p_intf
= (intf_thread_t
*)param
;
1298 p_intf
->p_sys
->p_mi
->toggleFSC();