screensaver/screensaverplugins/snsrbigclockscreensaverplugin/src/snsrbigclockcontainer.cpp
changeset 97 66b5fe3c07fd
parent 95 32e56106abf2
child 98 e6f74eb7f69f
equal deleted inserted replaced
95:32e56106abf2 97:66b5fe3c07fd
     1 /*
       
     2 * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Base class container.
       
    15 *
       
    16 */
       
    17 
       
    18 #include "snsrbigclockcontainer.h"
       
    19 
       
    20 #include <QPainter>
       
    21 #include <QDebug>
       
    22 #include <QTime>
       
    23 #include <QGraphicsLinearLayout>
       
    24 
       
    25 #include <HbEvent>
       
    26 #include <HbColorScheme>
       
    27 #include <HbMainWindow>
       
    28 
       
    29 #include "snsrbigclockcontainer.h"
       
    30 #include "snsrindicatorwidget.h"
       
    31 #include "snsrindicatormodel.h"
       
    32 
       
    33 /*!
       
    34     \class SnsrBigClockContainer
       
    35     \ingroup group_snsrbigclockscreensaverplugin
       
    36     \brief Base class. Container used for drawing background and for preparing layout.
       
    37  */
       
    38 
       
    39 
       
    40 
       
    41 const int gStep(5);
       
    42 
       
    43 
       
    44 /*!
       
    45     Constructs a new SnsrBigClockContainer.
       
    46  */
       
    47 SnsrBigClockContainer::SnsrBigClockContainer() :
       
    48     mBackgroundContainerLayout(0),
       
    49     mMainView(0),
       
    50     mMainContainer(0),
       
    51     mIndicatorModel(0),
       
    52     mIndicatorWidget(0),
       
    53     mCurrentOrientation(-1)
       
    54 {
       
    55     setBackgroundColor();
       
    56     mBackgroundContainerLayout = new QGraphicsLinearLayout(Qt::Vertical, this);
       
    57     setLayout(mBackgroundContainerLayout);
       
    58     qsrand(QTime::currentTime().msec());
       
    59 }
       
    60 
       
    61 /*!
       
    62     Destructs the class.
       
    63  */
       
    64 SnsrBigClockContainer::~SnsrBigClockContainer()
       
    65 {    
       
    66     // e.g. mIndicatorWidget gets deleted during these calls
       
    67     mDocumentLoader.reset();
       
    68     qDeleteAll(mDocumentObjects);
       
    69     mDocumentObjects.clear();
       
    70 
       
    71     //mMainContainer,mBackgroundContainerLayout - deleted by the parent
       
    72     mIndicatorModel=0; // not owned
       
    73 }
       
    74 
       
    75 /*!
       
    76     \fn virtual void update() = 0;
       
    77 
       
    78     Slot for members update in container e.g. when time or date changed.
       
    79  */
       
    80 
       
    81 /*!
       
    82     Changes screensaver layout based on orientation changes.
       
    83     \param orientation Current orientation.
       
    84  */
       
    85 void SnsrBigClockContainer::changeLayout(Qt::Orientation orientation)
       
    86 {
       
    87     SCREENSAVER_TEST_FUNC_ENTRY("SnsrBigClockContainer::changeLayout")
       
    88 
       
    89     if (mCurrentOrientation != orientation) {
       
    90         mCurrentOrientation = orientation;
       
    91         
       
    92         // delete any old widgets
       
    93         if ( mBackgroundContainerLayout->count() ) {
       
    94             mBackgroundContainerLayout->removeAt(0);
       
    95         }
       
    96         mDocumentLoader.reset();
       
    97         qDeleteAll(mDocumentObjects);
       
    98         mDocumentObjects.clear();
       
    99 
       
   100         // reload widgets from docml
       
   101         loadWidgets();
       
   102     }
       
   103     mBackgroundContainerLayout->setGeometry( mainWindow()->layoutRect() );
       
   104     update();
       
   105 
       
   106     SCREENSAVER_TEST_FUNC_EXIT("SnsrBigClockContainer::changeLayout")
       
   107 }
       
   108 
       
   109 /*!
       
   110     Set used indicator model that is owned by the screensaver class. 
       
   111     Model's life cycle must be the same as screensaver's so that indicators'
       
   112     status data can be kept in memory and one can receive updates. 
       
   113     This method should be called when the current container is set.
       
   114  */
       
   115 void SnsrBigClockContainer::setIndicatorModel(SnsrIndicatorModel &model)
       
   116 {
       
   117     mIndicatorModel = &model;
       
   118 }
       
   119 
       
   120 /*!
       
   121     @copydoc Screensaver::currentPowerMode()
       
   122  */
       
   123 Screensaver::ScreenPowerMode SnsrBigClockContainer::displayPowerMode()
       
   124 {
       
   125     // The default implementation returns full power mode. Inherited classes
       
   126     // must override this if low power or display off mode are required.
       
   127     return Screensaver::ScreenModeFullPower;
       
   128 }
       
   129 
       
   130 /*!
       
   131     @copydoc Screensaver::getActiveScreenRows()
       
   132  */
       
   133 void SnsrBigClockContainer::getActiveScreenRows(int *firstActiveRow, int *lastActiveRow)
       
   134 {
       
   135     // This default implementation return the whole area of the
       
   136     // container. Inherited low power mode containers can and should
       
   137     // return smaller area which just barely encloses all the content.
       
   138     if ( mMainContainer ) {
       
   139         QRect mainRect = mMainContainer->rect().toRect();
       
   140         if ( mCurrentOrientation == Qt::Vertical ) {
       
   141             *firstActiveRow = mainRect.top();
       
   142             *lastActiveRow = mainRect.bottom();
       
   143         }
       
   144         else {
       
   145             *firstActiveRow = mainRect.left();
       
   146             *lastActiveRow = mainRect.right();
       
   147         }
       
   148     }
       
   149 }
       
   150 
       
   151 /*!
       
   152     Tell if this container wants to lock the screen orientation.
       
   153     Default implementation in not locked but inherited classes may
       
   154     override this.
       
   155  */
       
   156 bool SnsrBigClockContainer::isOrientationLocked()
       
   157 {
       
   158     return false;
       
   159 }
       
   160 
       
   161 /*!
       
   162     \fn virtual int updateIntervalInMilliseconds() = 0;
       
   163 
       
   164     Concrete inherited container classes must implement this to return
       
   165     the desired update interval for that clock mode.
       
   166  */
       
   167 
       
   168 /*!
       
   169     \fn virtual int loadWidgets() = 0;
       
   170 
       
   171     Concrete inherited container classes must implement this to instantiate
       
   172     all the widgets shown in the container. The base class calls this
       
   173     method when screen layuot is changed. The old widgets are already 
       
   174     deleted by the base class before this is called. Also changing the visible
       
   175     container is treated as a layout change, and results in call to this method.
       
   176     Thus, inherited containers don't have to load their widgets yet in their
       
   177     constructors.
       
   178  */
       
   179 
       
   180 /*!
       
   181     \reimp
       
   182  */
       
   183 void SnsrBigClockContainer::changeEvent(QEvent *event)
       
   184 {
       
   185     if (event->type() == HbEvent::ThemeChanged) {
       
   186         setBackgroundColor();
       
   187     }
       
   188     return QGraphicsWidget::changeEvent(event);
       
   189 }
       
   190 
       
   191 /*!
       
   192     Returns random point for given range.
       
   193     \param rect Area within which the generated point will be.
       
   194  */
       
   195 QPointF SnsrBigClockContainer::randomPosition(const QRectF &rect)
       
   196 {
       
   197     int width( rect.width() );
       
   198     int height( rect.height() );
       
   199     if ( width > 0 && height > 0 ) {
       
   200         return rect.topLeft() + QPointF( qrand()%width, qrand()%height );
       
   201     }
       
   202     else {
       
   203         return QPointF();
       
   204     }
       
   205 
       
   206 }
       
   207 
       
   208 /*!
       
   209     Returns new position between curRect position and destPos position.
       
   210     \param curPos Current position.
       
   211     \param destPos Destination position. When current position is near this
       
   212                    position or outside of the container, a new value is generated.
       
   213     \param containerRect The container within which the destination position will always
       
   214                          be after a call.
       
   215  */
       
   216 QPointF SnsrBigClockContainer::nextRandomPosition(const QPointF &curPos, QPointF &destPos, const QRectF &containerRect)
       
   217 {
       
   218     const int delta(gStep+2);
       
   219     const int minCntDimension(3*delta);
       
   220 
       
   221     // The random movement logic can work only if the container has enough space to move the
       
   222     // clock around. If the container is too small, just return the middle point of the container.
       
   223     if ( containerRect.width() < minCntDimension && containerRect.height() < minCntDimension ) {
       
   224         return containerRect.center();
       
   225     }
       
   226     
       
   227     int xDistance = abs( destPos.x() - curPos.x() );
       
   228     int yDistance = abs( destPos.y() - curPos.y() );
       
   229     
       
   230     // Generate new destination position when current widget position is close to 
       
   231     // destination random position or when current destination position is out of bounds.
       
   232     // It is possible that the new random position is very close to the current position,
       
   233     // in which case the random position is generated again.
       
   234     // It is paramount that container is large enough when next loop is entered
       
   235     // to prevent infinite looping.
       
   236     while ( (xDistance < delta && yDistance < delta)
       
   237             || !containerRect.contains(destPos) ) {
       
   238         destPos = randomPosition( containerRect );
       
   239         xDistance = abs( destPos.x() - curPos.x() );
       
   240         yDistance = abs( destPos.y() - curPos.y() );
       
   241     }
       
   242 
       
   243     // If, for some reason, the current position is out-of-bounds, then there's no
       
   244     // point to slowly move towards the destination. In that case, move immediately
       
   245     // to destination point.
       
   246     if ( !containerRect.contains(curPos) ) {
       
   247         return destPos;
       
   248     }
       
   249     // Otherwise, this is normal case and we will calculate a point which is just
       
   250     // a bit closer to the destination.
       
   251     
       
   252     // Version 1:
       
   253     //  o-----o---------------------------o
       
   254     //  p1    p2                          p3
       
   255     //
       
   256     // Version 2:
       
   257     //  o---------------------------o-----o
       
   258     //  p3                          p2    p1
       
   259     //
       
   260     // p1 - current widget position
       
   261     // p2 - next position to compute
       
   262     // p3 - destination random position
       
   263     QPointF p1(curPos);
       
   264     QPointF p2(0,0);
       
   265     QPointF p3(destPos);
       
   266 
       
   267     // Computes point p2 - new position between p1 and p3
       
   268 
       
   269     // Move the coordinate which is further away from the destination
       
   270     // and calculate the other coordinate from that so that the
       
   271     // result point p2 lies on the straigth line between p1 and p3.
       
   272     if ( yDistance > xDistance ) {
       
   273         if (p3.y() > p1.y()) {
       
   274             p2.setY(p1.y()+gStep);
       
   275         }
       
   276         else {
       
   277             p2.setY(p1.y()-gStep);
       
   278         }
       
   279         p2.setX((((p2.y()-p1.y())*(p3.x()-p1.x())) / (p3.y()-p1.y())) + p1.x()); // x2 = (((y2-y1)*(x3-x1)) / (y3-y1)) + x1
       
   280     }
       
   281     else {
       
   282         if (p3.x() > p1.x()) {
       
   283             p2.setX(p1.x()+gStep);
       
   284         }
       
   285         else {
       
   286             p2.setX(p1.x()-gStep);
       
   287         }
       
   288         p2.setY((((p3.y()-p1.y())*(p2.x()-p1.x())) / (p3.x()-p1.x())) + p1.y()); // y2 = (((y3-y1)*(x2-x1)) / (x3-x1)) + y1
       
   289     }
       
   290 
       
   291     // Return new position between points p1 and p3.
       
   292     return p2;
       
   293 }
       
   294 
       
   295 /*!
       
   296     Do necessary initializations to show currently active indicators.
       
   297     Should be called after the indicator widget is created.
       
   298  */
       
   299 void SnsrBigClockContainer::initIndicatorWidget()
       
   300 {
       
   301     Q_ASSERT(mIndicatorModel && mIndicatorWidget);
       
   302     
       
   303     connect(mIndicatorModel, SIGNAL(indicatorsUpdated(QList<SnsrIndicatorInfo>)),
       
   304             mIndicatorWidget, SLOT(showIndicators(QList<SnsrIndicatorInfo>)));
       
   305                 
       
   306     connect(mIndicatorModel, SIGNAL(allIndicatorsDeactivated()),
       
   307             mIndicatorWidget, SLOT(removeAllIndicators()));
       
   308         
       
   309     mIndicatorModel->initializeIndicatorWidget();
       
   310 }
       
   311 
       
   312 /*!
       
   313     Disconnect connections between indicator model and widget.
       
   314     Should be called before deleting the indicator widget.
       
   315  */
       
   316 void SnsrBigClockContainer::resetIndicatorConnections()
       
   317 {   
       
   318     if (mIndicatorWidget && mIndicatorModel) {
       
   319         disconnect(mIndicatorModel, SIGNAL(indicatorsUpdated(QList<SnsrIndicatorInfo>)),
       
   320                    mIndicatorWidget, SLOT(showIndicators(QList<SnsrIndicatorInfo>)));
       
   321         
       
   322         disconnect(mIndicatorModel, SIGNAL(allIndicatorsDeactivated()),
       
   323                    mIndicatorWidget, SLOT(removeAllIndicators()));
       
   324     }
       
   325 }
       
   326 
       
   327 /*!
       
   328     Set background color.
       
   329  */
       
   330 void SnsrBigClockContainer::setBackgroundColor()
       
   331 {
       
   332     mBackgroundColor = Qt::black;
       
   333 }
       
   334 
       
   335 /*!
       
   336     Paints the contents of an item in local coordinates.
       
   337  */
       
   338 #ifdef COVERAGE_MEASUREMENT
       
   339 #pragma CTC SKIP
       
   340 #endif //COVERAGE_MEASUREMENT
       
   341 void SnsrBigClockContainer::paint(
       
   342         QPainter *painter,
       
   343         const QStyleOptionGraphicsItem *option,
       
   344         QWidget *widget
       
   345         )
       
   346 {
       
   347     Q_UNUSED(option)
       
   348     Q_UNUSED(widget)
       
   349 
       
   350     painter->fillRect(rect(), mBackgroundColor);
       
   351 }
       
   352 #ifdef COVERAGE_MEASUREMENT
       
   353 #pragma CTC ENDSKIP
       
   354 #endif //COVERAGE_MEASUREMENT
       
   355