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