screensaver/snsrplugins/snsrbigclockscreensaverplugin/src/snsrbigclockcontainer.cpp
changeset 97 66b5fe3c07fd
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 #include <HbEffect>
       
    29 
       
    30 #ifdef Q_OS_SYMBIAN
       
    31 #include <xqsettingsmanager.h>
       
    32 #include <screensaverdomaincrkeys.h>
       
    33 #endif //Q_OS_SYMBIAN
       
    34 
       
    35 #include "snsrbigclockcontainer.h"
       
    36 #include "snsrindicatorwidget.h"
       
    37 #include "snsrindicatormodel.h"
       
    38 #include "snsrcolors.h"
       
    39 
       
    40 /*!
       
    41     \class SnsrBigClockContainer
       
    42     \ingroup group_snsrbigclockscreensaverplugin
       
    43     \brief Base class. Container used for drawing background and for preparing layout.
       
    44  */
       
    45 
       
    46 
       
    47 
       
    48 const int gStep(5);
       
    49 
       
    50 
       
    51 /*!
       
    52     Constructs a new SnsrBigClockContainer.
       
    53  */
       
    54 SnsrBigClockContainer::SnsrBigClockContainer() :
       
    55     mBackgroundContainerLayout(0),
       
    56     mMainView(0),
       
    57     mMainContainer(0),
       
    58     mIndicatorModel(0),
       
    59     mIndicatorWidget(0),
       
    60     mCurrentOrientation(-1)
       
    61 {
       
    62     setBackgroundColor();
       
    63     mBackgroundContainerLayout = new QGraphicsLinearLayout(Qt::Vertical, this);
       
    64     setLayout(mBackgroundContainerLayout);
       
    65     qsrand(QTime::currentTime().msec());
       
    66     connect( mainWindow(), SIGNAL(aboutToChangeOrientation()), SLOT(fadeOutView()) );
       
    67 }
       
    68 
       
    69 /*!
       
    70     Destructs the class.
       
    71  */
       
    72 SnsrBigClockContainer::~SnsrBigClockContainer()
       
    73 {
       
    74     // e.g. mIndicatorWidget gets deleted during this call
       
    75     resetWidgets();
       
    76 
       
    77     //mBackgroundContainerLayout - deleted by the parent
       
    78     mIndicatorModel = 0; // not owned
       
    79 }
       
    80 
       
    81 /*!
       
    82     \fn virtual void update() = 0;
       
    83 
       
    84     Slot for members update in container e.g. when time or date changed.
       
    85  */
       
    86 
       
    87 /*!
       
    88     Changes screensaver layout based on orientation changes.
       
    89     \param orientation Current orientation.
       
    90  */
       
    91 void SnsrBigClockContainer::changeLayout(Qt::Orientation orientation)
       
    92 {
       
    93     SCREENSAVER_TEST_FUNC_ENTRY("SnsrBigClockContainer::changeLayout")
       
    94 
       
    95     if (mCurrentOrientation != orientation) {
       
    96         mCurrentOrientation = orientation;
       
    97         
       
    98         // delete any old widgets
       
    99         if ( mBackgroundContainerLayout->count() ) {
       
   100             mBackgroundContainerLayout->removeAt(0);
       
   101         }
       
   102         resetWidgets();
       
   103 
       
   104         // reload widgets from docml
       
   105         loadWidgets();
       
   106         
       
   107         // register orientation effects for the newly loaded main view
       
   108         HbEffect::add( mMainView, "notificationdialog_appear", "appear" );
       
   109         HbEffect::add( mMainView, "notificationdialog_disappear", "disappear" );
       
   110     }
       
   111     mBackgroundContainerLayout->setGeometry( mainWindow()->layoutRect() );
       
   112     update();
       
   113 
       
   114     // Run the fade-in effect, except if this container is a low-power one.
       
   115     // In low-power mode, animations don't look good because of reduced 
       
   116     // color-depth and refresh rate.
       
   117     if ( displayPowerMode() == Screensaver::ScreenModeFullPower ) {
       
   118         HbEffect::start( mMainView, "appear" );
       
   119     }
       
   120 
       
   121     SCREENSAVER_TEST_FUNC_EXIT("SnsrBigClockContainer::changeLayout")
       
   122 }
       
   123 
       
   124 /*!
       
   125     Set used indicator model that is owned by the screensaver class. 
       
   126     Model's life cycle must be the same as screensaver's so that indicators'
       
   127     status data can be kept in memory and one can receive updates. 
       
   128     This method should be called when the current container is set.
       
   129  */
       
   130 void SnsrBigClockContainer::setIndicatorModel(SnsrIndicatorModel &model)
       
   131 {
       
   132     mIndicatorModel = &model;
       
   133 }
       
   134 
       
   135 /*!
       
   136     @copydoc Screensaver::currentPowerMode()
       
   137  */
       
   138 Screensaver::ScreenPowerMode SnsrBigClockContainer::displayPowerMode()
       
   139 {
       
   140     // The default implementation returns full power mode. Inherited classes
       
   141     // must override this if low power or display off mode are required.
       
   142     return Screensaver::ScreenModeFullPower;
       
   143 }
       
   144 
       
   145 /*!
       
   146     @copydoc Screensaver::getActiveScreenRows()
       
   147  */
       
   148 void SnsrBigClockContainer::getActiveScreenRows(int *firstActiveRow, int *lastActiveRow)
       
   149 {
       
   150     // This default implementation return the whole area of the
       
   151     // container. Inherited low power mode containers can and should
       
   152     // return smaller area which just barely encloses all the content.
       
   153     if ( mMainContainer ) {
       
   154         QRect mainRect = mMainContainer->rect().toRect();
       
   155         if ( mCurrentOrientation == Qt::Vertical ) {
       
   156             *firstActiveRow = mainRect.top();
       
   157             *lastActiveRow = mainRect.bottom();
       
   158         }
       
   159         else {
       
   160             *firstActiveRow = mainRect.left();
       
   161             *lastActiveRow = mainRect.right();
       
   162         }
       
   163     }
       
   164 }
       
   165 
       
   166 /*!
       
   167     Tell if this container wants to lock the screen orientation.
       
   168     Default implementation in not locked but inherited classes may
       
   169     override this.
       
   170  */
       
   171 bool SnsrBigClockContainer::isOrientationLocked()
       
   172 {
       
   173     return false;
       
   174 }
       
   175 
       
   176 /*!
       
   177     \fn virtual int updateIntervalInMilliseconds() = 0;
       
   178 
       
   179     Concrete inherited container classes must implement this to return
       
   180     the desired update interval for that clock mode.
       
   181  */
       
   182 
       
   183 /*!
       
   184     \fn virtual int loadWidgets() = 0;
       
   185 
       
   186     Concrete inherited container classes must implement this to instantiate
       
   187     all the widgets shown in the container. The base class calls this
       
   188     method when screen layuot is changed. The old widgets are already 
       
   189     deleted by the base class before this is called. Also changing the visible
       
   190     container is treated as a layout change, and results in call to this method.
       
   191     Thus, inherited containers don't have to load their widgets yet in their
       
   192     constructors.
       
   193  */
       
   194 
       
   195 /*!
       
   196     \reimp
       
   197  */
       
   198 void SnsrBigClockContainer::changeEvent(QEvent *event)
       
   199 {
       
   200     if (event->type() == HbEvent::ThemeChanged) {
       
   201         setBackgroundColor();
       
   202     }
       
   203     return QGraphicsWidget::changeEvent(event);
       
   204 }
       
   205 
       
   206 /*!
       
   207     Returns random point for given range.
       
   208     \param rect Area within which the generated point will be.
       
   209  */
       
   210 QPointF SnsrBigClockContainer::randomPosition(const QRectF &rect)
       
   211 {
       
   212     int width( rect.width() );
       
   213     int height( rect.height() );
       
   214     if ( width > 0 && height > 0 ) {
       
   215         return rect.topLeft() + QPointF( qrand()%width, qrand()%height );
       
   216     }
       
   217     else {
       
   218         return QPointF();
       
   219     }
       
   220 
       
   221 }
       
   222 
       
   223 /*!
       
   224     Returns new position between curRect position and destPos position.
       
   225     \param curPos Current position.
       
   226     \param destPos Destination position. When current position is near this
       
   227                    position or outside of the container, a new value is generated.
       
   228     \param containerRect The container within which the destination position will always
       
   229                          be after a call.
       
   230  */
       
   231 QPointF SnsrBigClockContainer::nextRandomPosition(const QPointF &curPos, QPointF &destPos, const QRectF &containerRect)
       
   232 {
       
   233     const int delta(gStep+2);
       
   234     const int minCntDimension(3*delta);
       
   235 
       
   236     // The random movement logic can work only if the container has enough space to move the
       
   237     // clock around. If the container is too small, just return the middle point of the container.
       
   238     if ( containerRect.width() < minCntDimension && containerRect.height() < minCntDimension ) {
       
   239         return containerRect.center();
       
   240     }
       
   241     
       
   242     int xDistance = abs( destPos.x() - curPos.x() );
       
   243     int yDistance = abs( destPos.y() - curPos.y() );
       
   244     
       
   245     // Generate new destination position when current widget position is close to 
       
   246     // destination random position or when current destination position is out of bounds.
       
   247     // It is possible that the new random position is very close to the current position,
       
   248     // in which case the random position is generated again.
       
   249     // It is paramount that container is large enough when next loop is entered
       
   250     // to prevent infinite looping.
       
   251     while ( (xDistance < delta && yDistance < delta)
       
   252             || !containerRect.contains(destPos) ) {
       
   253         destPos = randomPosition( containerRect );
       
   254         xDistance = abs( destPos.x() - curPos.x() );
       
   255         yDistance = abs( destPos.y() - curPos.y() );
       
   256     }
       
   257 
       
   258     // If, for some reason, the current position is out-of-bounds, then there's no
       
   259     // point to slowly move towards the destination. In that case, move immediately
       
   260     // to destination point.
       
   261     if ( !containerRect.contains(curPos) ) {
       
   262         return destPos;
       
   263     }
       
   264     // Otherwise, this is normal case and we will calculate a point which is just
       
   265     // a bit closer to the destination.
       
   266     
       
   267     // Version 1:
       
   268     //  o-----o---------------------------o
       
   269     //  p1    p2                          p3
       
   270     //
       
   271     // Version 2:
       
   272     //  o---------------------------o-----o
       
   273     //  p3                          p2    p1
       
   274     //
       
   275     // p1 - current widget position
       
   276     // p2 - next position to compute
       
   277     // p3 - destination random position
       
   278     QPointF p1(curPos);
       
   279     QPointF p2(0,0);
       
   280     QPointF p3(destPos);
       
   281 
       
   282     // Computes point p2 - new position between p1 and p3
       
   283 
       
   284     // Move the coordinate which is further away from the destination
       
   285     // and calculate the other coordinate from that so that the
       
   286     // result point p2 lies on the straigth line between p1 and p3.
       
   287     if ( yDistance > xDistance ) {
       
   288         if (p3.y() > p1.y()) {
       
   289             p2.setY(p1.y()+gStep);
       
   290         }
       
   291         else {
       
   292             p2.setY(p1.y()-gStep);
       
   293         }
       
   294         p2.setX((((p2.y()-p1.y())*(p3.x()-p1.x())) / (p3.y()-p1.y())) + p1.x()); // x2 = (((y2-y1)*(x3-x1)) / (y3-y1)) + x1
       
   295     }
       
   296     else {
       
   297         if (p3.x() > p1.x()) {
       
   298             p2.setX(p1.x()+gStep);
       
   299         }
       
   300         else {
       
   301             p2.setX(p1.x()-gStep);
       
   302         }
       
   303         p2.setY((((p3.y()-p1.y())*(p2.x()-p1.x())) / (p3.x()-p1.x())) + p1.y()); // y2 = (((y3-y1)*(x2-x1)) / (x3-x1)) + y1
       
   304     }
       
   305 
       
   306     // Return new position between points p1 and p3.
       
   307     return p2;
       
   308 }
       
   309 
       
   310 /*!
       
   311     Do necessary initializations to show currently active indicators.
       
   312     Should be called after the indicator widget is created.
       
   313  */
       
   314 void SnsrBigClockContainer::connectIndicatorWidgetToModel()
       
   315 {
       
   316     Q_ASSERT(mIndicatorModel && mIndicatorWidget);
       
   317     
       
   318     connect(mIndicatorModel, SIGNAL(indicatorsUpdated(QList<SnsrIndicatorInfo>)),
       
   319             mIndicatorWidget, SLOT(showIndicators(QList<SnsrIndicatorInfo>)));
       
   320                 
       
   321     connect(mIndicatorModel, SIGNAL(allIndicatorsDeactivated()),
       
   322             mIndicatorWidget, SLOT(removeAllIndicators()));
       
   323         
       
   324     mIndicatorModel->initializeIndicatorWidget();
       
   325 }
       
   326 
       
   327 /*!
       
   328     Disconnect connections between indicator model and widget.
       
   329     Should be called before deleting the indicator widget.
       
   330  */
       
   331 void SnsrBigClockContainer::resetIndicatorConnections()
       
   332 {   
       
   333     if (mIndicatorWidget && mIndicatorModel) {
       
   334         disconnect(mIndicatorModel, SIGNAL(indicatorsUpdated(QList<SnsrIndicatorInfo>)),
       
   335                    mIndicatorWidget, SLOT(showIndicators(QList<SnsrIndicatorInfo>)));
       
   336         
       
   337         disconnect(mIndicatorModel, SIGNAL(allIndicatorsDeactivated()),
       
   338                    mIndicatorWidget, SLOT(removeAllIndicators()));
       
   339     }
       
   340 }
       
   341 
       
   342 /*!
       
   343     Destroy all the contained widgets
       
   344  */
       
   345 void SnsrBigClockContainer::resetWidgets()
       
   346 {
       
   347     // deregister effects
       
   348     if ( mMainView ) {
       
   349         HbEffect::remove( mMainView );
       
   350     }
       
   351     
       
   352     mDocumentLoader.reset();
       
   353     qDeleteAll(mDocumentObjects);
       
   354     mDocumentObjects.clear();
       
   355 }
       
   356 
       
   357 /*!
       
   358     Set background color.
       
   359  */
       
   360 void SnsrBigClockContainer::setBackgroundColor()
       
   361 {
       
   362     mBackgroundColor = SnsrColors::BackgroundColor;
       
   363 }
       
   364 
       
   365 
       
   366 /*
       
   367  * Returns true if swipe widget is used,
       
   368  * false if swipe is not used.
       
   369  */
       
   370 bool SnsrBigClockContainer::swipeToUnlockSupported()
       
   371 {
       
   372 #ifdef Q_OS_SYMBIAN 
       
   373     XQSettingsManager::Error error;
       
   374     int swipeWidget = 0; 
       
   375     XQCentralRepositorySettingsKey settingsKey(
       
   376              KCRUidScreensaverSettings.iUid, KScreensaverSwipeToOpen ); 
       
   377     XQSettingsManager settingsManager;
       
   378     swipeWidget = settingsManager.readItemValue(settingsKey, XQSettingsManager::TypeInt).toInt();
       
   379     error = settingsManager.error();
       
   380     if (error == XQSettingsManager::NoError && swipeWidget == 1) {
       
   381         return true;
       
   382     }
       
   383     else {
       
   384         return false;
       
   385     }
       
   386 #else
       
   387     return true;
       
   388 #endif //Q_OS_SYMBIAN
       
   389 }
       
   390 
       
   391 /*!
       
   392     Paints the contents of an item in local coordinates.
       
   393  */
       
   394 #ifdef COVERAGE_MEASUREMENT
       
   395 #pragma CTC SKIP
       
   396 #endif //COVERAGE_MEASUREMENT
       
   397 void SnsrBigClockContainer::paint(
       
   398         QPainter *painter,
       
   399         const QStyleOptionGraphicsItem *option,
       
   400         QWidget *widget
       
   401         )
       
   402 {
       
   403     Q_UNUSED(option)
       
   404     Q_UNUSED(widget)
       
   405 
       
   406     painter->fillRect(rect(), mBackgroundColor);
       
   407 }
       
   408 #ifdef COVERAGE_MEASUREMENT
       
   409 #pragma CTC ENDSKIP
       
   410 #endif //COVERAGE_MEASUREMENT
       
   411 
       
   412 /*!
       
   413     Run the fade-out transition effect.
       
   414  */
       
   415 void SnsrBigClockContainer::fadeOutView()
       
   416 {
       
   417     // there's no point in animating the fade-out in the low-power mode
       
   418     if ( mMainView && displayPowerMode() == Screensaver::ScreenModeFullPower ) {
       
   419         HbEffect::start( mMainView, "disappear" );
       
   420     }
       
   421 }
       
   422