• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kviewshell

pageView.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Wilco Greven <greven@kde.org>
00003    Copyright (C) 2002-2004 Stefan Kebekus <kebekus@kde.org>
00004    Copyright (C) 2004-2005 Wilfried Huss <Wilfried.Huss@gmx.at>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019    Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include <config.h>
00023 
00024 #include <kdebug.h>
00025 #include <qcursor.h>
00026 #include <qpainter.h>
00027 #include <qrect.h>
00028 #include <math.h>
00029 
00030 #include "pageView.h"
00031 #include "pageNumber.h"
00032 
00033 PageView::PageView( QWidget* parent, const char* name )
00034   : QScrollView( parent, name, WStaticContents | WNoAutoErase)
00035 {
00036   moveTool = true;
00037 
00038   widgetList = 0;
00039   viewport()->setFocusPolicy(QWidget::StrongFocus);
00040 
00041   setResizePolicy(QScrollView::Manual);
00042 
00043   setVScrollBarMode(QScrollView::Auto);
00044   setHScrollBarMode(QScrollView::Auto);
00045 
00046   viewport()->setBackgroundMode(Qt::NoBackground);
00047 
00048   setResizePolicy(Manual);
00049   setDragAutoScroll(false);
00050 
00051   enableClipper(true);
00052   nrCols = 1;
00053   nrRows = 1;
00054   continuousViewmode = true;
00055   fullScreen = false;
00056 
00057   connect(this, SIGNAL(contentsMoving(int, int)), this, SLOT(calculateCurrentPageNumber(int, int)));
00058 }
00059 
00060 
00061 void PageView::addChild( QPtrVector<DocumentWidget> *wdgList )
00062 {
00063   if( wdgList == 0 ) {
00064     kdError(1223) << "PageView::addChild(...) called with invalid arguments" << endl;
00065     return;
00066   }
00067 
00068   widgetList = wdgList;
00069   layoutPages();
00070 }
00071 
00072 
00073 bool PageView::atTop() const
00074 {
00075   return verticalScrollBar()->value() == verticalScrollBar()->minValue();
00076 }
00077 
00078 
00079 bool PageView::atBottom() const 
00080 {
00081   return verticalScrollBar()->value() == verticalScrollBar()->maxValue();
00082 }
00083 
00084 
00085 bool PageView::readUp()
00086 {
00087   if( atTop() )
00088     return false;
00089   else {
00090     // Coordinate of the top of the viewport
00091     int top = contentsY();
00092 
00093     DocumentWidget* widget = 0;
00094     // Find the widget(s) that intersect the top of the viewport
00095     // TODO: It would be better to use a binary search.
00096     for(Q_UINT16 i=0; i<widgetList->size(); i++)
00097     {
00098       widget = widgetList->at(i);
00099       if (childY(widget) < top && childY(widget) + widget->height() > top)
00100       {
00101         // Draw scrollguide
00102         widget->drawScrollGuide(top - childY(widget));
00103       }
00104     }
00105 
00106     int newValue = QMAX( verticalScrollBar()->value() - (int)(height() * 0.9),
00107                          verticalScrollBar()->minValue() );
00108     verticalScrollBar()->setValue( newValue );
00109     return true;
00110   }
00111 }
00112 
00113 
00114 bool PageView::readDown()
00115 {
00116   if( atBottom() )
00117     return false;
00118   else {
00119     // Coordinate of the bottom of the viewport
00120     int bottom = contentsY() + visibleHeight();
00121 
00122     DocumentWidget* widget = 0;
00123     // Find the widget(s) that intersect the bottom of the viewport
00124     // TODO: It would be better to use a binary search.
00125     for(Q_UINT16 i=0; i<widgetList->size(); i++)
00126     {
00127       widget = widgetList->at(i);
00128       if (childY(widget) < bottom && childY(widget) + widget->height() > bottom)
00129       {
00130         // Draw scrollguide
00131         widget->drawScrollGuide(bottom - childY(widget));
00132       }
00133     }
00134 
00135     int newValue = QMIN( verticalScrollBar()->value() + (int)(height() * 0.9),
00136                          verticalScrollBar()->maxValue() );
00137     verticalScrollBar()->setValue( newValue );
00138 
00139     return true;
00140   }
00141 }
00142 
00143 
00144 void PageView::scrollRight()
00145 {
00146   horizontalScrollBar()->addLine();
00147 }
00148 
00149 void PageView::scrollLeft()
00150 {
00151   horizontalScrollBar()->subtractLine();
00152 }
00153 
00154 void PageView::scrollDown()
00155 {
00156   verticalScrollBar()->addLine();
00157 }
00158 
00159 void PageView::scrollUp()
00160 {
00161   verticalScrollBar()->subtractLine();
00162 }
00163 
00164 void PageView::scrollBottom()
00165 {
00166   verticalScrollBar()->setValue( verticalScrollBar()->maxValue() );
00167 }
00168 
00169 void PageView::scrollTop()
00170 {
00171   verticalScrollBar()->setValue( verticalScrollBar()->minValue() );
00172 }
00173 
00174 void PageView::keyPressEvent( QKeyEvent* e )
00175 {
00176   switch ( e->key() ) {
00177     case Key_Up:
00178       scrollUp();
00179       break;
00180     case Key_Down:
00181       scrollDown();
00182       break;
00183     case Key_Left:
00184       scrollLeft();
00185       break;
00186     case Key_Right:
00187       scrollRight();
00188       break;
00189     default:
00190       e->ignore();
00191       return;
00192   }
00193   e->accept();
00194 }
00195 
00196 void PageView::contentsMousePressEvent( QMouseEvent* e )
00197 {
00198   if (e->button() == LeftButton)
00199   {
00200     if (moveTool)
00201     {
00202       setCursor(Qt::SizeAllCursor);
00203       dragGrabPos = e->globalPos();
00204     }
00205     else
00206     {
00207       // we are in selection mode
00208     }
00209   }
00210   else
00211   {
00212     setCursor(Qt::arrowCursor);
00213   }
00214 }
00215 
00216 void PageView::contentsMouseReleaseEvent( QMouseEvent* )
00217 {
00218   setCursor(Qt::arrowCursor);
00219 }
00220 
00221 void PageView::contentsMouseMoveEvent( QMouseEvent* e )
00222 {
00223   QPoint newPos = e->globalPos();
00224 
00225   if (e->state() == LeftButton && moveTool)
00226   {
00227     QPoint delta = dragGrabPos - newPos;
00228     scrollBy(delta.x(), delta.y());
00229   }
00230   dragGrabPos = newPos;
00231 }
00232 
00233 void PageView::viewportResizeEvent( QResizeEvent* e )
00234 {
00235   QScrollView::viewportResizeEvent( e );
00236 
00237   if (!widgetList)
00238     return;
00239 
00240   layoutPages();
00241 
00242   emit viewSizeChanged( viewport()->size() );
00243 }
00244 
00245 void PageView::setNrColumns( Q_UINT8 cols )
00246 {
00247   nrCols = cols;
00248 }
00249 
00250 void PageView::setNrRows( Q_UINT8 rows )
00251 {
00252   nrRows = rows;
00253 }
00254 
00255 void PageView::setContinuousViewMode(bool continuous)
00256 {
00257   continuousViewmode = continuous;
00258 }
00259 
00260 bool PageView::singlePageFullScreenMode()
00261 {
00262   return (nrCols == 1 && nrRows == 1 && !continuousViewmode && fullScreen);
00263 }
00264 
00265 void PageView::slotShowScrollbars(bool status)
00266 {
00267   if (status == true) {
00268     setVScrollBarMode(QScrollView::Auto);
00269     setHScrollBarMode(QScrollView::Auto);
00270   } else {
00271     setVScrollBarMode(QScrollView::AlwaysOff);
00272     setHScrollBarMode(QScrollView::AlwaysOff);
00273   }
00274 }
00275 
00276 void PageView::setFullScreenMode(bool fullScreen)
00277 {
00278   this -> fullScreen = fullScreen;
00279   if (fullScreen == true) 
00280   {
00281     setVScrollBarMode(QScrollView::AlwaysOff);
00282     setHScrollBarMode(QScrollView::AlwaysOff);
00283     oldFrameStyle = frameStyle();
00284     setFrameStyle(QFrame::NoFrame);
00285     backgroundColor = viewport()->paletteBackgroundColor();
00286     if (singlePageFullScreenMode())
00287     {
00288       viewport()->setPaletteBackgroundColor( Qt::black ) ;
00289     }
00290   }
00291   else
00292   {
00293     viewport()->setPaletteBackgroundColor( backgroundColor ) ;
00294     setFrameStyle(oldFrameStyle);
00295   }
00296 }
00297 
00298 void PageView::layoutPages(bool zoomChanged)
00299 {
00300   // Paranoid safety check
00301   if (widgetList == 0)
00302     return;
00303 
00304   // If there are no widgets, e.g. because the last widget has been
00305   // removed, the matter is easy: set the contents size to 0. If there
00306   // are no widgets because previously existing widgets were removed
00307   // (we detect that by looking at the contentsWidth and -Height).
00308   if (widgetList->isEmpty()) {
00309     if ((contentsWidth() != 0) || (contentsHeight() != 0)) {
00310       QScrollView::resizeContents(0,0);
00311     }
00312     return;
00313   }
00314 
00315   // Ok, now we are in a situation where we do have some widgets that
00316   // shall be centered.
00317   int distance = distanceBetweenWidgets;
00318   if (singlePageFullScreenMode())
00319   {
00320     // In single page fullscreen mode we don't want a margin around the pages
00321     distance = 0;
00322   }
00323 
00324   QMemArray<Q_UINT32> colWidth(nrCols);
00325   for(Q_UINT8 i=0; i<colWidth.size(); i++)
00326     colWidth[i] = 0;
00327 
00328   Q_UINT16 numRows;
00329   if(nrCols <= 2)
00330   {
00331     numRows = (widgetList->size()+2*nrCols-2) / nrCols;
00332   }
00333   else
00334   {
00335     numRows = (Q_INT16)ceil(((double)widgetList->size()) / nrCols);
00336   }
00337 
00338   QMemArray<Q_UINT32> rowHeight(numRows);
00339   for(Q_UINT16 i=0; i<rowHeight.size(); i++)
00340     rowHeight[i] = 0;
00341 
00342   // Now find the widths and heights of the columns
00343   for(Q_UINT16 i=0; i<widgetList->size(); i++) 
00344   {
00345     Q_UINT8 col;
00346     Q_UINT16 row;
00347 
00348     if (nrCols == 2) {
00349       // In two-column display, start with the right column
00350       col = (i+1+nrCols) % nrCols;
00351       row = (i+1+nrCols) / nrCols - 1;
00352     } else {
00353       col = (i+nrCols) % nrCols;
00354       row = (i+nrCols) / nrCols - 1;
00355     }
00356 
00357     colWidth[col] = QMAX(colWidth[col], (Q_UINT32)widgetList->at(i)->pageSize().width());
00358     rowHeight[row] = QMAX(rowHeight[row], (Q_UINT32)widgetList->at(i)->pageSize().height());
00359   }
00360 
00361   // Calculate the total width and height of the display
00362   Q_UINT32 totalHeight = 0;
00363   for(Q_UINT16 i=0; i<rowHeight.size(); i++)
00364     totalHeight += rowHeight[i];
00365 
00366   totalHeight += (numRows+1)*distance;
00367   Q_UINT32 totalWidth = 0;
00368   for(Q_UINT8 i=0; i<colWidth.size(); i++)
00369     totalWidth += colWidth[i];
00370 
00371   totalWidth += (nrCols+1)*distance;
00372   QSize newViewportSize = viewportSize( totalWidth, totalHeight );
00373   Q_UINT32 centeringLeft = 0;
00374   if( (Q_UINT32)newViewportSize.width() > totalWidth )
00375     centeringLeft = ( newViewportSize.width() - totalWidth )/2;
00376   Q_UINT32 centeringTop = 0;
00377   if( (Q_UINT32)newViewportSize.height() > totalHeight )
00378     centeringTop = ( newViewportSize.height() - totalHeight)/2;
00379 
00380   // Resize the viewport
00381   if (((Q_UINT32)contentsWidth() != totalWidth) || ((Q_UINT32)contentsHeight() != totalHeight))
00382   {
00383     // Calculate the point in the coordinates of the contents which is currently at the center of the viewport.
00384     QPoint midPoint = QPoint(visibleWidth() / 2 + contentsX(), visibleHeight() / 2 + contentsY()); 
00385     double midPointRatioX = (double)(midPoint.x()) / contentsWidth();
00386     double midPointRatioY = (double)(midPoint.y()) / contentsHeight();
00387 
00388     resizeContents(totalWidth,totalHeight);
00389 
00390     // If the zoom changed recenter the former midPoint
00391     if (zoomChanged)
00392       center((int)(contentsWidth() * midPointRatioX), (int)(contentsHeight() * midPointRatioY));
00393   }
00394 
00395   // Finally, calculate the left and top coordinates of each row and
00396   // column, respectively
00397   QMemArray<Q_UINT32> colLeft(nrCols);
00398   colLeft[0] = distance;
00399   for(Q_UINT8 i=1; i<colLeft.size(); i++)
00400     colLeft[i] = colLeft[i-1]+colWidth[i-1]+distance;
00401 
00402   QMemArray<Q_UINT32> rowTop(numRows);
00403   rowTop[0] = distance;
00404   for(Q_UINT16 i=1; i<rowTop.size(); i++)
00405     rowTop[i] = rowTop[i-1]+rowHeight[i-1]+distance;
00406 
00407   for(Q_UINT16 i=0; i<widgetList->size(); i++) 
00408   {
00409     Q_UINT8 col;
00410     Q_UINT16 row;
00411     if (nrCols == 2)
00412     {
00413       // In two column-mode start with the right column.
00414       col = (i+nrCols-1) % nrCols;
00415       row = (i+nrCols-1) / nrCols;
00416     }
00417     else
00418     {
00419       col = (i+nrCols) % nrCols;
00420       row = i / nrCols;
00421     }
00422     if (nrCols == 2)
00423     {
00424       // in 2-column mode right justify the first column, and leftjustify the second column
00425       int width = widgetList->at(i)->width();
00426       int left;
00427       if (col == 0)
00428         left = centeringLeft + colLeft[col] + colWidth[col]-width + distance/2;
00429       else
00430         left = centeringLeft + colLeft[col];
00431       moveChild( widgetList->at(i), left, centeringTop+rowTop[row]);
00432     }
00433     else
00434     {
00435       // in single column and overview mode center the widgets
00436       int widgetWidth = widgetList->at(i)->width();
00437       int left = centeringLeft + colLeft[col] + ((int)colWidth[col]-widgetWidth)/2;
00438       moveChild(widgetList->at(i), left, centeringTop+rowTop[row]);
00439     }
00440   }
00441   calculateCurrentPageNumber();
00442 }
00443 
00444 
00445 void PageView::contentsWheelEvent ( QWheelEvent * e )
00446 {
00447   emit(wheelEventReceived(e));
00448 }
00449 
00450 
00451 void PageView::moveViewportToWidget(QWidget* widget, int y)
00452 {
00453   int verticalPos = 0;
00454   int verticalPosTop = 0;
00455 
00456   if (y != 0)
00457   {
00458     verticalPosTop = childY(widget) +  y - visibleHeight()/2;
00459     verticalPos = childY(widget) +  y;
00460   }
00461   else
00462   {
00463     verticalPos = childY(widget) - distanceBetweenWidgets;
00464     verticalPosTop = verticalPos;
00465   }
00466 
00467   if (nrCols == 1)
00468   {
00469     // In single column viewmodes, we change the vertical position only, to make it
00470     // easier to work with high zoomlevels where not the whole pagewidth is visible.
00471     // TODO: Smarter algorithm also for continuous facing viewmode.
00472     int top = (int)(contentsY() + 0.1 * visibleHeight());
00473     int bottom = (int)(contentsY() + 0.9 * visibleHeight());
00474 
00475     // Move the viewport if the target is currently not visible, or lies at the edge
00476     // of the viewport. If y = 0 always move the top of the targetpage to the top edge
00477     // of the viewport.
00478     if (verticalPos < top || verticalPos > bottom || y == 0)
00479     {
00480       setContentsPos(contentsX(), verticalPosTop);
00481     }
00482   }
00483   else
00484   {
00485     setContentsPos(childX(widget) - distanceBetweenWidgets, verticalPosTop);
00486   }
00487 }
00488 
00489 
00490 void PageView::viewportPaintEvent(QPaintEvent* e)
00491 {
00492   // Region from which rectangles occupied by child widgets will by substracted.
00493   QRegion backgroundArea(e->rect());
00494 
00495   if (widgetList != 0)
00496   {
00497     for (unsigned int i = 0; i < widgetList->count(); i++)
00498     {
00499       DocumentWidget* item = widgetList->at(i);
00500 
00501       // Check if the Widget needs to be updated.
00502       if (!item->geometry().intersects(e->rect()))
00503         continue;
00504 
00505       QRect widgetGeometry = item->geometry();
00506 
00507       // Draw the widget.
00508       if (e->rect().intersects(widgetGeometry))
00509       {
00510         QRect widgetRect = e->rect().intersect(widgetGeometry);
00511         widgetRect.moveBy(-widgetGeometry.left(), -widgetGeometry.top());
00512 
00513         item->update(widgetRect);
00514       }
00515 
00516       // Substract the painted area.
00517       backgroundArea -= widgetGeometry.intersect(e->rect());
00518     }
00519   }
00520 
00521   // Paint the background.
00522   QPainter p(viewport());
00523 
00524   QMemArray<QRect> backgroundRects = backgroundArea.rects();
00525 
00526   for (unsigned int i = 0; i < backgroundRects.count(); i++)
00527     p.fillRect(backgroundRects[i], colorGroup().mid());
00528 }
00529 
00530 
00531 void PageView::calculateCurrentPageNumber(int x, int y)
00532 {
00533   // Safety check
00534   if (widgetList == 0)
00535     return;
00536 
00537   QRect viewportRect(x, y, visibleWidth(), visibleHeight());
00538 
00539   //kdDebug() << "viewportRect(" << viewportRect.x() << ", " << viewportRect.y() << ", "
00540   //          << viewportRect.width() << ", " << viewportRect.height() << ")" << endl;
00541 
00542   int maxVisiblePixels = 0;
00543   DocumentWidget* _currentWidget = 0;
00544 
00545   for (Q_UINT16 i = 0; i < widgetList->size(); i++)
00546   {
00547     DocumentWidget* documentWidget = widgetList->at(i);
00548     // Safety check
00549     if (documentWidget == 0)
00550       continue;
00551 
00552     // Check if the Widget is visible
00553     int cx = childX(documentWidget);
00554     int cy = childY(documentWidget);
00555     QRect widgetRect(cx, cy, documentWidget->width(), documentWidget->height());
00556     bool isVisible = widgetRect.intersects(viewportRect);
00557 
00558     if (!isVisible)
00559       continue;
00560 
00561     // Calculate the number of visible pixels of the widget
00562     QRect visibleRect = widgetRect.intersect(viewportRect);
00563     int visiblePixels = visibleRect.width() * visibleRect.height();
00564 
00565     //kdDebug() << visiblePixels << " pixels are visible of page " << documentWidget->getPageNumber() << endl;
00566 
00567     // If a bigger part of this widget as of the previous widgets is visible make it the current widget.
00568     if (maxVisiblePixels < visiblePixels)
00569     {
00570       maxVisiblePixels = visiblePixels;
00571       _currentWidget = documentWidget;
00572     }
00573   }
00574 
00575   // No page is visible
00576   if (_currentWidget == 0)
00577     return;
00578 
00579   // Return the number of the current page
00580   emit currentPageChanged(_currentWidget->getPageNumber());
00581 }
00582 
00583 void PageView::calculateCurrentPageNumber()
00584 {
00585   calculateCurrentPageNumber(contentsX(), contentsY());
00586 }
00587 
00588 void PageView::slotEnableMoveTool(bool enable)
00589 {
00590   moveTool = enable;
00591 }
00592 
00593 #include "pageView.moc"

kviewshell

Skip menu "kviewshell"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • kviewshell
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal