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