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 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
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
00290
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;
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
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
00357
00358
00359 if (d->layoutSchedulingEnabled)
00360 layout();
00361
00362 KApplication::sendPostedEvents(viewport(), QEvent::Paint);
00363 }
00364
00365
00366 void KHTMLView::drawContents( QPainter*)
00367 {
00368 }
00369
00370 void KHTMLView::drawContents( QPainter *p, int ex, int ey, int ew, int eh )
00371 {
00372
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
00420 _marginWidth = w;
00421 }
00422
00423 void KHTMLView::setMarginHeight(int h)
00424 {
00425
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
00444
00445
00446
00447 }
00448 else if (!d->tooltip)
00449 d->tooltip = new KHTMLToolTip( this, d );
00450 }
00451
00452 _height = visibleHeight();
00453 _width = visibleWidth();
00454
00455
00456 root->setMinMaxKnown(false);
00457 root->setLayouted(false);
00458 root->layout();
00459
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
00474
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
00503
00505
00506 void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
00507 {
00508 if(!m_part->xmlDocImpl()) return;
00509 if (d->possibleTripleClick)
00510 {
00511 viewportMouseDoubleClickEvent( _mouse );
00512 return;
00513 }
00514
00515 int xm, ym;
00516 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
00517
00518
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
00526
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
00568
00569 if ( mev.innerNode.handle() && mev.innerNode.handle()->renderer() &&
00570 mev.innerNode.handle()->renderer()->isWidget() )
00571 return;
00572
00573
00574
00575 if (d->clickCount > 0 && d->clickX == xm && d->clickY == ym)
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
00616
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;
00627 }
00628
00629
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
00711
00712 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseRelease );
00713 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
00714
00715
00716
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
00852
00853
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
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
00890
00891
00892
00893
00894
00895
00896
00897 Q_UNUSED(_ke);
00898 }
00899 }
00900
00901 void KHTMLView::contentsContextMenuEvent ( QContextMenuEvent * )
00902 {
00903
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 );
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
00931 if (m_part->xmlDocImpl()) {
00932 focusNextPrevNode(next);
00933 if (m_part->xmlDocImpl()->focusNode() != 0)
00934 return true;
00935 }
00936
00937
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;
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
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
00991 if (x < contentsX() + d->borderX )
00992 deltax = x - contentsX() - d->borderX;
00993
00994 else if (xe + d->borderX > contentsX() + curWidth)
00995 deltax = xe + d->borderX - ( contentsX() + curWidth );
00996 else
00997 deltax = 0;
00998
00999
01000 if (y < contentsY() + d->borderY)
01001 deltay = y - contentsY() - d->borderY;
01002
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
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
01047
01048
01049
01050
01051 DocumentImpl *doc = m_part->xmlDocImpl();
01052 NodeImpl *oldFocusNode = doc->focusNode();
01053 NodeImpl *newFocusNode;
01054
01055
01056 if (next)
01057 newFocusNode = doc->nextFocusNode(oldFocusNode);
01058 else
01059 newFocusNode = doc->previousFocusNode(oldFocusNode);
01060
01061
01062
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
01074 visible = true;
01075 }
01076 else {
01077
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
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
01101 {
01102 if (oldFocusNode)
01103 {
01104 if (!scrollTo(newFocusNode->getRect()))
01105 return;
01106 }
01107 else
01108 {
01109 ensureVisible(contentsX(), next?0:contentsHeight());
01110
01111 }
01112 }
01113
01114 m_part->xmlDocImpl()->setFocusNode(newFocusNode);
01115 emit m_part->nodeActivated(Node(newFocusNode));
01116
01117 #if 0
01118 if (newFocusNode) {
01119
01120
01121
01122
01123
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
01164 KPrinter *printer = new KPrinter(QPrinter::PrinterResolution);
01165 printer->addDialogPage(new KHTMLPrintSettings());
01166 if(printer->setup(this)) {
01167 viewport()->setCursor( waitCursor );
01168
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
01183
01184
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
01198
01199
01200
01201
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
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
01237
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
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;
01303
01304 top = root->truncatedAt();
01305 p->resetXForm();
01306 page++;
01307 }
01308
01309 p->end();
01310 delete p;
01311
01312
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
01428
01429
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
01464
01465
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
01490 if (setUnder && (d->prevMouseX != mx || d->prevMouseY != my)) {
01491
01492
01493
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
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
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
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
01596
01597
01598 if ( m_part->parentPart() )
01599 {
01600
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 ) &&
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
01623
01624
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
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
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
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
01754
01755
01756 bool parsing = false;
01757 if( m_part->xmlDocImpl() ) {
01758 parsing = m_part->xmlDocImpl()->parsing();
01759 }
01760
01761
01762
01763
01764 int time;
01765
01766
01767 if (d->complete)
01768
01769 time = 0;
01770 else
01771 {
01772 if (parsing)
01773
01774 time = 300;
01775 else
01776
01777
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
01790 }
01791
01792 void KHTMLView::complete()
01793 {
01794
01795
01796 d->complete = true;
01797
01798
01799 if (d->timerId)
01800 {
01801
01802
01803 killTimer(d->timerId);
01804 d->timerId = startTimer( 0 );
01805 }
01806
01807
01808 if (d->repaintTimerId)
01809 {
01810
01811
01812 killTimer(d->repaintTimerId);
01813 d->repaintTimerId = startTimer( 1 );
01814 }
01815 }