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