Qt: small simplification
[vlc/vlc-skelet.git] / modules / gui / qt4 / main_interface.cpp
blob1c67e02036f4fc778936e6d3b12bd0c59857b497
1 /*****************************************************************************
2 * main_interface.cpp : Main interface
3 ****************************************************************************
4 * Copyright (C) 2006-2010 VideoLAN and AUTHORS
5 * $Id$
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 *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include "qt4.hpp"
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>
49 #include <QKeyEvent>
51 #include <QUrl>
52 #include <QSize>
53 #include <QDate>
55 #include <QMenu>
56 #include <QMenuBar>
57 #include <QStatusBar>
58 #include <QLabel>
59 #include <QStackedWidget>
61 #include <vlc_keys.h> /* Wheel event */
62 #include <vlc_vout_display.h> /* vout_thread_t and VOUT_ events */
64 // #define DEBUG_INTF
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 */
75 bgWidget = NULL;
76 videoWidget = NULL;
77 playlistWidget = NULL;
78 stackCentralOldWidget= NULL;
79 #ifndef HAVE_MAEMO
80 sysTray = NULL;
81 #endif
82 fullscreenControls = NULL;
83 cryptedLabel = NULL;
84 controls = NULL;
85 inputC = NULL;
87 b_hideAfterCreation = false; // --qt-start-minimized
88 playlistVisible = false;
89 input_name = "";
92 /* Ask for Privacy */
93 FirstRun::CheckAndRun( this, p_intf );
95 /**
96 * Configuration and settings
97 * Pre-building of interface
98 **/
99 /* Main settings */
100 setFocusPolicy( Qt::StrongFocus );
101 setAcceptDrops( true );
102 setWindowRole( "vlc-main" );
103 setWindowIcon( QApplication::windowIcon() );
104 setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
105 #ifdef Q_WS_MAC
106 setAttribute( Qt::WA_MacBrushedMetal );
107 #endif
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" );
125 #ifdef WIN32
126 /* Volume keys */
127 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
128 #endif
130 /* */
131 b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
133 settings->endGroup( );
135 /*********************************
136 * Create the Systray Management *
137 *********************************/
138 initSystray();
140 /**************************
141 * UI and Widgets design
142 **************************/
143 setVLCWindowsTitle();
145 /************
146 * Menu Bar *
147 ************/
148 QVLCMenu::createMenuBar( this, p_intf );
149 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
150 this, destroyPopupMenu() );
152 createMainWidget( settings );
154 /**************
155 * Status Bar *
156 **************/
157 createStatusBar();
158 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
160 /********************
161 * Input Manager *
162 ********************/
163 MainInputManager::getInstance( p_intf );
165 #ifdef WIN32
166 himl = NULL;
167 p_taskbl = NULL;
168 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
169 #endif
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& ) );
181 /* and systray */
182 #ifndef HAVE_MAEMO
183 if( sysTray )
185 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
186 this, updateSystrayTooltipName( const QString& ) );
188 #endif
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 */
200 #ifndef HAVE_MAEMO
201 if( sysTray )
203 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
204 this, updateSystrayTooltipStatus( int ) );
206 #endif
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));
221 if( videoWidget )
223 if( b_autoresize )
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**/
241 /************
242 * Callbacks
243 ************/
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 );
249 /* Playlist */
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() */
267 if( b_minimalView )
268 toggleMinimalView( true );
270 b_hasPausedWhenMinimized = false;
273 MainInterface::~MainInterface()
275 /* Unsure we hide the videoWidget before destroying it */
276 if( stackCentralOldWidget == videoWidget )
277 showTab( bgWidget );
279 if( videoWidget )
280 releaseVideoSlot();
282 #ifdef WIN32
283 if( himl )
284 ImageList_Destroy( himl );
285 if(p_taskbl)
286 p_taskbl->vt->Release(p_taskbl);
287 CoUninitialize();
288 #endif
290 /* Be sure to kill the actionsManager... Only used in the MI and control */
291 ActionsManager::killInstance();
293 /* Idem */
294 ExtensionsManager::killInstance();
296 /* Delete the FSC controller */
297 delete fullscreenControls;
299 /* Save states */
300 settings->beginGroup( "MainWindow" );
302 settings->setValue( "pl-dock-status", b_plDocked );
303 /* Save playlist state */
304 if( playlistWidget )
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] );
315 /* Save this size */
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;
326 delete statusBar();
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()
337 int minWidth = 30;
338 if( menuBar()->isVisible() )
339 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
341 setMinimumWidth( minWidth );
344 /*****************************
345 * Main UI handling *
346 *****************************/
347 void MainInterface::recreateToolbars()
349 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
351 settings->beginGroup( "MainWindow" );
352 delete controls;
353 delete inputC;
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,
367 controls );
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 );
380 /* */
381 stackCentralW = new QVLCStackedWidget( main );
383 /* Bg Cone */
384 bgWidget = new BackgroundWidget( p_intf );
385 stackCentralW->addWidget( bgWidget );
386 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
387 bgWidget->setWithArt( false );
388 else
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,
412 controls );
414 /* Visualisation, disabled for now, they SUCK */
415 #if 0
416 visualSelector = new VisualSelector( p_intf );
417 mainLayout->insertWidget( 0, visualSelector );
418 visualSelector->hide();
419 #endif
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()
440 #ifndef HAVE_MAEMO
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;
451 else
452 msg_Err( p_intf, "cannot start minimized without system tray bar" );
455 if( b_systrayAvailable && b_systrayWanted )
456 createSystray();
457 #endif
460 inline void MainInterface::createStatusBar()
462 /****************
463 * Status Bar *
464 ****************/
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
493 elapsed time.*/
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
506 tell me -- jb
508 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
511 /**********************************************************************
512 * Handling of sizing of the components
513 **********************************************************************/
515 void MainInterface::debug()
517 #ifdef DEBUG_INTF
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() );
525 #endif
528 inline void MainInterface::showVideo() { showTab( videoWidget ); }
529 inline void MainInterface::restoreStackOldWidget()
530 { showTab( stackCentralOldWidget ); }
532 inline void MainInterface::showTab( QWidget *widget )
534 #ifdef DEBUG_INTF
535 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
536 #endif
538 stackCentralOldWidget = stackCentralW->currentWidget();
539 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
541 stackCentralW->setCurrentWidget( widget );
542 if( b_autoresize )
543 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
545 #ifdef DEBUG_INTF
546 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
547 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
548 #endif
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 /****************************************************************************
570 * Video Handling
571 ****************************************************************************/
574 * NOTE:
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 )
583 if( !videoWidget )
584 return 0;
586 /* This is a blocking call signal. Results are returned through pointers.
587 * Beware of deadlocks! */
588 WId id;
589 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
590 return id;
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 );
599 *p_id = ret;
600 if( ret ) /* The videoWidget is available */
602 /* Consider the video active now */
603 showVideo();
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;
644 if( 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
649 * is
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 );
665 else
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 );
672 videoWidget->sync();
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;
683 if( b_videoOnTop )
684 newflags = oldflags | Qt::WindowStaysOnTopHint;
685 else
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 )
698 switch( i_query )
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 );
706 return VLC_SUCCESS;
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 );
714 return VLC_SUCCESS;
716 case VOUT_WINDOW_SET_FULLSCREEN:
718 bool b_fs = va_arg( args, int );
720 emit askVideoSetFullScreen( b_fs );
721 return VLC_SUCCESS;
723 default:
724 msg_Warn( p_intf, "unsupported control query" );
725 return VLC_EGENERIC;
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 );
739 if( b_plDocked )
741 stackCentralW->addWidget( playlistWidget );
742 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
744 else
746 #ifdef WIN32
747 playlistWidget->setParent( NULL );
748 #endif
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 )
762 createPlaylist();
765 if( b_plDocked )
767 /* Playlist is not visible, show it */
768 if( stackCentralW->currentWidget() != playlistWidget )
770 showTab( playlistWidget );
772 else /* Hide it! */
774 restoreStackOldWidget();
776 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
778 else
780 #ifdef WIN32
781 playlistWidget->setParent( NULL );
782 #endif
783 playlistWidget->setWindowFlags( Qt::Window );
784 playlistVisible = !playlistVisible;
785 playlistWidget->setVisible( playlistVisible );
787 debug();
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 */
796 if( !p_docked )
798 stackCentralW->removeWidget( playlistWidget );
799 #ifdef WIN32
800 playlistWidget->setParent( NULL );
801 #endif
802 playlistWidget->setWindowFlags( Qt::Window );
803 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
804 playlistWidget, QSize( 600, 300 ) );
805 playlistWidget->show();
806 restoreStackOldWidget();
808 else
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 );
880 #if 0
881 void MainInterface::visual()
883 if( !VISIBLE( visualSelector) )
885 visualSelector->show();
886 if( !THEMIM->getIM()->hasVideo() )
888 /* Show the background widget */
890 visualSelectorEnabled = true;
892 else
894 /* Stop any currently running visualization */
895 visualSelector->hide();
896 visualSelectorEnabled = false;
899 #endif
901 /************************************************************************
902 * Other stuff
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
908 fit in the label */
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" ) );
923 else
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 *****************************************************************************/
952 #ifndef HAVE_MAEMO
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()
959 QIcon iconVLC;
960 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
961 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
962 else
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 );
971 sysTray->show();
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 */
983 if( isHidden() )
985 show();
986 activateWindow();
988 else if( isMinimized() )
990 /* Minimized */
991 showNormal();
992 activateWindow();
994 else
996 /* Visible (possibly under other windows) */
997 #ifdef WIN32
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 */
1001 WINDOWINFO wi;
1002 HWND hwnd;
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) )
1012 hide();
1014 else
1016 activateWindow();
1018 #else
1019 hide();
1020 #endif
1022 QVLCMenu::updateSystrayMenu( this, p_intf );
1025 void MainInterface::showUpdateSystrayMenu()
1027 if( isHidden() )
1028 show();
1029 if( isMinimized() )
1030 showNormal();
1031 activateWindow();
1033 QVLCMenu::updateSystrayMenu( this, p_intf );
1036 void MainInterface::hideUpdateSystrayMenu()
1038 hide();
1039 QVLCMenu::updateSystrayMenu( this, p_intf );
1042 void MainInterface::handleSystrayClick(
1043 QSystemTrayIcon::ActivationReason reason )
1045 switch( reason )
1047 case QSystemTrayIcon::Trigger:
1048 case QSystemTrayIcon::DoubleClick:
1049 #ifdef Q_WS_MAC
1050 QVLCMenu::updateSystrayMenu( this, p_intf );
1051 #else
1052 toggleUpdateSystrayMenu();
1053 #endif
1054 break;
1055 case QSystemTrayIcon::MiddleClick:
1056 sysTray->showMessage( qtr( "VLC media player" ),
1057 qtr( "Control menu for the player" ),
1058 QSystemTrayIcon::Information, 3000 );
1059 break;
1060 default:
1061 break;
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" ) );
1075 else
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 )
1094 switch( i_status )
1096 case PLAYING_S:
1097 sysTray->setToolTip( input_name );
1098 break;
1099 case PAUSE_S:
1100 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1101 break;
1102 default:
1103 sysTray->setToolTip( qtr( "VLC media player" ) );
1104 break;
1106 QVLCMenu::updateSystrayMenu( this, p_intf );
1108 #endif
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;
1128 THEMIM->pause();
1131 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1133 if( b_hasPausedWhenMinimized )
1135 THEMIM->play();
1140 QWidget::changeEvent(event);
1143 /************************************************************************
1144 * D&D Events
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 );
1155 else
1156 return;
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() ) ),
1165 true ) )
1167 event->accept();
1168 return;
1172 bool first = b_play;
1173 foreach( const QUrl &url, mimeData->urls() )
1175 if( url.isValid() )
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 );
1181 first = false;
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 );
1197 event->accept();
1199 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1201 event->acceptProposedAction();
1203 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1205 event->acceptProposedAction();
1207 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1209 event->accept();
1212 /************************************************************************
1213 * Events stuff
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 );
1225 e->accept();
1228 int i_vlck = qtEventToVLCKey( e );
1229 if( i_vlck > 0 )
1231 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1232 e->accept();
1234 else
1235 e->ignore();
1238 void MainInterface::wheelEvent( QWheelEvent *e )
1240 int i_vlckey = qtWheelEventToVLCKey( e );
1241 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1242 e->accept();
1245 void MainInterface::closeEvent( QCloseEvent *e )
1247 e->ignore(); /* Do not quit */
1248 // hide();
1249 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1252 void MainInterface::setInterfaceFullScreen( bool fs )
1254 if( fs )
1255 setWindowState( windowState() | Qt::WindowFullScreen );
1256 else
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 );
1285 return VLC_SUCCESS;
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();
1300 /* Show event */
1301 return VLC_SUCCESS;