00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <KoView.h>
00021 #include <KoDocument.h>
00022 #include <KoMainWindow.h>
00023 #include <KoFrame.h>
00024
00025 #include "KoViewAdaptor.h"
00026 #include <KoDocumentChild.h>
00027 #include <KoDockFactory.h>
00028 #include <kactioncollection.h>
00029 #include <klocale.h>
00030 #include <kglobal.h>
00031 #include <kdebug.h>
00032 #include <kparts/partmanager.h>
00033 #include <kparts/event.h>
00034 #include <kcursor.h>
00035 #include <assert.h>
00036 #include <kstatusbar.h>
00037 #include <kapplication.h>
00038 #include <QTimer>
00039 #include <QtGui/QDockWidget>
00040
00041 #include <Q3PtrList>
00042 #include <QEvent>
00043 #include <Q3ValueList>
00044 #include <QMouseEvent>
00045 #include <QCustomEvent>
00046 #include <kicon.h>
00047
00048
00049 QString KoView::newObjectName()
00050 {
00051 static int s_viewIFNumber = 0;
00052 QString name; name.setNum( s_viewIFNumber++ ); name.prepend("view_");
00053 return name;
00054 }
00055
00056 class KoViewPrivate
00057 {
00058 public:
00059 KoViewPrivate()
00060 {
00061 m_inOperation = false;
00062 m_zoom = 1.0;
00063 m_children.setAutoDelete( true );
00064 m_manager = 0L;
00065 m_tempActiveWidget = 0L;
00066
00067 m_registered=false;
00068 m_documentDeleted=false;
00069 }
00070 ~KoViewPrivate()
00071 {
00072 }
00073
00074 QPointer<KoDocument> m_doc;
00075 QPointer<KParts::PartManager> m_manager;
00076 double m_zoom;
00077 Q3PtrList<KoViewChild> m_children;
00078 QWidget *m_tempActiveWidget;
00079
00080 bool m_registered;
00081 bool m_documentDeleted;
00082
00083
00084 QTimer *m_scrollTimer;
00085
00086
00087
00088 class StatusBarItem {
00089 public:
00090 StatusBarItem()
00091 : m_widget(0), m_visible(false)
00092 {}
00093 StatusBarItem( QWidget * widget, int stretch, bool permanent )
00094 : m_widget(widget), m_stretch(stretch), m_permanent(permanent), m_visible(false)
00095 {}
00096
00097 QWidget * widget() const { return m_widget; }
00098
00099 void ensureItemShown( KStatusBar * sb )
00100 {
00101 if ( !m_visible )
00102 {
00103 if( m_permanent )
00104 sb->addPermanentWidget( m_widget, m_stretch );
00105 else
00106 sb->addWidget( m_widget, m_stretch );
00107
00108 m_visible = true;
00109 m_widget->show();
00110 }
00111 }
00112 void ensureItemHidden( KStatusBar * sb )
00113 {
00114 if ( m_visible )
00115 {
00116 sb->removeWidget( m_widget );
00117 m_visible = false;
00118 m_widget->hide();
00119 }
00120 }
00121 private:
00122 QWidget * m_widget;
00123 int m_stretch;
00124 bool m_permanent;
00125 bool m_visible;
00126 };
00127 Q3ValueList<StatusBarItem> m_statusBarItems;
00128 bool m_inOperation;
00129 };
00130
00131 KoView::KoView( KoDocument *document, QWidget *parent )
00132 : QWidget( parent )
00133 {
00134 Q_ASSERT( document );
00135
00136 setObjectName( newObjectName() );
00137
00138 new KoViewAdaptor(this);
00139 QDBusConnection::sessionBus().registerObject('/' + objectName(), this);
00140
00141
00142 d = new KoViewPrivate;
00143 d->m_doc = document;
00144 KParts::PartBase::setPartObject( this );
00145
00146 setFocusPolicy( Qt::StrongFocus );
00147
00148 setMouseTracking( true );
00149
00150 connect( d->m_doc, SIGNAL( childChanged( KoDocumentChild * ) ),
00151 this, SLOT( slotChildChanged( KoDocumentChild * ) ) );
00152
00153 connect( d->m_doc, SIGNAL( sigBeginOperation() ),
00154 this, SLOT( beginOperation() ) );
00155
00156 connect( d->m_doc, SIGNAL( sigEndOperation() ),
00157 this, SLOT( endOperation() ) );
00158
00159
00160 actionCollection()->setAssociatedWidget(this);
00161 setupGlobalActions();
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 KStatusBar * sb = statusBar();
00172 if ( sb )
00173 {
00174
00175 #warning portKDE4
00176 #if 0
00177 connect( coll, SIGNAL( actionStatusText( const QString & ) ),
00178 this, SLOT( slotActionStatusText( const QString & ) ) );
00179 connect( coll, SIGNAL( clearStatusText() ),
00180 this, SLOT( slotClearStatusText() ) );
00181 #endif
00182
00183 connect( d->m_doc, SIGNAL( sigStatusBarMessage( const QString& ) ),
00184 this, SLOT( slotActionStatusText( const QString& ) ) );
00185 connect( d->m_doc, SIGNAL( sigClearStatusBarMessage() ),
00186 this, SLOT( slotClearStatusText() ) );
00187 }
00188 d->m_doc->setCurrent();
00189
00190 d->m_scrollTimer = new QTimer( this );
00191 connect (d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ) );
00192 }
00193
00194 KoView::~KoView()
00195 {
00196 kDebug(30003) << "KoView::~KoView " << this << endl;
00197 delete d->m_scrollTimer;
00198
00199 if (!d->m_documentDeleted)
00200 {
00201 if ( koDocument() && !koDocument()->isSingleViewMode() )
00202 {
00203 if ( d->m_manager && d->m_registered )
00204 d->m_manager->removePart( koDocument() );
00205 d->m_doc->removeView(this);
00206 d->m_doc->setCurrent( false );
00207 }
00208 }
00209 delete d;
00210 }
00211
00212 KoDocument *KoView::koDocument() const
00213 {
00214 return d->m_doc;
00215 }
00216
00217 void KoView::setDocumentDeleted()
00218 {
00219 d->m_documentDeleted = true;
00220 }
00221
00222 bool KoView::documentDeleted() const
00223 {
00224 return d->m_documentDeleted;
00225 }
00226
00227 bool KoView::hasDocumentInWindow( KoDocument *doc )
00228 {
00229 return child( doc ) != 0L;
00230 }
00231
00232 void KoView::setPartManager( KParts::PartManager *manager )
00233 {
00234 d->m_manager = manager;
00235 if ( !koDocument()->isSingleViewMode() &&
00236 !manager->parts().contains( koDocument() ) )
00237 {
00238 d->m_registered = true;
00239 manager->addPart( koDocument(), false );
00240 }
00241 else
00242 d->m_registered = false;
00243 }
00244
00245 KParts::PartManager *KoView::partManager() const
00246 {
00247 return d->m_manager;
00248 }
00249
00250 KAction *KoView::action( const QDomElement &element ) const
00251 {
00252 static const QString &attrName = KGlobal::staticQString( "name" );
00253 QString name = element.attribute( attrName );
00254
00255 KAction *act = KXMLGUIClient::action( name.toUtf8() );
00256
00257 if ( !act )
00258 act = d->m_doc->KXMLGUIClient::action( name.toUtf8() );
00259
00260 return act;
00261 }
00262
00263 KoDocument *KoView::hitTest( const QPoint &viewPos )
00264 {
00265 KoViewChild *viewChild;
00266
00267 QPoint pos = reverseViewTransformations( viewPos );
00268
00269 KoDocumentChild *docChild = selectedChild();
00270 if ( docChild )
00271 {
00272 if ( ( viewChild = child( docChild->document() ) ) )
00273 {
00274 if ( viewChild->frameRegion().contains( pos ) )
00275 return 0;
00276 }
00277 else
00278 if ( docChild->frameRegion().contains( pos ) )
00279 return 0;
00280 }
00281
00282 docChild = activeChild();
00283 if ( docChild )
00284 {
00285 if ( ( viewChild = child( docChild->document() ) ) )
00286 {
00287 if ( viewChild->frameRegion().contains( pos ) )
00288 return 0;
00289 }
00290 else
00291 if ( docChild->frameRegion().contains( pos ) )
00292 return 0;
00293 }
00294
00295 return koDocument()->hitTest( pos, this );
00296 }
00297
00298 int KoView::leftBorder() const
00299 {
00300 return 0;
00301 }
00302
00303 int KoView::rightBorder() const
00304 {
00305 return 0;
00306 }
00307
00308 int KoView::topBorder() const
00309 {
00310 return 0;
00311 }
00312
00313 int KoView::bottomBorder() const
00314 {
00315 return 0;
00316 }
00317
00318 void KoView::setZoom( double zoom )
00319 {
00320 d->m_zoom = zoom;
00321 update();
00322 }
00323
00324 double KoView::zoom() const
00325 {
00326 return d->m_zoom;
00327 }
00328
00329 QWidget *KoView::canvas() const
00330 {
00331
00332
00333 return const_cast<KoView *>(this);
00334 }
00335
00336 int KoView::canvasXOffset() const
00337 {
00338 return 0;
00339 }
00340
00341 int KoView::canvasYOffset() const
00342 {
00343 return 0;
00344 }
00345
00346 void KoView::canvasAddChild( KoViewChild * )
00347 {
00348 }
00349
00350 void KoView::customEvent( QEvent *ev )
00351 {
00352 if ( KParts::PartActivateEvent::test( ev ) )
00353 partActivateEvent( (KParts::PartActivateEvent *)ev );
00354 else if ( KParts::PartSelectEvent::test( ev ) )
00355 partSelectEvent( (KParts::PartSelectEvent *)ev );
00356 else if( KParts::GUIActivateEvent::test( ev ) )
00357 guiActivateEvent( (KParts::GUIActivateEvent*)ev );
00358 }
00359
00360 void KoView::partActivateEvent( KParts::PartActivateEvent *event )
00361 {
00362 if ( event->part() != (KParts::Part *)koDocument() )
00363 {
00364 assert( event->part()->inherits( "KoDocument" ) );
00365
00366 KoDocumentChild *child = koDocument()->child( (KoDocument *)event->part() );
00367 if ( child && event->activated() )
00368 {
00369 if ( child->isRectangle() && !child->isTransparent() )
00370 {
00371 KoViewChild *viewChild = new KoViewChild( child, this );
00372 d->m_children.append( viewChild );
00373
00374 QApplication::setOverrideCursor(Qt::WaitCursor);
00375
00376 d->m_manager->setActivePart( child->document(), viewChild->frame()->view() );
00377 QApplication::restoreOverrideCursor();
00378
00379
00380 viewChild->setInitialFrameGeometry();
00381 }
00382 else
00383 {
00384 emit regionInvalidated( child->frameRegion( matrix() ), true );
00385 }
00386 emit childActivated( child );
00387 }
00388 else if ( child )
00389 {
00390 emit regionInvalidated( child->frameRegion( matrix() ), true );
00391 emit childDeactivated( child );
00392 }
00393 else
00394 emit invalidated();
00395 }
00396 else
00397 emit activated( event->activated() );
00398 }
00399
00400 void KoView::partSelectEvent( KParts::PartSelectEvent *event )
00401 {
00402 if ( event->part() != (KParts::Part *)koDocument() )
00403 {
00404 assert( event->part()->inherits( "KoDocument" ) );
00405
00406 KoDocumentChild *child = koDocument()->child( (KoDocument *)event->part() );
00407
00408 if ( child && event->selected() )
00409 {
00410 QRegion r = child->frameRegion( matrix() );
00411 r.translate( - canvasXOffset(), - canvasYOffset() );
00412 emit regionInvalidated( r, true );
00413 emit childSelected( child );
00414 }
00415 else if ( child )
00416 {
00417 QRegion r = child->frameRegion( matrix() );
00418 r.translate( - canvasXOffset(), - canvasYOffset() );
00419 emit regionInvalidated( r, true );
00420 emit childUnselected( child );
00421 }
00422 else
00423 emit invalidated();
00424 }
00425 else
00426 emit selected( event->selected() );
00427 }
00428
00429 void KoView::guiActivateEvent( KParts::GUIActivateEvent * ev )
00430 {
00431 showAllStatusBarItems( ev->activated() );
00432 }
00433
00434 void KoView::showAllStatusBarItems( bool show )
00435 {
00436 KStatusBar * sb = statusBar();
00437 if ( !sb )
00438 return;
00439 Q3ValueListIterator<KoViewPrivate::StatusBarItem> it = d->m_statusBarItems.begin();
00440 for ( ; it != d->m_statusBarItems.end() ; ++it )
00441 if ( show )
00442 (*it).ensureItemShown( sb );
00443 else
00444 (*it).ensureItemHidden( sb );
00445 }
00446
00447
00448 void KoView::addStatusBarItem( QWidget * widget, int stretch, bool permanent )
00449 {
00450 KoViewPrivate::StatusBarItem item( widget, stretch, permanent );
00451 d->m_statusBarItems.append(item);
00452 Q3ValueListIterator<KoViewPrivate::StatusBarItem> it = d->m_statusBarItems.fromLast();
00453 KStatusBar * sb = statusBar();
00454 Q_ASSERT(sb);
00455 if (sb)
00456 (*it).ensureItemShown( sb );
00457 }
00458
00459 void KoView::removeStatusBarItem( QWidget * widget )
00460 {
00461 KStatusBar * sb = statusBar();
00462 Q3ValueListIterator<KoViewPrivate::StatusBarItem> it = d->m_statusBarItems.begin();
00463 for ( ; it != d->m_statusBarItems.end() ; ++it )
00464 if ( (*it).widget() == widget )
00465 {
00466 if ( sb )
00467 (*it).ensureItemHidden( sb );
00468 d->m_statusBarItems.remove( it );
00469 break;
00470 }
00471 if ( it == d->m_statusBarItems.end() )
00472 kWarning() << "KoView::removeStatusBarItem. Widget not found : " << widget << endl;
00473 }
00474
00475 QDockWidget * KoView::createDock(const QString & title, QWidget * w)
00476 {
00477 QDockWidget * d = new QDockWidget(title, mainWindow());
00478 d->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
00479 d->setWidget(w);
00480 d->setObjectName(title);
00481 mainWindow()->addDockWidget(Qt::RightDockWidgetArea, d);
00482
00483 return d;
00484 }
00485
00486
00487
00488
00489 KoDocumentChild *KoView::selectedChild()
00490 {
00491 if ( !d->m_manager )
00492 return 0L;
00493
00494 KParts::Part *selectedPart = d->m_manager->selectedPart();
00495
00496 if ( !selectedPart || !selectedPart->inherits( "KoDocument" ) )
00497 return 0L;
00498
00499 return koDocument()->child( (KoDocument *)selectedPart );
00500 }
00501
00502 KoDocumentChild *KoView::activeChild()
00503 {
00504 if ( !d->m_manager )
00505 return 0L;
00506
00507 KParts::Part *activePart = d->m_manager->activePart();
00508
00509 if ( !activePart || !activePart->inherits( "KoDocument" ) )
00510 return 0L;
00511
00512 return koDocument()->child( (KoDocument *)activePart );
00513 }
00514
00515 void KoView::enableAutoScroll( )
00516 {
00517 d->m_scrollTimer->start( 50 );
00518 }
00519
00520 void KoView::disableAutoScroll( )
00521 {
00522 d->m_scrollTimer->stop();
00523 }
00524
00525 void KoView::paintEverything( QPainter &painter, const QRect &rect, bool transparent )
00526 {
00527 koDocument()->paintEverything( painter, rect, transparent, this );
00528 }
00529
00530 KoViewChild *KoView::child( KoView *view )
00531 {
00532 Q3PtrListIterator<KoViewChild> it( d->m_children );
00533 for (; it.current(); ++it )
00534 if ( it.current()->frame()->view() == view )
00535 return it.current();
00536
00537 return 0L;
00538 }
00539
00540 KoViewChild *KoView::child( KoDocument *doc )
00541 {
00542 Q3PtrListIterator<KoViewChild> it( d->m_children );
00543 for (; it.current(); ++it )
00544 if ( it.current()->documentChild()->document() == doc )
00545 return it.current();
00546
00547 return 0L;
00548 }
00549
00550 QMatrix KoView::matrix() const
00551 {
00552 QMatrix m;
00553 m.scale( zoom(), zoom() );
00554
00555 return m;
00556 }
00557
00558 void KoView::slotChildActivated( bool a )
00559 {
00560
00561 if ( a )
00562 return;
00563
00564 KoViewChild* ch = child( (KoView*)sender() );
00565 if ( !ch )
00566 return;
00567
00568 KoView* view = ch->frame()->view();
00569
00570 QWidget *activeWidget = view->d->m_tempActiveWidget;
00571
00572 if ( d->m_manager->activeWidget() )
00573 activeWidget = d->m_manager->activeWidget();
00574
00575 if ( !activeWidget || !activeWidget->inherits( "KoView" ) )
00576 return;
00577
00578
00579
00580
00581 QObject *n = activeWidget;
00582 while( n )
00583 if ( n == (QObject *)view )
00584 return;
00585 else
00586 n = n->parent();
00587
00588
00589 d->m_tempActiveWidget = activeWidget;
00590 QApplication::setOverrideCursor(Qt::WaitCursor);
00591 d->m_manager->setActivePart( 0L );
00592
00593 QPointer<KoDocumentChild> docChild = ch->documentChild();
00594 QPointer<KoFrame> chFrame = ch->frame();
00595 if ( docChild && chFrame && chFrame->view() )
00596 {
00597 docChild->setContentsPos( chFrame->view()->canvasXOffset(),
00598 chFrame->view()->canvasYOffset() );
00599 docChild->document()->setViewBuildDocument( chFrame->view(), chFrame->view()->xmlguiBuildDocument() );
00600 }
00601
00602 d->m_children.remove( ch );
00603
00604 d->m_manager->addPart( docChild->document(), false );
00605
00606 QApplication::restoreOverrideCursor();
00607
00608
00609
00610
00611 emit activated( false );
00612 }
00613
00614 void KoView::slotChildChanged( KoDocumentChild *child )
00615 {
00616 QRegion region( child->oldPointArray( matrix() ) );
00617 emit regionInvalidated( child->frameRegion( matrix(), true ).unite( region ), true );
00618 }
00619
00620 int KoView::autoScrollAcceleration( int offset ) const
00621 {
00622 if(offset < 40)
00623 return offset;
00624 else
00625 return offset*offset/40;
00626 }
00627
00628 void KoView::slotAutoScroll( )
00629 {
00630 QPoint scrollDistance;
00631 bool actuallyDoScroll = false;
00632 QPoint pos( mapFromGlobal( QCursor::pos() ) );
00633
00634
00635 if ( pos.y() < topBorder() )
00636 {
00637 scrollDistance.setY ((int) - autoScrollAcceleration( - pos.y() + topBorder() ));
00638 actuallyDoScroll = true;
00639 }
00640 else if ( pos.y() > height() - bottomBorder() )
00641 {
00642 scrollDistance.setY ((int) autoScrollAcceleration(pos.y() - height() + bottomBorder() ));
00643 actuallyDoScroll = true;
00644 }
00645
00646 if ( pos.x() < leftBorder() )
00647 {
00648 scrollDistance.setX ((int) - autoScrollAcceleration( - pos.x() + leftBorder() ));
00649 actuallyDoScroll = true;
00650 }
00651 else if ( pos.x() > width() - rightBorder() )
00652 {
00653 scrollDistance.setX ((int) autoScrollAcceleration( pos.x() - width() + rightBorder() ));
00654 actuallyDoScroll = true;
00655 }
00656
00657 if ( actuallyDoScroll )
00658 {
00659 pos = canvas()->mapFrom(this, pos);
00660 QMouseEvent* event = new QMouseEvent( QEvent::MouseMove, pos, Qt::NoButton, Qt::NoButton,
00661 QApplication::keyboardModifiers());
00662
00663 QApplication::postEvent( canvas(), event );
00664 emit autoScroll( scrollDistance );
00665 }
00666 }
00667
00668
00669 void KoView::setupGlobalActions()
00670 {
00671 actionNewView = new KAction( KIcon("window_new"), i18n( "&New View" ),
00672 actionCollection(), "view_newview" );
00673 connect( actionNewView, SIGNAL(triggered(bool)), this, SLOT(newView()) );
00674 }
00675
00676 void KoView::setupPrinter( KPrinter & )
00677 {
00678 kDebug() << "KoView::setupPrinter not implemented by the application!" << endl;
00679 }
00680
00681 void KoView::print( KPrinter & )
00682 {
00683 kDebug() << "KoView::print not implemented by the application!" << endl;
00684 }
00685
00686 void KoView::newView() {
00687 assert( ( d!=0L && d->m_doc ) );
00688
00689 KoDocument *thisDocument = d->m_doc;
00690 KoMainWindow *shell = new KoMainWindow( thisDocument->instance() );
00691 shell->setRootDocument(thisDocument);
00692 shell->show();
00693 }
00694
00695 bool KoView::isInOperation() const
00696 {
00697 return d->m_inOperation;
00698 }
00699
00700 void KoView::beginOperation()
00701 {
00702 d->m_inOperation = true;
00703 canvas()->setUpdatesEnabled( false );
00704 }
00705
00706 void KoView::endOperation()
00707 {
00708 canvas()->setUpdatesEnabled( true );
00709 d->m_inOperation = false;
00710
00711
00712 }
00713
00714 KoMainWindow * KoView::shell() const
00715 {
00716 return dynamic_cast<KoMainWindow *>( topLevelWidget() );
00717 }
00718
00719 KMainWindow * KoView::mainWindow() const
00720 {
00721 return dynamic_cast<KMainWindow *>( topLevelWidget() );
00722 }
00723
00724 KStatusBar * KoView::statusBar() const
00725 {
00726 KoMainWindow *mw = shell();
00727 return mw ? mw->statusBar() : 0L;
00728 }
00729
00730 void KoView::slotActionStatusText( const QString &text )
00731 {
00732 KStatusBar *sb = statusBar();
00733 if ( sb )
00734 sb->showMessage( text );
00735 }
00736
00737 void KoView::slotClearStatusText()
00738 {
00739 KStatusBar *sb = statusBar();
00740 if ( sb )
00741 sb->clearMessage();
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751 QDockWidget *KoView::createDockWidget(KoDockFactory* factory)
00752 {
00753 if( !shell() )
00754 return 0;
00755
00756 return shell()->createDockWidget(factory);
00757 }
00758
00759 QPoint KoView::applyViewTransformations( const QPoint& p ) const
00760 {
00761 return QPoint( qRound( p.x() * zoom() ), qRound( p.y() * zoom() ) );
00762 }
00763
00764 QPoint KoView::reverseViewTransformations( const QPoint& v ) const
00765 {
00766 return QPoint( qRound( v.x() / zoom() ), qRound( v.y() / zoom() ) );
00767 }
00768
00769 QRect KoView::applyViewTransformations( const QRect& r ) const
00770 {
00771 return QRect( applyViewTransformations( r.topLeft() ),
00772 applyViewTransformations( r.bottomRight() ) );
00773 }
00774
00775 QRect KoView::reverseViewTransformations( const QRect& r ) const
00776 {
00777 return QRect( reverseViewTransformations( r.topLeft() ),
00778 reverseViewTransformations( r.bottomRight() ) );
00779 }
00780
00781 #include "KoView.moc"
00782