/* This file is part of the KDE project
   Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#include <KoView.h>
#include <KoDocument.h>
#include <KoMainWindow.h>
#include <KoFrame.h>
#include <KoViewIface.h>
#include <KoDocumentChild.h>

#include <tdelocale.h>
#include <tdeglobal.h>
#include <kdebug.h>
#include <tdeparts/partmanager.h>
#include <tdeparts/event.h>
#include <kcursor.h>
#include <assert.h>
#include <kstatusbar.h>
#include <tdeapplication.h>
#include <tqtimer.h>

class KoViewPrivate
{
public:
  KoViewPrivate()
  {
    m_inOperation = false;
    m_zoom = 1.0;
    m_children.setAutoDelete( true );
    m_manager = 0L;
    m_tempActiveWidget = 0L;
    m_dcopObject = 0;
    m_registered=false;
    m_documentDeleted=false;
  }
  ~KoViewPrivate()
  {
  }

  TQGuardedPtr<KoDocument> m_doc; // our KoDocument
  TQGuardedPtr<KParts::PartManager> m_manager;
  double m_zoom;
  TQPtrList<KoViewChild> m_children;
  TQWidget *m_tempActiveWidget;
  KoViewIface *m_dcopObject;
  bool m_registered;  // are we registered at the part manager?
  bool m_documentDeleted; // true when m_doc gets deleted [can't use m_doc==0
                          // since this only happens in ~TQObject, and views
                          // get deleted by ~KoDocument].
  TQTimer *m_scrollTimer;

  // Hmm sorry for polluting the private class with such a big inner class.
  // At the beginning it was a little struct :)
  class StatusBarItem {
  public:
      StatusBarItem() // for TQValueList
          : m_widget(0), m_visible(false)
      {}
      StatusBarItem( TQWidget * widget, int stretch, bool permanent )
          : m_widget(widget), m_stretch(stretch), m_permanent(permanent), m_visible(false)
      {}

      TQWidget * widget() const { return m_widget; }

      void ensureItemShown( KStatusBar * sb )
      {
            if ( !m_visible )
            {
                sb->addWidget( m_widget, m_stretch, m_permanent );
                m_visible = true;
                m_widget->show();
            }
      }
      void ensureItemHidden( KStatusBar * sb )
      {
            if ( m_visible )
            {
                sb->removeWidget( m_widget );
                m_visible = false;
                m_widget->hide();
            }
      }
  private:
      TQWidget * m_widget;
      int m_stretch;
      bool m_permanent;
      bool m_visible;  // true when the item has been added to the statusbar
  };
  TQValueList<StatusBarItem> m_statusBarItems; // Our statusbar items
  bool m_inOperation; //in the middle of an operation (no screen refreshing)?
};

KoView::KoView( KoDocument *document, TQWidget *parent, const char *name )
 : TQWidget( parent, name )
{
  Q_ASSERT( document );

  //kdDebug(30003) << "KoView::KoView " << this << endl;
  d = new KoViewPrivate;
  d->m_doc = document;
  KParts::PartBase::setPartObject( TQT_TQOBJECT(this) );

  setFocusPolicy( TQ_StrongFocus );

  setMouseTracking( true );

  connect( d->m_doc, TQT_SIGNAL( childChanged( KoDocumentChild * ) ),
           this, TQT_SLOT( slotChildChanged( KoDocumentChild * ) ) );

  connect( d->m_doc, TQT_SIGNAL( sigBeginOperation() ),
           this, TQT_SLOT( beginOperation() ) );

  connect( d->m_doc, TQT_SIGNAL( sigEndOperation() ),
           this, TQT_SLOT( endOperation() ) );


  actionCollection()->setWidget( this );
  setupGlobalActions();
  TDEActionCollection *coll = actionCollection();
  /**** not needed anymore, according to David (Werner)
  TQValueList<TDEAction*> docActions = document->actionCollection()->actions();
  TQValueList<TDEAction*>::ConstIterator it = docActions.begin();
  TQValueList<TDEAction*>::ConstIterator end = docActions.end();
  for (; it != end; ++it )
      coll->insert( *it );
  */

  KStatusBar * sb = statusBar();
  if ( sb ) // No statusbar in e.g. konqueror
  {
      coll->setHighlightingEnabled( true );
      connect( coll, TQT_SIGNAL( actionStatusText( const TQString & ) ),
               this, TQT_SLOT( slotActionStatusText( const TQString & ) ) );
      connect( coll, TQT_SIGNAL( clearStatusText() ),
               this, TQT_SLOT( slotClearStatusText() ) );

      connect( d->m_doc, TQT_SIGNAL( sigStatusBarMessage( const TQString& ) ),
               this, TQT_SLOT( slotActionStatusText( const TQString& ) ) );
      connect( d->m_doc, TQT_SIGNAL( sigClearStatusBarMessage() ),
               this, TQT_SLOT( slotClearStatusText() ) );
  }
  d->m_doc->setCurrent();

  d->m_scrollTimer = new TQTimer( this );
  connect (d->m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotAutoScroll() ) );
}

KoView::~KoView()
{
  kdDebug(30003) << "KoView::~KoView " << this << endl;
  delete d->m_scrollTimer;
  delete d->m_dcopObject;
  if (!d->m_documentDeleted)
  {
    if ( koDocument() && !koDocument()->isSingleViewMode() )
    {
      if ( d->m_manager && d->m_registered ) // if we aren't registered we mustn't unregister :)
        d->m_manager->removePart( koDocument() );
      d->m_doc->removeView(this);
      d->m_doc->setCurrent( false );
    }
  }
  delete d;
}

KoDocument *KoView::koDocument() const
{
  return d->m_doc;
}

void KoView::setDocumentDeleted()
{
    d->m_documentDeleted = true;
}

bool KoView::documentDeleted() const
{
    return d->m_documentDeleted;
}

bool KoView::hasDocumentInWindow( KoDocument *doc )
{
  return child( doc ) != 0L;
}

void KoView::setPartManager( KParts::PartManager *manager )
{
  d->m_manager = manager;
  if ( !koDocument()->isSingleViewMode() &&
       manager->parts()->containsRef( koDocument() ) == 0 ) // is there another view registered?
  {
    d->m_registered = true; // no, so we have to register now and ungregister again in the DTOR
    manager->addPart( koDocument(), false );
  }
  else
    d->m_registered = false;  // There is already another view registered for that part...
}

KParts::PartManager *KoView::partManager() const
{
  return d->m_manager;
}

TDEAction *KoView::action( const TQDomElement &element ) const
{
  static const TQString &attrName = TDEGlobal::staticQString( "name" );
  TQString name = element.attribute( attrName );

  TDEAction *act = KXMLGUIClient::action( name.utf8() );

  if ( !act )
    act = d->m_doc->KXMLGUIClient::action( name.utf8() );

  return act;
}

KoDocument *KoView::hitTest( const TQPoint &viewPos )
{
  KoViewChild *viewChild;

  TQPoint pos = reverseViewTransformations( viewPos );

  KoDocumentChild *docChild = selectedChild();
  if ( docChild )
  {
    if ( ( viewChild = child( docChild->document() ) ) )
    {
      if ( viewChild->frameRegion().contains( pos ) )
        return 0;
    }
    else
      if ( docChild->frameRegion().contains( pos ) )
        return 0;
  }

  docChild = activeChild();
  if ( docChild )
  {
    if ( ( viewChild = child( docChild->document() ) ) )
    {
      if ( viewChild->frameRegion().contains( pos ) )
        return 0;
    }
    else
      if ( docChild->frameRegion().contains( pos ) )
        return 0;
  }

  return koDocument()->hitTest( pos );
}

int KoView::leftBorder() const
{
  return 0;
}

int KoView::rightBorder() const
{
  return 0;
}

int KoView::topBorder() const
{
  return 0;
}

int KoView::bottomBorder() const
{
  return 0;
}

void KoView::setZoom( double zoom )
{
  d->m_zoom = zoom;
  update();
}

double KoView::zoom() const
{
  return d->m_zoom;
}

TQWidget *KoView::canvas() const
{
    //dfaure: since the view plays two roles in this method (the const means "you can modify the canvas
    // but not the view", it's just coincidence that the view is the canvas by default ;)
   return const_cast<KoView *>(this);
}

int KoView::canvasXOffset() const
{
  return 0;
}

int KoView::canvasYOffset() const
{
  return 0;
}

void KoView::canvasAddChild( KoViewChild * )
{
}

void KoView::customEvent( TQCustomEvent *ev )
{
  if ( KParts::PartActivateEvent::test( ev ) )
    partActivateEvent( (KParts::PartActivateEvent *)ev );
  else if ( KParts::PartSelectEvent::test( ev ) )
    partSelectEvent( (KParts::PartSelectEvent *)ev );
  else if( KParts::GUIActivateEvent::test( ev ) )
    guiActivateEvent( (KParts::GUIActivateEvent*)ev );
}

void KoView::partActivateEvent( KParts::PartActivateEvent *event )
{
  if ( event->part() != (KParts::Part *)koDocument() )
  {
    assert( event->part()->inherits( "KoDocument" ) );

    KoDocumentChild *child = koDocument()->child( (KoDocument *)event->part() );
    if ( child && event->activated() )
    {
      if ( child->isRectangle() && !child->isTransparent() )
      {
        KoViewChild *viewChild = new KoViewChild( child, this );
        d->m_children.append( viewChild );

        TQApplication::setOverrideCursor(waitCursor);
        // This is the long operation (due to toolbar layout stuff)
        d->m_manager->setActivePart( child->document(), viewChild->frame()->view() );
        TQApplication::restoreOverrideCursor();

        // Now we can move the frame to the right place
        viewChild->setInitialFrameGeometry();
      }
      else
      {
        emit regionInvalidated( child->frameRegion( matrix() ), true );
      }
      emit childActivated( child );
    }
    else if ( child )
    {
      emit regionInvalidated( child->frameRegion( matrix() ), true );
      emit childDeactivated( child );
    }
    else
      emit invalidated();
  }
  else
    emit activated( event->activated() );
}

void KoView::partSelectEvent( KParts::PartSelectEvent *event )
{
  if ( event->part() != (KParts::Part *)koDocument() )
  {
    assert( event->part()->inherits( "KoDocument" ) );

    KoDocumentChild *child = koDocument()->child( (KoDocument *)event->part() );

    if ( child && event->selected() )
    {
      TQRegion r = child->frameRegion( matrix() );
      r.translate( - canvasXOffset(), - canvasYOffset() );
      emit regionInvalidated( r, true );
      emit childSelected( child );
    }
    else if ( child )
    {
      TQRegion r = child->frameRegion( matrix() );
      r.translate( - canvasXOffset(), - canvasYOffset() );
      emit regionInvalidated( r, true );
      emit childUnselected( child );
    }
    else
      emit invalidated();
  }
  else
    emit selected( event->selected() );
}

void KoView::guiActivateEvent( KParts::GUIActivateEvent * ev )
{
    showAllStatusBarItems( ev->activated() );
}

void KoView::showAllStatusBarItems( bool show )
{
    KStatusBar * sb = statusBar();
    if ( !sb )
        return;
    TQValueListIterator<KoViewPrivate::StatusBarItem> it = d->m_statusBarItems.begin();
    for ( ; it != d->m_statusBarItems.end() ; ++it )
        if ( show )
            (*it).ensureItemShown( sb );
        else
            (*it).ensureItemHidden( sb );
}

void KoView::addStatusBarItem( TQWidget * widget, int stretch, bool permanent )
{
    KoViewPrivate::StatusBarItem item( widget, stretch, permanent );
    d->m_statusBarItems.append(item);
    TQValueListIterator<KoViewPrivate::StatusBarItem> it = d->m_statusBarItems.fromLast();
    KStatusBar * sb = statusBar();
    Q_ASSERT(sb);
    if (sb)
        (*it).ensureItemShown( sb );
}

void KoView::removeStatusBarItem( TQWidget * widget )
{
    KStatusBar * sb = statusBar();
    TQValueListIterator<KoViewPrivate::StatusBarItem> it = d->m_statusBarItems.begin();
    for ( ; it != d->m_statusBarItems.end() ; ++it )
        if ( (*it).widget() == widget )
        {
            if ( sb )
                (*it).ensureItemHidden( sb );
            d->m_statusBarItems.remove( it );
            break;
        }
    if ( it == d->m_statusBarItems.end() )
        kdWarning() << "KoView::removeStatusBarItem. Widget not found : " << widget << endl;
}

KoDocumentChild *KoView::selectedChild()
{
  if ( !d->m_manager )
    return 0L;

  KParts::Part *selectedPart = d->m_manager->selectedPart();

  if ( !selectedPart || !selectedPart->inherits( "KoDocument" ) )
    return 0L;

  return koDocument()->child( (KoDocument *)selectedPart );
}

KoDocumentChild *KoView::activeChild()
{
  if ( !d->m_manager )
    return 0L;

  KParts::Part *activePart = d->m_manager->activePart();

  if ( !activePart || !activePart->inherits( "KoDocument" ) )
    return 0L;

  return koDocument()->child( (KoDocument *)activePart );
}

void KoView::enableAutoScroll( )
{
    d->m_scrollTimer->start( 50 );
}

void KoView::disableAutoScroll( )
{
    d->m_scrollTimer->stop();
}

void KoView::paintEverything( TQPainter &painter, const TQRect &rect, bool transparent )
{
  koDocument()->paintEverything( painter, rect, transparent, this );
}

KoViewChild *KoView::child( KoView *view )
{
  TQPtrListIterator<KoViewChild> it( d->m_children );
  for (; it.current(); ++it )
    if ( it.current()->frame()->view() == view )
      return it.current();

  return 0L;
}

KoViewChild *KoView::child( KoDocument *doc )
{
  TQPtrListIterator<KoViewChild> it( d->m_children );
  for (; it.current(); ++it )
    if ( it.current()->documentChild()->document() == doc )
      return it.current();

  return 0L;
}

TQWMatrix KoView::matrix() const
{
  TQWMatrix m;
  m.scale( zoom(), zoom() );
  //m.translate(  canvasXOffset() ,  canvasYOffset() );
  return m;
}

void KoView::slotChildActivated( bool a )
{
  // Only interested in deactivate events
  if ( a )
    return;

  KoViewChild* ch = child( (KoView*)sender() );
  if ( !ch )
    return;

  KoView* view = ch->frame()->view();

  TQWidget *activeWidget = view->d->m_tempActiveWidget;

  if ( d->m_manager->activeWidget() )
    activeWidget = d->m_manager->activeWidget();

  if ( !activeWidget || !activeWidget->inherits( "KoView" ) )
    return;

  // Is the new active view a child of this one ?
  // In this case we may not delete!
  //  TQObject *n = d->m_manager->activeWidget();
  TQObject *n = TQT_TQOBJECT(activeWidget);
  while( n )
    if ( n == (TQObject *)view )
      return;
    else
     n = n->parent();


  d->m_tempActiveWidget = activeWidget;
  TQApplication::setOverrideCursor(waitCursor);
  d->m_manager->setActivePart( 0L );

  TQGuardedPtr<KoDocumentChild> docChild = ch->documentChild();
  TQGuardedPtr<KoFrame> chFrame = ch->frame();
  if ( docChild && chFrame && chFrame->view() )
  {
    docChild->setContentsPos( chFrame->view()->canvasXOffset(),
                              chFrame->view()->canvasYOffset() );
    docChild->document()->setViewBuildDocument( chFrame->view(), chFrame->view()->xmlguiBuildDocument() );
  }

  d->m_children.remove( ch );

  d->m_manager->addPart( docChild->document(), false ); // the destruction of the view removed the part from the partmanager. re-add it :)

  TQApplication::restoreOverrideCursor();

  // #### HACK
  // We want to delete as many views as possible and this
  // trick is used to go upwards in the view-tree.
  emit activated( FALSE );
}

void KoView::slotChildChanged( KoDocumentChild *child )
{
  TQRegion region( child->oldPointArray( matrix() ) );
  emit regionInvalidated( child->frameRegion( matrix(), true ).unite( region ), true );
}

int KoView::autoScrollAcceleration( int offset ) const
{
    if(offset < 40)
        return offset;
    else
        return offset*offset/40;
}

void KoView::slotAutoScroll(  )
{
    TQPoint scrollDistance;
    bool actuallyDoScroll = false;
    TQPoint pos( mapFromGlobal( TQCursor::pos() ) );

    //Provide progressive scrolling depending on the mouse position
    if ( pos.y() < topBorder() )
    {
        scrollDistance.setY ((int) - autoScrollAcceleration( - pos.y() + topBorder() ));
        actuallyDoScroll = true;
    }
    else if ( pos.y() > height() - bottomBorder() )
    {
        scrollDistance.setY ((int) autoScrollAcceleration(pos.y() - height() + bottomBorder() ));
        actuallyDoScroll = true;
    }

    if ( pos.x() < leftBorder() )
    {
        scrollDistance.setX ((int) - autoScrollAcceleration( - pos.x() + leftBorder() ));
        actuallyDoScroll = true;
    }
    else if ( pos.x() > width() - rightBorder() )
    {
        scrollDistance.setX ((int) autoScrollAcceleration( pos.x() - width() + rightBorder() ));
        actuallyDoScroll = true;
    }

    if ( actuallyDoScroll )
    {
        int state=0;
#if KDE_IS_VERSION(3,4,0)
        state = kapp->keyboardMouseState();
#endif

        pos = canvas()->mapFrom(this, pos);
        TQMouseEvent * event = new TQMouseEvent(TQEvent::MouseMove, pos, 0, state);

        TQApplication::postEvent( canvas(), event );
        emit autoScroll( scrollDistance );
    }
}


void KoView::setupGlobalActions() {
    actionNewView = new TDEAction( i18n( "&New View" ), "window_new", 0,
        TQT_TQOBJECT(this), TQT_SLOT( newView() ),
        actionCollection(), "view_newview" );
}

void KoView::setupPrinter( KPrinter & )
{
    kdDebug() << "KoView::setupPrinter not implemented by the application!" << endl;
}

void KoView::print( KPrinter & )
{
    kdDebug() << "KoView::print not implemented by the application!" << endl;
}

void KoView::newView() {
    assert( ( d!=0L && d->m_doc ) );

    KoDocument *thisDocument = d->m_doc;
    KoMainWindow *shell = new KoMainWindow( thisDocument->instance() );
    shell->setRootDocument(thisDocument);
    shell->show();
}

bool KoView::isInOperation() const
{
   return d->m_inOperation;
}

void KoView::beginOperation()
{
   d->m_inOperation = true;
   canvas()->setUpdatesEnabled(FALSE);
}

void KoView::endOperation()
{
   canvas()->setUpdatesEnabled(TRUE);
   d->m_inOperation = false;

//   canvas()->update();
}

KoMainWindow * KoView::shell() const
{
    return dynamic_cast<KoMainWindow *>( topLevelWidget() );
}

TDEMainWindow * KoView::mainWindow() const
{
    return dynamic_cast<TDEMainWindow *>( topLevelWidget() );
}

KStatusBar * KoView::statusBar() const
{
    KoMainWindow *mw = shell();
    return mw ? mw->statusBar() : 0L;
}

void KoView::slotActionStatusText( const TQString &text )
{
  KStatusBar *sb = statusBar();
  if ( sb )
      sb->message( text );
}

void KoView::slotClearStatusText()
{
  KStatusBar *sb = statusBar();
  if ( sb )
      sb->clear();
}

DCOPObject *KoView::dcopObject()
{
    if ( !d->m_dcopObject )
        d->m_dcopObject = new KoViewIface( this );
    return d->m_dcopObject;
}

class KoViewChild::KoViewChildPrivate
{
public:
  KoViewChildPrivate()
  {
  }
  ~KoViewChildPrivate()
  {
  }
};

KoViewChild::KoViewChild( KoDocumentChild *child, KoView *_parentView )
{
  d = new KoViewChildPrivate;
  m_parentView = _parentView;
  m_child = child;

  m_frame = new KoFrame( parentView()->canvas() );
  KoView *view = child->document()->createView( m_frame );
  view->setXMLGUIBuildDocument( child->document()->viewBuildDocument( view ) );

  view->setPartManager( parentView()->partManager() );

  // hack? (Werner)
  view->setZoom( parentView()->zoom() * TQMAX(child->xScaling(), child->yScaling()) );

  m_frame->setView( view );
  m_frame->show();
  m_frame->raise();

  parentView()->canvasAddChild( this );


  /*
   KoViewChild has basically three geometries to keep in sync.
   - The KoDocumentChild geometry (i.e. the embedded object's geometry, unzoomed)
   - Its own geometry (used for hit-test etc.)
   - The KoFrame geometry (the graphical widget for moving the object when active)

   So we need to subtract the scrollview's offset for the frame geometry, since it's a widget.

   The rules are
   (R1) frameGeometry = viewGeometry(childGeometry) "+" m_frame->{left|right|top|bottom}Border() - scrollview offset,
   (R2) frameGeometry = myGeometry "+" active_frame_border - scrollview offset.

   So: (R3, unused) myGeometry = viewGeometry(childGeometry) "+" m_frame->{left|right|top|bottom}Border() "-" active_frame_border

   Notes: active_frame_border is m_frame->border() (0 when inactive, 5 when active).
          {left|right|top|bottom}Border are the borders used in kspread (0 when inactive, big when active).
          "+" border means we add a border, so it's a subtraction on x, y and an addition on width, height.

          viewGeometry() applies the zoom as well as any other translation the app might want to do
   */

  // Setting the frameGeometry is done in setInitialFrameGeometry, which is
  // also called right after activation.

  connect( view, TQT_SIGNAL( activated( bool ) ),
           parentView(), TQT_SLOT( slotChildActivated( bool ) ) );
}

KoViewChild::~KoViewChild()
{
  if ( m_frame )
  {
    slotFrameGeometryChanged();
    delete static_cast<KoFrame *>( m_frame );
  }
  delete d;
}

void KoViewChild::slotFrameGeometryChanged()
{
  // Set our geometry from the frame geometry (R2 reversed)
  TQRect geom = m_frame->geometry();
  int b = m_frame->border();
  TQRect borderRect( geom.x() + b + parentView()->canvasXOffset(),
                    geom.y() + b + parentView()->canvasYOffset(),
                    geom.width() - b * 2,
                    geom.height() - b * 2 );
  setGeometry( borderRect );

  if(m_child)
  {
    // Set the child geometry from the frame geometry (R1 reversed)
    TQRect borderLessRect( geom.x() + m_frame->leftBorder() + parentView()->canvasXOffset(),
                          geom.y() + m_frame->topBorder() + parentView()->canvasYOffset(),
                          geom.width() - m_frame->leftBorder() - m_frame->rightBorder(),
                          geom.height() - m_frame->topBorder() - m_frame->bottomBorder() );

    // We don't want to trigger slotDocGeometryChanged again
    lock();
    TQRect childGeom = parentView()->reverseViewTransformations( borderLessRect );
    kdDebug() << "KoChild::slotFrameGeometryChanged child geometry "
              << ( geometry() == childGeom ? "already " : "set to " )
              << childGeom << endl;
    m_child->setGeometry( childGeom );
    unlock();
  }
}

void KoViewChild::slotDocGeometryChanged()
{
  if ( locked() )
      return;
  // Set frame geometry from child geometry (R1)
  // The frame's resizeEvent will call slotFrameGeometryChanged.
  TQRect geom = parentView()->applyViewTransformations( m_child->geometry() );
  TQRect borderRect( geom.x() - m_frame->leftBorder() - parentView()->canvasXOffset(),
                    geom.y() - m_frame->topBorder() - parentView()->canvasYOffset(),
                    geom.width() + m_frame->leftBorder() + m_frame->rightBorder(),
                    geom.height() + m_frame->topBorder() + m_frame->bottomBorder() );
  kdDebug() << "KoViewChild::slotDocGeometryChanged frame geometry "
            << ( m_frame->geometry() == borderRect ? "already " : "set to " )
            << borderRect << endl;

  m_frame->setGeometry( borderRect );
}

TQPoint KoView::applyViewTransformations( const TQPoint& p ) const
{
  return TQPoint( tqRound( p.x() * zoom() ), tqRound( p.y() * zoom() ) );
}

TQPoint KoView::reverseViewTransformations( const TQPoint& v ) const
{
  return TQPoint( tqRound( v.x() / zoom() ), tqRound( v.y() / zoom() ) );
}

TQRect KoView::applyViewTransformations( const TQRect& r ) const
{
  return TQRect( applyViewTransformations( r.topLeft() ),
                applyViewTransformations( r.bottomRight() ) );
}

TQRect KoView::reverseViewTransformations( const TQRect& r ) const
{
  return TQRect( reverseViewTransformations( r.topLeft() ),
                reverseViewTransformations( r.bottomRight() ) );
}

void KoViewChild::setInitialFrameGeometry()
{
    kdDebug() << k_funcinfo << endl;

    // Connect only now, so that the GUI building doesn't move us around.
    connect( m_frame, TQT_SIGNAL( geometryChanged() ),
             this, TQT_SLOT( slotFrameGeometryChanged() ) );
    connect( m_child, TQT_SIGNAL( changed( KoChild * ) ),
             this, TQT_SLOT( slotDocGeometryChanged() ) );

    // Set frameGeometry from childGeometry
    slotDocGeometryChanged();
    // Set myGeometry from frameGeometry
    slotFrameGeometryChanged();

}

#include "KoView.moc"

