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