]> git.sesse.net Git - vlc/blob - modules/gui/qt4/main_interface.cpp
Qt: remove debug and cosmetics
[vlc] / modules / gui / qt4 / main_interface.cpp
1 /*****************************************************************************
2  * main_interface.cpp : Main interface
3  ****************************************************************************
4  * Copyright (C) 2006-2009 the VideoLAN team
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
23  * Foundation, Inc., 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"
34 #include "actions_manager.hpp"
35 #include "extensions_manager.hpp" // killInstance
36
37 #include "util/customwidgets.hpp"
38 #include "util/qt_dirs.hpp"
39
40 #include "components/interface_widgets.hpp"
41 #include "components/controller.hpp"
42 #include "components/playlist/playlist.hpp"
43 #include "dialogs/external.hpp"
44 #include "dialogs/firstrun.hpp"
45
46 #include "menus.hpp"
47 #include "recents.hpp"
48
49 #include <QCloseEvent>
50 #include <QKeyEvent>
51
52 #include <QUrl>
53 #include <QSize>
54 #include <QDate>
55
56 #include <QMenu>
57 #include <QMenuBar>
58 #include <QStatusBar>
59 #include <QLabel>
60 #include <QGroupBox>
61 #include <QPushButton>
62 #include <QStackedWidget>
63
64 #ifdef WIN32
65  #include <vlc_windows_interfaces.h>
66  #include <QBitmap>
67 #endif
68
69 #include <assert.h>
70
71 #include <vlc_keys.h> /* Wheel event */
72 #include <vlc_vout_window.h>
73 #include <vlc_vout_display.h>
74
75 // #define DEBUG_INTF
76 /* Callback prototypes */
77 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
78                         vlc_value_t old_val, vlc_value_t new_val, void *param );
79 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
80                        vlc_value_t old_val, vlc_value_t new_val, void *param );
81
82 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
83 {
84     /* Variables initialisation */
85     // need_components_update = false;
86     bgWidget             = NULL;
87     videoWidget          = NULL;
88     playlistWidget       = NULL;
89 #ifndef HAVE_MAEMO
90     sysTray              = NULL;
91 #endif
92     fullscreenControls   = NULL;
93     cryptedLabel         = NULL;
94     controls             = NULL;
95     inputC               = NULL;
96
97     b_hideAfterCreation  = false;
98     playlistVisible      = false; // FIXME remove
99     input_name           = "";
100
101     i_bg_height          = 0;
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
117     /* Set The Video In emebedded Mode or not */
118     videoEmbeddedFlag = var_InheritBool( p_intf, "embedded-video" );
119
120     /* Does the interface resize to video size or the opposite */
121     b_keep_size = !var_InheritBool( p_intf, "qt-video-autoresize" );
122
123     /* Are we in the enhanced always-video mode or not ? */
124     i_visualmode = var_InheritInteger( p_intf, "qt-display-mode" );
125
126     /* Do we want anoying popups or not */
127     notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
128
129     /* Set the other interface settings */
130     settings = getSettings();
131     settings->beginGroup( "MainWindow" );
132
133     /**
134      * Retrieve saved sizes for main window
135      *   mainBasedSize = based window size for normal mode
136      *                  (no video, no background)
137      *   mainVideoSize = window size with video (all modes)
138      **/
139     mainBasedSize = settings->value( "mainBasedSize", QSize( 350, 120 ) ).toSize();
140     mainVideoSize = settings->value( "mainVideoSize", QSize( 400, 300 ) ).toSize();
141
142
143     /**************
144      * Status Bar *
145      **************/
146     createStatusBar();
147
148     /**************************
149      *  UI and Widgets design
150      **************************/
151     setVLCWindowsTitle();
152     createMainWidget( settings );
153
154     /************
155      * Menu Bar *
156      ************/
157     QVLCMenu::createMenuBar( this, p_intf );
158     CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
159              this, destroyPopupMenu() );
160
161     /*********************************
162      * Create the Systray Management *
163      *********************************/
164     initSystray();
165
166     /********************
167      * Input Manager    *
168      ********************/
169     MainInputManager::getInstance( p_intf );
170
171 #ifdef WIN32
172     himl = NULL;
173     p_taskbl = NULL;
174     taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
175 #endif
176
177     /************************************************************
178      * Connect the input manager to the GUI elements it manages *
179      ************************************************************/
180     /**
181      * Connects on nameChanged()
182      * Those connects are different because options can impeach them to trigger.
183      **/
184     /* Main Interface statusbar */
185     CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
186              this, setName( const QString& ) );
187     /* and systray */
188 #ifndef HAVE_MAEMO
189     if( sysTray )
190     {
191         CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
192                  this, updateSystrayTooltipName( const QString& ) );
193     }
194 #endif
195     /* and title of the Main Interface*/
196     if( var_InheritBool( p_intf, "qt-name-in-title" ) )
197     {
198         CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
199                  this, setVLCWindowsTitle( const QString& ) );
200     }
201
202     /**
203      * CONNECTS on PLAY_STATUS
204      **/
205     /* Status on the systray */
206 #ifndef HAVE_MAEMO
207     if( sysTray )
208     {
209         CONNECT( THEMIM->getIM(), statusChanged( int ),
210                  this, updateSystrayTooltipStatus( int ) );
211     }
212 #endif
213
214     /* END CONNECTS ON IM */
215
216     /* VideoWidget connects for asynchronous calls */
217     connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
218              this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
219              Qt::BlockingQueuedConnection );
220     connect( this, SIGNAL(askReleaseVideo( void )),
221              this, SLOT(releaseVideoSlot( void )),
222              Qt::BlockingQueuedConnection );
223
224     if( videoWidget )
225     {
226         CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
227                  videoWidget, SetSizing( unsigned int, unsigned int ) );
228         CONNECT( this, askVideoSetFullScreen( bool ),
229                  videoWidget, SetFullScreen( bool ) );
230         CONNECT( videoWidget, keyPressed( QKeyEvent * ),
231                  this, handleKeyPress( QKeyEvent * ) );
232     }
233
234     CONNECT( this, askUpdate(), this, doComponentsUpdate() );
235     CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
236
237         /* Enable the popup menu in the MI */
238     setContextMenuPolicy( Qt::CustomContextMenu );
239     CONNECT( this, customContextMenuRequested( const QPoint& ),
240              this, popupMenu( const QPoint& ) );
241
242     /** END of CONNECTS**/
243
244
245     /************
246      * Callbacks
247      ************/
248     var_AddCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
249
250     /* Register callback for the intf-popupmenu variable */
251     var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
252
253
254     /**** FINAL SIZING and placement of interface */
255     settings->beginGroup( "MainWindow" );
256     QVLCTools::restoreWidgetPosition( settings, this, QSize(380, 60) );
257
258     /* resize to previously saved main window size if appicable */
259     if( b_keep_size )
260     {
261        if( i_visualmode == QT_ALWAYS_VIDEO_MODE ||
262            i_visualmode == QT_MINIMAL_MODE )
263        {
264            resize( mainVideoSize );
265        }
266        else
267        {
268            resize( mainBasedSize );
269        }
270     }
271
272     msg_Dbg( p_intf, "%i", stackCentralOldState );
273
274     /* Playlist */
275     int i_plVis = settings->value( "playlist-visible", 0 ).toInt();
276
277     settings->endGroup();
278
279     if( i_plVis ) togglePlaylist();
280
281     /* Final sizing and showing */
282     setVisible( !b_hideAfterCreation );
283     //setMinimumSize( QSize( 0, 0 ) );
284     //    setMinimumWidth( __MAX( controls->sizeHint().width(),
285     //                          menuBar()->sizeHint().width() ) );
286
287     debug();
288     /* And switch to minimal view if needed
289        Must be called after the show() */
290     if( i_visualmode == QT_MINIMAL_MODE )
291         toggleMinimalView( true );
292
293     /* Update the geometry : It is useful if you switch between
294        qt-display-modes */
295     updateGeometry();
296     resize( sizeHint() );
297 }
298
299 MainInterface::~MainInterface()
300 {
301     /* Unsure we hide the videoWidget before destroying it */
302     if( stackCentralOldState == VIDEO_TAB )
303         showBg();
304
305     /* Save playlist state */
306     if( playlistWidget )
307     {
308         if( !isDocked() )
309             QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
310
311         delete playlistWidget;
312     }
313
314 #ifdef WIN32
315     if( himl )
316         ImageList_Destroy( himl );
317     if(p_taskbl)
318         p_taskbl->vt->Release(p_taskbl);
319     CoUninitialize();
320 #endif
321
322     /* Be sure to kill the actionsManager... FIXME */
323     ActionsManager::killInstance();
324
325     /* Idem, FIXME */
326     ExtensionsManager::killInstance();
327
328     /* Delete the FSC controller */
329     delete fullscreenControls;
330
331     /* Save states */
332     settings->beginGroup( "MainWindow" );
333     settings->setValue( "pl-dock-status", (int)i_pl_dock );
334     settings->setValue( "playlist-visible", (int)playlistVisible );
335     settings->setValue( "adv-controls",
336                         getControlsVisibilityStatus() & CONTROLS_ADVANCED );
337
338     settings->setValue( "mainBasedSize", mainBasedSize );
339     settings->setValue( "mainVideoSize", mainVideoSize );
340
341     if( bgWidget )
342         settings->setValue( "backgroundSize", bgWidget->size() );
343
344     /* Save this size */
345     QVLCTools::saveWidgetPosition(settings, this);
346     settings->endGroup();
347
348     delete statusBar();
349
350     /* Unregister callbacks */
351     var_DelCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
352     var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
353
354     p_intf->p_sys->p_mi = NULL;
355 }
356
357 /*****************************
358  *   Main UI handling        *
359  *****************************/
360 void MainInterface::recreateToolbars()
361 {
362     //msg_Dbg( p_intf, "Recreating the toolbars" );
363     settings->beginGroup( "MainWindow" );
364     delete controls;
365     delete inputC;
366
367     controls = new ControlsWidget( p_intf, false, this ); /* FIXME */
368     CONNECT( controls, advancedControlsToggled( bool ),
369              this, doComponentsUpdate() );
370     CONNECT( controls, sizeChanged(),
371              this, doComponentsUpdate() );
372
373     inputC = new InputControlsWidget( p_intf, this );
374
375     mainLayout->insertWidget( 2, inputC );
376     mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
377                               controls );
378     settings->endGroup();
379 }
380
381 void MainInterface::createMainWidget( QSettings *settings )
382 {
383     /* Create the main Widget and the mainLayout */
384     QWidget *main = new QWidget;
385     setCentralWidget( main );
386     mainLayout = new QVBoxLayout( main );
387
388     /* Margins, spacing */
389     main->setContentsMargins( 0, 0, 0, 0 );
390     mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
391
392     /* */
393     stackCentralW = new QStackedWidget( main );
394
395     /* Bg Cone */
396     bgWidget = new BackgroundWidget( p_intf );
397     bgWidget->resize(
398             settings->value( "backgroundSize", QSize( 300, 200 ) ).toSize() );
399     bgWidget->updateGeometry();
400     stackCentralW->insertWidget( BACKG_TAB, bgWidget );
401
402
403     /* And video Outputs */
404     if( videoEmbeddedFlag )
405     {
406         videoWidget = new VideoWidget( p_intf );
407         stackCentralW->insertWidget( VIDEO_TAB, videoWidget );
408     }
409     mainLayout->insertWidget( 1, stackCentralW, 100 );
410
411
412     /* Create the CONTROLS Widget */
413     controls = new ControlsWidget( p_intf,
414                    settings->value( "adv-controls", false ).toBool(), this );
415     CONNECT( controls, advancedControlsToggled( bool ),
416              this, doComponentsUpdate() );
417     CONNECT( controls, sizeChanged(),
418              this, doComponentsUpdate() );
419     inputC = new InputControlsWidget( p_intf, this );
420
421     if( i_visualmode != QT_ALWAYS_VIDEO_MODE &&
422         i_visualmode != QT_MINIMAL_MODE )
423     {
424         hideStackWidget();
425         stackCentralOldState = HIDDEN_TAB;
426     }
427     else
428     {
429         showTab( BACKG_TAB );
430         stackCentralOldState = BACKG_TAB;
431     }
432
433
434     //mainLayout->setRowStretch( 1, 10 );
435     mainLayout->insertWidget( 2, inputC );
436     mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
437                               controls );
438
439     /* Visualisation */
440     /* Disabled for now, they SUCK */
441     #if 0
442     visualSelector = new VisualSelector( p_intf );
443     mainLayout->insertWidget( 0, visualSelector );
444     visualSelector->hide();
445     #endif
446
447     /* Finish the sizing */
448     main->updateGeometry();
449
450     getSettings()->endGroup();
451 #ifdef WIN32
452     if ( depth() > 8 )
453 #endif
454     /* Create the FULLSCREEN CONTROLS Widget */
455     if( var_InheritBool( p_intf, "qt-fs-controller" ) )
456     {
457         fullscreenControls = new FullscreenControllerWidget( p_intf, this );
458         CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
459                  this, handleKeyPress( QKeyEvent * ) );
460     }
461 }
462
463 inline void MainInterface::initSystray()
464 {
465 #ifndef HAVE_MAEMO
466     bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
467     bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
468
469     if( var_InheritBool( p_intf, "qt-start-minimized") )
470     {
471         if( b_systrayAvailable )
472         {
473             b_systrayWanted = true;
474             b_hideAfterCreation = true;
475         }
476         else
477             msg_Err( p_intf, "cannot start minimized without system tray bar" );
478     }
479
480     if( b_systrayAvailable && b_systrayWanted )
481         createSystray();
482 #endif
483 }
484
485 inline void MainInterface::createStatusBar()
486 {
487     /****************
488      *  Status Bar  *
489      ****************/
490     /* Widgets Creation*/
491     QStatusBar *statusBarr = statusBar();
492
493     TimeLabel *timeLabel = new TimeLabel( p_intf );
494     nameLabel = new QLabel( this );
495     nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
496                                       | Qt::TextSelectableByKeyboard );
497     SpeedLabel *speedLabel = new SpeedLabel( p_intf, "1.00x", this );
498
499     /* Styling those labels */
500     timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
501     speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
502     nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
503
504     /* and adding those */
505     statusBarr->addWidget( nameLabel, 8 );
506     statusBarr->addPermanentWidget( speedLabel, 0 );
507     statusBarr->addPermanentWidget( timeLabel, 0 );
508
509     /* timeLabel behaviour:
510        - double clicking opens the goto time dialog
511        - right-clicking and clicking just toggle between remaining and
512          elapsed time.*/
513     CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
514
515     CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
516              this, showCryptedLabel( bool ) );
517
518     connect( THEMIM->getIM(), SIGNAL(seekRequested(float)),
519              timeLabel, SLOT(setDisplayPosition(float)) );
520 }
521
522 #ifdef WIN32
523 void MainInterface::createTaskBarButtons()
524 {
525     taskbar_wmsg = WM_NULL;
526     /*Here is the code for the taskbar thumb buttons
527     FIXME:We need pretty buttons in 16x16 px that are handled correctly by masks in Qt
528     FIXME:the play button's picture doesn't changed to pause when clicked
529     */
530
531     CoInitialize( 0 );
532
533     if( S_OK == CoCreateInstance( &clsid_ITaskbarList,
534                 NULL, CLSCTX_INPROC_SERVER,
535                 &IID_ITaskbarList3,
536                 (void **)&p_taskbl) )
537     {
538         p_taskbl->vt->HrInit(p_taskbl);
539
540         if(himl = ImageList_Create( 15, //cx
541                         18, //cy
542                         ILC_COLOR,//flags
543                         4,//initial nb of images
544                         0//nb of images that can be added
545                         ))
546         {
547             QPixmap img   = QPixmap(":/toolbar/previous_b");
548             QPixmap img2  = QPixmap(":/toolbar/pause_b");
549             QPixmap img3  = QPixmap(":/toolbar/play_b");
550             QPixmap img4  = QPixmap(":/toolbar/next_b");
551             QBitmap mask  = img.createMaskFromColor(Qt::transparent);
552             QBitmap mask2 = img2.createMaskFromColor(Qt::transparent);
553             QBitmap mask3 = img3.createMaskFromColor(Qt::transparent);
554             QBitmap mask4 = img4.createMaskFromColor(Qt::transparent);
555
556             if(-1 == ImageList_Add(himl, img.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask.toWinHBITMAP()))
557                 msg_Err( p_intf, "ImageList_Add failed" );
558             if(-1 == ImageList_Add(himl, img2.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask2.toWinHBITMAP()))
559                 msg_Err( p_intf, "ImageList_Add failed" );
560             if(-1 == ImageList_Add(himl, img3.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask3.toWinHBITMAP()))
561                 msg_Err( p_intf, "ImageList_Add failed" );
562             if(-1 == ImageList_Add(himl, img4.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask4.toWinHBITMAP()))
563                 msg_Err( p_intf, "ImageList_Add failed" );
564         }
565
566         // Define an array of two buttons. These buttons provide images through an
567         // image list and also provide tooltips.
568         DWORD dwMask = THB_BITMAP | THB_FLAGS;
569
570         THUMBBUTTON thbButtons[3];
571         thbButtons[0].dwMask = dwMask;
572         thbButtons[0].iId = 0;
573         thbButtons[0].iBitmap = 0;
574         thbButtons[0].dwFlags = THBF_HIDDEN;
575
576         thbButtons[1].dwMask = dwMask;
577         thbButtons[1].iId = 1;
578         thbButtons[1].iBitmap = 2;
579         thbButtons[1].dwFlags = THBF_HIDDEN;
580
581         thbButtons[2].dwMask = dwMask;
582         thbButtons[2].iId = 2;
583         thbButtons[2].iBitmap = 3;
584         thbButtons[2].dwFlags = THBF_HIDDEN;
585
586         HRESULT hr = p_taskbl->vt->ThumbBarSetImageList(p_taskbl, winId(), himl );
587         if(S_OK != hr)
588             msg_Err( p_intf, "ThumbBarSetImageList failed with error %08x", hr );
589         else
590         {
591             hr = p_taskbl->vt->ThumbBarAddButtons(p_taskbl, winId(), 3, thbButtons);
592             if(S_OK != hr)
593                 msg_Err( p_intf, "ThumbBarAddButtons failed with error %08x", hr );
594         }
595         CONNECT( THEMIM->getIM(), statusChanged( int ), this, changeThumbbarButtons( int ) );
596     }
597     else
598     {
599         himl = NULL;
600         p_taskbl = NULL;
601     }
602
603 }
604
605 bool MainInterface::winEvent ( MSG * msg, long * result )
606 {
607     if (msg->message == taskbar_wmsg)
608     {
609         //We received the taskbarbuttoncreated, now we can really create th buttons
610         createTaskBarButtons();
611     }
612
613     short cmd;
614     switch( msg->message )
615     {
616         case WM_COMMAND:
617             if (HIWORD(msg->wParam) == THBN_CLICKED)
618             {
619                 switch(LOWORD(msg->wParam))
620                 {
621                     case 0:
622                         THEMIM->prev();
623                         break;
624                     case 1:
625                         THEMIM->togglePlayPause();
626                         break;
627                     case 2:
628                         THEMIM->next();
629                         break;
630                 }
631             }
632             break;
633         case WM_APPCOMMAND:
634             cmd = GET_APPCOMMAND_LPARAM(msg->lParam);
635             switch(cmd)
636             {
637                 case APPCOMMAND_MEDIA_PLAY_PAUSE:
638                     THEMIM->togglePlayPause();
639                     break;
640                 case APPCOMMAND_MEDIA_PLAY:
641                     THEMIM->play();
642                     break;
643                 case APPCOMMAND_MEDIA_PAUSE:
644                     THEMIM->pause();
645                     break;
646                 case APPCOMMAND_MEDIA_PREVIOUSTRACK:
647                     THEMIM->prev();
648                     break;
649                 case APPCOMMAND_MEDIA_NEXTTRACK:
650                     THEMIM->next();
651                     break;
652                 case APPCOMMAND_MEDIA_STOP:
653                     THEMIM->stop();
654                     break;
655                 case APPCOMMAND_VOLUME_DOWN:
656                     THEAM->AudioDown();
657                     break;
658                 case APPCOMMAND_VOLUME_UP:
659                     THEAM->AudioUp();
660                     break;
661                 case APPCOMMAND_VOLUME_MUTE:
662                     THEAM->toggleMuteAudio();
663                     break;
664                 default:
665                      msg_Dbg( p_intf, "unknown APPCOMMAND = %d", cmd);
666                      break;
667             }
668             break;
669     }
670     return false;
671 }
672 #endif
673
674 /**********************************************************************
675  * Handling of sizing of the components
676  **********************************************************************/
677
678 /* This function is probably wrong, but we don't have many many choices...
679    Since we can't know from the playlist Widget if we are inside a dock or not,
680    because the playlist Widget can be called by THEDP, as a separate windows for
681    the skins.
682    Maybe the other solution is to redefine the sizeHint() of the playlist and
683    ask _parent->isFloating()...
684    If you think this would be better, please FIXME it...
685 */
686
687 QSize MainInterface::sizeHint() const
688 {
689 #if 0
690     if( b_keep_size )
691     {
692         if( i_visualmode == QT_ALWAYS_VIDEO_MODE ||
693             i_visualmode == QT_MINIMAL_MODE )
694         {
695                 return mainVideoSize;
696         }
697         else
698         {
699             if( VISIBLE( bgWidget) ||
700                 ( videoIsActive && videoWidget->isVisible() )
701               )
702                 return mainVideoSize;
703             else
704                 return mainBasedSize;
705         }
706     }
707 #endif
708
709     int nwidth  = __MAX( controls->sizeHint().width(),
710                          menuBar()->sizeHint().width() );
711
712     int nheight = controls->isVisible() ?
713                   controls->size().height()
714                   + inputC->size().height()
715                   + menuBar()->size().height()
716                   + statusBar()->size().height()
717                   : 0 ;
718
719     if( stackCentralW->isVisible() )
720     {
721         nheight += stackCentralW->height();
722         nwidth  = __MAX( nwidth, stackCentralW->width() );
723     }
724
725 /*    if( VISIBLE( bgWidget ) )
726     {
727         msg_Warn( p_intf, "Hello here" );
728         if( i_bg_height )
729             nheight += i_bg_height;
730         else
731             nheight += bgWidget->size().height();
732         nwidth  = __MAX( nwidth, bgWidget->size().width() );
733     }
734     else if( videoIsActive && videoWidget->isVisible() )
735     {
736         msg_Warn( p_intf, "Hello there" );
737         nheight += videoWidget->sizeHint().height();
738         nwidth  = __MAX( nwidth, videoWidget->sizeHint().width() );
739     }*/
740 #if 0
741     if( !dockPL->isFloating() && dockPL->isVisible() && dockPL->widget()  )
742     {
743         nheight += dockPL->size().height();
744         nwidth = __MAX( nwidth, dockPL->size().width() );
745         msg_Warn( p_intf, "3 %i %i", nheight, nwidth );
746     }
747 #endif
748     return QSize( nwidth, nheight );
749 }
750
751
752 /* Video widget cannot do this synchronously as it runs in another thread */
753 /* Well, could it, actually ? Probably dangerous ... */
754
755 /* This function is called:
756    - toggling of minimal View
757    - through askUpdate() by Vout thread request video and resize video (zoom)
758    - Advanced buttons toggled
759  */
760 void MainInterface::doComponentsUpdate()
761 {
762     if( isFullScreen() || isMaximized() ) return;
763
764 //    msg_Warn( p_intf, "Updating the geometry" );
765     /* Here we resize to sizeHint() and not adjustsize because we want
766        the videoWidget to be exactly the correctSize */
767
768 #ifndef NDEBUG
769     debug();
770 #endif
771     /* This is WRONG, but I believe there is a Qt bug here */
772     setMinimumSize( 0, 0 );
773     resize( sizeHint() );
774
775     //adjustSize() ; /* This is not needed, but might help in the future */
776 }
777
778 void MainInterface::debug()
779 {
780 #ifndef NDEBUG
781     msg_Dbg( p_intf, "Stack Size: %i - %i", stackCentralW->size().height(), size().width() );
782     if( videoEmbeddedFlag )
783         msg_Dbg( p_intf, "Stack Size: %i - %i",
784                  stackCentralW->widget( VIDEO_TAB )->size().height(),
785                  stackCentralW->widget( VIDEO_TAB )->size().width() );
786     else
787         msg_Dbg( p_intf, "no embedded video" );
788
789     msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
790     msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
791     //msg_Dbg( p_intf, "maximumsize: %i - %i", maximumSize().height(), maximumSize().width() );
792
793     msg_Dbg( p_intf, "Stack minimumsize: %i - %i", stackCentralW->minimumSize().height(), stackCentralW->minimumSize().width() );
794     msg_Dbg( p_intf, "Controls minimumsize: %i - %i", controls->minimumSize().height(), controls->minimumSize().width() );
795     msg_Dbg( p_intf, "Central minimumsize: %i - %i", centralWidget()->minimumSize().height(), centralWidget()->minimumSize().width() );
796     msg_Dbg( p_intf, "Menu minimumsize: %i - %i", menuBar()->minimumSize().height(), menuBar()->minimumSize().width() );
797     msg_Dbg( p_intf, "Input minimuSize: %i - %i", inputC->minimumSize().height(), inputC->minimumSize().width() );
798     msg_Dbg( p_intf, "Status minimumsize: %i - %i", statusBar()->minimumSize().height(), statusBar()->minimumSize().width() );
799     msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
800
801     /*if( videoWidget && videoWidget->isVisible() )
802     {
803         msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
804         msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
805     }*/
806 #endif
807 }
808
809 inline void MainInterface::showTab( int i_tab )
810 {
811 #ifdef DEBUG_INTF
812     msg_Err( p_intf, "showTab %i", i_tab );
813     msg_Warn( p_intf, "Old stackCentralOldState %i", stackCentralOldState );
814 #endif
815     stackCentralOldState = stackCentralW->isVisible() ? stackCentralW->currentIndex()
816                                           : HIDDEN_TAB;
817 #ifdef DEBUG_INTF
818     msg_Warn( p_intf, "State change %i %i",  stackCentralW->currentIndex(), i_tab );
819 #endif
820
821     if( i_visualmode == QT_NORMAL_MODE )
822     {
823         stackCentralW->setVisible( i_tab != HIDDEN_TAB );
824         doComponentsUpdate(); // resize the player
825     }
826     else
827         if( i_tab == HIDDEN_TAB ) i_tab = BACKG_TAB;
828
829     stackCentralW->setCurrentIndex( i_tab );
830
831 #ifdef DEBUG_INTF
832     msg_Warn( p_intf, "New stackCentralOldState %i", stackCentralOldState );
833 #endif
834 }
835
836 inline void MainInterface::restoreStackOldWidget()
837 {
838 #ifdef DEBUG_INTF
839     msg_Warn( p_intf, "Old stackCentralOldState %i", stackCentralOldState );
840 #endif
841     int temp = stackCentralW->isVisible() ? stackCentralW->currentIndex()
842                                           : HIDDEN_TAB;
843     stackCentralW->setCurrentIndex( stackCentralOldState );
844     if( i_visualmode == QT_NORMAL_MODE )
845     {
846         stackCentralW->setVisible( stackCentralOldState != HIDDEN_TAB );
847         doComponentsUpdate(); // resize the player
848     }
849
850     stackCentralOldState = temp;
851 #ifdef DEBUG_INTF
852     msg_Warn( p_intf, "Debug %i %i", temp, stackCentralW->currentIndex() );
853 #endif
854 }
855
856 void MainInterface::destroyPopupMenu()
857 {
858     QVLCMenu::PopupMenu( p_intf, false );
859 }
860
861 void MainInterface::toggleFSC()
862 {
863    if( !fullscreenControls ) return;
864
865    IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type, 0 );
866    QApplication::postEvent( fullscreenControls, eShow );
867 }
868
869 void MainInterface::popupMenu( const QPoint &p )
870 {
871     /* Ow, that's ugly: don't show the popup menu if cursor over
872      * the main menu bar or the status bar */
873     if( !childAt( p ) || ( ( childAt( p ) != menuBar() )
874                         && ( childAt( p )->parentWidget() != statusBar() ) ) )
875         QVLCMenu::PopupMenu( p_intf, true );
876 }
877
878 /****************************************************************************
879  * Video Handling
880  ****************************************************************************/
881
882 /* This event is used to deal with the fullscreen and always on top
883    issue conflict (bug in wx) */
884 class SetVideoOnTopQtEvent : public QEvent
885 {
886 public:
887     SetVideoOnTopQtEvent( bool _onTop ) :
888       QEvent( (QEvent::Type)SetVideoOnTopEvent_Type ), onTop( _onTop)
889     {}
890
891     bool OnTop() const { return onTop; }
892
893 private:
894     bool onTop;
895 };
896
897 /**
898  * NOTE:
899  * You must note change the state of this object or other Qt4 UI objects,
900  * from the video output thread - only from the Qt4 UI main loop thread.
901  * All window provider queries must be handled through signals or events.
902  * That's why we have all those emit statements...
903  */
904 WId MainInterface::getVideo( int *pi_x, int *pi_y,
905                              unsigned int *pi_width, unsigned int *pi_height )
906 {
907     if( !videoWidget )
908         return 0;
909
910     /* This is a blocking call signal. Results are returned through pointers.
911      * Beware of deadlocks! */
912     WId id;
913     emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
914     return id;
915 }
916
917 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
918                                   unsigned *pi_width, unsigned *pi_height )
919 {
920     /* Request the videoWidget */
921     WId ret = videoWidget->request( pi_x, pi_y,
922                                     pi_width, pi_height, b_keep_size );
923     *p_id = ret;
924     if( ret ) /* The videoWidget is available */
925     {
926         /* ask videoWidget to show */
927         videoWidget->SetSizing( *pi_width, *pi_height );
928
929         /* Consider the video active now */
930         showVideo();
931
932         stackCentralW->resize( *pi_width, *pi_height );
933
934         emit askUpdate();
935     }
936 }
937
938
939
940 /* Asynchronous call from the WindowClose function */
941 void MainInterface::releaseVideo( void )
942 {
943     emit askReleaseVideo( );
944 }
945
946 /* Function that is CONNECTED to the previous emit */
947 void MainInterface::releaseVideoSlot( void )
948 {
949     videoWidget->release( );
950
951     restoreStackOldWidget();
952
953     /* Try to resize, except when you are in Fullscreen mode */
954 //    doComponentsUpdate();
955 }
956
957 /* Asynchronous call from WindowControl function */
958 int MainInterface::controlVideo( int i_query, va_list args )
959 {
960     /* Debug to check if VOUT_WINDOW_SET_SIZE is called, because this is broken now */
961     msg_Warn( p_intf, "Control Video: %i", i_query );
962     switch( i_query )
963     {
964     case VOUT_WINDOW_SET_SIZE:
965     {
966         unsigned int i_width  = va_arg( args, unsigned int );
967         unsigned int i_height = va_arg( args, unsigned int );
968         emit askVideoToResize( i_width, i_height );
969         emit askUpdate();
970         return VLC_EGENERIC;
971     }
972     case VOUT_WINDOW_SET_STATE:
973     {
974         unsigned i_arg = va_arg( args, unsigned );
975         unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
976         QApplication::postEvent( this, new SetVideoOnTopQtEvent( on_top ) );
977         return VLC_SUCCESS;
978     }
979     case VOUT_WINDOW_SET_FULLSCREEN:
980     {
981         bool b_fs = va_arg( args, int );
982         emit askVideoSetFullScreen( b_fs );
983         return VLC_SUCCESS;
984     }
985     default:
986         msg_Warn( p_intf, "unsupported control query" );
987         return VLC_EGENERIC;
988     }
989 }
990
991 /*****************************************************************************
992  * Playlist, Visualisation and Menus handling
993  *****************************************************************************/
994 /**
995  * Toggle the playlist widget or dialog
996  **/
997 void MainInterface::createPlaylist( bool b_show )
998 {
999     playlistWidget = new PlaylistWidget( p_intf, this );
1000
1001     i_pl_dock = PL_BOTTOM;
1002     /* i_pl_dock = (pl_dock_e)getSettings()
1003       ->value( "pl-dock-status", PL_UNDOCKED ).toInt(); */
1004
1005     if( i_pl_dock == PL_UNDOCKED )
1006     {
1007         playlistWidget->setWindowFlags( Qt::Window );
1008
1009         /* This will restore the geometry but will not work for position,
1010            because of parenting */
1011         QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
1012                 playlistWidget, QSize( 600, 300 ) );
1013     }
1014     else
1015     {
1016 #ifdef DEBUG_INTF
1017         msg_Warn( p_intf, "Here %i", stackCentralW->currentIndex() );
1018 #endif
1019         stackCentralW->insertWidget( PLAYL_TAB, playlistWidget );
1020 #ifdef DEBUG_INTF
1021         msg_Warn( p_intf, "Here %i", stackCentralW->currentIndex() );
1022 #endif
1023     }
1024
1025     if( b_show )
1026     {
1027         playlistVisible = true;
1028         stackCentralW->show();
1029     }
1030 }
1031
1032 void MainInterface::togglePlaylist()
1033 {
1034 #ifdef DEBUG_INTF
1035     msg_Warn( p_intf, "Here toggling %i %i", stackCentralW->currentIndex(), stackCentralOldState );
1036 #endif
1037     if( !playlistWidget )
1038     {
1039         createPlaylist( true );
1040     }
1041 #ifdef DEBUG_INTF
1042     msg_Warn( p_intf, "Here toggling %i %i", stackCentralW->currentIndex(), stackCentralOldState );
1043
1044 #endif
1045     if( i_pl_dock != PL_UNDOCKED )
1046     {
1047         /* Playlist not visible */
1048         if( stackCentralW->currentIndex() != PLAYL_TAB )
1049         {
1050             showTab( PLAYL_TAB );
1051             stackCentralW->show();
1052         }
1053         else
1054         {
1055             restoreStackOldWidget();
1056         }
1057         playlistVisible = ( stackCentralW->currentIndex() == PLAYL_TAB );
1058         //doComponentsUpdate(); //resize( sizeHint() );
1059     }
1060 }
1061
1062 /* Function called from the menu to undock the playlist */
1063 void MainInterface::undockPlaylist()
1064 {
1065 //    dockPL->setFloating( true );
1066 //    adjustSize();
1067 }
1068
1069 void MainInterface::dockPlaylist( pl_dock_e i_pos )
1070 {
1071 }
1072
1073 void MainInterface::toggleMinimalView( bool b_switch )
1074 {
1075     if( i_visualmode != QT_ALWAYS_VIDEO_MODE &&
1076         i_visualmode != QT_MINIMAL_MODE )
1077     { /* NORMAL MODE then */
1078         stackCentralW->show();
1079         if( !videoWidget || stackCentralW->currentIndex() != VIDEO_TAB )
1080         {
1081             showBg();
1082         }
1083         else
1084         {
1085             /* If video is visible, then toggle the status of bgWidget */
1086             //bgWasVisible = !bgWasVisible;
1087             if( stackCentralOldState == BACKG_TAB )
1088                 stackCentralOldState = HIDDEN_TAB;
1089             else
1090                 stackCentralOldState = BACKG_TAB;
1091         }
1092     }
1093
1094     i_bg_height = stackCentralW->height();
1095
1096     menuBar()->setVisible( !b_switch );
1097     controls->setVisible( !b_switch );
1098     statusBar()->setVisible( !b_switch );
1099     inputC->setVisible( !b_switch );
1100
1101     doComponentsUpdate();
1102
1103     emit minimalViewToggled( b_switch );
1104 }
1105
1106 /* toggling advanced controls buttons */
1107 void MainInterface::toggleAdvanced()
1108 {
1109     controls->toggleAdvanced();
1110 //    if( fullscreenControls ) fullscreenControls->toggleAdvanced();
1111 }
1112
1113 /* Get the visibility status of the controls (hidden or not, advanced or not) */
1114 int MainInterface::getControlsVisibilityStatus()
1115 {
1116     return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
1117                 + CONTROLS_ADVANCED * controls->b_advancedVisible );
1118 }
1119
1120 #if 0
1121 void MainInterface::visual()
1122 {
1123     if( !VISIBLE( visualSelector) )
1124     {
1125         visualSelector->show();
1126         if( !THEMIM->getIM()->hasVideo() )
1127         {
1128             /* Show the background widget */
1129         }
1130         visualSelectorEnabled = true;
1131     }
1132     else
1133     {
1134         /* Stop any currently running visualization */
1135         visualSelector->hide();
1136         visualSelectorEnabled = false;
1137     }
1138     doComponentsUpdate();
1139 }
1140 #endif
1141
1142 /************************************************************************
1143  * Other stuff
1144  ************************************************************************/
1145 void MainInterface::setName( const QString& name )
1146 {
1147     input_name = name; /* store it for the QSystray use */
1148     /* Display it in the status bar, but also as a Tooltip in case it doesn't
1149        fit in the label */
1150     nameLabel->setText( " " + name + " " );
1151     nameLabel->setToolTip( " " + name +" " );
1152 }
1153
1154 /**
1155  * Give the decorations of the Main Window a correct Name.
1156  * If nothing is given, set it to VLC...
1157  **/
1158 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
1159 {
1160     if( aTitle.isEmpty() )
1161     {
1162         setWindowTitle( qtr( "VLC media player" ) );
1163     }
1164     else
1165     {
1166         setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
1167     }
1168 }
1169
1170 void MainInterface::showCryptedLabel( bool b_show )
1171 {
1172     if( cryptedLabel == NULL )
1173     {
1174         cryptedLabel = new QLabel;
1175         // The lock icon is not the right one for DRM protection/scrambled.
1176         //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
1177         cryptedLabel->setText( "DRM" );
1178         statusBar()->addWidget( cryptedLabel );
1179     }
1180
1181     cryptedLabel->setVisible( b_show );
1182 }
1183
1184 void MainInterface::showBuffering( float f_cache )
1185 {
1186     QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
1187     statusBar()->showMessage( amount, 1000 );
1188 }
1189
1190 /*****************************************************************************
1191  * Systray Icon and Systray Menu
1192  *****************************************************************************/
1193 #ifndef HAVE_MAEMO
1194 /**
1195  * Create a SystemTray icon and a menu that would go with it.
1196  * Connects to a click handler on the icon.
1197  **/
1198 void MainInterface::createSystray()
1199 {
1200     QIcon iconVLC;
1201     if( QDate::currentDate().dayOfYear() >= 354 )
1202         iconVLC =  QIcon( ":/logo/vlc128-christmas.png" );
1203     else
1204         iconVLC =  QIcon( ":/logo/vlc128.png" );
1205     sysTray = new QSystemTrayIcon( iconVLC, this );
1206     sysTray->setToolTip( qtr( "VLC media player" ));
1207
1208     systrayMenu = new QMenu( qtr( "VLC media player" ), this );
1209     systrayMenu->setIcon( iconVLC );
1210
1211     QVLCMenu::updateSystrayMenu( this, p_intf, true );
1212     sysTray->show();
1213
1214     CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
1215             this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
1216 }
1217
1218 /**
1219  * Updates the Systray Icon's menu and toggle the main interface
1220  */
1221 void MainInterface::toggleUpdateSystrayMenu()
1222 {
1223     /* If hidden, show it */
1224     if( isHidden() )
1225     {
1226         show();
1227         activateWindow();
1228     }
1229     else if( isMinimized() )
1230     {
1231         /* Minimized */
1232         showNormal();
1233         activateWindow();
1234     }
1235     else
1236     {
1237         /* Visible (possibly under other windows) */
1238 #ifdef WIN32
1239         /* check if any visible window is above vlc in the z-order,
1240          * but ignore the ones always on top
1241          * and the ones which can't be activated */
1242         WINDOWINFO wi;
1243         HWND hwnd;
1244         wi.cbSize = sizeof( WINDOWINFO );
1245         for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1246                 hwnd && ( !IsWindowVisible( hwnd ) ||
1247                     ( GetWindowInfo( hwnd, &wi ) &&
1248                       (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1249                 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1250             if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1251                 (wi.dwExStyle&WS_EX_TOPMOST) )
1252             {
1253                 hide();
1254             }
1255             else
1256             {
1257                 activateWindow();
1258             }
1259 #else
1260         hide();
1261 #endif
1262     }
1263     QVLCMenu::updateSystrayMenu( this, p_intf );
1264 }
1265
1266 void MainInterface::handleSystrayClick(
1267                                     QSystemTrayIcon::ActivationReason reason )
1268 {
1269     switch( reason )
1270     {
1271         case QSystemTrayIcon::Trigger:
1272         case QSystemTrayIcon::DoubleClick:
1273             toggleUpdateSystrayMenu();
1274             break;
1275         case QSystemTrayIcon::MiddleClick:
1276             sysTray->showMessage( qtr( "VLC media player" ),
1277                     qtr( "Control menu for the player" ),
1278                     QSystemTrayIcon::Information, 3000 );
1279             break;
1280         default:
1281             break;
1282     }
1283 }
1284
1285 /**
1286  * Updates the name of the systray Icon tooltip.
1287  * Doesn't check if the systray exists, check before you call it.
1288  **/
1289 void MainInterface::updateSystrayTooltipName( const QString& name )
1290 {
1291     if( name.isEmpty() )
1292     {
1293         sysTray->setToolTip( qtr( "VLC media player" ) );
1294     }
1295     else
1296     {
1297         sysTray->setToolTip( name );
1298         if( notificationEnabled && ( isHidden() || isMinimized() ) )
1299         {
1300             sysTray->showMessage( qtr( "VLC media player" ), name,
1301                     QSystemTrayIcon::NoIcon, 3000 );
1302         }
1303     }
1304
1305     QVLCMenu::updateSystrayMenu( this, p_intf );
1306 }
1307
1308 /**
1309  * Updates the status of the systray Icon tooltip.
1310  * Doesn't check if the systray exists, check before you call it.
1311  **/
1312 void MainInterface::updateSystrayTooltipStatus( int i_status )
1313 {
1314     switch( i_status )
1315     {
1316         case  0:
1317         case  END_S:
1318             {
1319                 sysTray->setToolTip( qtr( "VLC media player" ) );
1320                 break;
1321             }
1322         case PLAYING_S:
1323             {
1324                 sysTray->setToolTip( input_name );
1325                 break;
1326             }
1327         case PAUSE_S:
1328             {
1329                 sysTray->setToolTip( input_name + " - "
1330                         + qtr( "Paused") );
1331                 break;
1332             }
1333     }
1334     QVLCMenu::updateSystrayMenu( this, p_intf );
1335 }
1336 #endif
1337
1338 /************************************************************************
1339  * D&D Events
1340  ************************************************************************/
1341 void MainInterface::dropEvent(QDropEvent *event)
1342 {
1343     dropEventPlay( event, true );
1344 }
1345
1346 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1347 {
1348     event->setDropAction( Qt::CopyAction );
1349     if( !event->possibleActions() & Qt::CopyAction )
1350         return;
1351
1352     const QMimeData *mimeData = event->mimeData();
1353
1354     /* D&D of a subtitles file, add it on the fly */
1355     if( mimeData->urls().size() == 1 && THEMIM->getIM()->hasInput() )
1356     {
1357         if( !input_AddSubtitle( THEMIM->getInput(),
1358                  qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1359                  true ) )
1360         {
1361             event->accept();
1362             return;
1363         }
1364     }
1365
1366     bool first = b_play;
1367     foreach( const QUrl &url, mimeData->urls() )
1368     {
1369         QString s = toNativeSeparators( url.toLocalFile() );
1370
1371         if( s.length() > 0 ) {
1372             char* psz_uri = make_URI( qtu(s) );
1373             playlist_Add( THEPL, psz_uri, NULL,
1374                           PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1375                           PLAYLIST_END, true, pl_Unlocked );
1376             free( psz_uri );
1377             first = false;
1378             RecentsMRL::getInstance( p_intf )->addRecent( s );
1379         }
1380     }
1381     event->accept();
1382 }
1383 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1384 {
1385      event->acceptProposedAction();
1386 }
1387 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1388 {
1389      event->acceptProposedAction();
1390 }
1391 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1392 {
1393      event->accept();
1394 }
1395
1396 /************************************************************************
1397  * Events stuff
1398  ************************************************************************/
1399 void MainInterface::customEvent( QEvent *event )
1400 {
1401 #if 0
1402     if( event->type() == PLDockEvent_Type )
1403     {
1404         PlaylistDialog::killInstance();
1405         playlistEmbeddedFlag = true;
1406         menuBar()->clear();
1407         QVLCMenu::createMenuBar(this, p_intf, true, visualSelectorEnabled);
1408         togglePlaylist();
1409     }
1410 #endif
1411     /*else */
1412     if ( event->type() == (int)SetVideoOnTopEvent_Type )
1413     {
1414         SetVideoOnTopQtEvent* p_event = (SetVideoOnTopQtEvent*)event;
1415         if( p_event->OnTop() )
1416             setWindowFlags( windowFlags() | Qt::WindowStaysOnTopHint );
1417         else
1418             setWindowFlags( windowFlags() & ~Qt::WindowStaysOnTopHint );
1419         show(); /* necessary to apply window flags */
1420     }
1421 }
1422
1423 void MainInterface::keyPressEvent( QKeyEvent *e )
1424 {
1425     handleKeyPress( e );
1426 }
1427
1428 void MainInterface::handleKeyPress( QKeyEvent *e )
1429 {
1430     if( ( e->modifiers() &  Qt::ControlModifier ) && ( e->key() == Qt::Key_H )
1431           && !menuBar()->isVisible() )
1432     {
1433         toggleMinimalView( false );
1434         e->accept();
1435     }
1436
1437     int i_vlck = qtEventToVLCKey( e );
1438     if( i_vlck > 0 )
1439     {
1440         var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1441         e->accept();
1442     }
1443     else
1444         e->ignore();
1445 }
1446
1447 void MainInterface::resizeEvent( QResizeEvent * event )
1448 {
1449 #if 0
1450     if( b_keep_size )
1451     {
1452         if( i_visualmode == QT_ALWAYS_VIDEO_MODE ||
1453             i_visualmode == QT_MINIMAL_MODE )
1454         {
1455                 mainVideoSize = size();
1456         }
1457         else
1458         {
1459             if( VISIBLE( bgWidget) ||
1460                 ( videoIsActive && videoWidget->isVisible() )
1461               )
1462                 mainVideoSize = size();
1463             else
1464                 mainBasedSize = size();
1465         }
1466     }
1467 #endif
1468     QVLCMW::resizeEvent( event );
1469     msg_Dbg( p_intf, "Resize Event, height: %i", size().height() );
1470 }
1471
1472 void MainInterface::wheelEvent( QWheelEvent *e )
1473 {
1474     int i_vlckey = qtWheelEventToVLCKey( e );
1475     var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1476     e->accept();
1477 }
1478
1479 void MainInterface::closeEvent( QCloseEvent *e )
1480 {
1481     e->accept();
1482     hide();
1483     THEDP->quit();
1484 }
1485
1486 void MainInterface::toggleFullScreen( void )
1487 {
1488     if( isFullScreen() )
1489     {
1490         showNormal();
1491         emit askUpdate(); // Needed if video was launched after the F11
1492         emit fullscreenInterfaceToggled( false );
1493     }
1494     else
1495     {
1496         showFullScreen();
1497         emit fullscreenInterfaceToggled( true );
1498     }
1499
1500 }
1501
1502 //moc doesn't know about #ifdef, so we have to build this method for every platform
1503 void MainInterface::changeThumbbarButtons( int i_status)
1504 {
1505 #ifdef WIN32
1506     // Define an array of three buttons. These buttons provide images through an
1507     // image list and also provide tooltips.
1508     DWORD dwMask = THB_BITMAP | THB_FLAGS;
1509
1510     THUMBBUTTON thbButtons[3];
1511     //prev
1512     thbButtons[0].dwMask = dwMask;
1513     thbButtons[0].iId = 0;
1514     thbButtons[0].iBitmap = 0;
1515
1516     //play/pause
1517     thbButtons[1].dwMask = dwMask;
1518     thbButtons[1].iId = 1;
1519
1520     //next
1521     thbButtons[2].dwMask = dwMask;
1522     thbButtons[2].iId = 2;
1523     thbButtons[2].iBitmap = 3;
1524
1525     switch( i_status )
1526     {
1527         case PLAYING_S:
1528             {
1529                 thbButtons[0].dwFlags = THBF_ENABLED;
1530                 thbButtons[1].dwFlags = THBF_ENABLED;
1531                 thbButtons[2].dwFlags = THBF_ENABLED;
1532                 thbButtons[1].iBitmap = 1;
1533                 break;
1534             }
1535         case PAUSE_S:
1536             {
1537                 thbButtons[0].dwFlags = THBF_ENABLED;
1538                 thbButtons[1].dwFlags = THBF_ENABLED;
1539                 thbButtons[2].dwFlags = THBF_ENABLED;
1540                 thbButtons[1].iBitmap = 2;
1541                 break;
1542             }
1543         default:
1544             return;
1545     }
1546     HRESULT hr =  p_taskbl->vt->ThumbBarUpdateButtons(p_taskbl, this->winId(), 3, thbButtons);
1547     if(S_OK != hr)
1548         msg_Err( p_intf, "ThumbBarUpdateButtons failed with error %08x", hr );
1549 #else
1550     ;
1551 #endif
1552 }
1553
1554 /*****************************************************************************
1555  * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1556  *  We don't show the menu directly here because we don't want the
1557  *  caller to block for a too long time.
1558  *****************************************************************************/
1559 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1560                         vlc_value_t old_val, vlc_value_t new_val, void *param )
1561 {
1562     intf_thread_t *p_intf = (intf_thread_t *)param;
1563
1564     if( p_intf->pf_show_dialog )
1565     {
1566         p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1567                                 new_val.b_bool, NULL );
1568     }
1569
1570     return VLC_SUCCESS;
1571 }
1572
1573 /*****************************************************************************
1574  * IntfShowCB: callback triggered by the intf-show libvlc variable.
1575  *****************************************************************************/
1576 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1577                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1578 {
1579     intf_thread_t *p_intf = (intf_thread_t *)param;
1580     p_intf->p_sys->p_mi->toggleFSC();
1581
1582     /* Show event */
1583      return VLC_SUCCESS;
1584 }