00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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 QRect r(m_view->rect());
00247 r.moveTopLeft(p + QPoint(2, 16));
00248 r.setWidth(-1);
00249 tip( region, s, r );
00250 break;
00251 }
00252 }
00253 node = node->parentNode();
00254 }
00255 }
00256 #endif
00257
00258 KHTMLView::KHTMLView( KHTMLPart *part, QWidget *parent, const char *name)
00259 : QScrollView( parent, name, WResizeNoErase | WRepaintNoErase | WPaintUnclipped )
00260 {
00261 m_medium = "screen";
00262
00263 m_part = part;
00264 d = new KHTMLViewPrivate;
00265 QScrollView::setVScrollBarMode(d->vmode);
00266 QScrollView::setHScrollBarMode(d->hmode);
00267 connect(kapp, SIGNAL(kdisplayPaletteChanged()), this, SLOT(slotPaletteChanged()));
00268 connect(this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotScrollBarMoved()));
00269
00270
00271 enableClipper(true);
00272 setResizePolicy(Manual);
00273 viewport()->setMouseTracking(true);
00274 viewport()->setBackgroundMode(NoBackground);
00275
00276 KImageIO::registerFormats();
00277
00278 #ifndef QT_NO_TOOLTIP
00279 d->tooltip = new KHTMLToolTip( this, d );
00280 #endif
00281
00282 init();
00283
00284 viewport()->show();
00285 }
00286
00287 KHTMLView::~KHTMLView()
00288 {
00289 closeChildDialogs();
00290 if (m_part)
00291 {
00292
00293
00294 DOM::DocumentImpl *doc = m_part->xmlDocImpl();
00295 if (doc)
00296 doc->detach();
00297 }
00298 delete d; d = 0;
00299 }
00300
00301 void KHTMLView::init()
00302 {
00303 if(!d->paintBuffer) d->paintBuffer = new QPixmap(PAINT_BUFFER_HEIGHT, PAINT_BUFFER_HEIGHT);
00304 if(!d->vertPaintBuffer)
00305 d->vertPaintBuffer = new QPixmap(10, PAINT_BUFFER_HEIGHT);
00306 if(!d->tp) d->tp = new QPainter();
00307
00308 setFocusPolicy(QWidget::StrongFocus);
00309 viewport()->setFocusPolicy( QWidget::WheelFocus );
00310 viewport()->setFocusProxy(this);
00311
00312 _marginWidth = -1;
00313 _marginHeight = -1;
00314 _width = 0;
00315 _height = 0;
00316
00317 setAcceptDrops(true);
00318 resizeContents(visibleWidth(), visibleHeight());
00319 }
00320
00321 void KHTMLView::clear()
00322 {
00323
00324 setStaticBackground(true);
00325
00326 d->reset();
00327 killTimers();
00328 emit cleared();
00329
00330 QScrollView::setHScrollBarMode(d->hmode);
00331 if (d->vmode==Auto)
00332 QScrollView::setVScrollBarMode(d->prevScrollbarVisible?AlwaysOn:Auto);
00333 else
00334 QScrollView::setVScrollBarMode(d->vmode);
00335 }
00336
00337 void KHTMLView::hideEvent(QHideEvent* e)
00338 {
00339 QScrollView::hideEvent(e);
00340 }
00341
00342 void KHTMLView::showEvent(QShowEvent* e)
00343 {
00344 QScrollView::showEvent(e);
00345 }
00346
00347 void KHTMLView::resizeEvent (QResizeEvent* e)
00348 {
00349 QScrollView::resizeEvent(e);
00350
00351 if ( m_part && m_part->xmlDocImpl() )
00352 m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false );
00353 }
00354
00355 void KHTMLView::viewportResizeEvent (QResizeEvent* e)
00356 {
00357 QScrollView::viewportResizeEvent(e);
00358
00359
00360
00361
00362 if (d->layoutSchedulingEnabled)
00363 layout();
00364
00365 KApplication::sendPostedEvents(viewport(), QEvent::Paint);
00366 }
00367
00368
00369 void KHTMLView::drawContents( QPainter*)
00370 {
00371 }
00372
00373 void KHTMLView::drawContents( QPainter *p, int ex, int ey, int ew, int eh )
00374 {
00375
00376 if(!m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
00377 p->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00378 return;
00379 }
00380 if (eh > PAINT_BUFFER_HEIGHT && ew <= 10) {
00381 if ( d->vertPaintBuffer->height() < visibleHeight() )
00382 d->vertPaintBuffer->resize(10, visibleHeight());
00383 d->tp->begin(d->vertPaintBuffer);
00384 d->tp->translate(-ex, -ey);
00385 d->tp->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00386 m_part->xmlDocImpl()->renderer()->paint(d->tp, ex, ey, ew, eh, 0, 0);
00387 d->tp->end();
00388 p->drawPixmap(ex, ey, *d->vertPaintBuffer, 0, 0, ew, eh);
00389 }
00390 else {
00391 if ( d->paintBuffer->width() < visibleWidth() )
00392 d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT);
00393
00394 int py=0;
00395 while (py < eh) {
00396 int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
00397 d->tp->begin(d->paintBuffer);
00398 d->tp->translate(-ex, -ey-py);
00399 d->tp->fillRect(ex, ey+py, ew, ph, palette().active().brush(QColorGroup::Base));
00400 m_part->xmlDocImpl()->renderer()->paint(d->tp, ex, ey+py, ew, ph, 0, 0);
00401 #ifdef BOX_DEBUG
00402 if (m_part->xmlDocImpl()->focusNode())
00403 {
00404 d->tp->setBrush(Qt::NoBrush);
00405 d->tp->drawRect(m_part->xmlDocImpl()->focusNode()->getRect());
00406 }
00407 #endif
00408 d->tp->end();
00409
00410 p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
00411 py += PAINT_BUFFER_HEIGHT;
00412 }
00413 }
00414
00415 khtml::DrawContentsEvent event( p, ex, ey, ew, eh );
00416 QApplication::sendEvent( m_part, &event );
00417
00418 }
00419
00420 void KHTMLView::setMarginWidth(int w)
00421 {
00422
00423 _marginWidth = w;
00424 }
00425
00426 void KHTMLView::setMarginHeight(int h)
00427 {
00428
00429 _marginHeight = h;
00430 }
00431
00432 void KHTMLView::layout()
00433 {
00434 if( m_part->xmlDocImpl() ) {
00435 DOM::DocumentImpl *document = m_part->xmlDocImpl();
00436
00437 khtml::RenderRoot* root = static_cast<khtml::RenderRoot *>(document->renderer());
00438 if ( !root ) return;
00439
00440 if (document->isHTMLDocument()) {
00441 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
00442 if(body && body->renderer() && body->id() == ID_FRAMESET) {
00443 QScrollView::setVScrollBarMode(AlwaysOff);
00444 QScrollView::setHScrollBarMode(AlwaysOff);
00445 body->renderer()->setLayouted(false);
00446
00447
00448
00449
00450 }
00451 else if (!d->tooltip)
00452 d->tooltip = new KHTMLToolTip( this, d );
00453 }
00454
00455 _height = visibleHeight();
00456 _width = visibleWidth();
00457
00458
00459 root->setMinMaxKnown(false);
00460 root->setLayouted(false);
00461 root->layout();
00462
00463 }
00464 else
00465 _width = visibleWidth();
00466 }
00467
00468 void KHTMLView::closeChildDialogs()
00469 {
00470 QObjectList *dlgs = queryList("QDialog");
00471 for (QObject *dlg = dlgs->first(); dlg; dlg = dlgs->next())
00472 {
00473 KDialogBase* dlgbase = dynamic_cast<KDialogBase *>( dlg );
00474 if ( dlgbase ) {
00475 kdDebug(6000) << "closeChildDialogs: closing dialog " << dlgbase << endl;
00476
00477
00478 dlgbase->cancel();
00479 }
00480 else
00481 {
00482 kdWarning() << "closeChildDialogs: not a KDialogBase! Don't use QDialogs in KDE! " << static_cast<QWidget*>(dlg) << endl;
00483 static_cast<QWidget*>(dlg)->hide();
00484 }
00485 }
00486 delete dlgs;
00487 d->m_dialogsAllowed = false;
00488 }
00489
00490 bool KHTMLView::dialogsAllowed() {
00491 bool allowed = d->m_dialogsAllowed;
00492 KHTMLPart* p = m_part->parentPart();
00493 if (p && p->view())
00494 allowed &= p->view()->dialogsAllowed();
00495 return allowed;
00496 }
00497
00498 void KHTMLView::closeEvent( QCloseEvent* ev )
00499 {
00500 closeChildDialogs();
00501 QScrollView::closeEvent( ev );
00502 }
00503
00504
00505
00506
00508
00509 void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
00510 {
00511 if(!m_part->xmlDocImpl()) return;
00512 if (d->possibleTripleClick)
00513 {
00514 viewportMouseDoubleClickEvent( _mouse );
00515 return;
00516 }
00517
00518 int xm, ym;
00519 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
00520
00521
00522
00523 d->isDoubleClick = false;
00524
00525 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MousePress );
00526 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
00527
00528
00529
00530 if ( mev.innerNode.handle() && mev.innerNode.handle()->renderer() &&
00531 mev.innerNode.handle()->renderer()->isWidget() )
00532 return;
00533
00534 if (d->clickCount > 0 &&
00535 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
00536 d->clickCount++;
00537 else {
00538 d->clickCount = 1;
00539 d->clickX = xm;
00540 d->clickY = ym;
00541 }
00542
00543 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),true,
00544 d->clickCount,_mouse,true,DOM::NodeImpl::MousePress);
00545 if (mev.innerNode.handle())
00546 mev.innerNode.handle()->setPressed();
00547
00548 if (!swallowEvent) {
00549 khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
00550 QApplication::sendEvent( m_part, &event );
00551
00552 emit m_part->nodeActivated(mev.innerNode);
00553 }
00554 }
00555
00556 void KHTMLView::viewportMouseDoubleClickEvent( QMouseEvent *_mouse )
00557 {
00558 if(!m_part->xmlDocImpl()) return;
00559
00560 int xm, ym;
00561 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
00562
00563 kdDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym << endl;
00564
00565 d->isDoubleClick = true;
00566
00567 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseDblClick );
00568 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
00569
00570
00571
00572 if ( mev.innerNode.handle() && mev.innerNode.handle()->renderer() &&
00573 mev.innerNode.handle()->renderer()->isWidget() )
00574 return;
00575
00576
00577
00578 if (d->clickCount > 0 && d->clickX == xm && d->clickY == ym)
00579 d->clickCount++;
00580 else {
00581 d->clickCount = 1;
00582 d->clickX = xm;
00583 d->clickY = ym;
00584 }
00585 kdDebug() << "KHTMLView::viewportMouseDoubleClickEvent clickCount=" << d->clickCount << endl;
00586 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),true,
00587 d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick);
00588
00589 if (mev.innerNode.handle())
00590 mev.innerNode.handle()->setPressed();
00591
00592 if (!swallowEvent) {
00593 khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount );
00594 QApplication::sendEvent( m_part, &event );
00595 }
00596
00597 d->possibleTripleClick=true;
00598 QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(tripleClickTimeout()));
00599 }
00600
00601 void KHTMLView::tripleClickTimeout()
00602 {
00603 d->possibleTripleClick = false;
00604 d->clickCount = 0;
00605 }
00606
00607 void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse )
00608 {
00609
00610 if(!m_part->xmlDocImpl()) return;
00611
00612 int xm, ym;
00613 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
00614
00615 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseMove );
00616 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
00617
00618
00619
00620 if ( mev.innerNode.handle() && mev.innerNode.handle()->renderer() &&
00621 mev.innerNode.handle()->renderer()->isWidget() )
00622 return;
00623
00624 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,mev.innerNode.handle(),false,
00625 0,_mouse,true,DOM::NodeImpl::MouseMove);
00626
00627 if (d->clickCount > 0 &&
00628 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > QApplication::startDragDistance()) {
00629 d->clickCount = 0;
00630 }
00631
00632
00633 m_part->executeScheduledScript();
00634
00635 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
00636 khtml::RenderStyle* style = (r && r->style()) ? r->style() : 0;
00637 QCursor c;
00638 switch ( style ? style->cursor() : CURSOR_AUTO) {
00639 case CURSOR_AUTO:
00640 if ( mev.url.length() && m_part->settings()->changeCursor() )
00641 c = m_part->urlCursor();
00642
00643 if (r && r->isFrameSet() && !static_cast<RenderFrameSet*>(r)->noResize())
00644 c = QCursor(static_cast<RenderFrameSet*>(r)->cursorShape());
00645
00646 break;
00647 case CURSOR_CROSS:
00648 c = KCursor::crossCursor();
00649 break;
00650 case CURSOR_POINTER:
00651 c = m_part->urlCursor();
00652 break;
00653 case CURSOR_PROGRESS:
00654 c = KCursor::workingCursor();
00655 break;
00656 case CURSOR_MOVE:
00657 c = KCursor::sizeAllCursor();
00658 break;
00659 case CURSOR_E_RESIZE:
00660 case CURSOR_W_RESIZE:
00661 c = KCursor::sizeHorCursor();
00662 break;
00663 case CURSOR_N_RESIZE:
00664 case CURSOR_S_RESIZE:
00665 c = KCursor::sizeVerCursor();
00666 break;
00667 case CURSOR_NE_RESIZE:
00668 case CURSOR_SW_RESIZE:
00669 c = KCursor::sizeBDiagCursor();
00670 break;
00671 case CURSOR_NW_RESIZE:
00672 case CURSOR_SE_RESIZE:
00673 c = KCursor::sizeFDiagCursor();
00674 break;
00675 case CURSOR_TEXT:
00676 c = KCursor::ibeamCursor();
00677 break;
00678 case CURSOR_WAIT:
00679 c = KCursor::waitCursor();
00680 break;
00681 case CURSOR_HELP:
00682 c = KCursor::whatsThisCursor();
00683 break;
00684 case CURSOR_DEFAULT:
00685 break;
00686 }
00687
00688 if ( viewport()->cursor().handle() != c.handle() ) {
00689 if( c.handle() == KCursor::arrowCursor().handle()) {
00690 for (KHTMLPart* p = m_part; p; p = p->parentPart())
00691 p->view()->viewport()->unsetCursor();
00692 }
00693 else
00694 viewport()->setCursor( c );
00695 }
00696
00697 d->prevMouseX = xm;
00698 d->prevMouseY = ym;
00699
00700 if (!swallowEvent) {
00701 khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
00702 QApplication::sendEvent( m_part, &event );
00703 }
00704 }
00705
00706 void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse )
00707 {
00708 if ( !m_part->xmlDocImpl() ) return;
00709
00710 int xm, ym;
00711 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
00712
00713
00714
00715 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseRelease );
00716 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
00717
00718
00719
00720 if ( mev.innerNode.handle() && mev.innerNode.handle()->renderer() &&
00721 mev.innerNode.handle()->renderer()->isWidget() )
00722 return;
00723
00724 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,mev.innerNode.handle(),true,
00725 d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease);
00726
00727 if (d->clickCount > 0 &&
00728 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
00729 dispatchMouseEvent(EventImpl::CLICK_EVENT,mev.innerNode.handle(),true,
00730 d->clickCount,_mouse,true,DOM::NodeImpl::MouseRelease);
00731
00732 if (mev.innerNode.handle())
00733 mev.innerNode.handle()->setPressed(false);
00734
00735 if (!swallowEvent) {
00736 khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
00737 QApplication::sendEvent( m_part, &event );
00738 }
00739 }
00740
00741 void KHTMLView::keyPressEvent( QKeyEvent *_ke )
00742 {
00743
00744 if (m_part->xmlDocImpl()) {
00745 if (m_part->xmlDocImpl()->focusNode())
00746 if (m_part->xmlDocImpl()->focusNode()->dispatchKeyEvent(_ke))
00747 {
00748 _ke->accept();
00749 return;
00750 }
00751 if (!_ke->text().isNull() && m_part->xmlDocImpl()->getHTMLEventListener(EventImpl::KHTML_KEYDOWN_EVENT))
00752 if (m_part->xmlDocImpl()->documentElement()->dispatchKeyEvent(_ke))
00753 {
00754 _ke->accept();
00755 return;
00756 }
00757 }
00758 int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
00759 if (_ke->state() & Qt::ShiftButton)
00760 switch(_ke->key())
00761 {
00762 case Key_Space:
00763 if ( d->vmode == QScrollView::AlwaysOff )
00764 _ke->accept();
00765 else
00766 scrollBy( 0, -clipper()->height() - offs );
00767 break;
00768
00769 case Key_Down:
00770 case Key_J:
00771 d->adjustScroller(this, KHTMLViewPrivate::ScrollDown, KHTMLViewPrivate::ScrollUp);
00772 break;
00773
00774 case Key_Up:
00775 case Key_K:
00776 d->adjustScroller(this, KHTMLViewPrivate::ScrollUp, KHTMLViewPrivate::ScrollDown);
00777 break;
00778
00779 case Key_Left:
00780 case Key_H:
00781 d->adjustScroller(this, KHTMLViewPrivate::ScrollLeft, KHTMLViewPrivate::ScrollRight);
00782 break;
00783
00784 case Key_Right:
00785 case Key_L:
00786 d->adjustScroller(this, KHTMLViewPrivate::ScrollRight, KHTMLViewPrivate::ScrollLeft);
00787 break;
00788 }
00789 else
00790 switch ( _ke->key() )
00791 {
00792 case Key_Down:
00793 case Key_J:
00794 if ( d->vmode == QScrollView::AlwaysOff )
00795 _ke->accept();
00796 else {
00797 if (d->scrollTimerId)
00798 d->newScrollTimer(this, 0);
00799 else
00800 scrollBy( 0, 10 );
00801 }
00802 break;
00803
00804 case Key_Space:
00805 case Key_Next:
00806 if ( d->vmode == QScrollView::AlwaysOff )
00807 _ke->accept();
00808 else
00809 scrollBy( 0, clipper()->height() - offs );
00810 break;
00811
00812 case Key_Up:
00813 case Key_K:
00814 if ( d->vmode == QScrollView::AlwaysOff )
00815 _ke->accept();
00816 else {
00817 if (d->scrollTimerId)
00818 d->newScrollTimer(this, 0);
00819 else
00820 scrollBy( 0, -10 );
00821 }
00822 break;
00823
00824 case Key_Prior:
00825 if ( d->vmode == QScrollView::AlwaysOff )
00826 _ke->accept();
00827 else
00828 scrollBy( 0, -clipper()->height() + offs );
00829 break;
00830 case Key_Right:
00831 case Key_L:
00832 if ( d->hmode == QScrollView::AlwaysOff )
00833 _ke->accept();
00834 else {
00835 if (d->scrollTimerId)
00836 d->newScrollTimer(this, 0);
00837 else
00838 scrollBy( 10, 0 );
00839 }
00840 break;
00841 case Key_Left:
00842 case Key_H:
00843 if ( d->hmode == QScrollView::AlwaysOff )
00844 _ke->accept();
00845 else {
00846 if (d->scrollTimerId)
00847 d->newScrollTimer(this, 0);
00848 else
00849 scrollBy( -10, 0 );
00850 }
00851 break;
00852 case Key_Enter:
00853 case Key_Return:
00854
00855
00856
00857 if (m_part->xmlDocImpl()) {
00858 NodeImpl *n = m_part->xmlDocImpl()->focusNode();
00859 if (n)
00860 n->setActive();
00861 d->originalNode = n;
00862 }
00863 break;
00864 case Key_Home:
00865 if ( d->vmode == QScrollView::AlwaysOff )
00866 _ke->accept();
00867 else
00868 setContentsPos( 0, 0 );
00869 break;
00870 case Key_End:
00871 if ( d->vmode == QScrollView::AlwaysOff )
00872 _ke->accept();
00873 else
00874 setContentsPos( 0, contentsHeight() - visibleHeight() );
00875 break;
00876 case Key_Shift:
00877
00878 _ke->ignore();
00879 return;
00880 default:
00881 if (d->scrollTimerId)
00882 d->newScrollTimer(this, 0);
00883 _ke->ignore();
00884 return;
00885 }
00886 _ke->accept();
00887 }
00888
00889 void KHTMLView::keyReleaseEvent(QKeyEvent *_ke)
00890 {
00891 if(m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()) {
00892
00893
00894
00895
00896
00897
00898
00899
00900 Q_UNUSED(_ke);
00901 }
00902 }
00903
00904 void KHTMLView::contentsContextMenuEvent ( QContextMenuEvent * )
00905 {
00906
00907 #if 0
00908 if (!m_part->xmlDocImpl()) return;
00909 int xm = _ce->x();
00910 int ym = _ce->y();
00911
00912 DOM::NodeImpl::MouseEvent mev( _ce->state(), DOM::NodeImpl::MouseMove );
00913 m_part->xmlDocImpl()->prepareMouseEvent( xm, ym, &mev );
00914
00915 NodeImpl *targetNode = mev.innerNode.handle();
00916 if (targetNode && targetNode->renderer() && targetNode->renderer()->isWidget()) {
00917 int absx = 0;
00918 int absy = 0;
00919 targetNode->renderer()->absolutePosition(absx,absy);
00920 QPoint pos(xm-absx,ym-absy);
00921
00922 QWidget *w = static_cast<RenderWidget*>(targetNode->renderer())->widget();
00923 QContextMenuEvent cme(_ce->reason(),pos,_ce->globalPos(),_ce->state());
00924 setIgnoreEvents(true);
00925 QApplication::sendEvent(w,&cme);
00926 setIgnoreEvents(false);
00927 }
00928 #endif
00929 }
00930
00931 bool KHTMLView::focusNextPrevChild( bool next )
00932 {
00933
00934 if (m_part->xmlDocImpl()) {
00935 focusNextPrevNode(next);
00936 if (m_part->xmlDocImpl()->focusNode() != 0)
00937 return true;
00938 }
00939
00940
00941 if (m_part->parentPart() && m_part->parentPart()->view()) {
00942 return m_part->parentPart()->view()->focusNextPrevChild(next);
00943 }
00944
00945 return QWidget::focusNextPrevChild(next);
00946 }
00947
00948 void KHTMLView::doAutoScroll()
00949 {
00950 QPoint pos = QCursor::pos();
00951 pos = viewport()->mapFromGlobal( pos );
00952
00953 int xm, ym;
00954 viewportToContents(pos.x(), pos.y(), xm, ym);
00955
00956 pos = QPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
00957 if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
00958 (pos.x() < 0) || (pos.x() > visibleWidth()) )
00959 {
00960 ensureVisible( xm, ym, 0, 5 );
00961 }
00962 }
00963
00964 DOM::NodeImpl *KHTMLView::nodeUnderMouse() const
00965 {
00966 return d->underMouse;
00967 }
00968
00969 bool KHTMLView::scrollTo(const QRect &bounds)
00970 {
00971 d->scrollingSelf = true;
00972
00973 int x, y, xe, ye;
00974 x = bounds.left();
00975 y = bounds.top();
00976 xe = bounds.right();
00977 ye = bounds.bottom();
00978
00979
00980
00981 int deltax;
00982 int deltay;
00983
00984 int curHeight = visibleHeight();
00985 int curWidth = visibleWidth();
00986
00987 if (ye-y>curHeight-d->borderY)
00988 ye = y + curHeight - d->borderY;
00989
00990 if (xe-x>curWidth-d->borderX)
00991 xe = x + curWidth - d->borderX;
00992
00993
00994 if (x < contentsX() + d->borderX )
00995 deltax = x - contentsX() - d->borderX;
00996
00997 else if (xe + d->borderX > contentsX() + curWidth)
00998 deltax = xe + d->borderX - ( contentsX() + curWidth );
00999 else
01000 deltax = 0;
01001
01002
01003 if (y < contentsY() + d->borderY)
01004 deltay = y - contentsY() - d->borderY;
01005
01006 else if (ye + d->borderY > contentsY() + curHeight)
01007 deltay = ye + d->borderY - ( contentsY() + curHeight );
01008 else
01009 deltay = 0;
01010
01011 int maxx = curWidth-d->borderX;
01012 int maxy = curHeight-d->borderY;
01013
01014 int scrollX,scrollY;
01015
01016 scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx);
01017 scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy);
01018
01019 if (contentsX() + scrollX < 0)
01020 scrollX = -contentsX();
01021 else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
01022 scrollX = contentsWidth() - visibleWidth() - contentsX();
01023
01024 if (contentsY() + scrollY < 0)
01025 scrollY = -contentsY();
01026 else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
01027 scrollY = contentsHeight() - visibleHeight() - contentsY();
01028
01029 scrollBy(scrollX, scrollY);
01030
01031
01032
01033
01034 if (scrollX<0)
01035 scrollX=-scrollX;
01036 if (scrollY<0)
01037 scrollY=-scrollY;
01038
01039 d->scrollingSelf = false;
01040
01041 if ( (scrollX!=maxx) && (scrollY!=maxy) )
01042 return true;
01043 else return false;
01044
01045 }
01046
01047 void KHTMLView::focusNextPrevNode(bool next)
01048 {
01049
01050
01051
01052
01053
01054 DocumentImpl *doc = m_part->xmlDocImpl();
01055 NodeImpl *oldFocusNode = doc->focusNode();
01056 NodeImpl *newFocusNode;
01057
01058
01059 if (next)
01060 newFocusNode = doc->nextFocusNode(oldFocusNode);
01061 else
01062 newFocusNode = doc->previousFocusNode(oldFocusNode);
01063
01064
01065
01066 if (!oldFocusNode && newFocusNode && d->scrollBarMoved) {
01067
01068 kdDebug(6000) << " searching for visible link" << endl;
01069
01070 bool visible = false;
01071 NodeImpl *toFocus = newFocusNode;
01072 while (!visible && toFocus) {
01073 QRect focusNodeRect = toFocus->getRect();
01074 if ((focusNodeRect.left() > contentsX()) && (focusNodeRect.right() < contentsX() + visibleWidth()) &&
01075 (focusNodeRect.top() > contentsY()) && (focusNodeRect.bottom() < contentsY() + visibleHeight())) {
01076
01077 visible = true;
01078 }
01079 else {
01080
01081 if (next)
01082 toFocus = doc->nextFocusNode(toFocus);
01083 else
01084 toFocus = doc->previousFocusNode(toFocus);
01085 }
01086 }
01087
01088 if (toFocus)
01089 newFocusNode = toFocus;
01090 }
01091
01092 d->scrollBarMoved = false;
01093
01094 if (!newFocusNode)
01095 {
01096
01097 if (next)
01098 scrollTo(QRect(contentsX()+visibleWidth()/2,contentsHeight(),0,0));
01099 else
01100 scrollTo(QRect(contentsX()+visibleWidth()/2,0,0,0));
01101 }
01102 else
01103
01104 {
01105 if (oldFocusNode)
01106 {
01107 if (!scrollTo(newFocusNode->getRect()))
01108 return;
01109 }
01110 else
01111 {
01112 ensureVisible(contentsX(), next?0:contentsHeight());
01113
01114 }
01115 }
01116
01117 m_part->xmlDocImpl()->setFocusNode(newFocusNode);
01118 emit m_part->nodeActivated(Node(newFocusNode));
01119
01120 #if 0
01121 if (newFocusNode) {
01122
01123
01124
01125
01126
01127
01128 HTMLAnchorElementImpl *anchor = 0;
01129 if ((newFocusNode->id() == ID_A || newFocusNode->id() == ID_AREA))
01130 anchor = static_cast<HTMLAnchorElementImpl *>(newFocusNode);
01131
01132 if (anchor && !anchor->areaHref().isNull())
01133 m_part->overURL(anchor->areaHref().string(), 0);
01134 else
01135 m_part->overURL(QString(), 0);
01136 }
01137 #endif
01138 }
01139
01140 void KHTMLView::setMediaType( const QString &medium )
01141 {
01142 m_medium = medium;
01143 }
01144
01145 QString KHTMLView::mediaType() const
01146 {
01147 return m_medium;
01148 }
01149
01150 void KHTMLView::setWidgetVisible(RenderWidget* w, bool vis)
01151 {
01152 if (vis) {
01153 assert(w->widget());
01154 d->visibleWidgets.replace(w, w->widget());
01155 }
01156 else
01157 d->visibleWidgets.remove(w);
01158 }
01159
01160 void KHTMLView::print()
01161 {
01162 if(!m_part->xmlDocImpl()) return;
01163 khtml::RenderRoot *root = static_cast<khtml::RenderRoot *>(m_part->xmlDocImpl()->renderer());
01164 if(!root) return;
01165
01166
01167 KPrinter *printer = new KPrinter(QPrinter::PrinterResolution);
01168 printer->addDialogPage(new KHTMLPrintSettings());
01169 if(printer->setup(this)) {
01170 viewport()->setCursor( waitCursor );
01171
01172 printer->setFullPage(false);
01173 printer->setCreator("KDE 3.0 HTML Library");
01174 QString docname = m_part->xmlDocImpl()->URL();
01175 if ( !docname.isEmpty() )
01176 printer->setDocName(KStringHandler::csqueeze(docname, 80));
01177
01178 QPainter *p = new QPainter;
01179 p->begin( printer );
01180 khtml::setPrintPainter( p );
01181
01182 m_part->xmlDocImpl()->setPaintDevice( printer );
01183 QString oldMediaType = mediaType();
01184 setMediaType( "print" );
01185
01186
01187
01188 m_part->xmlDocImpl()->setPrintStyleSheet( printer->option("app-khtml-printfriendly") == "true" ?
01189 "* { background-image: none !important;"
01190 " background-color: white !important;"
01191 " color: black !important; }"
01192 "body { margin: 0px !important; }"
01193 "html { margin: 0px !important; }" :
01194 "body { margin: 0px !important; }"
01195 "html { margin: 0px !important; }"
01196 );
01197
01198 QPaintDeviceMetrics metrics( printer );
01199
01200
01201
01202
01203
01204
01205 kdDebug(6000) << "printing: physical page width = " << metrics.width()
01206 << " height = " << metrics.height() << endl;
01207 root->setPrintingMode(true);
01208 root->setWidth(metrics.width());
01209
01210 m_part->xmlDocImpl()->styleSelector()->computeFontSizes(&metrics, 100);
01211 m_part->xmlDocImpl()->updateStyleSelector();
01212 root->setPrintImages( printer->option("app-khtml-printimages") == "true");
01213 root->setLayouted( false );
01214 root->setMinMaxKnown( false );
01215 root->layout();
01216
01217 bool printHeader = (printer->option("app-khtml-printheader") == "true");
01218
01219 int headerHeight = 0;
01220 QFont headerFont("helvetica", 8);
01221
01222 QString headerLeft = KGlobal::locale()->formatDate(QDate::currentDate(),true);
01223 QString headerMid = docname;
01224 QString headerRight;
01225
01226 if (printHeader)
01227 {
01228 p->setFont(headerFont);
01229 headerHeight = (p->fontMetrics().lineSpacing() * 3) / 2;
01230 }
01231
01232
01233 kdDebug(6000) << "printing: html page width = " << root->docWidth()
01234 << " height = " << root->docHeight() << endl;
01235 kdDebug(6000) << "printing: margins left = " << printer->margins().width()
01236 << " top = " << printer->margins().height() << endl;
01237 kdDebug(6000) << "printing: paper width = " << metrics.width()
01238 << " height = " << metrics.height() << endl;
01239
01240
01241 int pageHeight = metrics.height();
01242 int pageWidth = metrics.width();
01243 p->setClipRect(0,0, pageWidth, pageHeight);
01244
01245 pageHeight -= headerHeight;
01246
01247 bool scalePage = false;
01248 double scale = 0.0;
01249 #ifndef QT_NO_TRANSFORMATIONS
01250 if(root->docWidth() > metrics.width()) {
01251 scalePage = true;
01252 scale = ((double) metrics.width())/((double) root->docWidth());
01253 pageHeight = (int) (pageHeight/scale);
01254 pageWidth = (int) (pageWidth/scale);
01255 headerHeight = (int) (headerHeight/scale);
01256 }
01257 #endif
01258 kdDebug(6000) << "printing: scaled html width = " << pageWidth
01259 << " height = " << pageHeight << endl;
01260
01261
01262 if (printHeader)
01263 {
01264 int available_width = metrics.width() - 10 -
01265 2 * QMAX(p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(),
01266 p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width());
01267 if (available_width < 150)
01268 available_width = 150;
01269 int mid_width;
01270 int squeeze = 120;
01271 do {
01272 headerMid = KStringHandler::csqueeze(docname, squeeze);
01273 mid_width = p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width();
01274 squeeze -= 10;
01275 } while (mid_width > available_width);
01276 }
01277
01278 int top = 0;
01279 int page = 1;
01280 while(top < root->docHeight()) {
01281 if(top > 0) printer->newPage();
01282 if (printHeader)
01283 {
01284 int dy = p->fontMetrics().lineSpacing();
01285 p->setPen(Qt::black);
01286 p->setFont(headerFont);
01287
01288 headerRight = QString("#%1").arg(page);
01289
01290 p->drawText(0, 0, metrics.width(), dy, Qt::AlignLeft, headerLeft);
01291 p->drawText(0, 0, metrics.width(), dy, Qt::AlignHCenter, headerMid);
01292 p->drawText(0, 0, metrics.width(), dy, Qt::AlignRight, headerRight);
01293 }
01294
01295 #ifndef QT_NO_TRANSFORMATIONS
01296 if (scalePage)
01297 p->scale(scale, scale);
01298 #endif
01299 p->translate(0, headerHeight-top);
01300
01301 root->setTruncatedAt(top+pageHeight);
01302
01303 root->paint(p, 0, top, pageWidth, pageHeight, 0, 0);
01304 if (top + pageHeight >= root->docHeight())
01305 break;
01306
01307 top = root->truncatedAt();
01308 p->resetXForm();
01309 page++;
01310 }
01311
01312 p->end();
01313 delete p;
01314
01315
01316 root->setPrintingMode(false);
01317 khtml::setPrintPainter( 0 );
01318 setMediaType( oldMediaType );
01319 m_part->xmlDocImpl()->setPaintDevice( this );
01320 m_part->xmlDocImpl()->styleSelector()->computeFontSizes(m_part->xmlDocImpl()->paintDeviceMetrics(), m_part->zoomFactor());
01321 m_part->xmlDocImpl()->updateStyleSelector();
01322 viewport()->unsetCursor();
01323 }
01324 delete printer;
01325 }
01326
01327 void KHTMLView::slotPaletteChanged()
01328 {
01329 if(!m_part->xmlDocImpl()) return;
01330 DOM::DocumentImpl *document = m_part->xmlDocImpl();
01331 if (!document->isHTMLDocument()) return;
01332 khtml::RenderRoot *root = static_cast<khtml::RenderRoot *>(document->renderer());
01333 if(!root) return;
01334 root->style()->resetPalette();
01335 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
01336 if(!body) return;
01337 body->setChanged(true);
01338 body->recalcStyle( NodeImpl::Force );
01339 }
01340
01341 void KHTMLView::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
01342 {
01343 if(!m_part->xmlDocImpl()) return;
01344 khtml::RenderRoot *root = static_cast<khtml::RenderRoot *>(m_part->xmlDocImpl()->renderer());
01345 if(!root) return;
01346
01347 m_part->xmlDocImpl()->setPaintDevice(p->device());
01348 root->setPrintingMode(true);
01349 root->setWidth(rc.width());
01350
01351 p->save();
01352 p->setClipRect(rc);
01353 p->translate(rc.left(), rc.top());
01354 double scale = ((double) rc.width()/(double) root->docWidth());
01355 int height = (int) ((double) rc.height() / scale);
01356 #ifndef QT_NO_TRANSFORMATIONS
01357 p->scale(scale, scale);
01358 #endif
01359
01360 root->paint(p, 0, yOff, root->docWidth(), height, 0, 0);
01361 if (more)
01362 *more = yOff + height < root->docHeight();
01363 p->restore();
01364
01365 root->setPrintingMode(false);
01366 m_part->xmlDocImpl()->setPaintDevice( this );
01367 }
01368
01369
01370 void KHTMLView::useSlowRepaints()
01371 {
01372 kdDebug(0) << "slow repaints requested" << endl;
01373 d->useSlowRepaints = true;
01374 setStaticBackground(true);
01375 }
01376
01377
01378 void KHTMLView::setVScrollBarMode ( ScrollBarMode mode )
01379 {
01380 #ifndef KHTML_NO_SCROLLBARS
01381 d->vmode = mode;
01382 QScrollView::setVScrollBarMode(mode);
01383 #else
01384 Q_UNUSED( mode );
01385 #endif
01386 }
01387
01388 void KHTMLView::setHScrollBarMode ( ScrollBarMode mode )
01389 {
01390 #ifndef KHTML_NO_SCROLLBARS
01391 d->hmode = mode;
01392 QScrollView::setHScrollBarMode(mode);
01393 #else
01394 Q_UNUSED( mode );
01395 #endif
01396 }
01397
01398 void KHTMLView::restoreScrollBar()
01399 {
01400 int ow = visibleWidth();
01401 QScrollView::setVScrollBarMode(d->vmode);
01402 if (visibleWidth() != ow)
01403 layout();
01404 d->prevScrollbarVisible = verticalScrollBar()->isVisible();
01405 }
01406
01407 QStringList KHTMLView::formCompletionItems(const QString &name) const
01408 {
01409 if (!m_part->settings()->isFormCompletionEnabled())
01410 return QStringList();
01411 if (!d->formCompletions)
01412 d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
01413 return d->formCompletions->readListEntry(name);
01414 }
01415
01416 void KHTMLView::clearCompletionHistory(const QString& name)
01417 {
01418 if (!d->formCompletions)
01419 {
01420 d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
01421 }
01422 d->formCompletions->writeEntry(name, "");
01423 d->formCompletions->sync();
01424 }
01425
01426 void KHTMLView::addFormCompletionItem(const QString &name, const QString &value)
01427 {
01428 if (!m_part->settings()->isFormCompletionEnabled())
01429 return;
01430
01431
01432
01433 bool cc_number(true);
01434 for (unsigned int i = 0; i < value.length(); ++i)
01435 {
01436 QChar c(value[i]);
01437 if (!c.isNumber() && c != '-' && !c.isSpace())
01438 {
01439 cc_number = false;
01440 break;
01441 }
01442 }
01443 if (cc_number)
01444 return;
01445 QStringList items = formCompletionItems(name);
01446 if (!items.contains(value))
01447 items.prepend(value);
01448 while ((int)items.count() > m_part->settings()->maxFormCompletionItems())
01449 items.remove(items.fromLast());
01450 d->formCompletions->writeEntry(name, items);
01451 }
01452
01453 bool KHTMLView::dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode, bool cancelable,
01454 int detail,QMouseEvent *_mouse, bool setUnder,
01455 int mouseEventType)
01456 {
01457 if (d->underMouse)
01458 d->underMouse->deref();
01459 d->underMouse = targetNode;
01460 if (d->underMouse)
01461 d->underMouse->ref();
01462
01463 int exceptioncode = 0;
01464 int mx, my;
01465 viewportToContents(_mouse->x(), _mouse->y(), mx, my);
01466
01467
01468
01469 int clientX = mx - contentsX();
01470 int clientY = my - contentsY();
01471 int screenX = _mouse->globalX();
01472 int screenY = _mouse->globalY();
01473 int button = -1;
01474 switch (_mouse->button()) {
01475 case LeftButton:
01476 button = 0;
01477 break;
01478 case MidButton:
01479 button = 1;
01480 break;
01481 case RightButton:
01482 button = 2;
01483 break;
01484 default:
01485 break;
01486 }
01487 bool ctrlKey = (_mouse->state() & ControlButton);
01488 bool altKey = (_mouse->state() & AltButton);
01489 bool shiftKey = (_mouse->state() & ShiftButton);
01490 bool metaKey = (_mouse->state() & MetaButton);
01491
01492
01493 if (setUnder && (d->prevMouseX != mx || d->prevMouseY != my)) {
01494
01495
01496
01497 NodeImpl *oldUnder = 0;
01498 if (d->prevMouseX >= 0 && d->prevMouseY >= 0) {
01499 NodeImpl::MouseEvent mev( _mouse->stateAfter(), static_cast<NodeImpl::MouseEventType>(mouseEventType));
01500 m_part->xmlDocImpl()->prepareMouseEvent( true, d->prevMouseX, d->prevMouseY, &mev );
01501 oldUnder = mev.innerNode.handle();
01502 }
01503 if (oldUnder != targetNode) {
01504
01505 if (oldUnder){
01506 oldUnder->ref();
01507 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOUT_EVENT,
01508 true,true,m_part->xmlDocImpl()->defaultView(),
01509 0,screenX,screenY,clientX,clientY,
01510 ctrlKey,altKey,shiftKey,metaKey,
01511 button,targetNode);
01512 me->ref();
01513 oldUnder->dispatchEvent(me,exceptioncode,true);
01514 me->deref();
01515 }
01516
01517
01518 if (targetNode) {
01519 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOVER_EVENT,
01520 true,true,m_part->xmlDocImpl()->defaultView(),
01521 0,screenX,screenY,clientX,clientY,
01522 ctrlKey,altKey,shiftKey,metaKey,
01523 button,oldUnder);
01524
01525 me->ref();
01526 targetNode->dispatchEvent(me,exceptioncode,true);
01527 me->deref();
01528 }
01529
01530 if (oldUnder)
01531 oldUnder->deref();
01532 }
01533 }
01534
01535 bool swallowEvent = false;
01536
01537 if (targetNode) {
01538
01539 MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
01540 true,cancelable,m_part->xmlDocImpl()->defaultView(),
01541 detail,screenX,screenY,clientX,clientY,
01542 ctrlKey,altKey,shiftKey,metaKey,
01543 button,0);
01544 me->ref();
01545 targetNode->dispatchEvent(me,exceptioncode,true);
01546 if (me->defaultHandled() || me->defaultPrevented())
01547 swallowEvent = true;
01548 me->deref();
01549
01550 if( eventId == EventImpl::MOUSEDOWN_EVENT ) {
01551 if (targetNode->isSelectable())
01552 m_part->xmlDocImpl()->setFocusNode(targetNode);
01553 else
01554 m_part->xmlDocImpl()->setFocusNode(0);
01555 }
01556 }
01557
01558 return swallowEvent;
01559 }
01560
01561 void KHTMLView::setIgnoreWheelEvents( bool e )
01562 {
01563 d->ignoreWheelEvents = e;
01564 }
01565
01566 #ifndef QT_NO_WHEELEVENT
01567
01568 void KHTMLView::viewportWheelEvent(QWheelEvent* e)
01569 {
01570 if ( ( e->state() & ShiftButton ) == ShiftButton )
01571 {
01572 emit zoomView( e->delta() );
01573 e->accept();
01574 }
01575 else if ( d->ignoreWheelEvents && !verticalScrollBar()->isVisible()
01576 && m_part->parentPart() ) {
01577 if ( m_part->parentPart()->view() )
01578 m_part->parentPart()->view()->wheelEvent( e );
01579 e->ignore();
01580 }
01581 else if ( d->vmode == QScrollView::AlwaysOff ) {
01582 e->accept();
01583 }
01584 else {
01585 d->scrollBarMoved = true;
01586 QScrollView::viewportWheelEvent( e );
01587
01588 QMouseEvent *tempEvent = new QMouseEvent( QEvent::MouseMove, QPoint(-1,-1), QPoint(-1,-1), Qt::NoButton, e->state() );
01589 emit viewportMouseMoveEvent ( tempEvent );
01590 delete tempEvent;
01591 }
01592
01593 }
01594 #endif
01595
01596 void KHTMLView::dragEnterEvent( QDragEnterEvent* ev )
01597 {
01598
01599
01600
01601 if ( m_part->parentPart() )
01602 {
01603
01604 if ( QUriDrag::canDecode( ev ) )
01605 {
01606 KURL::List lstDragURLs;
01607 bool ok = KURLDrag::decode( ev, lstDragURLs );
01608 QObjectList *children = this->queryList( "QWidget" );
01609
01610 if ( ok &&
01611 !lstDragURLs.first().url().contains( "javascript:", false ) &&
01612 ev->source() != this &&
01613 children &&
01614 children->findRef( ev->source() ) == -1 )
01615 ev->acceptAction();
01616
01617 delete children;
01618 }
01619 }
01620 QScrollView::dragEnterEvent( ev );
01621 }
01622
01623 void KHTMLView::dropEvent( QDropEvent *ev )
01624 {
01625
01626
01627
01628 if ( m_part->parentPart() )
01629 {
01630 KURL::List lstDragURLs;
01631 bool ok = KURLDrag::decode( ev, lstDragURLs );
01632
01633 KHTMLPart* part = m_part->parentPart();
01634 while ( part && part->parentPart() )
01635 part = part->parentPart();
01636 KParts::BrowserExtension *ext = part->browserExtension();
01637 if ( ok && ext && lstDragURLs.first().isValid() )
01638 emit ext->openURLRequest( lstDragURLs.first() );
01639 }
01640 QScrollView::dropEvent( ev );
01641 }
01642
01643 void KHTMLView::focusOutEvent( QFocusEvent *e )
01644 {
01645 if(m_part) m_part->stopAutoScroll();
01646 QScrollView::focusOutEvent( e );
01647 }
01648
01649 void KHTMLView::slotScrollBarMoved()
01650 {
01651 if (!d->scrollingSelf)
01652 d->scrollBarMoved = true;
01653 }
01654
01655 void KHTMLView::timerEvent ( QTimerEvent *e )
01656 {
01657
01658 if (e->timerId() == d->scrollTimerId) {
01659 switch (d->scrollDirection) {
01660 case KHTMLViewPrivate::ScrollDown:
01661 if (contentsY() + visibleHeight () >= contentsHeight())
01662 d->newScrollTimer(this, 0);
01663 else
01664 scrollBy( 0, d->scrollBy );
01665 break;
01666 case KHTMLViewPrivate::ScrollUp:
01667 if (contentsY() <= 0)
01668 d->newScrollTimer(this, 0);
01669 else
01670 scrollBy( 0, -d->scrollBy );
01671 break;
01672 case KHTMLViewPrivate::ScrollRight:
01673 if (contentsX() + visibleWidth () >= contentsWidth())
01674 d->newScrollTimer(this, 0);
01675 else
01676 scrollBy( d->scrollBy, 0 );
01677 break;
01678 case KHTMLViewPrivate::ScrollLeft:
01679 if (contentsX() <= 0)
01680 d->newScrollTimer(this, 0);
01681 else
01682 scrollBy( -d->scrollBy, 0 );
01683 break;
01684 }
01685 return;
01686 }
01687 if (e->timerId()==d->timerId)
01688 {
01689 d->firstRelayout = false;
01690 killTimer(d->timerId);
01691
01692 d->dirtyLayout = true;
01693 d->layoutSchedulingEnabled=false;
01694 layout();
01695 d->layoutSchedulingEnabled=true;
01696
01697 d->timerId = 0;
01698
01699
01700
01701 d->updateRect = QRect(contentsX(),contentsY(),visibleWidth(),visibleHeight());
01702 }
01703
01704 if( m_part->xmlDocImpl() ) {
01705 DOM::DocumentImpl *document = m_part->xmlDocImpl();
01706 khtml::RenderRoot* root = static_cast<khtml::RenderRoot *>(document->renderer());
01707
01708 if ( !root->layouted() ) {
01709 killTimer(d->repaintTimerId);
01710 d->repaintTimerId = 0;
01711 scheduleRelayout();
01712 return;
01713 }
01714 }
01715
01716 setStaticBackground(d->useSlowRepaints);
01717
01718
01719 killTimer(d->repaintTimerId);
01720 updateContents( d->updateRect );
01721
01722 if (d->dirtyLayout && !d->visibleWidgets.isEmpty()) {
01723 d->dirtyLayout = false;
01724
01725 QRect visibleRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
01726 QPtrList<RenderWidget> toRemove;
01727 QWidget* w;
01728 for (QPtrDictIterator<QWidget> it(d->visibleWidgets); it.current(); ++it) {
01729 int xp = 0, yp = 0;
01730 w = it.current();
01731 RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
01732 if (!rw->absolutePosition(xp, yp) ||
01733 !visibleRect.intersects(QRect(xp, yp, w->width(), w->height())))
01734 toRemove.append(rw);
01735 }
01736 for (RenderWidget* r = toRemove.first(); r; r = toRemove.next())
01737 if ( (w = d->visibleWidgets.take(r) ) )
01738 addChild(w, 0, -500000);
01739 }
01740
01741 d->repaintTimerId = 0;
01742 }
01743
01744 void KHTMLView::scheduleRelayout()
01745 {
01746 if (!d->layoutSchedulingEnabled || d->timerId)
01747 return;
01748
01749 d->timerId = startTimer( m_part->xmlDocImpl() && m_part->xmlDocImpl()->parsing()
01750 ? 1000 : 0 );
01751 }
01752
01753 void KHTMLView::scheduleRepaint(int x, int y, int w, int h)
01754 {
01755
01756
01757
01758
01759 bool parsing = false;
01760 if( m_part->xmlDocImpl() ) {
01761 parsing = m_part->xmlDocImpl()->parsing();
01762 }
01763
01764
01765
01766
01767 int time;
01768
01769
01770 if (d->complete)
01771
01772 time = 0;
01773 else
01774 {
01775 if (parsing)
01776
01777 time = 300;
01778 else
01779
01780
01781 time = d->repaintTimerId ? 400 : 0;
01782 }
01783
01784 if (d->repaintTimerId) {
01785 killTimer(d->repaintTimerId);
01786 d->updateRect = d->updateRect.unite(QRect(x,y,w,h));
01787 } else
01788 d->updateRect = QRect(x,y,w,h);
01789
01790 d->repaintTimerId = startTimer( time );
01791
01792
01793 }
01794
01795 void KHTMLView::complete()
01796 {
01797
01798
01799 d->complete = true;
01800
01801
01802 if (d->timerId)
01803 {
01804
01805
01806 killTimer(d->timerId);
01807 d->timerId = startTimer( 0 );
01808 }
01809
01810
01811 if (d->repaintTimerId)
01812 {
01813
01814
01815 killTimer(d->repaintTimerId);
01816 d->repaintTimerId = startTimer( 1 );
01817 }
01818 }