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

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2007-2009 Thorsten Zachmann <zachmann@kde.org>
0003  * Copyright (C) 2008 Jim Courtiau <jeremy.courtiau@gmail.com>
0004  * Copyright (C) 2009 Alexia Allanic <alexia_allanic@yahoo.fr>
0005  * Copyright (C) 2009 Jean-Nicolas Artaud <jeannicolasartaud@gmail.com>
0006  * Copyright (C) 2009 Jérémy Lugagne <jejewindsurf@hotmail.com>
0007  * Copyright (C) 2009 Johann Hingue <yoan1703@hotmail.fr>
0008  *
0009  * This library is free software; you can redistribute it and/or
0010  * modify it under the terms of the GNU Library General Public
0011  * License as published by the Free Software Foundation; either
0012  * version 2 of the License, or (at your option) any later version.
0013  *
0014  * This library is distributed in the hope that it will be useful,
0015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017  * Library General Public License for more details.
0018  *
0019  * You should have received a copy of the GNU Library General Public License
0020  * along with this library; see the file COPYING.LIB.  If not, write to
0021  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0022  * Boston, MA 02110-1301, USA.
0023  */
0024 
0025 #include "KPrPresentationTool.h"
0026 
0027 #include <QWidget>
0028 #include <QVBoxLayout>
0029 #include <QPainter>
0030 #include <QKeyEvent>
0031 #include <QAbstractTextDocumentLayout>
0032 #include <QDesktopServices>
0033 #include <QUrl>
0034 #include <QDBusConnection>
0035 #include <QFrame>
0036 
0037 #include <KoShape.h>
0038 #include <KoShapeManager.h>
0039 #include <KoPointerEvent.h>
0040 #include <KoEventAction.h>
0041 #include <KoPACanvasBase.h>
0042 #include <KoTextShapeData.h>
0043 #include <KoTextLayoutRootArea.h>
0044 #include <KoPointedAt.h>
0045 
0046 #include "KPrViewModePresentation.h"
0047 #include "KPrPresentationStrategy.h"
0048 #include "KPrPresentationHighlightStrategy.h"
0049 #include "KPrPresentationDrawStrategy.h"
0050 #include "KPrPresentationBlackStrategy.h"
0051 #include "ui/KPrPresentationToolWidget.h"
0052 
0053 #ifndef QT_NO_DBUS
0054 #include "KPrPresentationToolAdaptor.h"
0055 #endif
0056 
0057 
0058 KPrPresentationTool::KPrPresentationTool( KPrViewModePresentation &viewMode )
0059 : KoToolBase( viewMode.canvas() )
0060 , m_viewMode( viewMode )
0061 , m_strategy( new KPrPresentationStrategy( this ) )
0062 #ifndef QT_NO_DBUS
0063 , m_bus ( new KPrPresentationToolAdaptor( this ) )
0064 #endif
0065 {   
0066 #ifndef QT_NO_DBUS
0067     QDBusConnection::sessionBus().registerObject("/kpresenter/PresentationTools", this);
0068 #endif
0069 
0070     // tool box
0071     m_frame = new QFrame( m_viewMode.canvas()->canvasWidget() );
0072 
0073     QVBoxLayout *frameLayout = new QVBoxLayout();
0074 
0075     m_presentationToolWidget = new KPrPresentationToolWidget(m_viewMode.canvas()->canvasWidget());
0076     frameLayout->addWidget( m_presentationToolWidget, 0, Qt::AlignLeft | Qt::AlignBottom );
0077     m_frame->setLayout( frameLayout );
0078     m_frame->show();
0079 
0080     m_presentationToolWidget->raise();
0081     m_presentationToolWidget->setVisible( false );
0082     m_presentationToolWidget->installEventFilter(this);
0083 
0084     // Connections of button clicked to slots
0085     connect( m_presentationToolWidget->presentationToolUi().penButton, SIGNAL(clicked()), this, SLOT(drawOnPresentation()) );
0086     connect( m_presentationToolWidget->presentationToolUi().highLightButton, SIGNAL(clicked()), this, SLOT(highlightPresentation()) );
0087     connect( m_presentationToolWidget->presentationToolUi().blackButton, SIGNAL(clicked()), this, SLOT(blackPresentation()) );
0088 
0089 }
0090 
0091 KPrPresentationTool::~KPrPresentationTool()
0092 {
0093     delete m_strategy;
0094 }
0095 
0096 bool KPrPresentationTool::wantsAutoScroll() const
0097 {
0098     return false;
0099 }
0100 
0101 void KPrPresentationTool::paint( QPainter &painter, const KoViewConverter &converter )
0102 {
0103     Q_UNUSED(painter);
0104     Q_UNUSED(converter);
0105 }
0106 
0107 void KPrPresentationTool::mousePressEvent( KoPointerEvent *event )
0108 {
0109     if ( event->button() & Qt::LeftButton ) {
0110         event->accept();
0111         finishEventActions();
0112         KoShape * shapeClicked = canvas()->shapeManager()->shapeAt( event->point );
0113         if (shapeClicked) {
0114             QString link;
0115             if (checkHyperlink(event, shapeClicked, link)) {
0116                 runHyperlink(link);
0117                 return;
0118             }
0119 
0120             m_eventActions = shapeClicked->eventActions();
0121             if (!m_eventActions.isEmpty()) {
0122                 foreach ( KoEventAction * eventAction, m_eventActions ) {
0123                     eventAction->start();
0124                 }
0125                 // don't do next step if a action was executed
0126                 return;
0127             }
0128         }
0129         m_viewMode.navigate( KPrAnimationDirector::NextStep );
0130     }
0131     else if ( event->button() & Qt::RightButton ) {
0132         event->accept();
0133         finishEventActions();
0134         m_viewMode.navigate( KPrAnimationDirector::PreviousStep );
0135     }
0136 }
0137 
0138 void KPrPresentationTool::mouseDoubleClickEvent( KoPointerEvent *event )
0139 {
0140     Q_UNUSED(event);
0141 }
0142 
0143 void KPrPresentationTool::mouseMoveEvent( KoPointerEvent *event )
0144 {
0145     KoShape * shape = canvas()->shapeManager()->shapeAt(event->point);
0146 
0147     QString link;
0148     if (checkHyperlink(event, shape, link)) {
0149         canvas()->setCursor(Qt::PointingHandCursor);
0150         return;
0151     }
0152 
0153     canvas()->setCursor(Qt::ArrowCursor);
0154 }
0155 
0156 void KPrPresentationTool::mouseReleaseEvent( KoPointerEvent *event )
0157 {
0158     Q_UNUSED(event);
0159 }
0160 
0161 void KPrPresentationTool::keyPressEvent( QKeyEvent *event )
0162 {
0163     finishEventActions();
0164     // first try to handle the event in the strategy if it is done there no need to use the default action
0165     if ( ! m_strategy->keyPressEvent( event ) ) {
0166         switch ( event->key() )
0167         {
0168             case Qt::Key_Escape:
0169                 m_viewMode.activateSavedViewMode();
0170                 break;
0171             case Qt::Key_Home:
0172                 m_viewMode.navigate( KPrAnimationDirector::FirstPage );
0173                 break;
0174             case Qt::Key_Up:
0175             case Qt::Key_PageUp:
0176                 m_viewMode.navigate( KPrAnimationDirector::PreviousPage );
0177                 break;
0178             case Qt::Key_Backspace:
0179             case Qt::Key_Left:
0180                 m_viewMode.navigate( KPrAnimationDirector::PreviousStep );
0181                 break;
0182             case Qt::Key_Right:
0183             case Qt::Key_Space:
0184                 m_viewMode.navigate( KPrAnimationDirector::NextStep );
0185                 break;
0186             case Qt::Key_Down:
0187             case Qt::Key_PageDown:
0188                 m_viewMode.navigate( KPrAnimationDirector::NextPage );
0189                 break;
0190             case Qt::Key_End:
0191                 m_viewMode.navigate( KPrAnimationDirector::LastPage );
0192                 break;
0193             default:
0194                 event->ignore();
0195                 break;
0196         }
0197     }
0198 }
0199 
0200 void KPrPresentationTool::keyReleaseEvent( QKeyEvent *event )
0201 {
0202     Q_UNUSED( event );
0203 }
0204 
0205 void KPrPresentationTool::wheelEvent( KoPointerEvent * event )
0206 {
0207     Q_UNUSED( event );
0208 }
0209 
0210 void KPrPresentationTool::activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes)
0211 {
0212     Q_UNUSED(toolActivation);
0213     Q_UNUSED(shapes);
0214     m_frame->setGeometry( canvas()->canvasWidget()->geometry() );
0215     m_presentationToolWidget->setVisible( false );
0216     // redirect event to tool widget
0217     m_frame->installEventFilter( this );
0218     // activate tracking for show/hide tool buttons
0219     m_frame->setMouseTracking( true );
0220 }
0221 
0222 void KPrPresentationTool::deactivate()
0223 {
0224     switchStrategy( new KPrPresentationStrategy( this ) );
0225     finishEventActions();
0226 }
0227 
0228 void KPrPresentationTool::finishEventActions()
0229 {
0230     foreach ( KoEventAction * eventAction, m_eventActions ) {
0231         eventAction->finish();
0232     }
0233 }
0234 
0235 void KPrPresentationTool::switchStrategy( KPrPresentationStrategyBase * strategy )
0236 {
0237     Q_ASSERT( strategy );
0238     Q_ASSERT( m_strategy != strategy );
0239     delete m_strategy;
0240     m_strategy = strategy;
0241 }
0242 
0243 // SLOTS
0244 void KPrPresentationTool::highlightPresentation()
0245 {
0246     KPrPresentationStrategyBase * strategy;
0247     if ( dynamic_cast<KPrPresentationHighlightStrategy *>( m_strategy ) ) {
0248         strategy = new KPrPresentationStrategy( this );
0249     }
0250     else {
0251         strategy = new KPrPresentationHighlightStrategy( this );
0252     }
0253     switchStrategy( strategy );
0254 }
0255 
0256 void KPrPresentationTool::drawOnPresentation()
0257 {
0258     KPrPresentationStrategyBase * strategy;
0259     if ( dynamic_cast<KPrPresentationDrawStrategy*>( m_strategy ) ) {
0260         strategy = new KPrPresentationStrategy( this );
0261     }
0262     else {
0263         strategy = new KPrPresentationDrawStrategy( this );
0264     }
0265     switchStrategy( strategy );
0266 }
0267 
0268 void KPrPresentationTool::blackPresentation()
0269 {
0270     KPrPresentationStrategyBase * strategy;
0271     if ( dynamic_cast<KPrPresentationBlackStrategy*>( m_strategy ) ) {
0272         strategy = new KPrPresentationStrategy( this );
0273     }
0274     else {
0275         strategy = new KPrPresentationBlackStrategy( this );
0276     }
0277     switchStrategy( strategy );
0278 }
0279 
0280 bool KPrPresentationTool::eventFilter( QObject *obj, QEvent * event )
0281 {
0282     if ( event->type() == QEvent::MouseMove ) {
0283         QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event );
0284         QWidget *source = static_cast<QWidget*>( obj );
0285         QPoint pos = source->mapFrom( m_viewMode.canvas()->canvasWidget(), mouseEvent->pos() );
0286 
0287         QSize buttonSize = m_presentationToolWidget->size() + QSize( 20, 20 );
0288         QRect geometry = QRect( 0, m_frame->height() - buttonSize.height(), buttonSize.width(), buttonSize.height() );
0289         if ( geometry.contains( pos ) ) {
0290             m_presentationToolWidget->setVisible( true );
0291         }
0292         else {
0293             m_presentationToolWidget->setVisible( false );
0294         }
0295     }
0296     return false;
0297 }
0298 
0299 bool KPrPresentationTool::checkHyperlink(KoPointerEvent *event, KoShape *shape, QString & hyperLink)
0300 {
0301     if (!shape) {
0302         return false;
0303     }
0304 
0305     KoTextShapeData *textShapeData = qobject_cast<KoTextShapeData*>(shape->userData());
0306     if (textShapeData) {
0307         if (!textShapeData->rootArea()) {
0308             return false ; // not layouted yet
0309         }
0310         QPointF p = shape->absoluteTransformation(0).inverted().map(event->point);
0311         p = p + QPointF(0.0, textShapeData->documentOffset());
0312 
0313         KoPointedAt pointedAt = textShapeData->rootArea()->hitTest(p, Qt::ExactHit);
0314 
0315         if (!textShapeData->isDirty() && !pointedAt.externalHRef.isEmpty()) {
0316             hyperLink = pointedAt.externalHRef;
0317             return true;
0318         }
0319     }
0320     return false;
0321 }
0322 
0323 void KPrPresentationTool::runHyperlink(const QString &hyperLink)
0324 {
0325     QUrl url = QUrl::fromUserInput(hyperLink);
0326 
0327     QDesktopServices::openUrl(url);
0328 }
0329 
0330 KPrPresentationStrategyBase *KPrPresentationTool::strategy()
0331 {
0332     return m_strategy;
0333 }
0334 
0335 KPrViewModePresentation &KPrPresentationTool::viewModePresentation()
0336 {
0337     return m_viewMode;
0338 }
0339 
0340 
0341 void KPrPresentationTool::normalPresentation()
0342 {
0343    switchStrategy( new KPrPresentationStrategy( this ) );
0344 }