add a small widget for showing an animation from the "animations" category of the...
[kdegraphics.git] / okular / ui / videowidget.cpp
blobb5d2315c54945dc3a44e052f687da1987e9c7070
1 /***************************************************************************
2 * Copyright (C) 2008 by Pino Toscano <pino@kde.org> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 ***************************************************************************/
10 #include "videowidget.h"
12 // qt/kde includes
13 #include <qaction.h>
14 #include <qdir.h>
15 #include <qevent.h>
16 #include <qlayout.h>
17 #include <qmenu.h>
18 #include <qtoolbar.h>
19 #include <qtoolbutton.h>
20 #include <qwidgetaction.h>
22 #include <kicon.h>
23 #include <klocale.h>
25 #include <phonon/seekslider.h>
26 #include <phonon/videoplayer.h>
28 #include "core/area.h"
29 #include "core/annotations.h"
30 #include "core/document.h"
31 #include "core/movie.h"
33 static QAction* createToolBarButtonWithWidgetPopup( QToolBar* toolBar, QWidget *widget, const QIcon &icon )
35 QToolButton *button = new QToolButton( toolBar );
36 QAction *action = toolBar->addWidget( button );
37 button->setAutoRaise( true );
38 button->setIcon( icon );
39 button->setPopupMode( QToolButton::InstantPopup );
40 QMenu *menu = new QMenu( button );
41 button->setMenu( menu );
42 QWidgetAction *widgetAction = new QWidgetAction( menu );
43 QWidget *dummy = new QWidget( menu );
44 widgetAction->setDefaultWidget( dummy );
45 QVBoxLayout *dummyLayout = new QVBoxLayout( dummy );
46 dummyLayout->setMargin( 5 );
47 dummyLayout->addWidget( widget );
48 menu->addAction( widgetAction );
49 return action;
52 /* Private storage. */
53 class VideoWidget::Private
55 public:
56 Private( Okular::MovieAnnotation *ma, Okular::Document *doc, VideoWidget *qq )
57 : q( qq ), anno( ma ), document( doc ), loaded( false )
61 enum PlayPauseMode { PlayMode, PauseMode };
63 void load();
64 void setupPlayPauseAction( PlayPauseMode mode );
66 // slots
67 void finished();
68 void playOrPause();
70 VideoWidget *q;
71 Okular::MovieAnnotation *anno;
72 Okular::Document *document;
73 Okular::NormalizedRect geom;
74 Phonon::VideoPlayer *player;
75 Phonon::SeekSlider *seekSlider;
76 QToolBar *controlBar;
77 QAction *playPauseAction;
78 QAction *stopAction;
79 QAction *seekSliderAction;
80 QAction *seekSliderMenuAction;
81 bool loaded : 1;
84 void VideoWidget::Private::load()
86 if ( loaded )
87 return;
89 loaded = true;
91 QString url = anno->movie()->url();
92 KUrl newurl;
93 if ( QDir::isRelativePath( url ) )
95 newurl = document->currentDocument();
96 newurl.setFileName( url );
98 else
100 newurl = url;
102 if ( newurl.isLocalFile() )
103 player->load( newurl.toLocalFile() );
104 else
105 player->load( newurl );
107 seekSlider->setEnabled( true );
110 void VideoWidget::Private::setupPlayPauseAction( PlayPauseMode mode )
112 if ( mode == PlayMode )
114 playPauseAction->setIcon( KIcon( "media-playback-start" ) );
115 playPauseAction->setText( i18nc( "start the movie playback", "Play" ) );
117 else if ( mode == PauseMode )
119 playPauseAction->setIcon( KIcon( "media-playback-pause" ) );
120 playPauseAction->setText( i18nc( "pause the movie playback", "Pause" ) );
124 void VideoWidget::Private::finished()
126 switch ( anno->movie()->playMode() )
128 case Okular::Movie::PlayOnce:
129 case Okular::Movie::PlayOpen:
130 // playback has ended, nothing to do
131 stopAction->setEnabled( false );
132 setupPlayPauseAction( PlayMode );
133 if ( anno->movie()->playMode() == Okular::Movie::PlayOnce )
134 controlBar->setVisible( false );
135 break;
136 case Okular::Movie::PlayRepeat:
137 // repeat the playback
138 player->play();
139 break;
140 case Okular::Movie::PlayPalindrome:
141 // FIXME we should play backward, but we cannot
142 player->play();
143 break;
147 void VideoWidget::Private::playOrPause()
149 if ( player->isPlaying() )
151 player->pause();
152 setupPlayPauseAction( PlayMode );
154 else
156 q->play();
160 VideoWidget::VideoWidget( Okular::MovieAnnotation *movieann, Okular::Document *document, QWidget *parent )
161 : QWidget( parent ), d( new Private( movieann, document, this ) )
163 // do not propagate the mouse events to the parent widget;
164 // they should be tied to this widget, not spread around...
165 setAttribute( Qt::WA_NoMousePropagation );
167 QVBoxLayout *mainlay = new QVBoxLayout( this );
168 mainlay->setMargin( 0 );
169 mainlay->setSpacing( 0 );
171 d->player = new Phonon::VideoPlayer( Phonon::NoCategory, this );
172 d->player->installEventFilter( this );
173 mainlay->addWidget( d->player );
175 d->controlBar = new QToolBar( this );
176 d->controlBar->setIconSize( QSize( 16, 16 ) );
177 d->controlBar->setAutoFillBackground( true );
178 mainlay->addWidget( d->controlBar );
180 d->playPauseAction = new QAction( d->controlBar );
181 d->controlBar->addAction( d->playPauseAction );
182 d->setupPlayPauseAction( Private::PlayMode );
183 d->stopAction = d->controlBar->addAction(
184 KIcon( "media-playback-stop" ),
185 i18nc( "stop the movie playback", "Stop" ),
186 this, SLOT( stop() ) );
187 d->stopAction->setEnabled( false );
188 d->controlBar->addSeparator();
189 d->seekSlider = new Phonon::SeekSlider( d->player->mediaObject(), d->controlBar );
190 d->seekSliderAction = d->controlBar->addWidget( d->seekSlider );
191 d->seekSlider->setEnabled( false );
193 Phonon::SeekSlider *verticalSeekSlider = new Phonon::SeekSlider( d->player->mediaObject(), 0 );
194 verticalSeekSlider->setMaximumHeight( 100 );
195 d->seekSliderMenuAction = createToolBarButtonWithWidgetPopup(
196 d->controlBar, verticalSeekSlider, KIcon( "player-time" ) );
197 d->seekSliderMenuAction->setVisible( false );
199 d->controlBar->setVisible( movieann->movie()->showControls() );
201 connect( d->player, SIGNAL( finished() ), this, SLOT( finished() ) );
202 connect( d->playPauseAction, SIGNAL( triggered() ), this, SLOT( playOrPause() ) );
204 d->geom = movieann->transformedBoundingRectangle();
207 VideoWidget::~VideoWidget()
209 delete d;
212 void VideoWidget::setNormGeometry( const Okular::NormalizedRect &rect )
214 d->geom = rect;
217 Okular::NormalizedRect VideoWidget::normGeometry() const
219 return d->geom;
222 void VideoWidget::play()
224 d->load();
225 d->player->play();
226 d->stopAction->setEnabled( true );
227 d->setupPlayPauseAction( Private::PauseMode );
230 void VideoWidget::stop()
232 d->player->stop();
233 d->stopAction->setEnabled( false );
234 d->setupPlayPauseAction( Private::PlayMode );
237 void VideoWidget::pause()
239 d->player->pause();
240 d->setupPlayPauseAction( Private::PlayMode );
243 bool VideoWidget::eventFilter( QObject * object, QEvent * event )
245 if ( object == d->player )
247 switch ( event->type() )
249 case QEvent::MouseButtonPress:
251 QMouseEvent * me = static_cast< QMouseEvent * >( event );
252 if ( me->button() == Qt::LeftButton )
254 if ( !d->player->isPlaying() )
256 play();
258 event->accept();
261 default: ;
265 return false;
268 bool VideoWidget::event( QEvent * event )
270 switch ( event->type() )
272 case QEvent::ToolTip:
273 // "eat" the help events (= tooltips), avoid parent widgets receiving them
274 event->accept();
275 return true;
276 break;
277 default: ;
280 return QWidget::event( event );
283 void VideoWidget::resizeEvent( QResizeEvent * event )
285 const QSize &s = event->size();
286 int usedSpace = d->seekSlider->geometry().left() + d->seekSlider->iconSize().width();
287 // try to give the slider at least 30px of space
288 if ( s.width() < ( usedSpace + 30 ) )
290 d->seekSliderAction->setVisible( false );
291 d->seekSliderMenuAction->setVisible( true );
293 else
295 d->seekSliderAction->setVisible( true );
296 d->seekSliderMenuAction->setVisible( false );
300 #include "videowidget.moc"