main_interface.cpp 43.7 KB
Newer Older
zorglub's avatar
zorglub committed
1
/*****************************************************************************
zorglub's avatar
Wtf ?    
zorglub committed
2
 * main_interface.cpp : Main interface
zorglub's avatar
zorglub committed
3
 ****************************************************************************
4
 * Copyright (C) 2006-2011 VideoLAN and AUTHORS
5
 * $Id$
zorglub's avatar
zorglub committed
6
7
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
8
 *          Jean-Baptiste Kempf <jb@videolan.org>
9
 *          Ilkka Ollakka <ileoo@videolan.org>
zorglub's avatar
zorglub committed
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
22
23
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24
 *****************************************************************************/
25

26
27
28
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
zorglub's avatar
zorglub committed
29

30
#include "qt4.hpp"
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
31

zorglub's avatar
zorglub committed
32
#include "main_interface.hpp"
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
33
34
35
#include "input_manager.hpp"                    // Creation
#include "actions_manager.hpp"                  // killInstance
#include "extensions_manager.hpp"               // killInstance
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
36

37
#include "util/customwidgets.hpp"               // qtEventToVLCKey, QVLCStackedWidget
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
38
#include "util/qt_dirs.hpp"                     // toNativeSeparators
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
39

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
40
41
42
43
#include "components/interface_widgets.hpp"     // bgWidget, videoWidget
#include "components/controller.hpp"            // controllers
#include "components/playlist/playlist.hpp"     // plWidget
#include "dialogs/firstrun.hpp"                 // First Run
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
44

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
45
46
#include "menus.hpp"                            // Menu creation
#include "recents.hpp"                          // RecentItems when DnD
47

zorglub's avatar
zorglub committed
48
#include <QCloseEvent>
49
#include <QKeyEvent>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
50

zorglub's avatar
zorglub committed
51
#include <QUrl>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
52
#include <QSize>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
53
54
#include <QDate>

55
#include <QMenu>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
56
57
#include <QMenuBar>
#include <QStatusBar>
58
#include <QLabel>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
59
#include <QStackedWidget>
60

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
61
62
#include <vlc_keys.h>                       /* Wheel event */
#include <vlc_vout_display.h>               /* vout_thread_t and VOUT_ events */
63

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
64
// #define DEBUG_INTF
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
65

66
67
68
69
70
/* Callback prototypes */
static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
                        vlc_value_t old_val, vlc_value_t new_val, void *param );
static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
                       vlc_value_t old_val, vlc_value_t new_val, void *param );
71
72
static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
                       vlc_value_t old_val, vlc_value_t new_val, void *param );
73
74
75
static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
                           vlc_value_t old_val, vlc_value_t new_val,
                           void *param );
zorglub's avatar
zorglub committed
76

zorglub's avatar
zorglub committed
77
MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
zorglub's avatar
zorglub committed
78
{
79
    /* Variables initialisation */
80
81
82
    bgWidget             = NULL;
    videoWidget          = NULL;
    playlistWidget       = NULL;
83
    stackCentralOldWidget= NULL;
84
85
    sysTray              = NULL;
    fullscreenControls   = NULL;
86
    cryptedLabel         = NULL;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
87
88
    controls             = NULL;
    inputC               = NULL;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
89

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
90
    b_hideAfterCreation  = false; // --qt-start-minimized
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
91
    playlistVisible      = false;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
92
    input_name           = "";
93
    b_interfaceFullScreen= false;
94
    b_hasPausedWhenMinimized = false;
95

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
96

97
    /* Ask for Privacy */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
98
    FirstRun::CheckAndRun( this, p_intf );
99

100
    /**
101
     *  Configuration and settings
102
     *  Pre-building of interface
103
     **/
104
105
    /* Main settings */
    setFocusPolicy( Qt::StrongFocus );
106
    setAcceptDrops( true );
Nick Pope's avatar
Nick Pope committed
107
    setWindowRole( "vlc-main" );
108
    setWindowIcon( QApplication::windowIcon() );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
109
    setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
110
111
112
#ifdef Q_WS_MAC
    setAttribute( Qt::WA_MacBrushedMetal );
#endif
113

Rémi Denis-Courmont's avatar
Grammar    
Rémi Denis-Courmont committed
114
    /* Is video in embedded in the UI or not */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
115
    b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
zorglub's avatar
zorglub committed
116

117
    /* Does the interface resize to video size or the opposite */
118
    b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
119

120
    /* Are we in the enhanced always-video mode or not ? */
121
    b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
zorglub's avatar
zorglub committed
122

123
    /* Do we want anoying popups or not */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
124
    b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
125

126
    /* */
127
128
    b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );

129
    /* Set the other interface settings */
130
    settings = getSettings();
131

132
133
134
135
136
#ifdef WIN32
    /* Volume keys */
    p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
#endif

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
137
    /* */
138
    b_plDocked = getSettings()->value( "MainWindow/pl-dock-status", true ).toBool();
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
139

140

141
142
143
    /**************************
     *  UI and Widgets design
     **************************/
144
    setVLCWindowsTitle();
145

146
147
148
    /************
     * Menu Bar *
     ************/
149
    VLCMenuBar::createMenuBar( this, p_intf );
150
151
    CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
             this, destroyPopupMenu() );
152

153
    createMainWidget( settings );
154
155
156
157
158
159
160

    /**************
     * Status Bar *
     **************/
    createStatusBar();
    setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );

161
162
163
164
    /********************
     * Input Manager    *
     ********************/
    MainInputManager::getInstance( p_intf );
165

166
#ifdef WIN32
167
168
    himl = NULL;
    p_taskbl = NULL;
169
    taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
170
171
#endif

172
173
174
175
176
    /*********************************
     * Create the Systray Management *
     *********************************/
    initSystray();

177
178
179
180
    /*************************************************************
     * Connect the input manager to the GUI elements it manages  *
     * Beware initSystray did some connects on input manager too *
     *************************************************************/
181
182
    /**
     * Connects on nameChanged()
183
184
185
     * Those connects are different because options can impeach them to trigger.
     **/
    /* Main Interface statusbar */
ivoire's avatar
ivoire committed
186
187
    CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
             this, setName( const QString& ) );
188
    /* and title of the Main Interface*/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
189
    if( var_InheritBool( p_intf, "qt-name-in-title" ) )
190
    {
191
192
        CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
                 this, setVLCWindowsTitle( const QString& ) );
193
    }
194
195
    /* END CONNECTS ON IM */

196
    /* VideoWidget connects for asynchronous calls */
197
    b_videoFullScreen = false;
198
199
200
    connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
             this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
             Qt::BlockingQueuedConnection );
201
    connect( this, SIGNAL(askReleaseVideo( void )),
202
203
             this, SLOT(releaseVideoSlot( void )),
             Qt::BlockingQueuedConnection );
204
    CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
205

206
    if( videoWidget )
207
    {
208
209
210
        if( b_autoresize )
        {
            CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
211
                     this, setVideoSize( unsigned int, unsigned int ) );
212
213
214
            CONNECT( videoWidget, sizeChanged( int, int ),
                     this, resizeStack( int,  int ) );
        }
215
        CONNECT( this, askVideoSetFullScreen( bool ),
216
                 this, setVideoFullScreen( bool ) );
217
218
    }

219
    CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
220

221
222
    CONNECT( this, askToQuit(), THEDP, quit() );

223
    CONNECT( this, askBoss(), this, setBoss() );
224
    CONNECT( this, askRaise(), this, setRaise() );
225

226
227
228
    /** END of CONNECTS**/


229
230
231
    /************
     * Callbacks
     ************/
232
    var_AddCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
233
    var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
234
    var_AddCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
235
236
237
238

    /* Register callback for the intf-popupmenu variable */
    var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );

239

240
    /* Final Sizing, restoration and placement of the interface */
241
    if( settings->value( "MainWindow/playlist-visible", false ).toBool() )
242
243
        togglePlaylist();

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
244
    QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
245

246
247
    b_interfaceFullScreen = isFullScreen();

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
248
    setVisible( !b_hideAfterCreation );
249

250
    computeMinimumSize();
251

252
    /* Switch to minimal view if needed, must be called after the show() */
253
    if( b_minimalView )
254
        toggleMinimalView( true );
255
256
257
258
}

MainInterface::~MainInterface()
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
259
    /* Unsure we hide the videoWidget before destroying it */
260
    if( stackCentralOldWidget == videoWidget )
261
        showTab( bgWidget );
262

263
264
    if( videoWidget )
        releaseVideoSlot();
265

266
#ifdef WIN32
267
268
    if( himl )
        ImageList_Destroy( himl );
269
270
271
272
273
    if(p_taskbl)
        p_taskbl->vt->Release(p_taskbl);
    CoUninitialize();
#endif

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
274
    /* Be sure to kill the actionsManager... Only used in the MI and control */
275
276
    ActionsManager::killInstance();

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
277
    /* Idem */
278
279
    ExtensionsManager::killInstance();

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
280
    /* Delete the FSC controller */
281
    delete fullscreenControls;
282

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
283
    /* Save states */
284

285
    settings->beginGroup("MainWindow");
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
286
    settings->setValue( "pl-dock-status", b_plDocked );
287
288
    /* Save playlist state */
    if( playlistWidget )
289
        settings->setValue( "playlist-visible", playlistVisible );
290

291
    settings->setValue( "adv-controls",
292
                        getControlsVisibilityStatus() & CONTROLS_ADVANCED );
293
    settings->setValue( "status-bar-visible", b_statusbarVisible );
294

295
296
297
    /* Save the stackCentralW sizes */
    settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
    settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
298
    settings->endGroup();
299

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
300
    /* Save this size */
301
    QVLCTools::saveWidgetPosition(settings, this);
302
303
304
305
306

    /* Save undocked playlist size */
    if( playlistWidget && !isPlDocked() )
        QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );

jpd's avatar
jpd committed
307
    delete playlistWidget;
308

309
310
    delete statusBar();

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
311
    /* Unregister callbacks */
312
    var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
313
    var_DelCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
314
    var_DelCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
315
    var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
316

317
    p_intf->p_sys->p_mi = NULL;
318
319
}

320
321
322
323
324
325
326
327
328
void MainInterface::computeMinimumSize()
{
    int minWidth = 30;
    if( menuBar()->isVisible() )
        minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );

    setMinimumWidth( minWidth );
}

329
330
331
/*****************************
 *   Main UI handling        *
 *****************************/
332
333
void MainInterface::recreateToolbars()
{
334
335
    bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;

336
337
    delete controls;
    delete inputC;
338

339
    controls = new ControlsWidget( p_intf, b_adv, this );
340
    inputC = new InputControlsWidget( p_intf, this );
341
    mainLayout->insertWidget( 2, inputC );
342
    mainLayout->insertWidget( settings->value( "MainWindow/ToolbarPos", 0 ).toInt() ? 0: 3,
343
                              controls );
344

345
346
347
348
349
350
351
    if( fullscreenControls )
    {
        delete fullscreenControls;
        fullscreenControls = new FullscreenControllerWidget( p_intf, this );
        CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
                 this, handleKeyPress( QKeyEvent * ) );
    }
352
353
}

354
355
356
357
358
359
360
361
362
363
364
365
366
367
void MainInterface::reloadPrefs()
{
    b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
    b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
#ifdef WIN32
    p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
#endif
    if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
    {
        delete fullscreenControls;
        fullscreenControls = NULL;
    }
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
368
void MainInterface::createMainWidget( QSettings *settings )
369
{
370
    /* Create the main Widget and the mainLayout */
371
    QWidget *main = new QWidget;
372
    setCentralWidget( main );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
373
    mainLayout = new QVBoxLayout( main );
374
    main->setContentsMargins( 0, 0, 0, 0 );
375
    mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
376

377
    /* */
378
    stackCentralW = new QVLCStackedWidget( main );
379

380
381
    /* Bg Cone */
    bgWidget = new BackgroundWidget( p_intf );
382
    stackCentralW->addWidget( bgWidget );
383
384
385
386
387
    if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
        bgWidget->setWithArt( false );
    else
        if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
            bgWidget->setExpandstoHeight( true );
388

389
    /* And video Outputs */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
390
    if( b_videoEmbedded )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
391
    {
392
        videoWidget = new VideoWidget( p_intf );
393
        stackCentralW->addWidget( videoWidget );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
394
    }
395
    mainLayout->insertWidget( 1, stackCentralW );
396

397
    stackWidgetsSizes[bgWidget] = settings->value( "MainWindow/bgSize", QSize( 600, 0 ) ).toSize();
398
399
    /* Resize even if no-auto-resize, because we are at creation */
    resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
jpd's avatar
jpd committed
400

401
402
    /* Create the CONTROLS Widget */
    controls = new ControlsWidget( p_intf,
403
                   settings->value( "MainWindow/adv-controls", false ).toBool(), this );
404
405
    inputC = new InputControlsWidget( p_intf, this );

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
406
407
408
    mainLayout->insertWidget( 2, inputC );
    mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
                              controls );
409

410
    /* Visualisation, disabled for now, they SUCK */
411
412
413
414
415
416
    #if 0
    visualSelector = new VisualSelector( p_intf );
    mainLayout->insertWidget( 0, visualSelector );
    visualSelector->hide();
    #endif

417

418
419
420
421
422
    /* Enable the popup menu in the MI */
    main->setContextMenuPolicy( Qt::CustomContextMenu );
    CONNECT( main, customContextMenuRequested( const QPoint& ),
             this, popupMenu( const QPoint& ) );

423
424
425
426
427
428
429
430
    if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
        /* Create the FULLSCREEN CONTROLS Widget */
        if( var_InheritBool( p_intf, "qt-fs-controller" ) )
        {
            fullscreenControls = new FullscreenControllerWidget( p_intf, this );
            CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
                     this, handleKeyPress( QKeyEvent * ) );
        }
zorglub's avatar
zorglub committed
431
432
}

433
434
435
inline void MainInterface::initSystray()
{
    bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
436
    bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
437

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
438
    if( var_InheritBool( p_intf, "qt-start-minimized") )
439
440
441
442
443
444
445
446
447
448
449
450
451
452
    {
        if( b_systrayAvailable )
        {
            b_systrayWanted = true;
            b_hideAfterCreation = true;
        }
        else
            msg_Err( p_intf, "cannot start minimized without system tray bar" );
    }

    if( b_systrayAvailable && b_systrayWanted )
        createSystray();
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
453
454
455
456
457
458
459
460
461
462
463
464
inline void MainInterface::createStatusBar()
{
    /****************
     *  Status Bar  *
     ****************/
    /* Widgets Creation*/
    QStatusBar *statusBarr = statusBar();

    TimeLabel *timeLabel = new TimeLabel( p_intf );
    nameLabel = new QLabel( this );
    nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
                                      | Qt::TextSelectableByKeyboard );
465
    SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
466
467
468
469
470

    /* Styling those labels */
    timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
    speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
    nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
471
472
473
474
    timeLabel->setStyleSheet(
            "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
    speedLabel->setStyleSheet(
            "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
475
476
    /* pad both label and its tooltip */
    nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
477
478
479
480
481
482
483
484
485
486
487
488
489
490

    /* and adding those */
    statusBarr->addWidget( nameLabel, 8 );
    statusBarr->addPermanentWidget( speedLabel, 0 );
    statusBarr->addPermanentWidget( timeLabel, 0 );

    /* timeLabel behaviour:
       - double clicking opens the goto time dialog
       - right-clicking and clicking just toggle between remaining and
         elapsed time.*/
    CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );

    CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
             this, showCryptedLabel( bool ) );
491

492
493
    CONNECT( THEMIM->getIM(), seekRequested( float ),
             timeLabel, setDisplayPosition( float ) );
494
495
496
497
498
499
500
501

    /* This shouldn't be necessary, but for somehow reason, the statusBarr
       starts at height of 20px and when a text is shown it needs more space.
       But, as the QMainWindow policy doesn't allow statusBar to change QMW's
       geometry, we need to force a height. If you have a better idea, please
       tell me -- jb
     */
    statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
502
503
}

504
/**********************************************************************
505
 * Handling of sizing of the components
506
 **********************************************************************/
507

508
509
void MainInterface::debug()
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
510
#ifdef DEBUG_INTF
511
512
    msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
    msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
513
    msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
514

515
    msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
516
    msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
517
    msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
518
#endif
519
520
}

521
inline void MainInterface::showVideo() { showTab( videoWidget ); }
522
523
inline void MainInterface::restoreStackOldWidget()
            { showTab( stackCentralOldWidget ); }
524
525

inline void MainInterface::showTab( QWidget *widget )
526
{
527
528
529
#ifdef DEBUG_INTF
    msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
#endif
530

531
    stackCentralOldWidget = stackCentralW->currentWidget();
532
533
    stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();

534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
    /* If we are playing video, embedded */
    if( videoWidget && THEMIM->getIM()->hasVideo() )
    {
        /* Video -> Playlist */
        if( videoWidget == stackCentralOldWidget && widget == playlistWidget )
        {
            stackCentralW->removeWidget( videoWidget );
            videoWidget->show(); videoWidget->raise();
        }

        /* Playlist -> Video */
        if( playlistWidget == stackCentralOldWidget && widget == videoWidget )
        {
            playlistWidget->artContainer->removeWidget( videoWidget );
            videoWidget->show(); videoWidget->raise();
            stackCentralW->addWidget( videoWidget );
        }
    }

553
    stackCentralW->setCurrentWidget( widget );
554
555
    if( b_autoresize )
        resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
556

557
558
559
560
#ifdef DEBUG_INTF
    msg_Warn( p_intf, "State change %i",  stackCentralW->currentIndex() );
    msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
#endif
561
562
563
564
565
566
567
568

    /* This part is done later, to account for the new pl size */
    if( videoWidget && THEMIM->getIM()->hasVideo() &&
        videoWidget == stackCentralOldWidget && widget == playlistWidget )
    {
        playlistWidget->artContainer->addWidget( videoWidget );
        playlistWidget->artContainer->setCurrentWidget( videoWidget );
    }
569
}
570

571
572
void MainInterface::destroyPopupMenu()
{
573
    VLCMenuBar::PopupMenu( p_intf, false );
574
575
}

576
void MainInterface::popupMenu( const QPoint & )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
577
{
578
    VLCMenuBar::PopupMenu( p_intf, true );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
579
580
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
581
582
583
584
void MainInterface::toggleFSC()
{
   if( !fullscreenControls ) return;

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
585
   IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
586
587
588
   QApplication::postEvent( fullscreenControls, eShow );
}

589
590
591
/****************************************************************************
 * Video Handling
 ****************************************************************************/
592

593
/**
594
 * NOTE:
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
595
 * You must not change the state of this object or other Qt4 UI objects,
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
 * from the video output thread - only from the Qt4 UI main loop thread.
 * All window provider queries must be handled through signals or events.
 * That's why we have all those emit statements...
 */
WId MainInterface::getVideo( int *pi_x, int *pi_y,
                             unsigned int *pi_width, unsigned int *pi_height )
{
    if( !videoWidget )
        return 0;

    /* This is a blocking call signal. Results are returned through pointers.
     * Beware of deadlocks! */
    WId id;
    emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
    return id;
}

void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
                                  unsigned *pi_width, unsigned *pi_height )
615
{
616
617
618
619
    /* Hidden or minimized, activate */
    if( isHidden() || isMinimized() )
        toggleUpdateSystrayMenu();

620
    /* Request the videoWidget */
621
    WId ret = videoWidget->request( pi_x, pi_y,
622
                                    pi_width, pi_height, !b_autoresize );
623
    *p_id = ret;
624
    if( ret ) /* The videoWidget is available */
625
    {
626
        /* Consider the video active now */
627
        showVideo();
628
629
630
631

        /* Ask videoWidget to resize correctly, if we are in normal mode */
        if( !isFullScreen() && !isMaximized() && b_autoresize )
            videoWidget->SetSizing( *pi_width, *pi_height );
632
    }
633
634
}

635
/* Asynchronous call from the WindowClose function */
636
void MainInterface::releaseVideo( void )
637
{
638
    emit askReleaseVideo();
639
640
}

641
/* Function that is CONNECTED to the previous emit */
642
void MainInterface::releaseVideoSlot( void )
643
{
644
645
646
647
648
    /* This function is called when the embedded video window is destroyed,
     * or in the rare case that the embedded window is still here but the
     * Qt4 interface exits. */
    assert( videoWidget );
    videoWidget->release();
649
    setVideoOnTop( false );
650
    setVideoFullScreen( false );
zorglub's avatar
zorglub committed
651

jpd's avatar
jpd committed
652
653
    if( stackCentralW->currentWidget() == videoWidget )
        restoreStackOldWidget();
654
655
    else if( playlistWidget &&
             playlistWidget->artContainer->currentWidget() == videoWidget )
656
657
658
659
    {
        playlistWidget->artContainer->setCurrentIndex( 0 );
        stackCentralW->addWidget( videoWidget );
    }
zorglub's avatar
zorglub committed
660

661
662
    /* We don't want to have a blank video to popup */
    stackCentralOldWidget = bgWidget;
663
664
}

665
666
void MainInterface::setVideoSize( unsigned int w, unsigned int h )
{
667
668
    if( !isFullScreen() && !isMaximized() )
        videoWidget->SetSizing( w, h );
669
670
}

671
672
673
void MainInterface::setVideoFullScreen( bool fs )
{
    b_videoFullScreen = fs;
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
    if( fs )
    {
        int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
        /* if user hasn't defined screennumber, or screennumber that is bigger
         * than current number of screens, take screennumber where current interface
         * is
         */
        if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
            numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );

        QRect screenres = QApplication::desktop()->screenGeometry( numscreen );

        /* To be sure window is on proper-screen in xinerama */
        if( !screenres.contains( pos() ) )
        {
            msg_Dbg( p_intf, "Moving video to correct screen");
            move( QPoint( screenres.x(), screenres.y() ) );
        }
692
693

        /* */
Edward Wang's avatar
Edward Wang committed
694
        if( playlistWidget != NULL && playlistWidget->artContainer->currentWidget() == videoWidget )
695
696
697
698
699
        {
            showTab( videoWidget );
        }

        /* */
700
701
702
703
704
705
706
707
708
709
710
        setMinimalView( true );
        setInterfaceFullScreen( true );
    }
    else
    {
        /* TODO do we want to restore screen and position ? (when
         * qt-fullscreen-screennumber is forced) */
        setMinimalView( b_minimalView );
        setInterfaceFullScreen( b_interfaceFullScreen );
    }
    videoWidget->sync();
711
712
}

713
714
715
716
717
718
/* Slot to change the video always-on-top flag.
 * Emit askVideoOnTop() to invoke this from other thread. */
void MainInterface::setVideoOnTop( bool on_top )
{
    Qt::WindowFlags oldflags = windowFlags(), newflags;

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
719
    if( on_top )
720
721
722
        newflags = oldflags | Qt::WindowStaysOnTopHint;
    else
        newflags = oldflags & ~Qt::WindowStaysOnTopHint;
723
    if( newflags != oldflags && !b_videoFullScreen )
724
725
726
727
728
729
730

    {
        setWindowFlags( newflags );
        show(); /* necessary to apply window flags */
    }
}

731
/* Asynchronous call from WindowControl function */
732
int MainInterface::controlVideo( int i_query, va_list args )
733
734
735
{
    switch( i_query )
    {
736
737
738
739
    case VOUT_WINDOW_SET_SIZE:
    {
        unsigned int i_width  = va_arg( args, unsigned int );
        unsigned int i_height = va_arg( args, unsigned int );
740

741
        emit askVideoToResize( i_width, i_height );
742
        return VLC_SUCCESS;
743
    }
744
    case VOUT_WINDOW_SET_STATE:
745
    {
746
747
        unsigned i_arg = va_arg( args, unsigned );
        unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
748
749

        emit askVideoOnTop( on_top != 0 );
750
751
        return VLC_SUCCESS;
    }
752
753
754
    case VOUT_WINDOW_SET_FULLSCREEN:
    {
        bool b_fs = va_arg( args, int );
755

756
757
758
        emit askVideoSetFullScreen( b_fs );
        return VLC_SUCCESS;
    }
759
760
761
    default:
        msg_Warn( p_intf, "unsupported control query" );
        return VLC_EGENERIC;
762
763
764
    }
}

765
766
767
768
769
770
/*****************************************************************************
 * Playlist, Visualisation and Menus handling
 *****************************************************************************/
/**
 * Toggle the playlist widget or dialog
 **/
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
771
void MainInterface::createPlaylist()
772
{
773
    playlistWidget = new PlaylistWidget( p_intf, this );
774

775
776
777
    if( b_plDocked )
    {
        stackCentralW->addWidget( playlistWidget );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
778
        stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
779
780
    }
    else
781
    {
782
783
784
#ifdef WIN32
        playlistWidget->setParent( NULL );
#endif
785
        playlistWidget->setWindowFlags( Qt::Window );
786

787
788
789
790
791
792
        /* This will restore the geometry but will not work for position,
           because of parenting */
        QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
                playlistWidget, QSize( 600, 300 ) );
    }
}
793

794
795
796
void MainInterface::togglePlaylist()
{
    if( !playlistWidget )
797
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
798
        createPlaylist();
799
    }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
800
801

    if( b_plDocked )
802
    {
803
804
805
806
807
808
809
810
811
        /* Playlist is not visible, show it */
        if( stackCentralW->currentWidget() != playlistWidget )
        {
            showTab( playlistWidget );
        }
        else /* Hide it! */
        {
            restoreStackOldWidget();
        }
812
        playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
813
    }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
814
815
    else
    {
816
817
818
#ifdef WIN32
        playlistWidget->setParent( NULL );
#endif
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
819
820
821
822
        playlistWidget->setWindowFlags( Qt::Window );
        playlistVisible = !playlistVisible;
        playlistWidget->setVisible( playlistVisible );
    }
823
    debug();
824
825
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
826
void MainInterface::dockPlaylist( bool p_docked )
827
{
828
    if( b_plDocked == p_docked ) return;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
829
    b_plDocked = p_docked;
830

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
831
832
833
834
    if( !playlistWidget ) return; /* Playlist wasn't created yet */
    if( !p_docked )
    {
        stackCentralW->removeWidget( playlistWidget );
835
836
837
#ifdef WIN32
        playlistWidget->setParent( NULL );
#endif
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
838
839
840
841
        playlistWidget->setWindowFlags( Qt::Window );
        QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
                playlistWidget, QSize( 600, 300 ) );
        playlistWidget->show();
842
        restoreStackOldWidget();
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
843
844
845
    }
    else
    {
846
        QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
847
848
849
        playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
        // It would be logical that QStackWidget::addWidget reset the flags...
        stackCentralW->addWidget( playlistWidget );
jpd's avatar
jpd committed
850
        showTab( playlistWidget );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
851
    }
jpd's avatar
jpd committed
852
    playlistVisible = true;
zorglub's avatar
zorglub committed
853
854
}

855
856
857
858
/*
 * setMinimalView is the private function used by
 * the SLOT toggleMinimalView and setVideoFullScreen
 */
859
860
861
862
void MainInterface::setMinimalView( bool b_minimal )
{
    menuBar()->setVisible( !b_minimal );
    controls->setVisible( !b_minimal );
863
    statusBar()->setVisible( !b_minimal && b_statusbarVisible );
864
865
866
    inputC->setVisible( !b_minimal );
}

867
/*
868
869
870
 * This public SLOT is used for moving to minimal View Mode
 *
 * If b_minimal is false, then we are normalView
871
 */
872
void MainInterface::toggleMinimalView( bool b_minimal )
873
{
874
    if( !b_minimalView && b_autoresize ) /* Normal mode */
875
876
    {
        if( stackCentralW->currentWidget() == bgWidget )
877
        {
878
879
880
881
            if( stackCentralW->height() < 16 )
            {
                resizeStack( stackCentralW->width(), 100 );
            }
882
883
        }
    }
884
885
    b_minimalView = b_minimal;
    if( !b_videoFullScreen )
886
    {
887
        setMinimalView( b_minimalView );
888
889
        computeMinimumSize();
    }
890

891
    emit minimalViewToggled( b_minimalView );
892
893
}

894
/* toggling advanced controls buttons */
895
void MainInterface::toggleAdvancedButtons()
896
897
{
    controls->toggleAdvanced();
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
898
//    if( fullscreenControls ) fullscreenControls->toggleAdvanced();
899
900
}

901
/* Get the visibility status of the controls (hidden or not, advanced or not) */
902
int MainInterface::getControlsVisibilityStatus()
903
{
904
    if( !controls ) return 0;
905
906
    return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
                + CONTROLS_ADVANCED * controls->b_advancedVisible );
907
908
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
909
910
911
void MainInterface::setStatusBarVisibility( bool b_visible )
{
    statusBar()->setVisible( b_visible );
912
    b_statusbarVisible = b_visible;
913
    if( controls ) controls->setGripVisible( !b_statusbarVisible );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
914
915
}

916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
#if 0
void MainInterface::visual()
{
    if( !VISIBLE( visualSelector) )
    {
        visualSelector->show();
        if( !THEMIM->getIM()->hasVideo() )
        {
            /* Show the background widget */
        }
        visualSelectorEnabled = true;
    }
    else
    {
        /* Stop any currently running visualization */
        visualSelector->hide();
        visualSelectorEnabled = false;
    }
}
#endif

937
938
939
/************************************************************************
 * Other stuff
 ************************************************************************/
ivoire's avatar
ivoire committed
940
void MainInterface::setName( const QString& name )
941
{
942
943
944
    input_name = name; /* store it for the QSystray use */
    /* Display it in the status bar, but also as a Tooltip in case it doesn't
       fit in the label */
945
946
    nameLabel->setText( name );
    nameLabel->setToolTip( name );
947
948
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
949
950
951
952
/**
 * Give the decorations of the Main Window a correct Name.
 * If nothing is given, set it to VLC...
 **/
ivoire's avatar
ivoire committed
953
void MainInterface::setVLCWindowsTitle( const QString& aTitle )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
{
    if( aTitle.isEmpty() )
    {
        setWindowTitle( qtr( "VLC media player" ) );
    }
    else
    {
        setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
    }
}

void MainInterface::showCryptedLabel( bool b_show