QRect DocumentWidget::pageRect() const
{
  QRect boundingRect = rect();
  // Substract the shadow.
  boundingRect.addCoords(1,1,-5,-5);
  return boundingRect;
}
void MultiLayer::mousePressEvent(QMouseEvent *e) {
  int margin = 5;
  QPoint pos = canvas->mapFromParent(e->pos());
  // iterate backwards, so layers on top are preferred for selection
  QList<QWidget *>::iterator i = graphsList.end();
  while (i != graphsList.begin()) {
    --i;
    QRect igeo = (*i)->frameGeometry();
    igeo.addCoords(-margin, -margin, margin, margin);
    if (igeo.contains(pos)) {
      if (e->modifiers() & Qt::ShiftModifier) {
        if (d_layers_selector)
          d_layers_selector->add(*i);
        else {
          d_layers_selector = new SelectionMoveResizer(*i);
          connect(d_layers_selector, SIGNAL(targetsChanged()), this,
                  SIGNAL(modifiedPlot()));
        }
      } else {
        setActiveGraph((Graph *)(*i));
        active_graph->raise();
        if (!d_layers_selector) {
          d_layers_selector = new SelectionMoveResizer(*i);
          connect(d_layers_selector, SIGNAL(targetsChanged()), this,
                  SIGNAL(modifiedPlot()));
        }
      }
      return;
    }
  }
  if (d_layers_selector) delete d_layers_selector;
}
bool ScalePicker::eventFilter(QObject *object, QEvent *e)
{  
	if ( object->inherits("QwtScale") && e->type() == QEvent::MouseButtonDblClick)
    	{
		mouseDblClicked((const QwtScale *)object, ((QMouseEvent *)e)->pos());
        return TRUE;
    	}

	if ( object->inherits("QwtScale") && e->type() == QEvent::MouseButtonPress)
    	{
		const QMouseEvent *me = (const QMouseEvent *)e;	
		if (me->button()==QEvent::LeftButton)
			{
			emit clicked();	

			if (plot()->margin() < 2 && plot()->lineWidth() < 2)
				{
				QRect r = ((const QwtScale *)object)->rect();
				r.addCoords(2, 2, -2, -2);
				if (!r.contains(me->pos()))
					emit highlightGraph();
				}
			return TRUE;
			}
		else if (me->button() == QEvent::RightButton)
			{
			mouseRightClicked((const QwtScale *)object, me->pos());
			return TRUE;
			}
    	}
	
	if ( object->inherits("QwtScale") && e->type() == QEvent::MouseMove)
    	{	
		const QMouseEvent *me = (const QMouseEvent *)e;			

		movedGraph=TRUE;
		emit moveGraph(me->pos());

        return TRUE;
   	 }
	
	if ( object->inherits("QwtScale") && e->type() == QEvent::MouseButtonRelease)
    	{
		if (movedGraph)
			{
			emit releasedGraph();
			movedGraph=FALSE;
			}
				
        return TRUE;
    	}
		
return QObject::eventFilter(object, e);
}
void DocumentWidget::flash(int fo)
{
  if (timerIdent != 0)
  {
    killTimer(timerIdent);
    // Delete old flash rectangle
    animationCounter = 10;
    QRect flashRect = linkFlashRect();
    flashRect.addCoords(-1, -1, 1, 1);
    repaint(flashRect, false);
  }
  animationCounter = 0;
  flashOffset      = fo;
  timerIdent       = startTimer(50); // Start the animation. The animation proceeds in 1/10s intervals
}
void DocumentWidget::timerEvent( QTimerEvent *e )
{
  if (animationCounter == 0) {
    killTimer(e->timerId());
    timerIdent = startTimer(50); // Proceed with the animation in 1/10s intervals
  }

  animationCounter++;

  QRect flashRect = linkFlashRect();
  flashRect.addCoords(-1, -1, 1, 1);

  if (animationCounter >= 10) {
    killTimer(e->timerId());
    timerIdent       = 0;
    animationCounter = 0;
  }

  repaint(flashRect, false);
}
Example #6
0
void QFrame::paintEvent( QPaintEvent *event )
{
    const int m = margin();
    if ( m && testWFlags( WNoAutoErase ) ) {
	QRect r = contentsRect();
	r.addCoords( -m, -m, m, m );
	erase( event->region().intersect( QRegion( r ) - contentsRect() ) );
    }

    QPainter paint( this );

    if ( !contentsRect().contains( event->rect() ) ) {
        paint.save();
	paint.setClipRegion( event->region().intersect(frameRect()) );
        drawFrame( &paint );
        paint.restore();
    }
    if ( event->rect().intersects( contentsRect() ) &&
         (fstyle & MShape) != HLine && (fstyle & MShape) != VLine ) {
        paint.setClipRegion( event->region().intersect( contentsRect() ) );
        drawContents( &paint );
    }
}
Example #7
0
void PagePainter::paintPageOnPainter( const KPDFPage * page, int id, int flags,
    QPainter * destPainter, const QRect & limits, int width, int height )
{
    QPixmap * pixmap = 0;

    // if a pixmap is present for given id, use it
    if ( page->m_pixmaps.contains( id ) )
        pixmap = page->m_pixmaps[ id ];

    // else find the closest match using pixmaps of other IDs (great optim!)
    else if ( !page->m_pixmaps.isEmpty() && width != -1 )
    {
        int minDistance = -1;
        QMap< int,QPixmap * >::const_iterator it = page->m_pixmaps.begin(), end = page->m_pixmaps.end();
        for ( ; it != end; ++it )
        {
            int pixWidth = (*it)->width(),
                distance = pixWidth > width ? pixWidth - width : width - pixWidth;
            if ( minDistance == -1 || distance < minDistance )
            {
                pixmap = *it;
                minDistance = distance;
            }
        }
    }

    // if have no pixmap, draw blank page with gray cross and exit
    if ( !pixmap )
    {
        QColor color = Qt::white;
        if ( KpdfSettings::changeColors() )
        {
            switch ( KpdfSettings::renderMode() )
            {
                case KpdfSettings::EnumRenderMode::Inverted:
                    color = Qt::black;
                    break;
                case KpdfSettings::EnumRenderMode::Paper:
                    color = KpdfSettings::paperColor();
                    break;
                case KpdfSettings::EnumRenderMode::Recolor:
                    color = KpdfSettings::recolorBackground();
                    break;
                default: ;
            }
        }
        destPainter->fillRect( limits, color );

        // draw a cross (to  that the pixmap as not yet been loaded)
        // helps a lot on pages that take much to render
        destPainter->setPen( Qt::gray );
        destPainter->drawLine( 0, 0, width-1, height-1 );
        destPainter->drawLine( 0, height-1, width-1, 0 );
        // idea here: draw a hourglass (or kpdf icon :-) on top-left corner
        return;
    }

    // find out what to paint over the pixmap (manipulations / overlays)
    bool paintAccessibility = (flags & Accessibility) && KpdfSettings::changeColors() && (KpdfSettings::renderMode() != KpdfSettings::EnumRenderMode::Paper);
    bool paintHighlights = (flags & Highlights) && !page->m_highlights.isEmpty();
    bool enhanceLinks = (flags & EnhanceLinks) && KpdfSettings::highlightLinks();
    bool enhanceImages = (flags & EnhanceImages) && KpdfSettings::highlightImages();
    // check if there are really some highlightRects to paint
    if ( paintHighlights )
    {
        // precalc normalized 'limits rect' for intersection
        double nXMin = (double)limits.left() / (double)width,
               nXMax = (double)limits.right() / (double)width,
               nYMin = (double)limits.top() / (double)height,
               nYMax = (double)limits.bottom() / (double)height;
        // if no rect intersects limits, disable paintHighlights
        paintHighlights = false;
        QValueList< HighlightRect * >::const_iterator hIt = page->m_highlights.begin(), hEnd = page->m_highlights.end();
        for ( ; hIt != hEnd; ++hIt )
        {
            if ( (*hIt)->intersects( nXMin, nYMin, nXMax, nYMax ) )
            {
                paintHighlights = true;
                break;
            }
        }
    }

    // use backBuffer if 'pixmap direct manipulation' is needed
    bool backBuffer = paintAccessibility || paintHighlights;
    QPixmap * backPixmap = 0;
    QPainter * p = destPainter;
    if ( backBuffer )
    {
        // let's paint using a buffered painter
        backPixmap = new QPixmap( limits.width(), limits.height() );
        p = new QPainter( backPixmap );
        p->translate( -limits.left(), -limits.top() );
    }

    // 1. fast blit the pixmap if it has the right size..
    if ( pixmap->width() == width && pixmap->height() == height )
        p->drawPixmap( limits.topLeft(), *pixmap, limits );
    // ..else set a scale matrix to the painter and paint a quick 'zoomed' pixmap
    else
    {
        p->save();
        // TODO paint only the needed part (note: hope that Qt4 transforms are faster)
        p->scale( width / (double)pixmap->width(), height / (double)pixmap->height() );
        p->drawPixmap( 0,0, *pixmap, 0,0, pixmap->width(), pixmap->height() );
        p->restore();
    }

    // 2. mangle pixmap: convert it to 32-bit qimage and perform pixel-level manipulations
    if ( backBuffer )
    {
        QImage backImage = backPixmap->convertToImage();
        // 2.1. modify pixmap following accessibility settings
        if ( paintAccessibility )
        {
            switch ( KpdfSettings::renderMode() )
            {
                case KpdfSettings::EnumRenderMode::Inverted:
                    // Invert image pixels using QImage internal function
                    backImage.invertPixels(false);
                    break;
                case KpdfSettings::EnumRenderMode::Recolor:
                    // Recolor image using KImageEffect::flatten with dither:0
                    KImageEffect::flatten( backImage, KpdfSettings::recolorForeground(), KpdfSettings::recolorBackground() );
                    break;
                case KpdfSettings::EnumRenderMode::BlackWhite:
                    // Manual Gray and Contrast
                    unsigned int * data = (unsigned int *)backImage.bits();
                    int val, pixels = backImage.width() * backImage.height(),
                        con = KpdfSettings::bWContrast(), thr = 255 - KpdfSettings::bWThreshold();
                    for( int i = 0; i < pixels; ++i )
                    {
                        val = qGray( data[i] );
                        if ( val > thr )
                            val = 128 + (127 * (val - thr)) / (255 - thr);
                        else if ( val < thr )
                            val = (128 * val) / thr;
                        if ( con > 2 )
                        {
                            val = con * ( val - thr ) / 2 + thr;
                            if ( val > 255 )
                                val = 255;
                            else if ( val < 0 )
                                val = 0;
                        }
                        data[i] = qRgba( val, val, val, 255 );
                    }
                    break;
            }
        }
        // 2.2. highlight rects in page
        if ( paintHighlights )
        {
            // draw highlights that are inside the 'limits' paint region
            QValueList< HighlightRect * >::const_iterator hIt = page->m_highlights.begin(), hEnd = page->m_highlights.end();
            for ( ; hIt != hEnd; ++hIt )
            {
                HighlightRect * r = *hIt;
                QRect highlightRect = r->geometry( width, height );
                if ( highlightRect.isValid() && highlightRect.intersects( limits ) )
                {
                    // find out the rect to highlight on pixmap
                    highlightRect = highlightRect.intersect( limits );
                    highlightRect.moveBy( -limits.left(), -limits.top() );

                    // highlight composition (product: highlight color * destcolor)
                    unsigned int * data = (unsigned int *)backImage.bits();
                    int val, newR, newG, newB,
                        rh = r->color.red(),
                        gh = r->color.green(),
                        bh = r->color.blue(),
                        offset = highlightRect.top() * backImage.width();
                    for( int y = highlightRect.top(); y <= highlightRect.bottom(); ++y )
                    {
                        for( int x = highlightRect.left(); x <= highlightRect.right(); ++x )
                        {
                            val = data[ x + offset ];
                            newR = (qRed(val) * rh) / 255;
                            newG = (qGreen(val) * gh) / 255;
                            newB = (qBlue(val) * bh) / 255;
                            data[ x + offset ] = qRgba( newR, newG, newB, 255 );
                        }
                        offset += backImage.width();
                    }
                }
            }
        }
        backPixmap->convertFromImage( backImage );
    }

    // 3. visually enchance links and images if requested
    if ( enhanceLinks || enhanceImages )
    {
        QColor normalColor = QApplication::palette().active().highlight();
        QColor lightColor = normalColor.light( 140 );
        // enlarging limits for intersection is like growing the 'rectGeometry' below
        QRect limitsEnlarged = limits;
        limitsEnlarged.addCoords( -2, -2, 2, 2 );
        // draw rects that are inside the 'limits' paint region as opaque rects
        QValueList< ObjectRect * >::const_iterator lIt = page->m_rects.begin(), lEnd = page->m_rects.end();
        for ( ; lIt != lEnd; ++lIt )
        {
            ObjectRect * rect = *lIt;
            if ( (enhanceLinks && rect->objectType() == ObjectRect::Link) ||
                 (enhanceImages && rect->objectType() == ObjectRect::Image) )
            {
                QRect rectGeometry = rect->geometry( width, height );
                if ( rectGeometry.intersects( limitsEnlarged ) )
                {
                    // expand rect and draw inner border
                    rectGeometry.addCoords( -1,-1,1,1 );
                    p->setPen( lightColor );
                    p->drawRect( rectGeometry );
                    // expand rect to draw outer border
                    rectGeometry.addCoords( -1,-1,1,1 );
                    p->setPen( normalColor );
                    p->drawRect( rectGeometry );
                }
            }
        }
    }

    // 4. if was backbuffering, copy the backPixmap to destination
    if ( backBuffer )
    {
        delete p;
        destPainter->drawPixmap( limits.left(), limits.top(), *backPixmap );
        delete backPixmap;
    }
}
Example #8
0
void OSDWidget::renderOSDText( const QString &txt )
{
                                                  // Escaped text
    QString text = Konversation::removeIrcMarkup(txt);

    static QBitmap mask;

    //This is various spacings and margins, based on the font to look "just right"
    const uint METRIC = fontMetrics().width( 'x' );

    // Set a sensible maximum size, don't cover the whole desktop or cross the screen
    QSize max = QApplication::desktop()->screen( m_screen )->size() - QSize( MARGIN*2 + METRIC*2, 100 );
    QFont titleFont( "Arial", 12, QFont::Bold );
    QFontMetrics titleFm( titleFont );

    // The title cannnot be taller than one line
    // AlignAuto = align Arabic to the right, etc.
    QRect titleRect = titleFm.boundingRect( 0, 0, max.width() - METRIC, titleFm.height(), AlignAuto, m_appName );
    // The osd cannot be larger than the screen
    QRect textRect = fontMetrics().boundingRect( 0, 0, max.width(), max.height(), AlignAuto | WordBreak, text );

    if ( textRect.width() < titleRect.width() )
        textRect.setWidth( titleRect.width() );

    //this should still be within the screen bounds
    textRect.addCoords( 0, 0, METRIC*2, titleRect.height() + METRIC );

    osdBuffer.resize( textRect.size() );
    mask.resize( textRect.size() );

    // Start painting!
    QPainter bufferPainter( &osdBuffer );
    QPainter maskPainter( &mask );

    // Draw backing rectangle
    const uint xround = (METRIC * 200) / textRect.width();
    const uint yround = (METRIC * 200) / textRect.height();

    bufferPainter.setPen( Qt::black );
    bufferPainter.setBrush( backgroundColor() );
    bufferPainter.drawRoundRect( textRect, xround, yround );
    bufferPainter.setFont( font() );

    const uint w = textRect.width()  - 1;
    const uint h = textRect.height() - 1;

    // Draw the text shadow
    if ( m_shadow )
    {
        bufferPainter.setPen( backgroundColor().dark( 175 ) );
        bufferPainter.drawText( METRIC + 3, (METRIC/2) + titleFm.height() + 1, w, h, AlignLeft | WordBreak, text );
    }

    // Draw the text
    bufferPainter.setPen( foregroundColor() );
    bufferPainter.drawText( METRIC, (METRIC/2) + titleFm.height() - 1, w, h, AlignLeft | WordBreak, text );

    // Draw the title text
    bufferPainter.setFont( titleFont );
    bufferPainter.drawText( METRIC * 2, (METRIC/2), w, h, AlignLeft, m_appName );

    // Masking for transparency
    mask.fill( Qt::black );
    maskPainter.setBrush( Qt::white );
    maskPainter.drawRoundRect( textRect, xround, yround );
    setMask( mask );

    //do last to reduce noticeable change when showing multiple OSDs in succession
    reposition( textRect.size() );

    m_currentText = text;
    m_dirty = false;

    update();
}
Example #9
0
void KdmLayoutBox::update(const QRect &parentGeometry, bool force)
{
    kdDebug() << this << " update " << parentGeometry << endl;

    // I can't layout children if the parent rectangle is not valid
    if(!parentGeometry.isValid() || parentGeometry.isEmpty())
        return;

    // Check if box size was computed. If not compute it
    // TODO check if this prevents updating changing items
    //	if (!hintedSize.isValid())
    //		sizeHint();

    //	kdDebug() << this << " hintedSize " << hintedSize << endl;

    // XXX why was this asymmetric? it broke things big time.
    QRect childrenRect = /*box.isVertical ? QRect( parentGeometry.topLeft(), hintedSize ) :*/ parentGeometry;
    // Begin cutting the parent rectangle to attach children on the right place
    childrenRect.addCoords(box.xpadding, box.ypadding, -box.xpadding, -box.ypadding);

    kdDebug() << this << " childrenRect " << childrenRect << endl;

    // For each child in list ...
    if(box.homogeneous)
    {
        int ccnt = 0;
        for(QValueList< KdmItem * >::ConstIterator it = m_children.begin(); it != m_children.end(); ++it)
            if(!(*it)->isExplicitlyHidden())
                ccnt++;
        int height = (childrenRect.height() - (ccnt - 1) * box.spacing) / ccnt;
        int width = (childrenRect.width() - (ccnt - 1) * box.spacing) / ccnt;

        for(QValueList< KdmItem * >::ConstIterator it = m_children.begin(); it != m_children.end(); ++it)
        {
            if((*it)->isExplicitlyHidden())
                continue;
            if(box.isVertical)
            {
                QRect temp(childrenRect.left(), childrenRect.top(), childrenRect.width(), height);
                (*it)->setGeometry(temp, force);
                childrenRect.setTop(childrenRect.top() + height + box.spacing);
            }
            else
            {
                QRect temp(childrenRect.left(), childrenRect.top(), width, childrenRect.height());
                kdDebug() << "placement " << *it << " " << temp << " " << (*it)->placementHint(temp) << endl;
                temp = (*it)->placementHint(temp);
                (*it)->setGeometry(temp, force);
                childrenRect.setLeft(childrenRect.left() + width + box.spacing);
            }
        }
    }
    else
    {
        for(QValueList< KdmItem * >::ConstIterator it = m_children.begin(); it != m_children.end(); ++it)
        {
            if((*it)->isExplicitlyHidden())
                continue;

            QRect temp = childrenRect, itemRect;
            if(box.isVertical)
            {
                temp.setHeight(0);
                itemRect = (*it)->placementHint(temp);
                temp.setHeight(itemRect.height());
                childrenRect.setTop(childrenRect.top() + itemRect.size().height() + box.spacing);
            }
            else
            {
                temp.setWidth(0);
                itemRect = (*it)->placementHint(temp);
                kdDebug() << this << " placementHint " << *it << " " << temp << " " << itemRect << endl;
                temp.setWidth(itemRect.width());
                childrenRect.setLeft(childrenRect.left() + itemRect.size().width() + box.spacing);
                kdDebug() << "childrenRect after " << *it << " " << childrenRect << endl;
            }
            itemRect = (*it)->placementHint(temp);
            kdDebug() << this << " placementHint2 " << *it << " " << temp << " " << itemRect << endl;
            (*it)->setGeometry(itemRect, force);
        }
    }
}
bool TitlePicker::eventFilter(QObject *object, QEvent *e)
{
	if (object != (QObject *)title)
		return FALSE;
	
    if ( object->inherits("QLabel") && e->type() == QEvent::MouseButtonDblClick)
		{
		emit doubleClicked();
        return TRUE;
		}

	if ( object->inherits("QLabel") &&  e->type() == QEvent::MouseButtonPress )
		{
		emit clicked();

		const QMouseEvent *me = (const QMouseEvent *)e;	
		if (me->button()==QEvent::RightButton)
			emit showTitleMenu();

		QwtPlot *plot = (QwtPlot *)title->parent();
		if (plot->margin() < 2 && plot->lineWidth() < 2)
			{
			QRect r = title->rect();
			r.addCoords(2, 2, -2, -2);
			if (!r.contains(me->pos()))
				emit highlightGraph();
			}

		return TRUE;
		}

	if ( object->inherits("QLabel") &&  e->type() == QEvent::MouseMove)
		{	
		const QMouseEvent *me = (const QMouseEvent *)e;			
		movedGraph=TRUE;
		emit moveGraph(me->pos());

        return TRUE;
		}
	
	if ( object->inherits("QLabel") && e->type() == QEvent::MouseButtonRelease)
		{
		const QMouseEvent *me = (const QMouseEvent *)e;
		if (me->button()== QEvent::LeftButton)
			{
			emit clicked();
			if (movedGraph)
				{
				emit releasedGraph();
				movedGraph=FALSE;
				}
        	return TRUE;
			}
		}

	if ( object->inherits("QLabel") && 
        e->type() == QEvent::KeyPress)
		{
		switch (((const QKeyEvent *)e)->key()) 
			{
			case Qt::Key_Delete: 
			emit removeTitle();	
            return TRUE;
			}
		}

    return QObject::eventFilter(object, e);
}
Example #11
0
void MultiLayer::printAllLayers(QPainter *painter) {
  if (!painter) return;

  QPrinter *printer = (QPrinter *)painter->device();
  QRect paperRect = ((QPrinter *)painter->device())->paperRect();
  QRect canvasRect = canvas->rect();
  QRect pageRect = printer->pageRect();
  QRect cr = canvasRect;  // cropmarks rectangle

  if (d_scale_on_print) {
    int margin = (int)((1 / 2.54) * printer->logicalDpiY());  // 1 cm margins
    double scaleFactorX =
        (double)(paperRect.width() - 2 * margin) / (double)canvasRect.width();
    double scaleFactorY =
        (double)(paperRect.height() - 2 * margin) / (double)canvasRect.height();

    if (d_print_cropmarks) {
      cr.moveTo(QPoint(margin + int(cr.x() * scaleFactorX),
                       margin + int(cr.y() * scaleFactorY)));
      cr.setWidth(int(cr.width() * scaleFactorX));
      cr.setHeight(int(cr.height() * scaleFactorX));
    }

    for (int i = 0; i < (int)graphsList.count(); i++) {
      Graph *gr = (Graph *)graphsList.at(i);
      Plot *myPlot = gr->plotWidget();

      QPoint pos = gr->pos();
      pos = QPoint(margin + int(pos.x() * scaleFactorX),
                   margin + int(pos.y() * scaleFactorY));

      int width = int(myPlot->frameGeometry().width() * scaleFactorX);
      int height = int(myPlot->frameGeometry().height() * scaleFactorY);

      gr->print(painter, QRect(pos, QSize(width, height)));
    }
  } else {
    int x_margin = (pageRect.width() - canvasRect.width()) / 2;
    int y_margin = (pageRect.height() - canvasRect.height()) / 2;

    if (d_print_cropmarks) cr.moveTo(x_margin, y_margin);

    for (int i = 0; i < (int)graphsList.count(); i++) {
      Graph *gr = (Graph *)graphsList.at(i);
      Plot *myPlot = (Plot *)gr->plotWidget();

      QPoint pos = gr->pos();
      pos = QPoint(x_margin + pos.x(), y_margin + pos.y());
      gr->print(painter, QRect(pos, myPlot->size()));
    }
  }
  if (d_print_cropmarks) {
    cr.addCoords(-1, -1, 2, 2);
    painter->save();
    painter->setPen(QPen(QColor(Qt::black), 0.5, Qt::DashLine));
    painter->drawLine(paperRect.left(), cr.top(), paperRect.right(), cr.top());
    painter->drawLine(paperRect.left(), cr.bottom(), paperRect.right(),
                      cr.bottom());
    painter->drawLine(cr.left(), paperRect.top(), cr.left(),
                      paperRect.bottom());
    painter->drawLine(cr.right(), paperRect.top(), cr.right(),
                      paperRect.bottom());
    painter->restore();
  }
}
void DocumentWidget::mouseMoveEvent ( QMouseEvent * e )
{
#ifdef DEBUG_DOCUMENTWIDGET
  kdDebug(1223) << "DocumentWidget::mouseMoveEvent(...) called" << endl;
#endif


  // pageNr == 0 indicated an invalid page (e.g. page number not yet
  // set)
  if (pageNr == 0)
    return;

  // Get a pointer to the page contents
  RenderedDocumentPage *pageData = documentCache->getPage(pageNr);
  if (pageData == 0) {
    kdDebug(1223) << "DocumentWidget::selectAll() pageData for page #" << pageNr << " is empty" << endl;
    return;
  }

  // If no mouse button pressed
  if (e->state() == 0) {
    // Remember the index of the underlined link.
    int lastUnderlinedLink = indexOfUnderlinedLink;
    // go through hyperlinks
    for(unsigned int i = 0; i < pageData->hyperLinkList.size(); i++) {
      if (pageData->hyperLinkList[i].box.contains(e->pos())) {
        clearStatusBarTimer.stop();
        setCursor(pointingHandCursor);
        QString link = pageData->hyperLinkList[i].linkText;
        if ( link.startsWith("#") )
          link = link.remove(0,1);

        emit setStatusBarText( i18n("Link to %1").arg(link) );

        indexOfUnderlinedLink = i;
        if (KVSPrefs::underlineLinks() == KVSPrefs::EnumUnderlineLinks::OnlyOnHover &&
            indexOfUnderlinedLink != lastUnderlinedLink)
        {
          QRect newUnderline = pageData->hyperLinkList[i].box;
          // Increase Rectangle so that the whole line really lines in it.
          newUnderline.addCoords(0, 0, 0, 2);
          // Redraw widget
          update(newUnderline);

          if (lastUnderlinedLink != -1 && lastUnderlinedLink < pageData->hyperLinkList.size())
          {
            // Erase old underline
            QRect oldUnderline = pageData->hyperLinkList[lastUnderlinedLink].box;
            oldUnderline.addCoords(0, 0, 0, 2);
            update(oldUnderline);
          }
        }
        return;
      }
    }
    // Whenever we reach this the mouse hovers no link.
    indexOfUnderlinedLink = -1;
    if (KVSPrefs::underlineLinks() == KVSPrefs::EnumUnderlineLinks::OnlyOnHover &&
        lastUnderlinedLink != -1 && lastUnderlinedLink < pageData->hyperLinkList.size())
    {
      // Erase old underline
      QRect oldUnderline = pageData->hyperLinkList[lastUnderlinedLink].box;
      // Increase Rectangle so that the whole line really lines in it.
      oldUnderline.addCoords(0, 0, 0, 2);
      // Redraw widget
      update(oldUnderline);
    }
    // Cursor not over hyperlink? Then let the cursor be the usual arrow if we use the move tool, and
    // The textselection cursor if we use the selection tool.
    setStandardCursor();
  }

  if (!clearStatusBarTimer.isActive())
    clearStatusBarTimer.start(200, true); // clear the statusbar after 200 msec.

  // Left mouse button pressed -> Text scroll function
  if ((e->state() & LeftButton) != 0 && moveTool)
  {
    // Pass the mouse event on to the owner of this widget ---under
    // normal circumstances that is the centeringScrollView which will
    // then scroll the scrollview contents
    e->ignore();
  }

  // Right mouse button pressed -> Text copy function
  if ((e->state() & RightButton) != 0 || (!moveTool && (e->state() & LeftButton != 0)))
  {
    if (selectedRectangle.isEmpty()) {
      firstSelectedPoint = e->pos();
      selectedRectangle.setRect(e->pos().x(),e->pos().y(),1,1);
    } else {
      int lx = e->pos().x() < firstSelectedPoint.x() ? e->pos().x() : firstSelectedPoint.x();
      int rx = e->pos().x() > firstSelectedPoint.x() ? e->pos().x() : firstSelectedPoint.x();
      int ty = e->pos().y() < firstSelectedPoint.y() ? e->pos().y() : firstSelectedPoint.y();
      int by = e->pos().y() > firstSelectedPoint.y() ? e->pos().y() : firstSelectedPoint.y();
      selectedRectangle.setCoords(lx,ty,rx,by);
    }

    // Now that we know the rectangle, we have to find out which words
    // intersect it!
    TextSelection newTextSelection = pageData->select(selectedRectangle);

    updateSelection(newTextSelection);
  }
}
void DocumentWidget::paintEvent(QPaintEvent *e)
{
#ifdef DEBUG_DOCUMENTWIDGET
  kdDebug(1223) << "DocumentWidget::paintEvent() called" << endl;
#endif

  // Check if this widget is really visible to the user. If not, there
  // is nothing to do. Remark: if we don't do this, then under QT
  // 3.2.3 the following happens: when the user changes the zoom
  // value, all those widgets are updated which the user has EVER
  // seen, not just those that are visible at the moment. If the
  // document contains several thousand pages, it is easily possible
  // that this means that a few hundred of these are re-painted (which
  // takes substantial time) although perhaps only three widgets are
  // visible and *should* be updated. I believe this is some error in
  // QT, but I am not positive about that ---Stefan Kebekus.
  if (!isVisible())
  {
    //kdDebug() << "widget of page " << pageNr << " is not visible. Abort rendering" << endl;
    kapp->processEvents();
    return;
  }

  QPainter p(this);
  p.setClipRegion(e->region());

  // Paint a black border around the widget
  p.setRasterOp(Qt::CopyROP);
  p.setBrush(NoBrush);
  p.setPen(Qt::black);
  QRect outlineRect = pageRect();
  outlineRect.addCoords(-1, -1, 1, 1);
  p.drawRect(outlineRect);

  // Paint page shadow
  QColor backgroundColor = colorGroup().mid();

  // (Re-)generate the Pixmaps for the shadow corners, if necessary
  if (backgroundColor != backgroundColorForCorners)
  {
    backgroundColorForCorners = backgroundColor;
    QImage tmp(4, 4, 32);
    for(int x=0; x<4; x++)
      for(int y=0; y<4; y++)
        tmp.setPixel(x, y, backgroundColor.light(bottom_right_corner[x+4*y]).rgb() );
    BRShadow->convertFromImage(tmp);

    for(int x=0; x<4; x++)
      for(int y=0; y<4; y++)
        tmp.setPixel(x, y, backgroundColor.light(bottom_left_corner[x+4*y]).rgb() );
    BLShadow->convertFromImage(tmp);

    URShadow->convertFromImage(tmp.mirror(true, true));
  }

  // Draw right and bottom shadows
  for(int i=0; i<4; i++)
  {
    p.setPen(backgroundColor.light(shadow_strip[i]));
    // Right shadow
    p.drawLine(pageSize().width()+i+2, 8, pageSize().width()+i+2, pageSize().height()+2);
    // Bottom shadow
    p.drawLine(8, pageSize().height()+i+2, pageSize().width()+2, pageSize().height()+i+2);
  }
  // Draw shadow corners
  p.drawPixmap(pageSize().width()+2, pageSize().height()+2, *BRShadow);
  p.drawPixmap(4, pageSize().height()+2, *BLShadow);
  p.drawPixmap(pageSize().width()+2, 4, *URShadow);

  // Draw corners
  p.fillRect(0, pageSize().height()+2, 4, 4, backgroundColor);
  p.fillRect(pageSize().width()+2, 0, 4, 4, backgroundColor);

  if (!documentCache->isPageCached(pageNr, pageSize()))
  {
    QRect destRect = e->rect().intersect(pageRect());
    if (KVSPrefs::changeColors() && KVSPrefs::renderMode() == KVSPrefs::EnumRenderMode::Paper)
      p.fillRect(destRect, KVSPrefs::paperColor());
    else
      p.fillRect(destRect, Qt::white);

    // Draw busy indicator.
    // Im not really sure if this is a good idea.
    // While it is nice to see an indication that something is happening for pages which
    // take long to redraw, it gets quite annoing for fast redraws.
    // TODO: Disable or find something less distractiong.
    p.drawPixmap(10, 10, *busyIcon);

    if (!pixmapRequested)
    {
      // Request page pixmap.
      pixmapRequested = true;
      QTimer::singleShot(50, this, SLOT(delayedRequestPage()));
    }
    return;
  }

  RenderedDocumentPagePixmap *pageData = documentCache->getPage(pageNr);
  if (pageData == 0) {
#ifdef DEBUG_DOCUMENTWIDGET
    kdDebug(1223) << "DocumentWidget::paintEvent: no documentPage generated" << endl;
#endif
    return;
  }

  QMemArray<QRect> damagedRects = e->region().rects();
  for (unsigned int i = 0; i < damagedRects.count(); i++)
  {
    // Paint the page where it intersects with the damaged area.
    QRect destRect = damagedRects[i].intersect(pageRect());

    // The actual page starts at point (1,1) because of the outline.
    // Therefore we need to shift the destination rectangle.
    QRect pixmapRect = destRect;
    pixmapRect.moveBy(-1,-1);

    if (KVSPrefs::changeColors() && KVSPrefs::renderMode() != KVSPrefs::EnumRenderMode::Paper)
    {
      // Paint widget contents with accessibility changes.
      QPixmap pdpix = pageData->accessiblePixmap();
      bitBlt ( this, destRect.topLeft(), &pdpix, pixmapRect, CopyROP);
    }
    else
    {
      // Paint widget contents
      bitBlt ( this, destRect.topLeft(), pageData, pixmapRect, CopyROP);
    }
  }
  // Underline hyperlinks
  if (KVSPrefs::underlineLinks() == KVSPrefs::EnumUnderlineLinks::Enabled ||
      KVSPrefs::underlineLinks() == KVSPrefs::EnumUnderlineLinks::OnlyOnHover)
  {
    int h = 2; // Height of line.
    for(int i = 0; i < (int)pageData->hyperLinkList.size(); i++) 
    {
      if (KVSPrefs::underlineLinks() == KVSPrefs::EnumUnderlineLinks::OnlyOnHover && 
          i != indexOfUnderlinedLink)
        continue;
      int x = pageData->hyperLinkList[i].box.left();
      int w = pageData->hyperLinkList[i].box.width();
      int y = pageData->hyperLinkList[i].baseline;

      QRect hyperLinkRect(x, y, w, h);
      if (hyperLinkRect.intersects(e->rect()))
      {
#ifdef DEBUG_DOCUMENTWIDGET
        kdDebug(1223) << "Underline hyperlink \"" << pageData->hyperLinkList[i].linkText << "\"" << endl;
#endif
        p.fillRect(x, y, w, h, KGlobalSettings::linkColor());
      }
    }
  }

  // Paint flashing frame, if appropriate
  if (animationCounter > 0 && animationCounter < 10)
  {
    int gbChannel = 255 - (9-animationCounter)*28;
    p.setPen(QPen(QColor(255, gbChannel, gbChannel), 3));
    p.drawRect(linkFlashRect());
  }

  // Mark selected text.
  TextSelection selection = documentCache->selectedText();
  if ((selection.getPageNumber() != 0) && (selection.getPageNumber() == pageNr))
  {
    if (selectionNeedsUpdating)
    {
      //The zoom value has changed, therefore we need to recalculate
      //the selected region.
      selectedRegion = pageData->selectedRegion(selection);
      selectionNeedsUpdating = false;
    }

    p.setPen(NoPen);
    p.setBrush(white);
    p.setRasterOp(Qt::XorROP);

    QMemArray<QRect> selectionRects = selectedRegion.rects();

    for (unsigned int i = 0; i < selectionRects.count(); i++)
      p.drawRect(selectionRects[i]);
  }

  // Draw scroll Guide
  if (scrollGuide >= 0)
  {
    // Don't draw over the page shadow
    p.setClipRegion(e->region().intersect(pageRect()));
    p.setRasterOp(Qt::CopyROP);
    p.setPen(Qt::red);
    p.drawLine(1, scrollGuide, pageSize().width(), scrollGuide);
  }
}