screensaver/screensaverplugins/snsrbigclockscreensaverplugin/src/snsrbigclockcontainer.cpp
changeset 62 341166945d65
child 69 87476091b3f5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/screensaver/screensaverplugins/snsrbigclockscreensaverplugin/src/snsrbigclockcontainer.cpp	Fri Jun 25 19:19:22 2010 +0300
@@ -0,0 +1,277 @@
+/*
+* Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Base class container.
+*
+*/
+
+#include "snsrbigclockcontainer.h"
+
+#include <QPainter>
+#include <QDebug>
+#include <QTime>
+#include <QGraphicsLinearLayout>
+
+#include <hblabel.h>
+#include <hbevent.h>
+#include <hbcolorscheme.h>
+
+#include <qsysteminfo.h>
+
+#include "snsrbigclockcontainer.h"
+#include "snsrindicatorwidget.h"
+#include "snsrindicatormodel.h"
+
+/*!
+    \class SnsrBigClockContainer
+    \ingroup group_snsrbigclockscreensaverplugin
+    \brief Base class. Container used for drawing background and for preparing layout.
+ */
+
+const QString snsrBackgroundColorRole("snsrbackground");
+const int gStep(5);
+
+QTM_USE_NAMESPACE
+
+/*!
+    Constructs a new SnsrBigClockContainer.
+ */
+SnsrBigClockContainer::SnsrBigClockContainer() :
+    mBackgroundContainerLayout(0),
+    mMainView(0),
+    mMainContainer(0),
+    mIndicatorModel(0),
+    mIndicatorWidget(0),
+    mCurrentOrientation(-1)
+{
+    setBackgroundColor();
+    mBackgroundContainerLayout = new QGraphicsLinearLayout(Qt::Vertical);
+    setLayout(mBackgroundContainerLayout);
+    qsrand(QTime::currentTime().msec());
+}
+
+/*!
+    Destructs the class.
+ */
+SnsrBigClockContainer::~SnsrBigClockContainer()
+{
+    resetIndicatorConnections();
+    
+    // e.g. mIndicatorWidget gets deleted during these calls
+    mDocumentLoader.reset();
+    qDeleteAll(mDocumentObjects);
+    mDocumentObjects.clear();
+
+    //mMainContainer,mBackgroundContainerLayout - deleted by the parent
+    mIndicatorModel=0; // not owned
+}
+
+/*!
+    \fn virtual void update() = 0;
+
+    Slot for members update in container e.g. when time or date changed.
+ */
+
+/*!
+    \fn virtual void changeLayout(Qt::Orientation orientation) = 0;
+
+    Slot for members update in container when orientation changed.
+ */
+
+/*!
+    \fn virtual int updateIntervalInMilliseconds() = 0;
+
+    Concrete inherited container classes must implement this to return
+    the desired update interval for that clock mode.
+ */
+
+/*!
+    Set used indicator model and do necessary initializations to show currently
+    active indicators.
+ */
+void SnsrBigClockContainer::initIndicators(SnsrIndicatorModel &model)
+{
+    mIndicatorModel = &model;
+    if (mIndicatorWidget) {
+        connect(mIndicatorModel, SIGNAL(indicatorsUpdated(QList<SnsrIndicatorInfo>)),
+                mIndicatorWidget, SLOT(showIndicators(QList<SnsrIndicatorInfo>)));
+                
+        connect(mIndicatorModel, SIGNAL(allIndicatorsDeactivated()),
+                mIndicatorWidget, SLOT(removeAllIndicators()));
+        
+        mIndicatorModel->initializeIndicatorWidget();
+    }
+}
+
+/*!
+    \reimp
+ */
+void SnsrBigClockContainer::changeEvent(QEvent *event)
+{
+    if (event->type() == HbEvent::ThemeChanged) {
+        setBackgroundColor();
+    }
+    return QGraphicsWidget::changeEvent(event);
+}
+
+/*!
+    Returns random point for given range.
+    \param rect Area within which the generated point will be.
+ */
+QPointF SnsrBigClockContainer::randomPosition(const QRectF &rect)
+{
+    int width( rect.width() );
+    int height( rect.height() );
+    if ( width > 0 && height > 0 ) {
+        return rect.topLeft() + QPointF( qrand()%width, qrand()%height );
+    }
+    else {
+        return QPointF();
+    }
+
+}
+
+/*!
+    Returns new position between curRect position and destPos position.
+    \param curPos Current position.
+    \param destPos Destination position. When current position is near this
+                   position or outside of the container, a new value is generated.
+    \param containerRect The container within which the destination position will always
+                         be after a call.
+ */
+QPointF SnsrBigClockContainer::nextRandomPosition(const QPointF &curPos, QPointF &destPos, const QRectF &containerRect)
+{
+    const int delta(gStep+2);
+    const int minCntDimension(3*delta);
+
+    // The random movement logic can work only if the container has enough space to move the
+    // clock around. If the container is too small, just return the middle point of the container.
+    if ( containerRect.width() < minCntDimension && containerRect.height() < minCntDimension ) {
+        return containerRect.center();
+    }
+    
+    int xDistance = abs( destPos.x() - curPos.x() );
+    int yDistance = abs( destPos.y() - curPos.y() );
+    
+    // Generate new destination position when current widget position is close to 
+    // destination random position or when current destination position is out of bounds.
+    // It is possible that the new random position is very close to the current position,
+    // in which case the random position is generated again.
+    // It is paramount that container is large enough when next loop is entered
+    // to prevent infinite looping.
+    while ( (xDistance < delta && yDistance < delta)
+            || !containerRect.contains(destPos) ) {
+        destPos = randomPosition( containerRect );
+        xDistance = abs( destPos.x() - curPos.x() );
+        yDistance = abs( destPos.y() - curPos.y() );
+    }
+
+    // If, for some reason, the current position is out-of-bounds, then there's no
+    // point to slowly move towards the destination. In that case, move immediately
+    // to destination point.
+    if ( !containerRect.contains(curPos) ) {
+        return destPos;
+    }
+    // Otherwise, this is normal case and we will calculate a point which is just
+    // a bit closer to the destination.
+    
+    // Version 1:
+    //  o-----o---------------------------o
+    //  p1    p2                          p3
+    //
+    // Version 2:
+    //  o---------------------------o-----o
+    //  p3                          p2    p1
+    //
+    // p1 - current widget position
+    // p2 - next position to compute
+    // p3 - destination random position
+    QPointF p1(curPos);
+    QPointF p2(0,0);
+    QPointF p3(destPos);
+
+    // Computes point p2 - new position between p1 and p3
+
+    // Move the coordinate which is further away from the destination
+    // and calculate the other coordinate from that so that the
+    // result point p2 lies on the straigth line between p1 and p3.
+    if ( yDistance > xDistance ) {
+        if (p3.y() > p1.y()) {
+            p2.setY(p1.y()+gStep);
+        }
+        else {
+            p2.setY(p1.y()-gStep);
+        }
+        p2.setX((((p2.y()-p1.y())*(p3.x()-p1.x())) / (p3.y()-p1.y())) + p1.x()); // x2 = (((y2-y1)*(x3-x1)) / (y3-y1)) + x1
+    }
+    else {
+        if (p3.x() > p1.x()) {
+            p2.setX(p1.x()+gStep);
+        }
+        else {
+            p2.setX(p1.x()-gStep);
+        }
+        p2.setY((((p3.y()-p1.y())*(p2.x()-p1.x())) / (p3.x()-p1.x())) + p1.y()); // y2 = (((y3-y1)*(x2-x1)) / (x3-x1)) + y1
+    }
+
+    // Return new position between points p1 and p3.
+    return p2;
+}
+
+/*!
+    Disconnect connections between indicator model and widget.
+ */
+void SnsrBigClockContainer::resetIndicatorConnections()
+{
+    disconnect(mIndicatorModel, SIGNAL(indicatorsUpdated(QList<SnsrIndicatorInfo>)),
+               mIndicatorWidget, SLOT(showIndicators(QList<SnsrIndicatorInfo>)));
+    
+    disconnect(mIndicatorModel, SIGNAL(allIndicatorsDeactivated()),
+               mIndicatorWidget, SLOT(removeAllIndicators()));
+}
+
+/*!
+    Set background color.
+ */
+void SnsrBigClockContainer::setBackgroundColor()
+{
+    QColor backgroundColor = HbColorScheme::color(snsrBackgroundColorRole);
+    if (backgroundColor.isValid()) {
+        mBackgroundColor = backgroundColor;
+    }
+    else {
+        mBackgroundColor = Qt::black;
+    }
+}
+
+/*!
+    Paints the contents of an item in local coordinates.
+ */
+#ifdef COVERAGE_MEASUREMENT
+#pragma CTC SKIP
+#endif //COVERAGE_MEASUREMENT
+void SnsrBigClockContainer::paint(
+        QPainter *painter,
+        const QStyleOptionGraphicsItem *option,
+        QWidget *widget
+        )
+{
+    Q_UNUSED(option)
+    Q_UNUSED(widget)
+
+    painter->fillRect(rect(), mBackgroundColor);
+}
+#ifdef COVERAGE_MEASUREMENT
+#pragma CTC ENDSKIP
+#endif //COVERAGE_MEASUREMENT
+