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