X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fqt4%2Fcomponents%2Fcontroller.cpp;h=e1aaad1228d83893e6264ee168b4255731aabe7f;hb=4362a469b5203cc57a17d4acb9354e8d03925478;hp=219ff9da339f00b8e5e15d454dde2ae9fa851d6c;hpb=9a51f390108b2770592886c4e3ea81ae0d64dda5;p=vlc diff --git a/modules/gui/qt4/components/controller.cpp b/modules/gui/qt4/components/controller.cpp index 219ff9da33..e1aaad1228 100644 --- a/modules/gui/qt4/components/controller.cpp +++ b/modules/gui/qt4/components/controller.cpp @@ -1,12 +1,10 @@ /***************************************************************************** * Controller.cpp : Controller for the main interface **************************************************************************** - * Copyright ( C ) 2006-2008 the VideoLAN team + * Copyright (C) 2006-2008 the VideoLAN team * $Id$ * - * Authors: Clément Stenac - * Jean-Baptiste Kempf - * Rafaël Carré + * Authors: Jean-Baptiste Kempf * Ilkka Ollakka * * This program is free software; you can redistribute it and/or modify @@ -29,53 +27,48 @@ #endif #include +#include -#include "dialogs_provider.hpp" +#include "components/controller.hpp" +#include "components/controller_widget.hpp" #include "components/interface_widgets.hpp" -#include "main_interface.hpp" + +#include "dialogs_provider.hpp" /* Opening Dialogs */ #include "input_manager.hpp" -#include "menus.hpp" -#include "util/input_slider.hpp" -#include "util/customwidgets.hpp" +#include "actions_manager.hpp" + +#include "util/input_slider.hpp" /* InputSlider */ +#include "util/customwidgets.hpp" /* qEventToKey */ -#include #include -#include -#include #include #include -#include -#include -#include -#include #include - -#define I_PLAY_TOOLTIP N_("Play\nIf the playlist is empty, open a media") +#include /********************************************************************** * TEH controls **********************************************************************/ /****** - * This is an abstract Toolbar/Controller - * This has helper to create any toolbar, any buttons and to manage the actions - * - *****/ -AbstractController::AbstractController( intf_thread_t * _p_i ) : QFrame( NULL ) + * This is an abstract Toolbar/Controller + * This has helper to create any toolbar, any buttons and to manage the actions + * + *****/ +AbstractController::AbstractController( intf_thread_t * _p_i, QWidget *_parent ) + : QFrame( _parent ) { p_intf = _p_i; - - /* We need one layout. An controller without layout is stupid with - current architecture */ - controlLayout = new QGridLayout( this ); + advControls = NULL; /* Main action provider */ - toolbarActionsMapper = new QSignalMapper(); + toolbarActionsMapper = new QSignalMapper( this ); CONNECT( toolbarActionsMapper, mapped( int ), - this, doAction( int ) ); + ActionsManager::getInstance( p_intf ), doAction( int ) ); CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) ); } +/* Reemit some signals on status Change to activate some buttons */ void AbstractController::setStatus( int status ) { bool b_hasInput = THEMIM->getIM()->hasInput(); @@ -86,8 +79,12 @@ void AbstractController::setStatus( int status ) emit inputIsRecordable( b_hasInput && var_GetBool( THEMIM->getInput(), "can-record" ) ); + + emit inputIsTrickPlayable( b_hasInput && + var_GetBool( THEMIM->getInput(), "can-rewind" ) ); } +/* Generic button setup */ void AbstractController::setupButton( QAbstractButton *aButton ) { static QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); @@ -100,15 +97,82 @@ void AbstractController::setupButton( QAbstractButton *aButton ) aButton->setFocusPolicy( Qt::NoFocus ); } +/* Open the generic config line for the toolbar, parse it + * and create the widgets accordingly */ +void AbstractController::parseAndCreate( QString config, + QBoxLayout *controlLayout ) +{ + QStringList list = config.split( ";", QString::SkipEmptyParts ) ; + for( int i = 0; i < list.size(); i++ ) + { + QStringList list2 = list.at( i ).split( "-" ); + if( list2.size() < 1 ) + { + msg_Warn( p_intf, "Parsing error. Report this" ); + continue; + } + + bool ok; + int i_option = WIDGET_NORMAL; + buttonType_e i_type = (buttonType_e)list2.at( 0 ).toInt( &ok ); + if( !ok ) + { + msg_Warn( p_intf, "Parsing error 0. Please report this" ); + continue; + } + + if( list2.size() > 1 ) + { + i_option = list2.at( 1 ).toInt( &ok ); + if( !ok ) + { + msg_Warn( p_intf, "Parsing error 1. Please report this" ); + continue; + } + } + + createAndAddWidget( controlLayout, -1, i_type, i_option ); + } +} + +void AbstractController::createAndAddWidget( QBoxLayout *controlLayout, + int i_index, + buttonType_e i_type, + int i_option ) +{ + /* Special case for SPACERS, who aren't QWidgets */ + if( i_type == WIDGET_SPACER ) + { + controlLayout->insertSpacing( i_index, 16 ); + return; + } + + if( i_type == WIDGET_SPACER_EXTEND ) + { + controlLayout->insertStretch( i_index, 16 ); + return; + } + + QWidget *widg = createWidget( i_type, i_option ); + if( !widg ) return; + + controlLayout->insertWidget( i_index, widg ); +} + + #define CONNECT_MAP( a ) CONNECT( a, clicked(), toolbarActionsMapper, map() ) #define SET_MAPPING( a, b ) toolbarActionsMapper->setMapping( a , b ) #define CONNECT_MAP_SET( a, b ) \ CONNECT_MAP( a ); \ SET_MAPPING( a, b ); -#define BUTTON_SET_BAR( button, image, tooltip ) \ +#define BUTTON_SET_BAR( a_button ) \ + a_button->setToolTip( tooltipL[button] ); \ + a_button->setIcon( QIcon( iconL[button] ) ); +#define BUTTON_SET_BAR2( button, image, tooltip ) \ button->setToolTip( tooltip ); \ button->setIcon( QIcon( ":/"#image ) ); + #define ENABLE_ON_VIDEO( a ) \ CONNECT( THEMIM->getIM(), voutChanged( bool ), a, setEnabled( bool ) ); \ a->setEnabled( THEMIM->getIM()->hasVideo() ); /* TODO: is this necessary? when input is started before the interface? */ @@ -117,16 +181,21 @@ void AbstractController::setupButton( QAbstractButton *aButton ) CONNECT( this, inputExists( bool ), a, setEnabled( bool ) ); \ a->setEnabled( THEMIM->getIM()->hasInput() ); /* TODO: is this necessary? when input is started before the interface? */ -QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, - bool b_big, bool b_shiny ) +QWidget *AbstractController::createWidget( buttonType_e button, int options ) { + + bool b_flat = options & WIDGET_FLAT; + bool b_big = options & WIDGET_BIG; + bool b_shiny = options & WIDGET_SHINY; + bool b_special = false; + QWidget *widget = NULL; switch( button ) { case PLAY_BUTTON: { PlayButton *playButton = new PlayButton; setupButton( playButton ); - BUTTON_SET_BAR( playButton, play_b, qtr( I_PLAY_TOOLTIP ) ); + BUTTON_SET_BAR( playButton ); CONNECT_MAP_SET( playButton, PLAY_ACTION ); CONNECT( this, inputPlaying( bool ), playButton, updateButton( bool )); @@ -137,16 +206,23 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, QToolButton *stopButton = new QToolButton; setupButton( stopButton ); CONNECT_MAP_SET( stopButton, STOP_ACTION ); - BUTTON_SET_BAR( stopButton, stop_b, qtr( "Stop playback" ) ); + BUTTON_SET_BAR( stopButton ); widget = stopButton; } break; + case OPEN_BUTTON:{ + QToolButton *openButton = new QToolButton; + setupButton( openButton ); + CONNECT_MAP_SET( openButton, OPEN_ACTION ); + BUTTON_SET_BAR( openButton ); + widget = openButton; + } + break; case PREVIOUS_BUTTON:{ QToolButton *prevButton = new QToolButton; setupButton( prevButton ); CONNECT_MAP_SET( prevButton, PREVIOUS_ACTION ); - BUTTON_SET_BAR( prevButton, previous_b, - qtr( "Previous media in the playlist" ) ); + BUTTON_SET_BAR( prevButton ); widget = prevButton; } break; @@ -155,8 +231,7 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, QToolButton *nextButton = new QToolButton; setupButton( nextButton ); CONNECT_MAP_SET( nextButton, NEXT_ACTION ); - BUTTON_SET_BAR( nextButton, next_b, - qtr( "Next media in the playlist" ) ); + BUTTON_SET_BAR( nextButton ); widget = nextButton; } break; @@ -164,7 +239,7 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, QToolButton *slowerButton = new QToolButton; setupButton( slowerButton ); CONNECT_MAP_SET( slowerButton, SLOWER_ACTION ); - BUTTON_SET_BAR( slowerButton, slower, qtr( "Slower" ) ); + BUTTON_SET_BAR( slowerButton ); ENABLE_ON_INPUT( slowerButton ); widget = slowerButton; } @@ -172,28 +247,35 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, case FASTER_BUTTON:{ QToolButton *fasterButton = new QToolButton; setupButton( fasterButton ); - CONNECT_MAP_SET( fasterButton, SLOWER_ACTION ); - BUTTON_SET_BAR( fasterButton, faster, qtr( "Faster" ) ); + CONNECT_MAP_SET( fasterButton, FASTER_ACTION ); + BUTTON_SET_BAR( fasterButton ); ENABLE_ON_INPUT( fasterButton ); widget = fasterButton; } break; -#if 0 case FRAME_BUTTON: { - QToolButton *frameButton = new QToolButton( "Fr" ); + QToolButton *frameButton = new QToolButton; setupButton( frameButton ); - BUTTON_SET_BAR( frameButton, "", qtr( "Frame by frame" ) ); - ENABLE_ON_INPUT( frameButton ); + CONNECT_MAP_SET( frameButton, FRAME_ACTION ); + BUTTON_SET_BAR( frameButton ); + ENABLE_ON_VIDEO( frameButton ); widget = frameButton; } break; -#endif case FULLSCREEN_BUTTON:{ QToolButton *fullscreenButton = new QToolButton; setupButton( fullscreenButton ); CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION ); - BUTTON_SET_BAR( fullscreenButton, fullscreen, - qtr( "Toggle the video in fullscreen" ) ); + BUTTON_SET_BAR( fullscreenButton ); + ENABLE_ON_VIDEO( fullscreenButton ); + widget = fullscreenButton; + } + break; + case DEFULLSCREEN_BUTTON:{ + QToolButton *fullscreenButton = new QToolButton; + setupButton( fullscreenButton ); + CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION ); + BUTTON_SET_BAR( fullscreenButton ) ENABLE_ON_VIDEO( fullscreenButton ); widget = fullscreenButton; } @@ -202,8 +284,7 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, QToolButton *extSettingsButton = new QToolButton; setupButton( extSettingsButton ); CONNECT_MAP_SET( extSettingsButton, EXTENDED_ACTION ); - BUTTON_SET_BAR( extSettingsButton, extended, - qtr( "Show extended settings" ) ); + BUTTON_SET_BAR( extSettingsButton ) widget = extSettingsButton; } break; @@ -211,8 +292,7 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, QToolButton *playlistButton = new QToolButton; setupButton( playlistButton ); CONNECT_MAP_SET( playlistButton, PLAYLIST_ACTION ); - BUTTON_SET_BAR( playlistButton, playlist, - qtr( "Show playlist" ) ); + BUTTON_SET_BAR( playlistButton ); widget = playlistButton; } break; @@ -220,7 +300,7 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, QToolButton *snapshotButton = new QToolButton; setupButton( snapshotButton ); CONNECT_MAP_SET( snapshotButton, SNAPSHOT_ACTION ); - BUTTON_SET_BAR( snapshotButton, snapshot, qtr( "Take a snapshot" ) ); + BUTTON_SET_BAR( snapshotButton ); ENABLE_ON_VIDEO( snapshotButton ); widget = snapshotButton; } @@ -229,16 +309,18 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, QToolButton *recordButton = new QToolButton; setupButton( recordButton ); CONNECT_MAP_SET( recordButton, RECORD_ACTION ); - BUTTON_SET_BAR( recordButton, record, qtr( "Record" ) ); + BUTTON_SET_BAR( recordButton ); ENABLE_ON_INPUT( recordButton ); + recordButton->setCheckable( true ); + CONNECT( THEMIM->getIM(), recordingStateChanged( bool ), + recordButton, setChecked( bool ) ); widget = recordButton; } break; case ATOB_BUTTON: { AtoB_Button *ABButton = new AtoB_Button; setupButton( ABButton ); - BUTTON_SET_BAR( ABButton, atob_nob, qtr( "Loop from point A to point " - "B continuously.\nClick to set point A" ) ); + BUTTON_SET_BAR( ABButton ); ENABLE_ON_INPUT( ABButton ); CONNECT_MAP_SET( ABButton, ATOB_ACTION ); CONNECT( THEMIM->getIM(), AtoBchanged( bool, bool), @@ -248,12 +330,13 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, break; case INPUT_SLIDER: { InputSlider *slider = new InputSlider( Qt::Horizontal, NULL ); + /* Update the position when the IM has changed */ CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ), slider, setPosition( float, int, int ) ); /* And update the IM, when the position has changed */ CONNECT( slider, sliderDragged( float ), - THEMIM->getIM(), sliderUpdate( float ) ); + THEMIM->getIM(), sliderUpdate( float ) ); widget = slider; } break; @@ -265,14 +348,77 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, widget = telexFrame(); widget->hide(); break; + case VOLUME_SPECIAL: + b_special = true; case VOLUME: { - SoundWidget *snd = new SoundWidget( p_intf, b_shiny ); + SoundWidget *snd = new SoundWidget( this, p_intf, b_shiny, b_special ); widget = snd; } break; + case TIME_LABEL: + { + TimeLabel *timeLabel = new TimeLabel( p_intf ); + widget = timeLabel; + } + break; + case SPLITTER: + { + QFrame *line = new QFrame; + line->setFrameShape( QFrame::VLine ); + line->setFrameShadow( QFrame::Raised ); + line->setLineWidth( 0 ); + line->setMidLineWidth( 1 ); + widget = line; + } + break; + case ADVANCED_CONTROLLER: + { + advControls = new AdvControlsWidget( p_intf, this ); + widget = advControls; + } + break; + case REVERSE_BUTTON:{ + QToolButton *reverseButton = new QToolButton; + setupButton( reverseButton ); + CONNECT_MAP_SET( reverseButton, REVERSE_ACTION ); + BUTTON_SET_BAR( reverseButton ); + reverseButton->setCheckable( true ); + /* You should, of COURSE change this to the correct event, + when/if we have one, that tells us if trickplay is possible . */ + CONNECT( this, inputIsTrickPlayable( bool ), reverseButton, setVisible( bool ) ); + reverseButton->setVisible( false ); + widget = reverseButton; + } + break; + case SKIP_BACK_BUTTON: { + QToolButton *skipBakButton = new QToolButton; + setupButton( skipBakButton ); + CONNECT_MAP_SET( skipBakButton, SKIP_BACK_ACTION ); + BUTTON_SET_BAR( skipBakButton ); + ENABLE_ON_INPUT( skipBakButton ); + widget = skipBakButton; + } + break; + case SKIP_FW_BUTTON: { + QToolButton *skipFwButton = new QToolButton; + setupButton( skipFwButton ); + CONNECT_MAP_SET( skipFwButton, SKIP_FW_ACTION ); + BUTTON_SET_BAR( skipFwButton ); + ENABLE_ON_INPUT( skipFwButton ); + widget = skipFwButton; + } + break; + case QUIT_BUTTON: { + QToolButton *quitButton = new QToolButton; + setupButton( quitButton ); + CONNECT_MAP_SET( quitButton, QUIT_ACTION ); + BUTTON_SET_BAR( quitButton ); + widget = quitButton; + } + break; default: - msg_Warn( p_intf, "This should not happen" ); + msg_Warn( p_intf, "This should not happen %i", button ); break; } @@ -294,32 +440,31 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat, return widget; } -QWidget *AbstractController::discFrame() +QFrame *AbstractController::discFrame() { /** Disc and Menus handling */ - QWidget *discFrame = new QWidget( this ); + QFrame *discFrame = new QFrame( this ); QHBoxLayout *discLayout = new QHBoxLayout( discFrame ); discLayout->setSpacing( 0 ); discLayout->setMargin( 0 ); QToolButton *prevSectionButton = new QToolButton( discFrame ); setupButton( prevSectionButton ); - BUTTON_SET_BAR( prevSectionButton, dvd_prev, + BUTTON_SET_BAR2( prevSectionButton, dvd_prev, qtr("Previous Chapter/Title" ) ); discLayout->addWidget( prevSectionButton ); QToolButton *menuButton = new QToolButton( discFrame ); setupButton( menuButton ); discLayout->addWidget( menuButton ); - BUTTON_SET_BAR( menuButton, dvd_menu, qtr( "Menu" ) ); + BUTTON_SET_BAR2( menuButton, dvd_menu, qtr( "Menu" ) ); QToolButton *nextSectionButton = new QToolButton( discFrame ); setupButton( nextSectionButton ); discLayout->addWidget( nextSectionButton ); - BUTTON_SET_BAR( nextSectionButton, dvd_next, + BUTTON_SET_BAR2( nextSectionButton, dvd_next, qtr("Next Chapter/Title" ) ); - /* Change the navigation button display when the IM navigation changes */ CONNECT( THEMIM->getIM(), titleChanged( bool ), @@ -337,12 +482,12 @@ QWidget *AbstractController::discFrame() return discFrame; } -QWidget *AbstractController::telexFrame() +QFrame *AbstractController::telexFrame() { /** * Telextext QFrame **/ - TeletextController *telexFrame = new TeletextController; + QFrame *telexFrame = new QFrame; QHBoxLayout *telexLayout = new QHBoxLayout( telexFrame ); telexLayout->setSpacing( 0 ); telexLayout->setMargin( 0 ); CONNECT( THEMIM->getIM(), teletextPossible( bool ), @@ -350,37 +495,37 @@ QWidget *AbstractController::telexFrame() /* On/Off button */ QToolButton *telexOn = new QToolButton; - telexFrame->telexOn = telexOn; setupButton( telexOn ); - BUTTON_SET_BAR( telexOn, tv, qtr( "Teletext Activation" ) ); + BUTTON_SET_BAR2( telexOn, tv, qtr( "Teletext Activation" ) ); + telexOn->setEnabled( false ); + telexOn->setCheckable( true ); + telexLayout->addWidget( telexOn ); /* Teletext Activation and set */ CONNECT( telexOn, clicked( bool ), THEMIM->getIM(), activateTeletext( bool ) ); - CONNECT( THEMIM->getIM(), teletextActivated( bool ), - telexFrame, enableTeletextButtons( bool ) ); - + CONNECT( THEMIM->getIM(), teletextPossible( bool ), + telexOn, setEnabled( bool ) ); /* Transparency button */ QToolButton *telexTransparent = new QToolButton; - telexFrame->telexTransparent = telexTransparent; setupButton( telexTransparent ); - BUTTON_SET_BAR( telexTransparent, tvtelx, - qtr( "Toggle Transparency " ) ); + BUTTON_SET_BAR2( telexTransparent, tvtelx, + qtr( "Toggle Transparency " ) ); telexTransparent->setEnabled( false ); + telexTransparent->setCheckable( true ); telexLayout->addWidget( telexTransparent ); /* Transparency change and set */ CONNECT( telexTransparent, clicked( bool ), THEMIM->getIM(), telexSetTransparency( bool ) ); CONNECT( THEMIM->getIM(), teletextTransparencyActivated( bool ), - telexFrame, toggleTeletextTransparency( bool ) ); + telexTransparent, setChecked( bool ) ); /* Page setting */ - QSpinBox *telexPage = new QSpinBox; - telexFrame->telexPage = telexPage; + QSpinBox *telexPage = new QSpinBox( telexFrame ); telexPage->setRange( 0, 999 ); telexPage->setValue( 100 ); telexPage->setAccelerated( true ); @@ -396,326 +541,52 @@ QWidget *AbstractController::telexFrame() CONNECT( THEMIM->getIM(), newTelexPageSet( int ), telexPage, setValue( int ) ); + CONNECT( THEMIM->getIM(), teletextActivated( bool ), telexPage, setEnabled( bool ) ); + CONNECT( THEMIM->getIM(), teletextActivated( bool ), telexTransparent, setEnabled( bool ) ); + CONNECT( THEMIM->getIM(), teletextActivated( bool ), telexOn, setChecked( bool ) ); return telexFrame; } #undef CONNECT_MAP #undef SET_MAPPING +#undef CONNECT_MAP_SET #undef BUTTON_SET_BAR +#undef ENABLE_ON_VIDEO +#undef ENABLE_ON_INPUT -SoundWidget::SoundWidget( intf_thread_t * _p_intf, bool b_shiny ) - : b_my_volume( false ) -{ - p_intf = _p_intf; - QHBoxLayout *layout = new QHBoxLayout( this ); - layout->setSpacing( 0 ); layout->setMargin( 0 ); - hVolLabel = new VolumeClickHandler( p_intf, this ); - - volMuteLabel = new QLabel; - volMuteLabel->setPixmap( QPixmap( ":/volume-medium" ) ); - volMuteLabel->installEventFilter( hVolLabel ); - layout->addWidget( volMuteLabel ); - - if( b_shiny ) - { - volumeSlider = new SoundSlider( this, - config_GetInt( p_intf, "volume-step" ), - config_GetInt( p_intf, "qt-volume-complete" ), - config_GetPsz( p_intf, "qt-slider-colours" ) ); - } - else - { - volumeSlider = new QSlider( this ); - volumeSlider->setOrientation( Qt::Horizontal ); - } - volumeSlider->setMaximumSize( QSize( 200, 40 ) ); - volumeSlider->setMinimumSize( QSize( 85, 30 ) ); - volumeSlider->setFocusPolicy( Qt::NoFocus ); - layout->addWidget( volumeSlider ); - - /* Set the volume from the config */ - volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) * - VOLUME_MAX / (AOUT_VOLUME_MAX/2) ); - - /* Force the update at build time in order to have a muted icon if needed */ - updateVolume( volumeSlider->value() ); - - /* Volume control connection */ - CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) ); - CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) ); -} - -void SoundWidget::updateVolume( int i_sliderVolume ) -{ - if( !b_my_volume ) - { - int i_res = i_sliderVolume * (AOUT_VOLUME_MAX / 2) / VOLUME_MAX; - aout_VolumeSet( p_intf, i_res ); - } - if( i_sliderVolume == 0 ) - { - volMuteLabel->setPixmap( QPixmap(":/volume-muted" ) ); - volMuteLabel->setToolTip( qtr( "Unmute" ) ); - return; - } - - if( i_sliderVolume < VOLUME_MAX / 3 ) - volMuteLabel->setPixmap( QPixmap( ":/volume-low" ) ); - else if( i_sliderVolume > (VOLUME_MAX * 2 / 3 ) ) - volMuteLabel->setPixmap( QPixmap( ":/volume-high" ) ); - else volMuteLabel->setPixmap( QPixmap( ":/volume-medium" ) ); - volMuteLabel->setToolTip( qtr( "Mute" ) ); -} - -void SoundWidget::updateVolume() -{ - /* Audio part */ - audio_volume_t i_volume; - aout_VolumeGet( p_intf, &i_volume ); - i_volume = ( i_volume * VOLUME_MAX )/ (AOUT_VOLUME_MAX/2); - int i_gauge = volumeSlider->value(); - b_my_volume = false; - if( i_volume - i_gauge > 1 || i_gauge - i_volume > 1 ) - { - b_my_volume = true; - volumeSlider->setValue( i_volume ); - b_my_volume = false; - } -} - -void TeletextController::toggleTeletextTransparency( bool b_transparent ) -{ - telexTransparent->setIcon( b_transparent ? QIcon( ":/tvtelx" ) - : QIcon( ":/tvtelx-trans" ) ); -} - -void TeletextController::enableTeletextButtons( bool b_enabled ) -{ - telexOn->setChecked( b_enabled ); - telexTransparent->setEnabled( b_enabled ); - telexPage->setEnabled( b_enabled ); -} - -void PlayButton::updateButton( bool b_playing ) -{ - setIcon( b_playing ? QIcon( ":/pause_b" ) : QIcon( ":/play_b" ) ); - setToolTip( b_playing ? qtr( "Pause the playback" ) - : qtr( I_PLAY_TOOLTIP ) ); -} - -void AtoB_Button::setIcons( bool timeA, bool timeB ) -{ - if( !timeA && !timeB) - { - setIcon( QIcon( ":/atob_nob" ) ); - setToolTip( qtr( "Loop from point A to point B continuously\n" - "Click to set point A" ) ); - } - else if( timeA && !timeB ) - { - setIcon( QIcon( ":/atob_noa" ) ); - setToolTip( qtr( "Click to set point B" ) ); - } - else if( timeA && timeB ) - { - setIcon( QIcon( ":/atob" ) ); - setToolTip( qtr( "Stop the A to B loop" ) ); - } -} - - -//* Actions */ -void AbstractController::doAction( int id_action ) -{ - switch( id_action ) - { - case PLAY_ACTION: - play(); break; - case PREVIOUS_ACTION: - prev(); break; - case NEXT_ACTION: - next(); break; - case STOP_ACTION: - stop(); break; - case SLOWER_ACTION: - slower(); break; - case FASTER_ACTION: - faster(); break; - case FULLSCREEN_ACTION: - fullscreen(); break; - case EXTENDED_ACTION: - extSettings(); break; - case PLAYLIST_ACTION: - playlist(); break; - case SNAPSHOT_ACTION: - snapshot(); break; - case RECORD_ACTION: - record(); break; - case ATOB_ACTION: - THEMIM->getIM()->setAtoB(); break; - default: - msg_Dbg( p_intf, "Action: %i", id_action ); - break; - } -} - -void AbstractController::stop() -{ - THEMIM->stop(); -} - -void AbstractController::play() -{ - if( THEPL->current.i_size == 0 ) - { - /* The playlist is empty, open a file requester */ - THEDP->openFileDialog(); - return; - } - THEMIM->togglePlayPause(); -} - -void AbstractController::prev() -{ - THEMIM->prev(); -} - -void AbstractController::next() -{ - THEMIM->next(); -} - -/** - * TODO - * This functions toggle the fullscreen mode - * If there is no video, it should first activate Visualisations... - * This has also to be fixed in enableVideo() - */ -void AbstractController::fullscreen() -{ - vout_thread_t *p_vout = - (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE ); - if( p_vout) - { - var_SetBool( p_vout, "fullscreen", !var_GetBool( p_vout, "fullscreen" ) ); - vlc_object_release( p_vout ); - } -} - -void AbstractController::snapshot() -{ - vout_thread_t *p_vout = - (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE ); - if( p_vout ) - { - vout_Control( p_vout, VOUT_SNAPSHOT ); - vlc_object_release( p_vout ); - } -} - - -void AbstractController::extSettings() -{ - THEDP->extendedDialog(); -} - -void AbstractController::slower() -{ - THEMIM->getIM()->slower(); -} - -void AbstractController::faster() -{ - THEMIM->getIM()->faster(); -} - -void AbstractController::playlist() -{ - if( p_intf->p_sys->p_mi ) p_intf->p_sys->p_mi->togglePlaylist(); -} - -void AbstractController::record() -{ - input_thread_t *p_input = THEMIM->getInput(); - if( p_input ) - { - /* This method won't work fine if the stream can't be cut anywhere */ - const bool b_recording = var_GetBool( p_input, "record" ); - var_SetBool( p_input, "record", !b_recording ); -#if 0 - else - { - /* 'record' access-filter is not loaded, we open Save dialog */ - input_item_t *p_item = input_GetItem( p_input ); - if( !p_item ) - return; - - char *psz = input_item_GetURI( p_item ); - if( psz ) - THEDP->streamingDialog( NULL, psz, true ); - } -#endif - } -} - -#if 0 -//TODO Frame by frame function -void AbstractController::frame(){} -#endif - - +#include /***************************** * DA Control Widget ! *****************************/ ControlsWidget::ControlsWidget( intf_thread_t *_p_i, - bool b_advControls ) : - AbstractController( _p_i ) + bool b_advControls, + QWidget *_parent ) : + AbstractController( _p_i, _parent ) { setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum ); /* advanced Controls handling */ b_advancedVisible = b_advControls; - advControls = new AdvControlsWidget( p_intf ); - if( !b_advancedVisible ) advControls->hide(); - + QVBoxLayout *controlLayout = new QVBoxLayout( this ); + controlLayout->setLayoutMargins( 6, 4, 6, 2, 5 ); controlLayout->setSpacing( 0 ); - controlLayout->setLayoutMargins( 7, 5, 7, 3, 6 ); - - controlLayout->addWidget( createWidget( INPUT_SLIDER ), 0, 1, 1, 18 ); - controlLayout->addWidget( createWidget( SLOWER_BUTTON, true ), 0, 0 ); - controlLayout->addWidget( createWidget( FASTER_BUTTON, true ), 0, 19 ); - - controlLayout->addWidget( createWidget( MENU_BUTTONS ), 1, 8, 2, 3 ); - controlLayout->addWidget( createWidget( TELETEXT_BUTTONS ), 1, 8, 2, 5, Qt::AlignBottom ); - - controlLayout->addWidget( createWidget( PLAY_BUTTON, false, true ), 2, 0, 2, 2, Qt::AlignBottom ); - controlLayout->setColumnMinimumWidth( 2, 10 ); - controlLayout->setColumnStretch( 2, 0 ); - - controlLayout->addWidget( createWidget( PREVIOUS_BUTTON ), 3, 3, Qt::AlignBottom ); - controlLayout->addWidget( createWidget( STOP_BUTTON ), 3, 4, Qt::AlignBottom ); - controlLayout->addWidget( createWidget( NEXT_BUTTON ), 3, 5, Qt::AlignBottom ); - - /* Column 6 is unused */ - controlLayout->setColumnStretch( 6, 0 ); - controlLayout->setColumnStretch( 7, 0 ); - controlLayout->setColumnMinimumWidth( 7, 10 ); + QHBoxLayout *controlLayout1 = new QHBoxLayout; + controlLayout1->setSpacing( 0 ); - controlLayout->addWidget( createWidget( FULLSCREEN_BUTTON ), 3, 8, Qt::AlignBottom ); - controlLayout->addWidget( createWidget( PLAYLIST_BUTTON ), 3, 9, Qt::AlignBottom ); - controlLayout->addWidget( createWidget( EXTENDED_BUTTON ), 3, 10, Qt::AlignBottom ); - controlLayout->setColumnStretch( 11, 0 ); /* telex alignment */ + QString line1 = getSettings()->value( "MainToolbar1", MAIN_TB1_DEFAULT ) + .toString(); + parseAndCreate( line1, controlLayout1 ); - controlLayout->setColumnStretch( 12, 0 ); - controlLayout->setColumnMinimumWidth( 12, 10 ); + QHBoxLayout *controlLayout2 = new QHBoxLayout; + controlLayout2->setSpacing( 0 ); + QString line2 = getSettings()->value( "MainToolbar2", MAIN_TB2_DEFAULT ) + .toString(); + parseAndCreate( line2, controlLayout2 ); - controlLayout->addWidget( advControls, 3, 13, 1, 3, Qt::AlignBottom ); + if( !b_advancedVisible && advControls ) advControls->hide(); - controlLayout->setColumnStretch( 16, 10 ); - controlLayout->setColumnMinimumWidth( 16, 10 ); - - controlLayout->addWidget( createWidget( VOLUME, false, false, true ), - 3, 17, 1, 3, Qt::AlignBottom ); + controlLayout->addLayout( controlLayout1 ); + controlLayout->addLayout( controlLayout2 ); } ControlsWidget::~ControlsWidget() @@ -723,7 +594,9 @@ ControlsWidget::~ControlsWidget() void ControlsWidget::toggleAdvanced() { - if( advControls && !b_advancedVisible ) + if( !advControls ) return; + + if( !b_advancedVisible ) { advControls->show(); b_advancedVisible = true; @@ -736,21 +609,28 @@ void ControlsWidget::toggleAdvanced() emit advancedControlsToggled( b_advancedVisible ); } -AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i ) : - AbstractController( _p_i ) +AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i, QWidget *_parent ) : + AbstractController( _p_i, _parent ) { + controlLayout = new QHBoxLayout( this ); controlLayout->setMargin( 0 ); controlLayout->setSpacing( 0 ); - controlLayout->addWidget( createWidget( RECORD_BUTTON ), 0, 0 ); - controlLayout->addWidget( createWidget( SNAPSHOT_BUTTON ), 0, 1 ); - controlLayout->addWidget( createWidget( ATOB_BUTTON ), 0, 2 ); + QString line = getSettings()->value( "AdvToolbar", ADV_TB_DEFAULT ) + .toString(); + parseAndCreate( line, controlLayout ); } -AdvControlsWidget::~AdvControlsWidget() -{} - +InputControlsWidget::InputControlsWidget( intf_thread_t *_p_i, QWidget *_parent ) : + AbstractController( _p_i, _parent ) +{ + controlLayout = new QHBoxLayout( this ); + controlLayout->setMargin( 0 ); + controlLayout->setSpacing( 0 ); + QString line = getSettings()->value( "InputToolbar", INPT_TB_DEFAULT ).toString(); + parseAndCreate( line, controlLayout ); +} /********************************************************************** * Fullscrenn control widget **********************************************************************/ @@ -768,7 +648,9 @@ FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i ) #endif b_fullscreen = false; i_hide_timeout = 1; - p_vout = NULL; + i_screennumber = -1; + + vout.clear(); setWindowFlags( Qt::ToolTip ); setMinimumWidth( 600 ); @@ -777,33 +659,17 @@ FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i ) setFrameStyle( QFrame::Sunken ); setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); - controlLayout->setLayoutMargins( 5, 2, 5, 2, 5 ); + QVBoxLayout *controlLayout2 = new QVBoxLayout( this ); + controlLayout2->setLayoutMargins( 5, 2, 5, 2, 5 ); /* First line */ - controlLayout->addWidget( createWidget( SLOWER_BUTTON ), 0, 0 ); - controlLayout->addWidget( createWidget( INPUT_SLIDER ), 0, 1, 1, 13 ); - controlLayout->addWidget( createWidget( FASTER_BUTTON ), 0, 14 ); - - /* Second line */ - controlLayout->addWidget( createWidget( PLAY_BUTTON, false, true ), 1, 0, 1, 2 ); - controlLayout->addWidget( createWidget( PREVIOUS_BUTTON ), 1, 2 ); - controlLayout->addWidget( createWidget( STOP_BUTTON ), 1, 3 ); - controlLayout->addWidget( createWidget( NEXT_BUTTON ), 1, 4 ); - - controlLayout->addWidget( createWidget( MENU_BUTTONS ), 1, 5 ); - controlLayout->addWidget( createWidget( TELETEXT_BUTTONS ), 1, 6 ); - QToolButton *fullscreenButton = - qobject_cast(createWidget( FULLSCREEN_BUTTON ) ); - fullscreenButton->setIcon( QIcon( ":/defullscreen" ) ); - controlLayout->addWidget( fullscreenButton, 1, 7 ); - - controlLayout->setColumnStretch( 9, 10 ); + InputControlsWidget *inputC = new InputControlsWidget( p_intf, this ); + controlLayout2->addWidget( inputC ); - TimeLabel *timeLabel = new TimeLabel( p_intf ); - - controlLayout->addWidget( timeLabel, 1, 10 ); - controlLayout->addWidget( createWidget( VOLUME, false, false, true ), - 1, 11, 1, 3 ); + controlLayout = new QHBoxLayout; + QString line = getSettings()->value( "MainWindow/FSCtoolbar", FSC_TB_DEFAULT ).toString(); + parseAndCreate( line, controlLayout ); + controlLayout2->addLayout( controlLayout ); /* hiding timer */ p_hideTimer = new QTimer( this ); @@ -826,14 +692,14 @@ FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i ) #endif vlc_mutex_init_recursive( &lock ); + + CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ), this, setVoutList( vout_thread_t **, int ) ); } FullscreenControllerWidget::~FullscreenControllerWidget() { - getSettings()->beginGroup( "FullScreen" ); - getSettings()->setValue( "pos", pos() ); - getSettings()->endGroup(); - detachVout(); + getSettings()->setValue( "FullScreen/pos", pos() ); + setVoutList( NULL, 0 ); vlc_mutex_destroy( &lock ); } @@ -845,28 +711,17 @@ void FullscreenControllerWidget::showFSC() adjustSize(); /* center down */ int number = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi ); - int totalCount = QApplication::desktop()->numScreens(); - QRect screenRes = QApplication::desktop()->screenGeometry(number); - int offset_x = 0; - int offset_y = 0; - /* Loop all screens to get needed offset_x/y for - * physical screen center. - */ - for(int i=0; i <= totalCount ; i++) + if( number != i_screennumber || + screenRes != QApplication::desktop()->screenGeometry(number) ) { - QRect displayRect = QApplication::desktop()->screenGeometry(i); - if (displayRect.width()+offset_x <= screenRes.x()) - { - offset_x += displayRect.width(); - } - if ( displayRect.height()+offset_y <= screenRes.y()) - { - offset_y += displayRect.height(); - } + screenRes = QApplication::desktop()->screenGeometry(number); + msg_Dbg( p_intf, "Calculation fullscreen controllers center"); + /* screen has changed, calculate new position */ + QPoint pos = QPoint( screenRes.x() + (screenRes.width() / 2) - (width() / 2), + screenRes.y() + screenRes.height() - height()); + move( pos ); + i_screennumber = number; } - QPoint pos = QPoint( offset_x + (screenRes.width() / 2) - (width() / 2), - offset_y + screenRes.height() - height()); - move( pos ); #ifdef WIN32TRICK // after quiting and going to fs, we need to call show() if( isHidden() ) @@ -969,6 +824,7 @@ void FullscreenControllerWidget::customEvent( QEvent *event ) b_fs = b_fullscreen; vlc_mutex_unlock( &lock ); if( b_fs ) + { #ifdef WIN32TRICK if( b_fscHidden ) #else @@ -980,6 +836,7 @@ void FullscreenControllerWidget::customEvent( QEvent *event ) } else hideFSC(); + } break; case FullscreenControlShow_Type: vlc_mutex_lock( &lock ); @@ -1000,6 +857,8 @@ void FullscreenControllerWidget::customEvent( QEvent *event ) if( !b_mouse_over ) // Only if the mouse is not over FSC planHideFSC(); break; + default: + break; } } @@ -1042,6 +901,7 @@ void FullscreenControllerWidget::enterEvent( QEvent *event ) #if HAVE_TRANSPARENCY p_slowHideTimer->stop(); #endif + event->accept(); } /** @@ -1052,6 +912,7 @@ void FullscreenControllerWidget::leaveEvent( QEvent *event ) planHideFSC(); b_mouse_over = false; + event->accept(); } /** @@ -1077,11 +938,11 @@ static int FullscreenControllerWidgetFullscreenChanged( vlc_object_t *vlc_object vlc_value_t new_val, void *data ) { vout_thread_t *p_vout = (vout_thread_t *) vlc_object; + msg_Dbg( p_vout, "Qt4: Fullscreen state changed" ); FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data; - p_fs->fullscreenChanged( p_vout, new_val.b_bool, - var_GetInteger( p_vout, "mouse-hide-timeout" ) ); + p_fs->fullscreenChanged( p_vout, new_val.b_bool, var_GetInteger( p_vout, "mouse-hide-timeout" ) ); return VLC_SUCCESS; } @@ -1090,92 +951,81 @@ static int FullscreenControllerWidgetMouseMoved( vlc_object_t *vlc_object, const vlc_value_t old_val, vlc_value_t new_val, void *data ) { + vout_thread_t *p_vout = (vout_thread_t *)vlc_object; FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data; - int i_mousex, i_mousey; - bool b_toShow = false; - /* Get the value from the Vout - Trust the vout more than Qt */ - i_mousex = var_GetInteger( p_fs->p_vout, "mouse-x" ); - i_mousey = var_GetInteger( p_fs->p_vout, "mouse-y" ); + const int i_mousex = var_GetInteger( p_vout, "mouse-x" ); + const int i_mousey = var_GetInteger( p_vout, "mouse-y" ); - /* First time */ - if( p_fs->i_mouse_last_move_x == -1 || p_fs->i_mouse_last_move_y == -1 ) - { - p_fs->i_mouse_last_move_x = i_mousex; - p_fs->i_mouse_last_move_y = i_mousey; - b_toShow = true; - } - /* All other times */ - else - { - /* Trigger only if move > 3 px dans une direction */ - if( abs( p_fs->i_mouse_last_move_x - i_mousex ) > 2 || - abs( p_fs->i_mouse_last_move_y - i_mousey ) > 2 ) - { - b_toShow = true; - p_fs->i_mouse_last_move_x = i_mousex; - p_fs->i_mouse_last_move_y = i_mousey; - } - } - - if( b_toShow ) - { - /* Show event */ - IMEvent *eShow = new IMEvent( FullscreenControlShow_Type, 0 ); - QApplication::postEvent( p_fs, static_cast(eShow) ); - - /* Plan hide event */ - IMEvent *eHide = new IMEvent( FullscreenControlPlanHide_Type, 0 ); - QApplication::postEvent( p_fs, static_cast(eHide) ); - } + p_fs->mouseChanged( p_vout, i_mousex, i_mousey ); return VLC_SUCCESS; } - /** - * It is called when video start + * It is call to update the list of vout handled by the fullscreen controller */ -void FullscreenControllerWidget::attachVout( vout_thread_t *p_nvout ) +void FullscreenControllerWidget::setVoutList( vout_thread_t **pp_vout, int i_vout ) { - assert( p_nvout && !p_vout ); + QList del; + QList add; - p_vout = p_nvout; + QList set; - msg_Dbg( p_vout, "Qt FS: Attaching Vout" ); - vlc_mutex_lock( &lock ); + /* */ + for( int i = 0; i < i_vout; i++ ) + set += pp_vout[i]; - var_AddCallback( p_vout, "fullscreen", - FullscreenControllerWidgetFullscreenChanged, this ); - /* I miss a add and fire */ - fullscreenChanged( p_vout, var_GetBool( p_vout, "fullscreen" ), - var_GetInteger( p_vout, "mouse-hide-timeout" ) ); + /* Vout to remove */ + vlc_mutex_lock( &lock ); + foreach( vout_thread_t *p_vout, vout ) + { + if( !set.contains( p_vout ) ) + del += p_vout; + } vlc_mutex_unlock( &lock ); -} -/** - * It is called after turn off video. - */ -void FullscreenControllerWidget::detachVout() -{ - if( p_vout ) + + foreach( vout_thread_t *p_vout, del ) { - msg_Dbg( p_vout, "Qt FS: Detaching Vout" ); var_DelCallback( p_vout, "fullscreen", - FullscreenControllerWidgetFullscreenChanged, this ); + FullscreenControllerWidgetFullscreenChanged, this ); vlc_mutex_lock( &lock ); fullscreenChanged( p_vout, false, 0 ); + vout.removeAll( p_vout ); vlc_mutex_unlock( &lock ); - p_vout = NULL; } -} + /* Vout to track */ + vlc_mutex_lock( &lock ); + foreach( vout_thread_t *p_vout, set ) + { + if( !vout.contains( p_vout ) ) + add += p_vout; + } + vlc_mutex_unlock( &lock ); + + foreach( vout_thread_t *p_vout, add ) + { + vlc_object_hold( (vlc_object_t*)p_vout ); + + vlc_mutex_lock( &lock ); + vout.append( p_vout ); + var_AddCallback( p_vout, "fullscreen", + FullscreenControllerWidgetFullscreenChanged, this ); + /* I miss a add and fire */ + fullscreenChanged( p_vout, var_GetBool( p_vout, "fullscreen" ), + var_GetInteger( p_vout, "mouse-hide-timeout" ) ); + vlc_mutex_unlock( &lock ); + } +} /** * Register and unregister callback for mouse moving */ void FullscreenControllerWidget::fullscreenChanged( vout_thread_t *p_vout, bool b_fs, int i_timeout ) { + /* FIXME - multiple vout (ie multiple mouse position ?) and thread safety if multiple vout ? */ msg_Dbg( p_vout, "Qt: Entering Fullscreen" ); vlc_mutex_lock( &lock ); @@ -1197,8 +1047,38 @@ void FullscreenControllerWidget::fullscreenChanged( vout_thread_t *p_vout, /* Force fs hidding */ IMEvent *eHide = new IMEvent( FullscreenControlHide_Type, 0 ); - QApplication::postEvent( this, static_cast(eHide) ); + QApplication::postEvent( this, eHide ); } vlc_mutex_unlock( &lock ); } +/** + * Mouse change callback (show/hide the controller on mouse movement) + */ +void FullscreenControllerWidget::mouseChanged( vout_thread_t *p_vout, int i_mousex, int i_mousey ) +{ + bool b_toShow; + + /* FIXME - multiple vout (ie multiple mouse position ?) and thread safety if multiple vout ? */ + + b_toShow = false; + if( ( i_mouse_last_move_x == -1 || i_mouse_last_move_y == -1 ) || + ( abs( i_mouse_last_move_x - i_mousex ) > 2 || + abs( i_mouse_last_move_y - i_mousey ) > 2 ) ) + { + i_mouse_last_move_x = i_mousex; + i_mouse_last_move_y = i_mousey; + b_toShow = true; + } + + if( b_toShow ) + { + /* Show event */ + IMEvent *eShow = new IMEvent( FullscreenControlShow_Type, 0 ); + QApplication::postEvent( this, eShow ); + + /* Plan hide event */ + IMEvent *eHide = new IMEvent( FullscreenControlPlanHide_Type, 0 ); + QApplication::postEvent( this, eHide ); + } +}