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