Source Code (Use browser search to find items of interest.)

Class Index

kdelibs'KHTMLView (./kdelibs/khtml/khtmlview.h:51)

class KHTMLView : public QScrollView
{
    Q_OBJECT

    friend DOM::HTMLDocumentImpl;
    friend DOM::HTMLElementImpl;
    friend DOM::HTMLTitleElementImpl;
    friend class KHTMLPart;
    friend khtml::RenderRoot;

public:

    /**
     * Constructs a KHTMLView
     */
    KHTMLView( KHTMLPart *part, QWidget *parent, const char *name=0 );
    virtual ~KHTMLView();

    KHTMLPart *part() const { return m_part; }

protected:
    void init();
    void clear();

signals:
    void selectionChanged();

public:

    int frameWidth() const { return _width; }


    /*
     * @return the width of the parsed HTML code. Remember that
     * the documents width depends on the width of the widget.
     */
    //    int docWidth() const;

    /*
     * @return the height of the parsed HTML code. Remember that
     * the documents height depends on the width of the widget.
     */
    //    int docHeight() const;

    /*
     * Causes the widget contents to scroll automatically.  Call
     * @ref #stopAutoScrollY to stop.  Stops automatically when the
     * top or bottom of the document is reached.
     *
     * @param _delay Time in milliseconds to wait before scrolling the
     * document again.
     * @param _dy The amount to scroll the document when _delay elapses.
     *
     * (not implemented)
     */
    //    void autoScrollY( int _delay, int _dy );

    /*
     * Stops the document from @ref #autoScrollY ing.
     */
    //void stopAutoScrollY();

    /*
     * Returns if the widget is currently auto scrolling.
     */
    //    bool isAutoScrollingY()
    //    { return autoScrollYTimer.isActive(); }

    /**
     * Sets the cursor to use when the cursor is on a link.
     */
    void setURLCursor( const QCursor &c )
       { linkCursor = c; }

    /**
     * Returns the cursor which is used when the cursor is on a link.
     */
    const QCursor& urlCursor() const { return linkCursor; }

    /*
     * set a margin in x direction
     */
    //    void setMarginWidth(int x) { _marginWidth = x; }
    /**
     * @return the margin With
     */
     int marginWidth() const { return _marginWidth; }

    /*
     * set a margin in y direction
     */
    //    void setMarginHeight(int y) { _marginHeight = y; }
    /*
     * @return the margin height
     */
    //    int marginHeight() { return _marginHeight; }

    QString selectedText() const;

    bool hasSelection() const;

protected:
    void paintElement( khtml::RenderObject *o, int x, int y );
    virtual void resizeEvent ( QResizeEvent * event );
    virtual void viewportPaintEvent ( QPaintEvent* pe  );
    virtual bool focusNextPrevChild( bool next );
    virtual void drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph );

public:
    void layout(bool force = false);
protected:

    virtual void viewportMousePressEvent( QMouseEvent * );

    /**
     * This function emits the 'doubleClick' signal when the user
     * double clicks a <a href=...> tag.
     */
    virtual void viewportMouseDoubleClickEvent( QMouseEvent * );

    /**
     * This function is called when the user moves the mouse.
     */
    virtual void viewportMouseMoveEvent(QMouseEvent *);

    /**
     * this function is called when the user releases a mouse button.
     */
    virtual void viewportMouseReleaseEvent(QMouseEvent *);

    void keyPressEvent( QKeyEvent *_ke );
    void keyReleaseEvent( QKeyEvent *_ke );
protected:
    // ------------------------------------- member variables ------------------------------------

    /**
     * List of all open browsers.
     */
    static QList<KHTMLView> *lstViews;

    /**
     * This is just a temporary variable. It stores the URL the user clicked
     * on, until he releases the mouse again.
     *
     * @ref #mouseMoveHook
     * @ref #mousePressedHook
     */
   QString m_strSelectedURL;

private:
    DOM::NodeImpl *nodeUnderMouse() const;

    QCursor linkCursor;

    bool pressed;
    QString overURL;
    int _width;

    int _marginWidth;
    int _marginHeight;

    KHTMLPart *m_part;

    static QPixmap* paintBuffer;

    KHTMLViewPrivate *d;
};

kdelibs'KHTMLView::KHTMLView() (./kdelibs/khtml/khtmlview.cpp:86)

KHTMLView::KHTMLView( KHTMLPart *part, QWidget *parent, const char *name)
    : QScrollView( parent, name)
{
    m_part = part;

    // initialize QScrollview

    enableClipper(true);

    viewport()->setMouseTracking(true);
    viewport()->setBackgroundMode(NoBackground);

    kimgioRegister();

    setCursor(arrowCursor);
    linkCursor = QCursor(PointingHandCursor);
    init();

    viewport()->show();

    d = new KHTMLViewPrivate;
}


kdelibs'KHTMLView::~KHTMLView() (./kdelibs/khtml/khtmlview.cpp:109)

KHTMLView::~KHTMLView()
{
  lstViews->removeRef( this );
  if(lstViews->isEmpty())
  {
      delete lstViews;
      lstViews = 0;
      if(paintBuffer) delete paintBuffer;
      paintBuffer = 0;
  }

  delete d;
}


kdelibs'KHTMLView::init() (./kdelibs/khtml/khtmlview.cpp:123)

void KHTMLView::init()
{
    if ( lstViews == 0L )
	lstViews = new QList<KHTMLView>;
    lstViews->setAutoDelete( FALSE );
    lstViews->append( this );

    if(!paintBuffer) paintBuffer = new QPixmap();

  viewport()->setFocusPolicy( QWidget::WheelFocus );

  _marginWidth = 5;
  _marginHeight = 5;
  _width = width()- SCROLLBARWIDTH - 2*marginWidth();

  resizeContents(clipper()->width(), clipper()->height());
}


kdelibs'KHTMLView::clear() (./kdelibs/khtml/khtmlview.cpp:141)

void KHTMLView::clear()
{
    resizeContents(clipper()->width(), clipper()->height());

    pressed = false;

    setVScrollBarMode(Auto);
    setHScrollBarMode(Auto);

    d->selectionStart = 0;
    d->selectionEnd = 0;
    d->startOffset = 0;
    d->endOffset = 0;
    d->underMouse = 0;
}

/*
void KHTMLView::setFollowsLinks( bool follow )
{
    _followLinks = follow;
}

bool KHTMLView::followsLinks()
{
    return _followLinks;
}
*/



kdelibs'KHTMLView::resizeEvent() (./kdelibs/khtml/khtmlview.cpp:170)

void KHTMLView::resizeEvent ( QResizeEvent * event )
{
//    kdDebug( 6000 ) << "resizeEvent" << endl;
    layout();

    DOM::HTMLDocumentImpl *doc = m_part->docImpl();

    if ( doc && doc->body() )
      resizeContents( doc->renderer()->width(), doc->renderer()->height() );

    QScrollView::resizeEvent(event);
}




kdelibs'KHTMLView::viewportPaintEvent() (./kdelibs/khtml/khtmlview.cpp:185)

void KHTMLView::viewportPaintEvent ( QPaintEvent* pe  )
{
    QRect r = pe->rect();

//    kdDebug( 6000 ) << "viewportPaintEvent r x=" << //    	r.x() << ",y=" << r.y() << ",w=" << r.width() << ",h=" << r.height() << endl;

    NodeImpl *body = 0;

    if( m_part->docImpl() )
	body = m_part->docImpl()->body();

    QRect rr(
	-viewport()->x(), -viewport()->y(),
	clipper()->width(), clipper()->height()
    );
    r &= rr;
    int ex = r.x() + viewport()->x() + contentsX();
    int ey = r.y() + viewport()->y() + contentsY();
    int ew = r.width();
    int eh = r.height();

    if (ew<0)	    	// events generated with repaint() are bit weird...
    	ew = pe->rect().width();
    if (eh<0)
    	eh = pe->rect().height();

    if(!body)
    {
	QPainter p(viewport());

	p.fillRect(r.x(), r.y(), ew, eh, kapp->palette().normal().brush(QColorGroup::Background));
	return;
    }
//    kdDebug( 6000 ) << "viewportPaintEvent x=" << ex << ",y=" << ey << ",w=" << ew << ",h=" << eh << endl;

    if ( paintBuffer->width() < width() )
    {
        paintBuffer->resize(width(),PAINT_BUFFER_HEIGHT);
	QPainter p(paintBuffer);
	p.fillRect(r.x(), r.y(), ew, eh, kapp->palette().normal().brush(QColorGroup::Background));
    }

    QTime qt;
    qt.start();

    int py=0;
    while (py < eh)
    {
	QPainter* tp = new QPainter;
	tp->begin( paintBuffer );
	tp->translate(-ex,-ey-py);

    	int ph = eh-py<PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;	

	// ### fix this for frames...

	tp->fillRect(ex, ey+py, ew, ph, kapp->palette().normal().brush(QColorGroup::Background));

	m_part->docImpl()->renderer()->print(tp, ex, ey+py, ew, ph, 0, 0);

	
	drawContents(tp,ex,ey+py,ew,ph); // in case someone want to extend the widget
	tp->end();

	delete tp;

    	//kdDebug( 6000 ) << "bitBlt x=" << ex << ",y=" << ey+py << ",sw=" << ew << ",sh=" << ph << endl;
	bitBlt(viewport(),r.x(),r.y()+py,paintBuffer,0,0,ew,ph,Qt::CopyROP);
	
	py += PAINT_BUFFER_HEIGHT;
    }

    //kdDebug( 6000 ) << "TIME: print() dt=" << qt.elapsed() << endl;
}


kdelibs'KHTMLView::layout() (./kdelibs/khtml/khtmlview.cpp:260)

void KHTMLView::layout(bool force)
{
    //### take care of frmaes (hide scrollbars,...)

    if( m_part->docImpl() )
    {	
        DOM::HTMLDocumentImpl *document = m_part->docImpl();

	NodeImpl *body = document->body();
	if(body && body->id() == ID_FRAMESET)
	{
	    setVScrollBarMode(AlwaysOff);
	    setHScrollBarMode(AlwaysOff);
	    _width = width();
	
	    document->renderer()->setMinWidth(_width);
	    document->renderer()->layout(true);
	    return;
	}

	int w = width() - SCROLLBARWIDTH - 2*marginWidth();

//	if(w < _width-5 || w > _width + 5)
    	if (w != _width || force)
	{
	    //kdDebug( 6000 ) << "layouting document" << endl;

	    _width = w;

	    QTime qt;
	    qt.start();

	    document->renderer()->setMinWidth(_width);
	    document->renderer()->layout(true);
	    resizeContents(document->renderer()->width(), document->renderer()->height());
	    kdDebug( 6000 ) << "TIME: layout() dt=" << qt.elapsed() << endl;

	    viewport()->repaint(false);
	}
	else
	{
	    document->renderer()->layout(false);
	    viewport()->repaint(false);
	}
    }
    else
    {
	_width = width() - SCROLLBARWIDTH - 2*marginWidth();
    }
}


kdelibs'KHTMLView::paintElement() (./kdelibs/khtml/khtmlview.cpp:311)

void KHTMLView::paintElement( khtml::RenderObject *o, int xPos, int yPos )
{
    int yOff = contentsY();
    if(yOff > yPos + o->height() ||
       yOff + visibleHeight() < yPos)
	return;

    QWidget *vp = viewport();
    QPainter p(vp);
    int xOff = contentsX()+vp->x();
    yOff += vp->y();
    p.translate( -xOff, -yOff );

    o->printObject( &p , xOff, yOff, vp->width(), vp->height(),
		    xPos , yPos );
}

//
// Event Handling
//
/////////////////


kdelibs'KHTMLView::viewportMousePressEvent() (./kdelibs/khtml/khtmlview.cpp:333)

void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
{
    if(!m_part->docImpl()) return;


    int xm, ym;
    viewportToContents(_mouse->x(), _mouse->y(), xm, ym);

    //kdDebug( 6000 ) << "\nmousePressEvent: x=" << xm << ", y=" << ym << endl;


    // Make this frame the active one
    // ### need some visual indication for the active frame.
    /* ### use PartManager (Simon)
    if ( _isFrame && !_isSelected )
    {
	kdDebug( 6000 ) << "activating frame!" << endl;
	topView()->setFrameSelected(this);
    }*/

    DOMString url;
    NodeImpl *innerNode=0;
    long offset=0;
    m_part->docImpl()->mouseEvent( xm, ym, _mouse->stateAfter(), DOM::NodeImpl::MousePress, 0, 0, url, innerNode, offset );

    kdDebug( 6000 ) << "Her har vi long'n: " << offset << " " << endl;
    if(m_part->mousePressHook(_mouse, xm, ym, url, Node(innerNode), offset)) return;

    if(url != 0)
    {
	//kdDebug( 6000 ) << "mouseEvent: overURL " << url.string() << endl;
	m_strSelectedURL = url.string();
    }
    else
	m_strSelectedURL = QString::null;

    if ( _mouse->button() == LeftButton || _mouse->button() == MidButton )
    {
    	pressed = TRUE;
	if(_mouse->button() == LeftButton) {
    	    if(innerNode) {
		d->selectionStart = innerNode;
		d->startOffset = offset;
		d->selectionEnd = innerNode;
		d->endOffset = offset;
		m_part->docImpl()->clearSelection();
		kdDebug( 6000 ) << "setting start of selection to " << innerNode << "/" << offset << endl;
	    } else {
		d->selectionStart = 0;
		d->selectionEnd = 0;
	    }
	    // ### emit some signal
	    emit selectionChanged();
	}
    }

    if( _mouse->button() == RightButton )
    {
	m_part->popupMenu( m_strSelectedURL );
    }
    else if ( _mouse->button() == MidButton )
    {
      KURL u( m_part->url(), m_strSelectedURL );
      if ( !u.isMalformed() )
        emit m_part->browserExtension()->createNewWindow( u );
    }
}


kdelibs'KHTMLView::viewportMouseDoubleClickEvent() (./kdelibs/khtml/khtmlview.cpp:401)

void KHTMLView::viewportMouseDoubleClickEvent( QMouseEvent *_mouse )
{
    if(!m_part->docImpl()) return;

    int xm, ym;
    viewportToContents(_mouse->x(), _mouse->y(), xm, ym);

    kdDebug( 6000 ) << "\nmouseDblClickEvent: x=" << xm << ", y=" << ym << endl;

    DOMString url;
    NodeImpl *innerNode=0;
    long offset=0;
    m_part->docImpl()->mouseEvent( xm, ym, _mouse->stateAfter(), DOM::NodeImpl::MouseDblClick, 0, 0, url, innerNode, offset );

    if(m_part->mouseDoubleClickHook(_mouse, xm, ym, url, Node(innerNode), offset)) return;

    // ###
    //if ( url.length() )
    //emit doubleClick( url.string(), _mouse->button() );
}


kdelibs'KHTMLView::viewportMouseMoveEvent() (./kdelibs/khtml/khtmlview.cpp:422)

void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse )
{
    if(!m_part->docImpl()) return;


    int xm, ym;
    viewportToContents(_mouse->x(), _mouse->y(), xm, ym);

    DOMString url;
    NodeImpl *innerNode=0;
    long offset=0;
    m_part->docImpl()->mouseEvent( xm, ym, _mouse->stateAfter(), DOM::NodeImpl::MouseMove, 0, 0, url, innerNode, offset );

    d->underMouse = innerNode;
    if(m_part->mouseMoveHook(_mouse, xm, ym, url, Node(innerNode), offset)) return;

    // drag of URL

    if(pressed && !m_strSelectedURL.isEmpty())
    {
	QStrList uris;
	KURL u( m_part->completeURL( m_strSelectedURL) );
	uris.append(u.url().ascii());
	QDragObject *d = new QUriDrag(uris, this);
	QPixmap p = KMimeType::pixmapForURL(u, 0, KIconLoader::Medium);
	if(p.isNull()) kdDebug( 6000 ) << "null pixmap" << endl;
	d->setPixmap(p);
	d->drag();

	// when we finish our drag, we need to undo our mouse press
	pressed = false;
        m_strSelectedURL = "";
	return;
    }



    if ( !pressed && url.length() )
    {
	QString surl = url.string();
	if ( overURL.isEmpty() )
	{
	    setCursor( linkCursor );
	    overURL = surl;
	    m_part->overURL( overURL );
	}
	else if ( overURL != surl )
	{
	    m_part->overURL( overURL );
	    overURL = surl;
	}
	return;
    }
    else if( overURL.length() && !url.length() )
    {
	setCursor( arrowCursor );
	m_part->overURL( QString::null );
	overURL = "";
    }

    // selection stuff
    if( pressed && innerNode && innerNode->isTextNode()) {
	d->selectionEnd = innerNode;
	d->endOffset = offset;
	kdDebug( 6000 ) << "setting end of selection to " << innerNode << "/" << offset << endl;

	// we have to get to know if end is before start or not...
	NodeImpl *n = d->selectionStart;
	d->startBeforeEnd = false;
	while(n) {
	    if(n == d->selectionEnd) {
		d->startBeforeEnd = true;
		break;
	    }
	    NodeImpl *next = n->firstChild();
	    if(!next) next = n->nextSibling();
	    while( !next && (n = n->parentNode()) ) {
		next = n->nextSibling();
	    }
	    n = next;
	    //viewport()->repaint(false);
	}
	
	if (d->selectionEnd == d->selectionStart && d->endOffset < d->startOffset)
	     m_part->docImpl()
	    	->setSelection(d->selectionStart,d->endOffset,d->selectionEnd,d->startOffset);
	else if (d->startBeforeEnd)
	    m_part->docImpl()
	    	->setSelection(d->selectionStart,d->startOffset,d->selectionEnd,d->endOffset);
	else
	    m_part->docImpl()
	    	->setSelection(d->selectionEnd,d->endOffset,d->selectionStart,d->startOffset);
	
    }
}


kdelibs'KHTMLView::viewportMouseReleaseEvent() (./kdelibs/khtml/khtmlview.cpp:518)

void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse )
{
    if ( !m_part->docImpl() ) return;

    int xm, ym;
    viewportToContents(_mouse->x(), _mouse->y(), xm, ym);

    //kdDebug( 6000 ) << "\nmouseReleaseEvent: x=" << xm << ", y=" << ym << endl;

    DOMString url=0;
    NodeImpl *innerNode=0;
    long offset;
    m_part->docImpl()->mouseEvent( xm, ym, _mouse->stateAfter(), DOM::NodeImpl::MouseRelease, 0, 0, url, innerNode, offset );

    if(m_part->mouseReleaseHook(_mouse, xm, ym, url, Node(innerNode), offset)) return;


    if ( pressed )
    {
	// in case we started an autoscroll in MouseMove event
	// ###
	//stopAutoScrollY();
	//disconnect( this, SLOT( slotUpdateSelectText(int) ) );
    }

    // Used to prevent mouseMoveEvent from initiating a drag before
    // the mouse is pressed again.
    pressed = false;


    if ( !m_strSelectedURL.isEmpty() && _mouse->button() != RightButton )
    {
	KURL u(m_strSelectedURL);
	QString pressedTarget;
	if(u.protocol() == "target")
	{
	    m_strSelectedURL = u.ref();
	    pressedTarget = u.host();
	}	
	kdDebug( 6000 ) << "m_strSelectedURL='" << m_strSelectedURL << "' target=" << pressedTarget << endl;

	m_part->urlSelected( m_strSelectedURL, _mouse->button(), _mouse->state(), pressedTarget );
   }

    if(innerNode && innerNode->isTextNode()) {
	kdDebug( 6000 ) << "final range of selection to " << d->selectionStart << "/" << d->startOffset << " --> " << innerNode << "/" << offset << endl;
	d->selectionEnd = innerNode;
	d->endOffset = offset;
    }

    // delete selection in case start and end position are at the same point
    if(d->selectionStart == d->selectionEnd && d->startOffset == d->endOffset) {
	d->selectionStart = 0;
	d->selectionEnd = 0;
	d->startOffset = 0;
	d->endOffset = 0;
	emit selectionChanged();
    } else {
	// we have to get to know if end is before start or not...
	NodeImpl *n = d->selectionStart;
	d->startBeforeEnd = false;
	while(n) {
	    if(n == d->selectionEnd) {
		d->startBeforeEnd = true;
		break;
	    }
	    NodeImpl *next = n->firstChild();
	    if(!next) next = n->nextSibling();
	    while( !next && (n = n->parentNode()) ) {
		next = n->nextSibling();
	    }	
	    n = next;
	}
	if(!d->startBeforeEnd)
	{
	    NodeImpl *tmpNode = d->selectionStart;
	    int tmpOffset = d->startOffset;
	    d->selectionStart = d->selectionEnd;
	    d->startOffset = d->endOffset;
	    d->selectionEnd = tmpNode;
	    d->endOffset = tmpOffset;
	    d->startBeforeEnd = true;
	}
	// get selected text and paste to the clipboard
	QString text = selectedText();
	QClipboard *cb = QApplication::clipboard();
	cb->setText(text);
	//kdDebug( 6000 ) << "selectedText = " << text << endl;
	emit selectionChanged();
    }
}


kdelibs'KHTMLView::selectedText() (./kdelibs/khtml/khtmlview.cpp:610)

QString KHTMLView::selectedText() const
{
    QString text;
    NodeImpl *n = d->selectionStart;
    while(n) {
	if(n->isTextNode()) {
	    QString str = static_cast<TextImpl *>(n)->data().string();
	    if(n == d->selectionStart && n == d->selectionEnd)
		text = str.mid(d->startOffset, d->endOffset - d->startOffset);
	    else if(n == d->selectionStart)
		text = str.mid(d->startOffset);
	    else if(n == d->selectionEnd)
		text += str.left(d->endOffset);
	    else
		text += str;
	}
	else if(n->id() == ID_BR)
	    text += "\n";
	else if(n->id() == ID_P || n->id() == ID_TD)
	    text += "\n\n";
	if(n == d->selectionEnd) break;
	NodeImpl *next = n->firstChild();
	if(!next) next = n->nextSibling();
	while( !next && (n = n->parentNode()) ) {
	    next = n->nextSibling();
	}

	n = next;
    }
    return text;
}


kdelibs'KHTMLView::hasSelection() (./kdelibs/khtml/khtmlview.cpp:642)

bool KHTMLView::hasSelection() const
{
  return ( d->selectionStart != 0 && d->selectionEnd != 0 );
}


kdelibs'KHTMLView::keyPressEvent() (./kdelibs/khtml/khtmlview.cpp:647)

void KHTMLView::keyPressEvent( QKeyEvent *_ke )
{
    if(m_part->keyPressHook(_ke)) return;


    int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
    switch ( _ke->key() )
    {
    case Key_Down:
    case Key_J:
	scrollBy( 0, 10 );
	break;

    case Key_Next:
    case Key_Space:
	scrollBy( 0, clipper()->height() - offs );
	break;

    case Key_Up:
    case Key_K:
	scrollBy( 0, -10 );
	break;

    case Key_Prior:
    case Key_Backspace:
	scrollBy( 0, -clipper()->height() + offs );
	break;

    case Key_Right:
    case Key_L:
	scrollBy( 10, 0 );
	break;	

    case Key_Left:
    case Key_H:
	scrollBy( -10, 0 );
	break;

    default:
	QScrollView::keyPressEvent( _ke );
    }
}


kdelibs'KHTMLView::keyReleaseEvent() (./kdelibs/khtml/khtmlview.cpp:690)

void KHTMLView::keyReleaseEvent( QKeyEvent *_ke )
{
    if(m_part->keyReleaseHook(_ke)) return;
    QScrollView::keyReleaseEvent( _ke);
}


kdelibs'KHTMLView::focusNextPrevChild() (./kdelibs/khtml/khtmlview.cpp:696)

bool KHTMLView::focusNextPrevChild( bool next )
{
    kdDebug( 6000 ) << "focusNextPrev " << next << endl;
//    return true;    // ### temporary fix for qscrollview focus bug
    	    	    // as a side effect, disables tabbing between form elements
		    // -antti

//    return QScrollView::focusNextPrevChild( next );
        return QScrollView::focusNextPrevChild( next );
}


kdelibs'KHTMLView::drawContents() (./kdelibs/khtml/khtmlview.cpp:707)

void KHTMLView::drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph )
{
    m_part->drawContentsHook(p);
}


DOM::NodeImpl *KHTMLView::nodeUnderMouse() const
{
    return d->underMouse;
}