]> git.sesse.net Git - vlc/blob - modules/gui/qt4/main_interface.cpp
Qt4 - Comments about TODO and FIXMEs on the main_interface, for my holidays :D
[vlc] / modules / gui / qt4 / main_interface.cpp
1 /*****************************************************************************
2  * main_interface.cpp : Main interface
3  ****************************************************************************
4  * Copyright (C) 2006-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *          Jean-Baptiste Kempf <jb@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include "qt4.hpp"
26 #include "main_interface.hpp"
27 #include "input_manager.hpp"
28 #include "util/qvlcframe.hpp"
29 #include "util/customwidgets.hpp"
30 #include "dialogs_provider.hpp"
31 #include "components/interface_widgets.hpp"
32 #include "dialogs/playlist.hpp"
33 #include "menus.hpp"
34
35 #include <QMenuBar>
36 #include <QCloseEvent>
37 #include <QPushButton>
38 #include <QStatusBar>
39 #include <QKeyEvent>
40 #include <QUrl>
41 #include <QSystemTrayIcon>
42 #include <QSize>
43 #include <QMenu>
44 #include <QLabel>
45
46 #include <assert.h>
47 #include <vlc_keys.h>
48 #include <vlc_vout.h>
49
50 #ifdef WIN32
51     #define PREF_W 410
52     #define PREF_H 121
53 #else
54     #define PREF_W 450
55     #define PREF_H 125
56 #endif
57
58 #define VISIBLE(i) (i && i->isVisible())
59
60 #define SET_WIDTH(i,j) i->widgetSize.setWidth(j)
61 #define SET_HEIGHT(i,j) i->widgetSize.setHeight(j)
62 #define SET_WH( i,j,k) i->widgetSize.setWidth(j); i->widgetSize.setHeight(k);
63
64 #define DS(i) i.width(),i.height()
65
66 #define DEBUG_COLOR 0
67
68 /* Callback prototypes */
69 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
70                         vlc_value_t old_val, vlc_value_t new_val, void *param );
71 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
72                        vlc_value_t old_val, vlc_value_t new_val, void *param );
73 static int InteractCallback( vlc_object_t *, const char *, vlc_value_t,
74                              vlc_value_t, void *);
75 /* Video handling */
76 static void *DoRequest( intf_thread_t *p_intf, vout_thread_t *p_vout,
77                         int *pi1, int *pi2, unsigned int*pi3,unsigned int*pi4)
78 {
79     return p_intf->p_sys->p_mi->requestVideo( p_vout, pi1, pi2, pi3, pi4 );
80 }
81 static void DoRelease( intf_thread_t *p_intf, void *p_win )
82 {
83     return p_intf->p_sys->p_mi->releaseVideo( p_win );
84 }
85 static int DoControl( intf_thread_t *p_intf, void *p_win, int i_q, va_list a )
86 {
87     return p_intf->p_sys->p_mi->controlVideo( p_win, i_q, a );
88 }
89
90 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
91 {
92     /* Variables initialisation */
93     need_components_update = false;
94     bgWidget = NULL; videoWidget = NULL; playlistWidget = NULL;
95     embeddedPlaylistWasActive = videoIsActive = false;
96
97     bool b_createSystray = false;
98     input_name = "";
99
100     /**
101      *  Configuration and settings
102      **/
103     settings = new QSettings( "VideoLAN", "VLC" );
104     settings->beginGroup( "MainWindow" );
105
106     /* Main settings */
107     setFocusPolicy( Qt::StrongFocus );
108     setAcceptDrops(true);
109     setWindowIcon( QApplication::windowIcon() );
110
111     /* Set The Video In emebedded Mode or not */
112     videoEmbeddedFlag = false;
113     if( config_GetInt( p_intf, "embedded-video" ) )
114         videoEmbeddedFlag = true;
115
116     alwaysVideoFlag = false;
117     if( videoEmbeddedFlag && config_GetInt( p_intf, "qt-always-video" ) )
118         alwaysVideoFlag = true;
119
120     /* Set the other interface settings */
121     playlistEmbeddedFlag = settings->value("playlist-embedded", true).toBool();
122     advControlsEnabled= settings->value( "adv-controls", false ).toBool();
123     visualSelectorEnabled= settings->value( "visual-selector", false ).toBool();
124
125 #if DEBUG_COLOR
126     QPalette palette2;
127     palette2.setColor(this->backgroundRole(), Qt::magenta);
128     setPalette(palette2);
129 #endif
130
131     /**
132      *  UI design
133      **/
134     setVLCWindowsTitle();
135     handleMainUi( settings );
136
137     /* Menu Bar */
138     QVLCMenu::createMenuBar( this, p_intf, playlistEmbeddedFlag,
139                              advControlsEnabled, visualSelectorEnabled );
140
141     /* Status Bar */
142     /**
143      * TODO: clicking on the elapsed time should switch to the remaining time
144      **/
145     /**
146      * TODO: do we add a label for the current Volume 
147      **/
148     timeLabel = new QLabel;
149     nameLabel = new QLabel;
150     speedLabel = new QLabel( "1.0x" );
151     timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
152     speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
153     statusBar()->addWidget( nameLabel, 8 );
154     statusBar()->addPermanentWidget( speedLabel, 0 );
155     statusBar()->addPermanentWidget( timeLabel, 2 );
156     speedLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
157     timeLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
158     CONNECT( speedLabel, customContextMenuRequested( QPoint ),
159              this, showSpeedMenu( QPoint ) );
160     CONNECT( timeLabel, customContextMenuRequested( QPoint ),
161              this, showTimeMenu( QPoint ) );
162
163     /* Systray */
164     sysTray = NULL;
165     if( config_GetInt( p_intf, "qt-start-minimized") )
166     {
167         hide();
168         b_createSystray = true;
169     }
170     if( config_GetInt( p_intf, "qt-system-tray") )
171         b_createSystray = true;
172     if (QSystemTrayIcon::isSystemTrayAvailable() && b_createSystray )
173             createSystray();
174
175     /* Init input manager */
176     MainInputManager::getInstance( p_intf );
177     ON_TIMEOUT( updateOnTimer() );
178
179     /**
180      * CONNECTs
181      **/
182
183     /* Connect the input manager to the GUI elements it manages */
184     /* It is also connected to the control->slider */
185     CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
186              this, setDisplay( float, int, int ) );
187
188     /* Naming in the controller */
189     CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
190              setName( QString ) );
191     if( config_GetInt( p_intf, "qt-system-tray" ) && sysTray )
192     {
193         CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
194                  updateSystrayTooltipName( QString ) );
195     }
196     if( config_GetInt( p_intf, "qt-name-in-title" ) )
197     {
198         CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
199              setVLCWindowsTitle( QString ) );
200     }
201
202     /* PLAY_STATUS */
203     CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
204     if( config_GetInt( p_intf, "qt-system-tray" ) && sysTray )
205     {
206         CONNECT( THEMIM->getIM(), statusChanged( int ), this,
207                  updateSystrayTooltipStatus( int ) );
208     }
209
210     /**
211      * Callbacks
212      **/
213     var_Create( p_intf, "interaction", VLC_VAR_ADDRESS );
214     var_AddCallback( p_intf, "interaction", InteractCallback, this );
215     p_intf->b_interaction = VLC_TRUE;
216
217     /* Register callback for the intf-popupmenu variable */
218     playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
219                                         VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
220     if( p_playlist != NULL )
221     {
222         var_AddCallback( p_playlist, "intf-popupmenu", PopupMenuCB, p_intf );
223         var_AddCallback( p_playlist, "intf-show", IntfShowCB, p_intf );
224         vlc_object_release( p_playlist );
225     }
226 }
227
228 MainInterface::~MainInterface()
229 {
230     /* Unregister callback for the intf-popupmenu variable */
231     playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
232                                         VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
233     if( p_playlist != NULL )
234     {
235         var_DelCallback( p_playlist, "intf-popupmenu", PopupMenuCB, p_intf );
236         var_DelCallback( p_playlist, "intf-show", IntfShowCB, p_intf );
237         vlc_object_release( p_playlist );
238     }
239
240     settings->setValue( "playlist-embedded", playlistEmbeddedFlag );
241     settings->setValue( "adv-controls", advControlsEnabled );
242     settings->setValue( "pos", pos() );
243     settings->endGroup();
244     delete settings;
245     p_intf->b_interaction = VLC_FALSE;
246     var_DelCallback( p_intf, "interaction", InteractCallback, this );
247
248     p_intf->pf_request_window = NULL;
249     p_intf->pf_release_window = NULL;
250     p_intf->pf_control_window = NULL;
251 }
252
253 /*****************************
254  *   Main UI handling        *
255  *****************************/
256
257 /**
258  * Give the decorations of the Main Window a correct Name.
259  * If nothing is given, set it to VLC...
260  **/
261 void MainInterface::setVLCWindowsTitle( QString aTitle )
262 {
263     if( aTitle.isEmpty() )
264     {
265         setWindowTitle( qtr( "VLC media player" ) );
266     }
267     else
268     {
269         setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
270     }
271 }
272
273 void MainInterface::handleMainUi( QSettings *settings )
274 {
275     QWidget *main = new QWidget( this );
276     mainLayout = new QVBoxLayout( main );
277     setCentralWidget( main );
278
279     /* Margins, spacing */
280     main->setContentsMargins( 0, 0, 0, 0 );
281     mainLayout->setMargin( 0 );
282
283     /* CONTROLS */
284     controls = new ControlsWidget( p_intf );
285
286     /* Configure the UI */
287     BUTTON_SET_IMG( controls->playlistButton, "" , playlist_icon.png,
288                         playlistEmbeddedFlag ?  qtr( "Show playlist" ) :
289                                                 qtr( "Open playlist" ) );
290     BUTTONACT( controls->playlistButton, playlist() );
291
292 #if DEBUG_COLOR
293     QPalette palette;
294     palette.setColor(main->backgroundRole(), Qt::green);
295     main->setPalette(palette);
296 #endif
297
298     /* Add the controls Widget */
299     mainLayout->addWidget( controls );
300
301     /* Set initial size */
302     resize ( PREF_W, PREF_H );
303
304     addSize = QSize( mainLayout->margin() * 2, PREF_H );
305
306     /* advanced Controls handling */
307     advControls = new AdvControlsWidget( p_intf );
308     mainLayout->insertWidget( 0, advControls );
309     advControls->updateGeometry();
310     if( !advControlsEnabled ) advControls->hide();
311     need_components_update = true;
312
313     /* Visualisation */
314     visualSelector = new VisualSelector( p_intf );
315     mainLayout->insertWidget( 0, visualSelector );
316     visualSelector->hide();
317
318     /* And video Outputs */
319     if( alwaysVideoFlag )
320     {
321         bgWidget = new BackgroundWidget( p_intf );
322         bgWidget->widgetSize = settings->value( "backgroundSize",
323                                            QSize( 300, 300 ) ).toSize();
324         bgWidget->resize( bgWidget->widgetSize );
325         bgWidget->updateGeometry();
326         mainLayout->insertWidget( 0, bgWidget );
327     }
328
329     if( videoEmbeddedFlag )
330     {
331         videoWidget = new VideoWidget( p_intf );
332         videoWidget->widgetSize = QSize( 1, 1 );
333         //videoWidget->resize( videoWidget->widgetSize );
334         mainLayout->insertWidget( 0, videoWidget );
335
336         p_intf->pf_request_window  = ::DoRequest;
337         p_intf->pf_release_window  = ::DoRelease;
338         p_intf->pf_control_window  = ::DoControl;
339     }
340
341     /* Finish the sizing */
342     setMinimumSize( PREF_W, addSize.height() );
343 }
344
345 /**********************************************************************
346  * Handling of the components
347  **********************************************************************/
348 void MainInterface::calculateInterfaceSize()
349 {
350     int width = 0, height = 0;
351     if( VISIBLE( bgWidget ) )
352     {
353         width = bgWidget->widgetSize.width();
354         height = bgWidget->widgetSize.height();
355         assert( !(playlistWidget && playlistWidget->isVisible() ) );
356     }
357     else if( VISIBLE( playlistWidget ) )
358     {
359         width = playlistWidget->widgetSize.width();
360         height = playlistWidget->widgetSize.height();
361     }
362     else if( videoIsActive )
363     {
364         width =  videoWidget->widgetSize.width() ;
365         height = videoWidget->widgetSize.height();
366     }
367     else
368     {
369         width = PREF_W - addSize.width();
370         height = PREF_H - addSize.height();
371     }
372     if( VISIBLE( visualSelector ) )
373         height += visualSelector->height();
374     if( VISIBLE( advControls) )
375     {
376         height += advControls->sizeHint().height();
377     }
378     mainSize = QSize( width + addSize.width(), height + addSize.height() );
379 }
380
381 void MainInterface::resizeEvent( QResizeEvent *e )
382 {
383     videoWidget->widgetSize.setWidth(  e->size().width() - addSize.width() );
384     if( videoWidget && videoIsActive && videoWidget->widgetSize.height() > 1 )
385     {
386         SET_WH( videoWidget, e->size().width() - addSize.width(),
387                              e->size().height()  - addSize.height() );
388         videoWidget->updateGeometry();
389     }
390     if( VISIBLE( playlistWidget ) )
391     {
392         SET_WH( playlistWidget , e->size().width() - addSize.width(),
393                                  e->size().height() - addSize.height() );
394         playlistWidget->updateGeometry();
395     }
396 }
397 /****************************************************************************
398  * Small right-click menus
399  ****************************************************************************/
400 void MainInterface::showSpeedMenu( QPoint pos )
401 {
402     QMenu menu( this );
403     menu.addAction( "Not Implemented Yet" );
404     menu.exec( QCursor::pos() );
405 }
406
407 void MainInterface::showTimeMenu( QPoint pos )
408 {
409     QMenu menu( this );
410     menu.addAction( "Not Implemented Yet" );
411     menu.exec( QCursor::pos() );
412 }
413
414 /*****************************************************************************
415  * Systray Icon and Systray Menu
416  *****************************************************************************/
417
418 /**
419  * Create a SystemTray icon and a menu that would go with it.
420  * Connects to a click handler on the icon.
421  **/
422 void MainInterface::createSystray()
423 {
424     QIcon iconVLC =  QIcon( QPixmap( ":/vlc128.png" ) );
425     sysTray = new QSystemTrayIcon( iconVLC, this );
426     sysTray->setToolTip( qtr( "VLC media player" ));
427
428     systrayMenu = new QMenu( qtr( "VLC media player" ), this );
429     systrayMenu->setIcon( iconVLC );
430
431     QVLCMenu::updateSystrayMenu( this, p_intf, true );
432     sysTray->show();
433
434     CONNECT( sysTray, activated(  QSystemTrayIcon::ActivationReason ),
435             this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
436 }
437
438 /**
439  * Update the menu of the Systray Icon.
440  * May be unneedded, since it just calls QVLCMenu::update
441  * FIXME !!!
442  **/
443 void MainInterface::updateSystrayMenu( int status )
444 {
445     QVLCMenu::updateSystrayMenu( this, p_intf ) ;
446 }
447
448 /**
449  * Updates the Systray Icon's menu and toggle the main interface
450  */
451 void MainInterface::toggleUpdateSystrayMenu()
452 {
453     if( isHidden() )
454     {
455         show();
456         activateWindow();
457     }
458     else
459     {
460 #ifdef WIN32
461         /* check if any visible window is above vlc in the z-order,
462          * but ignore the ones always on top */
463         WINDOWINFO wi;
464         HWND hwnd;
465         wi.cbSize = sizeof( WINDOWINFO );
466         for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
467                 hwnd && !IsWindowVisible( hwnd );
468                 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
469         if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
470                 (wi.dwExStyle&WS_EX_TOPMOST) )
471 #else
472         if( isActiveWindow() )
473 #endif
474         {
475             hide();
476         }
477         else
478         {
479             activateWindow();
480         }
481     }
482     QVLCMenu::updateSystrayMenu( this, p_intf );
483 }
484
485 void MainInterface::handleSystrayClick(
486                                     QSystemTrayIcon::ActivationReason reason )
487 {
488     switch( reason )
489     {
490         case QSystemTrayIcon::Trigger:
491             toggleUpdateSystrayMenu();
492             break;
493         case QSystemTrayIcon::MiddleClick:
494             sysTray->showMessage( qtr( "VLC media player" ),
495                     qtr( "Control menu for the player" ),
496                     QSystemTrayIcon::Information, 4000 );
497             break;
498     }
499 }
500
501 /**
502  * Updates the name of the systray Icon tooltip.
503  * Doesn't check if the systray exists, check before you call it.
504  * FIXME !!! Fusion with next function ?
505  **/
506 void MainInterface::updateSystrayTooltipName( QString name )
507 {
508     if( name.isEmpty() )
509     {
510         sysTray->setToolTip( qtr( "VLC media player" ) );
511     }
512     else
513     {
514         sysTray->setToolTip( name );
515     }
516 }
517
518 /**
519  * Updates the status of the systray Icon tooltip.
520  * Doesn't check if the systray exists, check before you call it.
521  **/
522 void MainInterface::updateSystrayTooltipStatus( int i_status )
523 {
524     switch( i_status )
525     {
526         case  0:
527             {
528                 sysTray->setToolTip( qtr( "VLC media player" ) );
529                 break;
530             }
531         case PLAYING_S:
532             {
533                 sysTray->setToolTip( input_name );
534                 //+ " - " + qtr( "Playing" ) );
535                 break;
536             }
537         case PAUSE_S:
538             {
539                 sysTray->setToolTip( input_name + " - "
540                         + qtr( "Paused") );
541                 break;
542             }
543     }
544 }
545 void *MainInterface::requestVideo( vout_thread_t *p_nvout, int *pi_x,
546                                    int *pi_y, unsigned int *pi_width,
547                                    unsigned int *pi_height )
548 {
549     void *ret = videoWidget->request( p_nvout,pi_x, pi_y, pi_width, pi_height );
550     if( ret )
551     {
552         videoIsActive = true;
553         if( VISIBLE( playlistWidget ) )
554         {
555             embeddedPlaylistWasActive = true;
556 //            playlistWidget->hide();
557         }
558         bool bgWasVisible = false;
559         if( VISIBLE( bgWidget) )
560         {
561             bgWasVisible = true;
562             bgWidget->hide();
563         }
564         if( THEMIM->getIM()->hasVideo() || !bgWasVisible )
565         {
566             videoWidget->widgetSize = QSize( *pi_width, *pi_height );
567         }
568         else /* Background widget available, use its size */
569         {
570             /* Ok, our visualizations are bad, so don't do this for the moment
571              * use the requested size anyway */
572             // videoWidget->widgetSize = bgWidget->widgeTSize;
573             videoWidget->widgetSize = QSize( *pi_width, *pi_height );
574         }
575 //        videoWidget->updateGeometry(); /// FIXME: Needed ?
576         need_components_update = true;
577     }
578     return ret;
579 }
580
581 void MainInterface::releaseVideo( void *p_win )
582 {
583     videoWidget->release( p_win );
584     videoWidget->widgetSize = QSize( 0, 0 );
585     videoWidget->resize( videoWidget->widgetSize );
586
587     if( embeddedPlaylistWasActive )
588         playlistWidget->show();
589     else if( bgWidget )
590         bgWidget->show();
591
592     videoIsActive = false;
593     need_components_update = true;
594 }
595
596 class SetVideoOnTopQtEvent : public QEvent
597 {
598 public:
599     SetVideoOnTopQtEvent( bool _onTop ) :
600       QEvent( (QEvent::Type)SetVideoOnTopEvent_Type ), onTop( _onTop)
601     {
602     }
603
604     bool OnTop() const
605     {
606         return onTop;
607     }
608
609 private:
610     bool onTop;
611 };
612
613 int MainInterface::controlVideo( void *p_window, int i_query, va_list args )
614 {
615     int i_ret = VLC_EGENERIC;
616     switch( i_query )
617     {
618         case VOUT_GET_SIZE:
619         {
620             unsigned int *pi_width  = va_arg( args, unsigned int * );
621             unsigned int *pi_height = va_arg( args, unsigned int * );
622             *pi_width = videoWidget->widgetSize.width();
623             *pi_height = videoWidget->widgetSize.height();
624             i_ret = VLC_SUCCESS;
625             break;
626         }
627         case VOUT_SET_SIZE:
628         {
629             unsigned int i_width  = va_arg( args, unsigned int );
630             unsigned int i_height = va_arg( args, unsigned int );
631             videoWidget->widgetSize = QSize( i_width, i_height );
632             // videoWidget->updateGeometry();
633             need_components_update = true;
634             i_ret = VLC_SUCCESS;
635             break;
636         }
637         case VOUT_SET_STAY_ON_TOP:
638         {
639             int i_arg = va_arg( args, int );
640             QApplication::postEvent( this, new SetVideoOnTopQtEvent( i_arg ) );
641             i_ret = VLC_SUCCESS;
642             break;
643         }
644         default:
645             msg_Warn( p_intf, "unsupported control query" );
646             break;
647     }
648     return i_ret;
649 }
650
651 void MainInterface::advanced()
652 {
653     if( !VISIBLE( advControls ) )
654     {
655         advControls->show();
656         advControlsEnabled = true;
657     }
658     else
659     {
660         advControls->hide();
661         advControlsEnabled = false;
662     }
663     doComponentsUpdate();
664 }
665
666 void MainInterface::visual()
667 {
668     if( !VISIBLE( visualSelector) )
669     {
670         visualSelector->show();
671         if( !THEMIM->getIM()->hasVideo() )
672         {
673             /* Show the background widget */
674         }
675         visualSelectorEnabled = true;
676     }
677     else
678     {
679         /* Stop any currently running visualization */
680         visualSelector->hide();
681         visualSelectorEnabled = false;
682     }
683     doComponentsUpdate();
684 }
685
686 void MainInterface::playlist()
687 {
688     // Toggle the playlist dialog
689     if( !playlistEmbeddedFlag )
690     {
691         if( playlistWidget )
692         {
693             /// \todo Destroy it
694         }
695         THEDP->playlistDialog();
696         return;
697     }
698
699     if( !playlistWidget )
700     {
701         PlaylistDialog::killInstance();
702         playlistWidget = new PlaylistWidget( p_intf );
703         mainLayout->insertWidget( 0, playlistWidget );
704         playlistWidget->widgetSize = settings->value( "playlistSize",
705                                                QSize( 650, 310 ) ).toSize();
706         playlistWidget->hide();
707         if(bgWidget)
708         CONNECT( playlistWidget, artSet( QString ), bgWidget, setArt(QString) );
709     }
710     if( VISIBLE( playlistWidget ) )
711     {
712         playlistWidget->hide();
713         if( bgWidget ) bgWidget->show();
714         if( videoIsActive )
715         {
716             videoWidget->widgetSize = savedVideoSize;
717             videoWidget->resize( videoWidget->widgetSize );
718             videoWidget->updateGeometry();
719             if( bgWidget ) bgWidget->hide();
720         }
721     }
722     else
723     {
724         playlistWidget->show();
725         if( videoIsActive )
726         {
727             savedVideoSize = videoWidget->widgetSize;
728             videoWidget->widgetSize.setHeight( 0 );
729             videoWidget->resize( videoWidget->widgetSize );
730             videoWidget->updateGeometry();
731         }
732         if( VISIBLE( bgWidget ) ) bgWidget->hide();
733     }
734     doComponentsUpdate();
735 }
736
737 /* Video widget cannot do this synchronously as it runs in another thread */
738 /* Well, could it, actually ? Probably dangerous ... */
739 void MainInterface::doComponentsUpdate()
740 {
741     calculateInterfaceSize();
742     resize( mainSize );
743 }
744
745 void MainInterface::undockPlaylist()
746 {
747     if( playlistWidget )
748     {
749         playlistWidget->hide();
750         playlistWidget->deleteLater();
751         mainLayout->removeWidget( playlistWidget );
752         playlistWidget = NULL;
753         playlistEmbeddedFlag = false;
754
755         menuBar()->clear();
756         QVLCMenu::createMenuBar( this, p_intf, false, advControlsEnabled,
757                                  visualSelectorEnabled);
758
759         if( videoIsActive )
760         {
761             videoWidget->widgetSize = savedVideoSize;
762             videoWidget->resize( videoWidget->widgetSize );
763             videoWidget->updateGeometry();
764         }
765
766         doComponentsUpdate();
767         THEDP->playlistDialog();
768     }
769 }
770
771 void MainInterface::toggleMenus()
772 {
773     if( menuBar()->isVisible() ) menuBar()->hide();
774         else menuBar()->show();
775     msg_Dbg( p_intf, "I was there: \\_o<~~ coin coin" );
776 }
777
778 void MainInterface::customEvent( QEvent *event )
779 {
780     if( event->type() == PLDockEvent_Type )
781     {
782         PlaylistDialog::killInstance();
783         playlistEmbeddedFlag = true;
784         menuBar()->clear();
785         QVLCMenu::createMenuBar(this, p_intf, true, advControlsEnabled,
786                                 visualSelectorEnabled);
787         playlist();
788     }
789     else if ( event->type() == SetVideoOnTopEvent_Type )
790     {
791         SetVideoOnTopQtEvent* p_event = (SetVideoOnTopQtEvent*)event;
792         if( p_event->OnTop() )
793             setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
794         else
795             setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
796         show(); /* necessary to apply window flags?? */
797     }
798 }
799
800
801 /************************************************************************
802  * D&D
803  ************************************************************************/
804 void MainInterface::dropEvent(QDropEvent *event)
805 {
806      const QMimeData *mimeData = event->mimeData();
807
808      /* D&D of a subtitles file, add it on the fly */
809      if( mimeData->urls().size() == 1 )
810      {
811         if( THEMIM->getIM()->hasInput() )
812         {
813             if( input_AddSubtitles( THEMIM->getInput(),
814                                     qtu( mimeData->urls()[0].toString() ),
815                                     VLC_TRUE ) )
816             {
817                 event->acceptProposedAction();
818                 return;
819             }
820         }
821      }
822      bool first = true;
823      foreach( QUrl url, mimeData->urls() ) {
824         QString s = url.toString();
825         if( s.length() > 0 ) {
826             playlist_Add( THEPL, qtu(s), NULL,
827                           PLAYLIST_APPEND | (first ? PLAYLIST_GO:0),
828                           PLAYLIST_END, VLC_TRUE, VLC_FALSE );
829             first = false;
830         }
831      }
832      event->acceptProposedAction();
833 }
834 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
835 {
836      event->acceptProposedAction();
837 }
838 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
839 {
840      event->acceptProposedAction();
841 }
842 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
843 {
844      event->accept();
845 }
846
847 /************************************************************************
848  * Other stuff
849  ************************************************************************/
850 void MainInterface::keyPressEvent( QKeyEvent *e )
851 {
852     int i_vlck = qtEventToVLCKey( e );
853     if( i_vlck >= 0 )
854     {
855         var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
856         e->accept();
857     }
858     else
859         e->ignore();
860 }
861
862 void MainInterface::wheelEvent( QWheelEvent *e )
863 {
864     int i_vlckey = qtWheelEventToVLCKey( e );
865     var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
866     e->accept();
867 }
868
869 void MainInterface::setDisplay( float pos, int time, int length )
870 {
871     char psz_length[MSTRTIME_MAX_SIZE], psz_time[MSTRTIME_MAX_SIZE];
872     secstotimestr( psz_length, length );
873     secstotimestr( psz_time, time );
874     QString title;
875     title.sprintf( "%s/%s", psz_time, psz_length );
876     timeLabel->setText( " "+title+" " );
877 }
878
879 void MainInterface::setName( QString name )
880 {
881     input_name = name;
882     nameLabel->setText( " " + name+" " );
883 }
884
885 void MainInterface::setStatus( int status )
886 {
887     controls->setStatus( status );
888     if( systrayMenu )
889         updateSystrayMenu( status );
890 }
891
892 void MainInterface::updateOnTimer()
893 {
894     /* \todo Make this event-driven */
895     // TO MOVE TO controls
896     advControls->enableInput( THEMIM->getIM()->hasInput() );
897     controls->enableInput( THEMIM->getIM()->hasInput() );
898     advControls->enableVideo( THEMIM->getIM()->hasVideo() );
899     controls->enableVideo( THEMIM->getIM()->hasVideo() );
900
901     if( intf_ShouldDie( p_intf ) )
902     {
903         QApplication::closeAllWindows();
904         QApplication::quit();
905     }
906     if( need_components_update )
907     {
908         doComponentsUpdate();
909         need_components_update = false;
910     }
911
912     controls->updateOnTimer();
913 }
914
915 void MainInterface::closeEvent( QCloseEvent *e )
916 {
917     hide();
918     vlc_object_kill( p_intf );
919 }
920
921 static int InteractCallback( vlc_object_t *p_this,
922                              const char *psz_var, vlc_value_t old_val,
923                              vlc_value_t new_val, void *param )
924 {
925     intf_dialog_args_t *p_arg = new intf_dialog_args_t;
926     p_arg->p_dialog = (interaction_dialog_t *)(new_val.p_address);
927     DialogEvent *event = new DialogEvent( INTF_DIALOG_INTERACTION, 0, p_arg );
928     QApplication::postEvent( THEDP, static_cast<QEvent*>(event) );
929     return VLC_SUCCESS;
930 }
931
932 /*****************************************************************************
933  * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
934  *  We don't show the menu directly here because we don't want the
935  *  caller to block for a too long time.
936  *****************************************************************************/
937 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
938                         vlc_value_t old_val, vlc_value_t new_val, void *param )
939 {
940     intf_thread_t *p_intf = (intf_thread_t *)param;
941
942     if( p_intf->pf_show_dialog )
943     {
944         p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
945                                 new_val.b_bool, 0 );
946     }
947
948     return VLC_SUCCESS;
949 }
950
951 /*****************************************************************************
952  * IntfShowCB: callback triggered by the intf-show playlist variable.
953  *****************************************************************************/
954 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
955                        vlc_value_t old_val, vlc_value_t new_val, void *param )
956 {
957     intf_thread_t *p_intf = (intf_thread_t *)param;
958     //p_intf->p_sys->b_intf_show = VLC_TRUE;
959
960     return VLC_SUCCESS;
961 }