]> git.sesse.net Git - vlc/blob - modules/gui/qt4/main_interface.cpp
Qt: Menu: change icon quit(cross) -> exit
[vlc] / modules / gui / qt4 / main_interface.cpp
1 /*****************************************************************************
2  * main_interface.cpp : Main interface
3  ****************************************************************************
4  * Copyright (C) 2006-2011 VideoLAN and AUTHORS
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *          Jean-Baptiste Kempf <jb@videolan.org>
9  *          Ilkka Ollakka <ileoo@videolan.org>
10  *
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.
15  *
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.
20  *
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  *****************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include "qt4.hpp"
31
32 #include "main_interface.hpp"
33 #include "input_manager.hpp"                    // Creation
34 #include "actions_manager.hpp"                  // killInstance
35 #include "extensions_manager.hpp"               // killInstance
36
37 #include "util/customwidgets.hpp"               // qtEventToVLCKey, QVLCStackedWidget
38 #include "util/qt_dirs.hpp"                     // toNativeSeparators
39
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
44 #include "dialogs/playlist.hpp"                 // PlaylistDialog
45
46 #include "menus.hpp"                            // Menu creation
47 #include "recents.hpp"                          // RecentItems when DnD
48
49 #include <QCloseEvent>
50 #include <QKeyEvent>
51
52 #include <QUrl>
53 #include <QSize>
54 #include <QDate>
55 #include <QMimeData>
56
57 #include <QMenu>
58 #include <QMenuBar>
59 #include <QStatusBar>
60 #include <QLabel>
61 #include <QStackedWidget>
62 #include <QFileInfo>
63
64 #include <vlc_keys.h>                       /* Wheel event */
65 #include <vlc_vout_display.h>               /* vout_thread_t and VOUT_ events */
66
67 // #define DEBUG_INTF
68
69 /* Callback prototypes */
70 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
71                         vlc_value_t old_val, vlc_value_t new_val, void *param );
72 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
73                        vlc_value_t old_val, vlc_value_t new_val, void *param );
74 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
75                        vlc_value_t old_val, vlc_value_t new_val, void *param );
76 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
77                            vlc_value_t old_val, vlc_value_t new_val,
78                            void *param );
79
80 const QEvent::Type MainInterface::ToolbarsNeedRebuild =
81         (QEvent::Type)QEvent::registerEventType();
82
83 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
84 {
85     /* Variables initialisation */
86     bgWidget             = NULL;
87     videoWidget          = NULL;
88     playlistWidget       = NULL;
89     stackCentralOldWidget= NULL;
90     sysTray              = NULL;
91     fullscreenControls   = NULL;
92     cryptedLabel         = NULL;
93     controls             = NULL;
94     inputC               = NULL;
95
96     b_hideAfterCreation  = false; // --qt-start-minimized
97     playlistVisible      = false;
98     input_name           = "";
99     b_interfaceFullScreen= false;
100     b_hasPausedWhenMinimized = false;
101     i_kc_offset          = false;
102
103     /* Ask for Privacy */
104     FirstRun::CheckAndRun( this, p_intf );
105
106     /**
107      *  Configuration and settings
108      *  Pre-building of interface
109      **/
110     /* Main settings */
111     setFocusPolicy( Qt::StrongFocus );
112     setAcceptDrops( true );
113     setWindowRole( "vlc-main" );
114     setWindowIcon( QApplication::windowIcon() );
115     setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
116 #ifdef Q_WS_MAC
117     setAttribute( Qt::WA_MacBrushedMetal );
118 #endif
119
120     /* Is video in embedded in the UI or not */
121     b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
122
123     /* Does the interface resize to video size or the opposite */
124     b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
125
126     /* Are we in the enhanced always-video mode or not ? */
127     b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
128
129     /* Do we want anoying popups or not */
130     i_notificationSetting = var_InheritInteger( p_intf, "qt-notification" );
131
132     /* */
133     b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
134
135     /* Set the other interface settings */
136     settings = getSettings();
137
138 #ifdef WIN32
139     /* Volume keys */
140     p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
141 #endif
142
143     /* */
144     b_plDocked = getSettings()->value( "MainWindow/pl-dock-status", true ).toBool();
145
146
147     /**************************
148      *  UI and Widgets design
149      **************************/
150     setVLCWindowsTitle();
151
152     /************
153      * Menu Bar *
154      ************/
155     VLCMenuBar::createMenuBar( this, p_intf );
156     CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
157              this, destroyPopupMenu() );
158
159     createMainWidget( settings );
160
161     /**************
162      * Status Bar *
163      **************/
164     createStatusBar();
165     setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
166
167     /********************
168      * Input Manager    *
169      ********************/
170     MainInputManager::getInstance( p_intf );
171
172 #ifdef WIN32
173     himl = NULL;
174     p_taskbl = NULL;
175     taskbar_wmsg = RegisterWindowMessage(TEXT("TaskbarButtonCreated"));
176 #endif
177
178     /*********************************
179      * Create the Systray Management *
180      *********************************/
181     initSystray();
182
183     /*************************************************************
184      * Connect the input manager to the GUI elements it manages  *
185      * Beware initSystray did some connects on input manager too *
186      *************************************************************/
187     /**
188      * Connects on nameChanged()
189      * Those connects are different because options can impeach them to trigger.
190      **/
191     /* Main Interface statusbar */
192     CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
193              this, setName( const QString& ) );
194     /* and title of the Main Interface*/
195     if( var_InheritBool( p_intf, "qt-name-in-title" ) )
196     {
197         CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
198                  this, setVLCWindowsTitle( const QString& ) );
199     }
200     /* END CONNECTS ON IM */
201
202     /* VideoWidget connects for asynchronous calls */
203     b_videoFullScreen = false;
204     connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
205              this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
206              Qt::BlockingQueuedConnection );
207     connect( this, SIGNAL(askReleaseVideo( void )),
208              this, SLOT(releaseVideoSlot( void )),
209              Qt::BlockingQueuedConnection );
210     CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
211
212     if( videoWidget )
213     {
214         if( b_autoresize )
215         {
216             CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
217                      this, setVideoSize( unsigned int, unsigned int ) );
218             CONNECT( videoWidget, sizeChanged( int, int ),
219                      this, videoSizeChanged( int,  int ) );
220         }
221         CONNECT( this, askVideoSetFullScreen( bool ),
222                  this, setVideoFullScreen( bool ) );
223     }
224
225     CONNECT( THEDP, toolBarConfUpdated(), this, toolBarConfUpdated() );
226     installEventFilter( this );
227
228     CONNECT( this, askToQuit(), THEDP, quit() );
229
230     CONNECT( this, askBoss(), this, setBoss() );
231     CONNECT( this, askRaise(), this, setRaise() );
232
233     /** END of CONNECTS**/
234
235
236     /************
237      * Callbacks
238      ************/
239     var_AddCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
240     var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
241     var_AddCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
242
243     /* Register callback for the intf-popupmenu variable */
244     var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
245
246
247     /* Final Sizing, restoration and placement of the interface */
248     if( settings->value( "MainWindow/playlist-visible", false ).toBool() )
249         togglePlaylist();
250
251     QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
252
253     b_interfaceFullScreen = isFullScreen();
254
255     setVisible( !b_hideAfterCreation );
256
257     computeMinimumSize();
258
259     /* Switch to minimal view if needed, must be called after the show() */
260     if( b_minimalView )
261         toggleMinimalView( true );
262 }
263
264 MainInterface::~MainInterface()
265 {
266     /* Unsure we hide the videoWidget before destroying it */
267     if( stackCentralOldWidget == videoWidget )
268         showTab( bgWidget );
269
270     if( videoWidget )
271         releaseVideoSlot();
272
273 #ifdef WIN32
274     if( himl )
275         ImageList_Destroy( himl );
276     if(p_taskbl)
277         p_taskbl->Release();
278     CoUninitialize();
279 #endif
280
281     /* Be sure to kill the actionsManager... Only used in the MI and control */
282     ActionsManager::killInstance();
283
284     /* Idem */
285     ExtensionsManager::killInstance();
286
287     /* Delete the FSC controller */
288     delete fullscreenControls;
289
290     /* Save states */
291
292     settings->beginGroup("MainWindow");
293     settings->setValue( "pl-dock-status", b_plDocked );
294
295     /* Save playlist state */
296     settings->setValue( "playlist-visible", playlistVisible );
297
298     settings->setValue( "adv-controls",
299                         getControlsVisibilityStatus() & CONTROLS_ADVANCED );
300     settings->setValue( "status-bar-visible", b_statusbarVisible );
301
302     /* Save the stackCentralW sizes */
303     settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
304     settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
305     settings->endGroup();
306
307     /* Save this size */
308     QVLCTools::saveWidgetPosition(settings, this);
309
310     delete statusBar();
311
312     /* Unregister callbacks */
313     var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
314     var_DelCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
315     var_DelCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
316     var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
317
318     p_intf->p_sys->p_mi = NULL;
319 }
320
321 void MainInterface::computeMinimumSize()
322 {
323     int minWidth = 30;
324     if( menuBar()->isVisible() )
325         minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
326
327     setMinimumWidth( minWidth );
328 }
329
330 /*****************************
331  *   Main UI handling        *
332  *****************************/
333 void MainInterface::recreateToolbars()
334 {
335     bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
336
337     delete controls;
338     delete inputC;
339
340     controls = new ControlsWidget( p_intf, b_adv, this );
341     inputC = new InputControlsWidget( p_intf, this );
342     mainLayout->insertWidget( 2, inputC );
343     mainLayout->insertWidget( settings->value( "MainWindow/ToolbarPos", 0 ).toInt() ? 0: 3,
344                               controls );
345
346     if( fullscreenControls )
347     {
348         delete fullscreenControls;
349         fullscreenControls = new FullscreenControllerWidget( p_intf, this );
350         CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
351                  this, handleKeyPress( QKeyEvent * ) );
352         THEMIM->requestVoutUpdate();
353     }
354
355     setMinimalView( b_minimalView );
356 }
357
358 void MainInterface::reloadPrefs()
359 {
360     i_notificationSetting = var_InheritInteger( p_intf, "qt-notification" );
361     b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
362 #ifdef WIN32
363     p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
364 #endif
365     if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
366     {
367         delete fullscreenControls;
368         fullscreenControls = NULL;
369     }
370 }
371
372 void MainInterface::createMainWidget( QSettings *creationSettings )
373 {
374     /* Create the main Widget and the mainLayout */
375     QWidget *main = new QWidget;
376     setCentralWidget( main );
377     mainLayout = new QVBoxLayout( main );
378     main->setContentsMargins( 0, 0, 0, 0 );
379     mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
380
381     /* */
382     stackCentralW = new QVLCStackedWidget( main );
383
384     /* Bg Cone */
385     if ( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY
386          && var_InheritBool( p_intf, "qt-icon-change" ) )
387     {
388         bgWidget = new EasterEggBackgroundWidget( p_intf );
389         CONNECT( this, kc_pressed(), bgWidget, animate() );
390     }
391     else
392         bgWidget = new BackgroundWidget( p_intf );
393
394     stackCentralW->addWidget( bgWidget );
395     if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
396         bgWidget->setWithArt( false );
397     else
398         if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
399             bgWidget->setExpandstoHeight( true );
400
401     /* And video Outputs */
402     if( b_videoEmbedded )
403     {
404         videoWidget = new VideoWidget( p_intf );
405         stackCentralW->addWidget( videoWidget );
406     }
407     mainLayout->insertWidget( 1, stackCentralW );
408
409     stackWidgetsSizes[bgWidget] =
410         creationSettings->value( "MainWindow/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() );
413
414     /* Create the CONTROLS Widget */
415     controls = new ControlsWidget( p_intf,
416         creationSettings->value( "MainWindow/adv-controls", false ).toBool(), this );
417     inputC = new InputControlsWidget( p_intf, this );
418
419     mainLayout->insertWidget( 2, inputC );
420     mainLayout->insertWidget(
421         creationSettings->value( "MainWindow/ToolbarPos", 0 ).toInt() ? 0: 3,
422         controls );
423
424     /* Visualisation, disabled for now, they SUCK */
425     #if 0
426     visualSelector = new VisualSelector( p_intf );
427     mainLayout->insertWidget( 0, visualSelector );
428     visualSelector->hide();
429     #endif
430
431
432     /* Enable the popup menu in the MI */
433     main->setContextMenuPolicy( Qt::CustomContextMenu );
434     CONNECT( main, customContextMenuRequested( const QPoint& ),
435              this, popupMenu( const QPoint& ) );
436
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" ) )
440         {
441             fullscreenControls = new FullscreenControllerWidget( p_intf, this );
442             CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
443                      this, handleKeyPress( QKeyEvent * ) );
444         }
445 }
446
447 inline void MainInterface::initSystray()
448 {
449     bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
450     bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
451
452     if( var_InheritBool( p_intf, "qt-start-minimized") )
453     {
454         if( b_systrayAvailable )
455         {
456             b_systrayWanted = true;
457             b_hideAfterCreation = true;
458         }
459         else
460             msg_Err( p_intf, "cannot start minimized without system tray bar" );
461     }
462
463     if( b_systrayAvailable && b_systrayWanted )
464         createSystray();
465 }
466
467 inline void MainInterface::createStatusBar()
468 {
469     /****************
470      *  Status Bar  *
471      ****************/
472     /* Widgets Creation*/
473     QStatusBar *statusBarr = statusBar();
474
475     TimeLabel *timeLabel = new TimeLabel( p_intf );
476     nameLabel = new ClickableQLabel();
477     nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
478                                       | Qt::TextSelectableByKeyboard );
479     SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
480
481     /* Styling those labels */
482     timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
483     speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
484     nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
485     timeLabel->setStyleSheet(
486             "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
487     speedLabel->setStyleSheet(
488             "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
489     /* pad both label and its tooltip */
490     nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
491
492     /* and adding those */
493     statusBarr->addWidget( nameLabel, 8 );
494     statusBarr->addPermanentWidget( speedLabel, 0 );
495     statusBarr->addPermanentWidget( timeLabel, 0 );
496
497     CONNECT( nameLabel, doubleClicked(), THEDP, epgDialog() );
498     /* timeLabel behaviour:
499        - double clicking opens the goto time dialog
500        - right-clicking and clicking just toggle between remaining and
501          elapsed time.*/
502     CONNECT( timeLabel, doubleClicked(), THEDP, gotoTimeDialog() );
503
504     CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
505              this, showCryptedLabel( bool ) );
506
507     CONNECT( THEMIM->getIM(), seekRequested( float ),
508              timeLabel, setDisplayPosition( float ) );
509
510     /* This shouldn't be necessary, but for somehow reason, the statusBarr
511        starts at height of 20px and when a text is shown it needs more space.
512        But, as the QMainWindow policy doesn't allow statusBar to change QMW's
513        geometry, we need to force a height. If you have a better idea, please
514        tell me -- jb
515      */
516     statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
517 }
518
519 /**********************************************************************
520  * Handling of sizing of the components
521  **********************************************************************/
522
523 void MainInterface::debug()
524 {
525 #ifdef DEBUG_INTF
526     msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
527     msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
528     msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
529
530     msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
531     msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
532     msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
533 #endif
534 }
535
536 inline void MainInterface::showVideo() { showTab( videoWidget ); }
537 inline void MainInterface::restoreStackOldWidget()
538             { showTab( stackCentralOldWidget ); }
539
540 inline void MainInterface::showTab( QWidget *widget )
541 {
542     if ( !widget ) widget = bgWidget; /* trying to restore a null oldwidget */
543 #ifdef DEBUG_INTF
544     if ( stackCentralOldWidget )
545         msg_Dbg( p_intf, "Old stackCentralOldWidget %s at index %i",
546                  stackCentralOldWidget->metaObject()->className(),
547                  stackCentralW->indexOf( stackCentralOldWidget ) );
548     msg_Dbg( p_intf, "ShowTab request for %s", widget->metaObject()->className() );
549 #endif
550     /* fixing when the playlist has been undocked after being hidden.
551        restoreStackOldWidget() is called when video stops but
552        stackCentralOldWidget would still be pointing to playlist */
553     if ( widget == playlistWidget && !isPlDocked() )
554         widget = bgWidget;
555
556     stackCentralOldWidget = stackCentralW->currentWidget();
557     stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
558
559     /* If we are playing video, embedded */
560     if( videoWidget && THEMIM->getIM()->hasVideo() )
561     {
562         /* Video -> Playlist */
563         if( videoWidget == stackCentralOldWidget && widget == playlistWidget )
564         {
565             stackCentralW->removeWidget( videoWidget );
566             videoWidget->show(); videoWidget->raise();
567         }
568
569         /* Playlist -> Video */
570         if( playlistWidget == stackCentralOldWidget && widget == videoWidget )
571         {
572             playlistWidget->artContainer->removeWidget( videoWidget );
573             videoWidget->show(); videoWidget->raise();
574             stackCentralW->addWidget( videoWidget );
575         }
576
577         /* Embedded playlist -> Non-embedded playlist */
578         if( bgWidget == stackCentralOldWidget && widget == videoWidget )
579         {
580             /* In rare case when video is started before the interface */
581             if( playlistWidget != NULL )
582                 playlistWidget->artContainer->removeWidget( videoWidget );
583             videoWidget->show(); videoWidget->raise();
584             stackCentralW->addWidget( videoWidget );
585             stackCentralW->setCurrentWidget( videoWidget );
586         }
587     }
588
589     stackCentralW->setCurrentWidget( widget );
590     if( b_autoresize )
591         resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
592
593 #ifdef DEBUG_INTF
594     msg_Dbg( p_intf, "Stack state changed to %s, index %i",
595               stackCentralW->currentWidget()->metaObject()->className(),
596               stackCentralW->currentIndex() );
597     msg_Dbg( p_intf, "New stackCentralOldWidget %s at index %i",
598               stackCentralOldWidget->metaObject()->className(),
599               stackCentralW->indexOf( stackCentralOldWidget ) );
600 #endif
601
602     /* This part is done later, to account for the new pl size */
603     if( videoWidget && THEMIM->getIM()->hasVideo() &&
604         videoWidget == stackCentralOldWidget && widget == playlistWidget )
605     {
606         playlistWidget->artContainer->addWidget( videoWidget );
607         playlistWidget->artContainer->setCurrentWidget( videoWidget );
608     }
609 }
610
611 void MainInterface::destroyPopupMenu()
612 {
613     VLCMenuBar::PopupMenu( p_intf, false );
614 }
615
616 void MainInterface::popupMenu( const QPoint & )
617 {
618     VLCMenuBar::PopupMenu( p_intf, true );
619 }
620
621 void MainInterface::toggleFSC()
622 {
623    if( !fullscreenControls ) return;
624
625    IMEvent *eShow = new IMEvent( IMEvent::FullscreenControlToggle );
626    QApplication::postEvent( fullscreenControls, eShow );
627 }
628
629 /****************************************************************************
630  * Video Handling
631  ****************************************************************************/
632
633 /**
634  * NOTE:
635  * You must not change the state of this object or other Qt4 UI objects,
636  * from the video output thread - only from the Qt4 UI main loop thread.
637  * All window provider queries must be handled through signals or events.
638  * That's why we have all those emit statements...
639  */
640 WId MainInterface::getVideo( int *pi_x, int *pi_y,
641                              unsigned int *pi_width, unsigned int *pi_height )
642 {
643     if( !videoWidget )
644         return 0;
645
646     /* This is a blocking call signal. Results are returned through pointers.
647      * Beware of deadlocks! */
648     WId id;
649     emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
650     return id;
651 }
652
653 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
654                                   unsigned *pi_width, unsigned *pi_height )
655 {
656     /* Hidden or minimized, activate */
657     if( isHidden() || isMinimized() )
658         toggleUpdateSystrayMenu();
659
660     /* Request the videoWidget */
661     WId ret = videoWidget->request( pi_x, pi_y,
662                                     pi_width, pi_height, !b_autoresize );
663     *p_id = ret;
664     if( ret ) /* The videoWidget is available */
665     {
666         /* Consider the video active now */
667         showVideo();
668
669         /* Ask videoWidget to resize correctly, if we are in normal mode */
670         if( !isFullScreen() && !isMaximized() && b_autoresize )
671             videoWidget->SetSizing( *pi_width, *pi_height );
672     }
673 }
674
675 /* Asynchronous call from the WindowClose function */
676 void MainInterface::releaseVideo( void )
677 {
678     emit askReleaseVideo();
679 }
680
681 /* Function that is CONNECTED to the previous emit */
682 void MainInterface::releaseVideoSlot( void )
683 {
684     /* This function is called when the embedded video window is destroyed,
685      * or in the rare case that the embedded window is still here but the
686      * Qt4 interface exits. */
687     assert( videoWidget );
688     videoWidget->release();
689     setVideoOnTop( false );
690     setVideoFullScreen( false );
691
692     if( stackCentralW->currentWidget() == videoWidget )
693         restoreStackOldWidget();
694     else if( playlistWidget &&
695              playlistWidget->artContainer->currentWidget() == videoWidget )
696     {
697         playlistWidget->artContainer->setCurrentIndex( 0 );
698         stackCentralW->addWidget( videoWidget );
699     }
700
701     /* We don't want to have a blank video to popup */
702     stackCentralOldWidget = bgWidget;
703 }
704
705 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
706 {
707     if( !isFullScreen() && !isMaximized() )
708         videoWidget->SetSizing( w, h );
709 }
710
711 void MainInterface::videoSizeChanged( int w, int h )
712 {
713     if( !playlistWidget || playlistWidget->artContainer->currentWidget() != videoWidget )
714         resizeStack( w, h );
715 }
716
717 void MainInterface::setVideoFullScreen( bool fs )
718 {
719     b_videoFullScreen = fs;
720     if( fs )
721     {
722         int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
723         /* if user hasn't defined screennumber, or screennumber that is bigger
724          * than current number of screens, take screennumber where current interface
725          * is
726          */
727         if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
728             numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
729
730         QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
731
732         /* To be sure window is on proper-screen in xinerama */
733         if( !screenres.contains( pos() ) )
734         {
735             msg_Dbg( p_intf, "Moving video to correct screen");
736             move( QPoint( screenres.x(), screenres.y() ) );
737         }
738
739         /* */
740         if( playlistWidget != NULL && playlistWidget->artContainer->currentWidget() == videoWidget )
741         {
742             showTab( videoWidget );
743         }
744
745         /* */
746         setMinimalView( true );
747         setInterfaceFullScreen( true );
748     }
749     else
750     {
751         /* TODO do we want to restore screen and position ? (when
752          * qt-fullscreen-screennumber is forced) */
753         setMinimalView( b_minimalView );
754         setInterfaceFullScreen( b_interfaceFullScreen );
755     }
756     videoWidget->sync();
757 }
758
759 /* Slot to change the video always-on-top flag.
760  * Emit askVideoOnTop() to invoke this from other thread. */
761 void MainInterface::setVideoOnTop( bool on_top )
762 {
763     Qt::WindowFlags oldflags = windowFlags(), newflags;
764
765     if( on_top )
766         newflags = oldflags | Qt::WindowStaysOnTopHint;
767     else
768         newflags = oldflags & ~Qt::WindowStaysOnTopHint;
769     if( newflags != oldflags && !b_videoFullScreen )
770
771     {
772         setWindowFlags( newflags );
773         show(); /* necessary to apply window flags */
774     }
775 }
776
777 /* Asynchronous call from WindowControl function */
778 int MainInterface::controlVideo( int i_query, va_list args )
779 {
780     switch( i_query )
781     {
782     case VOUT_WINDOW_SET_SIZE:
783     {
784         unsigned int i_width  = va_arg( args, unsigned int );
785         unsigned int i_height = va_arg( args, unsigned int );
786
787         emit askVideoToResize( i_width, i_height );
788         return VLC_SUCCESS;
789     }
790     case VOUT_WINDOW_SET_STATE:
791     {
792         unsigned i_arg = va_arg( args, unsigned );
793         unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
794
795         emit askVideoOnTop( on_top != 0 );
796         return VLC_SUCCESS;
797     }
798     case VOUT_WINDOW_SET_FULLSCREEN:
799     {
800         bool b_fs = va_arg( args, int );
801
802         emit askVideoSetFullScreen( b_fs );
803         return VLC_SUCCESS;
804     }
805     default:
806         msg_Warn( p_intf, "unsupported control query" );
807         return VLC_EGENERIC;
808     }
809 }
810
811 /*****************************************************************************
812  * Playlist, Visualisation and Menus handling
813  *****************************************************************************/
814 /**
815  * Toggle the playlist widget or dialog
816  **/
817 void MainInterface::createPlaylist()
818 {
819     PlaylistDialog *dialog = PlaylistDialog::getInstance( p_intf );
820
821     if( b_plDocked )
822     {
823         playlistWidget = dialog->exportPlaylistWidget();
824         stackCentralW->addWidget( playlistWidget );
825         stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
826     }
827     CONNECT( dialog, visibilityChanged(bool), this, setPlaylistVisibility(bool) );
828 }
829
830 void MainInterface::togglePlaylist()
831 {
832     if( !playlistWidget ) createPlaylist();
833
834     PlaylistDialog *dialog = PlaylistDialog::getInstance( p_intf );
835     if( b_plDocked )
836     {
837         if ( dialog->hasPlaylistWidget() )
838             playlistWidget = dialog->exportPlaylistWidget();
839         /* Playlist is not visible, show it */
840         if( stackCentralW->currentWidget() != playlistWidget )
841         {
842             if( stackCentralW->indexOf( playlistWidget ) == -1 )
843                 stackCentralW->addWidget( playlistWidget );
844             showTab( playlistWidget );
845         }
846         else /* Hide it! */
847         {
848             restoreStackOldWidget();
849         }
850         playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
851     }
852     else
853     {
854         playlistVisible = !playlistVisible;
855         if ( ! dialog->hasPlaylistWidget() )
856             dialog->importPlaylistWidget( playlistWidget );
857         if ( playlistVisible )
858             dialog->show();
859         else
860             dialog->hide();
861     }
862     debug();
863 }
864
865 const Qt::Key MainInterface::kc[10] =
866 {
867     Qt::Key_Up, Qt::Key_Up,
868     Qt::Key_Down, Qt::Key_Down,
869     Qt::Key_Left, Qt::Key_Right, Qt::Key_Left, Qt::Key_Right,
870     Qt::Key_B, Qt::Key_A
871 };
872
873 void MainInterface::dockPlaylist( bool p_docked )
874 {
875     if( b_plDocked == p_docked ) return;
876     /* some extra check */
877     if ( b_plDocked && !playlistWidget ) createPlaylist();
878
879     b_plDocked = p_docked;
880     PlaylistDialog *dialog = PlaylistDialog::getInstance( p_intf );
881
882     if( !p_docked ) /* Previously docked */
883     {
884         playlistVisible = playlistWidget->isVisible();
885         stackCentralW->removeWidget( playlistWidget );
886         dialog->importPlaylistWidget( playlistWidget );
887         if ( playlistVisible ) dialog->show();
888         restoreStackOldWidget();
889     }
890     else /* Previously undocked */
891     {
892         playlistVisible = dialog->isVisible();
893         dialog->hide();
894         playlistWidget = dialog->exportPlaylistWidget();
895         stackCentralW->addWidget( playlistWidget );
896
897         /* If playlist is invisible don't show it */
898         if( playlistVisible ) showTab( playlistWidget );
899     }
900 }
901
902 /*
903  * setMinimalView is the private function used by
904  * the SLOT toggleMinimalView and setVideoFullScreen
905  */
906 void MainInterface::setMinimalView( bool b_minimal )
907 {
908     menuBar()->setVisible( !b_minimal );
909     controls->setVisible( !b_minimal );
910     statusBar()->setVisible( !b_minimal && b_statusbarVisible );
911     inputC->setVisible( !b_minimal );
912 }
913
914 /*
915  * This public SLOT is used for moving to minimal View Mode
916  *
917  * If b_minimal is false, then we are normalView
918  */
919 void MainInterface::toggleMinimalView( bool b_minimal )
920 {
921     if( !b_minimalView && b_autoresize ) /* Normal mode */
922     {
923         if( stackCentralW->currentWidget() == bgWidget )
924         {
925             if( stackCentralW->height() < 16 )
926             {
927                 resizeStack( stackCentralW->width(), 100 );
928             }
929         }
930     }
931     b_minimalView = b_minimal;
932     if( !b_videoFullScreen )
933     {
934         setMinimalView( b_minimalView );
935         computeMinimumSize();
936     }
937
938     emit minimalViewToggled( b_minimalView );
939 }
940
941 /* toggling advanced controls buttons */
942 void MainInterface::toggleAdvancedButtons()
943 {
944     controls->toggleAdvanced();
945 //    if( fullscreenControls ) fullscreenControls->toggleAdvanced();
946 }
947
948 /* Get the visibility status of the controls (hidden or not, advanced or not) */
949 int MainInterface::getControlsVisibilityStatus()
950 {
951     if( !controls ) return 0;
952     return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
953             + CONTROLS_ADVANCED * controls->b_advancedVisible );
954 }
955
956 StandardPLPanel *MainInterface::getPlaylistView()
957 {
958     if( !playlistWidget ) return NULL;
959     else return playlistWidget->mainView;
960 }
961
962 void MainInterface::setStatusBarVisibility( bool b_visible )
963 {
964     statusBar()->setVisible( b_visible );
965     b_statusbarVisible = b_visible;
966     if( controls ) controls->setGripVisible( !b_statusbarVisible );
967 }
968
969
970 void MainInterface::setPlaylistVisibility( bool b_visible )
971 {
972     if ( !isPlDocked() )
973         playlistVisible = b_visible;
974 }
975
976 #if 0
977 void MainInterface::visual()
978 {
979     if( !VISIBLE( visualSelector) )
980     {
981         visualSelector->show();
982         if( !THEMIM->getIM()->hasVideo() )
983         {
984             /* Show the background widget */
985         }
986         visualSelectorEnabled = true;
987     }
988     else
989     {
990         /* Stop any currently running visualization */
991         visualSelector->hide();
992         visualSelectorEnabled = false;
993     }
994 }
995 #endif
996
997 /************************************************************************
998  * Other stuff
999  ************************************************************************/
1000 void MainInterface::setName( const QString& name )
1001 {
1002     input_name = name; /* store it for the QSystray use */
1003     /* Display it in the status bar, but also as a Tooltip in case it doesn't
1004        fit in the label */
1005     nameLabel->setText( name );
1006     nameLabel->setToolTip( name );
1007 }
1008
1009 /**
1010  * Give the decorations of the Main Window a correct Name.
1011  * If nothing is given, set it to VLC...
1012  **/
1013 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
1014 {
1015     if( aTitle.isEmpty() )
1016     {
1017         setWindowTitle( qtr( "VLC media player" ) );
1018     }
1019     else
1020     {
1021         setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
1022     }
1023 }
1024
1025 void MainInterface::showCryptedLabel( bool b_show )
1026 {
1027     if( cryptedLabel == NULL )
1028     {
1029         cryptedLabel = new QLabel;
1030         // The lock icon is not the right one for DRM protection/scrambled.
1031         //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
1032         cryptedLabel->setText( "DRM" );
1033         statusBar()->addWidget( cryptedLabel );
1034     }
1035
1036     cryptedLabel->setVisible( b_show );
1037 }
1038
1039 void MainInterface::showBuffering( float f_cache )
1040 {
1041     QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
1042     statusBar()->showMessage( amount, 1000 );
1043 }
1044
1045 /*****************************************************************************
1046  * Systray Icon and Systray Menu
1047  *****************************************************************************/
1048 /**
1049  * Create a SystemTray icon and a menu that would go with it.
1050  * Connects to a click handler on the icon.
1051  **/
1052 void MainInterface::createSystray()
1053 {
1054     QIcon iconVLC;
1055     if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
1056         iconVLC =  QIcon( ":/logo/vlc128-xmas.png" );
1057     else
1058         iconVLC =  QIcon( ":/logo/vlc128.png" );
1059     sysTray = new QSystemTrayIcon( iconVLC, this );
1060     sysTray->setToolTip( qtr( "VLC media player" ));
1061
1062     systrayMenu = new QMenu( qtr( "VLC media player" ), this );
1063     systrayMenu->setIcon( iconVLC );
1064
1065     VLCMenuBar::updateSystrayMenu( this, p_intf, true );
1066     sysTray->show();
1067
1068     CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
1069              this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
1070
1071     /* Connects on nameChanged() */
1072     CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
1073              this, updateSystrayTooltipName( const QString& ) );
1074     /* Connect PLAY_STATUS on the systray */
1075     CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
1076              this, updateSystrayTooltipStatus( int ) );
1077 }
1078
1079 /**
1080  * Updates the Systray Icon's menu and toggle the main interface
1081  */
1082 void MainInterface::toggleUpdateSystrayMenu()
1083 {
1084     /* If hidden, show it */
1085     if( isHidden() )
1086     {
1087         show();
1088         activateWindow();
1089     }
1090     else if( isMinimized() )
1091     {
1092         /* Minimized */
1093         showNormal();
1094         activateWindow();
1095     }
1096     else
1097     {
1098         /* Visible (possibly under other windows) */
1099 #ifdef WIN32
1100         /* check if any visible window is above vlc in the z-order,
1101          * but ignore the ones always on top
1102          * and the ones which can't be activated */
1103         WINDOWINFO wi;
1104         HWND hwnd;
1105         wi.cbSize = sizeof( WINDOWINFO );
1106         for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1107                 hwnd && ( !IsWindowVisible( hwnd ) ||
1108                     ( GetWindowInfo( hwnd, &wi ) &&
1109                       (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1110                 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1111             if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1112                 (wi.dwExStyle&WS_EX_TOPMOST) )
1113             {
1114                 hide();
1115             }
1116             else
1117             {
1118                 activateWindow();
1119             }
1120 #else
1121         hide();
1122 #endif
1123     }
1124     if( sysTray )
1125         VLCMenuBar::updateSystrayMenu( this, p_intf );
1126 }
1127
1128 /* First Item of the systray menu */
1129 void MainInterface::showUpdateSystrayMenu()
1130 {
1131     if( isHidden() )
1132         show();
1133     if( isMinimized() )
1134         showNormal();
1135     activateWindow();
1136
1137     VLCMenuBar::updateSystrayMenu( this, p_intf );
1138 }
1139
1140 /* First Item of the systray menu */
1141 void MainInterface::hideUpdateSystrayMenu()
1142 {
1143     hide();
1144     VLCMenuBar::updateSystrayMenu( this, p_intf );
1145 }
1146
1147 /* Click on systray Icon */
1148 void MainInterface::handleSystrayClick(
1149                                     QSystemTrayIcon::ActivationReason reason )
1150 {
1151     switch( reason )
1152     {
1153         case QSystemTrayIcon::Trigger:
1154         case QSystemTrayIcon::DoubleClick:
1155 #ifdef Q_WS_MAC
1156             VLCMenuBar::updateSystrayMenu( this, p_intf );
1157 #else
1158             toggleUpdateSystrayMenu();
1159 #endif
1160             break;
1161         case QSystemTrayIcon::MiddleClick:
1162             sysTray->showMessage( qtr( "VLC media player" ),
1163                     qtr( "Control menu for the player" ),
1164                     QSystemTrayIcon::Information, 3000 );
1165             break;
1166         default:
1167             break;
1168     }
1169 }
1170
1171 /**
1172  * Updates the name of the systray Icon tooltip.
1173  * Doesn't check if the systray exists, check before you call it.
1174  **/
1175 void MainInterface::updateSystrayTooltipName( const QString& name )
1176 {
1177     if( name.isEmpty() )
1178     {
1179         sysTray->setToolTip( qtr( "VLC media player" ) );
1180     }
1181     else
1182     {
1183         sysTray->setToolTip( name );
1184         if( ( i_notificationSetting == NOTIFICATION_ALWAYS ) ||
1185             ( i_notificationSetting == NOTIFICATION_MINIMIZED && (isMinimized() || isHidden()) ) )
1186         {
1187             sysTray->showMessage( qtr( "VLC media player" ), name,
1188                     QSystemTrayIcon::NoIcon, 3000 );
1189         }
1190     }
1191
1192     VLCMenuBar::updateSystrayMenu( this, p_intf );
1193 }
1194
1195 /**
1196  * Updates the status of the systray Icon tooltip.
1197  * Doesn't check if the systray exists, check before you call it.
1198  **/
1199 void MainInterface::updateSystrayTooltipStatus( int i_status )
1200 {
1201     switch( i_status )
1202     {
1203     case PLAYING_S:
1204         sysTray->setToolTip( input_name );
1205         break;
1206     case PAUSE_S:
1207         sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1208         break;
1209     default:
1210         sysTray->setToolTip( qtr( "VLC media player" ) );
1211         break;
1212     }
1213     VLCMenuBar::updateSystrayMenu( this, p_intf );
1214 }
1215
1216 void MainInterface::changeEvent(QEvent *event)
1217 {
1218     if( event->type() == QEvent::WindowStateChange )
1219     {
1220         QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1221         Qt::WindowStates newState = windowState();
1222         Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1223
1224         if( newState & Qt::WindowMinimized )
1225         {
1226             b_hasPausedWhenMinimized = false;
1227
1228             if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1229                 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1230                 b_pauseOnMinimize )
1231             {
1232                 b_hasPausedWhenMinimized = true;
1233                 THEMIM->pause();
1234             }
1235         }
1236         else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1237         {
1238             if( b_hasPausedWhenMinimized )
1239             {
1240                 THEMIM->play();
1241             }
1242         }
1243     }
1244
1245     QWidget::changeEvent(event);
1246 }
1247
1248 /************************************************************************
1249  * D&D Events
1250  ************************************************************************/
1251 void MainInterface::dropEvent(QDropEvent *event)
1252 {
1253     dropEventPlay( event, true );
1254 }
1255
1256 /**
1257  * dropEventPlay
1258  *
1259  * Event called if something is dropped onto a VLC window
1260  * \param event the event in question
1261  * \param b_play whether to play the file immediately
1262  * \param b_playlist true to add to playlist, false to add to media library
1263  * \return nothing
1264  */
1265 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play, bool b_playlist )
1266 {
1267     if( event->possibleActions() & ( Qt::CopyAction | Qt::MoveAction | Qt::LinkAction ) )
1268        event->setDropAction( Qt::CopyAction );
1269     else
1270         return;
1271
1272     const QMimeData *mimeData = event->mimeData();
1273
1274     /* D&D of a subtitles file, add it on the fly */
1275     if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1276     {
1277         if( !input_AddSubtitle( THEMIM->getInput(),
1278                  qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1279                  true ) )
1280         {
1281             event->accept();
1282             return;
1283         }
1284     }
1285
1286     bool first = b_play;
1287     foreach( const QUrl &url, mimeData->urls() )
1288     {
1289         if( url.isValid() )
1290         {
1291             QString mrl = toURI( url.toEncoded().constData() );
1292             QFileInfo info( url.toLocalFile() );
1293             if( info.exists() && info.isSymLink() )
1294             {
1295                 QString target = info.symLinkTarget();
1296                 QUrl url;
1297                 if( QFile::exists( target ) )
1298                 {
1299                     url = QUrl::fromLocalFile( target );
1300                 }
1301                 else
1302                 {
1303                     url.setUrl( target );
1304                 }
1305                 mrl = toURI( url.toEncoded().constData() );
1306             }
1307             if( mrl.length() > 0 )
1308             {
1309                 playlist_Add( THEPL, qtu(mrl), NULL,
1310                           PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1311                           PLAYLIST_END, b_playlist, pl_Unlocked );
1312                 first = false;
1313                 RecentsMRL::getInstance( p_intf )->addRecent( mrl );
1314             }
1315         }
1316     }
1317
1318     /* Browsers give content as text if you dnd the addressbar,
1319        so check if mimedata has valid url in text and use it
1320        if we didn't get any normal Urls()*/
1321     if( !mimeData->hasUrls() && mimeData->hasText() &&
1322         QUrl(mimeData->text()).isValid() )
1323     {
1324         QString mrl = toURI( mimeData->text() );
1325         playlist_Add( THEPL, qtu(mrl), NULL,
1326                       PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1327                       PLAYLIST_END, b_playlist, pl_Unlocked );
1328     }
1329     event->accept();
1330 }
1331 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1332 {
1333      event->acceptProposedAction();
1334 }
1335 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1336 {
1337      event->acceptProposedAction();
1338 }
1339 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1340 {
1341      event->accept();
1342 }
1343
1344 /************************************************************************
1345  * Events stuff
1346  ************************************************************************/
1347 void MainInterface::keyPressEvent( QKeyEvent *e )
1348 {
1349     handleKeyPress( e );
1350
1351     /* easter eggs sequence handling */
1352     if ( e->key() == kc[ i_kc_offset ] )
1353         i_kc_offset++;
1354     else
1355         i_kc_offset = 0;
1356
1357     if ( i_kc_offset == (sizeof( kc ) / sizeof( Qt::Key )) )
1358     {
1359         i_kc_offset = 0;
1360         emit kc_pressed();
1361     }
1362 }
1363
1364 void MainInterface::handleKeyPress( QKeyEvent *e )
1365 {
1366     if( ( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) ) ||
1367         ( b_minimalView && !b_videoFullScreen && e->key() == Qt::Key_Escape ) )
1368     {
1369         toggleMinimalView( !b_minimalView );
1370         e->accept();
1371     }
1372
1373     int i_vlck = qtEventToVLCKey( e );
1374     if( i_vlck > 0 )
1375     {
1376         var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1377         e->accept();
1378     }
1379     else
1380         e->ignore();
1381 }
1382
1383 void MainInterface::wheelEvent( QWheelEvent *e )
1384 {
1385     int i_vlckey = qtWheelEventToVLCKey( e );
1386     var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1387     e->accept();
1388 }
1389
1390 void MainInterface::closeEvent( QCloseEvent *e )
1391 {
1392 //  hide();
1393     emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1394     /* Accept session quit. Otherwise we break the desktop mamager. */
1395     e->accept();
1396 }
1397
1398 bool MainInterface::eventFilter( QObject *obj, QEvent *event )
1399 {
1400     if ( event->type() == MainInterface::ToolbarsNeedRebuild ) {
1401         event->accept();
1402         recreateToolbars();
1403         return true;
1404     } else {
1405         return QObject::eventFilter( obj, event );
1406     }
1407 }
1408
1409 void MainInterface::toolBarConfUpdated()
1410 {
1411     QApplication::postEvent( this, new QEvent( MainInterface::ToolbarsNeedRebuild ) );
1412 }
1413
1414 void MainInterface::setInterfaceFullScreen( bool fs )
1415 {
1416     if( fs )
1417         setWindowState( windowState() | Qt::WindowFullScreen );
1418     else
1419         setWindowState( windowState() & ~Qt::WindowFullScreen );
1420 }
1421 void MainInterface::toggleInterfaceFullScreen()
1422 {
1423     b_interfaceFullScreen = !b_interfaceFullScreen;
1424     if( !b_videoFullScreen )
1425         setInterfaceFullScreen( b_interfaceFullScreen );
1426     emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1427 }
1428
1429 void MainInterface::emitBoss()
1430 {
1431     emit askBoss();
1432 }
1433 void MainInterface::setBoss()
1434 {
1435     THEMIM->pause();
1436     if( sysTray )
1437     {
1438         hide();
1439     }
1440     else
1441     {
1442         showMinimized();
1443     }
1444 }
1445
1446 void MainInterface::emitRaise()
1447 {
1448     emit askRaise();
1449 }
1450 void MainInterface::setRaise()
1451 {
1452     activateWindow();
1453     raise();
1454 }
1455
1456 /*****************************************************************************
1457  * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1458  *  We don't show the menu directly here because we don't want the
1459  *  caller to block for a too long time.
1460  *****************************************************************************/
1461 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1462                         vlc_value_t old_val, vlc_value_t new_val, void *param )
1463 {
1464     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1465
1466     intf_thread_t *p_intf = (intf_thread_t *)param;
1467
1468     if( p_intf->pf_show_dialog )
1469     {
1470         p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1471                                 new_val.b_bool, NULL );
1472     }
1473
1474     return VLC_SUCCESS;
1475 }
1476
1477 /*****************************************************************************
1478  * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1479  *****************************************************************************/
1480 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1481                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1482 {
1483     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1484     VLC_UNUSED( new_val );
1485
1486     intf_thread_t *p_intf = (intf_thread_t *)param;
1487     p_intf->p_sys->p_mi->toggleFSC();
1488
1489     /* Show event */
1490      return VLC_SUCCESS;
1491 }
1492
1493 /*****************************************************************************
1494  * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1495  *****************************************************************************/
1496 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
1497                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1498 {
1499     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1500     VLC_UNUSED( new_val );
1501
1502     intf_thread_t *p_intf = (intf_thread_t *)param;
1503     p_intf->p_sys->p_mi->emitRaise();
1504
1505     return VLC_SUCCESS;
1506 }
1507
1508 /*****************************************************************************
1509  * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1510  *****************************************************************************/
1511 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1512                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1513 {
1514     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1515     VLC_UNUSED( new_val );
1516
1517     intf_thread_t *p_intf = (intf_thread_t *)param;
1518     p_intf->p_sys->p_mi->emitBoss();
1519
1520     return VLC_SUCCESS;
1521 }