File indexing completed on 2024-05-12 16:36:50

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2007-2008 Thorsten Zachmann <zachmann@kde.org>
0003  * Copyright (C) 2008 Fredy Yanardi <fyanardi@kde.org>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Library General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (  at your option ) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #include "KPrViewModePresentation.h"
0022 
0023 #include <QEvent>
0024 #include <QKeyEvent>
0025 #include <QPainter>
0026 #include <QDesktopWidget>
0027 
0028 #include <kcursor.h>
0029 
0030 #include <KoPointerEvent.h>
0031 #include <KoCanvasController.h>
0032 #include <KoPageApp.h>
0033 #include <KoPACanvas.h>
0034 #include <KoPADocument.h>
0035 #include <KoPAViewBase.h>
0036 #include <KoZoomHandler.h>
0037 
0038 #include "StageDebug.h"
0039 #include <KPrView.h>
0040 #include "KPrDocument.h"
0041 #include "KPrPresenterViewWidget.h"
0042 #include "KPrEndOfSlideShowPage.h"
0043 
0044 KPrViewModePresentation::KPrViewModePresentation( KoPAViewBase * view, KoPACanvasBase * canvas )
0045 : KoPAViewMode( view, canvas )
0046 , m_savedParent( 0 )
0047 , m_tool( new KPrPresentationTool( *this ) )
0048 , m_animationDirector( 0 )
0049 , m_pvAnimationDirector( 0 )
0050 , m_presenterViewCanvas( 0 )
0051 , m_presenterViewWidget( 0 )
0052 , m_endOfSlideShowPage( 0 )
0053 , m_view( static_cast<KPrView *>(view) )
0054 {
0055     // TODO: make this viewmode work with non-QWidget-based canvases as well
0056     m_baseCanvas = dynamic_cast<KoPACanvas*>(canvas);
0057 }
0058 
0059 KPrViewModePresentation::~KPrViewModePresentation()
0060 {
0061     delete m_animationDirector;
0062     delete m_tool;
0063 }
0064 
0065 KoViewConverter * KPrViewModePresentation::viewConverter( KoPACanvasBase * canvas )
0066 {
0067     if ( m_baseCanvas && m_animationDirector && m_baseCanvas == canvas ) {
0068         return m_animationDirector->viewConverter();
0069     }
0070     else if ( m_pvAnimationDirector && m_presenterViewCanvas == canvas ) {
0071         return m_pvAnimationDirector->viewConverter();
0072     }
0073     else {
0074         // the m_animationDirector is not yet set up fully therefore return the viewConverter of the view
0075         return m_view->viewConverter();
0076     }
0077 }
0078 
0079 void KPrViewModePresentation::paint(KoPACanvasBase* canvas, QPainter& painter, const QRectF &paintRect)
0080 {
0081     if ( m_baseCanvas && m_baseCanvas == canvas && m_animationDirector ) {
0082         m_animationDirector->paint( painter, paintRect);
0083     } else if ( m_presenterViewCanvas == canvas && m_pvAnimationDirector ) {
0084         m_pvAnimationDirector->paint( painter, paintRect );
0085     }
0086 }
0087 
0088 void KPrViewModePresentation::tabletEvent( QTabletEvent *event, const QPointF &point )
0089 {
0090     Q_UNUSED(event);
0091     Q_UNUSED(point);
0092 }
0093 
0094 void KPrViewModePresentation::mousePressEvent( QMouseEvent *event, const QPointF &point )
0095 {
0096     KoPointerEvent ev( event, point );
0097 
0098     m_tool->mousePressEvent( &ev );
0099 }
0100 
0101 void KPrViewModePresentation::mouseDoubleClickEvent( QMouseEvent *event, const QPointF &point )
0102 {
0103     KoPointerEvent ev( event, point );
0104 
0105     m_tool->mouseDoubleClickEvent( &ev );
0106 }
0107 
0108 void KPrViewModePresentation::mouseMoveEvent( QMouseEvent *event, const QPointF &point )
0109 {
0110     KoPointerEvent ev( event, point );
0111 
0112     m_tool->mouseMoveEvent( &ev );
0113 }
0114 
0115 void KPrViewModePresentation::mouseReleaseEvent( QMouseEvent *event, const QPointF &point )
0116 {
0117     KoPointerEvent ev( event, point );
0118 
0119     m_tool->mouseReleaseEvent( &ev );
0120 }
0121 
0122 void KPrViewModePresentation::shortcutOverrideEvent( QKeyEvent *event )
0123 {
0124     m_tool->shortcutOverrideEvent( event );
0125 }
0126 
0127 void KPrViewModePresentation::keyPressEvent( QKeyEvent *event )
0128 {
0129     m_tool->keyPressEvent( event );
0130 }
0131 
0132 void KPrViewModePresentation::keyReleaseEvent( QKeyEvent *event )
0133 {
0134     m_tool->keyReleaseEvent( event );
0135 }
0136 
0137 void KPrViewModePresentation::wheelEvent( QWheelEvent * event, const QPointF &point )
0138 {
0139     KoPointerEvent ev( event, point );
0140 
0141     m_tool->wheelEvent( &ev );
0142 }
0143 
0144 void KPrViewModePresentation::closeEvent( QCloseEvent * event )
0145 {
0146     activateSavedViewMode();
0147     event->ignore();
0148 }
0149 
0150 void KPrViewModePresentation::activate( KoPAViewMode * previousViewMode )
0151 {
0152     if (!m_baseCanvas) return;
0153 
0154     m_savedViewMode = previousViewMode;               // store the previous view mode
0155     m_savedParent = m_baseCanvas->parentWidget();
0156     m_baseCanvas->setParent( ( QWidget* )0, Qt::Window ); // set parent to 0 and
0157 
0158     QDesktopWidget desktop;
0159 
0160     KPrDocument *document = static_cast<KPrDocument *>( m_view->kopaDocument() );
0161     bool presenterViewEnabled = document->isPresenterViewEnabled();
0162     int presentationscreen = document->presentationMonitor();
0163 
0164     // add end off slideshow page
0165     m_endOfSlideShowPage = new KPrEndOfSlideShowPage( desktop.screenGeometry( presentationscreen ), document );
0166     QList<KoPAPageBase*> pages = document->slideShow();
0167     pages.append( m_endOfSlideShowPage );
0168 
0169     QRect presentationRect = desktop.screenGeometry( presentationscreen );
0170 
0171 #ifdef Q_OS_LINUX
0172     // This breaks and is not required on Windows platforms
0173     m_baseCanvas->setParent(desktop.screen(presentationscreen), Qt::Window); // detach widget to the presentation screen
0174 #endif
0175 
0176     m_baseCanvas->setWindowFlags( Qt::Window ); // make it a window
0177 
0178     // the main animation director needs to be created first since it will set the active page
0179     // of the presentation
0180     // the animation director needs to be set before m_baseCanvas->move is called as this might try to call
0181     // viewConverter.
0182     m_animationDirector = new KPrAnimationDirector( m_view, m_baseCanvas, pages, m_view->activePage() );
0183     // move and resize now as otherwise it is not set when we call activate on the tool.
0184     m_baseCanvas->setGeometry(presentationRect);
0185     m_baseCanvas->setWindowState( m_baseCanvas->windowState() | Qt::WindowFullScreen ); // make it show full screen
0186 
0187     // show and setFocus needs to be done after move and resize as otherwise the move and resize have no effect
0188     m_baseCanvas->show();
0189     m_baseCanvas->setFocus();
0190 
0191     KCursor::setAutoHideCursor( m_baseCanvas, true );
0192 
0193     if ( presenterViewEnabled ) {
0194 
0195         if ( desktop.numScreens() > 1 ) {
0196             int newscreen = desktop.numScreens() - presentationscreen - 1; // What if we have > 2 screens?
0197             QRect pvRect = desktop.screenGeometry( newscreen );
0198 
0199             m_presenterViewCanvas = new KoPACanvas( m_view, document );
0200             m_presenterViewWidget = new KPrPresenterViewWidget( this, pages, m_presenterViewCanvas );
0201 #ifdef Q_OS_LINUX
0202     // This breaks and is not required on Windows platforms
0203             m_presenterViewWidget->setParent( desktop.screen(newscreen), Qt::Window );
0204 #endif
0205             m_presenterViewWidget->setGeometry(pvRect);
0206             m_presenterViewWidget->setWindowState(
0207                     m_presenterViewWidget->windowState() | Qt::WindowFullScreen );
0208             m_presenterViewWidget->updateWidget( pvRect.size(), presentationRect.size() );
0209             m_presenterViewWidget->show();
0210             m_presenterViewWidget->setFocus();                             // it shown full screen
0211 
0212             m_pvAnimationDirector = new KPrAnimationDirector( m_view,
0213                     m_presenterViewCanvas, pages, m_view->activePage() );
0214         }
0215         else {
0216             warnStage << "Presenter View is enabled but only found one monitor";
0217             document->setPresenterViewEnabled( false );
0218         }
0219     }
0220 
0221     m_tool->activate(KoToolBase::DefaultActivation, QSet<KoShape*>());
0222 
0223     emit activated();
0224     emit pageChanged( m_animationDirector->currentPage(), m_animationDirector->numStepsInPage() );
0225     emit stepChanged( m_animationDirector->currentStep() );
0226 }
0227 
0228 void KPrViewModePresentation::deactivate()
0229 {
0230     emit deactivated();
0231 
0232     m_animationDirector->deactivate();
0233     KoPAPageBase * page = m_view->activePage();
0234     if ( m_endOfSlideShowPage ) {
0235         if ( page == m_endOfSlideShowPage ) {
0236             KPrDocument *document = static_cast<KPrDocument *>( m_view->kopaDocument() );
0237             if (document->slideShow().size() > 0) {
0238                 page = document->slideShow().last();
0239             }
0240             else {
0241                 page = document->pages().first();
0242             }
0243         }
0244     }
0245     m_tool->deactivate();
0246 
0247     if (!m_baseCanvas) return;
0248 
0249     m_baseCanvas->setParent( m_savedParent, Qt::Widget );
0250     m_baseCanvas->setFocus();
0251     m_baseCanvas->setWindowState( m_baseCanvas->windowState() & ~Qt::WindowFullScreen ); // reset
0252     m_baseCanvas->show();
0253     KCursor::setAutoHideCursor( m_baseCanvas, false );
0254     m_baseCanvas->setMouseTracking( true );
0255     m_view->setActivePage( page );
0256 
0257     // only delete after the new page has been set
0258     delete m_endOfSlideShowPage;
0259     m_endOfSlideShowPage = 0;
0260 
0261     delete m_animationDirector;
0262     m_animationDirector = 0;
0263 
0264     if ( m_presenterViewWidget ) {
0265         m_presenterViewWidget->setWindowState(
0266             m_presenterViewWidget->windowState() & ~Qt::WindowFullScreen );
0267         delete m_pvAnimationDirector;
0268         m_pvAnimationDirector = 0;
0269 
0270         delete m_presenterViewWidget;
0271         m_presenterViewWidget = 0;
0272         m_presenterViewCanvas = 0;
0273     }
0274     // make sure the page does not have an offset after finishing a presentation
0275     m_baseCanvas->setDocumentOffset(QPoint(0, 0));
0276 }
0277 
0278 void KPrViewModePresentation::updateActivePage( KoPAPageBase *page )
0279 {
0280     m_view->setActivePage( page );
0281     if ( m_presenterViewWidget ) {
0282         if ( 0 != m_animationDirector ) {
0283             m_presenterViewWidget->setActivePage( m_animationDirector->currentPage() );
0284         }
0285         else {
0286             m_presenterViewWidget->setActivePage( page );
0287         }
0288     }
0289 }
0290 
0291 void KPrViewModePresentation::activateSavedViewMode()
0292 {
0293     m_view->setViewMode( m_savedViewMode );
0294 }
0295 
0296 KPrAnimationDirector * KPrViewModePresentation::animationDirector()
0297 {
0298     return m_animationDirector;
0299 }
0300 
0301 int KPrViewModePresentation::numPages() const
0302 {
0303     Q_ASSERT( 0 != m_animationDirector );
0304     return m_animationDirector ? m_animationDirector->numPages() : -1;
0305 }
0306 
0307 int KPrViewModePresentation::currentPage() const
0308 {
0309     Q_ASSERT( 0 != m_animationDirector );
0310     return m_animationDirector ? m_animationDirector->currentPage() : -1;
0311 }
0312 
0313 int KPrViewModePresentation::numStepsInPage() const
0314 {
0315     Q_ASSERT( 0 != m_animationDirector );
0316     return m_animationDirector ? m_animationDirector->numStepsInPage() : -1;
0317 }
0318 
0319 int KPrViewModePresentation::currentStep() const
0320 {
0321     Q_ASSERT( 0 != m_animationDirector );
0322     return m_animationDirector ? m_animationDirector->currentStep() : -1;
0323 }
0324 
0325 KPrPresentationTool * KPrViewModePresentation::presentationTool() const
0326 {
0327     Q_ASSERT( 0 != m_animationDirector );
0328     return m_tool;
0329 }
0330 
0331 void KPrViewModePresentation::navigate( KPrAnimationDirector::Navigation navigation )
0332 {
0333     Q_ASSERT( 0 != m_animationDirector );
0334     if ( 0 == m_animationDirector ) {
0335       return;
0336     }
0337     int previousPage = m_animationDirector->currentPage();
0338     bool finished = m_animationDirector->navigate( navigation );
0339     if ( m_pvAnimationDirector ) {
0340         finished = m_pvAnimationDirector->navigate( navigation ) && finished;
0341     }
0342 
0343     int newPage = m_animationDirector->currentPage();
0344     if ( previousPage != newPage ) {
0345         emit pageChanged( newPage, m_animationDirector->numStepsInPage() );
0346     }
0347     emit stepChanged( m_animationDirector->currentStep() );
0348 
0349     if ( finished ) {
0350         activateSavedViewMode();
0351     }
0352 }
0353 
0354 void KPrViewModePresentation::navigateToPage( int index )
0355 {
0356     Q_ASSERT( 0 != m_animationDirector );
0357     if ( 0 == m_animationDirector ) {
0358       return;
0359     }
0360     m_animationDirector->navigateToPage( index );
0361     if ( m_pvAnimationDirector ) {
0362         m_pvAnimationDirector->navigateToPage( index );
0363     }
0364 
0365     emit pageChanged( m_animationDirector->currentPage(), m_animationDirector->numStepsInPage() );
0366     emit stepChanged( m_animationDirector->currentStep() );
0367 }
0368 
0369 bool KPrViewModePresentation::isActivated()
0370 {
0371     return m_view->isPresentationRunning();
0372 }