| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# khtmlview.cpp

    00001 /* This file is part of the KDE project
    00002  *
    00003  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
    00004  *                     1999 Lars Knoll <knoll@kde.org>
    00005  *                     1999 Antti Koivisto <koivisto@kde.org>
    00006  *                     2000 Dirk Mueller <mueller@kde.org>
    00007  *
    00008  * This library is free software; you can redistribute it and/or
    00009  * modify it under the terms of the GNU Library General Public
    00010  * License as published by the Free Software Foundation; either
    00011  * version 2 of the License, or (at your option) any later version.
    00012  *
    00013  * This library is distributed in the hope that it will be useful,
    00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00016  * Library General Public License for more details.
    00017  *
    00018  * You should have received a copy of the GNU Library General Public License
    00019  * along with this library; see the file COPYING.LIB.  If not, write to
    00020  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00021  * Boston, MA 02111-1307, USA.
    00022  */
    00023 #include "khtmlview.moc"
    00024
    00025 #include "khtmlview.h"
    00026
    00027 #include "khtml_part.h"
    00028 #include "khtml_events.h"
    00029
    00030 #include "html/html_documentimpl.h"
    00031 #include "html/html_inlineimpl.h"
    00032 #include "rendering/render_root.h"
    00033 #include "rendering/render_frames.h"
    00034 #include "rendering/render_replaced.h"
    00035 #include "xml/dom2_eventsimpl.h"
    00036 #include "css/cssstyleselector.h"
    00037 #include "misc/htmlhashes.h"
    00038 #include "misc/helper.h"
    00039 #include "khtml_settings.h"
    00040 #include "khtml_printsettings.h"
    00041
    00042 #include <kcursor.h>
    00043 #include <ksimpleconfig.h>
    00044 #include <kstringhandler.h>
    00045 #include <kstandarddirs.h>
    00046 #include <kprinter.h>
    00047 #include <klocale.h>
    00048
    00049 #include <qtooltip.h>
    00050 #include <qpainter.h>
    00051 #include <qpaintdevicemetrics.h>
    00052 #include <qstylesheet.h>
    00053 #include <qobjectlist.h>
    00054 #include <kapplication.h>
    00055
    00056 #include <kimageio.h>
    00057 #include <assert.h>
    00058 #include <kdebug.h>
    00059 #include <kurldrag.h>
    00060 #include <qobjectlist.h>
    00061 #include <qtimer.h>
    00062 #include <kdialogbase.h>
    00063
    00064 #define PAINT_BUFFER_HEIGHT 128
    00065
    00066 using namespace DOM;
    00067 using namespace khtml;
    00068 class KHTMLToolTip;
    00069
    00070 #ifndef QT_NO_TOOLTIP
    00071
    00072 class KHTMLToolTip : public QToolTip
    00073 {
    00074 public:
    00075     KHTMLToolTip(KHTMLView *view,  KHTMLViewPrivate* vp) : QToolTip(view->viewport())
    00076     {
    00077         m_view = view;
    00078         m_viewprivate = vp;
    00079     };
    00080
    00081 protected:
    00082     virtual void maybeTip(const QPoint &);
    00083
    00084 private:
    00085     KHTMLView *m_view;
    00086     KHTMLViewPrivate* m_viewprivate;
    00087 };
    00088
    00089 #endif
    00090
    00091 class KHTMLViewPrivate {
    00092     friend class KHTMLToolTip;
    00093 public:
    00094     KHTMLViewPrivate()
    00095     {
    00096         underMouse = 0;
    00097         reset();
    00098         tp=0;
    00099         paintBuffer=0;
    00100         vertPaintBuffer=0;
    00101         formCompletions=0;
    00102         prevScrollbarVisible = true;
    00103         timerId = 0;
    00104         repaintTimerId = 0;
    00105         scrollTimerId = 0;
    00106         complete = false;
    00107         tooltip = 0;
    00108         possibleTripleClick = false;
    00109     }
    00110     ~KHTMLViewPrivate()
    00111     {
    00112         delete formCompletions;
    00113         delete tp; tp = 0;
    00114         delete paintBuffer; paintBuffer =0;
    00115         delete vertPaintBuffer;
    00116         if (underMouse)
    00117             underMouse->deref();
    00118         delete tooltip;
    00119     }
    00120     void reset()
    00121     {
    00122         if (underMouse)
    00123             underMouse->deref();
    00124         underMouse = 0;
    00125         linkPressed = false;
    00126         useSlowRepaints = false;
    00127         originalNode = 0;
    00128         borderTouched = false;
    00129 #ifndef KHTML_NO_SCROLLBARS
    00130         vmode = QScrollView::Auto;
    00131         hmode = QScrollView::Auto;
    00132 #else
    00133         vmode = QScrollView::AlwaysOff;
    00134         hmode = QScrollView::AlwaysOff;
    00135 #endif
    00136         scrollBarMoved = false;
    00137         ignoreWheelEvents = false;
    00138         borderX = 30;
    00139         borderY = 30;
    00140         clickX = -1;
    00141         clickY = -1;
    00142         prevMouseX = -1;
    00143         prevMouseY = -1;
    00144         clickCount = 0;
    00145         isDoubleClick = false;
    00146         scrollingSelf = false;
    00147         timerId = 0;
    00148         repaintTimerId = 0;
    00149         scrollTimerId = 0;
    00150         complete = false;
    00151         firstRelayout = true;
    00152         dirtyLayout = false;
    00153         layoutSchedulingEnabled = true;
    00154         updateRect = QRect();
    00155         m_dialogsAllowed = true;
    00156     }
    00157     void newScrollTimer(QWidget *view, int tid)
    00158     {
    00159         kdDebug() << "newScrollTimer timer" << tid << endl;
    00160         view->killTimer(scrollTimerId);
    00161         scrollTimerId = tid;
    00162     }
    00163     enum ScrollDirection { ScrollLeft, ScrollRight, ScrollUp, ScrollDown };
    00164
    00165     void adjustScroller(QWidget *view, ScrollDirection direction, ScrollDirection oppositedir)
    00166     {
    00167         static const struct { int msec, pixels; } timings [] = {
    00168             {100,1}, {50,1}, {30,1}, {20,1}, {20,2}, {20,4}, {20,6}, {0,0}
    00169         };
    00170         if (!scrollTimerId ||
    00171             (scrollDirection != direction &&
    00172              scrollDirection != oppositedir)) {
    00173             scrollTiming = 2;
    00174             scrollBy = timings[scrollTiming].pixels;
    00175             scrollDirection = direction;
    00176             newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
    00177         } else if (scrollDirection == direction &&
    00178                    timings[scrollTiming+1].msec) {
    00179             scrollBy = timings[++scrollTiming].pixels;
    00180             newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
    00181         } else if (scrollDirection == oppositedir) {
    00182             if (scrollTiming) {
    00183                 scrollBy = timings[--scrollTiming].pixels;
    00184                 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
    00185             } else
    00186                 newScrollTimer(view, 0);
    00187         }
    00188     }
    00189
    00190     QPainter *tp;
    00191     QPixmap  *paintBuffer;
    00192     QPixmap  *vertPaintBuffer;
    00193     NodeImpl *underMouse;
    00194
    00195     // the node that was selected when enter was pressed
    00196     NodeImpl *originalNode;
    00197
    00198     bool borderTouched:1;
    00199     bool borderStart:1;
    00200     bool scrollBarMoved:1;
    00201
    00202     QScrollView::ScrollBarMode vmode;
    00203     QScrollView::ScrollBarMode hmode;
    00204     bool prevScrollbarVisible;
    00205     bool linkPressed;
    00206     bool useSlowRepaints;
    00207     bool ignoreWheelEvents;
    00208
    00209     int borderX, borderY;
    00210     KSimpleConfig *formCompletions;
    00211
    00212     int clickX, clickY, clickCount;
    00213     bool isDoubleClick;
    00214
    00215     int prevMouseX, prevMouseY;
    00216     bool scrollingSelf;
    00217     int timerId;
    00218
    00219     int repaintTimerId;
    00220     int scrollTimerId;
    00221     int scrollTiming;
    00222     int scrollBy;
    00223     ScrollDirection scrollDirection;
    00224     bool complete;
    00225     bool firstRelayout;
    00226     bool layoutSchedulingEnabled;
    00227     bool possibleTripleClick;
    00228     bool dirtyLayout;
    00229     bool m_dialogsAllowed;
    00230     QRect updateRect;
    00231     KHTMLToolTip *tooltip;
    00232     QPtrDict<QWidget> visibleWidgets;
    00233 };
    00234
    00235 #ifndef QT_NO_TOOLTIP
    00236
    00237 void KHTMLToolTip::maybeTip(const QPoint& p)
    00238 {
    00239     DOM::NodeImpl *node = m_viewprivate->underMouse;
    00240     QRect region;
    00241     while ( node ) {
    00242         if ( node->isElementNode() ) {
    00243             QString s = static_cast<DOM::ElementImpl*>( node )->getAttribute( ATTR_TITLE ).string();
    00244             region |= QRect( m_view->contentsToViewport( node->getRect().topLeft() ), node->getRect().size() );
    00245             if ( !s.isEmpty() ) {
    00246                 tip( region, QStyleSheet::convertFromPlainText( s, QStyleSheetItem::WhiteSpaceNormal ) );
    00247                 break;
    00248             }
    00249         }
    00250         node = node->parentNode();
    00251     }
    00252 }
    00253 #endif
    00254
    00255 KHTMLView::KHTMLView( KHTMLPart *part, QWidget *parent, const char *name)
    00256     : QScrollView( parent, name, WResizeNoErase | WRepaintNoErase | WPaintUnclipped )
    00257 {
    00258     m_medium = "screen";
    00259
    00260     m_part = part;
    00261     d = new KHTMLViewPrivate;
    00262     QScrollView::setVScrollBarMode(d->vmode);
    00263     QScrollView::setHScrollBarMode(d->hmode);
    00264     connect(kapp, SIGNAL(kdisplayPaletteChanged()), this, SLOT(slotPaletteChanged()));
    00265     connect(this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotScrollBarMoved()));
    00266
    00267     // initialize QScrollview
    00268     enableClipper(true);
    00269     setResizePolicy(Manual);
    00270     viewport()->setMouseTracking(true);
    00271     viewport()->setBackgroundMode(NoBackground);
    00272
    00273     KImageIO::registerFormats();
    00274
    00275 #ifndef QT_NO_TOOLTIP
    00276     d->tooltip = new KHTMLToolTip( this, d );
    00277 #endif
    00278
    00279     init();
    00280
    00281     viewport()->show();
    00282 }
    00283
    00284 KHTMLView::~KHTMLView()
    00285 {
    00286     closeChildDialogs();
    00287     if (m_part)
    00288     {
    00289         //WABA: Is this Ok? Do I need to deref it as well?
    00290         //Does this need to be done somewhere else?
    00291         DOM::DocumentImpl *doc = m_part->xmlDocImpl();
    00292         if (doc)
    00293             doc->detach();
    00294     }
    00295     delete d; d = 0;
    00296 }
    00297
    00298 void KHTMLView::init()
    00299 {
    00300     if(!d->paintBuffer) d->paintBuffer = new QPixmap(PAINT_BUFFER_HEIGHT, PAINT_BUFFER_HEIGHT);
    00301     if(!d->vertPaintBuffer)
    00302         d->vertPaintBuffer = new QPixmap(10, PAINT_BUFFER_HEIGHT);
    00303     if(!d->tp) d->tp = new QPainter();
    00304
    00305     setFocusPolicy(QWidget::StrongFocus);
    00306     viewport()->setFocusPolicy( QWidget::WheelFocus );
    00307     viewport()->setFocusProxy(this);
    00308
    00309     _marginWidth = -1; // undefined
    00310     _marginHeight = -1;
    00311     _width = 0;
    00312     _height = 0;
    00313
    00314     setAcceptDrops(true);
    00315     resizeContents(visibleWidth(), visibleHeight());
    00316 }
    00317
    00318 void KHTMLView::clear()
    00319 {
    00320     // work around QScrollview's unbelievable bugginess
    00321     setStaticBackground(true);
    00322
    00323     d->reset();
    00324     killTimers();
    00325     emit cleared();
    00326
    00327     QScrollView::setHScrollBarMode(d->hmode);
    00328     if (d->vmode==Auto)
    00329         QScrollView::setVScrollBarMode(d->prevScrollbarVisible?AlwaysOn:Auto);
    00330     else
    00331         QScrollView::setVScrollBarMode(d->vmode);
    00332 }
    00333
    00334 void KHTMLView::hideEvent(QHideEvent* e)
    00335 {
    00336     QScrollView::hideEvent(e);
    00337 }
    00338
    00339 void KHTMLView::showEvent(QShowEvent* e)
    00340 {
    00341     QScrollView::showEvent(e);
    00342 }
    00343
    00344 void KHTMLView::resizeEvent (QResizeEvent* e)
    00345 {
    00346     QScrollView::resizeEvent(e);
    00347
    00348     if ( m_part && m_part->xmlDocImpl() )
    00349         m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false );
    00350 }
    00351
    00352 void KHTMLView::viewportResizeEvent (QResizeEvent* e)
    00353 {
    00354     QScrollView::viewportResizeEvent(e);
    00355
    00356     //int w = visibleWidth();
    00357     //int h = visibleHeight();
    00358
    00359     if (d->layoutSchedulingEnabled)
    00360         layout();
    00361
    00362     KApplication::sendPostedEvents(viewport(), QEvent::Paint);
    00363 }
    00364
    00365 // this is to get rid of a compiler virtual overload mismatch warning. do not remove
    00366 void KHTMLView::drawContents( QPainter*)
    00367 {
    00368 }
    00369
    00370 void KHTMLView::drawContents( QPainter *p, int ex, int ey, int ew, int eh )
    00371 {
    00372     //kdDebug( 6000 ) << "drawContents x=" << ex << ",y=" << ey << ",w=" << ew << ",h=" << eh << endl;
    00373     if(!m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
    00374         p->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
    00375         return;
    00376     }
    00377     if (eh > PAINT_BUFFER_HEIGHT && ew <= 10) {
    00378         if ( d->vertPaintBuffer->height() < visibleHeight() )
    00379             d->vertPaintBuffer->resize(10, visibleHeight());
    00380         d->tp->begin(d->vertPaintBuffer);
    00381         d->tp->translate(-ex, -ey);
    00382         d->tp->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
    00383         m_part->xmlDocImpl()->renderer()->paint(d->tp, ex, ey, ew, eh, 0, 0);
    00384         d->tp->end();
    00385         p->drawPixmap(ex, ey, *d->vertPaintBuffer, 0, 0, ew, eh);
    00386     }
    00387     else {
    00388         if ( d->paintBuffer->width() < visibleWidth() )
    00389             d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT);
    00390
    00391         int py=0;
    00392         while (py < eh) {
    00393             int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
    00394             d->tp->begin(d->paintBuffer);
    00395             d->tp->translate(-ex, -ey-py);
    00396             d->tp->fillRect(ex, ey+py, ew, ph, palette().active().brush(QColorGroup::Base));
    00397             m_part->xmlDocImpl()->renderer()->paint(d->tp, ex, ey+py, ew, ph, 0, 0);
    00398 #ifdef BOX_DEBUG
    00399             if (m_part->xmlDocImpl()->focusNode())
    00400             {
    00401                 d->tp->setBrush(Qt::NoBrush);
    00402                 d->tp->drawRect(m_part->xmlDocImpl()->focusNode()->getRect());
    00403             }
    00404 #endif
    00405             d->tp->end();
    00406
    00407             p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
    00408             py += PAINT_BUFFER_HEIGHT;
    00409         }
    00410     }
    00411
    00412     khtml::DrawContentsEvent event( p, ex, ey, ew, eh );
    00413     QApplication::sendEvent( m_part, &event );
    00414
    00415 }
    00416
    00417 void KHTMLView::setMarginWidth(int w)
    00418 {
    00419     // make it update the rendering area when set
    00420     _marginWidth = w;
    00421 }
    00422
    00423 void KHTMLView::setMarginHeight(int h)
    00424 {
    00425     // make it update the rendering area when set
    00426     _marginHeight = h;
    00427 }
    00428
    00429 void KHTMLView::layout()
    00430 {
    00431     if( m_part->xmlDocImpl() ) {
    00432         DOM::DocumentImpl *document = m_part->xmlDocImpl();
    00433
    00434         khtml::RenderRoot* root = static_cast<khtml::RenderRoot *>(document->renderer());
    00435         if ( !root ) return;
    00436
    00437          if (document->isHTMLDocument()) {
    00438              NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
    00439              if(body && body->renderer() && body->id() == ID_FRAMESET) {
    00440                  QScrollView::setVScrollBarMode(AlwaysOff);
    00441                  QScrollView::setHScrollBarMode(AlwaysOff);
    00442                  body->renderer()->setLayouted(false);
    00443 //                  if (d->tooltip) {
    00444 //                      delete d->tooltip;
    00445 //                      d->tooltip = 0;
    00446 //                  }
    00447              }
    00448              else if (!d->tooltip)
    00449                  d->tooltip = new KHTMLToolTip( this, d );
    00450          }
    00451
    00452         _height = visibleHeight();
    00453         _width = visibleWidth();
    00454         //QTime qt;
    00455         //qt.start();
    00456         root->setMinMaxKnown(false);
    00457         root->setLayouted(false);
    00458         root->layout();
    00459         //kdDebug( 6000 ) << "TIME: layout() dt=" << qt.elapsed() << endl;
    00460     }
    00461     else
    00462        _width = visibleWidth();
    00463 }
    00464
    00465 void KHTMLView::closeChildDialogs()
    00466 {
    00467     QObjectList *dlgs = queryList("QDialog");
    00468     for (QObject *dlg = dlgs->first(); dlg; dlg = dlgs->next())
    00469     {
    00470         KDialogBase* dlgbase = dynamic_cast<KDialogBase *>( dlg );
    00471         if ( dlgbase ) {
    00472             kdDebug(6000) << "closeChildDialogs: closing dialog " << dlgbase << endl;
    00473             // close() ends up calling QButton::animateClick, which isn't immediate
    00474             // we need something the exits the event loop immediately (#49068)
    00475             dlgbase->cancel();
    00476         }
    00477         else
    00478         {
    00479             kdWarning() << "closeChildDialogs: not a KDialogBase! Don't use QDialogs in KDE! " << static_cast<QWidget*>(dlg) << endl;
    00480             static_cast<QWidget*>(dlg)->hide();
    00481         }
    00482     }
    00483     delete dlgs;
    00484     d->m_dialogsAllowed = false;
    00485 }
    00486
    00487 bool KHTMLView::dialogsAllowed() {
    00488     bool allowed = d->m_dialogsAllowed;
    00489     KHTMLPart* p = m_part->parentPart();
    00490     if (p && p->view())
    00491         allowed &= p->view()->dialogsAllowed();
    00492     return allowed;
    00493 }
    00494
    00495 void KHTMLView::closeEvent( QCloseEvent* ev )
    00496 {
    00497     closeChildDialogs();
    00498     QScrollView::closeEvent( ev );
    00499 }
    00500
    00501 //
    00502 // Event Handling
    00503 //
    00505
    00506 void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
    00507 {
    00508     if(!m_part->xmlDocImpl()) return;
    00509     if (d->possibleTripleClick)
    00510     {
    00511         viewportMouseDoubleClickEvent( _mouse ); // it handles triple clicks too
    00512         return;
    00513     }
    00514
    00515     int xm, ym;
    00516     viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
    00517
    00518     //kdDebug( 6000 ) << "\nmousePressEvent: x=" << xm << ", y=" << ym << endl;
    00519
    00520     d->isDoubleClick = false;
    00521
    00522     DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MousePress );
    00523     m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
    00524
    00525     // Qt bug: sometimes Qt sends us events that should be sent
    00526     // to the widget instead
    00527     if (  mev.innerNode.handle() && mev.innerNode.handle()->renderer() &&
    00528          mev.innerNode.handle()->renderer()->isWidget() )
    00529         return;
    00530
    00531     if (d->clickCount > 0 &&
    00532         QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
    00533         d->clickCount++;
    00534     else {
    00535         d->clickCount = 1;
    00536         d->clickX = xm;
    00537         d->clickY = ym;
    00538     }
    00539
    00540     bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),true,
    00541                                            d->clickCount,_mouse,true,DOM::NodeImpl::MousePress);
    00542     if (mev.innerNode.handle())
    00543         mev.innerNode.handle()->setPressed();
    00544
    00545     if (!swallowEvent) {
    00546         khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
    00547         QApplication::sendEvent( m_part, &event );
    00548
    00549         emit m_part->nodeActivated(mev.innerNode);
    00550     }
    00551 }
    00552
    00553 void KHTMLView::viewportMouseDoubleClickEvent( QMouseEvent *_mouse )
    00554 {
    00555     if(!m_part->xmlDocImpl()) return;
    00556
    00557     int xm, ym;
    00558     viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
    00559
    00560     kdDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym << endl;
    00561
    00562     d->isDoubleClick = true;
    00563
    00564     DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseDblClick );
    00565     m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
    00566
    00567     // Qt bug: sometimes Qt sends us events that should be sent
    00568     // to the widget instead
    00569     if (  mev.innerNode.handle() && mev.innerNode.handle()->renderer() &&
    00570          mev.innerNode.handle()->renderer()->isWidget() )
    00571         return;
    00572
    00573     // We do the same thing as viewportMousePressEvent() here, since the DOM does not treat
    00574     // single and double-click events as separate (only the detail, i.e. number of clicks differs)
    00575     if (d->clickCount > 0 && d->clickX == xm && d->clickY == ym) // ### support mouse threshold
    00576         d->clickCount++;
    00577     else {
    00578         d->clickCount = 1;
    00579         d->clickX = xm;
    00580         d->clickY = ym;
    00581     }
    00582     kdDebug() << "KHTMLView::viewportMouseDoubleClickEvent clickCount=" << d->clickCount << endl;
    00583     bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),true,
    00584                                            d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick);
    00585
    00586     if (mev.innerNode.handle())
    00587         mev.innerNode.handle()->setPressed();
    00588
    00589     if (!swallowEvent) {
    00590         khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount );
    00591         QApplication::sendEvent( m_part, &event );
    00592     }
    00593
    00594     d->possibleTripleClick=true;
    00595     QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(tripleClickTimeout()));
    00596 }
    00597
    00598 void KHTMLView::tripleClickTimeout()
    00599 {
    00600     d->possibleTripleClick = false;
    00601     d->clickCount = 0;
    00602 }
    00603
    00604 void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse )
    00605 {
    00606
    00607     if(!m_part->xmlDocImpl()) return;
    00608
    00609     int xm, ym;
    00610     viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
    00611
    00612     DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseMove );
    00613     m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
    00614
    00615     // Qt bug: sometimes Qt sends us events that should be sent
    00616     // to the widget instead
    00617     if (  mev.innerNode.handle() && mev.innerNode.handle()->renderer() &&
    00618          mev.innerNode.handle()->renderer()->isWidget() )
    00619         return;
    00620
    00621     bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,mev.innerNode.handle(),false,
    00622                                            0,_mouse,true,DOM::NodeImpl::MouseMove);
    00623
    00624     if (d->clickCount > 0 &&
    00625         QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > QApplication::startDragDistance()) {
    00626         d->clickCount = 0;  // moving the mouse outside the threshold invalidates the click
    00627     }
    00628
    00629     // execute the scheduled script. This is to make sure the mouseover events come after the mouseout events
    00630     m_part->executeScheduledScript();
    00631
    00632     khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
    00633     khtml::RenderStyle* style = (r && r->style()) ? r->style() : 0;
    00634     QCursor c;
    00635     switch ( style ? style->cursor() : CURSOR_AUTO) {
    00636     case CURSOR_AUTO:
    00637         if ( mev.url.length() && m_part->settings()->changeCursor() )
    00638             c = m_part->urlCursor();
    00639
    00640         if (r && r->isFrameSet() && !static_cast<RenderFrameSet*>(r)->noResize())
    00641             c = QCursor(static_cast<RenderFrameSet*>(r)->cursorShape());
    00642
    00643         break;
    00644     case CURSOR_CROSS:
    00645         c = KCursor::crossCursor();
    00646         break;
    00647     case CURSOR_POINTER:
    00648         c = m_part->urlCursor();
    00649         break;
    00650     case CURSOR_PROGRESS:
    00651         c = KCursor::workingCursor();
    00652         break;
    00653     case CURSOR_MOVE:
    00654         c = KCursor::sizeAllCursor();
    00655         break;
    00656     case CURSOR_E_RESIZE:
    00657     case CURSOR_W_RESIZE:
    00658         c = KCursor::sizeHorCursor();
    00659         break;
    00660     case CURSOR_N_RESIZE:
    00661     case CURSOR_S_RESIZE:
    00662         c = KCursor::sizeVerCursor();
    00663         break;
    00664     case CURSOR_NE_RESIZE:
    00665     case CURSOR_SW_RESIZE:
    00666         c = KCursor::sizeBDiagCursor();
    00667         break;
    00668     case CURSOR_NW_RESIZE:
    00669     case CURSOR_SE_RESIZE:
    00670         c = KCursor::sizeFDiagCursor();
    00671         break;
    00672     case CURSOR_TEXT:
    00673         c = KCursor::ibeamCursor();
    00674         break;
    00675     case CURSOR_WAIT:
    00676         c = KCursor::waitCursor();
    00677         break;
    00678     case CURSOR_HELP:
    00679         c = KCursor::whatsThisCursor();
    00680         break;
    00681     case CURSOR_DEFAULT:
    00682         break;
    00683     }
    00684
    00685     if ( viewport()->cursor().handle() != c.handle() ) {
    00686         if( c.handle() == KCursor::arrowCursor().handle()) {
    00687             for (KHTMLPart* p = m_part; p; p = p->parentPart())
    00688                 p->view()->viewport()->unsetCursor();
    00689         }
    00690         else
    00691             viewport()->setCursor( c );
    00692     }
    00693
    00694     d->prevMouseX = xm;
    00695     d->prevMouseY = ym;
    00696
    00697     if (!swallowEvent) {
    00698         khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
    00699         QApplication::sendEvent( m_part, &event );
    00700     }
    00701 }
    00702
    00703 void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse )
    00704 {
    00705     if ( !m_part->xmlDocImpl() ) return;
    00706
    00707     int xm, ym;
    00708     viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
    00709
    00710     //kdDebug( 6000 ) << "\nmouseReleaseEvent: x=" << xm << ", y=" << ym << endl;
    00711
    00712     DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseRelease );
    00713     m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
    00714
    00715     // Qt bug: sometimes Qt sends us events that should be sent
    00716     // to the widget instead
    00717     if (  mev.innerNode.handle() && mev.innerNode.handle()->renderer() &&
    00718          mev.innerNode.handle()->renderer()->isWidget() )
    00719         return;
    00720
    00721     bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,mev.innerNode.handle(),true,
    00722                                            d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease);
    00723
    00724     if (d->clickCount > 0 &&
    00725         QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
    00726         dispatchMouseEvent(EventImpl::CLICK_EVENT,mev.innerNode.handle(),true,
    00727                            d->clickCount,_mouse,true,DOM::NodeImpl::MouseRelease);
    00728
    00729     if (mev.innerNode.handle())
    00730         mev.innerNode.handle()->setPressed(false);
    00731
    00732     if (!swallowEvent) {
    00733         khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
    00734         QApplication::sendEvent( m_part, &event );
    00735     }
    00736 }
    00737
    00738 void KHTMLView::keyPressEvent( QKeyEvent *_ke )
    00739 {
    00740
    00741     if (m_part->xmlDocImpl()) {
    00742         if (m_part->xmlDocImpl()->focusNode())
    00743             if (m_part->xmlDocImpl()->focusNode()->dispatchKeyEvent(_ke))
    00744             {
    00745                 _ke->accept();
    00746                 return;
    00747             }
    00748         if (!_ke->text().isNull() && m_part->xmlDocImpl()->getHTMLEventListener(EventImpl::KHTML_KEYDOWN_EVENT))
    00749             if (m_part->xmlDocImpl()->documentElement()->dispatchKeyEvent(_ke))
    00750             {
    00751                 _ke->accept();
    00752                 return;
    00753             }
    00754     }
    00755     int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
    00756     if (_ke->state() & Qt::ShiftButton)
    00757       switch(_ke->key())
    00758         {
    00759         case Key_Space:
    00760             if ( d->vmode == QScrollView::AlwaysOff )
    00761                 _ke->accept();
    00762             else
    00763                 scrollBy( 0, -clipper()->height() - offs );
    00764             break;
    00765
    00766         case Key_Down:
    00767         case Key_J:
    00768             d->adjustScroller(this, KHTMLViewPrivate::ScrollDown, KHTMLViewPrivate::ScrollUp);
    00769             break;
    00770
    00771         case Key_Up:
    00772         case Key_K:
    00773             d->adjustScroller(this, KHTMLViewPrivate::ScrollUp, KHTMLViewPrivate::ScrollDown);
    00774             break;
    00775
    00776         case Key_Left:
    00777         case Key_H:
    00778             d->adjustScroller(this, KHTMLViewPrivate::ScrollLeft, KHTMLViewPrivate::ScrollRight);
    00779             break;
    00780
    00781         case Key_Right:
    00782         case Key_L:
    00783             d->adjustScroller(this, KHTMLViewPrivate::ScrollRight, KHTMLViewPrivate::ScrollLeft);
    00784             break;
    00785         }
    00786     else
    00787         switch ( _ke->key() )
    00788         {
    00789         case Key_Down:
    00790         case Key_J:
    00791             if ( d->vmode == QScrollView::AlwaysOff )
    00792                 _ke->accept();
    00793             else {
    00794                 if (d->scrollTimerId)
    00795                     d->newScrollTimer(this, 0);
    00796                 else
    00797                     scrollBy( 0, 10 );
    00798             }
    00799             break;
    00800
    00801         case Key_Space:
    00802         case Key_Next:
    00803             if ( d->vmode == QScrollView::AlwaysOff )
    00804                 _ke->accept();
    00805             else
    00806                 scrollBy( 0, clipper()->height() - offs );
    00807             break;
    00808
    00809         case Key_Up:
    00810         case Key_K:
    00811             if ( d->vmode == QScrollView::AlwaysOff )
    00812                 _ke->accept();
    00813             else {
    00814                 if (d->scrollTimerId)
    00815                     d->newScrollTimer(this, 0);
    00816                 else
    00817                     scrollBy( 0, -10 );
    00818             }
    00819             break;
    00820
    00821         case Key_Prior:
    00822             if ( d->vmode == QScrollView::AlwaysOff )
    00823                 _ke->accept();
    00824             else
    00825                 scrollBy( 0, -clipper()->height() + offs );
    00826             break;
    00827         case Key_Right:
    00828         case Key_L:
    00829             if ( d->hmode == QScrollView::AlwaysOff )
    00830                 _ke->accept();
    00831             else {
    00832                 if (d->scrollTimerId)
    00833                     d->newScrollTimer(this, 0);
    00834                 else
    00835                     scrollBy( 10, 0 );
    00836             }
    00837             break;
    00838         case Key_Left:
    00839         case Key_H:
    00840             if ( d->hmode == QScrollView::AlwaysOff )
    00841                 _ke->accept();
    00842             else {
    00843                 if (d->scrollTimerId)
    00844                     d->newScrollTimer(this, 0);
    00845                 else
    00846                     scrollBy( -10, 0 );
    00847             }
    00848             break;
    00849         case Key_Enter:
    00850         case Key_Return:
    00851             // ### FIXME:
    00852             // move this code to HTMLAnchorElementImpl::setPressed(false),
    00853             // or even better to HTMLAnchorElementImpl::event()
    00854             if (m_part->xmlDocImpl()) {
    00855                 NodeImpl *n = m_part->xmlDocImpl()->focusNode();
    00856                 if (n)
    00857                     n->setActive();
    00858                 d->originalNode = n;
    00859             }
    00860             break;
    00861         case Key_Home:
    00862             if ( d->vmode == QScrollView::AlwaysOff )
    00863                 _ke->accept();
    00864             else
    00865                 setContentsPos( 0, 0 );
    00866             break;
    00867         case Key_End:
    00868             if ( d->vmode == QScrollView::AlwaysOff )
    00869                 _ke->accept();
    00870             else
    00871                 setContentsPos( 0, contentsHeight() - visibleHeight() );
    00872             break;
    00873         case Key_Shift:
    00874             // what are you doing here?
    00875             _ke->ignore();
    00876             return;
    00877         default:
    00878             if (d->scrollTimerId)
    00879                 d->newScrollTimer(this, 0);
    00880             _ke->ignore();
    00881             return;
    00882         }
    00883     _ke->accept();
    00884 }
    00885
    00886 void KHTMLView::keyReleaseEvent(QKeyEvent *_ke)
    00887 {
    00888     if(m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()) {
    00889         // Qt is damn buggy. we receive release events from our child
    00890         // widgets. therefore, do not support keyrelease event on generic
    00891         // nodes for now until we found  a workaround for the Qt bugs. (Dirk)
    00892 //         if (m_part->xmlDocImpl()->focusNode()->dispatchKeyEvent(_ke)) {
    00893 //             _ke->accept();
    00894 //             return;
    00895 //         }
    00896 //        QScrollView::keyReleaseEvent(_ke);
    00897         Q_UNUSED(_ke);
    00898     }
    00899 }
    00900
    00901 void KHTMLView::contentsContextMenuEvent ( QContextMenuEvent * /*ce*/ )
    00902 {
    00903 // ### what kind of c*** is that ?
    00904 #if 0
    00905     if (!m_part->xmlDocImpl()) return;
    00906     int xm = _ce->x();
    00907     int ym = _ce->y();
    00908
    00909     DOM::NodeImpl::MouseEvent mev( _ce->state(), DOM::NodeImpl::MouseMove ); // ### not a mouse event!
    00910     m_part->xmlDocImpl()->prepareMouseEvent( xm, ym, &mev );
    00911
    00912     NodeImpl *targetNode = mev.innerNode.handle();
    00913     if (targetNode && targetNode->renderer() && targetNode->renderer()->isWidget()) {
    00914         int absx = 0;
    00915         int absy = 0;
    00916         targetNode->renderer()->absolutePosition(absx,absy);
    00917         QPoint pos(xm-absx,ym-absy);
    00918
    00919         QWidget *w = static_cast<RenderWidget*>(targetNode->renderer())->widget();
    00920         QContextMenuEvent cme(_ce->reason(),pos,_ce->globalPos(),_ce->state());
    00921         setIgnoreEvents(true);
    00922         QApplication::sendEvent(w,&cme);
    00923         setIgnoreEvents(false);
    00924     }
    00925 #endif
    00926 }
    00927
    00928 bool KHTMLView::focusNextPrevChild( bool next )
    00929 {
    00930     // Now try to find the next child
    00931     if (m_part->xmlDocImpl()) {
    00932         focusNextPrevNode(next);
    00933         if (m_part->xmlDocImpl()->focusNode() != 0)
    00934             return true; // focus node found
    00935     }
    00936
    00937     // If we get here, there is no next/previous child to go to, so pass up to the next/previous child in our parent
    00938     if (m_part->parentPart() && m_part->parentPart()->view()) {
    00939         return m_part->parentPart()->view()->focusNextPrevChild(next);
    00940     }
    00941
    00942     return QWidget::focusNextPrevChild(next);
    00943 }
    00944
    00945 void KHTMLView::doAutoScroll()
    00946 {
    00947     QPoint pos = QCursor::pos();
    00948     pos = viewport()->mapFromGlobal( pos );
    00949
    00950     int xm, ym;
    00951     viewportToContents(pos.x(), pos.y(), xm, ym);
    00952
    00953     pos = QPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
    00954     if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
    00955          (pos.x() < 0) || (pos.x() > visibleWidth()) )
    00956     {
    00957         ensureVisible( xm, ym, 0, 5 );
    00958     }
    00959 }
    00960
    00961 DOM::NodeImpl *KHTMLView::nodeUnderMouse() const
    00962 {
    00963     return d->underMouse;
    00964 }
    00965
    00966 bool KHTMLView::scrollTo(const QRect &bounds)
    00967 {
    00968     d->scrollingSelf = true; // so scroll events get ignored
    00969
    00970     int x, y, xe, ye;
    00971     x = bounds.left();
    00972     y = bounds.top();
    00973     xe = bounds.right();
    00974     ye = bounds.bottom();
    00975
    00976     //kdDebug(6000)<<"scrolling coords: x="<<x<<" y="<<y<<" width="<<xe-x<<" height="<<ye-y<<endl;
    00977
    00978     int deltax;
    00979     int deltay;
    00980
    00981     int curHeight = visibleHeight();
    00982     int curWidth = visibleWidth();
    00983
    00984     if (ye-y>curHeight-d->borderY)
    00985         ye  = y + curHeight - d->borderY;
    00986
    00987     if (xe-x>curWidth-d->borderX)
    00988         xe = x + curWidth - d->borderX;
    00989
    00990     // is xpos of target left of the view's border?
    00991     if (x < contentsX() + d->borderX )
    00992             deltax = x - contentsX() - d->borderX;
    00993     // is xpos of target right of the view's right border?
    00994     else if (xe + d->borderX > contentsX() + curWidth)
    00995             deltax = xe + d->borderX - ( contentsX() + curWidth );
    00996     else
    00997         deltax = 0;
    00998
    00999     // is ypos of target above upper border?
    01000     if (y < contentsY() + d->borderY)
    01001             deltay = y - contentsY() - d->borderY;
    01002     // is ypos of target below lower border?
    01003     else if (ye + d->borderY > contentsY() + curHeight)
    01004             deltay = ye + d->borderY - ( contentsY() + curHeight );
    01005     else
    01006         deltay = 0;
    01007
    01008     int maxx = curWidth-d->borderX;
    01009     int maxy = curHeight-d->borderY;
    01010
    01011     int scrollX,scrollY;
    01012
    01013     scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx);
    01014     scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy);
    01015
    01016     if (contentsX() + scrollX < 0)
    01017         scrollX = -contentsX();
    01018     else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
    01019         scrollX = contentsWidth() - visibleWidth() - contentsX();
    01020
    01021     if (contentsY() + scrollY < 0)
    01022         scrollY = -contentsY();
    01023     else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
    01024         scrollY = contentsHeight() - visibleHeight() - contentsY();
    01025
    01026     scrollBy(scrollX, scrollY);
    01027
    01028
    01029
    01030     // generate abs(scroll.)
    01031     if (scrollX<0)
    01032         scrollX=-scrollX;
    01033     if (scrollY<0)
    01034         scrollY=-scrollY;
    01035
    01036     d->scrollingSelf = false;
    01037
    01038     if ( (scrollX!=maxx) && (scrollY!=maxy) )
    01039         return true;
    01040     else return false;
    01041
    01042 }
    01043
    01044 void KHTMLView::focusNextPrevNode(bool next)
    01045 {
    01046     // Sets the focus node of the document to be the node after (or if next is false, before) the current focus node.
    01047     // Only nodes that are selectable (i.e. for which isSelectable() returns true) are taken into account, and the order
    01048     // used is that specified in the HTML spec (see DocumentImpl::nextFocusNode() and DocumentImpl::previousFocusNode()
    01049     // for details).
    01050
    01051     DocumentImpl *doc = m_part->xmlDocImpl();
    01052     NodeImpl *oldFocusNode = doc->focusNode();
    01053     NodeImpl *newFocusNode;
    01054
    01055     // Find the next/previous node from the current one
    01056     if (next)
    01057         newFocusNode = doc->nextFocusNode(oldFocusNode);
    01058     else
    01059         newFocusNode = doc->previousFocusNode(oldFocusNode);
    01060
    01061     // If there was previously no focus node and the user has scrolled the document, then instead of picking the first
    01062     // focusable node in the document, use the first one that lies within the visible area (if possible).
    01063     if (!oldFocusNode && newFocusNode && d->scrollBarMoved) {
    01064
    01065       kdDebug(6000) << " searching for visible link" << endl;
    01066
    01067         bool visible = false;
    01068         NodeImpl *toFocus = newFocusNode;
    01069         while (!visible && toFocus) {
    01070             QRect focusNodeRect = toFocus->getRect();
    01071             if ((focusNodeRect.left() > contentsX()) && (focusNodeRect.right() < contentsX() + visibleWidth()) &&
    01072                 (focusNodeRect.top() > contentsY()) && (focusNodeRect.bottom() < contentsY() + visibleHeight())) {
    01073                 // toFocus is visible in the contents area
    01074                 visible = true;
    01075             }
    01076             else {
    01077                 // toFocus is _not_ visible in the contents area, pick the next node
    01078                 if (next)
    01079                     toFocus = doc->nextFocusNode(toFocus);
    01080                 else
    01081                     toFocus = doc->previousFocusNode(toFocus);
    01082             }
    01083         }
    01084
    01085         if (toFocus)
    01086             newFocusNode = toFocus;
    01087     }
    01088
    01089     d->scrollBarMoved = false;
    01090
    01091     if (!newFocusNode)
    01092       {
    01093         // No new focus node, scroll to bottom or top depending on next
    01094         if (next)
    01095             scrollTo(QRect(contentsX()+visibleWidth()/2,contentsHeight(),0,0));
    01096         else
    01097             scrollTo(QRect(contentsX()+visibleWidth()/2,0,0,0));
    01098     }
    01099     else
    01100     // Scroll the view as necessary to ensure that the new focus node is visible
    01101     {
    01102       if (oldFocusNode)
    01103         {
    01104           if (!scrollTo(newFocusNode->getRect()))
    01105             return;
    01106         }
    01107       else
    01108         {
    01109           ensureVisible(contentsX(), next?0:contentsHeight());
    01110           //return;
    01111         }
    01112     }
    01113     // Set focus node on the document
    01114     m_part->xmlDocImpl()->setFocusNode(newFocusNode);
    01115     emit m_part->nodeActivated(Node(newFocusNode));
    01116
    01117 #if 0
    01118     if (newFocusNode) {
    01119
    01120         // this does not belong here. it should run a query on the tree (Dirk)
    01121         // I'll fix this very particular part of the code soon when I cleaned
    01122         // up the positioning code
    01123         // If the newly focussed node is a link, notify the part
    01124
    01125         HTMLAnchorElementImpl *anchor = 0;
    01126         if ((newFocusNode->id() == ID_A || newFocusNode->id() == ID_AREA))
    01127             anchor = static_cast<HTMLAnchorElementImpl *>(newFocusNode);
    01128
    01129         if (anchor && !anchor->areaHref().isNull())
    01130             m_part->overURL(anchor->areaHref().string(), 0);
    01131         else
    01132             m_part->overURL(QString(), 0);
    01133     }
    01134 #endif
    01135 }
    01136
    01137 void KHTMLView::setMediaType( const QString &medium )
    01138 {
    01139     m_medium = medium;
    01140 }
    01141
    01142 QString KHTMLView::mediaType() const
    01143 {
    01144     return m_medium;
    01145 }
    01146
    01147 void KHTMLView::setWidgetVisible(RenderWidget* w, bool vis)
    01148 {
    01149     if (vis) {
    01150         assert(w->widget());
    01151         d->visibleWidgets.replace(w, w->widget());
    01152     }
    01153     else
    01154         d->visibleWidgets.remove(w);
    01155 }
    01156
    01157 void KHTMLView::print()
    01158 {
    01159     if(!m_part->xmlDocImpl()) return;
    01160     khtml::RenderRoot *root = static_cast<khtml::RenderRoot *>(m_part->xmlDocImpl()->renderer());
    01161     if(!root) return;
    01162
    01163     // this only works on Unix - we assume 72dpi
    01164     KPrinter *printer = new KPrinter(QPrinter::PrinterResolution);
    01165     printer->addDialogPage(new KHTMLPrintSettings());
    01166     if(printer->setup(this)) {
    01167         viewport()->setCursor( waitCursor ); // only viewport(), no QApplication::, otherwise we get the busy cursor in kdeprint's dialogs
    01168         // set up KPrinter
    01169         printer->setFullPage(false);
    01170         printer->setCreator("KDE 3.0 HTML Library");
    01171         QString docname = m_part->xmlDocImpl()->URL();
    01172         if ( !docname.isEmpty() )
    01173             printer->setDocName(KStringHandler::csqueeze(docname, 80));
    01174
    01175         QPainter *p = new QPainter;
    01176         p->begin( printer );
    01177         khtml::setPrintPainter( p );
    01178
    01179         m_part->xmlDocImpl()->setPaintDevice( printer );
    01180         QString oldMediaType = mediaType();
    01181         setMediaType( "print" );
    01182         // We ignore margin settings for html and body when printing
    01183         // and use the default margins from the print-system
    01184         // (In Qt 3.0.x the default margins are hardcoded in Qt)
    01185         m_part->xmlDocImpl()->setPrintStyleSheet( printer->option("app-khtml-printfriendly") == "true" ?
    01186                                                   "* { background-image: none !important;"
    01187                                                   "    background-color: white !important;"
    01188                                                   "    color: black !important; }"
    01189                                                   "body { margin: 0px !important; }"
    01190                                                   "html { margin: 0px !important; }" :
    01191                                                   "body { margin: 0px !important; }"
    01192                                                   "html { margin: 0px !important; }"
    01193                                                   );
    01194
    01195         QPaintDeviceMetrics metrics( printer );
    01196
    01197         // this is a simple approximation... we layout the document
    01198         // according to the width of the page, then just cut
    01199         // pages without caring about the content. We should do better
    01200         // in the future, but for the moment this is better than no
    01201         // printing support
    01202         kdDebug(6000) << "printing: physical page width = " << metrics.width()
    01203                       << " height = " << metrics.height() << endl;
    01204         root->setPrintingMode(true);
    01205         root->setWidth(metrics.width());
    01206
    01207         m_part->xmlDocImpl()->styleSelector()->computeFontSizes(&metrics, 100);
    01208         m_part->xmlDocImpl()->updateStyleSelector();
    01209         root->setPrintImages( printer->option("app-khtml-printimages") == "true");
    01210         root->setLayouted( false );
    01211         root->setMinMaxKnown( false );
    01212         root->layout();
    01213
    01214         bool printHeader = (printer->option("app-khtml-printheader") == "true");
    01215
    01216         int headerHeight = 0;
    01217         QFont headerFont("helvetica", 8);
    01218
    01219         QString headerLeft = KGlobal::locale()->formatDate(QDate::currentDate(),true);
    01220         QString headerMid = docname;
    01221         QString headerRight;
    01222
    01223         if (printHeader)
    01224         {
    01225            p->setFont(headerFont);
    01226            headerHeight = (p->fontMetrics().lineSpacing() * 3) / 2;
    01227         }
    01228
    01229         // ok. now print the pages.
    01230         kdDebug(6000) << "printing: html page width = " << root->docWidth()
    01231                       << " height = " << root->docHeight() << endl;
    01232         kdDebug(6000) << "printing: margins left = " << printer->margins().width()
    01233                       << " top = " << printer->margins().height() << endl;
    01234         kdDebug(6000) << "printing: paper width = " << metrics.width()
    01235                       << " height = " << metrics.height() << endl;
    01236         // if the width is too large to fit on the paper we just scale
    01237         // the whole thing.
    01238         int pageHeight = metrics.height();
    01239         int pageWidth = metrics.width();
    01240         p->setClipRect(0,0, pageWidth, pageHeight);
    01241
    01242         pageHeight -= headerHeight;
    01243
    01244         bool scalePage = false;
    01245         double scale = 0.0;
    01246 #ifndef QT_NO_TRANSFORMATIONS
    01247         if(root->docWidth() > metrics.width()) {
    01248             scalePage = true;
    01249             scale = ((double) metrics.width())/((double) root->docWidth());
    01250             pageHeight = (int) (pageHeight/scale);
    01251             pageWidth = (int) (pageWidth/scale);
    01252             headerHeight = (int) (headerHeight/scale);
    01253         }
    01254 #endif
    01255         kdDebug(6000) << "printing: scaled html width = " << pageWidth
    01256                       << " height = " << pageHeight << endl;
    01257
    01258         // Squeeze header to make it it on the page.
    01259         if (printHeader)
    01260         {
    01261             int available_width = metrics.width() - 10 -
    01262                 2 * QMAX(p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(),
    01263                          p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width());
    01264             if (available_width < 150)
    01265                available_width = 150;
    01266             int mid_width;
    01267             int squeeze = 120;
    01268             do {
    01269                 headerMid = KStringHandler::csqueeze(docname, squeeze);
    01270                 mid_width = p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width();
    01271                 squeeze -= 10;
    01272             } while (mid_width > available_width);
    01273         }
    01274
    01275         int top = 0;
    01276         int page = 1;
    01277         while(top < root->docHeight()) {
    01278             if(top > 0) printer->newPage();
    01279             if (printHeader)
    01280             {
    01281                 int dy = p->fontMetrics().lineSpacing();
    01282                 p->setPen(Qt::black);
    01283                 p->setFont(headerFont);
    01284
    01285                 headerRight = QString("#%1").arg(page);
    01286
    01287                 p->drawText(0, 0, metrics.width(), dy, Qt::AlignLeft, headerLeft);
    01288                 p->drawText(0, 0, metrics.width(), dy, Qt::AlignHCenter, headerMid);
    01289                 p->drawText(0, 0, metrics.width(), dy, Qt::AlignRight, headerRight);
    01290             }
    01291
    01292 #ifndef QT_NO_TRANSFORMATIONS
    01293             if (scalePage)
    01294                 p->scale(scale, scale);
    01295 #endif
    01296             p->translate(0, headerHeight-top);
    01297
    01298             root->setTruncatedAt(top+pageHeight);
    01299
    01300             root->paint(p, 0, top, pageWidth, pageHeight, 0, 0);
    01301             if (top + pageHeight >= root->docHeight())
    01302                 break; // Stop if we have printed everything
    01303
    01304             top = root->truncatedAt();
    01305             p->resetXForm();
    01306             page++;
    01307         }
    01308
    01309         p->end();
    01310         delete p;
    01311
    01312         // and now reset the layout to the usual one...
    01313         root->setPrintingMode(false);
    01314         khtml::setPrintPainter( 0 );
    01315         setMediaType( oldMediaType );
    01316         m_part->xmlDocImpl()->setPaintDevice( this );
    01317         m_part->xmlDocImpl()->styleSelector()->computeFontSizes(m_part->xmlDocImpl()->paintDeviceMetrics(), m_part->zoomFactor());
    01318         m_part->xmlDocImpl()->updateStyleSelector();
    01319         viewport()->unsetCursor();
    01320     }
    01321     delete printer;
    01322 }
    01323
    01324 void KHTMLView::slotPaletteChanged()
    01325 {
    01326     if(!m_part->xmlDocImpl()) return;
    01327     DOM::DocumentImpl *document = m_part->xmlDocImpl();
    01328     if (!document->isHTMLDocument()) return;
    01329     khtml::RenderRoot *root = static_cast<khtml::RenderRoot *>(document->renderer());
    01330     if(!root) return;
    01331     root->style()->resetPalette();
    01332     NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
    01333     if(!body) return;
    01334     body->setChanged(true);
    01335     body->recalcStyle( NodeImpl::Force );
    01336 }
    01337
    01338 void KHTMLView::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
    01339 {
    01340     if(!m_part->xmlDocImpl()) return;
    01341     khtml::RenderRoot *root = static_cast<khtml::RenderRoot *>(m_part->xmlDocImpl()->renderer());
    01342     if(!root) return;
    01343
    01344     m_part->xmlDocImpl()->setPaintDevice(p->device());
    01345     root->setPrintingMode(true);
    01346     root->setWidth(rc.width());
    01347
    01348     p->save();
    01349     p->setClipRect(rc);
    01350     p->translate(rc.left(), rc.top());
    01351     double scale = ((double) rc.width()/(double) root->docWidth());
    01352     int height = (int) ((double) rc.height() / scale);
    01353 #ifndef QT_NO_TRANSFORMATIONS
    01354     p->scale(scale, scale);
    01355 #endif
    01356
    01357     root->paint(p, 0, yOff, root->docWidth(), height, 0, 0);
    01358     if (more)
    01359         *more = yOff + height < root->docHeight();
    01360     p->restore();
    01361
    01362     root->setPrintingMode(false);
    01363     m_part->xmlDocImpl()->setPaintDevice( this );
    01364 }
    01365
    01366
    01367 void KHTMLView::useSlowRepaints()
    01368 {
    01369     kdDebug(0) << "slow repaints requested" << endl;
    01370     d->useSlowRepaints = true;
    01371     setStaticBackground(true);
    01372 }
    01373
    01374
    01375 void KHTMLView::setVScrollBarMode ( ScrollBarMode mode )
    01376 {
    01377 #ifndef KHTML_NO_SCROLLBARS
    01378     d->vmode = mode;
    01379     QScrollView::setVScrollBarMode(mode);
    01380 #else
    01381     Q_UNUSED( mode );
    01382 #endif
    01383 }
    01384
    01385 void KHTMLView::setHScrollBarMode ( ScrollBarMode mode )
    01386 {
    01387 #ifndef KHTML_NO_SCROLLBARS
    01388     d->hmode = mode;
    01389     QScrollView::setHScrollBarMode(mode);
    01390 #else
    01391     Q_UNUSED( mode );
    01392 #endif
    01393 }
    01394
    01395 void KHTMLView::restoreScrollBar()
    01396 {
    01397     int ow = visibleWidth();
    01398     QScrollView::setVScrollBarMode(d->vmode);
    01399     if (visibleWidth() != ow)
    01400         layout();
    01401     d->prevScrollbarVisible = verticalScrollBar()->isVisible();
    01402 }
    01403
    01404 QStringList KHTMLView::formCompletionItems(const QString &name) const
    01405 {
    01406     if (!m_part->settings()->isFormCompletionEnabled())
    01407         return QStringList();
    01408     if (!d->formCompletions)
    01409         d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
    01410     return d->formCompletions->readListEntry(name);
    01411 }
    01412
    01413 void KHTMLView::clearCompletionHistory(const QString& name)
    01414 {
    01415     if (!d->formCompletions)
    01416     {
    01417         d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
    01418     }
    01419     d->formCompletions->writeEntry(name, "");
    01420     d->formCompletions->sync();
    01421 }
    01422
    01423 void KHTMLView::addFormCompletionItem(const QString &name, const QString &value)
    01424 {
    01425     if (!m_part->settings()->isFormCompletionEnabled())
    01426         return;
    01427     // don't store values that are all numbers or just numbers with
    01428     // dashes or spaces as those are likely credit card numbers or
    01429     // something similar
    01430     bool cc_number(true);
    01431     for (unsigned int i = 0; i < value.length(); ++i)
    01432     {
    01433       QChar c(value[i]);
    01434       if (!c.isNumber() && c != '-' && !c.isSpace())
    01435       {
    01436         cc_number = false;
    01437         break;
    01438       }
    01439     }
    01440     if (cc_number)
    01441       return;
    01442     QStringList items = formCompletionItems(name);
    01443     if (!items.contains(value))
    01444         items.prepend(value);
    01445     while ((int)items.count() > m_part->settings()->maxFormCompletionItems())
    01446         items.remove(items.fromLast());
    01447     d->formCompletions->writeEntry(name, items);
    01448 }
    01449
    01450 bool KHTMLView::dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode, bool cancelable,
    01451                                    int detail,QMouseEvent *_mouse, bool setUnder,
    01452                                    int mouseEventType)
    01453 {
    01454     if (d->underMouse)
    01455         d->underMouse->deref();
    01456     d->underMouse = targetNode;
    01457     if (d->underMouse)
    01458         d->underMouse->ref();
    01459
    01460     int exceptioncode = 0;
    01461     int mx, my;
    01462     viewportToContents(_mouse->x(), _mouse->y(), mx, my);
    01463     // clientX and clientY are in viewport coordinates
    01464     // At least the JS code wants event.[xy]/event.client[XY] to be in viewport coords.
    01465     // [that's not the same as _mouse->[xy](), since we use the clipper]
    01466     int clientX = mx - contentsX();
    01467     int clientY = my - contentsY();
    01468     int screenX = _mouse->globalX();
    01469     int screenY = _mouse->globalY();
    01470     int button = -1;
    01471     switch (_mouse->button()) {
    01472         case LeftButton:
    01473             button = 0;
    01474             break;
    01475         case MidButton:
    01476             button = 1;
    01477             break;
    01478         case RightButton:
    01479             button = 2;
    01480             break;
    01481         default:
    01482             break;
    01483     }
    01484     bool ctrlKey = (_mouse->state() & ControlButton);
    01485     bool altKey = (_mouse->state() & AltButton);
    01486     bool shiftKey = (_mouse->state() & ShiftButton);
    01487     bool metaKey = (_mouse->state() & MetaButton);
    01488
    01489     // mouseout/mouseover
    01490     if (setUnder && (d->prevMouseX != mx || d->prevMouseY != my)) {
    01491
    01492         // ### this code sucks. we should save the oldUnder instead of calculating
    01493         // it again. calculating is expensive! (Dirk)
    01494         NodeImpl *oldUnder = 0;
    01495         if (d->prevMouseX >= 0 && d->prevMouseY >= 0) {
    01496             NodeImpl::MouseEvent mev( _mouse->stateAfter(), static_cast<NodeImpl::MouseEventType>(mouseEventType));
    01497             m_part->xmlDocImpl()->prepareMouseEvent( true, d->prevMouseX, d->prevMouseY, &mev );
    01498             oldUnder = mev.innerNode.handle();
    01499         }
    01500         if (oldUnder != targetNode) {
    01501             // send mouseout event to the old node
    01502             if (oldUnder){
    01503                 oldUnder->ref();
    01504                 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOUT_EVENT,
    01505                                                         true,true,m_part->xmlDocImpl()->defaultView(),
    01506                                                         0,screenX,screenY,clientX,clientY,
    01507                                                         ctrlKey,altKey,shiftKey,metaKey,
    01508                                                         button,targetNode);
    01509                 me->ref();
    01510                 oldUnder->dispatchEvent(me,exceptioncode,true);
    01511                 me->deref();
    01512             }
    01513
    01514             // send mouseover event to the new node
    01515             if (targetNode) {
    01516                 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOVER_EVENT,
    01517                                                         true,true,m_part->xmlDocImpl()->defaultView(),
    01518                                                         0,screenX,screenY,clientX,clientY,
    01519                                                         ctrlKey,altKey,shiftKey,metaKey,
    01520                                                         button,oldUnder);
    01521
    01522                 me->ref();
    01523                 targetNode->dispatchEvent(me,exceptioncode,true);
    01524                 me->deref();
    01525             }
    01526
    01527             if (oldUnder)
    01528                 oldUnder->deref();
    01529         }
    01530     }
    01531
    01532     bool swallowEvent = false;
    01533
    01534     if (targetNode) {
    01535         // send the actual event
    01536         MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
    01537                                                 true,cancelable,m_part->xmlDocImpl()->defaultView(),
    01538                                                 detail,screenX,screenY,clientX,clientY,
    01539                                                 ctrlKey,altKey,shiftKey,metaKey,
    01540                                                 button,0);
    01541         me->ref();
    01542         targetNode->dispatchEvent(me,exceptioncode,true);
    01543         if (me->defaultHandled() || me->defaultPrevented())
    01544             swallowEvent = true;
    01545         me->deref();
    01546
    01547         if( eventId == EventImpl::MOUSEDOWN_EVENT ) {
    01548             if (targetNode->isSelectable())
    01549                 m_part->xmlDocImpl()->setFocusNode(targetNode);
    01550             else
    01551                 m_part->xmlDocImpl()->setFocusNode(0);
    01552         }
    01553     }
    01554
    01555     return swallowEvent;
    01556 }
    01557
    01558 void KHTMLView::setIgnoreWheelEvents( bool e )
    01559 {
    01560     d->ignoreWheelEvents = e;
    01561 }
    01562
    01563 #ifndef QT_NO_WHEELEVENT
    01564
    01565 void KHTMLView::viewportWheelEvent(QWheelEvent* e)
    01566 {
    01567     if ( ( e->state() & ShiftButton ) == ShiftButton )
    01568     {
    01569         emit zoomView( e->delta() );
    01570         e->accept();
    01571     }
    01572     else if ( d->ignoreWheelEvents && !verticalScrollBar()->isVisible()
    01573                 && m_part->parentPart() ) {
    01574         if ( m_part->parentPart()->view() )
    01575             m_part->parentPart()->view()->wheelEvent( e );
    01576         e->ignore();
    01577     }
    01578     else if ( d->vmode == QScrollView::AlwaysOff ) {
    01579         e->accept();
    01580     }
    01581     else {
    01582         d->scrollBarMoved = true;
    01583         QScrollView::viewportWheelEvent( e );
    01584
    01585         QMouseEvent *tempEvent = new QMouseEvent( QEvent::MouseMove, QPoint(-1,-1), QPoint(-1,-1), Qt::NoButton, e->state() );
    01586         emit viewportMouseMoveEvent ( tempEvent );
    01587         delete tempEvent;
    01588     }
    01589
    01590 }
    01591 #endif
    01592
    01593 void KHTMLView::dragEnterEvent( QDragEnterEvent* ev )
    01594 {
    01595     // Handle drops onto frames (#16820)
    01596     // Drops on the main html part is handled by Konqueror (and shouldn't do anything
    01597     // in e.g. kmail, so not handled here).
    01598     if ( m_part->parentPart() )
    01599     {
    01600         // Duplicated from KonqView::eventFilter
    01601         if ( QUriDrag::canDecode( ev ) )
    01602         {
    01603             KURL::List lstDragURLs;
    01604             bool ok = KURLDrag::decode( ev, lstDragURLs );
    01605             QObjectList *children = this->queryList( "QWidget" );
    01606
    01607             if ( ok &&
    01608                  !lstDragURLs.first().url().contains( "javascript:", false ) && // ### this looks like a hack to me
    01609                  ev->source() != this &&
    01610                  children &&
    01611                  children->findRef( ev->source() ) == -1 )
    01612                 ev->acceptAction();
    01613
    01614             delete children;
    01615         }
    01616     }
    01617     QScrollView::dragEnterEvent( ev );
    01618 }
    01619
    01620 void KHTMLView::dropEvent( QDropEvent *ev )
    01621 {
    01622     // Handle drops onto frames (#16820)
    01623     // Drops on the main html part is handled by Konqueror (and shouldn't do anything
    01624     // in e.g. kmail, so not handled here).
    01625     if ( m_part->parentPart() )
    01626     {
    01627         KURL::List lstDragURLs;
    01628         bool ok = KURLDrag::decode( ev, lstDragURLs );
    01629
    01630         KHTMLPart* part = m_part->parentPart();
    01631         while ( part && part->parentPart() )
    01632             part = part->parentPart();
    01633         KParts::BrowserExtension *ext = part->browserExtension();
    01634         if ( ok && ext && lstDragURLs.first().isValid() )
    01635             emit ext->openURLRequest( lstDragURLs.first() );
    01636     }
    01637     QScrollView::dropEvent( ev );
    01638 }
    01639
    01640 void KHTMLView::focusOutEvent( QFocusEvent *e )
    01641 {
    01642     if(m_part) m_part->stopAutoScroll();
    01643     QScrollView::focusOutEvent( e );
    01644 }
    01645
    01646 void KHTMLView::slotScrollBarMoved()
    01647 {
    01648     if (!d->scrollingSelf)
    01649         d->scrollBarMoved = true;
    01650 }
    01651
    01652 void KHTMLView::timerEvent ( QTimerEvent *e )
    01653 {
    01654 //    kdDebug() << "timer event " << e->timerId() << endl;
    01655     if (e->timerId() == d->scrollTimerId) {
    01656         switch (d->scrollDirection) {
    01657             case KHTMLViewPrivate::ScrollDown:
    01658                 if (contentsY() + visibleHeight () >= contentsHeight())
    01659                     d->newScrollTimer(this, 0);
    01660                 else
    01661                     scrollBy( 0, d->scrollBy );
    01662                 break;
    01663             case KHTMLViewPrivate::ScrollUp:
    01664                 if (contentsY() <= 0)
    01665                     d->newScrollTimer(this, 0);
    01666                 else
    01667                     scrollBy( 0, -d->scrollBy );
    01668                 break;
    01669             case KHTMLViewPrivate::ScrollRight:
    01670                 if (contentsX() + visibleWidth () >= contentsWidth())
    01671                     d->newScrollTimer(this, 0);
    01672                 else
    01673                     scrollBy( d->scrollBy, 0 );
    01674                 break;
    01675             case KHTMLViewPrivate::ScrollLeft:
    01676                 if (contentsX() <= 0)
    01677                     d->newScrollTimer(this, 0);
    01678                 else
    01679                     scrollBy( -d->scrollBy, 0 );
    01680                 break;
    01681         }
    01682         return;
    01683     }
    01684     if (e->timerId()==d->timerId)
    01685     {
    01686         d->firstRelayout = false;
    01687         killTimer(d->timerId);
    01688
    01689         d->dirtyLayout = true;
    01690         d->layoutSchedulingEnabled=false;
    01691         layout();
    01692         d->layoutSchedulingEnabled=true;
    01693
    01694         d->timerId = 0;
    01695
    01696
    01697         //scheduleRepaint(contentsX(),contentsY(),visibleWidth(),visibleHeight());
    01698         d->updateRect = QRect(contentsX(),contentsY(),visibleWidth(),visibleHeight());
    01699     }
    01700
    01701     if( m_part->xmlDocImpl() ) {
    01702         DOM::DocumentImpl *document = m_part->xmlDocImpl();
    01703         khtml::RenderRoot* root = static_cast<khtml::RenderRoot *>(document->renderer());
    01704
    01705         if ( !root->layouted() ) {
    01706             killTimer(d->repaintTimerId);
    01707             d->repaintTimerId = 0;
    01708             scheduleRelayout();
    01709             return;
    01710         }
    01711     }
    01712
    01713     setStaticBackground(d->useSlowRepaints);
    01714
    01715 //        kdDebug() << "scheduled repaint "<< d->repaintTimerId  << endl;
    01716     killTimer(d->repaintTimerId);
    01717     updateContents( d->updateRect );
    01718
    01719     if (d->dirtyLayout && !d->visibleWidgets.isEmpty()) {
    01720         d->dirtyLayout = false;
    01721
    01722         QRect visibleRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
    01723         QPtrList<RenderWidget> toRemove;
    01724         QWidget* w;
    01725         for (QPtrDictIterator<QWidget> it(d->visibleWidgets); it.current(); ++it) {
    01726             int xp = 0, yp = 0;
    01727             w = it.current();
    01728             RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
    01729             if (!rw->absolutePosition(xp, yp) ||
    01730                 !visibleRect.intersects(QRect(xp, yp, w->width(), w->height())))
    01731                 toRemove.append(rw);
    01732         }
    01733         for (RenderWidget* r = toRemove.first(); r; r = toRemove.next())
    01734             if ( (w = d->visibleWidgets.take(r) ) )
    01735                 addChild(w, 0, -500000);
    01736     }
    01737
    01738     d->repaintTimerId = 0;
    01739 }
    01740
    01741 void KHTMLView::scheduleRelayout()
    01742 {
    01743     if (!d->layoutSchedulingEnabled || d->timerId)
    01744         return;
    01745
    01746     d->timerId = startTimer( m_part->xmlDocImpl() && m_part->xmlDocImpl()->parsing()
    01747                              ? 1000 : 0 );
    01748 }
    01749
    01750 void KHTMLView::scheduleRepaint(int x, int y, int w, int h)
    01751 {
    01752
    01753     //kdDebug() << "scheduleRepaint(" << x << "," << y << "," << w << "," << h << ")" << endl;
    01754
    01755
    01756     bool parsing = false;
    01757     if( m_part->xmlDocImpl() ) {
    01758         parsing = m_part->xmlDocImpl()->parsing();
    01759     }
    01760
    01761 //     kdDebug() << "parsing " << parsing << endl;
    01762 //     kdDebug() << "complete " << d->complete << endl;
    01763
    01764     int time;
    01765
    01766     // if complete...
    01767     if (d->complete)
    01768         // ...repaint immediatly
    01769         time = 0;
    01770     else
    01771     {
    01772         if (parsing)
    01773             // not complete and still parsing
    01774             time = 300;
    01775         else
    01776             // not complete, not parsing, extend the timer if it exists
    01777             // otherwise, repaint immediatly
    01778             time = d->repaintTimerId ? 400 : 0;
    01779     }
    01780
    01781     if (d->repaintTimerId) {
    01782         killTimer(d->repaintTimerId);
    01783         d->updateRect = d->updateRect.unite(QRect(x,y,w,h));
    01784     } else
    01785         d->updateRect = QRect(x,y,w,h);
    01786
    01787     d->repaintTimerId = startTimer( time );
    01788
    01789 //     kdDebug() << "starting timer " << time << endl;
    01790 }
    01791
    01792 void KHTMLView::complete()
    01793 {
    01794 //     kdDebug() << "KHTMLView::complete()" << endl;
    01795
    01796     d->complete = true;
    01797
    01798     // is there a relayout pending?
    01799     if (d->timerId)
    01800     {
    01801 //         kdDebug() << "requesting relayout now" << endl;
    01802         // do it now
    01803         killTimer(d->timerId);
    01804         d->timerId = startTimer( 0 );
    01805     }
    01806
    01807     // is there a repaint pending?
    01808     if (d->repaintTimerId)
    01809     {
    01810 //         kdDebug() << "requesting repaint now" << endl;
    01811         // do it now
    01812         killTimer(d->repaintTimerId);
    01813         d->repaintTimerId = startTimer( 1 );
    01814     }
    01815 }

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:34:09 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001