# HG changeset patch # User Dremov Kirill (Nokia-D-MSW/Tampere) # Date 1271677206 -10800 # Node ID 89c329efa9800fe260f50a07eb7a8a7202722499 Revision: 201011 Kit: 201015 diff -r 000000000000 -r 89c329efa980 bwins/ganeswidgetsu.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bwins/ganeswidgetsu.def Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,83 @@ +EXPORTS + ?setScrollBar@HgWidget@@QAEXPAVHbScrollBar@@@Z @ 1 NONAME ; void HgWidget::setScrollBar(class HbScrollBar *) + ?setCurrentIndex@HgWidget@@QAEXABVQModelIndex@@V?$QFlags@W4SelectionFlag@QItemSelectionModel@@@@@Z @ 2 NONAME ; void HgWidget::setCurrentIndex(class QModelIndex const &, class QFlags) + ?currentIndex@HgWidget@@QBE?AVQModelIndex@@XZ @ 3 NONAME ; class QModelIndex HgWidget::currentIndex(void) const + ?trUtf8@HgWidget@@SA?AVQString@@PBD0@Z @ 4 NONAME ; class QString HgWidget::trUtf8(char const *, char const *) + ?scrollTo@HgWidget@@QAEXABVQModelIndex@@@Z @ 5 NONAME ; void HgWidget::scrollTo(class QModelIndex const &) + ??1HgWidget@@UAE@XZ @ 6 NONAME ; HgWidget::~HgWidget(void) + ?selectionModel@HgWidget@@QBEPAVQItemSelectionModel@@XZ @ 7 NONAME ; class QItemSelectionModel * HgWidget::selectionModel(void) const + ?activated@HgWidget@@IAEXABVQModelIndex@@@Z @ 8 NONAME ; void HgWidget::activated(class QModelIndex const &) + ?eventFilter@HgWidget@@MAE_NPAVQObject@@PAVQEvent@@@Z @ 9 NONAME ; bool HgWidget::eventFilter(class QObject *, class QEvent *) + ?scrollBarPolicy@HgWidget@@QBE?AW4ScrollBarPolicy@1@XZ @ 10 NONAME ; enum HgWidget::ScrollBarPolicy HgWidget::scrollBarPolicy(void) const + ?selectAll@HgWidget@@QAEXXZ @ 11 NONAME ; void HgWidget::selectAll(void) + ?trUtf8@HgWidget@@SA?AVQString@@PBD0H@Z @ 12 NONAME ; class QString HgWidget::trUtf8(char const *, char const *, int) + ?tr@HgWidget@@SA?AVQString@@PBD0@Z @ 13 NONAME ; class QString HgWidget::tr(char const *, char const *) + ?getStaticMetaObject@HgWidget@@SAABUQMetaObject@@XZ @ 14 NONAME ; struct QMetaObject const & HgWidget::getStaticMetaObject(void) + ?qt_metacast@HgWidget@@UAEPAXPBD@Z @ 15 NONAME ; void * HgWidget::qt_metacast(char const *) + ?setSelectionModel@HgWidget@@QAEXPAVQItemSelectionModel@@@Z @ 16 NONAME ; void HgWidget::setSelectionModel(class QItemSelectionModel *) + ?d_func@HgWidget@@ABEPBVHgWidgetPrivate@@XZ @ 17 NONAME ; class HgWidgetPrivate const * HgWidget::d_func(void) const + ?setScrollBarPolicy@HgWidget@@QAEXW4ScrollBarPolicy@1@@Z @ 18 NONAME ; void HgWidget::setScrollBarPolicy(enum HgWidget::ScrollBarPolicy) + ?longPressEnabled@HgWidget@@QBE_NXZ @ 19 NONAME ; bool HgWidget::longPressEnabled(void) const + ?tr@HgWidget@@SA?AVQString@@PBD0H@Z @ 20 NONAME ; class QString HgWidget::tr(char const *, char const *, int) + ?setModel@HgWidget@@UAEXPAVQAbstractItemModel@@@Z @ 21 NONAME ; void HgWidget::setModel(class QAbstractItemModel *) + ?longPressed@HgWidget@@IAEXABVQModelIndex@@ABVQPointF@@@Z @ 22 NONAME ; void HgWidget::longPressed(class QModelIndex const &, class QPointF const &) + ?staticMetaObject@HgWidget@@2UQMetaObject@@B @ 23 NONAME ; struct QMetaObject const HgWidget::staticMetaObject + ?selectionMode@HgWidget@@QBE?AW4SelectionMode@1@XZ @ 24 NONAME ; enum HgWidget::SelectionMode HgWidget::selectionMode(void) const + ??_EHgWidget@@UAE@I@Z @ 25 NONAME ; HgWidget::~HgWidget(unsigned int) + ?qt_metacall@HgWidget@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 26 NONAME ; int HgWidget::qt_metacall(enum QMetaObject::Call, int, void * *) + ?d_func@HgWidget@@AAEPAVHgWidgetPrivate@@XZ @ 27 NONAME ; class HgWidgetPrivate * HgWidget::d_func(void) + ?metaObject@HgWidget@@UBEPBUQMetaObject@@XZ @ 28 NONAME ; struct QMetaObject const * HgWidget::metaObject(void) const + ?scrollBar@HgWidget@@QBEPAVHbScrollBar@@XZ @ 29 NONAME ; class HbScrollBar * HgWidget::scrollBar(void) const + ?model@HgWidget@@QBEPAVQAbstractItemModel@@XZ @ 30 NONAME ; class QAbstractItemModel * HgWidget::model(void) const + ?clearSelection@HgWidget@@QAEXXZ @ 31 NONAME ; void HgWidget::clearSelection(void) + ?setLongPressEnabled@HgWidget@@QAEX_N@Z @ 32 NONAME ; void HgWidget::setLongPressEnabled(bool) + ?dataChanged@HgWidget@@IAEXABVQModelIndex@@0@Z @ 33 NONAME ; void HgWidget::dataChanged(class QModelIndex const &, class QModelIndex const &) + ?setSelectionMode@HgWidget@@QAEXW4SelectionMode@1@_N@Z @ 34 NONAME ; void HgWidget::setSelectionMode(enum HgWidget::SelectionMode, bool) + ?event@HgWidget@@MAE_NPAVQEvent@@@Z @ 35 NONAME ; bool HgWidget::event(class QEvent *) + ?orientationChanged@HgWidget@@QAEXW4Orientation@Qt@@@Z @ 36 NONAME ; void HgWidget::orientationChanged(enum Qt::Orientation) + ?aboutToChangeOrientation@HgWidget@@QAEXXZ @ 37 NONAME ; void HgWidget::aboutToChangeOrientation(void) + ?getItemOutline@HgWidget@@QAE_NABVQModelIndex@@AAVQPolygonF@@@Z @ 38 NONAME ; bool HgWidget::getItemOutline(class QModelIndex const &, class QPolygonF &) + ?getVisibleItemIndices@HgWidget@@QBE?AV?$QList@VQModelIndex@@@@XZ @ 39 NONAME ; class QList HgWidget::getVisibleItemIndices(void) const + ?scrollingEnded@HgWidget@@IAEXXZ @ 40 NONAME ; void HgWidget::scrollingEnded(void) + ?scrollingStarted@HgWidget@@IAEXXZ @ 41 NONAME ; void HgWidget::scrollingStarted(void) + ?scrollDirection@HgWidget@@QBE?AW4Orientation@Qt@@XZ @ 42 NONAME ; enum Qt::Orientation HgWidget::scrollDirection(void) const + ?tr@HgMediawall@@SA?AVQString@@PBD0@Z @ 43 NONAME ; class QString HgMediawall::tr(char const *, char const *) + ?qt_metacall@HgMediawall@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 44 NONAME ; int HgMediawall::qt_metacall(enum QMetaObject::Call, int, void * *) + ?d_func@HgMediawall@@ABEPBVHgMediawallPrivate@@XZ @ 45 NONAME ; class HgMediawallPrivate const * HgMediawall::d_func(void) const + ?tr@HgGrid@@SA?AVQString@@PBD0H@Z @ 46 NONAME ; class QString HgGrid::tr(char const *, char const *, int) + ?metaObject@HgMediawall@@UBEPBUQMetaObject@@XZ @ 47 NONAME ; struct QMetaObject const * HgMediawall::metaObject(void) const + ?d_func@HgGrid@@ABEPBVHgGridPrivate@@XZ @ 48 NONAME ; class HgGridPrivate const * HgGrid::d_func(void) const + ?tr@HgMediawall@@SA?AVQString@@PBD0H@Z @ 49 NONAME ; class QString HgMediawall::tr(char const *, char const *, int) + ?staticMetaObject@HgMediawall@@2UQMetaObject@@B @ 50 NONAME ; struct QMetaObject const HgMediawall::staticMetaObject + ??_EHgGrid@@UAE@I@Z @ 51 NONAME ; HgGrid::~HgGrid(unsigned int) + ?trUtf8@HgMediawall@@SA?AVQString@@PBD0@Z @ 52 NONAME ; class QString HgMediawall::trUtf8(char const *, char const *) + ?getStaticMetaObject@HgMediawall@@SAABUQMetaObject@@XZ @ 53 NONAME ; struct QMetaObject const & HgMediawall::getStaticMetaObject(void) + ?getStaticMetaObject@HgGrid@@SAABUQMetaObject@@XZ @ 54 NONAME ; struct QMetaObject const & HgGrid::getStaticMetaObject(void) + ?d_func@HgGrid@@AAEPAVHgGridPrivate@@XZ @ 55 NONAME ; class HgGridPrivate * HgGrid::d_func(void) + ?qt_metacall@HgGrid@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 56 NONAME ; int HgGrid::qt_metacall(enum QMetaObject::Call, int, void * *) + ??0HgGrid@@QAE@W4Orientation@Qt@@PAVQGraphicsItem@@@Z @ 57 NONAME ; HgGrid::HgGrid(enum Qt::Orientation, class QGraphicsItem *) + ??0HgMediawall@@QAE@PAVQGraphicsItem@@@Z @ 58 NONAME ; HgMediawall::HgMediawall(class QGraphicsItem *) + ?qt_metacast@HgGrid@@UAEPAXPBD@Z @ 59 NONAME ; void * HgGrid::qt_metacast(char const *) + ?trUtf8@HgGrid@@SA?AVQString@@PBD0H@Z @ 60 NONAME ; class QString HgGrid::trUtf8(char const *, char const *, int) + ??0HgWidget@@IAE@PAVHbWidgetPrivate@@PAVQGraphicsItem@@@Z @ 61 NONAME ; HgWidget::HgWidget(class HbWidgetPrivate *, class QGraphicsItem *) + ?trUtf8@HgMediawall@@SA?AVQString@@PBD0H@Z @ 62 NONAME ; class QString HgMediawall::trUtf8(char const *, char const *, int) + ?trUtf8@HgGrid@@SA?AVQString@@PBD0@Z @ 63 NONAME ; class QString HgGrid::trUtf8(char const *, char const *) + ?tr@HgGrid@@SA?AVQString@@PBD0@Z @ 64 NONAME ; class QString HgGrid::tr(char const *, char const *) + ??1HgGrid@@UAE@XZ @ 65 NONAME ; HgGrid::~HgGrid(void) + ?qt_metacast@HgMediawall@@UAEPAXPBD@Z @ 66 NONAME ; void * HgMediawall::qt_metacast(char const *) + ?staticMetaObject@HgGrid@@2UQMetaObject@@B @ 67 NONAME ; struct QMetaObject const HgGrid::staticMetaObject + ??1HgMediawall@@UAE@XZ @ 68 NONAME ; HgMediawall::~HgMediawall(void) + ?metaObject@HgGrid@@UBEPBUQMetaObject@@XZ @ 69 NONAME ; struct QMetaObject const * HgGrid::metaObject(void) const + ??_EHgMediawall@@UAE@I@Z @ 70 NONAME ; HgMediawall::~HgMediawall(unsigned int) + ?d_func@HgMediawall@@AAEPAVHgMediawallPrivate@@XZ @ 71 NONAME ; class HgMediawallPrivate * HgMediawall::d_func(void) + ?descriptionPosition@HgMediawall@@QBE?AW4LabelPosition@1@XZ @ 72 NONAME ; enum HgMediawall::LabelPosition HgMediawall::descriptionPosition(void) const + ?setDescriptionFontSpec@HgMediawall@@QAEXABVHbFontSpec@@@Z @ 73 NONAME ; void HgMediawall::setDescriptionFontSpec(class HbFontSpec const &) + ?titleFontSpec@HgMediawall@@QBE?AVHbFontSpec@@XZ @ 74 NONAME ; class HbFontSpec HgMediawall::titleFontSpec(void) const + ?setDescriptionPosition@HgMediawall@@QAEXW4LabelPosition@1@@Z @ 75 NONAME ; void HgMediawall::setDescriptionPosition(enum HgMediawall::LabelPosition) + ?titlePosition@HgMediawall@@QBE?AW4LabelPosition@1@XZ @ 76 NONAME ; enum HgMediawall::LabelPosition HgMediawall::titlePosition(void) const + ?setTitleFontSpec@HgMediawall@@QAEXABVHbFontSpec@@@Z @ 77 NONAME ; void HgMediawall::setTitleFontSpec(class HbFontSpec const &) + ?setTitlePosition@HgMediawall@@QAEXW4LabelPosition@1@@Z @ 78 NONAME ; void HgMediawall::setTitlePosition(enum HgMediawall::LabelPosition) + ?descriptionFontSpec@HgMediawall@@QBE?AVHbFontSpec@@XZ @ 79 NONAME ; class HbFontSpec HgMediawall::descriptionFontSpec(void) const + ?setIndexFeedbackPolicy@HgWidget@@QAEXW4IndexFeedbackPolicy@1@@Z @ 80 NONAME ; void HgWidget::setIndexFeedbackPolicy(enum HgWidget::IndexFeedbackPolicy) + ?indexFeedbackPolicy@HgWidget@@QBE?AW4IndexFeedbackPolicy@1@XZ @ 81 NONAME ; enum HgWidget::IndexFeedbackPolicy HgWidget::indexFeedbackPolicy(void) const + diff -r 000000000000 -r 89c329efa980 eabi/ganeswidgetsu.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eabi/ganeswidgetsu.def Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,89 @@ +EXPORTS + _ZN11HgMediawall11qt_metacallEN11QMetaObject4CallEiPPv @ 1 NONAME + _ZN11HgMediawall11qt_metacastEPKc @ 2 NONAME + _ZN11HgMediawall16staticMetaObjectE @ 3 NONAME DATA 16 + _ZN11HgMediawall19getStaticMetaObjectEv @ 4 NONAME + _ZN11HgMediawallC1EP13QGraphicsItem @ 5 NONAME + _ZN11HgMediawallC2EP13QGraphicsItem @ 6 NONAME + _ZN11HgMediawallD0Ev @ 7 NONAME + _ZN11HgMediawallD1Ev @ 8 NONAME + _ZN11HgMediawallD2Ev @ 9 NONAME + _ZN6HgGrid11qt_metacallEN11QMetaObject4CallEiPPv @ 10 NONAME + _ZN6HgGrid11qt_metacastEPKc @ 11 NONAME + _ZN6HgGrid16staticMetaObjectE @ 12 NONAME DATA 16 + _ZN6HgGrid19getStaticMetaObjectEv @ 13 NONAME + _ZN6HgGridC1EN2Qt11OrientationEP13QGraphicsItem @ 14 NONAME + _ZN6HgGridC2EN2Qt11OrientationEP13QGraphicsItem @ 15 NONAME + _ZN6HgGridD0Ev @ 16 NONAME + _ZN6HgGridD1Ev @ 17 NONAME + _ZN6HgGridD2Ev @ 18 NONAME + _ZN8HgWidget11dataChangedERK11QModelIndexS2_ @ 19 NONAME + _ZN8HgWidget11eventFilterEP7QObjectP6QEvent @ 20 NONAME + _ZN8HgWidget11longPressedERK11QModelIndexRK7QPointF @ 21 NONAME + _ZN8HgWidget11qt_metacallEN11QMetaObject4CallEiPPv @ 22 NONAME + _ZN8HgWidget11qt_metacastEPKc @ 23 NONAME + _ZN8HgWidget12setScrollBarEP11HbScrollBar @ 24 NONAME + _ZN8HgWidget14clearSelectionEv @ 25 NONAME + _ZN8HgWidget14getItemOutlineERK11QModelIndexR9QPolygonF @ 26 NONAME + _ZN8HgWidget14scrollingEndedEv @ 27 NONAME + _ZN8HgWidget15setCurrentIndexERK11QModelIndex6QFlagsIN19QItemSelectionModel13SelectionFlagEE @ 28 NONAME + _ZN8HgWidget16scrollingStartedEv @ 29 NONAME + _ZN8HgWidget16setSelectionModeENS_13SelectionModeEb @ 30 NONAME + _ZN8HgWidget16staticMetaObjectE @ 31 NONAME DATA 16 + _ZN8HgWidget17setSelectionModelEP19QItemSelectionModel @ 32 NONAME + _ZN8HgWidget18orientationChangedEN2Qt11OrientationE @ 33 NONAME + _ZN8HgWidget18setScrollBarPolicyENS_15ScrollBarPolicyE @ 34 NONAME + _ZN8HgWidget19getStaticMetaObjectEv @ 35 NONAME + _ZN8HgWidget19setLongPressEnabledEb @ 36 NONAME + _ZN8HgWidget24aboutToChangeOrientationEv @ 37 NONAME + _ZN8HgWidget5eventEP6QEvent @ 38 NONAME + _ZN8HgWidget8scrollToERK11QModelIndex @ 39 NONAME + _ZN8HgWidget8setModelEP18QAbstractItemModel @ 40 NONAME + _ZN8HgWidget9activatedERK11QModelIndex @ 41 NONAME + _ZN8HgWidget9selectAllEv @ 42 NONAME + _ZN8HgWidgetC1EP15HbWidgetPrivateP13QGraphicsItem @ 43 NONAME + _ZN8HgWidgetC2EP15HbWidgetPrivateP13QGraphicsItem @ 44 NONAME + _ZN8HgWidgetD0Ev @ 45 NONAME + _ZN8HgWidgetD1Ev @ 46 NONAME + _ZN8HgWidgetD2Ev @ 47 NONAME + _ZNK11HgMediawall10metaObjectEv @ 48 NONAME + _ZNK6HgGrid10metaObjectEv @ 49 NONAME + _ZNK8HgWidget10metaObjectEv @ 50 NONAME + _ZNK8HgWidget12currentIndexEv @ 51 NONAME + _ZNK8HgWidget13selectionModeEv @ 52 NONAME + _ZNK8HgWidget14selectionModelEv @ 53 NONAME + _ZNK8HgWidget15scrollBarPolicyEv @ 54 NONAME + _ZNK8HgWidget15scrollDirectionEv @ 55 NONAME + _ZNK8HgWidget16longPressEnabledEv @ 56 NONAME + _ZNK8HgWidget21getVisibleItemIndicesEv @ 57 NONAME + _ZNK8HgWidget5modelEv @ 58 NONAME + _ZNK8HgWidget9scrollBarEv @ 59 NONAME + _ZTI11HgMediawall @ 60 NONAME + _ZTI6HgGrid @ 61 NONAME + _ZTI8HgWidget @ 62 NONAME + _ZTV11HgMediawall @ 63 NONAME + _ZTV6HgGrid @ 64 NONAME + _ZTV8HgWidget @ 65 NONAME + _ZThn16_N11HgMediawallD0Ev @ 66 NONAME + _ZThn16_N11HgMediawallD1Ev @ 67 NONAME + _ZThn16_N6HgGridD0Ev @ 68 NONAME + _ZThn16_N6HgGridD1Ev @ 69 NONAME + _ZThn16_N8HgWidgetD0Ev @ 70 NONAME + _ZThn16_N8HgWidgetD1Ev @ 71 NONAME + _ZThn8_N11HgMediawallD0Ev @ 72 NONAME + _ZThn8_N11HgMediawallD1Ev @ 73 NONAME + _ZThn8_N6HgGridD0Ev @ 74 NONAME + _ZThn8_N6HgGridD1Ev @ 75 NONAME + _ZThn8_N8HgWidgetD0Ev @ 76 NONAME + _ZThn8_N8HgWidgetD1Ev @ 77 NONAME + _ZN11HgMediawall16setTitleFontSpecERK10HbFontSpec @ 78 NONAME + _ZN11HgMediawall16setTitlePositionENS_13LabelPositionE @ 79 NONAME + _ZN11HgMediawall22setDescriptionFontSpecERK10HbFontSpec @ 80 NONAME + _ZN11HgMediawall22setDescriptionPositionENS_13LabelPositionE @ 81 NONAME + _ZNK11HgMediawall13titleFontSpecEv @ 82 NONAME + _ZNK11HgMediawall13titlePositionEv @ 83 NONAME + _ZNK11HgMediawall19descriptionFontSpecEv @ 84 NONAME + _ZNK11HgMediawall19descriptionPositionEv @ 85 NONAME + _ZN8HgWidget22setIndexFeedbackPolicyENS_19IndexFeedbackPolicyE @ 86 NONAME + _ZNK8HgWidget19indexFeedbackPolicyEv @ 87 NONAME + diff -r 000000000000 -r 89c329efa980 ganeswidgets/data/ganeswidgets.qrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/data/ganeswidgets.qrc Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,8 @@ + + + images/mark.svg + hgwidget.css + hgwidget.widgetml + hgindexfeedback.css + + diff -r 000000000000 -r 89c329efa980 ganeswidgets/data/hgindexfeedback.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/data/hgindexfeedback.css Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,7 @@ +HgIndexFeedback +{ + one-char-height:18un; + three-char-height:12un; + three-char-width:36un; + string-offset:8un; +} \ No newline at end of file diff -r 000000000000 -r 89c329efa980 ganeswidgets/data/hgwidget.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/data/hgwidget.css Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,40 @@ +HgWidget +{ + layout:default_layout; +} + +HgWidget::scrollbar-vertical +{ + left:0un; + right:0un; + top:-0.8un; + bottom:expr(var(hb-param-widget-scroll-bar-interactive-width)+0.8un); +} + +HgWidget::scrollbar-horizontal +{ + left:0un; + right:var(hb-param-widget-scroll-bar-interactive-width); + top:0un; + bottom:0un; +} + +HgWidget::continuation-indicator-bottom +{ + fixed-height:2.0un; +} + +HgWidget::continuation-indicator-top +{ + fixed-height:2.0un; +} + +HgWidget::continuation-indicator-left +{ + fixed-width:2.0un; +} + +HgWidget::continuation-indicator-right +{ + fixed-width:2.0un; +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/data/hgwidget.widgetml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/data/hgwidget.widgetml Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 000000000000 -r 89c329efa980 ganeswidgets/data/images/mark.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/data/images/mark.svg Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -r 000000000000 -r 89c329efa980 ganeswidgets/ganeswidgets.pro --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/ganeswidgets.pro Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,78 @@ +# Copyright (c) 2009 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: + +symbian:TARGET.UID3 = 0x10207C66 +TEMPLATE = lib +CONFIG += hb +TARGET = ganeswidgets +DEFINES += BUILD_HG_WIDGETS +TARGET.CAPABILITY = All \ + -TCB +DEPENDPATH += . +INCLUDEPATH += . \ + inc \ + $$MW_LAYER_SYSTEMINCLUDE \ + /sf/mw/hb/src/hbcore/gui +LIBS += -lestor.dll \ + -lmpxcommon.dll \ + -lhbcore \ + -lhbwidgets \ + -llibOpenVG.dll \ + -llibOpenVGU.dll +symbian { + TARGET.EPOCALLOWDLLDATA = 1 +} + +# Input +SOURCES += src/hgwidgets.cpp \ + src/hgwidgets_p.cpp \ + src/hgcontainer.cpp \ + src/hgwidgetitem.cpp \ + src/hgscrollbuffermanager.cpp \ + src/hgquad.cpp \ + src/hgquadrenderer.cpp \ + src/hgvgquadrenderer.cpp \ + src/hgvgimage.cpp \ + src/hgmediawallrenderer.cpp \ + src/hgspring.cpp \ + src/hgdrag.cpp \ + src/hgimagefader.cpp \ + src/hglongpressvisualizer.cpp \ + src/hgcoverflowcontainer.cpp \ + src/hggridcontainer.cpp \ + src/hgindexfeedback.cpp \ + src/hgindexfeedback_p.cpp \ + src/hggrid.cpp \ + src/hggrid_p.cpp \ + src/hgmediawall.cpp \ + src/hgmediawall_p.cpp +HEADERS = inc/trace.h \ + ../hgwidgets_plat/ganeswidgets_api/inc/hgwidgets.h \ + ../hgwidgets_plat/ganeswidgets_api/inc/hggrid.h \ + ../hgwidgets_plat/ganeswidgets_api/inc/hgmediawall.h \ + inc/hgwidgets_p.h \ + inc/hggrid_p.h \ + inc/hgmediawall_p.h \ + inc/hgmediawallrenderer.h \ + inc/hgcontainer.h \ + inc/hgspring.h \ + inc/hgdrag.h \ + inc/hgscrollbuffermanager.h \ + inc/hgimagefader.h \ + inc/hglongpressvisualizer.h \ + inc/hgcoverflowcontainer.h \ + inc/hggridcontainer.h \ + inc/hgindexfeedback.h +RESOURCES += data/ganeswidgets.qrc + + +include(rom/rom.pri) +include(sis/stub.pri) \ No newline at end of file diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/HgContainer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/HgContainer.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,200 @@ +/* +* Copyright (c) 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: +* +*/ + +#ifndef HGCONTAINER_H +#define HGCONTAINER_H + +#include +#include +#include + +#include "hgmediawalldataprovider.h" +#include "hgdrag.h" +#include "hgspring.h" + +class HgWidgetItem; +class HgQuadRenderer; +class HgMediaWallRenderer; +class QPanGesture; +class HbAbstractViewItem; +class HbGestureSceneFilter; +class HgLongPressVisualizer; + +class HgContainer: public HbWidget, public HgMediaWallDataProvider +{ + Q_OBJECT + Q_DISABLE_COPY(HgContainer) + +public: + explicit HgContainer(QGraphicsItem* parent = 0); + virtual ~HgContainer(); + + void setItemCount(int count); + int itemCount() const; + int rowCount() const; + + QList items() const; + HgWidgetItem* itemByIndex(const QModelIndex &index) const; + HgWidgetItem* itemByIndex(const int &index) const; + + void setSelectionModel(QItemSelectionModel *selectionModel); + QItemSelectionModel *selectionModel() const; + void setSelectionMode(HgWidget::SelectionMode mode, bool resetSelection); + HgWidget::SelectionMode selectionMode() const; + + void dimensions(qreal &screenSize, qreal &worldSize); + Qt::Orientation orientation() const; + void setOrientation(Qt::Orientation orientation, bool animate=true); + + // new size for the widget. calls resize. + void scrollToPosition(qreal value, bool animate = false); + virtual void scrollToPosition(const QPointF& pos, bool animate); + void scrollTo(const QModelIndex &index); + + void itemDataChanged(const QModelIndex &firstIndex, const QModelIndex &lastIndex); + + void addItems(int start, int end); + void removeItems(int start, int end); + void moveItems(int start, int end, int destination); + + bool getItemPoints(int index, QPolygonF& points); + + QList getVisibleItemIndices() const; + + virtual void itemDataChanged(const int &firstIndex, const int &lastIndex); + + void init(Qt::Orientation scrollDirection); + +signals: + + // emit this signal when scrolling. for example scrollbar can be connected to this signal. + void scrollPositionChanged(qreal value, bool scrollBarAnimation); + void centerItemChanged(const QModelIndex &index); + void activated(const QModelIndex &index); + void longPressed(const QModelIndex &index, const QPointF &coords); + void scrollingStarted(); + void scrollingEnded(); + +private slots: + + void updateBySpringPosition(); + void redraw(); + void updateLongPressVisualizer(); + void updateByCurrentIndex(const QModelIndex ¤t); + void onScrollingEnded(); + +protected: // from HgMediaWallDataProvider + + int imageCount() const; + const HgImage *image(int index) const; + int flags(int index) const; + const HgImage *indicator(int flags) const; + +protected: // events + + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + virtual void resizeEvent(QGraphicsSceneResizeEvent *event); + + // this needs to be implemented for gesture framework to work + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + // From HbWidget for gestures. + virtual void gestureEvent(QGestureEvent *event); +protected: + + virtual HgMediaWallRenderer* createRenderer()=0; + virtual qreal getCameraDistance(qreal springVelocity); + virtual qreal getCameraRotationY(qreal springVelocity); + virtual void handleTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex); + virtual void handleLongTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex); + virtual void onScrollPositionChanged(qreal pos); + virtual void handleCurrentChanged(const QModelIndex ¤t); + +protected: + + enum ItemActionType + { + LongTap = 1, + DoubleTap, + NormalTap, + TapStart, + LongTapStart + }; + + qreal worldWidth() const; + void initSpringForScrollBar(); + void initSpringForScrolling(); + void boundSpring(); + void handlePanning(QPanGesture *gesture); + void handleTap(Qt::GestureState state, const QPointF &pos); + void handleLongTap(Qt::GestureState state, const QPointF &pos); + void handleItemAction(const QPointF &pos, ItemActionType action); + + void selectItem(); + void updateSelectedItem(); + void unselectItem(); + + HgWidgetItem* getItemAt(const QPointF& pos, int& index); + void startLongPressWatcher(const QPointF& pos); + void stopLongPressWatcher(); + bool updateSelectionModel(HgWidgetItem* item); + + QTransform qtToVgTransform() const; + QPointF mapQtToVg(const QPointF& p) const; + +protected: // data + + QList mItems; + //int mRowCount; + //int mColumnCount; + + //HbLabel *mLabel; + HgQuadRenderer *mQuadRenderer; + HgMediaWallRenderer *mRenderer; + + HgSpring mSpring; + HgDrag mDrag; + + QTime mTapDuration; // Temp hack until HbTapGesture is available + QTime mDoubleTapDuration; + int mTapCount; + + bool mAnimateUsingScrollBar; + + HgWidget::SelectionMode mSelectionMode; + QItemSelectionModel *mSelectionModel; + HgImage *mMarkImage; + + qreal mSpringVelAtDragStart; + bool mDragged; + int mFramesDragged; + + HbAbstractViewItem* mHitItemView; + QPixmap mHitItemPixmap; + + HgLongPressVisualizer* mLongPressVisualizer; + QTimer* mLongPressTimer; + HgWidgetItem* mHitItem; + int mHitItemIndex; + + QPointF mOffsetAtDragStart; + QTime mLongTapDuration; + bool mScrollBarPressed; + +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/HgImageFader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/HgImageFader.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGIMAGEFADER_H_ +#define HGIMAGEFADER_H_ + +#include +#include +#include + +class HgImage; + +class HgImageFader : public QObject +{ + Q_OBJECT +public: + HgImageFader(); + virtual ~HgImageFader(); + void addImage(HgImage* image); + void removeImage(HgImage* image); + void fadeImages(); +signals: + void doUpdate(); +private slots: + void doFading(); +private: + QTimer mTimer; + QLinkedList mImages; +}; + +#endif /* HGIMAGEFADER_H_ */ diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/HgScrollBufferManager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/HgScrollBufferManager.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,86 @@ +/* +* Copyright (c) 2009 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: +* +*/ + + +#ifndef HGSCROLLBUFFERMANAGER_H_ +#define HGSCROLLBUFFERMANAGER_H_ + +#include +#include + +class HgScrollBufferManager: public QObject + { + Q_OBJECT +public: + + HgScrollBufferManager( + int bufferSize, + int bufferTreshold, + int initialPosition, + int totalCount); + + virtual ~HgScrollBufferManager(); + + void resetBuffer(int aPosition, int aTotalCount); + + void scrollPositionChanged(int newPosition); + + bool positionInsideBuffer(int position); + + void removeItems(int start, int end, int totalCount); + void addItems(int start, int end, int totalCount); + void moveItems(int start, int end, int target, int totalCount); + + void currentBuffer(int& bufferStart, int& bufferEnd); + +signals: + + void releaseItems(int releaseStart, int releaseEnd); + void requestItems(int requestStart, int requestEnd); + +protected slots: + + void timeout(); + +protected: + + void init(); + void asyncUpdate(); + bool isInsideBuffer(int pos); + bool isInsideBuffer(int start, int end); + +private: + + int mBufferSize; + int mBufferTreshold; + int mBufferPosition; + int mDiff; + int mTotalCount; + + bool mResetOrdered; + + int mRequestStart; + int mRequestCount; + int mReleaseStart; + int mReleaseCount; + QTimer mTimer; + +private: + Q_DISABLE_COPY(HgScrollBufferManager) + }; + +#endif /*HGSCROLLBUFFERMANAGER_H_*/ diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgcoverflowcontainer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgcoverflowcontainer.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,72 @@ +/* +* Copyright (c) 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: +* +*/ + +#ifndef HGCOVERFLOWCONTAINER_H +#define HGCOVERFLOWCONTAINER_H + +#include +#include "HgContainer.h" + +class HbLabel; + +class HgCoverflowContainer: public HgContainer +{ + Q_OBJECT + Q_DISABLE_COPY(HgCoverflowContainer) + +public: + explicit HgCoverflowContainer(QGraphicsItem* parent = 0); + virtual ~HgCoverflowContainer(); + + // events + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + virtual void resizeEvent(QGraphicsSceneResizeEvent *event); + + // from HgContainer + virtual HgMediaWallRenderer* createRenderer(); + virtual qreal getCameraDistance(qreal springVelocity); + virtual qreal getCameraRotationY(qreal springVelocity); + virtual void handleTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex); + virtual void handleLongTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex); + virtual void onScrollPositionChanged(qreal pos); + virtual void handleCurrentChanged(const QModelIndex & current); + virtual void itemDataChanged(const int &firstIndex, const int &lastIndex); + virtual void scrollToPosition(const QPointF& pos, bool animate); + + void setTitlePosition(HgMediawall::LabelPosition position); + HgMediawall::LabelPosition titlePosition() const; + void setDescriptionPosition(HgMediawall::LabelPosition position); + HgMediawall::LabelPosition descriptionPosition() const; + void setTitleFontSpec(const HbFontSpec &fontSpec); + HbFontSpec titleFontSpec() const; + void setDescriptionFontSpec(const HbFontSpec &fontSpec); + HbFontSpec descriptionFontSpec() const; + +private: + void positionLabels(); + void updateLabels(int itemIndex); + +private: + HbLabel *mTitleLabel; + HbLabel *mDescriptionLabel; + HgMediawall::LabelPosition mTitlePosition; + HgMediawall::LabelPosition mDescriptionPosition; + int mCenterIconTop; + int mPrevPos; +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgdrag.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgdrag.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,41 @@ +/* +* Copyright (c) 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: Container for pan (drag) gesture -related data and logic. +* +*/ + +#ifndef HGDRAG_H +#define HGDRAG_H + +#include + +class HgDrag +{ +public: + HgDrag(); + void reset(const qreal delta, const qreal viewPos); + qreal update(const qreal delta, const qreal viewPos, const qreal itemWidth); + bool finish(const qreal viewPos, bool stopToFullItem, qreal &newPos); + qreal viewPosAtStart() const; + +private: + QTime mDuration; + qreal mViewPosAtStart; + qreal mLength; + qreal mCumulatedDelta; + int mDirection; + int mDirectionChange; +}; + +#endif // HGDRAG_H diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hggrid_p.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hggrid_p.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,40 @@ +/* +* Copyright (c) 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: +* +*/ + +#ifndef HGGRID_P_H +#define HGGRID_P_H + +#include +#include "hgwidgets_p.h" + +class HgGridPrivate : public HgWidgetPrivate +{ + Q_DECLARE_PUBLIC(HgGrid) + +public: + + HgGridPrivate(); + virtual ~HgGridPrivate(); + + void init(Qt::Orientation scrollDirection); + +private: + +}; + +#endif //HGGRID_P_H + diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hggridcontainer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hggridcontainer.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,51 @@ +/* +* Copyright (c) 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: +* +*/ + +#ifndef HGGRIDCONTAINER_H +#define HGGRIDCONTAINER_H + +#include "HgContainer.h" + +class HbLabel; +class HgWidgetItem; +class HgMediaWallRenderer; + +class HgGridContainer : public HgContainer +{ + Q_OBJECT + Q_DISABLE_COPY(HgGridContainer) + +public: + explicit HgGridContainer(QGraphicsItem *parent = 0); + + virtual ~HgGridContainer(); + +protected: + + // events + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + // from HgContainer + virtual HgMediaWallRenderer* createRenderer(); + virtual qreal getCameraDistance(qreal springVelocity); + virtual qreal getCameraRotationY(qreal springVelocity); + virtual void handleTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex); + virtual void handleLongTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemindex); + +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgimage.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgimage.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGIMAGE_H +#define HGIMAGE_H + +class QImage; + +/** + * Interface class for Images provided to HgQuadRenderer. + */ +class HgImage +{ +public: + virtual ~HgImage() {} + virtual void setAlpha(qreal alpha) { mAlpha = alpha; } + virtual qreal alpha() const { return mAlpha; } + virtual void setImage(QImage& image)=0; + virtual void releaseImage()=0; +private: + qreal mAlpha; +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgindexfeedback.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgindexfeedback.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,71 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGINDEXFEEDBACK_H +#define HGINDEXFEEDBACK_H + +#include +#include +#include + +class HbScrollBar; +class HgIndexFeedbackPrivate; +class HbStyleOptionIndexFeedback; +class HgWidget; + +QT_BEGIN_NAMESPACE +class QGraphicsItem; +QT_END_NAMESPACE + +class HgIndexFeedback : public HbWidget +{ + Q_OBJECT + +public: + + explicit HgIndexFeedback(QGraphicsItem *parent=0); + virtual ~HgIndexFeedback(); + + enum { Type = Hb::ItemType_IndexFeedback }; + int type() const { return Type; } + + void setIndexFeedbackPolicy( HgWidget::IndexFeedbackPolicy policy); + HgWidget::IndexFeedbackPolicy indexFeedbackPolicy() const; + + void setWidget(HgWidget *itemView); + HgWidget* widget() const; + + virtual QGraphicsItem *primitive(HbStyle::Primitive primitive) const; + +protected: + virtual void polish( HbStyleParameters& params); + virtual bool sceneEventFilter(QGraphicsItem* watched, QEvent* event); + virtual bool eventFilter(QObject *obj, QEvent *event); + void initStyleOption(HbStyleOptionIndexFeedback *option) const; + +private: + Q_DECLARE_PRIVATE_D(d_ptr, HgIndexFeedback) + Q_DISABLE_COPY(HgIndexFeedback) + + Q_PRIVATE_SLOT(d_func(), void _q_scrollPositionChanged(qreal, Qt::Orientation)) + Q_PRIVATE_SLOT(d_func(), void _q_hideIndexFeedback()) + Q_PRIVATE_SLOT(d_func(), void _q_itemViewDestroyed()) + Q_PRIVATE_SLOT(d_func(), void _q_hideIndexFeedbackNow()) + Q_PRIVATE_SLOT(d_func(), void _q_currentModelIndexChanged(QModelIndex, QModelIndex)) +}; + +#endif // HGINDEXFEEDBACK_H diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgindexfeedback_p.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgindexfeedback_p.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,102 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGINDEXFEEDBACKPRIVATE_H +#define HGINDEXFEEDBACKPRIVATE_H + +#include "hgindexfeedback.h" +#include + +#define HB_INDEXFEEDBACK_TYPE "indexfeedback" +#define EFFECT_IFAPPEAR "appear" +#define EFFECT_IFDISAPPEAR "disappear" + +QT_BEGIN_NAMESPACE +class QGraphicsWidget; +class QGraphicsItem; +class QRectF; +class QItemSelectionModel; +QT_END_NAMESPACE + +class HgIndexFeedbackPrivate : public HbWidgetPrivate +{ + Q_DECLARE_PUBLIC( HgIndexFeedback ) + +public: + HgIndexFeedbackPrivate(); + virtual ~HgIndexFeedbackPrivate(); + void init(); + + void showIndexFeedback(); + void updateIndex(); + + void scrollBarPressed(); + void scrollBarReleased(); + + void connectScrollBarToIndexFeedback(HbScrollBar* scrollBar); + void disconnectItemView(); + void connectModelToIndexFeedback(QItemSelectionModel* model); + + void _q_scrollPositionChanged(qreal value, Qt::Orientation orientation); + void _q_hideIndexFeedback(); + void _q_itemViewDestroyed(); + void _q_hideIndexFeedbackNow(); + void _q_currentModelIndexChanged(const QModelIndex& current, const QModelIndex& previous); + + void updatePrimitives(); + void createPrimitives(); + + void calculatePopupRects(); + qreal textHeight() const; + qreal textWidth() const; + + QString displayText(const QVariant &data) const; + +public: + int mIndexFeedbackPressTimeout; + int mIndexFeedbackDwellTimeout; + int mIndexFeedbackReleaseTimeout; + HgWidget::IndexFeedbackPolicy mIndexFeedbackPolicy; + + // TODO::The values are storred here is a work around for a bug in hbscrollbar. + // the bug is that the value changed signal is emitted when the thumb + // is pressed, and again when it is released, regaurdless of if there was a value change. + // once that bug is fixed, this should be removed. + qreal mScrollBarValue; + + QTimer *mIndexFeedbackTimer; + QTimer *mDisappearTimer; + + QString mPopupContent; + QGraphicsItem *mTextItem; + QGraphicsItem *mPopupItem; + + QRectF mPopupTextRect; + QRectF mPopupBackgroundRect; + QRectF mItemViewContentsRect; + + qreal mOneCharHeight; + qreal mThreeCharHeight; + qreal mThreeCharWidth; + qreal mStringOffset; + + HgWidget* mWidget; + QList mPopupItemList; + bool mScrollBarPressed; +}; + +#endif //HBINDEXFEEDBACKPRIVATE_H diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hglongpressvisualizer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hglongpressvisualizer.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,47 @@ +/* +* Copyright (c) 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: +* +*/ + +#ifndef HGLONGPRESSVISUALIZER_H +#define HGLONGPRESSVISUALIZER_H + +#include +#include +#include + +#include "hgmediawalldataprovider.h" +#include "hgdrag.h" +#include "hgspring.h" + +class HgLongPressVisualizer : public HbWidget +{ +public: + HgLongPressVisualizer(QGraphicsItem* parent=0); + virtual ~HgLongPressVisualizer(); + + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget=0); + QRectF boundingRect() const; + + void start(const QPointF& pos); + void stop(); + void setFrame(int frame); +private: + QRectF rect; + bool active; + qreal spanAngle; +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgmediawall_p.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgmediawall_p.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,52 @@ +/* +* Copyright (c) 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: +* +*/ + +#ifndef HGMEDIAWALL_P_H +#define HGMEDIAWALL_P_H + +#include +#include "hgwidgets_p.h" + +class HgCoverflowContainer; + +class HgMediawallPrivate : public HgWidgetPrivate +{ + Q_DECLARE_PUBLIC(HgMediawall) + +public: + + HgMediawallPrivate(); + virtual ~HgMediawallPrivate(); + + void init(); + + void setTitlePosition(HgMediawall::LabelPosition position); + HgMediawall::LabelPosition titlePosition() const; + void setDescriptionPosition(HgMediawall::LabelPosition position); + HgMediawall::LabelPosition descriptionPosition() const; + void setTitleFontSpec(const HbFontSpec &fontSpec); + HbFontSpec titleFontSpec() const; + void setDescriptionFontSpec(const HbFontSpec &fontSpec); + HbFontSpec descriptionFontSpec() const; + +private: + HgCoverflowContainer *container(); + const HgCoverflowContainer *container() const; +}; + +#endif //HGMEDIAWALL_P_H + diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgmediawalldataprovider.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgmediawalldataprovider.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGMEDIAWALLDATAPROVIDER_H +#define HGMEDIAWALLDATAPROVIDER_H + +class HgImage; + +/** + * Data Provider interface for HgMediWallRenderer. + */ +class HgMediaWallDataProvider +{ +public: + virtual ~HgMediaWallDataProvider() {} + /** + * Gets the number of images the model contains. + * @return number of images the model contains. + */ + virtual int imageCount() const=0; + /** + * Gets the image at given index. + * @param index of the image in the model + * @return pointer to HgImage-object. + */ + virtual const HgImage* image(int index) const=0; + /** + * Gets the the flags associated to the item at index + * @param index of the item + * @return flags of the item + */ + virtual int flags(int index) const=0; + /** + * Gets the image associated to given flags. + * @param flags. + * @return pointer HgImage-object. + */ + virtual const HgImage* indicator(int flags) const=0; +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgmediawallrenderer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgmediawallrenderer.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,269 @@ +/* +* Copyright (c) 2009 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: +* +*/ +#ifndef HGMEDIAWALLRENDERER_H +#define HGMEDIAWALLRENDERER_H + +#include +#include + +class HgQuadRenderer; +class HgMediaWallDataProvider; +class QPointF; +class QPainter; +class QTimer; +class QStateMachine; +class HgAnimatedQuad; +class HgQuad; +class HgImageFader; +class HgImage; +class QPolygonF; + +/** + * MediaWall rendering engine class. + */ +class HgMediaWallRenderer : public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal animationAlpha READ animationAlpha WRITE setAnimationAlpha) + Q_PROPERTY(qreal stateAnimationAlpha READ stateAnimationAlpha WRITE setStateAnimationAlpha) +public: + + enum OpeningAnimationType + { + OpeningAnimationFlip, + OpeningAnimationZoomIn, + OpeningAnimationZoomOver + }; + + explicit HgMediaWallRenderer(HgMediaWallDataProvider* provider); + + virtual ~HgMediaWallRenderer(); + + void setCameraDistance(qreal distance); + qreal getCameraDistance() const; + void setCameraRotationY(qreal angle); + qreal getCameraRotationY() const; + void setCameraRotationZ(qreal angle); + qreal getCameraRotationZ() const; + + void draw( + const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter); + + void setFlipAnimationAngle(qreal angleInDegrees); + + void setOpeningAnimationType(OpeningAnimationType type); + + void setOpeningAnimationDuration(int msecs); + + void setOrientation(Qt::Orientation orientation, bool animate=false); + Qt::Orientation getOrientation() const; + + void enableCoverflowMode(bool enabled); + bool coverflowModeEnabled() const; + + void setRowCount(int rowCount, const QSizeF& newImageSize, bool animate=false); + int getRowCount() const; + + HgQuad* getQuadAt(const QPointF& position) const; + + void setRect(const QRectF& windowRect); + const QRectF& getRect() const; + void setSpacing(const QSizeF& spacing); + const QSizeF& getSpacing() const; + void setImageSize(const QSizeF& imageSize); + const QSizeF& getImageSize() const; + + void setFrontCoverElevationFactor(qreal elevation); + qreal getFrontCoverElevationFactor() const; + + void openItem(int index, bool animate); + void closeItem(bool animate); + bool isItemOpen() const; + + void enableReflections(bool enabled); + bool reflectionsEnabled() const; + + qreal getWorldWidth() const; + + void beginRemoveRows(int start, int end); + void endRemoveRows(); + + int getSelectedItem() const; + + void initialize(QPainter* painter); + bool initialized() const; + + HgQuadRenderer* getRenderer(); + + bool getItemPoints(int index, QPolygonF& points) const; + + QList getVisibleQuads() const; + +signals: + void renderingNeeded(); + void itemOpened(int index); + void itemClosed(int index); + void itemMarked(int index); + void toggleItem(); + void toggleState(); + void itemsRemoved(int start, int end); +private slots: + void onIdleState(); + void onOpenedState(); + void emitUpdate(); +protected: + + struct State + { + QList mQuads; + }; + + void setAnimationAlpha(qreal alpha); + qreal animationAlpha() const; + + void createStateMachine(); + void recordState(State& state); + + void updateStateAnimation(qreal alpha); + void setStateAnimationAlpha(qreal alpha); + qreal stateAnimationAlpha() const; + void setupStateAnimation(QPainter* painter); + + void setupRows( + const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter); + + void drawQuads(QPainter* painter); + void resetQuads(); + void updateCameraMatrices(); + void updateSpacingAndImageSize(); + qreal getRowPosY(int row); + qreal getColumnPosX(int column); + QPointF mapFromWindow(const QPointF& point) const; + void applyOpeningAnimation(HgQuad* quad); + void startStateAnimation(QPainter* painter); + + + void setupCoverflow(const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter); + + void setupGridPortrait(const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter); + + void setupGridLandscape(const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter); + + void setupGridRow(qreal posY, int itemIndex, int& quadIndex); + void setupGridColumn(qreal posX, int itemIndex, int& quadIndex); + void setupDefaultQuad(const QVector3D& pos, int itemIndex, bool reflectionsEnabled, int& quadIndex); + void setupIndicator(HgQuad* parent, + HgQuad* indicator, const HgImage* indicatorImage, int itemIndex); + bool initializeRenderer(QPainter* painter); + +protected: + + enum ItemState + { + ItemClosed, + ItemOpening, + ItemOpened, + ItemClosing + }; + + HgMediaWallDataProvider* mDataProvider; + HgQuadRenderer* mRenderer; + HgQuadRenderer* mIndicatorRenderer; + bool mRendererInitialized; + + Qt::Orientation mOrientation; + Qt::Orientation mNextOrientation; + + qreal mStateAnimationAlpha; + bool mStateAnimationOnGoing; + + qreal mAnimationAlpha; + + OpeningAnimationType mOpeningAnimationType; + int mOpeningAnimationDuration; + int mOpenedItem; + int mSelectedItem; + qreal mFlipAngle; + QTimer* mAnimationTimer; + QMatrix4x4 mViewMatrix; + QMatrix4x4 mProjMatrix; + QStateMachine* mStateMachine; + qreal mZoomAmount; + bool mCoverflowMode; + int mRowCount; + int mNextRowCount; + + QList mAnimatedQuads; + int mStateAnimationDuration; + qreal mStep; + qreal mZfar; + QRectF mRect; + + QSizeF mSpacing2D; + QSizeF mSpacing3D; + QSizeF mImageSize2D; + QSizeF mImageSize3D; + + qreal mCameraDistance; + qreal mCameraRotationY; + qreal mCameraRotationZ; + + qreal mFrontCoverElevation; + + State mOldState; + State mNextState; + + + bool mReflectionsEnabled; + HgImageFader* mImageFader; + + QSizeF mNextImageSize; + + bool mItemCountChanged; + int mRemoveStart; + int mRemoveEnd; + int mInsertStart; + int mInsertEnd; + int mColumnCount; + + ItemState mOpenedItemState; + +private: + Q_DISABLE_COPY(HgMediaWallRenderer) +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgquad.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgquad.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,161 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGQUAD_H +#define HGQUAD_H + +#include +#include +#include +#include + +class HgImage; + +/** + * Quad class to be used by HgQuadRenderer. + */ +class HgQuad +{ +public: + /** + * Constructor. + */ + HgQuad(); + /** + * Destructor. + */ + virtual ~HgQuad(); + /** + * Sets the position of the quad. + * @param position in 3D space. + */ + void setPosition(const QVector3D& position); + /** + * Sets the rotation of the quad. + * @param rotation as quaternion. + */ + void setRotation(const QQuaternion& rotation); + /** + * Sets the image to use in this quad. + * @param image to use in this quad. + */ + void setImage(const HgImage* image); + /** + * Toggles quads visible/hidden. + * @param visible true to make quad visible. + */ + void setVisible(bool visible); + /** + * Sets the pivot point of the quad. + * @pivot to set for this quad. Quads are considered unit quads so to set pivot for example, + * to bottom left corner you would use QVector2D(-0.5f, -0.5f). + */ + void setPivot(const QVector2D& pivot); + /** + * Sets the scale of the quad. + * @param scale scaling 2d vector (appliend before rotation but after pivot is transformed) + */ + void setScale(const QVector2D& scale); + /** + * Sets user data to this quad. + * @param userdata to be carried in this quad. This can be for example to identify object that is represented by this specific quad instance. + */ + void setUserData(const QVariant& data); + /** + * Gets the image in this quad. + * @return pointer HgImage-object carried by this quad. + */ + const HgImage* image() const; + /** + * Gets the position of this quad. + * @return position vector. + */ + const QVector3D& position() const; + /** + * Gets the roation of this quad. + * @return rotation quaternion. + */ + const QQuaternion& rotation() const; + /** + * Tells whether or not this quad is visible and should be rendered. + * @return true if this quad is visible and should be rendered. + */ + bool visible() const; + /** + * Gets the pivot point of this quad. + * @return pivot point applied to this quads trasformation. + */ + const QVector2D& pivot() const; + /** + * Gets the scale of this quad. + * @return scaling applied to this quads transformation. + */ + const QVector2D& scale() const; + /** + * Gets the user data associated in to this quad. + * @return user data carriend by this quad. + */ + const QVariant& userData() const; + /** + * + */ + HgQuad* copy() const; + /** + * + */ + void copyFrom(const HgQuad& quad); + /* + * + */ + void setOuterRotation(const QQuaternion& rot); + /* + * + */ + const QQuaternion outerRotation() const; + /** + * + */ + void enableMirrorImage(bool enabled); + /** + * + */ + bool mirrorImageEnabled() const; + /** + * + */ + void setAlpha(qreal alpha); + /** + * + */ + qreal alpha() const; +private: + QVector3D mPosition; + QQuaternion mRotation; + const HgImage* mImage; + bool mVisible; + QVector2D mPivot; + QVector2D mScale; + QVariant mUserData; + QQuaternion mOuterRotation; + bool mDrawMirror; + qreal mAlpha; +private: + Q_DISABLE_COPY(HgQuad) +}; + + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgquadrenderer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgquadrenderer.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,108 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGQUADRENDERER_H +#define HGQUADRENDERER_H + +#include + +class HgQuad; +class QPointF; +class QPainter; +class QRectF; +class QMatrix4x4; +class QPolygonF; +class HgImage; +class QImage; +class HgImageFader; +/** + * + * Abstract class to be inherited by differend quad renderer implementations. + * One could for example implement this in OpenGL instead of OpenVG. + */ +class HgQuadRenderer +{ +public: + /** + * Destructor. + */ + virtual ~HgQuadRenderer(); + /** + * Gets the quad at given index. + * @return HgQuad-object at index. + */ + virtual HgQuad* quad(int index); + /** + * Gets the max amount of quads this renderer can draw. + * @return max amount of quads. + */ + virtual int quadCount() const; + /** + * Gets quads index at pointer position. + * @param pointer position. + * @return quad under the pointer position or -1 if nothing is there. + */ + virtual HgQuad* getQuadAt(const QPointF& point) const = 0; + /** + * Transform quads with view and projection transformation for rendering. + * @param view view transformation matrix. + * @param projection transformation matrix. + * @rect window rectangle. + */ + virtual void transformQuads(const QMatrix4x4& view, const QMatrix4x4& proj, + const QRectF& rect)=0; + /** + * Draw transformed quads using painter or underlying Native graphics API. + * This should be called inside Widgets draw method. + * @param rect window rectangle. + * @param painter QPainter-object. + */ + virtual void drawQuads(const QRectF& rect, QPainter* painter)=0; + + /** + * + */ + virtual bool getQuadTranformedPoints(QPolygonF& points, int index) const=0; + + /** + * + */ + virtual void setMirroringPlaneY(qreal mirroringPlaneY); + + /** + * + */ + virtual HgImage* createNativeImage()=0; + + /** + * + */ + virtual void setImageFader(HgImageFader* fader); + + /** + * + */ + virtual QList getVisibleQuads(const QRectF& rect) const=0; +protected: + HgQuadRenderer(int maxQuads); + + QList mQuads; + qreal mMirroringPlaneY; + HgImageFader* mImageFader; +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgspring.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgspring.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,74 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGSPRING_H +#define HGSPRING_H + +#include +#include +#include + +class QTimer; + +/** + * Spring physics class. + */ +class HgSpring : public QObject +{ + Q_OBJECT +public: + + explicit HgSpring(); + virtual ~HgSpring(); + + void setK(qreal K); + void setDamping(qreal damping); + + void animateToPos(const QPointF& pos); + void gotoPos(const QPointF& pos); + void cancel(); + bool isActive() const; + + const QPointF& startPos() const; + const QPointF& pos() const; + const QPointF& endPos() const; + const QPointF& velocity() const; + + bool updatePositionIfNeeded(); + +signals: + void updated(); + void started(); + void ended(); +private slots: + void update(); +private: + Q_DISABLE_COPY(HgSpring) + + QPointF mStartPos; + QPointF mPos; + QPointF mEndPos; + QPointF mVelocity; + qreal mK; + qreal mDamping; + int mAccumulator; + QTimer* mTimer; + QTime mPrevTime; + bool mDoNotUpdate; +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgvgimage.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgvgimage.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGVGIMAGE_H +#define HGVGIMAGE_H + +#include +#include +#include +#include "HgImage.h" + +class HgVgImagePool; +class HgImageFader; +class HgVgQuadRenderer; +/** + * Implements HgImage for HgVgQuadRenderer implementation. + */ +class HgVgImage : public HgImage +{ +public: + HgVgImage(HgVgQuadRenderer* renderer); + virtual ~HgVgImage(); + + int width() const; + int height() const; + + VGImage image() const; + + int mirrorImageWidth() const; + int mirrorImageHeight() const; + + VGImage mirrorImage() const; + + void setImage(QImage& image); + void releaseImage(); + + void upload(bool mirror=false); + +private: + VGImage mVgImage; + VGImage mMirrorImage; + QSize mMirrorSize; + QImage mQImage; + HgVgQuadRenderer* mRenderer; +private: + Q_DISABLE_COPY(HgVgImage) +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgvgimagepool.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgvgimagepool.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGVGIMAGEPOOL_H_ +#define HGVGIMAGEPOOL_H_ + +#include +#include + +class HgVgImagePool +{ +public: + HgVgImagePool(int numImages, int imgWidth, int imgHeight, bool alpha); + ~HgVgImagePool(); + void releaseImage(VGImage image); + VGImage getImage(); +private: + QLinkedList mFreeImages; + QLinkedList mUsedImages; +}; + + +#endif /* HGVGIMAGEPOOL_H_ */ diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgvgquadrenderer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgvgquadrenderer.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGVGQUADRENDERER_H +#define HGVGQUADRENDERER_H + +#include "hgquadrenderer.h" +#include +#include +#include + +class QPoint; +class QPainter; +class QRectF; +class QMatrix4x4; +class HgVgQuad; +class HgVgImage; +class HgImageFader; +class QSize; +/** + * OpenVG implementation of the HgQuadRenderer. + */ +class HgVgQuadRenderer: public HgQuadRenderer +{ +public: + HgVgQuadRenderer(int maxQuads); + virtual ~HgVgQuadRenderer(); + virtual HgQuad* getQuadAt(const QPointF& point) const; + virtual void transformQuads(const QMatrix4x4& view, const QMatrix4x4& proj, + const QRectF& rect); + virtual void drawQuads(const QRectF& rect, QPainter* painter); + virtual bool getQuadTranformedPoints(QPolygonF& points, int index) const; + virtual HgImage* createNativeImage(); + virtual QList getVisibleQuads(const QRectF& rect) const; + + // new functions + HgVgImage* defaultImage(); + QSize imageSize(bool mirror=false) const; + HgImageFader* imageFader(); +private: + + QList mTransformedQuads; + + QList mSortedQuads; + + HgVgImage* mDefaultVgImage; + +}; + +#endif diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgwidgetitem.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgwidgetitem.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2008-2009 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: HgWidget private class definition +* +*/ + + +#ifndef HGWIDGETITEM_H +#define HGWIDGETITEM_H + +#include +#include +#include +#include +#include + +class HgQuadRenderer; +class HgImage; + +class HgWidgetItem +{ +public: + + HgWidgetItem(HgQuadRenderer* renderer); + HgWidgetItem( HgQuadRenderer* renderer, QImage image, QString title, QString description ); + virtual ~HgWidgetItem(); + + void setImage( QImage image ); + + void setTitle( QString title ); + QString title() const; + + const HgImage* image() const; + + void setDescription( QString description ); + QString description() const; + + void setModelIndex( const QModelIndex& index); + QModelIndex modelIndex() const; + + bool validData() const; + bool updateItemData(); + void releaseItemData(); + + bool visibility() const; + void setVisibility(bool visible); + +private: + + QString mTitle; + QString mDescription; + QModelIndex mModelIndex; + bool mValidData; + HgImage* mHgImage; + HgQuadRenderer* mRenderer; + bool mVisibility; + + Q_DISABLE_COPY(HgWidgetItem) +}; + +#endif //HGWIDGETITEM_H + diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/hgwidgets_p.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/hgwidgets_p.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,127 @@ +/* +* Copyright (c) 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: +* +*/ + +#ifndef HGWIDGET_P_H +#define HGWIDGET_P_H + +#include +#include +#include +#include + +class QAbstractItemModel; +class HgContainer; +class HgScrollBufferManager; +class QGraphicsLinearLayout; +class HgIndexFeedback; + +class HgWidgetPrivate : public HbWidgetPrivate +{ + Q_DECLARE_PUBLIC(HgWidget) + +public: + + HgWidgetPrivate(); + virtual ~HgWidgetPrivate(); + + void init(HgContainer *container); + + void setModel(QAbstractItemModel *model); + + void setSelectionModel(QItemSelectionModel *selectionModel); + QItemSelectionModel *selectionModel() const; + + void setSelectionMode(HgWidget::SelectionMode mode, bool resetSelection); + HgWidget::SelectionMode selectionMode() const; + void selectAll(); + void clearSelection(); + + QModelIndex currentIndex() const; + void setCurrentIndex(const QModelIndex &index, + QItemSelectionModel::SelectionFlags selectionFlag=QItemSelectionModel::NoUpdate); + + void scrollTo(const QModelIndex &index); + + bool getItemOutline(const QModelIndex& index, QPolygonF& points); + void aboutToChangeOrientation(); + void orientationChanged(Qt::Orientation orientation); + + QList getVisibleItemIndices() const; + Qt::Orientation scrollDirection() const; + + void setIndexFeedbackPolicy( HgWidget::IndexFeedbackPolicy policy); + HgWidget::IndexFeedbackPolicy indexFeedbackPolicy() const; + +private: + + void clearCurrentModel(); + void initializeNewModel(); + + void adjustGeometry(); + + void createScrollBar(Qt::Orientation orientation); + + void setScrollBarPolicy(HgWidget::ScrollBarPolicy policy); + void replaceScrollBar(HbScrollBar *scrollBar); + + virtual void updateScrollMetrics( qreal pos = 0 ); + void prepareScrollBars( qreal pos = 0); + + virtual void updateScrollBar(qreal pos = 0); + void displayScrollBar(qreal pos = 0); + void setScrollBarMetrics(qreal pos = 0); + + void lostForeground(); + void gainedForeground(); + + // private slot functions + void _q_scrollPositionChanged(qreal index, bool scrollBarAnimation); + void _q_releaseItems( int releaseStart, int releaseEnd ); + void _q_requestItems( int requestStart, int requestEnd ); + void _q_hideScrollBars(); + void _q_thumbPositionChanged(qreal value, Qt::Orientation orientation); + void _q_insertRows(const QModelIndex &parent, int start, int end); + void _q_removeRows(const QModelIndex &parent, int start, int end); + void _q_moveRows(const QModelIndex &sourceParent, int sourceStart, + int sourceEnd, const QModelIndex &destinationParent, + int destinationRow); + void _q_groovePressed(qreal value, Qt::Orientation orientation); + +protected: + + QGraphicsLinearLayout *mLayout; + + HgContainer *mContainer; + HgScrollBufferManager *mBufferManager; + + QAbstractItemModel *mModel; + QItemSelectionModel *mSelectionModel; + QItemSelectionModel *mDefaultSelectionModel; + + HbScrollBar *mScrollBar; + HgWidget::ScrollBarPolicy mScrollBarPolicy; + bool mAbleToScroll; + QTimer mScrollBarHideTimer; + + bool mHandleLongPress; + bool mForeground; + int mBufferSize; + HgIndexFeedback *mIndexFeedback; +}; + +#endif //HGWIDGET_p_H + diff -r 000000000000 -r 89c329efa980 ganeswidgets/inc/trace.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/inc/trace.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,148 @@ +/* +* Copyright (c) 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: Tracing macros, 2nd generation +* +*/ + +#ifndef TRACE_H +#define TRACE_H + +#include + +//----------------------------------------------------------------------------- +// Trace definitions +//----------------------------------------------------------------------------- +// + +/** +* Error trace enabled +*/ +#ifdef _DEBUG +//#ifdef __WINS__ + #define ERROR_TRACE + #define INFO_TRACE + #define TIMESTAMP_TRACE + #define FUNC_TRACE +#else + #undef ERROR_TRACE + #undef INFO_TRACE + #undef TIMESTAMP_TRACE + #undef FUNC_TRACE +#endif + + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- +// + +/** +* Trace prefixes for macros with component name. +*/ +#define _TRACE_PREFIX "[HG]:" + +/** +* Prefix error trace +*/ +#define _ERROR_PREFIX _TRACE_PREFIX " [ERROR]:" + +/** +* Prefix info trace. +*/ +#define _INFO_PREFIX _TRACE_PREFIX " [INFO]:" + +/** +* Prefix timestamp trace. +*/ +#define _TIMESTAMP_PREFIX _TRACE_PREFIX " [TIMESTAMP]:" + +//----------------------------------------------------------------------------- +// Error trace macros +// Usage: wrap traces in ERROR() macro to allow disabling them in release builds. +// Use normal stream object operations. +// Examples: +// ERROR( "xxx failed" ); +// ERROR( "Test trace arg =" << 999 << "arg2 =" << title() ); +//----------------------------------------------------------------------------- +// +#ifdef ERROR_TRACE + #define ERROR(trace) {qDebug() << _ERROR_PREFIX << trace;} + #define ERROR_PARAM(param) param + #define HANDLE_ERROR(trace) {ERROR(trace << "File:" << __FILE__ << ", line:" << __LINE__); __BREAKPOINT();} + #define HANDLE_ERROR_BOOL(x) {if (!x) {ERROR(#x << "is false" << "File:" << __FILE__ << ", line:" << __LINE__); __BREAKPOINT();}} + #define HANDLE_ERROR_NULL(x) {if (!x) {ERROR(#x << "is NULL" << "File:" << __FILE__ << ", line:" << __LINE__); __BREAKPOINT();}} + #define HANDLE_ERROR_NEG(x) {if (x < 0) {ERROR(#x << "=" << x << "File:" << __FILE__ << ", line:" << __LINE__); __BREAKPOINT();}} + #define CHECK_ERROR(err, trace) {if (err < 0) ERROR(trace << err);} +#else //ERROR_TRACE not defined + #define ERROR(trace) + #define ERROR_PARAM(param) + #define HANDLE_ERROR(trace) + #define HANDLE_ERROR_BOOL(x) + #define HANDLE_ERROR_NULL(x) + #define HANDLE_ERROR_NEG(x) + #define CHECK_ERROR(err,trace) +#endif //ERROR_TRACE + +//----------------------------------------------------------------------------- +// Info trace macros +// Usage: wrap traces in INFO() macro to allow disabling them in release builds. +// Use normal stream object operations. +// Examples: +// INFO( "Test trace" ); +// INFO( "Test trace arg =" << 999 << "arg2 =" << title() ); +//----------------------------------------------------------------------------- +// +#ifdef INFO_TRACE + #define INFO(trace) {qDebug() << _INFO_PREFIX << trace;} + #define INFO_PARAM(param) param +#else //INFO_TRACE not defined + #define INFO(trace) + #define INFO_PARAM(param) +#endif //INFO_TRACE + +//----------------------------------------------------------------------------- +// Function trace macros +//----------------------------------------------------------------------------- +// +#ifdef FUNC_TRACE + + class FuncLog + { + public: + inline FuncLog( const char* func ) : m_func( func ) + { qDebug() << _TRACE_PREFIX << m_func << "-START"; } + inline ~FuncLog() { qDebug() << _TRACE_PREFIX << m_func << "-END"; } + private: // Data + QString m_func; + }; + + #define FUNC_LOG FuncLog _fl( __PRETTY_FUNCTION__ ); +#else //FUNC_TRACE not defined + #define FUNC_LOG +#endif //FUNC_TRACE + +//----------------------------------------------------------------------------- +// Timestamp trace macros +//----------------------------------------------------------------------------- +// +#ifdef TIMESTAMP_TRACE + #include + #define TIMESTAMP(trace)\ + {qDebug() << _TIMESTAMP_PREFIX << "(" << \ + QTime::currentTime().toString("HH:mm:ss:zzz") << ")" << trace;} +#else //TIMESTAMP_TRACE not defined + #define TIMESTAMP(trace) +#endif //TIMESTAMP_TRACE + +#endif // TRACE_H diff -r 000000000000 -r 89c329efa980 ganeswidgets/rom/ganeswidgets.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/rom/ganeswidgets.iby Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,28 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef GANESWIDGETS_IBY +#define GANESWIDGETS_IBY + +#include + +#include + +file=ABI_DIR\BUILD_DIR\ganeswidgets.dll SHARED_LIB_DIR\ganeswidgets.dll +data=ZSYSTEM\install\ganeswidgetsstub.sis System\Install\ganeswidgetsstub.sis + +#endif //GANESWIDGETS_IBY diff -r 000000000000 -r 89c329efa980 ganeswidgets/rom/rom.pri --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/rom/rom.pri Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,27 @@ +# +# Copyright (c) 2009 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: +# + +symbian { + HGWIDGETS_IBY_DIR = $$section(PWD,":",1) + + exists(/epoc32/include/platform_paths.hrh) { + BLD_INF_RULES.prj_exports += "$${LITERAL_HASH}include " + } else { + BLD_INF_RULES.prj_exports += "$${LITERAL_HASH}include " + } + + BLD_INF_RULES.prj_exports += "$$HGWIDGETS_IBY_DIR/ganeswidgets.iby CORE_MW_LAYER_IBY_EXPORT_PATH(ganeswidgets.iby)" +} \ No newline at end of file diff -r 000000000000 -r 89c329efa980 ganeswidgets/sis/ganeswidgets.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/sis/ganeswidgets.pkg Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,35 @@ +; +; Copyright (c) 2009 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: +; +; Installation file for ganeswidgets DLL +; +;Language - standard language definitions +&EN + +; standard SIS file header +#{"GanesWidgets"},(0x10207C66),10,10,0, TYPE=SA, RU + +;Localised Vendor name +%{"Nokia"} + +;Unique Vendor name +:"Nokia" + +;Supports Series 60 v 5.0 +[0x1028315F], 0, 0, 0, {"S60ProductID"} + +;Files to install +;GanesWidgets +"\epoc32\release\armv5\urel\ganeswidgets.dll" -"c:\sys\bin\ganeswidgets.dll" diff -r 000000000000 -r 89c329efa980 ganeswidgets/sis/ganeswidgetsstub.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/sis/ganeswidgetsstub.pkg Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,32 @@ +; +; Copyright (c) 2009 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: +; +; Installation file for ganeswidgets library stub for IAD +; +;Language - standard language definitions +&EN + +; standard SIS file header +#{"ganeswidgets"},(0x10207C66),10,0,0, TYPE=SA + +;Localised Vendor name +%{"Nokia"} + +;Unique Vendor name +:"Nokia" + +;Files to install +;ganeswidgets +"" - "z:\sys\bin\ganeswidgets.dll" diff -r 000000000000 -r 89c329efa980 ganeswidgets/sis/ganeswidgetsstub.sis Binary file ganeswidgets/sis/ganeswidgetsstub.sis has changed diff -r 000000000000 -r 89c329efa980 ganeswidgets/sis/stub.pri --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/sis/stub.pri Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,21 @@ +# +# Copyright (c) 2009 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: +# + +symbian { + GANESWIDGETS_STUB_DIR = $$section(PWD,":",1) + + BLD_INF_RULES.prj_exports += "$$GANESWIDGETS_STUB_DIR/ganeswidgetsstub.sis /epoc32/data/z/system/install/ganeswidgetsstub.sis" +} \ No newline at end of file diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/HgContainer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/HgContainer.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,960 @@ +/* +* Copyright (c) 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: +* +*/ + +#include +#include +#include +#include +#include +#include "hgcontainer.h" +#include "hgmediawallrenderer.h" +#include "hgquad.h" +#include "hgvgquadrenderer.h" +#include "hgvgimage.h" +#include "hgwidgetitem.h" +#include "trace.h" + +#include +#include +#include +#include +#include "hglongpressvisualizer.h" + +static const qreal KSpringKScrolling(50.0); +static const qreal KSpringKScrollBar(10.0); +static const qreal KSpringDampingScrolling(20.0); +static const qreal KSpringDampingScrollBar(5.0); +static const qreal KFramesToZeroVelocity(60.0); +static const int KLongTapDuration(400); + + +HgContainer::HgContainer(QGraphicsItem* parent) : + HbWidget(parent), + mQuadRenderer(0), + mRenderer(0), + mTapCount(0), + mAnimateUsingScrollBar(false), + mSelectionMode(HgWidget::NoSelection), + mSelectionModel(0), + mMarkImage(0), + mSpringVelAtDragStart(0), + mDragged(false), + mFramesDragged(0), + mHitItemView(NULL), + mLongPressVisualizer(NULL), + mLongPressTimer(NULL), + mHitItemIndex(NULL) +{ + FUNC_LOG; + + grabGesture(Qt::PanGesture); + grabGesture(Qt::TapGesture); + grabGesture(Qt::TapAndHoldGesture); +} + +HgContainer::~HgContainer() +{ + FUNC_LOG; + + for (QList::iterator i = mItems.begin(); i != mItems.end(); ++i) { + delete (*i); + } + mItems.clear(); + delete mMarkImage; + delete mRenderer; +} + +void HgContainer::setItemCount(int itemCount) +{ + FUNC_LOG; + + mItems.clear(); + for (int i=0; igetRowCount() : 0; +} + +QList HgContainer::items() const +{ + return mItems; +} + +HgWidgetItem* HgContainer::itemByIndex(const QModelIndex& index) const +{ + foreach (HgWidgetItem* item, mItems) { + if (item->modelIndex() == index) + return item; + } + + return 0; +} + +HgWidgetItem* HgContainer::itemByIndex(const int& index) const +{ + if (mItems.count() > index && index >= 0) + return mItems.at(index); + else + return 0; +} + +/*! + Changes the selection model of the container. + Ownership is not transferred. + Widget is redrawn to make new selection visible. +*/ +void HgContainer::setSelectionModel(QItemSelectionModel *selectionModel) +{ + FUNC_LOG; + HANDLE_ERROR_NULL(selectionModel); // Parameter is always a valid QItemSelectionModel + + if (mSelectionModel != selectionModel) { + if (mSelectionModel) { // mSelectionModel is 0 when called first time + mSelectionModel->disconnect(SIGNAL(currentChanged(QModelIndex,QModelIndex)), this); + + if (mSelectionModel->currentIndex().isValid() && + !(selectionModel->currentIndex().isValid())) { + selectionModel->setCurrentIndex(mSelectionModel->currentIndex(), + QItemSelectionModel::Current); + } + } + mSelectionModel = selectionModel; + connect(mSelectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), + SLOT(updateByCurrentIndex(QModelIndex))); + update(); + } +} + +/*! + Returns the selection model of the container. + Ownership is not transferred. +*/ +QItemSelectionModel *HgContainer::selectionModel() const +{ + FUNC_LOG; + + return mSelectionModel; +} + +/*! + Changes the selection mode of the container (no selection/multiselection). +*/ +void HgContainer::setSelectionMode(HgWidget::SelectionMode mode, bool resetSelection) +{ + FUNC_LOG; + + if (mSelectionMode != mode) { + mSelectionMode = mode; + + if (mSelectionModel && resetSelection) { + mSelectionModel->clearSelection(); + update(); + } + } +} + +/*! + Returns the selection mode of the container (no selection/multiselection). +*/ +HgWidget::SelectionMode HgContainer::selectionMode() const +{ + FUNC_LOG; + + return mSelectionMode; +} + +void HgContainer::dimensions(qreal &screenSize, qreal &worldSize) +{ + const QRectF containerRect(rect()); + + // TODO, fix logic + if (containerRect.height() > containerRect.width()) { + // assume we are in portrait mode, ofcource this might not be the case + screenSize = containerRect.height()/(mRenderer->getImageSize().height() + mRenderer->getSpacing().height()); + worldSize = worldWidth(); + } + else{ + screenSize = containerRect.width()/(mRenderer->getImageSize().width() + mRenderer->getSpacing().width()); + worldSize = worldWidth(); + } +} + +Qt::Orientation HgContainer::orientation() const +{ + FUNC_LOG; + + return mRenderer->getOrientation(); +} + +void HgContainer::setOrientation(Qt::Orientation orientation, bool animate) +{ + FUNC_LOG; + + mRenderer->setOrientation(orientation, animate); +} + +void HgContainer::scrollToPosition(qreal value, bool animate) +{ + FUNC_LOG; + + scrollToPosition(QPointF(value*worldWidth(), 0), animate); +} + +void HgContainer::scrollToPosition(const QPointF& pos, bool animate) +{ + FUNC_LOG; + + mAnimateUsingScrollBar = animate; + initSpringForScrollBar(); + + if (animate) + mSpring.animateToPos(pos); + else + mSpring.gotoPos(pos); +} + +void HgContainer::scrollTo(const QModelIndex &index) +{ + FUNC_LOG; + + if (index.isValid()) { + scrollToPosition(QPointF(index.row(), index.column()), false); + } +} + +void HgContainer::itemDataChanged(const QModelIndex &firstIndex, const QModelIndex &lastIndex) +{ + FUNC_LOG; + + // TODO, fix this + int columns = firstIndex.model()->columnCount(QModelIndex()); + + // Check this!! + int index = columns*firstIndex.row()+firstIndex.column(); + int index2 = columns*lastIndex.row()+lastIndex.column(); + + // convert indeces to match one dimensional item array + itemDataChanged( index, index2 ); +} + +void HgContainer::addItems(int start, int end) +{ + FUNC_LOG; + + int first = qBound(0, start, mItems.count()-1); + int last = qBound(0, end, mItems.count()-1); + for (int i = 0; i <= end-start; i++) { + HgWidgetItem* item = new HgWidgetItem(mQuadRenderer); + mItems.insert(start, item); + } +} + +void HgContainer::removeItems(int start, int end) +{ + FUNC_LOG; + + int first = qBound(0, start, mItems.count()-1); + int last = qBound(0, end, mItems.count()-1); + for (int i = last; i >= first; i--) { + delete mItems.at(i); + mItems.removeAt(i); + } +} + +void HgContainer::moveItems(int start, int end, int destination) +{ + FUNC_LOG; + + int first = qBound(0, start, mItems.count()-1); + int last = qBound(0, end, mItems.count()-1); + int target = qBound(0, destination, mItems.count()-1); + + if (target < first) { + for (int i = 0; i <= last-first; i++) { + mItems.move(first+i, target+i); + } + } + else if (target > last) { + for (int i = 0; i <= last-first; i++) { + mItems.move(last-i, target); + } + } + // else do nothing +} + +int HgContainer::imageCount() const +{ + return mItems.count(); +} + +const HgImage *HgContainer::image(int index) const +{ + return mItems[index]->image(); +} + +int HgContainer::flags(int index) const +{ + if (index >= 0 && index < itemCount()) { + if (mSelectionModel && mSelectionModel->isSelected(mSelectionModel->model()->index(index, 0))) { + return 1; // TODO: Assign flag to mark indicator + } + } + return 0; +} + +const HgImage *HgContainer::indicator(int flags) const +{ + if (flags & 1) { + return mMarkImage; + } + + return 0; +} + +void HgContainer::updateBySpringPosition() +{ + update(); + + // spring works always in one dimension, that is, x coord. + qreal pos = mSpring.pos().x(); + + onScrollPositionChanged(pos); + + emit scrollPositionChanged(pos, mAnimateUsingScrollBar); +} + +void HgContainer::redraw() +{ + update(); +} + +void HgContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option) + Q_UNUSED(widget) + + if (mSpring.updatePositionIfNeeded()) + { + // spring works always in one dimension, that is, x coord. + qreal pos = mSpring.pos().x(); + onScrollPositionChanged(pos); + emit scrollPositionChanged(pos, mAnimateUsingScrollBar); + } + + QRectF vp = painter->viewport(); + QRectF rts = mapRectToScene(rect()); + QRectF r; + + // transform rectangle to vg space & + // rotate rendering according to orientation + if (mainWindow()->orientation() == Qt::Horizontal) { + r = QRectF(vp.width()-(rts.height()+rts.top()), rts.left(), rts.height(), rts.width()); + mRenderer->setCameraRotationZ(-90); + } + else { + r = QRectF(rts.left(), vp.height()-(rts.height()+rts.top()), rts.width(), rts.height()); + mRenderer->setCameraRotationZ(0); + } + + // interpolate spring velocity towards zero, this is done + // so that spring velocity for rendering doesn't drop directly to + // zero when dragging starts + qreal springVel = mSpring.velocity().x(); + if (mDragged) { + qreal t = qBound(mFramesDragged / KFramesToZeroVelocity, 0.0f, 1.0f); + springVel = mSpringVelAtDragStart * (1.0f - t); + mFramesDragged++; + } + + // setup rendering and draw the current view + mRenderer->setCameraDistance(getCameraDistance(springVel)); + mRenderer->setCameraRotationY(getCameraRotationY(springVel)); + mRenderer->setRect(r); + mRenderer->draw(mSpring.startPos(), mSpring.pos(), mSpring.endPos(), + springVel, painter); + +} + +void HgContainer::resizeEvent(QGraphicsSceneResizeEvent *event) +{ + FUNC_LOG; + + HbWidget::resizeEvent(event); +} + +// this needs to be implemented for gesture framework to work +void HgContainer::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event); +} + +void HgContainer::gestureEvent(QGestureEvent *event) +{ + FUNC_LOG; + + // Event may contain more than one gesture type + if (QGesture *gesture = event->gesture(Qt::TapAndHoldGesture)) { + QTapAndHoldGesture *tapAndHold = static_cast(gesture); + handleLongTap(tapAndHold->state(), + mapFromScene(event->mapToGraphicsScene(tapAndHold->position()))); + } + else if (QGesture *gesture = event->gesture(Qt::TapGesture)) { + // Tap and hold is not working yet in HW, tap gesture is delivered instead + QTapGesture *tap = static_cast(gesture); + handleTap(tap->state(), + mapFromScene(event->mapToGraphicsScene(tap->position()))); + } + else if (QGesture *pan = event->gesture(Qt::PanGesture)) { + handlePanning(static_cast(pan)); + } +} + +void HgContainer::init(Qt::Orientation scrollDirection) +{ + FUNC_LOG; + + mRenderer = createRenderer(); + if (mRenderer->coverflowModeEnabled()) + mRenderer->setOrientation(Qt::Horizontal, false); + else + mRenderer->setOrientation(scrollDirection, false); + + mQuadRenderer = mRenderer->getRenderer(); + + QImage markImage(":/images/mark.svg"); + if (markImage.isNull()) { + ERROR("Failed to load :/images/mark.svg"); + } + mMarkImage = mQuadRenderer->createNativeImage(); + HANDLE_ERROR_NULL(mMarkImage); + if (mMarkImage) { + mMarkImage->setImage(markImage); + } + + connect(&mSpring, SIGNAL(updated()), SLOT(updateBySpringPosition())); + connect(&mSpring, SIGNAL(ended()), SLOT(onScrollingEnded())); + connect(&mSpring, SIGNAL(ended()), SIGNAL(scrollingEnded())); + connect(&mSpring, SIGNAL(started()), SIGNAL(scrollingStarted())); + connect(mRenderer, SIGNAL(renderingNeeded()), SLOT(redraw())); + +} + +qreal HgContainer::worldWidth() const +{ + return (qreal)mRenderer->getWorldWidth(); +} + +void HgContainer::initSpringForScrollBar() +{ + FUNC_LOG; + + mSpring.setDamping(KSpringDampingScrollBar); + mSpring.setK(KSpringKScrollBar); +} + +void HgContainer::initSpringForScrolling() +{ + FUNC_LOG; + + mSpring.setDamping(KSpringDampingScrolling); + mSpring.setK(KSpringKScrolling); +} + +void HgContainer::boundSpring() +{ + FUNC_LOG; + + qreal x = mSpring.endPos().x(); + x = qBound(qreal(0), x, worldWidth()); + if (mRenderer->coverflowModeEnabled()) { + qreal i = floorf(x); + x = (x - i > 0.5f) ? ceilf(x) : i; + mSpring.animateToPos(QPointF(x, 0)); + } + + mSpring.animateToPos(QPointF(x, 0)); + +} + +void HgContainer::handlePanning(QPanGesture *gesture) +{ + mAnimateUsingScrollBar = false; + initSpringForScrolling(); + + qreal pos = mSpring.pos().x(); + qreal delta(0); + qreal itemSide(0); + + if (mRenderer->getOrientation() == mainWindow()->orientation()) { + delta = gesture->delta().y(); + } + else { + delta = gesture->delta().x(); + } + + if (mRenderer->getOrientation() == Qt::Vertical) + itemSide = mRenderer->getImageSize().height()+mRenderer->getSpacing().height(); + else + itemSide = mRenderer->getImageSize().width()+mRenderer->getSpacing().width(); + + if (gesture->state() == Qt::GestureStarted) { + mOffsetAtDragStart = gesture->offset(); + } + else if (gesture->state() == Qt::GestureUpdated) { + QPointF offset = gesture->offset(); + QPointF offsetDelta = offset - mOffsetAtDragStart; + if (!mDragged && (qAbs(offsetDelta.x()) > 8 || + qAbs(offsetDelta.y()) > 8)) { + mDragged = true; + mDrag.reset(delta, mSpring.pos().x()); + mDragged = true; + mSpringVelAtDragStart = mSpring.velocity().x(); + mFramesDragged = 0; + } + + if (mDragged) + { + emit scrollingStarted(); + + qreal newPosition = mDrag.update(delta, pos, itemSide); + if (qAbs(newPosition - mSpring.pos().x()) > 0.01f) + { + mSpring.gotoPos(QPointF(newPosition, 0)); + update(); + } + } + } + else if (mDragged && gesture->state() == Qt::GestureFinished) { + mDrag.update(delta, pos, itemSide); + mDragged = false; + qreal newPos(0); + if (mDrag.finish(pos, mRenderer->coverflowModeEnabled(), newPos)) { + mSpring.animateToPos(QPointF(qBound(qreal(0), newPos, worldWidth()), 0)); + HgWidgetItem* item = itemByIndex(newPos); + if (item && item->modelIndex() != mSelectionModel->currentIndex()) { + // mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current); + } + } + else { + boundSpring(); + } + } + else if (gesture->state() == Qt::GestureCanceled) { + boundSpring(); + } +} + + + +void HgContainer::handleTap(Qt::GestureState state, const QPointF &pos) +{ + FUNC_LOG; + + if (state == Qt::GestureStarted) { + mTapDuration.start(); + + startLongPressWatcher(pos); + } + else if (state == Qt::GestureCanceled) + { + stopLongPressWatcher(); + } + else if (state == Qt::GestureFinished) { + + stopLongPressWatcher(); + handleItemAction(pos, mTapDuration.elapsed() > KLongTapDuration ? LongTap : NormalTap); + } +} + +void HgContainer::handleLongTap(Qt::GestureState state, const QPointF &pos) +{ + FUNC_LOG; + + mAnimateUsingScrollBar = false; + initSpringForScrolling(); + + if (state == Qt::GestureFinished) { + handleItemAction(pos, LongTap); + } +} + +/*! + Handle tap, lang tap and double tap action. + Finds out the item in the tap position and sends out suitable signal, + Sets the item as the current item and in multiselection mode toggles the + item selection status. +*/ +void HgContainer::handleItemAction(const QPointF &pos, ItemActionType action) +{ + FUNC_LOG; + + // If there is content, mSelectionModel must always exist - either default or client-provided + if (!mSelectionModel) return; + + mHitItem = getItemAt(pos, mHitItemIndex); + if (mHitItem) + { + int index = mHitItemIndex; + + + HgWidgetItem* item = itemByIndex(index); + if (item && action != DoubleTap) { + mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current); + + if (action == LongTap) { + INFO("Long tap:" << item->modelIndex().row()); + + if (!mRenderer->coverflowModeEnabled()) + selectItem(); + + emit longPressed(item->modelIndex(), pos); + } + else if (mSelectionMode == HgWidget::MultiSelection) { + INFO("Select:" << item->modelIndex().row()); + mSelectionModel->select(item->modelIndex(), QItemSelectionModel::Toggle); + update(); // It would be enough to update the item + } + else if (mSelectionMode == HgWidget::SingleSelection) { + INFO("Select:" << item->modelIndex().row()); + mSelectionModel->select(item->modelIndex(), QItemSelectionModel::ClearAndSelect); + update(); // It would be enough to update the item + } + else if (mSelectionMode == HgWidget::ContiguousSelection) { + QModelIndex newSelected = item->modelIndex(); + QModelIndexList oldSelection = mSelectionModel->selectedIndexes(); + INFO("Select:" << newSelected.row()); + if (oldSelection.count() > 0 && !mSelectionModel->isSelected(newSelected)) { + if (newSelected.row() < oldSelection.front().row()) { + mSelectionModel->select(QItemSelection(newSelected, oldSelection.back()), + QItemSelectionModel::Select); + } + else { // newSelected.row() > oldSelection.back().row() + mSelectionModel->select(QItemSelection(oldSelection.front(), newSelected), + QItemSelectionModel::Select); + } + } + else { + mSelectionModel->select(newSelected, QItemSelectionModel::Select); + } + update(); // It would be enough to update the item + } + else { + INFO("Tap:" << item->modelIndex().row()); + + if (mRenderer->coverflowModeEnabled()) + { + if (qAbs(qreal(index) - mSpring.pos().x()) < 0.01f) + { + emit activated(item->modelIndex()); + } + else + { + mSpring.animateToPos(QPointF(index, 0)); + } + } + else + { + selectItem(); + emit activated(item->modelIndex()); + } + + } + } + } + else { + INFO("No quad at pos:" << pos); + + unselectItem(); + } +} + +bool HgContainer::getItemPoints(int index, QPolygonF& points) +{ + QPolygonF poly; + if (!mRenderer->getItemPoints(index, poly)) + return false; + + bool invertible; + QTransform t = qtToVgTransform().inverted(&invertible); + + points = t.map(poly); + return true; +} + +QList HgContainer::getVisibleItemIndices() const +{ + QList quads = mRenderer->getVisibleQuads(); + QList result; + for (int i = 0; i < quads.count(); i++) { + bool ok; + int index = quads.at(i)->userData().toInt(&ok); + result.append(itemByIndex(index)->modelIndex()); + } + qSort(result); + return result; +} + +void HgContainer::itemDataChanged(const int &firstIndex, const int &lastIndex) +{ + FUNC_LOG; + + // TODO FIX THIS FUNCTION!!!!!!!!!!!!!!!!!!!!!! + + int firstItemOnScreen = 0, lastItemOnScreen = 0; + firstItemOnScreen = mSpring.pos().x(); + firstItemOnScreen *= rowCount(); + + // This code doesnt take into count if there is some empty space at the + // beginning or at the end of the widget + + int itemsOnScreen = 0; + if (mRenderer->getOrientation() == Qt::Vertical) { + itemsOnScreen = this->rect().height()/mRenderer->getImageSize().height(); + itemsOnScreen += rowCount(); + } + else { + // Doesnt work here. Use some magic for now. + itemsOnScreen = this->rect().width()/mRenderer->getImageSize().width(); + itemsOnScreen += 4; + } + itemsOnScreen *= rowCount(); + lastItemOnScreen = firstItemOnScreen+itemsOnScreen; + + if ((firstIndex >= firstItemOnScreen && firstIndex <= lastItemOnScreen) || + (lastIndex >= firstItemOnScreen && lastIndex <= lastItemOnScreen)) { + update( this->rect() ); + } +} + +void HgContainer::selectItem() +{ + // TODO: replace this with own selection implementation + + if (mHitItemView) + { + delete mHitItemView; + mHitItemView = NULL; + } + + mHitItemView = new HbGridViewItem(this); + mHitItemView->setVisible(false); + + QModelIndex modelIndex = mItems[mHitItemIndex]->modelIndex(); + const QAbstractItemModel* model = modelIndex.model(); + mHitItemView->resize(mRenderer->getImageSize().width() + 10, + mRenderer->getImageSize().height() + 10); + + QVariant iconVariant = model->data(modelIndex, Qt::DecorationRole); + mHitItemPixmap = iconVariant.value(); + HbIcon icon(mHitItemPixmap); + + QGraphicsItem* item = mHitItemView->style()->createPrimitive(HbStyle::P_GridViewItem_icon, mHitItemView); + HbIconItem *iconItem = static_cast(item); + iconItem->setIcon(icon); + iconItem->setAlignment(Qt::AlignCenter); + iconItem->setAspectRatioMode(Qt::KeepAspectRatio); + + mHitItemView->setModelIndex(modelIndex); + mHitItemView->setPos(QPointF(-10,-10)); + mHitItemView->setPressed(true, false); + mHitItemView->updatePrimitives(); + +} + +void HgContainer::updateSelectedItem() +{ + if (!mHitItemView || mHitItemIndex == -1) + return; + + QPolygonF points; + if (!getItemPoints(mHitItemIndex, points)) + { + // the item was not rendered, we must hide + // our qt item + mHitItemView->setVisible(false); + } + + if (mHitItemPixmap.isNull()) + { + mHitItemView->setVisible(false); + return; + } + + QPolygonF img; + img.append(QPointF(0,mHitItemPixmap.height())); + img.append(QPointF(mHitItemPixmap.width(),mHitItemPixmap.height())); + img.append(QPointF(mHitItemPixmap.width(),0)); + img.append(QPointF(0,0)); + + QTransform t; + QTransform::quadToQuad(img, points, t); + + mHitItemView->setTransform(t); + mHitItemView->setVisible(true); +} + +void HgContainer::unselectItem() +{ + mHitItemIndex = -1; + if (mHitItemView) + { + mHitItemView->setPressed(false, false); + mHitItemView->setVisible(false); + } +} + +void HgContainer::updateLongPressVisualizer() +{ + int elapsed = mLongTapDuration.elapsed(); + + if (elapsed > 80) + { + int frame = 100.0f * qreal(elapsed - 80) / qreal(KLongTapDuration - 80); + mLongPressVisualizer->setFrame(frame); + } +} + +void HgContainer::updateByCurrentIndex(const QModelIndex ¤t) +{ + handleCurrentChanged(current); +} + +HgWidgetItem* HgContainer::getItemAt(const QPointF& pos, int& index) +{ + QPointF p = mapQtToVg(pos); + HgQuad* quad = mRenderer->getQuadAt(p); + if (quad) + { + bool ok; + index = quad->userData().toInt(&ok); + + HgWidgetItem* item = itemByIndex(index); + return item; + } + return NULL; +} + +void HgContainer::startLongPressWatcher(const QPointF& pos) +{ + if (!mLongPressVisualizer) + { + mLongPressVisualizer = new HgLongPressVisualizer(this); + mLongPressVisualizer->setZValue(zValue()+1); + } + + mLongPressVisualizer->start(pos); + + if (!mLongPressTimer) + { + mLongPressTimer = new QTimer(this); + QObject::connect(mLongPressTimer, SIGNAL(timeout()), this, SLOT(updateLongPressVisualizer())); + } + + mLongPressTimer->start(20); + + mLongTapDuration.start(); +} + +void HgContainer::stopLongPressWatcher() +{ + if (mLongPressTimer && mLongPressVisualizer) + { + mLongPressTimer->stop(); + mLongPressVisualizer->stop(); + } +} + +QTransform HgContainer::qtToVgTransform() const +{ + QTransform t; + if (mainWindow()->orientation() == Qt::Vertical) + { + t.translate(0, rect().height()); + t.scale(1, -1); + } + else // horizontal + { + t.translate(rect().height(), 0); + t.scale(-1, 1); + t.translate(0, rect().width()); + t.rotate(-90, Qt::ZAxis); + } + return t; +} + +QPointF HgContainer::mapQtToVg(const QPointF& p) const +{ + QTransform t = qtToVgTransform(); + return t.map(p); +} + +qreal HgContainer::getCameraDistance(qreal springVelocity) +{ + Q_UNUSED(springVelocity) + return 0; +} + +qreal HgContainer::getCameraRotationY(qreal springVelocity) +{ + Q_UNUSED(springVelocity) + return 0; +} + +void HgContainer::handleTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex) +{ + Q_UNUSED(pos) + Q_UNUSED(hitItem) + Q_UNUSED(hitItemIndex) +} + +void HgContainer::handleLongTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex) +{ + Q_UNUSED(pos) + Q_UNUSED(hitItem) + Q_UNUSED(hitItemIndex) +} + +void HgContainer::onScrollPositionChanged(qreal pos) +{ + Q_UNUSED(pos) +} + +void HgContainer::handleCurrentChanged(const QModelIndex ¤t) +{ + Q_UNUSED(current) + // By default do nothing +} + +void HgContainer::onScrollingEnded() +{ +/* int index; + HgWidgetItem* item = getItemAt(rect().center(), index); + if (item && item->modelIndex() != mSelectionModel->currentIndex()) { + mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current); + }*/ +} + diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/HgImageFader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/HgImageFader.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,80 @@ +/* +* Copyright (c) 2009 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: +* +*/ +/* + * HgImageFader.cpp + * + * Created on: Feb 10, 2010 + * Author: anpentti + */ + +#include "HgImageFader.h" +#include "hgimage.h" + +HgImageFader::HgImageFader() +{ + QObject::connect(&mTimer, SIGNAL(timeout()), this, SLOT(doFading())); +} + +HgImageFader::~HgImageFader() +{ + if (mTimer.isActive()) + mTimer.stop(); +} + +void HgImageFader::addImage(HgImage* image) +{ + mImages.push_back(image); +} + +void HgImageFader::removeImage(HgImage* image) +{ + mImages.removeOne(image); +} + +void HgImageFader::fadeImages() +{ + if (!mImages.empty() && !mTimer.isActive()) + { + mTimer.start(10); + } +} + +void HgImageFader::doFading() +{ + QLinkedList::iterator i = mImages.begin(); + while (i != mImages.end()) + { + HgImage* image = (*i); + image->setAlpha(image->alpha() + 0.1f); + if (image->alpha() >= 1.0f) + { + image->setAlpha(1.0f); + i = mImages.erase(i); + } + else + { + i++; + } + } + + //emit doUpdate(); + + if (mImages.empty()) + { + mTimer.stop(); + } +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/HgScrollBufferManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/HgScrollBufferManager.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,360 @@ +/* +* Copyright (c) 2009 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: +* +*/ + + +#include + +#include "HgScrollBufferManager.h" +#include "trace.h" + +// ----------------------------------------------------------------------------- +// HgScrollBufferManager::HgScrollBufferManager() +// ----------------------------------------------------------------------------- +// +HgScrollBufferManager::HgScrollBufferManager( + int bufferSize, + int bufferTreshold, + int initialPosition, + int totalCount ) +: mBufferSize( bufferSize ), + mBufferTreshold( bufferTreshold ), + mBufferPosition( initialPosition ), + mDiff(0), + mTotalCount( totalCount ), + mResetOrdered(false), + mRequestStart(0), + mRequestCount(0), + mReleaseStart(0), + mReleaseCount(0) + { + init(); + } + +// ----------------------------------------------------------------------------- +// HgScrollBufferManager::init() +// ----------------------------------------------------------------------------- +// +void HgScrollBufferManager::init() + { + mResetOrdered = ETrue; + mTimer.setSingleShot(true); + connect(&mTimer, SIGNAL(timeout()), this, SLOT(timeout())); + } + +// ----------------------------------------------------------------------------- +// HgScrollBufferManager::~HgScrollBufferManager() +// ----------------------------------------------------------------------------- +// +HgScrollBufferManager::~HgScrollBufferManager() + { + mTimer.stop(); + } + +// ----------------------------------------------------------------------------- +// HgScrollBufferManager::resetBuffer() +// ----------------------------------------------------------------------------- +// +void HgScrollBufferManager::resetBuffer( int aPosition, int totalCount ) + { + if( !mResetOrdered ) + { + // release Old buffer + mReleaseStart = mBufferPosition; + mReleaseCount = mBufferSize; + } + + // set position and count + mBufferPosition = aPosition - (mBufferSize / 2); + mTotalCount = totalCount; + mDiff = 0; + + if( mBufferPosition + mBufferSize > mTotalCount - 1 ) + { + mBufferPosition = mTotalCount - mBufferSize; + } + + if(mBufferPosition < 0 ) + { + mBufferPosition = 0; + } + + //request new Buffer + mRequestStart = mBufferPosition; + mRequestCount = mBufferSize; + mResetOrdered = ETrue; + asyncUpdate(); + } + +void HgScrollBufferManager::scrollPositionChanged( int newPosition ) + { + // If all the items fit in the buffer no need to move the buffer. + if( mTotalCount <= mBufferSize ) return; + + bool forceUpdate = EFalse; + newPosition -= mBufferSize / 2; // normalize index to Buffer start + + if(newPosition < 0) + { + newPosition = 0; + forceUpdate = ETrue; + } + else if( newPosition > mTotalCount - mBufferSize ) + { + newPosition = mTotalCount - mBufferSize; + forceUpdate = ETrue; + } + + mDiff = mBufferPosition - newPosition; + + // Too large change reset whole buffer + if( mDiff >= mBufferSize || -mDiff >= mBufferSize || mResetOrdered ) + { + resetBuffer(newPosition + (mBufferSize/2), mTotalCount ); + } + // Move Up + else if( mDiff >= mBufferTreshold ) + { + mRequestCount = mDiff; + mReleaseCount = mDiff; + asyncUpdate(); + } + // Move Down + else if( -mDiff >= mBufferTreshold ) + { + mRequestCount = -mDiff; + mReleaseCount = -mDiff; + asyncUpdate(); + } + // Top or bottom has been reached + else if( forceUpdate && mDiff ) + { + int diff = mDiff < 0 ? -mDiff : mDiff; + mRequestCount = diff; + mReleaseCount = diff; + asyncUpdate(); + } + } + +void HgScrollBufferManager::timeout() +{ + if(mResetOrdered) + { + mResetOrdered = EFalse; + } + else + { + if(mDiff < 0) + { + mReleaseStart = mBufferPosition; + mRequestStart = mBufferPosition + mBufferSize; + } + else if( mDiff > 0) + { + mReleaseStart = mBufferPosition + mBufferSize - mDiff; + mRequestStart = mBufferPosition - mDiff; + } + } + + // Release + int end = mReleaseStart + mReleaseCount < mTotalCount ? + mReleaseStart + mReleaseCount: mTotalCount; + end--; + if(end >= mReleaseStart ) + { + emit releaseItems( mReleaseStart, end ); + } + + mReleaseCount = 0; + + // Request + end = mRequestStart + mRequestCount < mTotalCount ? + mRequestStart + mRequestCount : mTotalCount; + + end--; + if(end >= mRequestStart ) + { + emit requestItems( mRequestStart, end ); + } + + mRequestCount = 0; + + // Move Buffer + mBufferPosition -= mDiff; + // Reset Diff + mDiff = 0; +} + +bool HgScrollBufferManager::positionInsideBuffer( int position ) +{ + return position >= mBufferPosition && position <= (mBufferPosition+mBufferSize); +} + +void HgScrollBufferManager::asyncUpdate() +{ + if( !mTimer.isActive()) + mTimer.start(0); +} + +void HgScrollBufferManager::currentBuffer(int& bufferStart, int& bufferEnd) +{ + bufferStart = mBufferPosition; + bufferEnd = mBufferPosition+mBufferSize > mTotalCount-1 ? + mTotalCount-1 : mBufferPosition+mBufferSize; +} + +void HgScrollBufferManager::removeItems(int start, int end, int totalCount) +{ + int oldTotalCount = mTotalCount; + mTotalCount = totalCount; + + if (isInsideBuffer(start, end)) { + if (mTotalCount > mBufferSize && mBufferPosition+mBufferSize == oldTotalCount) { + // We are at the end of items, move buffer + int oldBufferPos = mBufferPosition; + mBufferPosition = qMax(0, totalCount-mBufferSize); + + if (start < oldBufferPos) { // Removed items are partially inside buffer + emit requestItems(mBufferPosition, start-1); + } + else { + emit requestItems(mBufferPosition, oldBufferPos-1); + } + } + else { + int first = qBound(mBufferPosition, start, mBufferPosition+mBufferSize-1); + int last = qBound(mBufferPosition, end, mBufferPosition+mBufferSize-1); + + // Requested from the end + emit requestItems(mBufferPosition+mBufferSize-(last-first+1), + qMin(mBufferPosition+mBufferSize-1, mTotalCount)); + } + } +} + +void HgScrollBufferManager::addItems(int start, int end, int totalCount) +{ + int oldTotalCount = mTotalCount; + mTotalCount = totalCount; + + if (isInsideBuffer(start, end)) { + int first = start; + int last = end; + + if (mTotalCount > mBufferSize && mBufferPosition+mBufferSize == oldTotalCount) { + // We are at the end of items, keep it that way + int oldBufferPos = mBufferPosition; + mBufferPosition = qMin(mBufferPosition+(end-start+1), totalCount-mBufferSize); + + if (oldBufferPos < mBufferPosition) { + // Release from the beginning + emit releaseItems(oldBufferPos, mBufferPosition-1); + } + + // Added items may fall outside the buffer as the buffer is moved + if (isInsideBuffer(start, end)) { + first = qBound(mBufferPosition, start, mBufferPosition+mBufferSize-1); + last = qBound(mBufferPosition, end, mBufferPosition+mBufferSize-1); + emit requestItems(first, last); + } + } + else { + first = qBound(mBufferPosition, start, mBufferPosition+mBufferSize-1); + last = qBound(mBufferPosition, end, mBufferPosition+mBufferSize-1); + + if (mTotalCount > mBufferSize) { + // Release from the end + emit releaseItems(mBufferPosition+mBufferSize, + mBufferPosition+mBufferSize+(last-first+1)-1); + } + // If all the items fit in the buffer no need to release items + + emit requestItems(first, last); + } + } +} + +void HgScrollBufferManager::moveItems(int start, int end, int target, int totalCount) +{ + if (isInsideBuffer(start) && isInsideBuffer(end) && isInsideBuffer(target)) { + return; + } + + if (!isInsideBuffer(start, end) && !isInsideBuffer(target)) { + return; + } + + if (!isInsideBuffer(target)) { + if (isInsideBuffer(start) && isInsideBuffer(end)) { + if (mBufferPosition+mBufferSize == mTotalCount) { + // Fetch from beginning + emit requestItems(mBufferPosition, mBufferPosition+end-start); + } + else { + // Fetch from end + emit requestItems(mBufferPosition+mBufferSize-(end-start+1), + qMin(mBufferPosition+mBufferSize-1, mTotalCount)); + } + } + else if (isInsideBuffer(start) && end >= mBufferPosition+mBufferSize-1) { + emit requestItems(start, mBufferPosition+mBufferSize-1); + } + else if (start <= mBufferPosition && isInsideBuffer(end)) { + emit requestItems(mBufferPosition, end); + } + else { + emit requestItems(mBufferPosition, mBufferPosition+mBufferSize-1); + } + } + + if (isInsideBuffer(target)) { + // start-end may be partially inside buffer + if (!isInsideBuffer(start, end)) { + addItems(target, target+end-start, totalCount); + } + else if (isInsideBuffer(start)) { + addItems(target+(mBufferPosition+mBufferSize-start), target+end-start, totalCount); + } + else { // end is inside buffer + addItems(target, target+mBufferPosition-start-1, totalCount); + } + } +} + +bool HgScrollBufferManager::isInsideBuffer(int pos) +{ + return (pos >= mBufferPosition && pos < mBufferPosition+mBufferSize); +} + +bool HgScrollBufferManager::isInsideBuffer(int start, int end) +{ + INFO("Buffer:" << mBufferPosition << "-" << mBufferPosition+mBufferSize-1); + INFO("Change:" << start << "-" << end); + + if (isInsideBuffer(start)) { + return true; + } + if (isInsideBuffer(end)) { + return true; + } + if (start < mBufferPosition && end >= mBufferPosition+mBufferSize) { + return true; + } + + INFO("Buffer not affected"); + return false; +} + diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgcoverflowcontainer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgcoverflowcontainer.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,319 @@ +/* +* Copyright (c) 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: +* +*/ + +#include +#include +#include +#include "hgcoverflowcontainer.h" +#include "hgmediawallrenderer.h" +#include "hgwidgetitem.h" +#include "trace.h" + + +static const qreal KCameraMaxYAngle(20); +static const qreal KSpringVelocityToCameraYAngleFactor(2); +static const int KLabelMargin(4); + +HgCoverflowContainer::HgCoverflowContainer( + QGraphicsItem* parent) : HgContainer(parent), + mTitleLabel(0), + mDescriptionLabel(0), + mTitlePosition(HgMediawall::PositionAboveImage), + mDescriptionPosition(HgMediawall::PositionNone), + mCenterIconTop(0), + mPrevPos(-1) +{ + mTitleLabel = new HbLabel(this); + mTitleLabel->setZValue(zValue()+1); + mTitleLabel->setAlignment(Qt::AlignCenter); + mTitleLabel->setVisible(false); + + mDescriptionLabel = new HbLabel(this); + mDescriptionLabel->setZValue(zValue()+1); + mDescriptionLabel->setAlignment(Qt::AlignCenter); + mDescriptionLabel->setVisible(false); +} + +HgCoverflowContainer::~HgCoverflowContainer() +{ +} + +// events +void HgCoverflowContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + HgContainer::paint(painter, option, widget); +} + +void HgCoverflowContainer::resizeEvent(QGraphicsSceneResizeEvent *event) +{ + FUNC_LOG; + + HbWidget::resizeEvent(event); + + QSizeF s(size()); + qreal side = qMin(s.height()/1.8, s.width()/1.8); + INFO("Setting image size to:" << side << "," << side); + mRenderer->setImageSize(QSizeF(side, side)); + mCenterIconTop = (s.height()-side)/2; + + positionLabels(); +} + +// from HgContainer +HgMediaWallRenderer* HgCoverflowContainer::createRenderer() +{ + HgMediaWallRenderer* renderer = new HgMediaWallRenderer(this); + renderer->setImageSize(QSizeF(200, 200)); + renderer->enableCoverflowMode(true); + renderer->setRowCount(1, renderer->getImageSize(), false); + renderer->enableReflections(true); + renderer->setSpacing(QSizeF(1,1)); + renderer->setFrontCoverElevationFactor(0.5); + return renderer; +} + +qreal HgCoverflowContainer::getCameraDistance(qreal springVelocity) +{ + return qAbs(springVelocity * 0.01f); +} + +qreal HgCoverflowContainer::getCameraRotationY(qreal springVelocity) +{ + return qBound(-KCameraMaxYAngle, springVelocity * KSpringVelocityToCameraYAngleFactor, KCameraMaxYAngle); +} + +void HgCoverflowContainer::handleTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex) +{ + Q_UNUSED(pos) + + if (qAbs(qreal(hitItemIndex) - mSpring.pos().x()) < 0.01f) + { + emit activated(hitItem->modelIndex()); + } + else + { + mSpring.animateToPos(QPointF(hitItemIndex, 0)); + } +} + +void HgCoverflowContainer::handleLongTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex) +{ + Q_UNUSED(hitItemIndex) + + emit longPressed(hitItem->modelIndex(), pos); +} + +void HgCoverflowContainer::onScrollPositionChanged(qreal pos) +{ + HgContainer::onScrollPositionChanged(pos); + + if (mPrevPos != (int)pos) { + mPrevPos = (int)pos; + HgWidgetItem* item = itemByIndex((int)pos); + if (item && item->modelIndex() != mSelectionModel->currentIndex()) { + mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current); + } + } +} + +void HgCoverflowContainer::handleCurrentChanged(const QModelIndex ¤t) +{ + FUNC_LOG; + + if (current.isValid()) { + updateLabels(current.row()); + } +} + +void HgCoverflowContainer::itemDataChanged(const int &firstIndex, const int &lastIndex) +{ + FUNC_LOG; + HANDLE_ERROR_NULL(mSelectionModel); // If model has been set, also is selection model + + HgContainer::itemDataChanged(firstIndex, lastIndex); + + if (mSelectionModel->currentIndex().isValid()) { + int current = mSelectionModel->currentIndex().row(); + if (firstIndex <= current && current <= lastIndex) { + updateLabels(current); + } + } +} + +void HgCoverflowContainer::setTitlePosition(HgMediawall::LabelPosition position) +{ + FUNC_LOG; + + if (mTitlePosition != position) { + mTitlePosition = position; + positionLabels(); + } +} + +HgMediawall::LabelPosition HgCoverflowContainer::titlePosition() const +{ + FUNC_LOG; + + return mTitlePosition; +} + +void HgCoverflowContainer::setDescriptionPosition(HgMediawall::LabelPosition position) +{ + FUNC_LOG; + + if (mDescriptionPosition != position) { + mDescriptionPosition = position; + positionLabels(); + } +} + +HgMediawall::LabelPosition HgCoverflowContainer::descriptionPosition() const +{ + FUNC_LOG; + + return mDescriptionPosition; +} + +void HgCoverflowContainer::setTitleFontSpec(const HbFontSpec &fontSpec) +{ + FUNC_LOG; + + if (!mTitleLabel) return; + if (mTitleLabel->fontSpec() != fontSpec) { + mTitleLabel->setFontSpec(fontSpec); + positionLabels(); + } +} + +HbFontSpec HgCoverflowContainer::titleFontSpec() const +{ + FUNC_LOG; + + if (!mTitleLabel) return HbFontSpec(); + return mTitleLabel->fontSpec(); +} + +void HgCoverflowContainer::setDescriptionFontSpec(const HbFontSpec &fontSpec) +{ + FUNC_LOG; + + if (!mDescriptionLabel) return; + if (mDescriptionLabel->fontSpec() != fontSpec) { + mDescriptionLabel->setFontSpec(fontSpec); + positionLabels(); + } +} + +HbFontSpec HgCoverflowContainer::descriptionFontSpec() const +{ + FUNC_LOG; + + if (!mDescriptionLabel) return HbFontSpec(); + return mDescriptionLabel->fontSpec(); +} + +void HgCoverflowContainer::positionLabels() +{ + FUNC_LOG; + HANDLE_ERROR_NULL(mTitleLabel); + HANDLE_ERROR_NULL(mDescriptionLabel); + HANDLE_ERROR_NULL(mSelectionModel); + + int height = size().height(); + int width = size().width(); + int titleHeight = QFontMetrics(mTitleLabel->effectiveFontSpec().font()).height(); + int descriptionHeight = QFontMetrics(mDescriptionLabel->effectiveFontSpec().font()).height(); + + if (mTitlePosition == HgMediawall::PositionAboveImage && + mDescriptionPosition == HgMediawall::PositionAboveImage) { + mTitleLabel->setGeometry(QRectF( + 0, + qMax(KLabelMargin, mCenterIconTop-2*KLabelMargin-titleHeight-descriptionHeight), + width, titleHeight)); + mDescriptionLabel->setGeometry(QRectF( + 0, + mTitleLabel->geometry().bottom()+KLabelMargin, + width, descriptionHeight)); + } + else if (mTitlePosition == HgMediawall::PositionBelowImage && + mDescriptionPosition == HgMediawall::PositionBelowImage) { + mDescriptionLabel->setGeometry(QRectF( + 0, + height-descriptionHeight-KLabelMargin, + width, descriptionHeight)); + mTitleLabel->setGeometry(QRectF( + 0, + mDescriptionLabel->geometry().top()-titleHeight-KLabelMargin, + width, titleHeight)); + } + else { + if (mTitlePosition == HgMediawall::PositionAboveImage) { + mTitleLabel->setGeometry(QRectF( + 0, + qMax(KLabelMargin, mCenterIconTop-KLabelMargin-titleHeight), + width, titleHeight)); + } + else if (mTitlePosition == HgMediawall::PositionBelowImage) { + mTitleLabel->setGeometry(QRectF( + 0, + height-titleHeight-KLabelMargin, + width, titleHeight)); + } + + if (mDescriptionPosition == HgMediawall::PositionAboveImage) { + mDescriptionLabel->setGeometry(QRectF( + 0, + qMax(KLabelMargin, mCenterIconTop-KLabelMargin-descriptionHeight), + width, descriptionHeight)); + } + else if (mDescriptionPosition == HgMediawall::PositionBelowImage) { + mDescriptionLabel->setGeometry(QRectF( + 0, + height-descriptionHeight-KLabelMargin, + width, descriptionHeight)); + } + } + + mTitleLabel->setVisible(mTitlePosition != HgMediawall::PositionNone); + mDescriptionLabel->setVisible(mDescriptionPosition != HgMediawall::PositionNone); + + INFO("Title geometry:" << mTitleLabel->geometry() << "visible:" << mTitleLabel->isVisible()); + INFO("Description geometry:" << mDescriptionLabel->geometry() << "visible:" << mDescriptionLabel->isVisible()); + + if (mSelectionModel->currentIndex().isValid()) { + updateLabels(mSelectionModel->currentIndex().row()); + } +} + +void HgCoverflowContainer::updateLabels(int itemIndex) +{ + FUNC_LOG; + HANDLE_ERROR_NULL(mTitleLabel); + HANDLE_ERROR_NULL(mDescriptionLabel); + + if (itemIndex >= 0 && itemIndex < mItems.count()) { + mTitleLabel->setPlainText(mItems.at(itemIndex)->title()); + mDescriptionLabel->setPlainText(mItems.at(itemIndex)->description()); + } +} + +void HgCoverflowContainer::scrollToPosition(const QPointF& pos, bool animate) +{ + QPointF p = pos; + p.setX((int)pos.x()); + HgContainer::scrollToPosition(p,animate); +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgdrag.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgdrag.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,94 @@ +/* +* Copyright (c) 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: Container for pan (drag) gesture -related data and logic. +* +*/ + +#include "hgdrag.h" +#include "trace.h" + +HgDrag::HgDrag() +{ +} + +void HgDrag::reset(const qreal delta, const qreal viewPos) +{ + mViewPosAtStart = viewPos; + mDuration.start(); + mLength = 0; + mCumulatedDelta = 0; + mDirection = delta; + mDirectionChange = 0; + INFO("Drag reset at view pos:" << mViewPosAtStart); +} + +qreal HgDrag::update(const qreal delta, const qreal viewPos, const qreal itemWidth) +{ +// INFO("delta:" << delta << ", direction:" << mDirection); + if ((delta > 0 && mDirection < 0) || (delta < 0 && mDirection > 0)) + { + if (mDirectionChange > 2) + { + mDirectionChange = 0; + reset(delta, viewPos); + } + else + { + mDirectionChange++; + } + } + else + { + mDirection = delta; + mDirectionChange = 0; + } + + mCumulatedDelta = (mCumulatedDelta+delta)/2; + mLength += delta/itemWidth; + qreal pos = mViewPosAtStart-mLength; +// INFO("Drag len:" << mLength << ", new pos:" << pos); + return pos; +} + +bool HgDrag::finish(const qreal viewPos, bool stopToFullItem, qreal &newPos) +{ + int dt = mDuration.elapsed(); + if (dt > 10) + { + qreal t = (qreal)dt/1000; + INFO("Drag len:" << mLength << ", duration:" << t << ", cumulated:" << mCumulatedDelta); + if (qAbs(mCumulatedDelta) > 4) + { + newPos = viewPos-mLength/t * 0.5f; + } + else + { + newPos = mViewPosAtStart-mLength; + } + if (stopToFullItem) + { + qreal i = floorf(newPos); + newPos = (newPos - i > 0.5f) ? ceilf(newPos) : i; + } + + return true; + } + return false; +} + +qreal HgDrag::viewPosAtStart() const +{ + return mViewPosAtStart; +} + diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hggrid.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hggrid.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,35 @@ +/* +* Copyright (c) 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: +* +*/ + +#include +#include "hggrid_p.h" +#include "hggridcontainer.h" + +HgGrid::HgGrid( Qt::Orientation scrollDirection, QGraphicsItem *parent ): + HgWidget(new HgGridPrivate, parent) +{ + Q_D(HgGrid); + d->q_ptr = this; + + d->init(scrollDirection); +} + +HgGrid::~HgGrid() +{ +} + +// EOF diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hggrid_p.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hggrid_p.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,45 @@ +/* +* Copyright (c) 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: +* +*/ + +#include "hggrid_p.h" +#include "hggridcontainer.h" + +static const int BUFFERSIZE(120); + +HgGridPrivate::HgGridPrivate() +{ + +} + +HgGridPrivate::~HgGridPrivate() +{ + +} + +void HgGridPrivate::init(Qt::Orientation scrollDirection) +{ + Q_Q(HgGrid); + HgGridContainer *container = new HgGridContainer(q); + container->init(scrollDirection); + + // Use a little larger buffer for the grid than the default one. + mBufferSize = BUFFERSIZE; + + HgWidgetPrivate::init(container); +} + +// EOF diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hggridcontainer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hggridcontainer.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,104 @@ +/* +* Copyright (c) 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: +* +*/ + +#include +#include +#include +#include +#include +#include +#include "hggridcontainer.h" +#include "hgmediawallrenderer.h" +#include "hgquad.h" +#include "hgvgquadrenderer.h" +#include "hgvgimage.h" +#include "hgwidgetitem.h" +#include "trace.h" + +#include +#include +#include +#include +#include "hglongpressvisualizer.h" + + +static const qreal KCameraMaxYAngle(20); +static const qreal KSpringVelocityToCameraYAngleFactor(2); + +HgGridContainer::HgGridContainer(QGraphicsItem *parent) : HgContainer(parent) +{ + +} + +HgGridContainer::~HgGridContainer() +{ + +} + +void HgGridContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + HgContainer::paint(painter, option, widget); + + updateSelectedItem(); +} + +HgMediaWallRenderer* HgGridContainer::createRenderer() +{ + + HgMediaWallRenderer* renderer = new HgMediaWallRenderer(this); + renderer->enableCoverflowMode(false); + renderer->setImageSize(QSizeF(105, 80)); + renderer->setRowCount(3, renderer->getImageSize(), false); + renderer->enableReflections(false); + renderer->setSpacing(QSizeF(1,1)); + renderer->setFrontCoverElevationFactor(0.5); + + return renderer; +} + +qreal HgGridContainer::getCameraDistance(qreal springVelocity) +{ + if (mRenderer->getOrientation() == Qt::Vertical) + return 0; + + return qAbs(springVelocity * 0.01f); +} + +qreal HgGridContainer::getCameraRotationY(qreal springVelocity) +{ + if (mRenderer->getOrientation() == Qt::Vertical) + return 0; + + return qBound(-KCameraMaxYAngle, springVelocity * KSpringVelocityToCameraYAngleFactor, KCameraMaxYAngle); +} + +void HgGridContainer::handleTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex) +{ + Q_UNUSED(pos) + Q_UNUSED(hitItemIndex) + + selectItem(); + emit activated(hitItem->modelIndex()); +} + +void HgGridContainer::handleLongTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex) +{ + Q_UNUSED(hitItemIndex) + + selectItem(); + emit longPressed(hitItem->modelIndex(), pos); +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgindexfeedback.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgindexfeedback.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,329 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include "hgindexfeedback.h" +#include "hgindexfeedback_p.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +/* rather than magic numbers, let's define some constants. */ +namespace { +/* + string name from the index feedback .css for the single character height parameter. +*/ +static const QString ONE_CHAR_HEIGHT = QLatin1String("one-char-height"); + +/* + string name from the index feedback .css for the three character height parameter. +*/ +static const QString THREE_CHAR_HEIGHT = QLatin1String("three-char-height"); + +/* + string name from the index feedback .css for the three character width parameter. +*/ +static const QString THREE_CHAR_WIDTH = QLatin1String("three-char-width"); + +/* + string name from the index feedback .css for the string mode offest parameter. +*/ +static const QString STRING_OFFSET = QLatin1String("string-offset"); +} + +/*! + Constructs a new HgIndexFeedback with a parent. +*/ +HgIndexFeedback::HgIndexFeedback(QGraphicsItem *parent) + : HbWidget( *new HgIndexFeedbackPrivate, parent, 0) + +{ + Q_D( HgIndexFeedback ); + d->q_ptr = this; + + HbStyleLoader::registerFilePath(":/hgindexfeedback.css"); + + d->init(); +} + +/*! + Destructs the index feedback. +*/ +HgIndexFeedback::~HgIndexFeedback() +{ + HbStyleLoader::unregisterFilePath(":/hgindexfeedback.css"); +} + +/*! + \brief sets the index feedback policy. + + \param policy - The HgIndexFeedback::IndexFeedbackPolicy to use. + + \sa HgIndexFeedback::IndexFeedbackPolicy +*/ +void HgIndexFeedback::setIndexFeedbackPolicy(HgWidget::IndexFeedbackPolicy policy) +{ + Q_D( HgIndexFeedback ); + + if (policy != d->mIndexFeedbackPolicy) { + d->_q_hideIndexFeedbackNow(); + d->mIndexFeedbackPolicy = policy; + d->calculatePopupRects(); + d->updatePrimitives(); + } +} + +/*! + \brief Returns the index feedback policy. + + \return The HgIndexFeedback::IndexFeedbackPolicy that's currently in use. +*/ +HgWidget::IndexFeedbackPolicy HgIndexFeedback::indexFeedbackPolicy() const +{ + Q_D( const HgIndexFeedback ); + + return d->mIndexFeedbackPolicy; +} + +/*! + \brief sets the item view for the index feedback. + + Disconnects from the existing item view, then connects to the specified one. + + If set to NULL the index feedback is simply disconnected. + + \param itemView The HbAbstractItemView* to provide index feedback for. +*/ +void HgIndexFeedback::setWidget(HgWidget *widget) +{ + Q_D( HgIndexFeedback ); + + if (widget == d->mWidget) { + return; + } + + d->disconnectItemView(); + + d->mWidget = widget; + + if (!d->mWidget) { + return; + } + + d->connectModelToIndexFeedback(d->mWidget->selectionModel()); + + d->connectScrollBarToIndexFeedback(d->mWidget->scrollBar()); + + connect(d->mWidget, SIGNAL(destroyed(QObject*)), + this, SLOT(_q_itemViewDestroyed())); + + if (d->mWidget->scene()) { + d->mWidget->scene()->addItem(this); + d->mWidget->installSceneEventFilter(this); + } + + d->calculatePopupRects(); + updatePrimitives(); +} + +/*! + Returns the HbAbstractItemView which the index feedback currently monitors. + + \return HbAbstractItemView*. +*/ +HgWidget* HgIndexFeedback::widget() const +{ + Q_D( const HgIndexFeedback ); + + return d->mWidget; +} + +/*! + Returns the primitives used in HgIndexFeedback. + + \param primitive The primitive type requested. + + \return A pointer for the primitive requested. +*/ +QGraphicsItem* HgIndexFeedback::primitive(HbStyle::Primitive primitive) const +{ + Q_D( const HgIndexFeedback ); + + QGraphicsItem* retVal = HbWidget::primitive(primitive); + + switch (primitive) { + case HbStyle::P_IndexFeedback_popup_text: + retVal = d->mTextItem; + break; + + case HbStyle::P_IndexFeedback_popup_background: + retVal = d->mPopupItem; + break; + + default: + qt_noop(); + break; + } + + return retVal; +} + + +/* + A scene event filter. It's purpose is to call calculatePopupRects on + a resize event for the item view. +*/ +bool HgIndexFeedback::sceneEventFilter(QGraphicsItem *watched, QEvent *ev) +{ + Q_D( HgIndexFeedback ); + + if (ev->type() == QEvent::GraphicsSceneResize) { + d->calculatePopupRects(); + } + + return QGraphicsItem::sceneEventFilter(watched, ev); +} + +/* + Rather than adding signals to HbScrollBar specifically to implement + index feedback, an event filter is used. + + Specifically, if a scrollbar which is interactive is pressed or released + this function will call the appropriate function in HgIndexFeedbackPrivate. +*/ +bool HgIndexFeedback::eventFilter(QObject *obj, QEvent *ev) +{ + Q_D( HgIndexFeedback ); + HbScrollBar* scrollBar = qobject_cast(obj); + + if (d->mIndexFeedbackPolicy != HgWidget::IndexFeedbackNone + && scrollBar) { + switch (ev->type()) { + case QEvent::GraphicsSceneMousePress: + case QEvent::MouseButtonPress: + if (scrollBar->isInteractive()) { + d->scrollBarPressed(); + } + break; + + case QEvent::GraphicsSceneMouseRelease: + case QEvent::MouseButtonRelease: + if (scrollBar->isInteractive()) { + d->scrollBarReleased(); + } + break; + + case QEvent::GraphicsSceneResize: + case QEvent::Resize: + d->_q_hideIndexFeedbackNow(); + d->calculatePopupRects(); + d->updatePrimitives(); + break; + + default: + // do nothing, ignore other events. + break; + } + } + + return QObject::eventFilter(obj, ev); +} + +/* + For use with HbStyle. + + Provide the correct data to use in the 'model.' +*/ +void HgIndexFeedback::initStyleOption(HbStyleOptionIndexFeedback *option) const +{ + Q_D( const HgIndexFeedback ); + + HbWidget::initStyleOption(option); + + if (!d->mWidget) { + return; + } + + HbFontSpec fontSpec; + qreal margin = 0; + + style()->parameter(QLatin1String("hb-param-margin-gene-popup"), margin); + + switch (d->mIndexFeedbackPolicy) { + case HgWidget::IndexFeedbackSingleCharacter: + { + fontSpec = HbFontSpec(HbFontSpec::Primary); + fontSpec.setTextPaneHeight(d->textHeight()); + } + break; + + case HgWidget::IndexFeedbackThreeCharacter: + { + fontSpec = HbFontSpec(HbFontSpec::Primary); + fontSpec.setTextPaneHeight(d->textHeight()); + } + break; + + case HgWidget::IndexFeedbackString: + { + fontSpec = HbFontSpec(HbFontSpec::Primary); + qreal textPaneHeight = 0; + style()->parameter(QLatin1String("hb-param-text-height-primary"), textPaneHeight); + fontSpec.setTextPaneHeight( textPaneHeight ); + } + break; + + case HgWidget::IndexFeedbackNone: + // leave the HbStyleOption uninitialized + return; + } + + option->text = d->mPopupContent; + option->fontSpec = fontSpec; + option->textRect = d->mPopupTextRect; + option->popupRect = d->mPopupBackgroundRect; +} + +void HgIndexFeedback::polish(HbStyleParameters& params) +{ + Q_D( HgIndexFeedback ); + + params.addParameter( ONE_CHAR_HEIGHT ); + params.addParameter( THREE_CHAR_HEIGHT ); + params.addParameter( THREE_CHAR_WIDTH ); + params.addParameter( STRING_OFFSET ); + + HbWidget::polish( params ); + + d->mOneCharHeight = params.value( ONE_CHAR_HEIGHT ).toDouble(); + d->mThreeCharHeight = params.value( THREE_CHAR_HEIGHT ).toDouble(); + d->mThreeCharWidth = params.value( THREE_CHAR_WIDTH ).toDouble(); + d->mStringOffset = params.value( STRING_OFFSET ).toDouble(); + + d->calculatePopupRects(); +} + +#include "moc_hgindexfeedback.cpp" diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgindexfeedback_p.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgindexfeedback_p.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,566 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include "hgindexfeedback.h" +#include "hgindexfeedback_p.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// rather than having magic numbers +// defaults and constants are defined here. +namespace { +/* + Press timeout is the duration after the scrollbar is + pressed to when the index feedback will be dismissed. + + In the case that the press timeout has not yet passed + and the timer should be fired with the release timeout, + the timer with the press timeout will continue running. +*/ +static const int DEFAULT_INDEX_FEEDBACK_PRESS_TIMEOUT = 1000; + +/* + Dwell timeout is the duration after which if there is not a change + in the scrollbar's value the index feedback will be dismissed. +*/ +static const int DEFAULT_INDEX_FEEDBACK_DWELL_TIMEOUT = 2000; + +/* + Release timeout is the duration after which the user has lifted + their finger from the scrollbar to when the index feedback will be dismissed. +*/ +static const int DEFAULT_INDEX_FEEDBACK_RELEASE_TIMEOUT = 250; + +/* + The default value for the index feedback policy. +*/ +static const HgWidget::IndexFeedbackPolicy DEFAULT_INDEX_FEEDBACK_POLICY = HgWidget::IndexFeedbackNone; + +/* + The value of the index feedback's disappear animation +*/ +static const int INDEX_FEEDBACK_DISAPPEAR_DURATION = 300; +} + +/* + constructor +*/ +HgIndexFeedbackPrivate::HgIndexFeedbackPrivate() : + mIndexFeedbackPressTimeout(DEFAULT_INDEX_FEEDBACK_PRESS_TIMEOUT), + mIndexFeedbackDwellTimeout(DEFAULT_INDEX_FEEDBACK_DWELL_TIMEOUT), + mIndexFeedbackReleaseTimeout(DEFAULT_INDEX_FEEDBACK_RELEASE_TIMEOUT), + mIndexFeedbackPolicy(DEFAULT_INDEX_FEEDBACK_POLICY), + mScrollBarValue(-1.0), + mIndexFeedbackTimer(0), + mDisappearTimer(0), + mTextItem(0), + mPopupItem(0), + mOneCharHeight(1.0), + mThreeCharHeight(1.0), + mThreeCharWidth(1.0), + mStringOffset(0.0), + mWidget(0) +{ + +} + +/* + Destructor +*/ +HgIndexFeedbackPrivate::~HgIndexFeedbackPrivate() +{ + +} + +/* + 2ndary construction, called from public's constructor. +*/ +void HgIndexFeedbackPrivate::init() +{ + Q_Q( HgIndexFeedback ); + + //mItemView = 0; // double check that this is safe. + + HbEffect::add(HB_INDEXFEEDBACK_TYPE, "indexfeedback_appear", EFFECT_IFAPPEAR); + if (!HbEffect::add(HB_INDEXFEEDBACK_TYPE, "indexfeedback_disappear", EFFECT_IFDISAPPEAR)) { + mDisappearTimer = new QTimer(q); + mDisappearTimer->setSingleShot(true); + mDisappearTimer->setInterval(INDEX_FEEDBACK_DISAPPEAR_DURATION); + q->connect(mDisappearTimer, SIGNAL(timeout()), + q, SLOT(_q_hideIndexFeedbackNow())); + } + + mIndexFeedbackTimer = new QTimer(q); + mIndexFeedbackTimer->setSingleShot(true); + q->connect(mIndexFeedbackTimer, SIGNAL(timeout()), + q, SLOT(_q_hideIndexFeedback())); + + createPrimitives(); +} + +/* + Update the data for, and show the index feedback (if it's not already shown) +*/ +void HgIndexFeedbackPrivate::showIndexFeedback() +{ + if (!mWidget + || mIndexFeedbackPolicy == HgWidget::IndexFeedbackNone) { + return; + } + + QModelIndex targetIndex = mWidget->currentIndex(); + + if (targetIndex.isValid()) { + QVariant data = targetIndex.data(Hb::IndexFeedbackRole); + if (data.canConvert()) { + + QString testString = displayText(data); + if (testString != mPopupContent) { + mPopupContent = testString; + updatePrimitives(); + } + + if (mTextItem->opacity() == 0.0) { + HbEffect::start(mPopupItemList, HB_INDEXFEEDBACK_TYPE, EFFECT_IFAPPEAR); + } + if (mTextItem) { + mTextItem->show(); + } + + if (mPopupItem) { + mPopupItem->show(); + } + + if (mDisappearTimer) { + mDisappearTimer->stop(); + } + } else { + _q_hideIndexFeedback(); + } + } +} + +void HgIndexFeedbackPrivate::updateIndex() +{ + QModelIndex targetIndex = mWidget->currentIndex(); + + if (targetIndex.isValid()) { + QVariant data = targetIndex.data(Hb::IndexFeedbackRole); + if (data.canConvert()) { + QString testString = displayText(data); + if (testString != mPopupContent) { + mPopupContent = testString; + updatePrimitives(); + } + } + } +} + + +/* + Returns the qstring which will be the text in the index feedback. +*/ +QString HgIndexFeedbackPrivate::displayText(const QVariant &data) const +{ + QString retVal = QString(); + + switch (mIndexFeedbackPolicy) { + case HgWidget::IndexFeedbackSingleCharacter: + retVal = data.toString().left(1); + break; + + case HgWidget::IndexFeedbackThreeCharacter: + retVal = data.toString().left(3); + break; + + case HgWidget::IndexFeedbackString: + retVal = data.toString(); + break; + + default: + qt_noop(); + break; + } + + return retVal; +} + +/* + Handle the case of the scrollbar being pressed. + + This is show the index feedback and start the dismissal timer with the + press timeout. +*/ +void HgIndexFeedbackPrivate::scrollBarPressed() +{ + showIndexFeedback(); + + // need to record the scrollbar values + + // TODO::The values are storred here is a work around for a bug in hbscrollbar. + // the bug is that the value changed signal is emitted when the thumb + // is pressed, and again when it is released, regaurdless of if there was a value change. + // once that bug is fixed, this should be removed. + mScrollBarValue = mWidget->scrollBar()->value(); + mScrollBarPressed = true; +} + +/* + Handle the case of the scrollbar being released. + + This is to start the dismissal timer with the release timeout. + ...but not if the timer is still running with the press timeout... +*/ +void HgIndexFeedbackPrivate::scrollBarReleased() +{ + // record the scrollbar values in case position changed is emitted after us w/o a real change + + // TODO::The values are storred here is a work around for a bug in hbscrollbar. + // the bug is that the value changed signal is emitted when the thumb + // is pressed, and again when it is released, regaurdless of if there was a value change. + // once that bug is fixed, this should be removed. + mScrollBarValue = mWidget->scrollBar()->value(); + + // start this timer. + if (!(mIndexFeedbackTimer->isActive() + && mIndexFeedbackTimer->interval() == mIndexFeedbackPressTimeout)) { + mIndexFeedbackTimer->setInterval(mIndexFeedbackReleaseTimeout); + mIndexFeedbackTimer->start(); + } + + mScrollBarPressed = false; + +} + +/* + Handle the case of the scrollbar being moved. + + This is to stop any existing timers (only if the scrollbar actually moved), + and start a timer with the dwell timeout. + + NOTE:: this should be much simpler once the valueChanged signal from hbscrollbar + is emitted at the correct times. +*/ +void HgIndexFeedbackPrivate::_q_scrollPositionChanged(qreal value, Qt::Orientation orientation ) +{ + // using 3 timers. If the press timer is active, stop it, assuming the value actually changed. + + // TODO::The value check here is a work around for a bug in hbscrollbar. + // the bug is that the value changed signal is emitted when the thumb + // is pressed, and again when it is released, regaurdless of if there was a value change. + // once that bug is fixed, This should be just setting the dwell interval, + // starting the timer, and showing the index feedback. + if (value != mScrollBarValue && orientation == mWidget->scrollDirection()) { + showIndexFeedback(); + } +} + +/* + The private slot for hiding the index feedback. + + If effects are active, use the disappear effect to hide the index feedback's + primitives. Otherwise simply hide them. +*/ +void HgIndexFeedbackPrivate::_q_hideIndexFeedback() +{ + if (qFuzzyCompare(mTextItem->opacity(), (qreal) 1.0)) { + HbEffect::start(mPopupItemList, HB_INDEXFEEDBACK_TYPE, EFFECT_IFDISAPPEAR); + } + + if (mDisappearTimer) { + mDisappearTimer->start(); + } +} + +/* + A private slot for actually calling hide on the index feedback. + + This should happen after the index feedback's hide animation is completed + regardless of if it went successfully. +*/ +void HgIndexFeedbackPrivate::_q_hideIndexFeedbackNow() +{ + if (mTextItem) { + mTextItem->hide(); + } + + if (mPopupItem) { + mPopupItem->hide(); + } +} + +/* + Do the appropriate thing if the item view we're pointing at is destroyed +*/ +void HgIndexFeedbackPrivate::_q_itemViewDestroyed() +{ + mWidget = 0; +} + +/* + Update the primitives for the index feedback. +*/ +void HgIndexFeedbackPrivate::updatePrimitives() +{ + Q_Q( HgIndexFeedback ); + + HbStyleOptionIndexFeedback option; + q->initStyleOption(&option); + if (mTextItem) { + q->style()->updatePrimitive(mTextItem, HbStyle::P_IndexFeedback_popup_text, &option); + } + if (mPopupItem) { + q->style()->updatePrimitive(mPopupItem, HbStyle::P_IndexFeedback_popup_background, &option); + } +} + +/* + Create the primitives for the index feedback. +*/ +void HgIndexFeedbackPrivate::createPrimitives() +{ + Q_Q( HgIndexFeedback ); + + mPopupItemList.clear(); + + if (!mTextItem) { + mTextItem = q->style()->createPrimitive(HbStyle::P_IndexFeedback_popup_text, q); + mTextItem->hide(); + mPopupItemList.append(mTextItem); + } + + if (!mPopupItem) { + mPopupItem = q->style()->createPrimitive(HbStyle::P_IndexFeedback_popup_background, q); + mPopupItem->hide(); + mPopupItemList.append(mPopupItem); + } +} + +/* + disconnects the current item view from HgIndexFeedback's slots & event filters. +*/ +void HgIndexFeedbackPrivate::disconnectItemView() +{ + Q_Q( HgIndexFeedback ); + + if (mWidget) { + // disconnect from the existing itemView's scrollbars + mWidget->disconnect(q); + // uninstall the event filters; + mWidget->scrollBar()->removeEventFilter(q); + + mWidget->removeSceneEventFilter(q); + if (mWidget->scene()) { + mWidget->scene()->removeItem(q); + } + } + + mWidget = 0; +} + +/* + Hooks up the private slots & event filter to a scrollbar. +*/ +void HgIndexFeedbackPrivate::connectScrollBarToIndexFeedback(HbScrollBar* scrollBar) +{ + Q_Q( HgIndexFeedback ); + + if (scrollBar) { + //q->connect(scrollBar, SIGNAL(valueChanged(qreal, Qt::Orientation)), + // q, SLOT(_q_scrollPositionChanged(qreal, Qt::Orientation))); + scrollBar->installEventFilter(q); + } +} + +/* + Calculates the rects for the popup text and background. + + Does nothing if the rect is the same as the last time it was called. +*/ +void HgIndexFeedbackPrivate::calculatePopupRects() +{ + Q_Q( HgIndexFeedback ); + + if (!mWidget) { + return; + } + + QRectF contentRect = mWidget->rect(); + + HbScrollBar *scrollBar = mWidget->scrollBar(); + if (scrollBar->isInteractive() && mWidget->scrollDirection() == Qt::Vertical) { + contentRect.setWidth( contentRect.width() - scrollBar->rect().width() ); + if (HbApplication::layoutDirection() == Qt::RightToLeft) { + contentRect.setLeft( contentRect.left() + scrollBar->rect().width() ); + } + } + else if (scrollBar->isInteractive()) { + contentRect.setHeight( contentRect.height() - scrollBar->rect().height() ); + } + + if (contentRect == mItemViewContentsRect) { + return; + } + + qreal margin = 0; + q->style()->parameter(QLatin1String("hb-param-margin-gene-popup"), margin); + + QSizeF backgroundSize; + QSizeF textSize; + + switch (mIndexFeedbackPolicy) { + case HgWidget::IndexFeedbackSingleCharacter: + case HgWidget::IndexFeedbackThreeCharacter: + { + textSize.setHeight( textHeight() ); + textSize.setWidth ( textWidth() ); + + backgroundSize.setHeight( textSize.height() + 2 * margin ); + backgroundSize.setWidth ( textSize.width() + 2 * margin ); + + mPopupBackgroundRect.setLeft( contentRect.left() + (contentRect.width() - + backgroundSize.width()) / 2.0 ); + mPopupBackgroundRect.setTop ( contentRect.top() + (contentRect.height() - + backgroundSize.height()) / 2.0 ); + + mPopupTextRect.setLeft( mPopupBackgroundRect.left() + margin ); + mPopupTextRect.setTop ( mPopupBackgroundRect.top() + margin ); + + mPopupBackgroundRect.setSize(backgroundSize); + mPopupTextRect.setSize(textSize); + } + break; + + case HgWidget::IndexFeedbackString: + { + textSize.setHeight( textHeight() ); + backgroundSize.setHeight( textSize.height() + 2 * margin ); + + backgroundSize.setWidth( contentRect.width() - 2 * mStringOffset ); + textSize.setWidth( backgroundSize.width() - 2 * margin ); + + mPopupBackgroundRect.setLeft( contentRect.left() + mStringOffset ); + mPopupBackgroundRect.setTop( contentRect.top() + (contentRect.height() - + backgroundSize.height()) / 2.0 ); + + mPopupTextRect.setLeft( mPopupBackgroundRect.left() + margin ); + mPopupTextRect.setTop ( mPopupBackgroundRect.top() + margin ); + + mPopupBackgroundRect.setSize(backgroundSize); + mPopupTextRect.setSize(textSize); + } + break; + + case HgWidget::IndexFeedbackNone: + { + mPopupTextRect = QRectF(); + mPopupBackgroundRect = QRectF(); + } + break; + } +} + +/* + Returns the text height in pixels. +*/ +qreal HgIndexFeedbackPrivate::textHeight() const +{ + Q_Q( const HgIndexFeedback ); + + qreal retVal; + + switch (mIndexFeedbackPolicy) { + case HgWidget::IndexFeedbackNone: + retVal = 0.0; + break; + + case HgWidget::IndexFeedbackSingleCharacter: + retVal = mOneCharHeight; + break; + + case HgWidget::IndexFeedbackThreeCharacter: + retVal = mThreeCharHeight; + break; + + case HgWidget::IndexFeedbackString: + q->style()->parameter(QLatin1String("hb-param-text-height-primary"), retVal); + break; + } + + return retVal; +} + +/* + Returns the text width in units. +*/ +qreal HgIndexFeedbackPrivate::textWidth() const +{ + qreal retVal = 0.0; + + switch (mIndexFeedbackPolicy) { + case HgWidget::IndexFeedbackString: + case HgWidget::IndexFeedbackNone: + retVal = 0.0; + break; + + case HgWidget::IndexFeedbackSingleCharacter: + retVal = mOneCharHeight; + break; + + case HgWidget::IndexFeedbackThreeCharacter: + retVal = mThreeCharWidth; + break; + } + + return retVal; +} + +/* + Connects model currentSelectionChanged slot to index feedback. + */ +void HgIndexFeedbackPrivate::connectModelToIndexFeedback(QItemSelectionModel* model) +{ + Q_Q(HgIndexFeedback); + + if (!model) + return; + + q->connect(model, SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), + q, SLOT(_q_currentModelIndexChanged(const QModelIndex&, const QModelIndex&))); + +} + +void HgIndexFeedbackPrivate::_q_currentModelIndexChanged(const QModelIndex& current, const QModelIndex& previous) +{ + Q_UNUSED(current) + Q_UNUSED(previous) + + if (mScrollBarPressed) + updateIndex(); +} + + diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hglongpressvisualizer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hglongpressvisualizer.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,85 @@ +/* +* Copyright (c) 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: +* +*/ + +#include +#include +#include +#include +#include +#include +#include "hglongpressvisualizer.h" + +HgLongPressVisualizer::HgLongPressVisualizer(QGraphicsItem* parent) : HbWidget(parent), + active(false), + spanAngle(0) +{ + +} + +HgLongPressVisualizer::~HgLongPressVisualizer() +{ + +} + + +void HgLongPressVisualizer::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + if (active) { + QPen pen( Qt::lightGray ); + pen.setWidth(5); + painter->setPen(pen); + painter->drawArc(rect, 90*16, -spanAngle*16); + } +} + +void HgLongPressVisualizer::start(const QPointF& scenePos) +{ + prepareGeometryChange(); + rect = QRect( 0, 0, 30, 30); + + if (scenePos.y() < 60 ) { + //Draw the animation below of the touch point + rect.moveCenter( QPointF(scenePos.x(), scenePos.y()+50)); + } + else { + //Draw the animation above of the touch point + rect.moveCenter( QPointF(scenePos.x(), scenePos.y()-50)); + } + + setFrame(0); + active = true; +} + +void HgLongPressVisualizer::stop() +{ + active = false; + update(); +} + +void HgLongPressVisualizer::setFrame(int frame) +{ + spanAngle = frame*360/100; + update(); +} + +QRectF HgLongPressVisualizer::boundingRect() const +{ + return rect; +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgmediawall.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgmediawall.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,113 @@ +/* +* Copyright (c) 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: +* +*/ + +#include +#include "hgmediawall_p.h" +#include "hgwidgets_p.h" +#include "hgcoverflowcontainer.h" + +HgMediawall::HgMediawall(QGraphicsItem *parent ): + HgWidget(new HgMediawallPrivate, parent) +{ + Q_D(HgMediawall); + d->q_ptr = this; + d->init(); +} + +HgMediawall::~HgMediawall() +{ +} + +/*! + Sets the placement of the title. +*/ +void HgMediawall::setTitlePosition(LabelPosition position) +{ + Q_D(HgMediawall); + d->setTitlePosition(position); +} + +/*! + Returns the placement of the title. +*/ +HgMediawall::LabelPosition HgMediawall::titlePosition() const +{ + Q_D(const HgMediawall); + return d->titlePosition(); +} + +/*! + Sets the placement of the description. +*/ +void HgMediawall::setDescriptionPosition(LabelPosition position) +{ + Q_D(HgMediawall); + d->setDescriptionPosition(position); +} + +/*! + Returns the placement of the description. +*/ +HgMediawall::LabelPosition HgMediawall::descriptionPosition() const +{ + Q_D(const HgMediawall); + return d->descriptionPosition(); +} + +/*! + Sets the fontSpec property of the title. + + The font specification defines the font with a font role and optional + other parameters. +*/ +void HgMediawall::setTitleFontSpec(const HbFontSpec &fontSpec) +{ + Q_D(HgMediawall); + d->setTitleFontSpec(fontSpec); +} + +/*! + Returns the fontSpec property of the title. +*/ +HbFontSpec HgMediawall::titleFontSpec() const +{ + Q_D(const HgMediawall); + return d->titleFontSpec(); +} + +/*! + Sets the fontSpec property of the description. + + The font specification defines the font with a font role and optional + other parameters. +*/ +void HgMediawall::setDescriptionFontSpec(const HbFontSpec &fontSpec) +{ + Q_D(HgMediawall); + d->setDescriptionFontSpec(fontSpec); +} + +/*! + Returns the fontSpec property of the description. +*/ +HbFontSpec HgMediawall::descriptionFontSpec() const +{ + Q_D(const HgMediawall); + return d->descriptionFontSpec(); +} + +// EOF diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgmediawall_p.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgmediawall_p.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,111 @@ +/* +* Copyright (c) 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: +* +*/ + +#include "hgmediawall_p.h" +#include "hgcoverflowcontainer.h" +#include "trace.h" + +HgMediawallPrivate::HgMediawallPrivate() +{ + FUNC_LOG; +} + +HgMediawallPrivate::~HgMediawallPrivate() +{ + FUNC_LOG; +} + +void HgMediawallPrivate::init() +{ + FUNC_LOG; + + Q_Q(HgMediawall); + HgCoverflowContainer* container = new HgCoverflowContainer(q); + // Mediawall supports only horizontal scrolling. + container->init(Qt::Horizontal); + HgWidgetPrivate::init(container); +} + +void HgMediawallPrivate::setTitlePosition(HgMediawall::LabelPosition position) +{ + FUNC_LOG; + + container()->setTitlePosition(position); +} + +HgMediawall::LabelPosition HgMediawallPrivate::titlePosition() const +{ + FUNC_LOG; + + return container()->titlePosition(); +} + +void HgMediawallPrivate::setDescriptionPosition(HgMediawall::LabelPosition position) +{ + FUNC_LOG; + + container()->setDescriptionPosition(position); +} + +HgMediawall::LabelPosition HgMediawallPrivate::descriptionPosition() const +{ + FUNC_LOG; + + return container()->descriptionPosition(); +} + +void HgMediawallPrivate::setTitleFontSpec(const HbFontSpec &fontSpec) +{ + FUNC_LOG; + + container()->setTitleFontSpec(fontSpec); +} + +HbFontSpec HgMediawallPrivate::titleFontSpec() const +{ + FUNC_LOG; + + return container()->titleFontSpec(); +} + +void HgMediawallPrivate::setDescriptionFontSpec(const HbFontSpec &fontSpec) +{ + FUNC_LOG; + + container()->setDescriptionFontSpec(fontSpec); +} + +HbFontSpec HgMediawallPrivate::descriptionFontSpec() const +{ + FUNC_LOG; + + return container()->descriptionFontSpec(); +} + +HgCoverflowContainer *HgMediawallPrivate::container() +{ + HANDLE_ERROR_NULL(mContainer); + return qobject_cast(mContainer); +} + +const HgCoverflowContainer *HgMediawallPrivate::container() const +{ + HANDLE_ERROR_NULL(mContainer); + return qobject_cast(mContainer); +} + +// EOF diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgmediawallrenderer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgmediawallrenderer.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,977 @@ +/* +* Copyright (c) 2009 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: +* +*/ +#include "HgMediaWallRenderer.h" +#include "hgmediawalldataprovider.h" +#include "hgquadrenderer.h" +#include "hgquad.h" +#include "hgimage.h" +#include "HgImageFader.h" +#include "hgvgquadrenderer.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const Qt::Orientation KDefaultOrientation(Qt::Vertical); +const qreal KPi = 3.1415926535897932384626433832795; + +static qreal lerp(qreal start, qreal end, qreal t) +{ + return start * (1.0f - t) + end * t; +} + +class MyVectorAnimation : public QVariantAnimation +{ +public: + virtual void updateCurrentValue(const QVariant& value) + { + mValue = value.value(); + } + QVector3D getValue() const + { + return mValue; + } +private: + QVector3D mValue; +}; + +class HgAnimatedQuad +{ +public: + + HgAnimatedQuad(HgQuad* start, HgQuad* end, + int duration) : mQuad(start) + { + mPositionAnimation.setDuration(duration); + mPositionAnimation.setKeyValueAt(0, start->position()); + mPositionAnimation.setKeyValueAt(1.0, end->position()); + mPositionAnimation.setEasingCurve(QEasingCurve::Linear); + + mScaleAnimation.setDuration(duration); + mScaleAnimation.setKeyValueAt(0, QVector3D(start->scale().x(), start->scale().y(), 0)); + mScaleAnimation.setKeyValueAt(1, QVector3D(end->scale().x(), end->scale().y(), 0)); + mScaleAnimation.setEasingCurve(QEasingCurve::Linear); + + } + + ~HgAnimatedQuad() + { + } + + void start() + { + mPositionAnimation.start(); + mScaleAnimation.start(); + } + + void update() + { + mQuad->setPosition(mPositionAnimation.currentValue().value()); + QVector3D scale = mScaleAnimation.currentValue().value(); + mQuad->setScale(QVector2D(scale.x(), scale.y())); + } + + HgQuad* mQuad; + MyVectorAnimation mPositionAnimation; + MyVectorAnimation mScaleAnimation; +}; + +HgMediaWallRenderer::HgMediaWallRenderer(HgMediaWallDataProvider* provider) : + mDataProvider(provider), + mRenderer(NULL), + mIndicatorRenderer(NULL), + mRendererInitialized(false), + mOrientation(KDefaultOrientation), + mNextOrientation(KDefaultOrientation), + mStateAnimationAlpha(0), + mStateAnimationOnGoing(false), + mAnimationAlpha(0), + mOpeningAnimationDuration(500), + mOpenedItem(-1), + mFlipAngle(qreal(360)), + mZoomAmount(qreal(0.5)), + mCoverflowMode(false), + mRowCount(1), + mNextRowCount(1), + mStateAnimationDuration(300), + mStep(1.1), + mZfar(-2), + mSpacing2D(10,10), + mImageSize2D(100, 60), + mCameraDistance(0), + mCameraRotationY(0), + mCameraRotationZ(0), + mFrontCoverElevation(0.4), + mReflectionsEnabled(true), + mItemCountChanged(false), + mOpenedItemState(ItemClosed) +{ + createStateMachine(); + mImageFader = new HgImageFader(); + mRenderer = new HgVgQuadRenderer(256); + mRendererInitialized = true; +} + +HgMediaWallRenderer::~HgMediaWallRenderer() +{ + delete mRenderer; + delete mImageFader; + delete mStateMachine; +} + + +void HgMediaWallRenderer::setCameraDistance(qreal distance) +{ + mCameraDistance = distance; +} + +void HgMediaWallRenderer::setCameraRotationY(qreal angle) +{ + mCameraRotationY = angle; +} + +void HgMediaWallRenderer::setCameraRotationZ(qreal angle) +{ + mCameraRotationZ = angle; +} + +qreal HgMediaWallRenderer::getCameraDistance() const +{ + return mCameraDistance; +} + +qreal HgMediaWallRenderer::getCameraRotationY() const +{ + return mCameraRotationY; +} + +qreal HgMediaWallRenderer::getCameraRotationZ() const +{ + return mCameraRotationZ; +} + +void HgMediaWallRenderer::draw( + const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter) +{ + // if still not initialized we cant draw anything + if (!mRendererInitialized) + return; + + if (mOrientation != mNextOrientation || + mRowCount != mNextRowCount) + { + + // save old state of the quads + recordState(mOldState); + + // goto wanted orientation / rowcount + mOrientation = mNextOrientation; + mRowCount = mNextRowCount; + setImageSize(mNextImageSize); + + // setup quads to new state + setupRows(startPosition, position, targetPosition, springVelocity, painter); + + // record state for animation + recordState(mNextState); + + startStateAnimation(painter); + } + else + { + if (!mStateAnimationOnGoing) + { + setupRows(startPosition, position, targetPosition, springVelocity, painter); + } + else + { + setupStateAnimation(painter); + } + } + + updateCameraMatrices(); + drawQuads(painter); +} + +void HgMediaWallRenderer::setupRows(const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter) +{ + // draw the state for it + resetQuads(); + updateSpacingAndImageSize(); + + if (mCoverflowMode) + { + //setupRow(startPosition, position, targetPosition, springVelocity, painter, 0); + setupCoverflow(startPosition, position, targetPosition, springVelocity, painter); + } + else + { + if (mOrientation == Qt::Vertical) + { + setupGridPortrait(startPosition, position, targetPosition, + springVelocity, painter); + } + else + { + setupGridLandscape(startPosition, position, targetPosition, + springVelocity, painter); + } + } +} + +void HgMediaWallRenderer::setFlipAnimationAngle(qreal angleInDegrees) +{ + mFlipAngle = angleInDegrees; +} + +void HgMediaWallRenderer::setOpeningAnimationType(HgMediaWallRenderer::OpeningAnimationType type) +{ + mOpeningAnimationType = type; +} + +void HgMediaWallRenderer::setOpeningAnimationDuration(int msecs) +{ + mOpeningAnimationDuration = msecs; +} + +qreal HgMediaWallRenderer::animationAlpha() const +{ + return mAnimationAlpha; +} + +void HgMediaWallRenderer::setAnimationAlpha(qreal alpha) +{ + mAnimationAlpha = alpha; + + if (mOpenedItemState == ItemClosing && alpha == 0.0f) + mOpenedItemState = ItemClosed; + + if (mOpenedItemState == ItemOpening && alpha == 1.0f) + mOpenedItemState = ItemOpened; + + emit renderingNeeded(); +} + +qreal HgMediaWallRenderer::stateAnimationAlpha() const +{ + return mStateAnimationAlpha; +} + +void HgMediaWallRenderer::setStateAnimationAlpha(qreal alpha) +{ + mStateAnimationAlpha = alpha; + if (alpha == 1 && mStateAnimationOnGoing) + { + mStateAnimationOnGoing = false; + } + emit renderingNeeded(); +} + +void HgMediaWallRenderer::createStateMachine() +{ + mStateMachine = new QStateMachine(this); + mStateMachine->setAnimated(true); + + QState* root = new QState(QState::ParallelStates); + QState* p1 = new QState(root); + QState* p2 = new QState(root); + + // create idle/opened states + { + QState* idle = new QState(p1); + QState* opened = new QState(p1); + + idle->assignProperty(this, "animationAlpha", qreal(0)); + opened->assignProperty(this, "animationAlpha", qreal(1)); + + // add opening animation + QPropertyAnimation* anim1 = new QPropertyAnimation(this, "animationAlpha"); + anim1->setDuration(mOpeningAnimationDuration); + idle->addTransition(this, SIGNAL(toggleItem()), opened)->addAnimation(anim1); + + // add closing animation + QPropertyAnimation* anim2 = new QPropertyAnimation(this, "animationAlpha"); + anim2->setDuration(mOpeningAnimationDuration); + opened->addTransition(this, SIGNAL(toggleItem()), idle)->addAnimation(anim2); + + QObject::connect(idle, SIGNAL(entered()), this, SLOT(onIdleState())); + QObject::connect(opened, SIGNAL(entered()), this, SLOT(onOpenedState())); + + p1->setInitialState(idle); + } + + // create two states to animate between + { + QState* s1 = new QState(p2); + QState* s2 = new QState(p2); + + s1->assignProperty(this, "stateAnimationAlpha", qreal(0)); + s2->assignProperty(this, "stateAnimationAlpha", qreal(0)); + + QPropertyAnimation* anim = new QPropertyAnimation(this, "stateAnimationAlpha"); + anim->setStartValue(qreal(0)); + anim->setEndValue(qreal(1)); + anim->setDuration(mStateAnimationDuration); + + s1->addTransition(this, SIGNAL(toggleState()), s2)->addAnimation(anim); + s2->addTransition(this, SIGNAL(toggleState()), s1)->addAnimation(anim); + + p2->setInitialState(s1); + } + + root->setInitialState(p1); + mStateMachine->addState(root); + mStateMachine->setInitialState(root); + mStateMachine->start(); + +} + +void HgMediaWallRenderer::onIdleState() +{ + emit itemClosed(mOpenedItem); +} + +void HgMediaWallRenderer::onOpenedState() +{ + emit itemOpened(mOpenedItem); +} + +void HgMediaWallRenderer::setOrientation(Qt::Orientation orientation, bool animate) +{ + if (mOrientation != orientation) + { + mStateMachine->setAnimated(animate); + mNextOrientation = orientation; + + if (!animate) + mOrientation = orientation; + else + { + emit renderingNeeded(); + } + } +} + +Qt::Orientation HgMediaWallRenderer::getOrientation() const +{ + return mOrientation; +} + +void HgMediaWallRenderer::drawQuads(QPainter* painter) +{ + mRenderer->transformQuads(mViewMatrix, mProjMatrix, mRect); + + mRenderer->drawQuads(mRect, painter); +} + + +void HgMediaWallRenderer::enableCoverflowMode(bool enabled) +{ + mCoverflowMode = enabled; +} + +bool HgMediaWallRenderer::coverflowModeEnabled() const +{ + return mCoverflowMode; +} + +void HgMediaWallRenderer::setRowCount(int rowCount, const QSizeF& newImageSize, bool animate) +{ + if (rowCount != mRowCount) + { + mStateMachine->setAnimated(animate); + + mNextRowCount = rowCount; + mNextImageSize = newImageSize; + + mColumnCount = rowCount; + + if (!animate) + { + mRowCount = rowCount; + } + else + { + emit renderingNeeded(); + } + + } + +} + +int HgMediaWallRenderer::getRowCount() const +{ + return mRowCount; +} + +void HgMediaWallRenderer::recordState(HgMediaWallRenderer::State& state) +{ + // cleanup old quads + for (int i = 0; i < state.mQuads.size(); i++) + { + delete state.mQuads[i]; + } + + state.mQuads.clear(); + + // record new quads + for (int i = 0; i < mRenderer->quadCount(); i++) + { + HgQuad* quad = mRenderer->quad(i); + if (!quad->visible()) + continue; + + state.mQuads.append(quad->copy()); + } +} + +void HgMediaWallRenderer::setupStateAnimation(QPainter* painter) +{ + Q_UNUSED(painter) + + resetQuads(); + // setup quads from animated state + for (int i = 0; i < mOldState.mQuads.size(); i++) + { + mAnimatedQuads[i]->update(); + mRenderer->quad(i)->copyFrom(*mOldState.mQuads[i]); + } +} + +void HgMediaWallRenderer::resetQuads() +{ + for (int i = 0; i < mRenderer->quadCount(); i++) + mRenderer->quad(i)->setVisible(false); +} + +HgQuad* HgMediaWallRenderer::getQuadAt(const QPointF& position) const +{ + if (!mRendererInitialized) + return NULL; + + return mRenderer->getQuadAt(position);//mapFromWindow(position)); +} + +bool HgMediaWallRenderer::isItemOpen() const +{ + return (mOpenedItem != -1 && mAnimationAlpha > 0); +} + +void HgMediaWallRenderer::setRect(const QRectF& windowRect) +{ + mRect = windowRect; +} + +const QRectF& HgMediaWallRenderer::getRect() const +{ + return mRect; +} + +void HgMediaWallRenderer::updateCameraMatrices() +{ + QMatrix4x4 view; + + view.setToIdentity(); + + view.lookAt(QVector3D(0.0, 0.0, 1.0f + mCameraDistance), + QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 1.0f, 0.0f)); + + QMatrix4x4 rot; + rot.rotate(mCameraRotationZ, QVector3D(0,0,1)); + rot.rotate(mCameraRotationY, QVector3D(0,1,0)); + view *= rot; + + qreal aspect = mRect.width() / mRect.height(); + + QMatrix4x4 proj; + proj.setToIdentity(); + + if (mRect.width() <= mRect.height()) + { + qreal aspect = mRect.height() / mRect.width(); + proj.frustum(-0.5f, 0.5f, -0.5f*aspect, 0.5f*aspect, 1.0f, 1000.0f); + } + else + { + qreal aspect = mRect.width() / mRect.height(); + proj.frustum(-0.5f*aspect, 0.5f*aspect, -0.5f, 0.5f, 1.0f, 1000.0f); + } + + mViewMatrix = view; + mProjMatrix = proj; + + qreal mirrorPlaneY = getRowPosY(mRowCount-1)-mImageSize3D.height()/2; + mRenderer->setMirroringPlaneY(mirrorPlaneY); +} + +void HgMediaWallRenderer::updateSpacingAndImageSize() +{ + qreal div = mRect.width() <= mRect.height() ? mRect.width() : mRect.height(); + + mSpacing3D = mSpacing2D / div; + mImageSize3D = mImageSize2D / div; +} + +void HgMediaWallRenderer::setSpacing(const QSizeF& spacing) +{ + mSpacing2D = spacing; +} + +void HgMediaWallRenderer::setImageSize(const QSizeF& imageSize) +{ + mImageSize2D = imageSize; + mNextImageSize = imageSize; +} + +const QSizeF& HgMediaWallRenderer::getSpacing() const +{ + return mSpacing2D; +} + +const QSizeF& HgMediaWallRenderer::getImageSize() const +{ + return mImageSize2D; +} + +void HgMediaWallRenderer::setFrontCoverElevationFactor(qreal elevation) +{ + mFrontCoverElevation = elevation; +} + +qreal HgMediaWallRenderer::getFrontCoverElevationFactor() const +{ + return mFrontCoverElevation; +} + +void HgMediaWallRenderer::openItem(int index, bool animate) +{ + if (isItemOpen()) + return; + + mOpenedItem = index; + mOpenedItemState = animate ? ItemOpening : ItemOpened; + + mStateMachine->setAnimated(animate); + emit toggleItem(); + +} + +void HgMediaWallRenderer::closeItem(bool animate) +{ + if (!isItemOpen()) + return; + + mOpenedItemState = animate ? ItemClosing : ItemClosed; + if (!animate) + mOpenedItem = -1; + + mStateMachine->setAnimated(animate); + emit toggleItem(); +} + +qreal HgMediaWallRenderer::getRowPosY(int row) +{ + qreal step = mSpacing3D.height() + mImageSize3D.height(); + return mRowCount == 1 ? qreal(0) : (((qreal)mRowCount/qreal(2)-qreal(0.5)) - (qreal)row) * step; +} + +qreal HgMediaWallRenderer::getColumnPosX(int col) +{ + qreal step = -(mSpacing3D.width() + mImageSize3D.width()); + return mColumnCount == 1 ? qreal(0) : (((qreal)mColumnCount/qreal(2)-qreal(0.5)) - (qreal)col) * step; +} + + +void HgMediaWallRenderer::enableReflections(bool enabled) +{ + mReflectionsEnabled = enabled; +} + +bool HgMediaWallRenderer::reflectionsEnabled() const +{ + return mReflectionsEnabled; +} + +QPointF HgMediaWallRenderer::mapFromWindow(const QPointF& point) const +{ + return QPointF(point.x(), mRect.height() - point.y()); +} + +void HgMediaWallRenderer::emitUpdate() +{ + emit renderingNeeded(); +} + +void HgMediaWallRenderer::applyOpeningAnimation(HgQuad* quad) +{ + QQuaternion rot(0,0,0,1); + qreal rotAngle = mAnimationAlpha * mFlipAngle; + rot = QQuaternion::fromAxisAndAngle(QVector3D(0,1,0), rotAngle); + quad->setRotation(rot); + quad->setPosition(quad->position() + QVector3D(0,0,mAnimationAlpha * mZoomAmount)); +} + + +qreal HgMediaWallRenderer::getWorldWidth() const +{ + qreal width = (qreal)mDataProvider->imageCount() / (qreal)mRowCount - 1.0f; + + if (mOrientation == Qt::Vertical) + { + qreal step = mSpacing2D.height() + mImageSize2D.height(); + width -= (mRect.height() / step - 1.0f); + } + + return width; +} + +void HgMediaWallRenderer::beginRemoveRows(int start, int end) +{ + mRemoveStart = start; + mRemoveEnd = end; + mItemCountChanged = true; + + recordState(mOldState); + +} + +void HgMediaWallRenderer::endRemoveRows() +{ + + mStateMachine->setAnimated(true); + + emit renderingNeeded(); + +} + +void HgMediaWallRenderer::startStateAnimation(QPainter* painter) +{ + + // clear previous animation quads + for (int i = 0; i < mAnimatedQuads.size(); i++) + { + delete mAnimatedQuads[i]; + } + mAnimatedQuads.clear(); + + // setup animated quads + HgQuad* defaultQuad = new HgQuad(); + defaultQuad->setPosition(QVector3D(100,100,-100)); + int n = mOldState.mQuads.count() < mNextState.mQuads.count() ? mNextState.mQuads.count() : mOldState.mQuads.count(); + for (int i = 0; i < n; i++) + { + HgQuad* qA = (i >= mOldState.mQuads.count()) ? defaultQuad : mOldState.mQuads[i]; + HgQuad* qB = (i >= mNextState.mQuads.count()) ? defaultQuad : mNextState.mQuads[i]; + + HgAnimatedQuad* q = new HgAnimatedQuad(qA, qB, mStateAnimationDuration); + mAnimatedQuads.append(q); + q->start(); + } + + mStateAnimationOnGoing = true; + + // setup first frame of the animation + setupStateAnimation(painter); + + // toggle state animation on + toggleState(); + +} + +void HgMediaWallRenderer::setupCoverflow(const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter) +{ + Q_UNUSED(startPosition) + Q_UNUSED(targetPosition) + Q_UNUSED(springVelocity) + Q_UNUSED(painter) + + // save selected item for coverflow + mSelectedItem = ceil(position.x()); + + int quadsVisible = (mRect.width() / mImageSize2D.width() + 1) * 4; + int selectedItemIndex = quadsVisible / 2; + + qreal step = mSpacing3D.width() + mImageSize3D.width(); + qreal ipos = floorf(position.x()); + qreal frac = (position.x() - ipos) * step; + qreal posX = -(qreal)(selectedItemIndex + 0) * step - frac; + qreal zFar = -mFrontCoverElevation; + qreal posY = 0; + + int count = mDataProvider->imageCount(); + int quadIndex = 0; + int itemIndex = ((int)(ipos - (qreal)selectedItemIndex)); + int index = 0; + + while (1) + { + if (itemIndex < 0) + { + itemIndex++; + posX += step; + index++; + continue; + } + else if (itemIndex >= count || index >= quadsVisible || quadIndex >= mRenderer->quadCount()) + { + break; + } + + qreal posZ = zFar; + + // if this is center item modify its z + qreal p = posX / step; + if (p > -1.0f && p < 1.0f) + { + qreal d = lerp(-zFar, 0, qBound(qreal(0), qAbs(springVelocity)/6.0f, qreal(1))); + posZ = zFar + sin((p+1.0f) * KPi / 2) * d; + } + + // modify z also for sorting + posZ -= 0.001f * abs(posX/step); + + // setup quad for this item + HgQuad* quad = mRenderer->quad(quadIndex); + setupDefaultQuad(QVector3D(posX, posY, posZ), itemIndex, mReflectionsEnabled, quadIndex); + + // step to next item + posX += step; + itemIndex++; + index++; + } + +} + + +void HgMediaWallRenderer::setupGridPortrait(const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter) +{ + Q_UNUSED(startPosition) + Q_UNUSED(targetPosition) + Q_UNUSED(springVelocity) + Q_UNUSED(painter) + + int rowCount = (mRect.height() / mImageSize2D.height() + 1) * 4; + int rowsUp = rowCount/2; + + qreal stepY = mSpacing3D.height() + mImageSize3D.height(); + qreal ipos = floorf(position.x()); + qreal frac = (position.x() - ipos) * stepY; + qreal posY = -(qreal)rowsUp * stepY - frac; + + // adjust height so that we begin from top + qreal div = mRect.width() <= mRect.height() ? mRect.width() : mRect.height(); + posY -= mRect.height() / div / 2.0 - stepY / 2.0; + + int count = mDataProvider->imageCount(); + int itemIndex = ((int)(ipos - (qreal)rowsUp)) * mColumnCount; + int row = 0; + int quadIndex = 0; + + while (1) + { + if (itemIndex < 0) + { + itemIndex+=mColumnCount; + posY += stepY; + row++; + continue; + } + else if (itemIndex >= count || quadIndex >= mRenderer->quadCount() || row >= rowCount) + { + break; + } + + setupGridRow(-posY, itemIndex, quadIndex); + + posY += stepY; + row++; + itemIndex+=mColumnCount; + } + +} + +void HgMediaWallRenderer::setupGridLandscape(const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter) +{ + Q_UNUSED(startPosition) + Q_UNUSED(targetPosition) + Q_UNUSED(springVelocity) + Q_UNUSED(painter) + + int colCount = (mRect.width() / mImageSize2D.width() + 1) * 3; + int colsLeft = colCount/2; + + qreal stepX = mSpacing3D.width() + mImageSize3D.width(); + qreal ipos = floorf(position.x()); + qreal frac = (position.x() - ipos) * stepX; + qreal posX = -(qreal)colsLeft * stepX - frac; + + int count = mDataProvider->imageCount(); + int itemIndex = ((int)(ipos - (qreal)colsLeft)) * mRowCount; + int col = 0; + int quadIndex = 0; + + while (1) + { + if (itemIndex < 0) + { + itemIndex+=mColumnCount; + posX += stepX; + col++; + continue; + } + else if (itemIndex >= count || col >= colCount || quadIndex >= mRenderer->quadCount()) + { + break; + } + + setupGridColumn(posX, itemIndex, quadIndex); + + posX += stepX; + col++; + itemIndex+=mRowCount; + } +} + +void HgMediaWallRenderer::setupGridColumn(qreal posX, int itemIndex, int& quadIndex) +{ + for (int i = 0; i < mRowCount; i++) + { + qreal posY = getRowPosY(i); + + // enable reflections for the last row needed + bool reflections = (i == (mRowCount-1) && mReflectionsEnabled); + + setupDefaultQuad(QVector3D(posX, posY, 0), itemIndex++, reflections, quadIndex); + + if (itemIndex >= mDataProvider->imageCount()) + return; + } +} + +void HgMediaWallRenderer::setupGridRow(qreal posY, int itemIndex, int& quadIndex) +{ + for (int i = 0; i < mColumnCount; i++) + { + qreal posX = getColumnPosX(i); + setupDefaultQuad(QVector3D(posX, posY, 0), itemIndex++, false, quadIndex); + if (itemIndex >= mDataProvider->imageCount()) + return; + } +} + +void HgMediaWallRenderer::setupDefaultQuad(const QVector3D& pos, int itemIndex, bool reflectionsEnabled, int& quadIndex) +{ + HgQuad* quad = mRenderer->quad(quadIndex++); + quad->setPosition(pos); + quad->setImage(mDataProvider->image(itemIndex)); + quad->setVisible(true); + quad->setScale(QVector2D(mImageSize3D.width(),mImageSize3D.height())); + quad->setPivot(QVector2D(0,0)); + quad->setUserData(QVariant(itemIndex)); + quad->setRotation(QQuaternion(1,0,0,0)); + quad->setOuterRotation(QQuaternion(1,0,0,0)); + quad->enableMirrorImage(reflectionsEnabled); + quad->setAlpha(1.0f); + + // apply opening animation if needed + /* if (itemIndex == mOpenedItem) + applyOpeningAnimation(quad); +*/ + // setup indicator/decorator for the item if needed + int flags = mDataProvider->flags(itemIndex); + const HgImage* indicatorImage = mDataProvider->indicator(flags); + if (flags != 0 && indicatorImage) + { + HgQuad* indicator = mRenderer->quad(quadIndex++); + setupIndicator(quad, indicator, indicatorImage, + itemIndex); + indicator->enableMirrorImage(reflectionsEnabled); + } + + +} + +void HgMediaWallRenderer::setupIndicator(HgQuad* parent, + HgQuad* indicator, const HgImage* indicatorImage, int itemIndex) +{ + indicator->setPosition(parent->position()+ + QVector3D(0.25*mImageSize3D.width(), -0.25*mImageSize3D.height(), 0.0001f)); + indicator->setImage(indicatorImage); + indicator->setVisible(true); + indicator->setScale(QVector2D(0.25f*mImageSize3D.width(), 0.25f*mImageSize3D.height())); + indicator->setPivot(QVector2D(0.0, 0.0)); + indicator->setUserData(QVariant(itemIndex)); + indicator->setRotation(parent->rotation()); + indicator->setOuterRotation(parent->outerRotation()); + indicator->enableMirrorImage(false); + indicator->setAlpha(parent->alpha()); + + // apply opening animation to indicator if needed + if (itemIndex == mOpenedItem) + applyOpeningAnimation(indicator); +} + +HgQuadRenderer* HgMediaWallRenderer::getRenderer() +{ + return mRenderer; +} + +bool HgMediaWallRenderer::getItemPoints(int index, QPolygonF& points) const +{ + QPolygonF poly; + if (!mRenderer->getQuadTranformedPoints(poly, index)) + return false; + + points = poly; + return true; +} + +QList HgMediaWallRenderer::getVisibleQuads() const +{ + return mRenderer->getVisibleQuads(QRectF(0, 0, mRect.width(), mRect.height())); +} + + diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgquad.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgquad.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,155 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include "HgQuad.h" + +HgQuad::HgQuad() : +mRotation(QQuaternion(1,0,0,0)), +mImage(NULL), +mVisible(false), +mPivot(0, 0), +mScale(1, 1), +mOuterRotation(QQuaternion(1,0,0,0)), +mDrawMirror(false), +mAlpha(1) +{ +} + +HgQuad::~HgQuad() +{ +} + +void HgQuad::setPosition(const QVector3D& position) +{ + mPosition = position; +} + +void HgQuad::setRotation(const QQuaternion& rotation) +{ + mRotation = rotation; +} + +const QVector3D& HgQuad::position() const +{ + return mPosition; +} + +const QQuaternion& HgQuad::rotation() const +{ + return mRotation; +} + +void HgQuad::setImage(const HgImage* image) +{ + mImage = image; +} + +const HgImage* HgQuad::image() const +{ + return mImage; +} + +void HgQuad::setVisible(bool visible) +{ + mVisible = visible; +} + +bool HgQuad::visible() const +{ + return mVisible; +} + +void HgQuad::setPivot(const QVector2D& pivot) +{ + mPivot = pivot; +} + +void HgQuad::setScale(const QVector2D& scale) +{ + mScale = scale; +} + +void HgQuad::setUserData(const QVariant& userData) +{ + mUserData = userData; +} + +const QVector2D& HgQuad::pivot() const + { + return mPivot; + } + +const QVector2D& HgQuad::scale() const + { + return mScale; + } + +const QVariant& HgQuad::userData() const + { + return mUserData; + } + +HgQuad* HgQuad::copy() const + { + HgQuad* q = new HgQuad(); + q->copyFrom(*this); + return q; + } + + +void HgQuad::copyFrom(const HgQuad& quad) + { + mPosition = quad.mPosition; + mRotation = quad.mRotation; + mScale = quad.mScale; + mPivot = quad.mPivot; + mImage = quad.mImage; + mUserData = quad.mUserData; + mVisible = quad.mVisible; + } + +void HgQuad::setOuterRotation(const QQuaternion& rot) +{ + mOuterRotation = rot; +} + +const QQuaternion HgQuad::outerRotation() const +{ + return mOuterRotation; +} + +void HgQuad::enableMirrorImage(bool enabled) +{ + mDrawMirror = enabled; +} + +bool HgQuad::mirrorImageEnabled() const +{ + return mDrawMirror; +} + +void HgQuad::setAlpha(qreal alpha) +{ + mAlpha = alpha; +} + +qreal HgQuad::alpha() const +{ + return mAlpha; +} + + diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgquadrenderer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgquadrenderer.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include "hgquadrenderer.h" +#include "hgquad.h" + +HgQuadRenderer::HgQuadRenderer(int maxQuads) +{ + for (int i = 0; i < maxQuads; i++) + { + mQuads.append(new HgQuad()); + } +} + +HgQuadRenderer::~HgQuadRenderer() +{ + for (int i = 0; i < mQuads.size(); i++) + { + delete mQuads[i]; + } +} + +int HgQuadRenderer::quadCount() const + { + return mQuads.size(); + } + +HgQuad* HgQuadRenderer::quad(int index) +{ + return mQuads[index]; +} + +void HgQuadRenderer::setMirroringPlaneY(qreal mirroringPlaneY) +{ + mMirroringPlaneY = mirroringPlaneY; +} + +void HgQuadRenderer::setImageFader(HgImageFader* fader) +{ + mImageFader = fader; +} + diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgspring.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgspring.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,167 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include "HgSpring.h" +#include +#include "trace.h" + +const int KTimeDelta(10); +const qreal KTimeDeltaF(0.01f); +//const qreal KVelocitySnap(0.05f); +const qreal KPositionSnap(0.01f); +const int KTimerInterval(10); + +HgSpring::HgSpring() : +mStartPos(QPointF(0,0)), +mPos(QPointF(0,0)), +mEndPos(QPointF(0,0)), +mVelocity(QPointF(0,0)), +mK(30.1), +mDamping(10.1), +mAccumulator(0.0), +mDoNotUpdate(false) +{ + mTimer = new QTimer(this); + + QObject::connect( mTimer, SIGNAL( timeout() ), this, SLOT( update() ) ); + +} + +HgSpring::~HgSpring() +{ + +} + +void HgSpring::setK(qreal k) +{ + mK = k; +} + +void HgSpring::setDamping(qreal damping) +{ + mDamping = damping; +} + +void HgSpring::animateToPos(const QPointF& pos) +{ + mStartPos = mPos; + mEndPos = pos; + + emit started(); + + if (!mTimer->isActive()) + { + mTimer->start(KTimerInterval); + mPrevTime.start(); + } +} + +void HgSpring::gotoPos(const QPointF& pos) +{ + if (mTimer->isActive()) + { + mTimer->stop(); + } + + mPos = pos; + mEndPos = pos; +} + +void HgSpring::cancel() +{ + if (mTimer->isActive()) + mTimer->stop(); +} + +const QPointF& HgSpring::startPos() const +{ + return mStartPos; +} + +const QPointF& HgSpring::pos() const +{ + return mPos; +} + +const QPointF& HgSpring::endPos() const +{ + return mEndPos; +} + +const QPointF& HgSpring::velocity() const +{ +return mVelocity; +} + + +void HgSpring::update() +{ + int deltaTime = mPrevTime.elapsed(); + + mPrevTime.start(); + + mAccumulator += deltaTime; + + bool stopped = false; + while (mAccumulator >= KTimeDelta) + { + QPointF delta = mEndPos - mPos; + QPointF force = delta * mK - mVelocity * mDamping; + mVelocity += force * KTimeDeltaF; + mPos += mVelocity * KTimeDeltaF; + if ( (qAbs(mPos.x() - mEndPos.x()) < KPositionSnap && + qAbs(mPos.y() - mEndPos.y()) < KPositionSnap) ) + { + mPos = mEndPos; + mAccumulator = 0; + mVelocity = QPointF(0,0); + mTimer->stop(); + stopped = true; + break; + } + + mAccumulator -= KTimeDelta; + } + + if (!mDoNotUpdate) + emit updated(); + + if (stopped) + emit ended(); + +} + +bool HgSpring::isActive() const +{ + return mTimer->isActive(); +} + +bool HgSpring::updatePositionIfNeeded() +{ + if (isActive() && mPrevTime.elapsed() > KTimeDelta) { + mDoNotUpdate = true; + update(); + mDoNotUpdate = false; + mTimer->stop(); + mTimer->start(KTimerInterval); + return true; + } + return false; +} + + + diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgvgimage.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgvgimage.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,179 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include "HgVgImage.h" +#include "HgImageFader.h" +#include "hgvgquadrenderer.h" + +const int KMaxMirrorWidth(128); +const int KMaxMirrorHeight(64); + +static QSize getMirrorSize(const QImage& image) +{ + return QSize( + qMin(image.width() / 2, KMaxMirrorWidth), + qMin(image.height() / 4, KMaxMirrorHeight) + ); +} + +HgVgImage::HgVgImage(HgVgQuadRenderer* renderer) : + mVgImage(VG_INVALID_HANDLE), + mMirrorImage(VG_INVALID_HANDLE), + mMirrorSize(0,0), + mRenderer(renderer) +{ + setAlpha(1.0); +} + +HgVgImage::~HgVgImage() +{ + releaseImage(); +} + +int HgVgImage::width() const +{ + return mQImage.width(); +} + +int HgVgImage::height() const +{ + return mQImage.height(); +} + +VGImage HgVgImage::image() const +{ + return mVgImage; +} + +int HgVgImage::mirrorImageWidth() const +{ + return mMirrorSize.width(); +} + +int HgVgImage::mirrorImageHeight() const +{ + return mMirrorSize.height(); +} + +VGImage HgVgImage::mirrorImage() const +{ + return mMirrorImage; +} + + +void HgVgImage::setImage(QImage& image) +{ + if (image.isNull()) + return; + + // release previous images vg data + releaseImage(); + + mQImage = image; + + mMirrorSize = getMirrorSize(mQImage); + +} + +void HgVgImage::releaseImage() +{ + if (mVgImage != VG_INVALID_HANDLE) + { + vgDestroyImage(mVgImage); + mVgImage = VG_INVALID_HANDLE; + } + if (mMirrorImage != VG_INVALID_HANDLE) + { + vgDestroyImage(mMirrorImage); + mMirrorImage = VG_INVALID_HANDLE; + } + + // TODO, check that this will free all the previously reserved image resources. + mQImage = QImage(); +} + +void HgVgImage::upload(bool mirror) +{ + + if (mVgImage == VG_INVALID_HANDLE) + { + + VGImageFormat format; + + switch (mQImage.format()) + { + case QImage::Format_ARGB32_Premultiplied: + format = VG_sARGB_8888_PRE; + break; + case QImage::Format_ARGB32: + format = VG_sARGB_8888; + break; + case QImage::Format_RGB16: + format = VG_sRGB_565; + break; + default: + mQImage = mQImage.convertToFormat(QImage::Format_RGB16); + format = VG_sRGB_565; + break; + } + + + mVgImage = vgCreateImage(format, + mQImage.width(), mQImage.height(),VG_IMAGE_QUALITY_NONANTIALIASED); + if (mVgImage == VG_INVALID_HANDLE) + { + qWarning("HgMediaWall run out of video memory for images!"); + return; + } + + vgImageSubData(mVgImage, mQImage.bits(), mQImage.bytesPerLine(), + format, 0, 0, mQImage.width(), mQImage.height() ); + } + + if (mirror && mMirrorImage == VG_INVALID_HANDLE) + { + mMirrorImage = vgCreateImage(VG_sARGB_8888_PRE, mMirrorSize.width(), mMirrorSize.height(), VG_IMAGE_QUALITY_NONANTIALIASED); + if (mMirrorImage == VG_INVALID_HANDLE) + { + qWarning("HgMediaWall run out of video memory for images!"); + return; + } + + // cut half of the image, then scale to desired width/height if needed + QImage mirrorImage = mQImage.copy(0, mQImage.height()/2, mQImage.width(), mQImage.height()/2).scaled(mMirrorSize).convertToFormat(QImage::Format_ARGB32); + + // apply gradient to alpha channel so that mirror image looks like + // it fades under the floor + for (int i = 0; i < mirrorImage.height(); i++) + { + qreal t = qreal(i) / qreal(mirrorImage.height()); + int a = (int)(t * 255.0); + for (int j = 0; j < mirrorImage.width(); j++) + { + QRgb rgb = mirrorImage.pixel(j, i); + mirrorImage.setPixel(j, i, qRgba(qRed(rgb), qGreen(rgb), qBlue(rgb), a)); + } + } + + // copy data to vg image + vgImageSubData(mMirrorImage, mirrorImage.bits(), mirrorImage.bytesPerLine(), + VG_sARGB_8888, 0, 0, mirrorImage.width(), mirrorImage.height() ); + + } + +} + diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgvgimagepool.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgvgimagepool.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,89 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include "hgvgimagepool.h" +#include "trace.h" + +HgVgImagePool::HgVgImagePool(int numImages, int imgWidth, int imgHeight, bool alpha) +{ + for (int i = 0; i < numImages; i++) + { + VGImage vgimage = vgCreateImage(alpha ? VG_sARGB_8888 : VG_sRGB_565, + imgWidth, imgHeight,VG_IMAGE_QUALITY_NONANTIALIASED); + + mFreeImages.push_back(vgimage); + } +} +HgVgImagePool::~HgVgImagePool() +{ + QLinkedList::const_iterator it = mUsedImages.begin(); + while (it != mUsedImages.end()) + { + vgDestroyImage((*it)); + it++; + } + + QLinkedList::const_iterator it2 = mFreeImages.begin(); + while (it2 != mFreeImages.end()) + { + vgDestroyImage((*it2)); + it2++; + } + +} +void HgVgImagePool::releaseImage(VGImage image) +{ + if (image == VG_INVALID_HANDLE) + return; + + for (QLinkedList::iterator it = mUsedImages.begin(); + it != mUsedImages.end(); ++it) + { + if ((*it) == image) + { + mUsedImages.erase(it); + break; + } + } + vgClearImage(image, 0, 0, vgGetParameteri(image, VG_IMAGE_WIDTH), vgGetParameteri(image, VG_IMAGE_HEIGHT)); + mFreeImages.push_back(image); +} + +VGImage HgVgImagePool::getImage() +{ + FUNC_LOG + + if (mFreeImages.empty()) + { + INFO("Hg: Run out of images!"); + + // if no free images left, use the one which was allocated + // longer ago + QLinkedList::iterator i = mUsedImages.begin(); + VGImage img = *i; + mUsedImages.erase(i); + mUsedImages.push_back(img); + return img; + } + + QLinkedList::iterator i = mFreeImages.begin(); + VGImage img = *i; + mUsedImages.push_back(img); + mFreeImages.erase(i); + + return img; +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgvgquadrenderer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgvgquadrenderer.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,471 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include "hgvgquadrenderer.h" +#include "hgquad.h" +#include "hgvgimage.h" +#include "trace.h" +#include "HgImageFader.h" + +#include +#include +#include +#include +#include +#include + + +class HgVgQuad +{ +public: + HgVgQuad(HgVgQuadRenderer* renderer); + ~HgVgQuad(); + + int index() const; + bool isPointInside(const QPointF& point) const; + void transformQuad(int index, const QMatrix4x4& matrix, HgQuad* quad, + const QRectF& rect, qreal mirroringPlaneY); + void draw(); + + void getTransformedPoints(QPolygonF& polygon) const; + + void computeMirrorMatrix(const QMatrix4x4& tm, const QMatrix4x4& projView, + const QRectF& rect, qreal mirroringPlaneY); + + bool perspectiveTransformPoints(QVector2D* points, const QMatrix4x4& matrix, + const QRectF& rect); + + void computeWarpMatrix(VGfloat* matrix, int pxWidth, int pxHeight, const QVector2D* points); + + void drawImage(HgVgImage* image, qreal alpha); + + int mIndex; + HgQuad* mQuad; + QVector2D mTransformedPoints[4]; + VGfloat mMatrix[9]; + VGfloat mMirrorMatrix[9]; + HgVgQuadRenderer* mRenderer; + bool mDegenerate; +private: + HgVgQuad(const HgVgQuad&); + HgVgQuad& operator=(const HgVgQuad&); +}; + +static bool quadSorter(HgVgQuad* a, HgVgQuad* b) +{ + return a->mQuad->position().z() < b->mQuad->position().z(); +} + +HgVgQuad::HgVgQuad(HgVgQuadRenderer* renderer) : mRenderer(renderer) +{ + +} + +HgVgQuad::~HgVgQuad() +{ + +} + +int HgVgQuad::index() const + { + return mIndex; + } + +bool HgVgQuad::isPointInside(const QPointF& point) const +{ + QPolygonF poly; + getTransformedPoints(poly); + QRectF rect = poly.boundingRect(); + if (rect.contains(point)) + { + return true; + } + return false; +} + + +void HgVgQuad::computeMirrorMatrix(const QMatrix4x4& trans, const QMatrix4x4& projView, + const QRectF& rect, qreal mirroringPlaneY) +{ + HgQuad* quad = mQuad; + + QMatrix4x4 mirror = trans; + + qreal distToPlane = qAbs(quad->position().y() - mirroringPlaneY); + + mirror.translate(quad->position().x(), mirroringPlaneY - distToPlane/2, quad->position().z()); + mirror.scale(quad->scale().x(), -quad->scale().y()/2); + mirror.rotate(quad->rotation()); + + QMatrix4x4 modelViewProjMatrix = projView * mirror; + + QVector2D temp[4]; + + perspectiveTransformPoints(temp, modelViewProjMatrix, rect); + + HgVgImage* image = (HgVgImage*)mQuad->image(); + + if (image == NULL) + { + image = mRenderer->defaultImage(); + } + + int pxWidth = image->mirrorImageWidth(); + int pxHeight = image->mirrorImageHeight(); + + computeWarpMatrix(mMirrorMatrix, pxWidth, pxHeight, temp); +} + +void HgVgQuad::transformQuad(int index, const QMatrix4x4& projView, HgQuad* quad, + const QRectF& rect, qreal mirroringPlaneY) +{ + mIndex = index; + mQuad = quad; + + QMatrix4x4 tm; + tm.setToIdentity(); + tm.rotate(quad->outerRotation()); + + if (mQuad->mirrorImageEnabled()) + { + computeMirrorMatrix(tm, projView, rect, mirroringPlaneY); + } + + tm.translate(quad->position()); + tm.rotate(quad->rotation()); + tm.scale(quad->scale().x(), quad->scale().y()); + + tm = projView * tm; + //QMatrix4x4 tmt = tm.transposed(); + + mDegenerate = false; + if (!perspectiveTransformPoints(mTransformedPoints, tm, rect)) + { + mDegenerate = true; + } + + HgVgImage* image = (HgVgImage*)mQuad->image(); + + if (image == NULL) + { + image = mRenderer->defaultImage(); + } + + int pxWidth = image->width(); + int pxHeight = image->height(); + + computeWarpMatrix(mMatrix, pxWidth, pxHeight, mTransformedPoints); + +} + +bool HgVgQuad::perspectiveTransformPoints(QVector2D* outPoints, const QMatrix4x4& matrix, + const QRectF& rect) +{ + const QVector4D points[] = + { + QVector4D(-0.5f, -0.5f, 0.0f, 1.0f), + QVector4D( 0.5f, -0.5f, 0.0f, 1.0f), + QVector4D( 0.5f, 0.5f, 0.0f, 1.0f), + QVector4D(-0.5f, 0.5f, 0.0f, 1.0f) + }; + + qreal hw = rect.width() * 0.5f; + qreal hh = rect.height() * 0.5f; + + for (int i = 0; i < 4; i++) + { + QVector4D temp = matrix * points[i]; + + outPoints[i] = QVector2D( + hw + temp.x() / temp.w() * hw, + hh + temp.y() / temp.w() * hh); + + } + + return true; +} + +void HgVgQuad::computeWarpMatrix(VGfloat* matrix, int pxWidth, int pxHeight, const QVector2D* points) +{ + vguComputeWarpQuadToQuad( + points[0].x(), points[0].y(), + points[1].x(), points[1].y(), + points[2].x(), points[2].y(), + points[3].x(), points[3].y(), + 0, pxHeight, + pxWidth, pxHeight, + pxWidth, 0, + 0, 0, + matrix); +/* + INFO("P0 x:" << points[0].x() << " y:" << points[0].y()); + INFO("P1 x:" << points[1].x() << " y:" << points[1].y()); + INFO("P2 x:" << points[2].x() << " y:" << points[2].y()); + INFO("P3 x:" << points[3].x() << " y:" << points[3].y());*/ +} + + +void HgVgQuad::draw() +{ + if (!mQuad->visible()) + return; + + if (mDegenerate) + return; + + HgVgImage* image = (HgVgImage*)mQuad->image(); + + + if (image == NULL || image->alpha() == 0) + { + return; + //drawImage(mRenderer->defaultImage(), 1.0f); + } + else + { + image->upload(mQuad->mirrorImageEnabled()); + + if (image->image() == VG_INVALID_HANDLE) + { + drawImage(mRenderer->defaultImage(), 1.0f); + } + else + { + + if ( mQuad->alpha() < 1.0f ) + { + drawImage(mRenderer->defaultImage(), 1.0f - mQuad->alpha()); + } + + drawImage(image, mQuad->alpha()); + } + } + + +} + +void HgVgQuad::drawImage(HgVgImage* image, qreal alpha) +{ + Q_UNUSED(alpha) + + //VGfloat values[] = { 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 }; + //values[3] = alpha; + + //vgSetfv(VG_COLOR_TRANSFORM_VALUES, 8, values); + + VGImage vgImage = image->image(); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + + VGfloat m[9]; + vgGetMatrix(m); + + vgMultMatrix(mMatrix); + vgDrawImage(vgImage); + + vgLoadMatrix(m); + + if (mQuad->mirrorImageEnabled()) + { + VGImage mirrorImage = image->mirrorImage(); + if (mirrorImage == VG_INVALID_HANDLE) + return; + + vgMultMatrix(mMirrorMatrix); + + vgDrawImage(mirrorImage); + vgLoadMatrix(m); + } + +} + + +void HgVgQuad::getTransformedPoints(QPolygonF& poly) const +{ + poly.append(mTransformedPoints[0].toPointF()); + poly.append(mTransformedPoints[1].toPointF()); + poly.append(mTransformedPoints[2].toPointF()); + poly.append(mTransformedPoints[3].toPointF()); +} + + +HgVgQuadRenderer::HgVgQuadRenderer(int maxQuads) : + HgQuadRenderer(maxQuads), + mDefaultVgImage(NULL) +{ + for (int i = 0; i < maxQuads; i++) + { + mTransformedQuads.append(new HgVgQuad(this)); + } + mImageFader = new HgImageFader(); +} + +HgVgQuadRenderer::~HgVgQuadRenderer() +{ + delete mDefaultVgImage; +} + +HgQuad* HgVgQuadRenderer::getQuadAt(const QPointF& point) const +{ + FUNC_LOG + + // TODO: need to use sorted quads here, in reversed order. + QList::const_iterator i = mSortedQuads.begin(); + while(i != mSortedQuads.end()) + { + HgVgQuad* q = (*i); + if (q->isPointInside(point)) + { + return q->mQuad; + } + i++; + } + + return NULL; +} + + +void HgVgQuadRenderer::transformQuads(const QMatrix4x4& view, const QMatrix4x4& proj, + const QRectF& rect) +{ + QMatrix4x4 pv = proj * view; + + mSortedQuads.clear(); + + for (int i = 0; i < mQuads.size(); i++) + { + HgQuad* q = mQuads[i]; + + HgVgQuad* tq = mTransformedQuads[i]; + + if (q->visible()) + { + tq->transformQuad(i, pv, q, rect, mMirroringPlaneY); + mSortedQuads.append(tq); + } + } + + qSort(mSortedQuads.begin(), mSortedQuads.end(), quadSorter); +} + +void HgVgQuadRenderer::drawQuads(const QRectF& rect, QPainter* painter) +{ + Q_UNUSED(rect) + + + painter->beginNativePainting(); + + // need to save old scissoring rects, otherwise hb + // screws up with rendering +/* VGint oldScissoring = vgGeti(VG_SCISSORING); + VGint numRects = 32;//vgGeti(VG_MAX_SCISSOR_RECTS); + VGint oldRects[32*4]; + vgGetiv(VG_SCISSOR_RECTS, numRects, oldRects); + + // setup our new scissoring rects + VGint sRect[4]; + sRect[0] = rect.left(); + sRect[1] = rect.top(); + sRect[2] = rect.width(); + sRect[3] = rect.height(); + vgSeti(VG_SCISSORING, VG_TRUE); + vgSetiv(VG_SCISSOR_RECTS, 4, sRect); + */ + // setup root transform + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + vgLoadIdentity(); + vgTranslate(rect.left(), rect.top()); + + vgSeti(VG_COLOR_TRANSFORM, VG_FALSE); + vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER); + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL); + + // draw quads + for (int i = 0; i < mSortedQuads.size(); i++) + { + mSortedQuads[i]->draw(); + } + + // set back old scissor rects + // vgSeti(VG_SCISSORING, oldScissoring); + // vgSetiv(VG_SCISSOR_RECTS, numRects, oldRects); + + painter->endNativePainting(); + +} + +bool HgVgQuadRenderer::getQuadTranformedPoints(QPolygonF& points, int index) const +{ + for (int i = 0; i < mSortedQuads.count(); i++) + { + HgVgQuad* quad = mSortedQuads[i]; + if (quad->mQuad) + { + bool bOk; + if (quad->mQuad->userData().toInt(&bOk) == index) + { + quad->getTransformedPoints(points); + return true; + } + } + } + + return false; +} + +HgImage* HgVgQuadRenderer::createNativeImage() +{ + return new HgVgImage(this); +} + +HgVgImage* HgVgQuadRenderer::defaultImage() +{ + if (mDefaultVgImage == NULL) + { + QImage defaultImage(64,64,QImage::Format_RGB16); + defaultImage.fill(qRgb(255,0,0)); + mDefaultVgImage = static_cast(createNativeImage()); + mDefaultVgImage->setImage(defaultImage); + mDefaultVgImage->upload(true); + } + return mDefaultVgImage; +} + +HgImageFader* HgVgQuadRenderer::imageFader() +{ + return mImageFader; +} + +QList HgVgQuadRenderer::getVisibleQuads(const QRectF& rect) const +{ + FUNC_LOG; + + // this implementation isn't 100% precise + QList result; + for (int i = 0; i < mSortedQuads.count(); i++) { + QPolygonF poly; + mSortedQuads[i]->getTransformedPoints(poly); + QRectF bounds = poly.boundingRect(); + if (bounds.intersects(rect) || rect.contains(bounds)) { + result.append(mSortedQuads[i]->mQuad); + } + } + + return result; +} + + diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgwidgetitem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgwidgetitem.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,190 @@ +/* +* Copyright (c) 2009 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: +* +*/ +#include "hgwidgetitem.h" +#include "hgquadrenderer.h" +#include +#include +#include + +HgWidgetItem::HgWidgetItem(HgQuadRenderer* renderer): +mTitle(""), +mDescription(""), +mValidData(false), +mHgImage(NULL), +mRenderer(renderer) +{ +} + +HgWidgetItem::HgWidgetItem(HgQuadRenderer* renderer, QImage image, QString title, QString description ) : +mTitle(""), +mDescription(""), +mValidData(false), +mHgImage(NULL), +mRenderer(renderer), +mVisibility(true) +{ + Q_UNUSED(image) + setTitle(title); + setDescription(description); +} + +HgWidgetItem::~HgWidgetItem() +{ + releaseItemData(); + delete mHgImage; +} + +void HgWidgetItem::setImage( QImage image ) +{ + if (!mHgImage) + { + mHgImage = mRenderer->createNativeImage(); + } + mHgImage->setImage(image); + if (!mVisibility) + mHgImage->setAlpha(0); + +} + +void HgWidgetItem::setTitle( QString title ) +{ + mTitle = title; +} + +QString HgWidgetItem::title() const +{ + return mTitle; +} + +void HgWidgetItem::setDescription( QString description ) +{ + mDescription = description; +} + +QString HgWidgetItem::description() const +{ + return mDescription; +} + +void HgWidgetItem::setModelIndex(const QModelIndex& index) +{ + mModelIndex = index; +} + +QModelIndex HgWidgetItem::modelIndex() const +{ + return mModelIndex; +} + +bool HgWidgetItem::updateItemData() +{ + mValidData = false; + if( mModelIndex.isValid() ){ + QVariant image = mModelIndex.data(Qt::DecorationRole); + QVariant texts = mModelIndex.data(Qt::DisplayRole); + + QVariant vis = mModelIndex.data(HgWidget::HgVisibilityRole); + if (vis.canConvert()) + { + setVisibility(vis.toBool()); + } + + // Convert data to correct format if possible. + if(image.canConvert()){ + setImage(image.value()); + mValidData = true; + } + else if(image.canConvert()){ + // This is heavy operation but we need to support + // HbIcon too. + HbIcon hbIcon = image.value(); + if (!hbIcon.isNull()){ + QIcon &qicon = hbIcon.qicon(); + QList sizes = qicon.availableSizes(); + QSize size; + foreach(size, sizes){ + if (size.width() != 0 && size.height() != 0 ){ + QPixmap pixmap = qicon.pixmap(size); + if (!pixmap.isNull()){ + setImage(pixmap.toImage()); + mValidData = true; + } + break; + } + } + } + } + else if (image.canConvert()){ + // This is heavy operation but we need to support + // QIcon too. + QIcon tempIcon = image.value(); + QList sizes = tempIcon.availableSizes(); + QSize size; + foreach(size, sizes){ + if (size.width() != 0 && size.height() != 0 ){ + QPixmap pixmap = tempIcon.pixmap(size); + if (!pixmap.isNull()){ + setImage(pixmap.toImage()); + mValidData = true; + } + break; + } + } + } + if( texts.canConvert() ){ + QStringList list(texts.toStringList() ); + if( list.count() >= 2 ){ + setTitle(list.at(0)); + setDescription(list.at(1)); + mValidData = true; + } + } + + } + return mValidData; +} + +void HgWidgetItem::releaseItemData() +{ + mTitle = ""; + mDescription = ""; + mValidData = false; + if (mHgImage) + mHgImage->releaseImage(); +} + +bool HgWidgetItem::validData() const +{ + return mValidData; +} + +const HgImage* HgWidgetItem::image() const +{ + return mHgImage; +} + +void HgWidgetItem::setVisibility(bool visibility) +{ + mVisibility = visibility; + if (mHgImage) + { + if (!mVisibility) + mHgImage->setAlpha(0); + else + mHgImage->setAlpha(1); + } +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgwidgets.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgwidgets.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,325 @@ +/* +* Copyright (c) 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: +* +*/ + +#include +#include +#include +#include +#include +#include + +#include "hgwidgets_p.h" +#include "hgcontainer.h" +#include "hgwidgetitem.h" +#include "hgscrollbuffermanager.h" +#include "hgcoverflowcontainer.h" +#include "hggridcontainer.h" +#include "trace.h" + +HgWidget::HgWidget(HbWidgetPrivate* widgetPrivate, QGraphicsItem *parent ): + HbWidget(*widgetPrivate, parent) +{ + Q_D(HgWidget); + d->q_ptr = this; + + HbStyleLoader::registerFilePath(":/hgwidget.css"); + HbStyleLoader::registerFilePath(":/hgwidget.widgetml"); +} + +HgWidget::~HgWidget() +{ + HbStyleLoader::unregisterFilePath(":/hgwidget.css"); + HbStyleLoader::unregisterFilePath(":/hgwidget.widgetml"); +} + +/*! + Returns model that view is currently presenting. +*/ +QAbstractItemModel *HgWidget::model() const +{ + Q_D(const HgWidget); + return d->mModel; +} + +/*! + Sets the model to \a model and replaces current item prototype with \a prototype. + Ownership of the model is not taken. Ownership of the prototype is taken. + If no prototype has been passed, default prototype is used. + */ +void HgWidget::setModel(QAbstractItemModel *model ) +{ + Q_D(HgWidget); + d->setModel(model); +} + +void HgWidget::setSelectionModel(QItemSelectionModel *selectionModel) +{ + Q_D(HgWidget); + d->setSelectionModel(selectionModel); +} + +QItemSelectionModel *HgWidget::selectionModel() const +{ + Q_D(const HgWidget); + return d->selectionModel(); +} + +HgWidget::SelectionMode HgWidget::selectionMode() const +{ + Q_D(const HgWidget); + return d->selectionMode(); +} + +/*! + If newMode is not same as current selection mode of view, updates + selection mode and all viewitems. If resetSelection is true (the default), + it clears all existing selections. +*/ +void HgWidget::setSelectionMode(SelectionMode mode, bool resetSelection) +{ + Q_D(HgWidget); + d->setSelectionMode(mode, resetSelection); +} + +void HgWidget::selectAll() +{ + Q_D(HgWidget); + d->selectAll(); +} + +void HgWidget::clearSelection() +{ + Q_D(HgWidget); + d->clearSelection(); +} + +QModelIndex HgWidget::currentIndex() const +{ + Q_D(const HgWidget); + return d->currentIndex(); +} + +void HgWidget::setCurrentIndex( + const QModelIndex &index, QItemSelectionModel::SelectionFlags selectionFlag) +{ + Q_D(HgWidget); + d->setCurrentIndex(index, selectionFlag); +} + +void HgWidget::scrollTo(const QModelIndex &index) +{ + Q_D(HgWidget); + d->scrollTo(index); +} + +void HgWidget::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + Q_D( HgWidget); + // TODO,take columns into count + for( int i = topLeft.row(); i <= bottomRight.row(); i++ ){ + // if data for item outside our current buffer has changed + // we just have to ignore it since we dont have resources + // to handle it(or we dont want to waste resources). + if(d->mBufferManager->positionInsideBuffer(i)){ + HgWidgetItem* item = d->mContainer->itemByIndex( i ); + if( item ){ + item->updateItemData(); + } + } + } + d->mContainer->itemDataChanged( topLeft, bottomRight ); +} + +/*! + * Returns true if the scroll area handles + * long press gestures, false otherwise + * + * \sa HbScrollArea::setHandleLongPress() + */ +bool HgWidget::longPressEnabled() const +{ + Q_D( const HgWidget ); + + return d->mHandleLongPress; +} + +/*! + * Sets the value of the handleLongPress property. This value is set + * to true if the widget is to respond to long press gestures, false otherwise. + * + * The default value is false. + * + * \sa HbScrollArea::handleLongPress() + */ +void HgWidget::setLongPressEnabled (bool value) +{ + Q_D( HgWidget ); + + if (d->mHandleLongPress != value) + { + d->mHandleLongPress = value; + if (value) + { + grabGesture(Qt::TapAndHoldGesture); + } + else + { + ungrabGesture(Qt::TapAndHoldGesture); + } + } + + // TODO, should we do something like this????? +// if (isChanged) { +// d->updateGestures(); +// emit gestureSceneFilterChanged( d->mGestureFilter ); +// } +} + +HgWidget::ScrollBarPolicy HgWidget::scrollBarPolicy() const +{ + Q_D(const HgWidget); + return d->mScrollBarPolicy; +} + +/*! + Sets the policy for vertical scrollbar + + The default policy is HgWidget::ScrollBarAutoHide. + + \sa setHorizontalScrollBarPolicy(), verticalScrollBarPolicy() +*/ +void HgWidget::setScrollBarPolicy(ScrollBarPolicy policy) +{ + Q_D(HgWidget); + d->setScrollBarPolicy(policy); +} + +/*! + Returns the vertical scroll bar. + + \sa verticalScrollBarPolicy(), horizontalScrollBar() + */ +HbScrollBar *HgWidget::scrollBar() const +{ + Q_D(const HgWidget); + return d->mScrollBar; +} + +/*! + Replaces the existing vertical scroll bar with \a scrollBar. The former + scroll bar is deleted. + + HgWidget already provides vertical and horizontal scroll bars by + default. You can call this function to replace the default vertical + scroll bar with your own custom scroll bar. + + \sa verticalScrollBar(), setHorizontalScrollBar() +*/ +void HgWidget::setScrollBar(HbScrollBar *scrollBar) +{ + Q_D(HgWidget); + if (!scrollBar) { + qWarning("HgWidget::setVerticalScrollBar: Cannot set a null scroll bar"); + return; + } + + d->replaceScrollBar(scrollBar); +} + +bool HgWidget::eventFilter(QObject *obj,QEvent *event) +{ + Q_D(HgWidget); + switch (event->type() ) + { + case QEvent::ApplicationActivate: + { + d->gainedForeground(); + break; + } + case QEvent::ApplicationDeactivate: + { + d->lostForeground(); + break; + } + case QEvent::GraphicsSceneResize: + { + d->adjustGeometry(); + break; + } + default: + break; + } + return QObject::eventFilter(obj, event); +} + +bool HgWidget::event(QEvent *event) +{ + Q_D(HgWidget); + + bool value(false); + if (event){ + value = HbWidget::event(event); + if (event->type() == QEvent::GraphicsSceneResize){ + d->adjustGeometry(); + } + } + return value; +} + +bool HgWidget::getItemOutline(const QModelIndex& index, QPolygonF& points) +{ + Q_D(HgWidget); + + return d->getItemOutline(index, points); +} + +void HgWidget::aboutToChangeOrientation() +{ + +} + +void HgWidget::orientationChanged(Qt::Orientation orientation) +{ + Q_D(HgWidget); + d->orientationChanged(orientation); +} + +Qt::Orientation HgWidget::scrollDirection() const +{ + Q_D(const HgWidget); + return d->scrollDirection(); +} + +QList HgWidget::getVisibleItemIndices() const +{ + Q_D(const HgWidget); + return d->getVisibleItemIndices(); +} + +void HgWidget::setIndexFeedbackPolicy(IndexFeedbackPolicy policy) +{ + Q_D(HgWidget); + d->setIndexFeedbackPolicy(policy); +} + +HgWidget::IndexFeedbackPolicy HgWidget::indexFeedbackPolicy() const +{ + Q_D(const HgWidget); + return d->indexFeedbackPolicy(); +} + +// EOF diff -r 000000000000 -r 89c329efa980 ganeswidgets/src/hgwidgets_p.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/src/hgwidgets_p.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,693 @@ +/* +* Copyright (c) 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: +* +*/ + +#include +#include +#include +#include + +#include "hgwidgets_p.h" +#include "hgcontainer.h" +#include "hgcoverflowcontainer.h" +#include "hgscrollbuffermanager.h" +#include "hgwidgetitem.h" +#include "trace.h" +#include "hgindexfeedback.h" + +static const int INITIAL_SCROLLBAR_HIDE_TIMEOUT(4000); +static const int DEFAULT_BUFFER_SIZE(40); + +HgWidgetPrivate::HgWidgetPrivate() : + mLayout(0), + mContainer(0), + mBufferManager(0), + mModel(0), + mSelectionModel(0), + mDefaultSelectionModel(0), + mScrollBar(0), + mAbleToScroll(false), + mHandleLongPress(false), + mBufferSize(DEFAULT_BUFFER_SIZE) +{ + FUNC_LOG; +} + +HgWidgetPrivate::~HgWidgetPrivate() +{ + FUNC_LOG; + + delete mDefaultSelectionModel; + delete mBufferManager; +} + +void HgWidgetPrivate::init(HgContainer *container) +{ + FUNC_LOG; + Q_Q(HgWidget); + + mScrollBarHideTimer.setParent(q); + mScrollBarHideTimer.setSingleShot(true); + + q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + q->setFlag( QGraphicsItem::ItemClipsChildrenToShape, true ); + q->setFocusPolicy(Qt::StrongFocus); + + createScrollBar(container->orientation()); + + QObject::connect(&(mScrollBarHideTimer), SIGNAL(timeout()), q, SLOT(_q_hideScrollBars())); + + mContainer = container; + + mScrollBarPolicy = HgWidget::ScrollBarAutoHide; + + q->connect(mContainer, SIGNAL(scrollPositionChanged(qreal,bool)), + q, SLOT(_q_scrollPositionChanged(qreal,bool))); + q->connect(mContainer, SIGNAL(activated(const QModelIndex&)), + q, SIGNAL(activated(const QModelIndex&))); + q->connect(mContainer, SIGNAL(longPressed(const QModelIndex&, const QPointF &)), + q, SIGNAL(longPressed(const QModelIndex&, const QPointF &))); + q->connect(mContainer, SIGNAL(scrollingStarted()), q, SIGNAL(scrollingStarted())); + q->connect(mContainer, SIGNAL(scrollingEnded()), q, SIGNAL(scrollingEnded())); + + mIndexFeedback = new HgIndexFeedback(q); + mIndexFeedback->setWidget(q); + +} + +void HgWidgetPrivate::setModel( QAbstractItemModel *model ) +{ + FUNC_LOG; + + if (model != mModel) { + clearCurrentModel(); + mModel = model; + initializeNewModel(); + } +} + +void HgWidgetPrivate::setSelectionModel(QItemSelectionModel *selectionModel) +{ + FUNC_LOG; + + Q_Q(HgWidget); + + if (mContainer) { + if (selectionModel == 0) { + QItemSelectionModel *oldSelectionModel = mDefaultSelectionModel; + mDefaultSelectionModel = 0; + mDefaultSelectionModel = new QItemSelectionModel(mModel); + mContainer->setSelectionModel(mDefaultSelectionModel); + delete oldSelectionModel; + } + else if (selectionModel != mContainer->selectionModel()) { + QItemSelectionModel *oldSelectionModel = mDefaultSelectionModel; + mDefaultSelectionModel = 0; + mContainer->setSelectionModel(selectionModel); + delete oldSelectionModel; + } + if (mContainer->selectionModel()) { + if (mIndexFeedback) { + delete mIndexFeedback; + mIndexFeedback = 0; + } + mIndexFeedback = new HgIndexFeedback(q); + mIndexFeedback->setWidget(q); + } + } +} + +QItemSelectionModel *HgWidgetPrivate::selectionModel() const +{ + FUNC_LOG; + + if (mContainer) { + return mContainer->selectionModel(); + } + return 0; +} + +HgWidget::SelectionMode HgWidgetPrivate::selectionMode() const +{ + FUNC_LOG; + + if (mContainer) { + return mContainer->selectionMode(); + } + return HgWidget::NoSelection; +} + +void HgWidgetPrivate::setSelectionMode(HgWidget::SelectionMode mode, bool resetSelection) +{ + FUNC_LOG; + + if (mContainer) { + mContainer->setSelectionMode(mode, resetSelection); + } +} + +void HgWidgetPrivate::selectAll() +{ + FUNC_LOG; + Q_Q(HgWidget); + + if (mContainer && + (mContainer->selectionMode() == HgWidget::MultiSelection || + mContainer->selectionMode() == HgWidget::ContiguousSelection) && + mModel && mModel->columnCount() > 0 && mModel->rowCount() > 0) { + QItemSelection selection( + mModel->index(0, 0), + mModel->index(mModel->rowCount()-1, mModel->columnCount()-1)); + mContainer->selectionModel()->select(selection, QItemSelectionModel::Select); + q->update(); + } +} + +void HgWidgetPrivate::clearSelection() +{ + FUNC_LOG; + Q_Q(HgWidget); + + if (mContainer) { + mContainer->selectionModel()->clearSelection(); + q->update(); + } +} + +QModelIndex HgWidgetPrivate::currentIndex() const +{ + FUNC_LOG; + + if (mContainer && mContainer->selectionModel()) { + return mContainer->selectionModel()->currentIndex(); + } + return QModelIndex(); +} + +void HgWidgetPrivate::setCurrentIndex( + const QModelIndex &index, QItemSelectionModel::SelectionFlags selectionFlag) +{ + FUNC_LOG; + + if (mContainer && mContainer->selectionModel()) { + mContainer->selectionModel()->setCurrentIndex(index, selectionFlag); + } +} + +void HgWidgetPrivate::scrollTo(const QModelIndex &index) +{ + FUNC_LOG; + + if (index.isValid()) { + if (mContainer) { + mContainer->scrollTo(index); + } + if (mBufferManager) { + mBufferManager->scrollPositionChanged(index.row()); + } + } +} + +void HgWidgetPrivate::initializeNewModel() +{ + FUNC_LOG; + Q_Q(HgWidget); + + if (mModel) { + // These asserts do basic sanity checking of the model + Q_ASSERT_X(mModel->index(0,0) == mModel->index(0,0), + "HbAbstractItemView::setModel", + "A model should return the exact same index " + "(including its internal id/pointer) when asked for it twice in a row."); + Q_ASSERT_X(mModel->index(0,0).parent() == QModelIndex(), + "HbAbstractItemView::setModel", + "The parent of a top level index should be invalid"); + + q->connect(mModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + SLOT( dataChanged(QModelIndex,QModelIndex))); + q->connect(mModel, SIGNAL(rowsInserted(QModelIndex, int, int)), + SLOT(_q_insertRows(QModelIndex, int, int))); + q->connect(mModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), + SLOT(_q_removeRows(QModelIndex, int, int))); + q->connect(mModel, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)), + SLOT(_q_moveRows(QModelIndex, int, int, QModelIndex, int))); + + mContainer->setItemCount(mModel->rowCount(QModelIndex())); + QList items = mContainer->items(); + + // set model indexes for the items firsts + int itemCount = items.count(); + for( int i=0; isetModelIndex(mModel->index(i, 0, QModelIndex())); + } + + if( mBufferManager ) + { + delete mBufferManager; + mBufferManager = 0; + } + + mBufferManager = new HgScrollBufferManager(mBufferSize,mBufferSize/4,0,itemCount); + q->connect( mBufferManager, SIGNAL(releaseItems(int,int)), q, SLOT(_q_releaseItems(int,int))); + q->connect( mBufferManager, SIGNAL(requestItems(int,int)), q, SLOT(_q_requestItems(int,int))); + mBufferManager->resetBuffer(0, itemCount); + + setSelectionModel(0); // Default + + if (mModel->rowCount() > 0) + { + setCurrentIndex(mModel->index(0, 0)); + scrollTo(mModel->index(0, 0)); + } + } +} + +void HgWidgetPrivate::clearCurrentModel() +{ + FUNC_LOG; + Q_Q(HgWidget); + + if (mModel) { + mModel->disconnect(q, SLOT(dataChanged(QModelIndex, QModelIndex))); + mModel->disconnect(q, SLOT(_q_insertRows(QModelIndex, int, int))); + mModel->disconnect(q, SLOT(_q_removeRows(QModelIndex, int, int))); + mModel->disconnect(q, SLOT(_q_moveRows(QModelIndex, int, int, QModelIndex, int))); + mModel = 0; + } + +// TODO: setSelectionModel(0); + +} +void HgWidgetPrivate::_q_releaseItems( int releaseStart, int releaseEnd ) +{ + FUNC_LOG; + + QList items = mContainer->items(); + const int itemCount = items.count(); + + int start = qBound(0, releaseStart, itemCount-1); + int end = qBound(0, releaseEnd, itemCount-1); + + INFO("Release items:" << start << "-" << end); + // request data for items + for (int i = start; i <= end; i++) { + HgWidgetItem* item = items.at(i); + if (item) { + item->releaseItemData(); + } + } +} + +void HgWidgetPrivate::_q_requestItems(int requestStart, int requestEnd) +{ + FUNC_LOG; + + QList items = mContainer->items(); + const int itemCount = items.count(); + + int start = qBound(0, requestStart, itemCount-1); + int end = qBound(0, requestEnd, itemCount-1); + + // variables to track which items are really updated. + int firstUpdated = -1; + int lastUpdated = -1; + + INFO("Request items:" << start << "-" << end); + // request data for items + for (int i = start; i <= end; i++) { + HgWidgetItem* item = items.at(i); + if (item && item->updateItemData()) { + if (firstUpdated == -1) firstUpdated = i; + lastUpdated = i; + } + } + + // notify container which items have updated data available. + // container is responsible to redraw view if some of the items + // is visible. + if (firstUpdated != -1 && lastUpdated != -1) { + mContainer->itemDataChanged(firstUpdated, lastUpdated); + } +} + +void HgWidgetPrivate::_q_scrollPositionChanged(qreal index,bool scrollBarAnimation) +{ + int newPos = index; + newPos *= mContainer->rowCount(); + if (mBufferManager) { + mBufferManager->scrollPositionChanged(newPos); + } + + if (!scrollBarAnimation) + updateScrollMetrics(index); +} + +void HgWidgetPrivate::replaceScrollBar(HbScrollBar *scrollBar) +{ + Q_Q(HgWidget); + delete mScrollBar; + mScrollBar = scrollBar; + + scrollBar->setParentItem(q); + + // make sure the scrollbar is on top + scrollBar->setZValue(q->zValue() + 1); + + prepareScrollBars(); + + QObject::connect(scrollBar, SIGNAL(valueChanged(qreal, Qt::Orientation)), q, SLOT(_q_thumbPositionChanged(qreal, Qt::Orientation))); +} + +void HgWidgetPrivate::prepareScrollBars( qreal pos ) +{ + Q_Q( HgWidget ); + + QRectF boundingRect = q->boundingRect(); + + bool scrollBarsVisible(false); + + if ((mAbleToScroll && mScrollBarPolicy != HgWidget::ScrollBarAlwaysOff) || + mScrollBarPolicy == HgWidget::ScrollBarAlwaysOn) { + + displayScrollBar(pos ); + scrollBarsVisible = true; + } + else if((!mAbleToScroll || mScrollBarPolicy == HgWidget::ScrollBarAlwaysOff) + && mScrollBar->isVisible()){ + mScrollBar->setVisible(false); + } + + if (scrollBarsVisible && !mScrollBarHideTimer.isActive()) { + mScrollBarHideTimer.start(INITIAL_SCROLLBAR_HIDE_TIMEOUT); + } +} + +void HgWidgetPrivate::displayScrollBar(qreal pos) +{ + Q_Q(HgWidget); + // Layout the scrollbar + setScrollBarMetrics(pos); + + // Activate the scrollbar + if ( !mScrollBar->isVisible() && q->isVisible()) { + mScrollBar->setVisible(true); + } +} + +void HgWidgetPrivate::setScrollBarPolicy(HgWidget::ScrollBarPolicy policy) +{ + mScrollBarPolicy = policy; + + if (mScrollBarPolicy == HgWidget::ScrollBarAlwaysOff && + mScrollBar->isVisible()){ + mScrollBar->setVisible(false); + } + + if(policy != HgWidget::ScrollBarAlwaysOff){ + updateScrollMetrics(); + } +} + +void HgWidgetPrivate::_q_hideScrollBars() +{ + if (mScrollBar && mScrollBarPolicy == HgWidget::ScrollBarAutoHide) { + + // TODO, do we need to know if scrollbar was pressed? we cannot access the private methods, since + // only scrollareaprivate is a friend class. + if (false/*scrollBarPressed(mHorizontalScrollBar) || + scrollBarPressed(mVerticalScrollBar)*/) { + mScrollBarHideTimer.start(); + } else if(mScrollBarPolicy != HgWidget::ScrollBarAlwaysOn + && mScrollBar->isVisible()){ + mScrollBar->setVisible(false); + + } + } +} + +/** + * + */ +void HgWidgetPrivate::_q_thumbPositionChanged(qreal value, Qt::Orientation orientation) +{ + Q_UNUSED(orientation) + + mContainer->scrollToPosition( value, true ); + + // TODO, stop all scrolling and animations + + if (mScrollBarHideTimer.isActive()) { + mScrollBarHideTimer.stop(); + mScrollBarHideTimer.start(); + } +} + +void HgWidgetPrivate::_q_insertRows(const QModelIndex &parent, int start, int end) +{ + FUNC_LOG; + INFO("Insert rows" << start << "-" << end); + Q_UNUSED(parent) + Q_Q(HgWidget); + + if (mContainer) { + mContainer->addItems(start, end); + // re-set model indexes for the items including and after the added indexes + QList items = mContainer->items(); + int newItemCount = items.count(); + for (int i = start; i < newItemCount; i++) { + items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); + } + mBufferManager->addItems(start, end, newItemCount); + q->update(); + } +} + +void HgWidgetPrivate::_q_removeRows(const QModelIndex &parent, int start, int end) +{ + FUNC_LOG; + INFO("Remove rows" << start << "-" << end); + Q_UNUSED(parent) + Q_Q(HgWidget); + + if (mContainer && mBufferManager) { + mContainer->removeItems(start, end); + // re-set model indexes for the items after the removed indexes + QList items = mContainer->items(); + int newItemCount = items.count(); + for (int i = start; i < newItemCount; i++) { + items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); + } + mBufferManager->removeItems(start, end, newItemCount); + q->update(); + } +} + +void HgWidgetPrivate::_q_moveRows(const QModelIndex &sourceParent, + int sourceStart, int sourceEnd, + const QModelIndex &destinationParent, int destinationRow) +{ + FUNC_LOG; + INFO("Move rows" << sourceStart << "-" << sourceEnd << "to" << destinationRow); + Q_UNUSED(sourceParent) + Q_UNUSED(destinationParent) + Q_Q(HgWidget); + + if (mContainer) { + mContainer->moveItems(sourceStart, sourceEnd, destinationRow); + // re-set model indexes for the items after the removed indexes + QList items = mContainer->items(); + int itemCount = items.count(); + for (int i = qMin(sourceStart, destinationRow); i < itemCount; i++) { + items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); + } + mBufferManager->moveItems(sourceStart, sourceEnd, destinationRow, itemCount); + q->update(); + } +} + +void HgWidgetPrivate::setScrollBarMetrics(qreal pos) +{ + Q_Q( HgWidget ); + + if (!mContainer) + return; + + qreal screenSize, worldSize; + mContainer->dimensions(screenSize,worldSize); + + const qreal start(0.0); + const qreal end(1.0); + const qreal page(screenSize/worldSize); + + // Set handle size + mScrollBar->setPageSize( qBound(start,page,end ) ); + + updateScrollBar(pos); +} + +void HgWidgetPrivate::updateScrollBar(qreal pos) +{ + Q_Q( HgWidget ); + + if (pos < 0.0) + pos = 0.0; + else if (pos > 1.0) + pos = 1.0; + // The scrollbar "thumb" position is the current position of the contents widget divided + // by the difference between the height of the contents widget and the height of the scroll area. + // This formula assumes that the "thumb" of the the scroll bar is sized proportionately to + // the height of the contents widget. + mScrollBar->setValue(pos); +} + +/* + * updateScrollMetrics() is a private function called when + * scrolling starts to set the metrics needed in scrolling. + */ +void HgWidgetPrivate::updateScrollMetrics( qreal pos) +{ + Q_Q(HgWidget); + + QRectF scrollAreaBoundingRect = q->boundingRect(); + + if (!mContainer || scrollAreaBoundingRect.isNull() || + !scrollAreaBoundingRect.isValid()) + return; + + qreal screenSize, worldSize; + mContainer->dimensions(screenSize,worldSize); + + mAbleToScroll = false; + if (worldSize > screenSize) { + mAbleToScroll = true; + } + + prepareScrollBars( pos/worldSize ); +} + +void HgWidgetPrivate::adjustGeometry() +{ + Q_Q(HgWidget); + + QRectF scrollAreaBoundingRect = q->boundingRect(); + if( scrollAreaBoundingRect.isNull() || + !scrollAreaBoundingRect.isValid() || + !mContainer || + scrollAreaBoundingRect == mContainer->boundingRect() ) + return; + + mContainer->resize(scrollAreaBoundingRect.size()); + + updateScrollMetrics(0); +} + + +void HgWidgetPrivate::lostForeground() +{ + if( !mForeground ) return; + + mForeground = false; + QList list = mContainer->items(); + foreach(HgWidgetItem* item, list){ + item->releaseItemData(); + } +} + +void HgWidgetPrivate::gainedForeground() +{ + if( mForeground ) return; + + mForeground = true; + QList list = mContainer->items(); + int bufferStart = 0; + int bufferEnd = 0; + mBufferManager->currentBuffer(bufferStart,bufferEnd); + for(;bufferStart<=bufferEnd;bufferStart++){ + list.at(bufferStart)->updateItemData(); + } +} + +bool HgWidgetPrivate::getItemOutline(const QModelIndex& index, QPolygonF& points) +{ + return mContainer->getItemPoints(index.row(), points); +} + +void HgWidgetPrivate::aboutToChangeOrientation() +{ + +} + +void HgWidgetPrivate::orientationChanged(Qt::Orientation orientation) +{ + Q_Q(HgWidget); + if (mContainer->orientation() != orientation) { + createScrollBar(orientation); + q->repolish(); + mContainer->setOrientation(orientation); + adjustGeometry(); + } +} + +void HgWidgetPrivate::_q_groovePressed(qreal value, Qt::Orientation orientation) +{ + Q_UNUSED(value); + Q_UNUSED(orientation); +} + +Qt::Orientation HgWidgetPrivate::scrollDirection() const +{ + return mContainer->orientation(); +} + +void HgWidgetPrivate::createScrollBar(Qt::Orientation orientation) +{ + Q_Q(HgWidget); + + delete mScrollBar; + mScrollBar = 0; + mScrollBar = new HbScrollBar(orientation,q); + if (orientation == Qt::Vertical) { + HbStyle::setItemName(mScrollBar, "scrollbar-vertical"); + } + else { + HbStyle::setItemName(mScrollBar, "scrollbar-horizontal"); + } + + mScrollBar->setZValue(q->zValue() + 1); + QObject::connect(mScrollBar, SIGNAL(valueChanged(qreal, Qt::Orientation)), + q, SLOT(_q_thumbPositionChanged(qreal, Qt::Orientation))); + QObject::connect(mScrollBar, SIGNAL(valueChangeRequested(qreal, Qt::Orientation)), + q, SLOT(_q_groovePressed(qreal, Qt::Orientation))); + mScrollBar->setVisible(false); +} + +QList HgWidgetPrivate::getVisibleItemIndices() const +{ + return mContainer->getVisibleItemIndices(); +} + +void HgWidgetPrivate::setIndexFeedbackPolicy( HgWidget::IndexFeedbackPolicy policy) +{ + mIndexFeedback->setIndexFeedbackPolicy(policy); +} + +HgWidget::IndexFeedbackPolicy HgWidgetPrivate::indexFeedbackPolicy() const +{ + return mIndexFeedback->indexFeedbackPolicy(); +} + +#include "moc_hgwidgets.cpp" diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/data/hgwidgettest.qrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/data/hgwidgettest.qrc Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,5 @@ + + + images/default.svg + + diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/data/images/default.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/data/images/default.svg Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/hgwidgettest.pro --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/hgwidgettest.pro Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,46 @@ +# Copyright (c) 2009 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: + + +TEMPLATE = app +CONFIG += hb +TARGET = hgwidgettest +DEPENDPATH += . +INCLUDEPATH += . +INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE $$APP_LAYER_SYSTEMINCLUDE +TARGET.CAPABILITY = All -TCB + +INCLUDEPATH += /sf/mw/hb/src/hbwidgets/itemviews /sf/mw/hb/src/hbcore/gui + +symbian { + TARGET.EPOCHEAPSIZE = 0x10000 0x2000000 + BLD_INF_RULES.prj_exports += "rom/hgwidgettest.iby CORE_APP_LAYER_IBY_EXPORT_PATH(hgwidgettest.iby)" \ + "rom/hgwidgettestresource.iby LANGUAGE_APP_LAYER_IBY_EXPORT_PATH(hgwidgettestresource.iby)" +} + +SOURCES += src/main.cpp \ + src/hgwidgettestdatamodel.cpp \ + src/hgwidgettestalbumartmanager.cpp \ + src/hgwidgettestview.cpp \ + src/hgtestview.cpp \ + src/hgselectiondialog.cpp \ + src/hgflipwidget.cpp +HEADERS += inc/hgwidgettestdatamodel.h \ + inc/hgwidgettestalbumartmanager.h \ + inc/hgwidgettestview.h \ + inc/hgtestview.h \ + inc/hgselectiondialog.h \ + inc/hgflipwidget.h +LIBS += -lganeswidgets.dll \ + -lthumbnailmanagerqt.dll + +RESOURCES += data/hgwidgettest.qrc + diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgflipwidget.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgflipwidget.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,65 @@ +/* +* Copyright (c) 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: Another view for test application. +* +*/ +#ifndef HGFLIPWIDGET_H_ +#define HGFLIPWIDGET_H_ + +#include +#include + +class HbAction; +class HbLabel; +class QPropertyAnimation; + +class HgFlipWidget : public HbWidget +{ + Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation) + Q_OBJECT +public: + enum State + { + StateClosed, + StateOpening1, + StateOpening2, + StateOpened, + StateClosing1, + StateClosing2 + }; + + HgFlipWidget(const QString &title1, const QString &title2, const QPixmap &pixmap, QGraphicsItem *parent=0); + + qreal yRotation(); + void setYRotation(qreal a); + + void close(); +signals: + void closed(); +private slots: + void animationFinished(); + void buttonClicked(bool checked=false); +private: + void resizeEvent(QGraphicsSceneResizeEvent *event); + void togglePage(); +private: + QPixmap mPixmap; + HbStackedWidget *mStack; + qreal mYRotation; + QPropertyAnimation* mAnimation; + State mState; + HbLabel* mIconLabel; +}; + +#endif /* HGTESTVIEW_H_ */ diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgselectiondialog.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgselectiondialog.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,46 @@ +/* +* Copyright (c) 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: Multiselection dialog +* +*/ + +#ifndef HGSELECTIONDIALOG_H +#define HGSELECTIONDIALOG_H + +#include + +class HbPushButton; +class HbLabel; +class HgWidget; + +class HgSelectionDialog : public HbDialog +{ + Q_OBJECT + Q_DISABLE_COPY(HgSelectionDialog) + +public: + HgSelectionDialog(const QString &title, const QString &primaryText, HgWidget *content, QGraphicsItem *parent=0); + ~HgSelectionDialog(); + +private slots: + void updateItems(); + void selectAll(); + +private: + HgWidget *mHgWidget; + HbPushButton *mSelectAll; + HbLabel *mCountLabel; +}; + +#endif //HGSELECTIONDIALOG_H diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgtestview.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgtestview.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,44 @@ +/* +* Copyright (c) 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: Another view for test application. +* +*/ +#ifndef HGTESTVIEW_H_ +#define HGTESTVIEW_H_ + +#include + +class HbAction; +class HbLabel; + +class HgTestView : public HbView +{ + Q_OBJECT + +public: + HgTestView(const QString &title1, const QString &title2, const QPixmap &pixmap, QGraphicsItem *parent=0); + +private slots: + void closeView(); + +private: + void resizeEvent(QGraphicsSceneResizeEvent *event); + +private: + HbAction *mBackAction; + HbLabel *mIconLabel; + QPixmap mPixmap; +}; + +#endif /* HGTESTVIEW_H_ */ diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgwidgettestalbumartmanager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgwidgettestalbumartmanager.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2009 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: +* +*/ + + +#ifndef HGWIDGETTESTALBUMARTMANAGER_H +#define HGWIDGETTESTALBUMARTMANAGER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class HgWidgetTestAlbumArtManager : public QObject +{ + Q_OBJECT + +public: + + explicit HgWidgetTestAlbumArtManager(QObject *parent=0); + virtual ~HgWidgetTestAlbumArtManager(); + + void setThumbnailSize(ThumbnailManager::ThumbnailSize size); + + QImage albumArt( const QString &albumArtUri, int index ); + bool cacheAlbumArt( const QStringList albumArtList ); + void cancel(); + +signals: + + void albumArtReady( int index ); + void albumCacheReady(); + +public slots: + + void thumbnailReady( const QPixmap& pixmap, void *data, int id, int error ); + void thumbnailReady( const QImage& image, void* data, int id, int error ); + void executeNext(); + +private: + + void applyMask( QPixmap &pixmap ); + +private: + + ThumbnailManager *mThumbnailManager; + QHash mImageCache; + QMap mTnmReqMap; + bool mCachingInProgress; + + QQueue< QPair > mRequestQueue; + int mRequestCount; + QBitmap mMask; + +}; + +#endif // HGWIDGETTESTALBUMARTMANAGER_H + diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgwidgettestdatamodel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgwidgettestdatamodel.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,81 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGWIDGETTESTDATAMODEL_H +#define HGWIDGETTESTDATAMODEL_H + +#include +#include +#include +#include +#include + +class HgWidgetTestAlbumArtManager; + + +class HgWidgetTestDataModel : public QAbstractListModel +{ + Q_OBJECT + +public: + + explicit HgWidgetTestDataModel(QObject *parent=0); + virtual ~HgWidgetTestDataModel(); + + void setThumbnailSize(ThumbnailManager::ThumbnailSize size); + + int rowCount(const QModelIndex &parent=QModelIndex()) const; + QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const; + bool setData(const QModelIndex& index, const QVariant& value, int role=Qt::EditRole); + + void refreshModel(); + + void remove(const QItemSelection &selection); + void move(const QItemSelection &selection, const QModelIndex &target); + void add(const QModelIndex &target, int count); + + enum ImageType{TypeQIcon, TypeHbIcon, TypeQImage}; + + void setImageDataType(ImageType type); + + void enableLowResImages(bool enabled); + bool lowResImagesEnabled() const; + +private: + + void init(); + +public slots: + + void updateAlbumArt( int index ); + void albumCacheReady(); + +private: + + HgWidgetTestAlbumArtManager *mAlbumArtManager; // Own + bool mCachingInProgress; + QStringList mFiles; + ImageType mImageType; + HbIcon mHbIcon; + QIcon mQIcon; + QImage mDefaultIcon; + QList mVisibility; + bool mUseLowResImages; +}; + +#endif // HgWidgetTestDataModel_H + diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgwidgettestview.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/inc/hgwidgettestview.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,100 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGWIDGETTESTVIEW_H_ +#define HGWIDGETTESTVIEW_H_ + +#include +#include + +class HbAction; +class QGraphicsLinearLayout; +class HgWidgetTestDataModel; +class HbListWidget; +class HgFlipWidget; +class HbLabel; + +class HgWidgetTestView : public HbView +{ + Q_OBJECT + +public: + + HgWidgetTestView(QGraphicsItem *parent = 0); + ~HgWidgetTestView(); + +private slots: + + void switchWidget(HbAction* action); + void toggleScrollDirection(); + void openDialog(const QModelIndex &index); + void openView(const QModelIndex& index); + void openDeleteItemsDialog(); + void openMoveItemsDialog(); + void openAddItemsDialog(); + void autoHideScrollBar(); + void scrollBarAlwaysOn(); + void scrollBarAlwaysOff(); + void interactiveScrollBar(); + void unInteractiveScrollBar(); + void feedqimages(); + void feedqicons(); + void feedhbicons(); + void flipClosed(); + void orientationChanged(); + void onScrollingStarted(); + void onScrollingEnded(); + void setDescriptionAboveImage(); + void setDescriptionBelowImage(); + void setDescriptionHidden(); + void setTitleAboveImage(); + void setTitleBelowImage(); + void setTitleHidden(); + void toggleLowResForCoverflow(); + +private: + + enum WidgetType { + HgWidgetGrid, + HgWidgetCoverflow + }; + + void createMenu(); + void initWidget( WidgetType type ); + void setScrollBarPolicy( HgWidget::ScrollBarPolicy policy ); + void setScrollBarInteractive( bool value ); + HgWidget *createWidget(WidgetType type) const; + HgWidget *copyWidget() const; + +private: // data + + HgWidget *mWidget; + QGraphicsLinearLayout *mLayout; + HgWidgetTestDataModel *mModel; + WidgetType mWidgetType; + HbListWidget *mListWidget; + bool mToggleOrientation; + bool mTBone; + QItemSelectionModel *mSelectionModel; + HgFlipWidget* mFlipWidget; + QModelIndex mFlippedIndex; + HbLabel* mFrontItem; + HbAction* mUseLowResAction; +}; + + +#endif /* HGWIDGETTESTVIEW_H_ */ diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/inc/trace.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/inc/trace.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,147 @@ +/* +* Copyright (c) 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: Tracing macros, 2nd generation +* +*/ + +#ifndef TRACE_H +#define TRACE_H + +#include + +//----------------------------------------------------------------------------- +// Trace definitions +//----------------------------------------------------------------------------- +// + +/** +* Error trace enabled +*/ +//#ifdef _DEBUG +#ifdef __WINS__ + #define ERROR_TRACE + #define TIMESTAMP_TRACE + #define FUNC_TRACE + #define INFO_TRACE +#else + #undef ERROR_TRACE + #undef TIMESTAMP_TRACE + #undef FUNC_TRACE + #undef INFO_TRACE +#endif + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- +// + +/** +* Trace prefixes for macros with component name. +*/ +#define _TRACE_PREFIX "[TEST]:" + +/** +* Prefix error trace +*/ +#define _ERROR_PREFIX _TRACE_PREFIX " [ERROR]:" + +/** +* Prefix info trace. +*/ +#define _INFO_PREFIX _TRACE_PREFIX " [INFO]:" + +/** +* Prefix timestamp trace. +*/ +#define _TIMESTAMP_PREFIX _TRACE_PREFIX " [TIMESTAMP]:" + +//----------------------------------------------------------------------------- +// Error trace macros +// Usage: wrap traces in ERROR() macro to allow disabling them in release builds. +// Use normal stream object operations. +// Examples: +// ERROR( "xxx failed" ); +// ERROR( "Test trace arg =" << 999 << "arg2 =" << title() ); +//----------------------------------------------------------------------------- +// +#ifdef ERROR_TRACE + #define ERROR(trace) {qDebug() << _ERROR_PREFIX << trace;} + #define ERROR_PARAM(param) param + #define HANDLE_ERROR(trace) {ERROR(trace); __BREAKPOINT();} + #define HANDLE_ERROR_BOOL(x) {if (!x) {ERROR(#x << "is false"); __BREAKPOINT();}} + #define HANDLE_ERROR_NULL(x) {if (!x) {ERROR(#x << "is NULL"); __BREAKPOINT();}} + #define HANDLE_ERROR_NEG(x) {if (x < 0) {ERROR(#x << "=" << x << "File:" << __FILE__ << ", line:" << __LINE__); __BREAKPOINT();}} + #define CHECK_ERROR(err, trace) {if (err < 0) ERROR(trace << err);} +#else //ERROR_TRACE not defined + #define ERROR(trace) + #define ERROR_PARAM(param) + #define HANDLE_ERROR(trace) + #define HANDLE_ERROR_BOOL(x) + #define HANDLE_ERROR_NULL(x) + #define HANDLE_ERROR_NEG(x) + #define CHECK_ERROR(err,trace) +#endif //ERROR_TRACE + +//----------------------------------------------------------------------------- +// Info trace macros +// Usage: wrap traces in INFO() macro to allow disabling them in release builds. +// Use normal stream object operations. +// Examples: +// INFO( "Test trace" ); +// INFO( "Test trace arg =" << 999 << "arg2 =" << title() ); +//----------------------------------------------------------------------------- +// +#ifdef INFO_TRACE + #define INFO(trace) {qDebug() << _INFO_PREFIX << trace;} + #define INFO_PARAM(param) param +#else //INFO_TRACE not defined + #define INFO(trace) + #define INFO_PARAM(param) +#endif //INFO_TRACE + +//----------------------------------------------------------------------------- +// Function trace macros +//----------------------------------------------------------------------------- +// +#ifdef FUNC_TRACE + + class FuncLog + { + public: + inline FuncLog( const char* func ) : m_func( func ) + { qDebug() << _TRACE_PREFIX << m_func << "-START"; } + inline ~FuncLog() { qDebug() << _TRACE_PREFIX << m_func << "-END"; } + private: // Data + QString m_func; + }; + + #define FUNC_LOG FuncLog _fl( __PRETTY_FUNCTION__ ); +#else //FUNC_TRACE not defined + #define FUNC_LOG +#endif //FUNC_TRACE + +//----------------------------------------------------------------------------- +// Timestamp trace macros +//----------------------------------------------------------------------------- +// +#ifdef TIMESTAMP_TRACE + #include + #define TIMESTAMP(trace)\ + {qDebug() << _TIMESTAMP_PREFIX << "(" << \ + QTime::currentTime().toString("HH:mm:ss:zzz") << ")" << trace;} +#else //TIMESTAMP_TRACE not defined + #define TIMESTAMP(trace) +#endif //TIMESTAMP_TRACE + +#endif // TRACE_H diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/rom/hgwidgettest.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/rom/hgwidgettest.iby Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,26 @@ +/* +* Copyright (c) 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: ROM include file for test application. +* +*/ + +#ifndef __HGWIDGETTEST_IBY__ +#define __HGWIDGETTEST_IBY__ + +#include + +file=ABI_DIR\BUILD_DIR\hgwidgettest.exe \sys\bin\hgwidgettest.exe +data=DATAZ_\private\10003a3f\import\apps\hgwidgettest_reg.rsc \private\10003a3f\import\apps\hgwidgettest_reg.rsc + +#endif // __HGWIDGETTEST_IBY__ diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/rom/hgwidgettestresource.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/rom/hgwidgettestresource.iby Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,25 @@ +/* +* Copyright (c) 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: ROM include file for test application. +* +*/ + +#ifndef __HGWIDGETTESTRESOURCE_IBY__ +#define __HGWIDGETTESTRESOURCE_IBY__ + +#include + +S60_APP_RESOURCE(hgwidgettest) + +#endif // __HGWIDGETTESTRESOURCE_IBY__ diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/sis/hgwidgettest.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/sis/hgwidgettest.pkg Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,39 @@ +; Copyright (c) 2009 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: pkg file for ganeswidgets and test application + +; Language +&EN + +; SIS header: name, uid, version +#{"hgwidgettest"},(0xE321b788),1,0,0 + +; Localised Vendor name +%{"Vendor"} + +; Unique Vendor name +:"Vendor" + +; Manual PKG pre-rules from PRO files +; Default HW/platform dependencies +[0x101F7961],0,0,0,{"S60ProductID"} +[0x102032BE],0,0,0,{"S60ProductID"} +[0x102752AE],0,0,0,{"S60ProductID"} +[0x1028315F],0,0,0,{"S60ProductID"} + +; Default dependency to Qt libraries +(0x2001E61C), 4, 5, 2, {"Qt"} + +; Executable and default resource files +"/epoc32/release/$(PLATFORM)/$(TARGET)/hgwidgettest.exe" - "!:\sys\bin\hgwidgettest.exe" +"/epoc32/data/z/resource/apps/hgwidgettest.rsc" - "!:\resource\apps\hgwidgettest.rsc" +"/epoc32/data/z/private/10003a3f/import/apps/hgwidgettest_reg.rsc" - "!:\private\10003a3f\import\apps\hgwidgettest_reg.rsc" + +; Manual PKG post-rules from PRO files diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/src/hgflipwidget.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/src/hgflipwidget.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,178 @@ +/* +* Copyright (c) 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: Another view for test application. +* +*/ +#include "hgflipwidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "trace.h" + +HgFlipWidget::HgFlipWidget(const QString &title1, const QString &title2, const QPixmap &pixmap, QGraphicsItem *parent) : + HbWidget(parent), mPixmap(pixmap), mYRotation(0) +{ + FUNC_LOG; + + Q_UNUSED(title1) + Q_UNUSED(title2) + + mStack = new HbStackedWidget(); + + HbWidget* front = new HbWidget(); + { + QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical); + mIconLabel = new HbLabel; + HANDLE_ERROR_NULL(mIconLabel); + if (mIconLabel) + { + mIconLabel->setIcon(HbIcon(mPixmap)); + mIconLabel->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + layout->setContentsMargins(0,0,0,0); + layout->addItem(mIconLabel); + } + front->setLayout(layout); + } + + HbWidget* back = new HbWidget(); + { + QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical); + HbListWidget* widget = new HbListWidget; + widget->addItem(QString("1. First item")); + widget->addItem(QString("2. Second item")); + widget->addItem(QString("3. Third item")); + widget->addItem(QString("4. Fourth item")); + HbPushButton* button = new HbPushButton("close"); + layout->addItem(widget); + layout->addItem(button); + QObject::connect(button, SIGNAL(clicked(bool)), this, SLOT(buttonClicked(bool))); + layout->setContentsMargins(0,0,0,0); + back->setLayout(layout); + } + + mStack->addWidget(front); + mStack->addWidget(back); + + QGraphicsLinearLayout* layout = new QGraphicsLinearLayout(this); + layout->addItem(mStack); + layout->setAlignment(mStack, Qt::AlignHCenter|Qt::AlignVCenter); + layout->setContentsMargins(0,0,0,0); + setLayout(layout); + + + mState = StateOpening1; + mAnimation = new QPropertyAnimation(this, "yRotation"); + mAnimation->setDuration(500); + mAnimation->setStartValue(qreal(0)); + mAnimation->setEndValue(qreal(90)); + QObject::connect(mAnimation, SIGNAL(finished()), this, SLOT(animationFinished())); + + mAnimation->start(); + +} + +void HgFlipWidget::togglePage() +{ + FUNC_LOG; + + mStack->setCurrentIndex(mStack->currentIndex() ^ 1); +} + +void HgFlipWidget::resizeEvent(QGraphicsSceneResizeEvent *event) +{ + FUNC_LOG; + + if (mIconLabel && event) + { + QSize iconSize(event->newSize().width(), event->newSize().height()); + mIconLabel->setIcon(HbIcon(mPixmap.scaled(iconSize, Qt::IgnoreAspectRatio))); + } + +} + +void HgFlipWidget::setYRotation(qreal a) +{ + mYRotation = a; + qreal s = 1.0f + (qAbs(a) / 90.0f * 0.5f); + QTransform t; + t.translate(rect().width()/2, rect().height()/2); + t.scale(s, s); + t.rotate(a, Qt::YAxis); + t.translate(-rect().width()/2, -rect().height()/2); + setTransform(t); + mStack->setTransform(t); +} + +qreal HgFlipWidget::yRotation() +{ + return mYRotation; +} + +void HgFlipWidget::animationFinished() +{ + if (mState == StateOpening1) + { + mAnimation->setStartValue(qreal(-90)); + mAnimation->setEndValue(qreal(0)); + mAnimation->start(); + mState = StateOpening2; + togglePage(); + } + else if (mState == StateOpening2) + { + mState = StateOpened; + } + else if (mState == StateClosing1) + { + mAnimation->setStartValue(-90); + mAnimation->setEndValue(0); + mAnimation->start(); + mState = StateClosing2; + togglePage(); + } + else if (mState == StateClosing2) + { + mState = StateClosed; + emit closed(); + } +} + +void HgFlipWidget::close() +{ + if (mState == StateOpened) + { + mState = StateClosing1; + mAnimation->setStartValue(0); + mAnimation->setEndValue(90); + mAnimation->start(); + } +} + +void HgFlipWidget::buttonClicked(bool checked) +{ + Q_UNUSED(checked) + + close(); +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/src/hgselectiondialog.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/src/hgselectiondialog.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,135 @@ +/* +* Copyright (c) 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: Multiselection dialog +* +*/ + +#include +#include +#include +#include +#include +#include "hgselectiondialog.h" +#include "trace.h" + +HgSelectionDialog::HgSelectionDialog( + const QString &title, const QString &primaryText, + HgWidget *content, QGraphicsItem *parent) : + HbDialog(parent), + mHgWidget(content), + mSelectAll(new HbPushButton("---")), + mCountLabel(new HbLabel("--/--")) +{ + FUNC_LOG; + + setDismissPolicy(HbDialog::NoDismiss); + setTimeout(HbDialog::NoTimeout); + setHeadingWidget(new HbLabel(title, this)); + setPrimaryAction(new HbAction(primaryText, this)); + primaryAction()->setDisabled(true); + setSecondaryAction(new HbAction("Cancel", this)); + + connect(content->selectionModel(), + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + SLOT(updateItems())); + connect(content->model(), + SIGNAL(rowsInserted(QModelIndex, int, int)), + SLOT(updateItems())); + connect(content->model(), + SIGNAL(rowsRemoved(QModelIndex, int, int)), + SLOT(updateItems())); + + HbWidget *contentWidget = new HbWidget; + HANDLE_ERROR_NULL(contentWidget); + if (contentWidget) { + QGraphicsLinearLayout *contentLayout = new QGraphicsLinearLayout(Qt::Vertical); + HANDLE_ERROR_NULL(contentLayout); + if (contentLayout) { + QGraphicsLinearLayout *topLayout = new QGraphicsLinearLayout(Qt::Horizontal); + HANDLE_ERROR_NULL(topLayout); + if (topLayout) { + HANDLE_ERROR_NULL(mSelectAll); + if (mSelectAll) { + topLayout->addItem(mSelectAll); + connect(mSelectAll, SIGNAL(clicked()), SLOT(selectAll())); + } + if (mCountLabel) { + mCountLabel->setAlignment(Qt::AlignRight); + topLayout->addItem(mCountLabel); + } + + contentLayout->addItem(topLayout); + } + + contentLayout->addItem(mHgWidget); + contentWidget->setLayout(contentLayout); + } + setContentWidget(contentWidget); + } + + updateItems(); +} + +HgSelectionDialog::~HgSelectionDialog() +{ + FUNC_LOG; +} + +void HgSelectionDialog::updateItems() +{ + FUNC_LOG; + + if (mHgWidget) { + QItemSelectionModel *selectionModel = mHgWidget->selectionModel(); + QAbstractItemModel *model = mHgWidget->model(); + if (selectionModel && model) { + primaryAction()->setEnabled(selectionModel->hasSelection()); + + int selectedCount = selectionModel->selectedIndexes().count(); + int itemCount = model->rowCount(); + + if (selectedCount == itemCount) { + mSelectAll->setText("Unselect all"); + mSelectAll->setChecked(false); + } + else { + mSelectAll->setText("Select all"); + mSelectAll->setChecked(false); + } + + mCountLabel->setPlainText(tr("%1/%2").arg(selectedCount).arg(itemCount)); + } + } +} + +void HgSelectionDialog::selectAll() +{ + FUNC_LOG; + + if (mHgWidget) { + QItemSelectionModel *selectionModel = mHgWidget->selectionModel(); + QAbstractItemModel *model = mHgWidget->model(); + if (selectionModel && model) { + int selectedCount = selectionModel->selectedIndexes().count(); + int itemCount = model->rowCount(); + + if (selectedCount == itemCount) { + mHgWidget->clearSelection(); + } + else { + mHgWidget->selectAll(); + } + } + } +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/src/hgtestview.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/src/hgtestview.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,94 @@ +/* +* Copyright (c) 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: Another view for test application. +* +*/ +#include +#include +#include +#include +#include +#include +#include "hgtestview.h" +#include "trace.h" + +HgTestView::HgTestView(const QString &title1, const QString &title2, const QPixmap &pixmap, QGraphicsItem *parent) : + HbView(parent), mPixmap(pixmap) +{ + FUNC_LOG; + + QList mainWindows = hbInstance->allMainWindows(); + if (mainWindows.count() > 0) + { + HbMainWindow *primaryWindow = mainWindows[0]; + + setTitle(primaryWindow->currentView()->title()); + setItemVisible(Hb::AllItems, true); // ensure that all needed view items stay visible + + // set view as parent because action will be removed on view exit + mBackAction = new HbAction(Hb::BackAction, this); + primaryWindow->addSoftKeyAction(Hb::SecondarySoftKey, mBackAction); + connect(mBackAction, SIGNAL(triggered()), SLOT(closeView())); + + QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical); + HANDLE_ERROR_NULL(layout); + if (layout) + { + HbLabel *title1Label = new HbLabel(title1); + title1Label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + layout->addItem(title1Label); + + HbLabel *title2Label = new HbLabel(title2); + title2Label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + layout->addItem(title2Label); + + mIconLabel = new HbLabel; + HANDLE_ERROR_NULL(mIconLabel); + if (mIconLabel) + { + mIconLabel->setIcon(HbIcon(mPixmap)); + mIconLabel->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + layout->addItem(mIconLabel); + } + setLayout(layout); + } + } +} + +void HgTestView::closeView() +{ + FUNC_LOG; + + QList mainWindows = hbInstance->allMainWindows(); + if (mainWindows.count() > 0) + { + HbMainWindow *primaryWindow = mainWindows[0]; + primaryWindow->removeView(this); + primaryWindow->setViewSwitchingEnabled(true); + primaryWindow->removeSoftKeyAction(Hb::SecondarySoftKey, mBackAction); // restores original action + } + delete this; // ownership transferred back from HbMainWindow +} + +void HgTestView::resizeEvent(QGraphicsSceneResizeEvent *event) +{ + FUNC_LOG; + + if (mIconLabel && event) + { + QSize iconSize(event->newSize().width()-5, event->newSize().height()-20); + mIconLabel->setIcon(HbIcon(mPixmap.scaled(iconSize, Qt::KeepAspectRatio))); + } +} + diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/src/hgwidgettestalbumartmanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/src/hgwidgettestalbumartmanager.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,301 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include +#include + +#include "hgwidgettestalbumartmanager.h" + +const int KMaxThumbnailReq = 1; + +/*! + \class HgWidgetTestAlbumArtManager + \brief Music Player collection album art manager. + + Collection album art manager provides access to album art needed for + display in certain collection views. It hides interface to the thumbnail + manager and also implements a caching mechanism for performance reasons. +*/ + +/*! + \fn void albumArtReady( int index ) + + This signal is emitted when album art for \a index is ready. + + \sa getAlbumArt() + */ + +/*! + \fn void albumCacheReady() + + This signal is emitted when album art cache is ready. + + \sa cacheAlbumArt() + */ + +/*! + Constructs the album art manager. + */ +HgWidgetTestAlbumArtManager::HgWidgetTestAlbumArtManager(QObject *parent) + : QObject(parent), + mCachingInProgress(false), + mRequestCount(0), + mMask() +{ + mThumbnailManager = new ThumbnailManager(this); + mThumbnailManager->setMode(ThumbnailManager::Default); + mThumbnailManager->setQualityPreference(ThumbnailManager::OptimizeForQuality); +// mThumbnailManager->setMode(ThumbnailManager::CreateQImages); + QPixmap qpixmap(":/icons/teardrop_mask.png"); + mMask = QBitmap(qpixmap); + +// connect( mThumbnailManager, SIGNAL(thumbnailReady(QImage, void *, int, int)), +// this, SLOT(thumbnailReady(QImage, void *, int, int)) ); + connect( mThumbnailManager, SIGNAL(thumbnailReady(QPixmap, void *, int, int)), + this, SLOT(thumbnailReady(QPixmap, void *, int, int)) ); +} + +/*! + Destructs the album art manager. + */ +HgWidgetTestAlbumArtManager::~HgWidgetTestAlbumArtManager() +{ + cancel(); + mImageCache.clear(); +} + +void HgWidgetTestAlbumArtManager::setThumbnailSize(ThumbnailManager::ThumbnailSize size) +{ + cancel(); + mImageCache.clear(); + mThumbnailManager->setThumbnailSize(size); +} + +/*! + Returns the album art for the given \a albumArtUri. If the album art is not + available in its cache, an asynchronous request is made to the thumbnail manager + and a null icon is returned. + + \sa signal albumArtReady + */ +QImage HgWidgetTestAlbumArtManager::albumArt( const QString& albumArtUri, int index ) +{ + QImage icon; + if ( mImageCache.contains(albumArtUri) ) { + icon = mImageCache.value(albumArtUri); + // If you want to cache all images disable this line. However, with large + // amount of items OOM will occure. +// mImageCache.remove(albumArtUri); + } + else { + if ( mRequestCount < KMaxThumbnailReq ) { + // Using negative index as priority will ensure that thumbnail requests + // are processed in the order they were requested. + int *clientData = new int(index); + int reqId = mThumbnailManager->getThumbnail( albumArtUri, clientData, -1 ); + if ( reqId != -1 ) { + mTnmReqMap.insert( reqId, albumArtUri ); + mRequestCount++; + } + else { + } + } + else { + mRequestQueue.enqueue( qMakePair(albumArtUri, index) ); + } + } + return icon; +} + +/*! + Request to cache the album art for the items specified in \a albumArtList. + Returns 'true' if caching is started. If all items already exist in cache, + 'false' is returned. + + \sa signal albumCacheReady + */ +bool HgWidgetTestAlbumArtManager::cacheAlbumArt( const QStringList albumArtList ) +{ + int allAvailable = true; + if ( !albumArtList.empty() ) { + QString albumArtUri; + int reqId; + QStringListIterator iter(albumArtList); + while ( iter.hasNext() ) { + albumArtUri = iter.next(); + if ( !mImageCache.contains(albumArtUri) ) { + reqId = mThumbnailManager->getThumbnail( albumArtUri ); + if ( reqId != -1 ) { + mTnmReqMap.insert( reqId, albumArtUri ); + mRequestCount++; + allAvailable = false; + } + else { + } + } + } + } + + if ( allAvailable ) { + return false; + } + else { + mCachingInProgress = true; + return true; + } +} + +/*! + Cancels all outstanding album art requests. + + \sa getAlbumArt, cacheAlbumArt + */ +void HgWidgetTestAlbumArtManager::cancel() +{ + if ( !mTnmReqMap.empty() ) { + QMapIterator iter(mTnmReqMap); + while ( iter.hasNext() ) { + iter.next(); + bool result = mThumbnailManager->cancelRequest(iter.key()); + } + } + mTnmReqMap.clear(); + mRequestQueue.clear(); + mRequestCount = 0; + mCachingInProgress = false; +} + + +/*! + Slot to be called when thumbnail bitmap generation or loading is complete. + */ +void HgWidgetTestAlbumArtManager::thumbnailReady( const QPixmap& pixmap, void *data, int id, int error ) +{ + // Find the index + if ( mTnmReqMap.contains(id) ) { + // Remove the request whether it completed successfully or with error. + QString albumArtUri = mTnmReqMap[id]; + mTnmReqMap.remove( id ); + mRequestCount--; + + if ( mCachingInProgress ) { + if ( error == 0 ) { +// QPixmap art(pixmap); +// applyMask(art); +// QIcon qicon(art); +// mImageCache.insert(albumArtUri, pixmap); + } + else { + } + if ( mTnmReqMap.empty() ) { + mCachingInProgress = false; + emit albumCacheReady(); + return; + } + } + else { + if ( error == 0 ) { + int *clientData = (int *)data; + int index = *clientData; + delete clientData; + QImage image = pixmap.toImage().convertToFormat(QImage::Format_RGB16); + mImageCache.insert(albumArtUri, image); + emit albumArtReady(index); + QTimer::singleShot(0, this, SLOT(executeNext())); + } + else { + } + } + } +} + +/*! + Slot to be called when thumbnail bitmap generation or loading is complete. + */ +void HgWidgetTestAlbumArtManager::thumbnailReady( const QImage& image, void *data, int id, int error ) +{ + // Find the index + if ( mTnmReqMap.contains(id) ) { + // Remove the request whether it completed successfully or with error. + QString albumArtUri = mTnmReqMap[id]; + mTnmReqMap.remove( id ); + mRequestCount--; + + if ( mCachingInProgress ) { + if ( error == 0 ) { +// QPixmap art(pixmap); +// applyMask(art); +// QIcon qicon(art); + mImageCache.insert(albumArtUri, image); + } + else { + } + if ( mTnmReqMap.empty() ) { + mCachingInProgress = false; + emit albumCacheReady(); + return; + } + } + else { + if ( error == 0 ) { + int *clientData = (int *)data; + int index = *clientData; + delete clientData; + QSize size = image.size(); + QImage newImage; + newImage = image.copy(); + mImageCache.insert(albumArtUri, newImage); + emit albumArtReady(index); + QTimer::singleShot(0, this, SLOT(executeNext())); + } + else { + } + } + } +} + + +/*! + Applies mask on the thumbnail. + */ +void HgWidgetTestAlbumArtManager::applyMask( QPixmap& pixmap ) +{ + pixmap.setMask(mMask); +} + +void HgWidgetTestAlbumArtManager::executeNext() +{ + // Check to see if any request is pending in the queue + while ( !mRequestQueue.isEmpty() + && (mRequestCount < KMaxThumbnailReq) ) { + QPair req = mRequestQueue.dequeue(); + QString albumArtUri = req.first; + int index = req.second; + + // Using negative index as priority will ensure that thumbnail requests + // are processed in the order they were requested. + int *clientData = new int(index); + int reqId = mThumbnailManager->getThumbnail( albumArtUri, clientData, -1 ); + if ( reqId != -1 ) { + mTnmReqMap.insert( reqId, albumArtUri ); + mRequestCount++; + } + else { + } + } + +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/src/hgwidgettestdatamodel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/src/hgwidgettestdatamodel.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,418 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include +#include +#include + +#include +#include +#include + +#include "hgwidgettestdatamodel.h" +#include "hgwidgettestalbumartmanager.h" +#include "trace.h" + +typedef QPair Range; +typedef QList RangeList; + +/*! + \class HgWidgetTestDataModel + \brief Music Player collection data model. + + Collection data model implements the interface specified by HbAbstractDataModel, + which defines the standard interface that item models must use to be able to + interoperate with other components in the model/view architecture. + + Every item of data that can be accessed via a model has an associated model + index. + + Each item has a number of data elements associated with it and they can be + retrieved by specifying a role (see Qt::ItemDataRole) to the model's data + returned by itemData() function. + + \sa HbAbstractDataModel +*/ + +/*! + Constructs the collection data model. + */ +HgWidgetTestDataModel::HgWidgetTestDataModel(QObject *parent) + : QAbstractListModel(parent), + mCachingInProgress(false), + mImageType(TypeQImage), + mDefaultIcon((":/images/default.svg")), + mUseLowResImages(false) +{ + FUNC_LOG; + + mAlbumArtManager = new HgWidgetTestAlbumArtManager; + connect( mAlbumArtManager, SIGNAL(albumArtReady(int)), this, SLOT(updateAlbumArt(int)) ); + connect( mAlbumArtManager, SIGNAL(albumCacheReady()), this, SLOT(albumCacheReady()) ); + init(); +} + +/*! + Destructs the collection data model. + */ +HgWidgetTestDataModel::~HgWidgetTestDataModel() +{ + FUNC_LOG; + + disconnect( mAlbumArtManager, SIGNAL(albumArtReady(int)), this, SLOT(updateAlbumArt(int)) ); + disconnect( mAlbumArtManager, SIGNAL(albumCacheReady()), this, SLOT(albumCacheReady()) ); + delete mAlbumArtManager; +} + +void HgWidgetTestDataModel::setThumbnailSize(ThumbnailManager::ThumbnailSize size) +{ + mAlbumArtManager->setThumbnailSize(size); +} + +void HgWidgetTestDataModel::init() +{ + FUNC_LOG; + + // Read all .jpg image paths from the c:/data/images folder + QDir dir; + dir.setFilter(QDir::Files | QDir:: Dirs); +#ifdef __WINS__ + dir.setPath(QString("c:/data/images")); +#else + dir.setPath(QString("f:/data/images")); +#endif + + QFileInfoList list = dir.entryInfoList(); + for (int i = 0; i < list.size(); ++i){ + QFileInfo fileInfo = list.at(i); + if (fileInfo.isFile()){ + QString s = fileInfo.filePath(); + if (s.indexOf(QString(".jpg"),0,Qt::CaseInsensitive)>0){ + mFiles.append(s); + mVisibility.append(true); + } + } + } + + QPixmap pixmap(":/images/default.svg"); + if (!pixmap.isNull()){ + mQIcon = QIcon(pixmap); + if (!mQIcon.isNull()){ + mHbIcon = HbIcon(mQIcon); + } + } +} + +/*! + Returns the number of rows under the given \a parent. + + View will request for the row count immediately after a model is set. + To prevent it from reading data while caching the album art for the first + screen, return row count as zero. + + \reimp + */ +int HgWidgetTestDataModel::rowCount( const QModelIndex &parent ) const +{ + Q_UNUSED(parent); + return mFiles.count(); +} + +/*! + Returns the data stored for the item referred to by the \a index. + + \reimp + */ +QVariant HgWidgetTestDataModel::data(const QModelIndex &index, int role) const +{ + QVariant returnValue = QVariant(); + if ( !index.isValid() ) { + return returnValue; + } + + int row = index.row(); + + if( row >= mFiles.count() ){ + return returnValue; + } + + switch ( role ) + { + case HgWidget::HgVisibilityRole: + { + returnValue = mVisibility[index.row()]; + } break; + case Qt::DisplayRole: + { + QStringList texts; + QString text( "Primary " ); + text.append(QString::number(row)); + texts << text; + text = "Secondary "; + text.append(QString::number(row)); + texts << text; + returnValue = texts; + break; + } + case Qt::DecorationRole: + { + // INFO("Requesting model item" << row << ", " << mFiles.at(row)); + if (mFiles.at(row).isEmpty()) { + returnValue = mDefaultIcon; + } + else { + QImage icon = mAlbumArtManager->albumArt(mFiles.at(row), row); + if ( !icon.isNull() ) + { + if (mUseLowResImages) { + QSize size = icon.size(); + icon = icon.scaled(QSize(size.width()/4, size.height()/4)); + } + + switch(mImageType) + { + case TypeHbIcon: + { + returnValue = mHbIcon; + break; + } + case TypeQImage: + { + returnValue = icon; + break; + } + case TypeQIcon: + { + returnValue = mQIcon; + break; + } + default: + break; + } + + } + else + { + returnValue = mDefaultIcon; + } + } + break; + } + case Hb::IndexFeedbackRole: + { + returnValue = QString::number(row); + break; + } + case Qt::BackgroundRole: + { + if ( (index.row() % 2) == 0 ) { + QColor color(211,211,211,127); + QBrush brush(color); + returnValue = brush; + } + else { + QColor color(255,250,250,127); + QBrush brush(color); + returnValue = brush; + } + break; + } + + case (Qt::UserRole+2): + { + QImage icon = mAlbumArtManager->albumArt(mFiles.at(row), row); + if (!icon.isNull()) + { + returnValue = icon; + } + } break; + } + + return returnValue; +} + +/*! + Must be called when data has changed and model needs to be refreshed + to reflect the new data. + */ +void HgWidgetTestDataModel::refreshModel() +{ + // Cancel all outstanding album art request first, then reset the model. + mAlbumArtManager->cancel(); + + // Before providing the new data to the view (list, grid, etc.), we want + // to make sure that we have enough album arts for the first screen. +/* mFiles.count() = mCollectionData->count(); + if ( mFiles.count() > 0 ) { + int initCount = ( mFiles.count() > KInitCacheSize ) ? KInitCacheSize : mFiles.count(); + QStringList albumArtList; + QString albumArtUri; + for ( int i = 0; i < initCount; i++ ) { + albumArtUri = mCollectionData->itemData(i, MpMpxCollectionData::AlbumArtUri); + if ( !albumArtUri.isEmpty() ) { + albumArtList << albumArtUri; + } + } + mCachingInProgress = mAlbumArtManager->cacheAlbumArt(albumArtList); + if ( !mCachingInProgress ) { + reset(); + } + } + else { + reset(); + } + */ +} + +/*! + Remove items from model (do not actually delete them). + */ +void HgWidgetTestDataModel::remove(const QItemSelection &selection) +{ + FUNC_LOG; + + QModelIndexList modelIndexes = selection.indexes(); + int removeCount = modelIndexes.count(); + int originalItemCount = mFiles.count(); + if (originalItemCount-removeCount > 0) { + RangeList removeRanges; + qSort(modelIndexes); + while (!modelIndexes.isEmpty()) { + QModelIndexList::iterator i = modelIndexes.begin(); + QModelIndexList::iterator start = i; + int lastRow = i->row(); + while (++i != modelIndexes.end() && i->row() == lastRow+1) { + lastRow++; + } + removeRanges.append(Range(start->row(), lastRow)); + modelIndexes.erase(start, i); + } + + // Work backwards to keep the indexes consistent + for (int i = removeRanges.count()-1; i >= 0; i--) { + Range range = removeRanges.at(i); + beginRemoveRows(QModelIndex(), range.first, range.second); + for (int j = range.second; j >= range.first; j--) { + INFO("Removing model item" << j); + mFiles.removeAt(j); + } + endRemoveRows(); + } + } + else if (originalItemCount-removeCount == 0) { + beginRemoveRows(QModelIndex(), 0, originalItemCount-1); + mFiles.clear(); + endRemoveRows(); + } +} + +/*! + Move items to the target index in the model. The selection should be contiguous. + */ +void HgWidgetTestDataModel::move(const QItemSelection &selection, const QModelIndex &target) +{ + FUNC_LOG; + + QModelIndexList modelIndexes = selection.indexes(); + + if (modelIndexes.count() > 0 && target.isValid()) { + int first = modelIndexes.front().row(); + int last = modelIndexes.back().row(); + int targetRow = target.row(); + INFO("Move indexes" << first << "-" << last << "to" << targetRow); + if (targetRow < first) { + beginMoveRows(QModelIndex(), first, last, QModelIndex(), targetRow); + for (int i = 0; i <= last-first; i++) { + mFiles.move(first+i, targetRow+i); + } + endMoveRows(); + } + else if (targetRow > last) { + beginMoveRows(QModelIndex(), first, last, QModelIndex(), targetRow); + for (int i = 0; i <= last-first; i++) { + mFiles.move(last-i, targetRow); + } + endMoveRows(); + } + } +} + +/*! + Add count dummy items at the target index in the model. + */ +void HgWidgetTestDataModel::add(const QModelIndex &target, int count) +{ + FUNC_LOG; + + if (target.isValid()) { + beginInsertRows(QModelIndex(), target.row(), target.row()+count-1); + for (int i = 0; i < count; i++) { + mFiles.insert(target.row(), QString()); + mVisibility.insert(target.row(), true); + } + endInsertRows(); + } +} + +/*! + Slot to be called when album art for the \a index needs to be updated. + */ +void HgWidgetTestDataModel::updateAlbumArt( int index ) +{ + if ( index >= 0 && index < mFiles.count() ) { + QModelIndex modelIndex = QAbstractItemModel::createIndex(index, 0); + emit dataChanged(modelIndex, modelIndex); + } +} + +/*! + Slot to be called when album art cache is ready. + */ +void HgWidgetTestDataModel::albumCacheReady() +{ + if ( mCachingInProgress ) { + mCachingInProgress = false; + reset(); + } +} + +void HgWidgetTestDataModel::setImageDataType(ImageType type) +{ + mImageType = type; +} + +bool HgWidgetTestDataModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + if (role == HgWidget::HgVisibilityRole) + { + mVisibility[index.row()] = value.toBool(); + emit dataChanged(index, index); + return true; + } + return false; +} + +void HgWidgetTestDataModel::enableLowResImages(bool enabled) { + + mUseLowResImages = enabled; +} + +bool HgWidgetTestDataModel::lowResImagesEnabled() const { + + return mUseLowResImages; +} + diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/src/hgwidgettestview.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/src/hgwidgettestview.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,702 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hgwidgettestview.h" +#include "hgtestview.h" +#include "hgselectiondialog.h" +#include "hgwidgettestdatamodel.h" +#include "hgflipwidget.h" +#include "trace.h" +#include +#include + +HgWidgetTestView::HgWidgetTestView(QGraphicsItem *parent) : + HbView(parent), + mWidget(NULL), + mModel(NULL), + mListWidget(NULL), + mToggleOrientation(false), + mTBone(false), + mFlipWidget(NULL), + mFrontItem(NULL) +{ + mModel = new HgWidgetTestDataModel(this); + mModel->setImageDataType(HgWidgetTestDataModel::TypeQImage); + mSelectionModel = new QItemSelectionModel(mModel, this); + + createMenu(); + + mLayout = new QGraphicsLinearLayout(Qt::Vertical); + mLayout->setContentsMargins(0,0,0,0); + initWidget( HgWidgetGrid ); + setLayout( mLayout ); +} + +HgWidgetTestView::~HgWidgetTestView() +{ +} + +void HgWidgetTestView::createMenu() +{ + FUNC_LOG; + + HbMenu* modeMenu = new HbMenu("Change widget type"); + menu()->addMenu(modeMenu); + + HbMenu* scrollBarMenu = new HbMenu("ScrollBar settings"); + menu()->addMenu( scrollBarMenu ); + + HbMenu* imageTypeMenu = new HbMenu("Datamodel image type"); + menu()->addMenu( imageTypeMenu ); + + HbAction* gridAction = modeMenu->addAction( "Use grid" ); + HbAction* coverFlowAction = modeMenu->addAction( "Use coverFlow" ); + HbAction* TBone = modeMenu->addAction( "Use TBone" ); + connect( modeMenu, SIGNAL(triggered(HbAction*)), this, SLOT(switchWidget(HbAction*)) ); + + QActionGroup* ac1 = new QActionGroup( this ); + gridAction->setCheckable( true ); + coverFlowAction->setCheckable( true ); + TBone->setCheckable(true); + gridAction->setChecked( true ); + ac1->addAction( gridAction ); + ac1->addAction( coverFlowAction ); + ac1->addAction( TBone ); + + HbAction* scrollBarAutoHideAction = scrollBarMenu->addAction( "Autohide ScrollBar" ); + HbAction* scrollBarAlwaysOnAction = scrollBarMenu->addAction( "ScrollBar always on" ); + HbAction* scrollBarAlwaysOffAction = scrollBarMenu->addAction( "ScrollBar always off" ); + scrollBarMenu->addSeparator(); + HbAction* interactiveScrollBarAction = scrollBarMenu->addAction( "Interactive scrollbar" ); + HbAction* uninteractiveScrollBarAction = scrollBarMenu->addAction( "Uninteractive scrollbar" ); + connect( scrollBarAutoHideAction, SIGNAL(triggered()), this, SLOT(autoHideScrollBar()) ); + connect( scrollBarAlwaysOnAction, SIGNAL(triggered()), this, SLOT(scrollBarAlwaysOn()) ); + connect( scrollBarAlwaysOffAction, SIGNAL(triggered()), this, SLOT(scrollBarAlwaysOff()) ); + connect( interactiveScrollBarAction, SIGNAL(triggered()), this, SLOT(interactiveScrollBar()) ); + connect( uninteractiveScrollBarAction, SIGNAL(triggered()), this, SLOT(unInteractiveScrollBar()) ); + + QActionGroup* ac2 = new QActionGroup( this ); + scrollBarAutoHideAction->setCheckable( true ); + scrollBarAlwaysOnAction->setCheckable( true ); + scrollBarAlwaysOffAction->setCheckable(true); + scrollBarAutoHideAction->setChecked( true ); + ac2->addAction( scrollBarAutoHideAction ); + ac2->addAction( scrollBarAlwaysOnAction ); + ac2->addAction( scrollBarAlwaysOffAction ); + + QActionGroup* ac3 = new QActionGroup( this ); + interactiveScrollBarAction->setCheckable( true ); + uninteractiveScrollBarAction->setCheckable( true ); + uninteractiveScrollBarAction->setChecked( true ); + ac3->addAction( interactiveScrollBarAction ); + ac3->addAction( uninteractiveScrollBarAction ); + + HbAction* qimageAction = imageTypeMenu->addAction( "feed QImages" ); + HbAction* hbiconAction = imageTypeMenu->addAction( "feed HbIcons" ); + HbAction* qiconAction = imageTypeMenu->addAction( "feed QIcons" ); + connect( qimageAction, SIGNAL(triggered()), this, SLOT(feedqimages()) ); + connect( hbiconAction, SIGNAL(triggered()), this, SLOT(feedhbicons()) ); + connect( qiconAction, SIGNAL(triggered()), this, SLOT(feedqicons()) ); + + QActionGroup* ac4 = new QActionGroup( this ); + qimageAction->setCheckable( true ); + hbiconAction->setCheckable( true ); + qiconAction->setCheckable( true ); + qimageAction->setChecked( true ); + ac4->addAction( qimageAction ); + ac4->addAction( hbiconAction ); + ac4->addAction( qiconAction ); + + menu()->addAction("Toggle scrolldirection", this, SLOT(toggleScrollDirection())); + menu()->addAction("Simulate orientation switch", this, SLOT(orientationChanged())); + + mUseLowResAction = menu()->addAction( "Use low res images for coverflow" ); + mUseLowResAction->setCheckable(true); + mUseLowResAction->setChecked(false); + mUseLowResAction->setEnabled(false); + connect( mUseLowResAction, SIGNAL(triggered()), this, SLOT(toggleLowResForCoverflow()) ); + + HbMenu *modelChangeSubMenu = menu()->addMenu("Change model"); + modelChangeSubMenu->addAction("Remove items", this, SLOT(openDeleteItemsDialog())); + modelChangeSubMenu->addAction("Move items", this, SLOT(openMoveItemsDialog())); + modelChangeSubMenu->addAction("Add items", this, SLOT(openAddItemsDialog())); + + HbMenu *labelChangeSubMenu = menu()->addMenu("Change labels"); + HbMenu *titleSubMenu = labelChangeSubMenu->addMenu("Title"); + HbAction *aboveAction1 = titleSubMenu->addAction("Above", this, SLOT(setTitleAboveImage())); + HbAction *belowAction1 = titleSubMenu->addAction("Below", this, SLOT(setTitleBelowImage())); + HbAction *hiddenAction1 = titleSubMenu->addAction("Hide", this, SLOT(setTitleHidden())); + QActionGroup* ac5 = new QActionGroup(this); + aboveAction1->setCheckable(true); + belowAction1->setCheckable(true); + hiddenAction1->setCheckable(true); + hiddenAction1->setChecked(true); + ac5->addAction(aboveAction1); + ac5->addAction(belowAction1); + ac5->addAction(hiddenAction1); + + HbMenu *descriptionSubMenu = labelChangeSubMenu->addMenu("Description"); + HbAction *aboveAction2 = descriptionSubMenu->addAction("Above", this, SLOT(setDescriptionAboveImage())); + HbAction *belowAction2 = descriptionSubMenu->addAction("Below", this, SLOT(setDescriptionBelowImage())); + HbAction *hiddenAction2 = descriptionSubMenu->addAction("Hide", this, SLOT(setDescriptionHidden())); + QActionGroup* ac6 = new QActionGroup(this); + aboveAction2->setCheckable(true); + belowAction2->setCheckable(true); + hiddenAction2->setCheckable(true); + hiddenAction2->setChecked(true); + ac6->addAction(aboveAction2); + ac6->addAction(belowAction2); + ac6->addAction(hiddenAction2); +} + +void HgWidgetTestView::switchWidget(HbAction* action) +{ + FUNC_LOG; + + mTBone = false; + if( action->text() == "Use grid"){ + initWidget( HgWidgetGrid ); + } + else if( action->text() == "Use coverFlow"){ + initWidget( HgWidgetCoverflow ); + } + else if( action->text() == "Use TBone" ){ + mTBone = true; + initWidget( HgWidgetCoverflow ); + } +} + +void HgWidgetTestView::toggleScrollDirection() +{ + FUNC_LOG; + + mToggleOrientation = !mToggleOrientation; + initWidget( mWidgetType ); +} + +void HgWidgetTestView::initWidget( WidgetType type ) +{ + FUNC_LOG; + + mWidgetType = type; + + // TODO, disconnecting signals required? + + if( mWidget ) + mLayout->removeItem(mWidget); + if( mListWidget ) + mLayout->removeItem(mListWidget); + + delete mWidget; + mWidget = NULL; + + delete mListWidget; + mListWidget = NULL; + + mWidget = createWidget(type); + mLayout->addItem(mWidget); + + switch (type) + { + case HgWidgetGrid: + { + mUseLowResAction->setEnabled(false); + mModel->enableLowResImages(false); + // TODO, init grid different model, + mModel->setThumbnailSize(ThumbnailManager::ThumbnailMedium); + break; + } + case HgWidgetCoverflow: + { + mUseLowResAction->setEnabled(true); + mModel->enableLowResImages(mUseLowResAction->isChecked()); + mModel->setThumbnailSize(ThumbnailManager::ThumbnailLarge); + if (mTBone) { + mListWidget = new HbListWidget; + mLayout->addItem(mListWidget); + mListWidget->addItem( "List item 1"); + mListWidget->addItem( "List item 2"); + mListWidget->addItem( "List item 3"); + } + break; + } + default: + break; + } + + HANDLE_ERROR_NULL(mWidget); + if (mWidget) + { + mWidget->setModel( mModel ); + connect(mWidget, SIGNAL(activated(QModelIndex)), SLOT(openDialog(QModelIndex))); + connect(mWidget, SIGNAL(longPressed(QModelIndex, QPointF)), SLOT(openView(QModelIndex))); + QList mainWindows = hbInstance->allMainWindows(); + if (mainWindows.count() > 0) + { + HbMainWindow *primaryWindow = mainWindows[0]; + connect(primaryWindow, SIGNAL(orientationChanged(Qt::Orientation)), mWidget, SLOT(orientationChanged(Qt::Orientation))); + } + + connect(mWidget, SIGNAL(scrollingStarted()), SLOT(onScrollingStarted())); + connect(mWidget, SIGNAL(scrollingEnded()), SLOT(onScrollingEnded())); + } +} + +void HgWidgetTestView::openDialog(const QModelIndex& index) +{ + FUNC_LOG; + + QVariant image = mModel->data(index, Qt::DecorationRole); + QVariant texts = mModel->data(index, Qt::DisplayRole); + + if (mWidgetType == HgWidgetCoverflow) + { + if (image.canConvert() && texts.canConvert()) + { + QStringList strList = texts.toStringList(); + if (strList.count() > 1) + { + if (mFrontItem) + mFrontItem->setVisible(false); + + if (mFlipWidget) + delete mFlipWidget; + + QPolygonF poly; + if (!mWidget->getItemOutline(index, poly)) + return; + + QRectF itemRect = poly.boundingRect(); + + mFlipWidget = + new HgFlipWidget( + strList.at(0), + strList.at(1), + image.value(), + this); + + mFlipWidget->setPos(QPointF( + itemRect.center().x() - itemRect.width() / 2, + itemRect.center().y() - itemRect.height() / 2 + )); + + mFlipWidget->resize(itemRect.width(), itemRect.height()); + mFlipWidget->show(); + + QObject::connect(mFlipWidget, SIGNAL(closed()), this, SLOT(flipClosed())); + mModel->setData(index, false, Qt::UserRole+1); + mFlippedIndex = index; + } + } + + return; + } + + HbDialog dlg; + dlg.setTimeout(HbPopup::NoTimeout); + dlg.setDismissPolicy(HbPopup::TapInside); + dlg.setPrimaryAction(new HbAction("Close")); + if (texts.canConvert()) + { + QStringList strList = texts.toStringList(); + if (strList.count() > 0) + { + dlg.setHeadingWidget(new HbLabel(strList.at(0))); + } + } + if (image.canConvert()) + { + HbLabel *content = new HbLabel; + QImage realImage(image.value()); + QPixmap pixmap = QPixmap::fromImage( realImage ); + content->setIcon(HbIcon(pixmap)); + dlg.setContentWidget(content); + } + dlg.exec(); +} + +void HgWidgetTestView::openView(const QModelIndex& index) +{ + FUNC_LOG; + + QVariant image = mModel->data(index, Qt::DecorationRole); + QVariant texts = mModel->data(index, Qt::DisplayRole); + + if (image.canConvert() && texts.canConvert()) + { + QStringList strList = texts.toStringList(); + if (strList.count() > 1) + { + HgTestView* view = + new HgTestView( + strList.at(0), + strList.at(1), + QPixmap::fromImage(image.value())); + QList mainWindows = hbInstance->allMainWindows(); + if (mainWindows.count() > 0) + { + HbMainWindow *primaryWindow = mainWindows[0]; + primaryWindow->addView(view); + primaryWindow->setViewSwitchingEnabled(false); + primaryWindow->setCurrentView(view); + } + } + } +} + +void HgWidgetTestView::openDeleteItemsDialog() +{ + FUNC_LOG; + HANDLE_ERROR_NULL(mWidget); + + HgWidget *widget = copyWidget(); + HANDLE_ERROR_NULL(widget); + + HgSelectionDialog *dlg = + new HgSelectionDialog("Remove items", "Remove", widget); // Takes ownership of widget + HANDLE_ERROR_NULL(dlg); + + mWidget->hide(); + widget->setSelectionMode(HgWidget::MultiSelection); + bool removeItems = (dlg->exec() == dlg->primaryAction()); + QItemSelection selection = mSelectionModel->selection(); + widget->setSelectionMode(HgWidget::NoSelection); // Clears the selection + delete dlg; + + if (removeItems) { + mModel->remove(selection); + } + + mWidget->show(); +} + +void HgWidgetTestView::openMoveItemsDialog() +{ + FUNC_LOG; + HANDLE_ERROR_NULL(mWidget); + + HgWidget *widget = copyWidget(); + HANDLE_ERROR_NULL(widget); + HgSelectionDialog *dlg = + new HgSelectionDialog("Select items to move", "Move to...", widget); // Takes ownership of widget + HANDLE_ERROR_NULL(dlg); + HANDLE_ERROR_NULL(dlg); + + mWidget->hide(); + widget->setSelectionMode(HgWidget::ContiguousSelection); + bool moveItems = (dlg->exec() == dlg->primaryAction()); + QItemSelection selection = mSelectionModel->selection(); + widget->setSelectionMode(HgWidget::NoSelection); // Clears the selection + delete dlg; + dlg = 0; + widget = 0; + + if (moveItems) { + widget = copyWidget(); + HANDLE_ERROR_NULL(widget); + widget->setPreferredSize(size().width(), 320); + dlg = new HgSelectionDialog("Select target location", "Move", widget); // Takes ownership of widget + HANDLE_ERROR_NULL(dlg); + widget->setSelectionMode(HgWidget::SingleSelection); + moveItems = (dlg->exec() == dlg->primaryAction()); + QItemSelection target = mSelectionModel->selection(); + widget->setSelectionMode(HgWidget::NoSelection); // Clears the selection + delete dlg; + + if (moveItems) { + mModel->move(selection, target.indexes().at(0)); + } + } + mWidget->show(); +} + +void HgWidgetTestView::openAddItemsDialog() +{ + FUNC_LOG; + HANDLE_ERROR_NULL(mWidget); + + HgWidget *widget = copyWidget(); + HANDLE_ERROR_NULL(widget); + HgSelectionDialog *dlg = + new HgSelectionDialog("Select position to add items to", "Add", widget); // Takes ownership of widget + HANDLE_ERROR_NULL(dlg); + + mWidget->hide(); + widget->setSelectionMode(HgWidget::SingleSelection); + bool addItems = (dlg->exec() == dlg->primaryAction()); + QItemSelection target = mSelectionModel->selection(); + widget->setSelectionMode(HgWidget::NoSelection); // Clears the selection + delete dlg; + + if (addItems) { + mModel->add(target.indexes().at(0), 5); + } + + mWidget->show(); +} + +void HgWidgetTestView::autoHideScrollBar() +{ + setScrollBarPolicy(HgWidget::ScrollBarAutoHide); +} + +void HgWidgetTestView::scrollBarAlwaysOn() +{ + setScrollBarPolicy(HgWidget::ScrollBarAlwaysOn); +} + +void HgWidgetTestView::scrollBarAlwaysOff() +{ + setScrollBarPolicy(HgWidget::ScrollBarAlwaysOff); +} + +void HgWidgetTestView::setScrollBarPolicy( HgWidget::ScrollBarPolicy policy ) +{ + mWidget->setScrollBarPolicy( policy ); +} + +void HgWidgetTestView::setScrollBarInteractive( bool value ) +{ + if( value ) + setScrollBarPolicy(HgWidget::ScrollBarAlwaysOn); + + mWidget->scrollBar()->setInteractive(value); + + if (mWidgetType == HgWidgetCoverflow) { + mWidget->setIndexFeedbackPolicy(HgWidget::IndexFeedbackSingleCharacter); + } + +} + +void HgWidgetTestView::interactiveScrollBar() +{ + setScrollBarInteractive(true); +} + +void HgWidgetTestView::unInteractiveScrollBar() +{ + setScrollBarInteractive(false); +} + +HgWidget *HgWidgetTestView::createWidget(WidgetType type) const +{ + FUNC_LOG; + HANDLE_ERROR_NULL(mModel); + HANDLE_ERROR_NULL(mSelectionModel); + + Qt::Orientation scrollDirection = !mToggleOrientation ? Qt::Vertical : Qt::Horizontal ; + + HgWidget* widget = 0; + + switch (type) { + case HgWidgetGrid: + widget = new HgGrid(scrollDirection); + break; + case HgWidgetCoverflow: + widget = new HgMediawall(); + break; + default: + break; + } + + HANDLE_ERROR_NULL(widget); + + widget->setModel(mModel); + widget->setSelectionModel(mSelectionModel); + widget->setLongPressEnabled(true); + widget->scrollTo(widget->currentIndex()); + + return widget; +} + +HgWidget *HgWidgetTestView::copyWidget() const +{ + FUNC_LOG; + HANDLE_ERROR_NULL(mWidget); + + HgWidget* widget = createWidget(mWidgetType); + widget->setPreferredSize(mWidget->size()); + + HgMediawall *original = qobject_cast(mWidget); + HgMediawall *copy = qobject_cast(widget); + if (original && copy) { + copy->setTitlePosition(original->titlePosition()); + copy->setDescriptionPosition(original->descriptionPosition()); + copy->setTitleFontSpec(original->titleFontSpec()); + copy->setDescriptionFontSpec(original->descriptionFontSpec()); + } + + return widget; +} + +void HgWidgetTestView::feedqimages() +{ + mModel->setImageDataType(HgWidgetTestDataModel::TypeQImage); +} + +void HgWidgetTestView::feedqicons() +{ + mModel->setImageDataType(HgWidgetTestDataModel::TypeQIcon); +} + +void HgWidgetTestView::feedhbicons() +{ + mModel->setImageDataType(HgWidgetTestDataModel::TypeHbIcon); +} + +void HgWidgetTestView::flipClosed() +{ + delete mFlipWidget; + mFlipWidget = 0; + mModel->setData(mFlippedIndex, true, Qt::UserRole+1); + + if (mFrontItem) { + mFrontItem->setVisible(true); + } + +} +void HgWidgetTestView::orientationChanged() +{ + mWidget->orientationChanged(Qt::Horizontal); +} + +void HgWidgetTestView::onScrollingStarted() +{ + FUNC_LOG; + + // scrolling started, need to hide + // label displaying full resolution image + if (mFrontItem) + mFrontItem->setVisible(false); + +} + +void HgWidgetTestView::onScrollingEnded() +{ + FUNC_LOG; + + if (mModel->lowResImagesEnabled()) { + + if (!mWidget) + return; + + // get index to current item + QModelIndex index = mWidget->currentIndex(); + if (!index.isValid()) + return; + + // get outlines of the item so we know where to render + QPolygonF poly; + if (!mWidget->getItemOutline(index, poly)) + return; + + // fetch highresolution image from the model + QVariant imgVariant = mModel->data(index, Qt::UserRole+2); + if (imgVariant.isNull()) + return; + + QRectF itemRect = poly.boundingRect(); + + // show it using HbLabel + QPixmap pixmap = imgVariant.value().scaled(itemRect.width(), itemRect.height()); + + if (!mFrontItem) { + mFrontItem = new HbLabel(this); + } + + + mFrontItem->setVisible(false); + mFrontItem->setIcon(HbIcon(pixmap)); + mFrontItem->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + mFrontItem->setPos(itemRect.center() - QPointF(itemRect.width()/2, itemRect.height()/2)); + mFrontItem->resize(itemRect.width(), itemRect.height()); + mFrontItem->setVisible(true); + + } + +} + +void HgWidgetTestView::toggleLowResForCoverflow() +{ + if (mWidgetType == HgWidgetCoverflow) { + mModel->enableLowResImages(mUseLowResAction->isChecked()); + initWidget(mWidgetType); + } +} + +void HgWidgetTestView::setTitleAboveImage() +{ + FUNC_LOG; + HgMediawall *mediawall = qobject_cast(mWidget); + if (mediawall) { + mediawall->setTitlePosition(HgMediawall::PositionAboveImage); + } +} + +void HgWidgetTestView::setTitleBelowImage() +{ + FUNC_LOG; + HgMediawall *mediawall = qobject_cast(mWidget); + if (mediawall) { + mediawall->setTitlePosition(HgMediawall::PositionBelowImage); + } +} + +void HgWidgetTestView::setTitleHidden() +{ + FUNC_LOG; + HgMediawall *mediawall = qobject_cast(mWidget); + if (mediawall) { + mediawall->setTitlePosition(HgMediawall::PositionNone); + } +} + +void HgWidgetTestView::setDescriptionAboveImage() +{ + FUNC_LOG; + HgMediawall *mediawall = qobject_cast(mWidget); + if (mediawall) { + mediawall->setDescriptionPosition(HgMediawall::PositionAboveImage); + } +} + +void HgWidgetTestView::setDescriptionBelowImage() +{ + FUNC_LOG; + HgMediawall *mediawall = qobject_cast(mWidget); + if (mediawall) { + mediawall->setDescriptionPosition(HgMediawall::PositionBelowImage); + } +} + +void HgWidgetTestView::setDescriptionHidden() +{ + FUNC_LOG; + HgMediawall *mediawall = qobject_cast(mWidget); + if (mediawall) { + mediawall->setDescriptionPosition(HgMediawall::PositionNone); + } +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/fute/HgWidgetTest/src/main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/fute/HgWidgetTest/src/main.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#include +#include +#include "hgwidgettestview.h" + +int main(int argc, char **argv) +{ + HbApplication app(argc, argv); + app.setApplicationName("HgWidgetTest"); + + HbMainWindow mainWindow; + // mainWindow.setOptimizationFlags( QGraphicsView::DontSavePainterState ); If this is used, menu is invisible + mainWindow.viewport()->grabGesture(Qt::PanGesture); + mainWindow.viewport()->grabGesture(Qt::TapGesture); + mainWindow.viewport()->grabGesture(Qt::TapAndHoldGesture); + + HgWidgetTestView *view = new HgWidgetTestView; + mainWindow.addView(view); + + mainWindow.show(); + return app.exec(); +} diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/unit/hbautotest.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/unit/hbautotest.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,832 @@ +/* +* Copyright (c) 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: Container for pan (drag) gesture -related data and logic. +* +*/ + +#include "hbautotest.h" +#include +#include + + +const qreal STEP = 10; //How many pixels to drag before sending an event + +//Init static members +bool HbAutoTest::pointerPressed = false; +QPointF HbAutoTest::pressPoint = QPointF(); + +void HbAutoTest::mouseMove (HbAutoTestMainWindow *window, HbWidget *widget, QPointF pos, int delay) +{ + if (delay!=-1) { + QTest::qWait(delay); + } + QPointF targetPoint=QPointF(); + if (pos==QPointF()) { + targetPoint = middlePointOfWidget(widget); + } else { + targetPoint = widget->mapToScene(pos); + } + if (pointerPressed) { + //Now we should drag an item + drag(window, targetPoint); + HbAutoTestMouseEvent me ( + QEvent::MouseMove, + targetPoint.toPoint(), + window->viewport()->mapToGlobal(targetPoint.toPoint()), + Qt::NoButton, + Qt::NoButton, + Qt::NoModifier); + QSpontaneKeyEvent::setSpontaneous(&me); + qApp->notify((window->viewport()), &me); + QCoreApplication::sendPostedEvents(); + QTest::qWait(1); + } else { + HbAutoTestMouseEvent me ( + QEvent::MouseMove, + targetPoint.toPoint(), + window->viewport()->mapToGlobal(targetPoint.toPoint()), + Qt::NoButton, + Qt::NoButton, + Qt::NoModifier); + QSpontaneKeyEvent::setSpontaneous(&me); + qApp->notify((window->viewport()), &me); + QCoreApplication::sendPostedEvents(); + QTest::qWait(1); + + } + QTest::qWait(1); + QTest::qWait(1); +} + +void HbAutoTest::mousePress (HbAutoTestMainWindow *window, HbWidget *widget, QPointF pos, int delay) +{ + if (delay!=-1) { + QTest::qWait(delay); + } + pointerPressed=true; + QPointF targetPoint=QPointF(); + if (pos==QPointF()) { + targetPoint = middlePointOfWidget(widget); + } else { + targetPoint = widget->mapToScene(pos); + } + QCursor::setPos(window->mapToGlobal(targetPoint.toPoint())); + + pressPoint=targetPoint; + + HbAutoTestMouseEvent me ( + QEvent::MouseButtonPress, + targetPoint.toPoint(), + window->viewport()->mapToGlobal(targetPoint.toPoint()), + Qt::LeftButton, + Qt::LeftButton, + Qt::NoModifier); + + QSpontaneKeyEvent::setSpontaneous(&me); + qApp->notify((window->viewport()), &me); + QCoreApplication::sendPostedEvents(); + QCoreApplication::sendPostedEvents(); + QTest::qWait(1); +} + +void HbAutoTest::mouseRelease (HbAutoTestMainWindow *window, HbWidget *widget, QPointF pos, int delay) +{ + if (delay!=-1) { + QTest::qWait(delay); + } + pointerPressed=false; + QPointF targetPoint=QPointF(); + if (pos==QPointF()) { + targetPoint = middlePointOfWidget(widget); + } else { + targetPoint = widget->mapToScene(pos); + } + QCursor::setPos(window->mapToGlobal(targetPoint.toPoint())); + pressPoint=QPointF(); + HbAutoTestMouseEvent me ( + QEvent::MouseButtonRelease, + targetPoint.toPoint(), + window->viewport()->mapToGlobal(targetPoint.toPoint()), + Qt::LeftButton, + Qt::LeftButton, + Qt::NoModifier); + + QSpontaneKeyEvent::setSpontaneous(&me); + qApp->notify((window->viewport()), &me); + QCoreApplication::sendPostedEvents(); + + QTest::qWait(1); + QTest::qWait(1); +} + +void HbAutoTest::mouseClick (HbAutoTestMainWindow *window, const HbWidget *widget, QPointF pos, int delay) +{ + if (delay!=-1) { + QTest::qWait(delay); + } + QPointF targetPoint=QPointF(); + if (pos==QPointF()) { + targetPoint = middlePointOfWidget(widget); + } else { + targetPoint = widget->mapToScene(pos); + } + + QCursor::setPos(window->mapToGlobal(targetPoint.toPoint())); + + HbAutoTestMouseEvent me ( + QEvent::MouseButtonPress, + targetPoint.toPoint(), + window->viewport()->mapToGlobal(targetPoint.toPoint()), + Qt::LeftButton, + Qt::LeftButton, + Qt::NoModifier); + QSpontaneKeyEvent::setSpontaneous(&me); + qApp->notify((window->viewport()), &me); + QCoreApplication::sendPostedEvents(); + QTest::qWait(1); + + if (delay!=-1) { + QTest::qWait(delay); + } + HbAutoTestMouseEvent me2 ( + QEvent::MouseButtonRelease, + targetPoint.toPoint(), + window->viewport()->mapToGlobal(targetPoint.toPoint()), + Qt::LeftButton, + Qt::LeftButton, + Qt::NoModifier); + + QSpontaneKeyEvent::setSpontaneous(&me2); + qApp->notify((window->viewport()), &me2); + QCoreApplication::sendPostedEvents(); + + QTest::qWait(1); + QTest::qWait(1); +} + +QPointF HbAutoTest::middlePointOfWidget( const HbWidget* widget) +{ + QRectF widgetRect = widget->rect(); + QRectF widgetSceneRect = widget->mapRectToScene(widgetRect); + qreal middleX = ((widgetSceneRect.right() - widgetSceneRect.left())/2)+widgetSceneRect.left(); + qreal middleY = ((widgetSceneRect.bottom() - widgetSceneRect.top())/2)+widgetSceneRect.top(); + return QPointF(middleX,middleY); +} + + + +void HbAutoTest::drag(HbAutoTestMainWindow *window, QPointF targetPoint) +{ + qreal tempX = targetPoint.x() - pressPoint.x(); + qreal tempY = targetPoint.y() - pressPoint.y(); + qreal totalTrip = sqrt ((tempX * tempX) + (tempY * tempY)); + + int numberOfSteps = qRound(totalTrip / STEP); + HbAutoTestMouseEvent me ( + QEvent::MouseMove, + targetPoint.toPoint(), + window->viewport()->mapToGlobal(targetPoint.toPoint()), + Qt::NoButton , + Qt::LeftButton, + Qt::NoModifier); + + QPointF nextPanPoint=pressPoint; + for (int i=1; imapToGlobal(nextPanPoint.toPoint())); + + me = HbAutoTestMouseEvent (QEvent::MouseMove, + nextPanPoint.toPoint(), + window->viewport()->mapToGlobal(nextPanPoint.toPoint()), + Qt::NoButton, + Qt::LeftButton, + Qt::NoModifier); + + QSpontaneKeyEvent::setSpontaneous(&me); + qApp->notify((window->viewport()), &me); + QCoreApplication::sendPostedEvents(); + } + + QCursor::setPos(window->mapToGlobal(targetPoint.toPoint())); + + //One more (or the only one) step to the target + me = HbAutoTestMouseEvent (QEvent::MouseMove, + targetPoint.toPoint(), + window->viewport()->mapToGlobal(targetPoint.toPoint()), + Qt::NoButton, + Qt::LeftButton, + Qt::NoModifier); + QSpontaneKeyEvent::setSpontaneous(&me); + qApp->notify((window->viewport()), &me); + QCoreApplication::sendPostedEvents(); +} + + +void HbAutoTest::simulateEvent(QWidget *widget, bool press, int code, + Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay) + { + //Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + /*extern int Q_TESTLIB_EXPORT defaultKeyDelay(); + + if (delay == -1 || delay < defaultKeyDelay()) + delay = defaultKeyDelay(); + if(delay > 0) + QTest::qWait(delay);*/ + Q_UNUSED(delay); + QTest::qWait(10); //TODO: Remove this and reveal above out-commented code + + HbAutoTestKeyEvent a(press ? QEvent::KeyPress : QEvent::KeyRelease, code, modifier, text, repeat); + QSpontaneKeyEvent::setSpontaneous(&a); + if (!qApp->notify(widget, &a)) + QTest::qWarn("Keyboard event not accepted by receiving widget"); + } + +void HbAutoTest::sendKeyEvent(QTest::KeyAction action, QWidget *widget, Qt::Key code, + QString text, Qt::KeyboardModifiers modifier, int delay) + { + QTEST_ASSERT(qApp); + + if (!widget) + widget = QWidget::keyboardGrabber(); + if (!widget) { + if (QWidget *apw = QApplication::activePopupWidget()) + widget = apw->focusWidget() ? apw->focusWidget() : apw; + else + widget = QApplication::focusWidget(); + } + if (!widget) + widget = QApplication::activeWindow(); + + QTEST_ASSERT(widget); + + if (action == QTest::Click) { + QPointer ptr(widget); + sendKeyEvent(QTest::Press, widget, code, text, modifier, delay); + if (!ptr) { + // if we send key-events to embedded widgets, they might be destroyed + // when the user presses Return + return; + } + sendKeyEvent(QTest::Release, widget, code, text, modifier, delay); + return; + } + + bool repeat = false; + + if (action == QTest::Press) { + if (modifier & Qt::ShiftModifier) + simulateEvent(widget, true, Qt::Key_Shift, 0, QString(), false, delay); + + if (modifier & Qt::ControlModifier) + simulateEvent(widget, true, Qt::Key_Control, modifier & Qt::ShiftModifier, QString(), false, delay); + + if (modifier & Qt::AltModifier) + simulateEvent(widget, true, Qt::Key_Alt, + modifier & (Qt::ShiftModifier | Qt::ControlModifier), QString(), false, delay); + if (modifier & Qt::MetaModifier) + simulateEvent(widget, true, Qt::Key_Meta, modifier & (Qt::ShiftModifier + | Qt::ControlModifier | Qt::AltModifier), QString(), false, delay); + simulateEvent(widget, true, code, modifier, text, repeat, delay); + } else if (action == QTest::Release) { + simulateEvent(widget, false, code, modifier, text, repeat, delay); + + if (modifier & Qt::MetaModifier) + simulateEvent(widget, false, Qt::Key_Meta, modifier, QString(), false, delay); + if (modifier & Qt::AltModifier) + simulateEvent(widget, false, Qt::Key_Alt, modifier & + (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier), QString(), false, delay); + + if (modifier & Qt::ControlModifier) + simulateEvent(widget, false, Qt::Key_Control, + modifier & (Qt::ShiftModifier | Qt::ControlModifier), QString(), false, delay); + + if (modifier & Qt::ShiftModifier) + simulateEvent(widget, false, Qt::Key_Shift, modifier & Qt::ShiftModifier, QString(), false, delay); + } + } + +void HbAutoTest::sendKeyEvent(QTest::KeyAction action, QWidget *widget, Qt::Key code, + char ascii, Qt::KeyboardModifiers modifier, int delay) + { + Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + QString text; + if (ascii) + text = QString(QChar::fromLatin1(ascii)); + sendKeyEvent(action, widget, code, text, modifier, delay); + } + +void HbAutoTest::keyEvent(QTest::KeyAction action, QWidget *widget, char ascii, + Qt::KeyboardModifiers modifier, int delay) + { + Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + sendKeyEvent(action, widget, asciiToKey(ascii), ascii, modifier, delay); + } + +void HbAutoTest::keyEvent(QTest::KeyAction action, QWidget *widget, Qt::Key key, + Qt::KeyboardModifiers modifier, int delay) + { + Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + sendKeyEvent(action, widget, key, keyToAscii(key), modifier, delay); + } + +void HbAutoTest::keyClicks(QWidget *widget, const QString &sequence, + Qt::KeyboardModifiers modifier, int delay) + { + Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + for (int i=0; i < sequence.length(); i++) + keyEvent(QTest::Click, widget, sequence.at(i).toLatin1(), modifier, delay); + } + +void HbAutoTest::keyPress(QWidget *widget, char key, Qt::KeyboardModifiers modifier, int delay) + { + Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + keyEvent(QTest::Press, widget, key, modifier, delay); + } + +void HbAutoTest::keyRelease(QWidget *widget, char key, Qt::KeyboardModifiers modifier, int delay) + { + Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + keyEvent(QTest::Release, widget, key, modifier, delay); + } + +void HbAutoTest::keyClick(QWidget *widget, char key, Qt::KeyboardModifiers modifier, int delay) + { + Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + keyEvent(QTest::Click, widget, key, modifier, delay); + } + +void HbAutoTest::keyPress(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier, int delay) + { + Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + keyEvent(QTest::Press, widget, key, modifier, delay); + } + +void HbAutoTest::keyRelease(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier, int delay) + { + Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + keyEvent(QTest::Release, widget, key, modifier, delay); } + +void HbAutoTest::keyClick(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier, int delay) + { + Q_ASSERT_X(dynamic_cast(( widget) ) != 0, "HbAutoTest", "Always use with HbAutoTestMainWindow"); + keyEvent(QTest::Click, widget, key, modifier, delay); + } + +Qt::Key HbAutoTest::asciiToKey(char ascii) +{ + switch ((unsigned char)ascii) { + case 0x08: return Qt::Key_Backspace; + case 0x09: return Qt::Key_Tab; + case 0x0b: return Qt::Key_Backtab; + case 0x0d: return Qt::Key_Return; + case 0x1b: return Qt::Key_Escape; + case 0x20: return Qt::Key_Space; + case 0x21: return Qt::Key_Exclam; + case 0x22: return Qt::Key_QuoteDbl; + case 0x23: return Qt::Key_NumberSign; + case 0x24: return Qt::Key_Dollar; + case 0x25: return Qt::Key_Percent; + case 0x26: return Qt::Key_Ampersand; + case 0x27: return Qt::Key_Apostrophe; + case 0x28: return Qt::Key_ParenLeft; + case 0x29: return Qt::Key_ParenRight; + case 0x2a: return Qt::Key_Asterisk; + case 0x2b: return Qt::Key_Plus; + case 0x2c: return Qt::Key_Comma; + case 0x2d: return Qt::Key_Minus; + case 0x2e: return Qt::Key_Period; + case 0x2f: return Qt::Key_Slash; + case 0x30: return Qt::Key_0; + case 0x31: return Qt::Key_1; + case 0x32: return Qt::Key_2; + case 0x33: return Qt::Key_3; + case 0x34: return Qt::Key_4; + case 0x35: return Qt::Key_5; + case 0x36: return Qt::Key_6; + case 0x37: return Qt::Key_7; + case 0x38: return Qt::Key_8; + case 0x39: return Qt::Key_9; + case 0x3a: return Qt::Key_Colon; + case 0x3b: return Qt::Key_Semicolon; + case 0x3c: return Qt::Key_Less; + case 0x3d: return Qt::Key_Equal; + case 0x3e: return Qt::Key_Greater; + case 0x3f: return Qt::Key_Question; + case 0x40: return Qt::Key_At; + case 0x41: return Qt::Key_A; + case 0x42: return Qt::Key_B; + case 0x43: return Qt::Key_C; + case 0x44: return Qt::Key_D; + case 0x45: return Qt::Key_E; + case 0x46: return Qt::Key_F; + case 0x47: return Qt::Key_G; + case 0x48: return Qt::Key_H; + case 0x49: return Qt::Key_I; + case 0x4a: return Qt::Key_J; + case 0x4b: return Qt::Key_K; + case 0x4c: return Qt::Key_L; + case 0x4d: return Qt::Key_M; + case 0x4e: return Qt::Key_N; + case 0x4f: return Qt::Key_O; + case 0x50: return Qt::Key_P; + case 0x51: return Qt::Key_Q; + case 0x52: return Qt::Key_R; + case 0x53: return Qt::Key_S; + case 0x54: return Qt::Key_T; + case 0x55: return Qt::Key_U; + case 0x56: return Qt::Key_V; + case 0x57: return Qt::Key_W; + case 0x58: return Qt::Key_X; + case 0x59: return Qt::Key_Y; + case 0x5a: return Qt::Key_Z; + case 0x5b: return Qt::Key_BracketLeft; + case 0x5c: return Qt::Key_Backslash; + case 0x5d: return Qt::Key_BracketRight; + case 0x5e: return Qt::Key_AsciiCircum; + case 0x5f: return Qt::Key_Underscore; + case 0x60: return Qt::Key_QuoteLeft; + case 0x61: return Qt::Key_A; + case 0x62: return Qt::Key_B; + case 0x63: return Qt::Key_C; + case 0x64: return Qt::Key_D; + case 0x65: return Qt::Key_E; + case 0x66: return Qt::Key_F; + case 0x67: return Qt::Key_G; + case 0x68: return Qt::Key_H; + case 0x69: return Qt::Key_I; + case 0x6a: return Qt::Key_J; + case 0x6b: return Qt::Key_K; + case 0x6c: return Qt::Key_L; + case 0x6d: return Qt::Key_M; + case 0x6e: return Qt::Key_N; + case 0x6f: return Qt::Key_O; + case 0x70: return Qt::Key_P; + case 0x71: return Qt::Key_Q; + case 0x72: return Qt::Key_R; + case 0x73: return Qt::Key_S; + case 0x74: return Qt::Key_T; + case 0x75: return Qt::Key_U; + case 0x76: return Qt::Key_V; + case 0x77: return Qt::Key_W; + case 0x78: return Qt::Key_X; + case 0x79: return Qt::Key_Y; + case 0x7a: return Qt::Key_Z; + case 0x7b: return Qt::Key_BraceLeft; + case 0x7c: return Qt::Key_Bar; + case 0x7d: return Qt::Key_BraceRight; + case 0x7e: return Qt::Key_AsciiTilde; + + // Latin 1 codes adapted from X: keysymdef.h,v 1.21 94/08/28 16:17:06 + case 0xa0: return Qt::Key_nobreakspace; + case 0xa1: return Qt::Key_exclamdown; + case 0xa2: return Qt::Key_cent; + case 0xa3: return Qt::Key_sterling; + case 0xa4: return Qt::Key_currency; + case 0xa5: return Qt::Key_yen; + case 0xa6: return Qt::Key_brokenbar; + case 0xa7: return Qt::Key_section; + case 0xa8: return Qt::Key_diaeresis; + case 0xa9: return Qt::Key_copyright; + case 0xaa: return Qt::Key_ordfeminine; + case 0xab: return Qt::Key_guillemotleft; + case 0xac: return Qt::Key_notsign; + case 0xad: return Qt::Key_hyphen; + case 0xae: return Qt::Key_registered; + case 0xaf: return Qt::Key_macron; + case 0xb0: return Qt::Key_degree; + case 0xb1: return Qt::Key_plusminus; + case 0xb2: return Qt::Key_twosuperior; + case 0xb3: return Qt::Key_threesuperior; + case 0xb4: return Qt::Key_acute; + case 0xb5: return Qt::Key_mu; + case 0xb6: return Qt::Key_paragraph; + case 0xb7: return Qt::Key_periodcentered; + case 0xb8: return Qt::Key_cedilla; + case 0xb9: return Qt::Key_onesuperior; + case 0xba: return Qt::Key_masculine; + case 0xbb: return Qt::Key_guillemotright; + case 0xbc: return Qt::Key_onequarter; + case 0xbd: return Qt::Key_onehalf; + case 0xbe: return Qt::Key_threequarters; + case 0xbf: return Qt::Key_questiondown; + case 0xc0: return Qt::Key_Agrave; + case 0xc1: return Qt::Key_Aacute; + case 0xc2: return Qt::Key_Acircumflex; + case 0xc3: return Qt::Key_Atilde; + case 0xc4: return Qt::Key_Adiaeresis; + case 0xc5: return Qt::Key_Aring; + case 0xc6: return Qt::Key_AE; + case 0xc7: return Qt::Key_Ccedilla; + case 0xc8: return Qt::Key_Egrave; + case 0xc9: return Qt::Key_Eacute; + case 0xca: return Qt::Key_Ecircumflex; + case 0xcb: return Qt::Key_Ediaeresis; + case 0xcc: return Qt::Key_Igrave; + case 0xcd: return Qt::Key_Iacute; + case 0xce: return Qt::Key_Icircumflex; + case 0xcf: return Qt::Key_Idiaeresis; + case 0xd0: return Qt::Key_ETH; + case 0xd1: return Qt::Key_Ntilde; + case 0xd2: return Qt::Key_Ograve; + case 0xd3: return Qt::Key_Oacute; + case 0xd4: return Qt::Key_Ocircumflex; + case 0xd5: return Qt::Key_Otilde; + case 0xd6: return Qt::Key_Odiaeresis; + case 0xd7: return Qt::Key_multiply; + case 0xd8: return Qt::Key_Ooblique; + case 0xd9: return Qt::Key_Ugrave; + case 0xda: return Qt::Key_Uacute; + case 0xdb: return Qt::Key_Ucircumflex; + case 0xdc: return Qt::Key_Udiaeresis; + case 0xdd: return Qt::Key_Yacute; + case 0xde: return Qt::Key_THORN; + case 0xdf: return Qt::Key_ssharp; + case 0xe5: return Qt::Key_Aring; + case 0xe6: return Qt::Key_AE; + case 0xf7: return Qt::Key_division; + case 0xf8: return Qt::Key_Ooblique; + case 0xff: return Qt::Key_ydiaeresis; + default: QTEST_ASSERT(false); return Qt::Key(0); + } +} + +char HbAutoTest::keyToAscii(Qt::Key key) +{ + switch (key) { + case Qt::Key_Backspace: return 0x8; //BS + case Qt::Key_Tab: return 0x09; // HT + case Qt::Key_Backtab: return 0x0b; // VT + case Qt::Key_Enter: + case Qt::Key_Return: return 0x0d; // CR + case Qt::Key_Escape: return 0x1b; // ESC + case Qt::Key_Space: return 0x20; // 7 bit printable ASCII + case Qt::Key_Exclam: return 0x21; + case Qt::Key_QuoteDbl: return 0x22; + case Qt::Key_NumberSign: return 0x23; + case Qt::Key_Dollar: return 0x24; + case Qt::Key_Percent: return 0x25; + case Qt::Key_Ampersand: return 0x26; + case Qt::Key_Apostrophe: return 0x27; + case Qt::Key_ParenLeft: return 0x28; + case Qt::Key_ParenRight: return 0x29; + case Qt::Key_Asterisk: return 0x2a; + case Qt::Key_Plus: return 0x2b; + case Qt::Key_Comma: return 0x2c; + case Qt::Key_Minus: return 0x2d; + case Qt::Key_Period: return 0x2e; + case Qt::Key_Slash: return 0x2f; + case Qt::Key_0: return 0x30; + case Qt::Key_1: return 0x31; + case Qt::Key_2: return 0x32; + case Qt::Key_3: return 0x33; + case Qt::Key_4: return 0x34; + case Qt::Key_5: return 0x35; + case Qt::Key_6: return 0x36; + case Qt::Key_7: return 0x37; + case Qt::Key_8: return 0x38; + case Qt::Key_9: return 0x39; + case Qt::Key_Colon: return 0x3a; + case Qt::Key_Semicolon: return 0x3b; + case Qt::Key_Less: return 0x3c; + case Qt::Key_Equal: return 0x3d; + case Qt::Key_Greater: return 0x3e; + case Qt::Key_Question: return 0x3f; + case Qt::Key_At: return 0x40; + case Qt::Key_A: return 0x61; // 0x41 == 'A', 0x61 == 'a' + case Qt::Key_B: return 0x62; + case Qt::Key_C: return 0x63; + case Qt::Key_D: return 0x64; + case Qt::Key_E: return 0x65; + case Qt::Key_F: return 0x66; + case Qt::Key_G: return 0x67; + case Qt::Key_H: return 0x68; + case Qt::Key_I: return 0x69; + case Qt::Key_J: return 0x6a; + case Qt::Key_K: return 0x6b; + case Qt::Key_L: return 0x6c; + case Qt::Key_M: return 0x6d; + case Qt::Key_N: return 0x6e; + case Qt::Key_O: return 0x6f; + case Qt::Key_P: return 0x70; + case Qt::Key_Q: return 0x71; + case Qt::Key_R: return 0x72; + case Qt::Key_S: return 0x73; + case Qt::Key_T: return 0x74; + case Qt::Key_U: return 0x75; + case Qt::Key_V: return 0x76; + case Qt::Key_W: return 0x77; + case Qt::Key_X: return 0x78; + case Qt::Key_Y: return 0x79; + case Qt::Key_Z: return 0x7a; + case Qt::Key_BracketLeft: return 0x5b; + case Qt::Key_Backslash: return 0x5c; + case Qt::Key_BracketRight: return 0x5d; + case Qt::Key_AsciiCircum: return 0x5e; + case Qt::Key_Underscore: return 0x5f; + case Qt::Key_QuoteLeft: return 0x60; + + case Qt::Key_BraceLeft: return 0x7b; + case Qt::Key_Bar: return 0x7c; + case Qt::Key_BraceRight: return 0x7d; + case Qt::Key_AsciiTilde: return 0x7e; + + case Qt::Key_Delete: return 0; + case Qt::Key_Insert: return 0; // = 0x1006, + case Qt::Key_Pause: return 0; // = 0x1008, + case Qt::Key_Print: return 0; // = 0x1009, + case Qt::Key_SysReq: return 0; // = 0x100a, + + case Qt::Key_Clear: return 0; // = 0x100b, + + case Qt::Key_Home: return 0; // = 0x1010, // cursor movement + case Qt::Key_End: return 0; // = 0x1011, + case Qt::Key_Left: return 0; // = 0x1012, + case Qt::Key_Up: return 0; // = 0x1013, + case Qt::Key_Right: return 0; // = 0x1014, + case Qt::Key_Down: return 0; // = 0x1015, + case Qt::Key_PageUp: return 0; // = 0x1016, + case Qt::Key_PageDown: return 0; // = 0x1017, + case Qt::Key_Shift: return 0; // = 0x1020, // modifiers + case Qt::Key_Control: return 0; // = 0x1021, + case Qt::Key_Meta: return 0; // = 0x1022, + case Qt::Key_Alt: return 0; // = 0x1023, + case Qt::Key_CapsLock: return 0; // = 0x1024, + case Qt::Key_NumLock: return 0; // = 0x1025, + case Qt::Key_ScrollLock: return 0; // = 0x1026, + case Qt::Key_F1: return 0; // = 0x1030, // function keys + case Qt::Key_F2: return 0; // = 0x1031, + case Qt::Key_F3: return 0; // = 0x1032, + case Qt::Key_F4: return 0; // = 0x1033, + case Qt::Key_F5: return 0; // = 0x1034, + case Qt::Key_F6: return 0; // = 0x1035, + case Qt::Key_F7: return 0; // = 0x1036, + case Qt::Key_F8: return 0; // = 0x1037, + case Qt::Key_F9: return 0; // = 0x1038, + case Qt::Key_F10: return 0; // = 0x1039, + case Qt::Key_F11: return 0; // = 0x103a, + case Qt::Key_F12: return 0; // = 0x103b, + case Qt::Key_F13: return 0; // = 0x103c, + case Qt::Key_F14: return 0; // = 0x103d, + case Qt::Key_F15: return 0; // = 0x103e, + case Qt::Key_F16: return 0; // = 0x103f, + case Qt::Key_F17: return 0; // = 0x1040, + case Qt::Key_F18: return 0; // = 0x1041, + case Qt::Key_F19: return 0; // = 0x1042, + case Qt::Key_F20: return 0; // = 0x1043, + case Qt::Key_F21: return 0; // = 0x1044, + case Qt::Key_F22: return 0; // = 0x1045, + case Qt::Key_F23: return 0; // = 0x1046, + case Qt::Key_F24: return 0; // = 0x1047, + case Qt::Key_F25: return 0; // = 0x1048, // F25 .. F35 only on X11 + case Qt::Key_F26: return 0; // = 0x1049, + case Qt::Key_F27: return 0; // = 0x104a, + case Qt::Key_F28: return 0; // = 0x104b, + case Qt::Key_F29: return 0; // = 0x104c, + case Qt::Key_F30: return 0; // = 0x104d, + case Qt::Key_F31: return 0; // = 0x104e, + case Qt::Key_F32: return 0; // = 0x104f, + case Qt::Key_F33: return 0; // = 0x1050, + case Qt::Key_F34: return 0; // = 0x1051, + case Qt::Key_F35: return 0; // = 0x1052, + case Qt::Key_Super_L: return 0; // = 0x1053, // extra keys + case Qt::Key_Super_R: return 0; // = 0x1054, + case Qt::Key_Menu: return 0; // = 0x1055, + case Qt::Key_Hyper_L: return 0; // = 0x1056, + case Qt::Key_Hyper_R: return 0; // = 0x1057, + case Qt::Key_Help: return 0; // = 0x1058, + case Qt::Key_Direction_L: return 0; // = 0x1059, + case Qt::Key_Direction_R: return 0; // = 0x1060, + + // Latin 1 codes adapted from X: keysymdef.h,v 1.21 94/08/28 16:17:06 + case Qt::Key_nobreakspace: return char(0xa0); + case Qt::Key_exclamdown: return char(0xa1); + case Qt::Key_cent: return char(0xa2); + case Qt::Key_sterling: return char(0xa3); + case Qt::Key_currency: return char(0xa4); + case Qt::Key_yen: return char(0xa5); + case Qt::Key_brokenbar: return char(0xa6); + case Qt::Key_section: return char(0xa7); + case Qt::Key_diaeresis: return char(0xa8); + case Qt::Key_copyright: return char(0xa9); + case Qt::Key_ordfeminine: return char(0xaa); + case Qt::Key_guillemotleft: return char(0xab); // left angle quotation mar + case Qt::Key_notsign: return char(0xac); + case Qt::Key_hyphen: return char(0xad); + case Qt::Key_registered: return char(0xae); + case Qt::Key_macron: return char(0xaf); + case Qt::Key_degree: return char(0xb0); + case Qt::Key_plusminus: return char(0xb1); + case Qt::Key_twosuperior: return char(0xb2); + case Qt::Key_threesuperior: return char(0xb3); + case Qt::Key_acute: return char(0xb4); + case Qt::Key_mu: return char(0xb5); + case Qt::Key_paragraph: return char(0xb6); + case Qt::Key_periodcentered: return char(0xb7); + case Qt::Key_cedilla: return char(0xb8); + case Qt::Key_onesuperior: return char(0xb9); + case Qt::Key_masculine: return char(0xba); + case Qt::Key_guillemotright: return char(0xbb); // right angle quotation mar + case Qt::Key_onequarter: return char(0xbc); + case Qt::Key_onehalf: return char(0xbd); + case Qt::Key_threequarters: return char(0xbe); + case Qt::Key_questiondown: return char(0xbf); + case Qt::Key_Agrave: return char(0xc0); + case Qt::Key_Aacute: return char(0xc1); + case Qt::Key_Acircumflex: return char(0xc2); + case Qt::Key_Atilde: return char(0xc3); + case Qt::Key_Adiaeresis: return char(0xc4); + case Qt::Key_Aring: return char(0xe5); + case Qt::Key_AE: return char(0xe6); + case Qt::Key_Ccedilla: return char(0xc7); + case Qt::Key_Egrave: return char(0xc8); + case Qt::Key_Eacute: return char(0xc9); + case Qt::Key_Ecircumflex: return char(0xca); + case Qt::Key_Ediaeresis: return char(0xcb); + case Qt::Key_Igrave: return char(0xcc); + case Qt::Key_Iacute: return char(0xcd); + case Qt::Key_Icircumflex: return char(0xce); + case Qt::Key_Idiaeresis: return char(0xcf); + case Qt::Key_ETH: return char(0xd0); + case Qt::Key_Ntilde: return char(0xd1); + case Qt::Key_Ograve: return char(0xd2); + case Qt::Key_Oacute: return char(0xd3); + case Qt::Key_Ocircumflex: return char(0xd4); + case Qt::Key_Otilde: return char(0xd5); + case Qt::Key_Odiaeresis: return char(0xd6); + case Qt::Key_multiply: return char(0xd7); + case Qt::Key_Ooblique: return char(0xf8); + case Qt::Key_Ugrave: return char(0xd9); + case Qt::Key_Uacute: return char(0xda); + case Qt::Key_Ucircumflex: return char(0xdb); + case Qt::Key_Udiaeresis: return char(0xdc); + case Qt::Key_Yacute: return char(0xdd); + case Qt::Key_THORN: return char(0xde); + case Qt::Key_ssharp: return char(0xdf); + case Qt::Key_division: return char(0xf7); + case Qt::Key_ydiaeresis: return char(0xff); + + // multimedia/internet keys - ignored by default - see QKeyEvent c'tor + + case Qt::Key_Back : return 0; // = 0x1061, + case Qt::Key_Forward : return 0; // = 0x1062, + case Qt::Key_Stop : return 0; // = 0x1063, + case Qt::Key_Refresh : return 0; // = 0x1064, + + case Qt::Key_VolumeDown: return 0; // = 0x1070, + case Qt::Key_VolumeMute : return 0; // = 0x1071, + case Qt::Key_VolumeUp: return 0; // = 0x1072, + case Qt::Key_BassBoost: return 0; // = 0x1073, + case Qt::Key_BassUp: return 0; // = 0x1074, + case Qt::Key_BassDown: return 0; // = 0x1075, + case Qt::Key_TrebleUp: return 0; // = 0x1076, + case Qt::Key_TrebleDown: return 0; // = 0x1077, + + case Qt::Key_MediaPlay : return 0; // = 0x1080, + case Qt::Key_MediaStop : return 0; // = 0x1081, + case Qt::Key_MediaPrevious : return 0; // = 0x1082, + case Qt::Key_MediaNext : return 0; // = 0x1083, + case Qt::Key_MediaRecord: return 0; // = 0x1084, + + case Qt::Key_HomePage : return 0; // = 0x1090, + case Qt::Key_Favorites : return 0; // = 0x1091, + case Qt::Key_Search : return 0; // = 0x1092, + case Qt::Key_Standby: return 0; // = 0x1093, + case Qt::Key_OpenUrl: return 0; // = 0x1094, + + case Qt::Key_LaunchMail : return 0; // = 0x10a0, + case Qt::Key_LaunchMedia: return 0; // = 0x10a1, + case Qt::Key_Launch0 : return 0; // = 0x10a2, + case Qt::Key_Launch1 : return 0; // = 0x10a3, + case Qt::Key_Launch2 : return 0; // = 0x10a4, + case Qt::Key_Launch3 : return 0; // = 0x10a5, + case Qt::Key_Launch4 : return 0; // = 0x10a6, + case Qt::Key_Launch5 : return 0; // = 0x10a7, + case Qt::Key_Launch6 : return 0; // = 0x10a8, + case Qt::Key_Launch7 : return 0; // = 0x10a9, + case Qt::Key_Launch8 : return 0; // = 0x10aa, + case Qt::Key_Launch9 : return 0; // = 0x10ab, + case Qt::Key_LaunchA : return 0; // = 0x10ac, + case Qt::Key_LaunchB : return 0; // = 0x10ad, + case Qt::Key_LaunchC : return 0; // = 0x10ae, + case Qt::Key_LaunchD : return 0; // = 0x10af, + case Qt::Key_LaunchE : return 0; // = 0x10b0, + case Qt::Key_LaunchF : return 0; // = 0x10b1, + + default: QTEST_ASSERT(false); return 0; + } +} + diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/unit/hbautotest.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/unit/hbautotest.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,276 @@ +/* +* Copyright (c) 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: Container for pan (drag) gesture -related data and logic. +* +*/ + +#ifndef HBAUTOTEST_H +#define HBAUTOTEST_H + +#include +#include +#include + +class HbMainWindow; +class HbWidget; +class HbAutoTestMainWindow; +class HbAutoTest; +class HbAutoTestMouseEvent; +/* +INSTRUCTIONS: +The class HbAutoTest is meant to be used with Orbit applications auto testing instead of GUI testing APIs of QTestLib. + +The functions of this class is to used similarily to the related QTestLib functions. + +Use HbAutoTestMainWindow (defined below) instead of HbMainWindow to enble filtering. +Filterin filters out UI events that are not sent by function defined in HbAutoTest class. + +*/ + +class HbAutoTestMouseEvent : public QMouseEvent +{ +public: + HbAutoTestMouseEvent(Type type, const QPoint & pos, const QPoint & globalPos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers ) + : QMouseEvent(type,pos,globalPos,button,buttons,modifiers){} +}; + +class HbAutoTestKeyEvent : public QKeyEvent +{ +public: + HbAutoTestKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text = QString(), + bool autorep = false, ushort count = 1 ) + : QKeyEvent(type, key, modifiers, text, autorep, count){} +}; + +class HbAutoTest +{ +public: + + static void mouseMove (HbAutoTestMainWindow *window, HbWidget *widget, QPointF pos = QPointF(), int delay = -1 ); + static void mousePress (HbAutoTestMainWindow *window, HbWidget *widget, QPointF pos = QPointF(), int delay = -1); + static void mouseRelease (HbAutoTestMainWindow *window, HbWidget *widget, QPointF pos = QPointF(), int delay = -1); + static void mouseClick (HbAutoTestMainWindow *window, const HbWidget *widget, QPointF pos = QPointF(), int delay = -1); + +private: + static void drag(HbAutoTestMainWindow *window, QPointF targetPoint); + static QPointF middlePointOfWidget( const HbWidget* widget); + + static bool pointerPressed; + static QPointF pressPoint; + +//Key event Part: copy-pasted from QTestLib and modified to support HbAutoTestKeyEvent to enable filtering. +//see HbAutoTestMainWindow below. +public: + + static Qt::Key asciiToKey(char ascii); + static char keyToAscii(Qt::Key key); + + static void simulateEvent(QWidget *widget, bool press, int code, + Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1); + + static void sendKeyEvent(QTest::KeyAction action, QWidget *widget, Qt::Key code, + QString text, Qt::KeyboardModifiers modifier, int delay=-1); + + static void sendKeyEvent(QTest::KeyAction action, QWidget *widget, Qt::Key code, + char ascii, Qt::KeyboardModifiers modifier, int delay=-1); + + static void keyEvent(QTest::KeyAction action, QWidget *widget, char ascii, + Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1); + + static void keyEvent(QTest::KeyAction action, QWidget *widget, Qt::Key key, + Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1); + + static void keyClicks(QWidget *widget, const QString &sequence, + Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1); + + static void keyPress(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1); + + static void keyRelease(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1); + + static void keyClick(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1); + + static void keyPress(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1); + + static void keyRelease(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1); + + static void keyClick(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1); +}; + +class HbTestEvent +{ +public: + virtual void simulate(QWidget *w) = 0; + virtual HbTestEvent *clone() const = 0; + + virtual ~HbTestEvent() {} +}; + +class HbTestKeyEvent: public HbTestEvent +{ +public: + inline HbTestKeyEvent(QTest::KeyAction action, Qt::Key key, Qt::KeyboardModifiers modifiers, int delay) + : _action(action), _delay(delay), _modifiers(modifiers), _ascii(0), _key(key) {} + inline HbTestKeyEvent(QTest::KeyAction action, char ascii, Qt::KeyboardModifiers modifiers, int delay) + : _action(action), _delay(delay), _modifiers(modifiers), + _ascii(ascii), _key(Qt::Key_unknown) {} + inline HbTestEvent *clone() const { return new HbTestKeyEvent(*this); } + + inline void simulate(QWidget *w) + { + if (_ascii == 0) + HbAutoTest::keyEvent(_action, w, _key, _modifiers, _delay); + else + HbAutoTest::keyEvent(_action, w, _ascii, _modifiers, _delay); + } + +protected: + QTest::KeyAction _action; + int _delay; + Qt::KeyboardModifiers _modifiers; + char _ascii; + Qt::Key _key; +}; + +class HbTestKeyClicksEvent: public HbTestEvent +{ +public: + inline HbTestKeyClicksEvent(const QString &keys, Qt::KeyboardModifiers modifiers, int delay) + : _keys(keys), _modifiers(modifiers), _delay(delay) {} + inline HbTestEvent *clone() const { return new HbTestKeyClicksEvent(*this); } + + inline void simulate(QWidget *w) + { + HbAutoTest::keyClicks(w, _keys, _modifiers, _delay); + } + +private: + QString _keys; + Qt::KeyboardModifiers _modifiers; + int _delay; +}; + +class HbTestDelayEvent: public HbTestEvent +{ +public: + inline HbTestDelayEvent(int msecs): _delay(msecs) {} + inline HbTestEvent *clone() const { return new HbTestDelayEvent(*this); } + + inline void simulate(QWidget * /*w*/) { QTest::qWait(_delay); } + +private: + int _delay; +}; + +class HbTestEventList: public QList +{ +public: + inline HbTestEventList() {} + inline HbTestEventList(const HbTestEventList &other): QList() + { for (int i = 0; i < other.count(); ++i) append(other.at(i)->clone()); } + inline ~HbTestEventList() + { clear(); } + inline void clear() + { qDeleteAll(*this); QList::clear(); } + + inline void addKeyClick(Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + { addKeyEvent(QTest::Click, qtKey, modifiers, msecs); } + inline void addKeyPress(Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + { addKeyEvent(QTest::Press, qtKey, modifiers, msecs); } + inline void addKeyRelease(Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + { addKeyEvent(QTest::Release, qtKey, modifiers, msecs); } + inline void addKeyEvent(QTest::KeyAction action, Qt::Key qtKey, + Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + { append(new HbTestKeyEvent(action, qtKey, modifiers, msecs)); } + + inline void addKeyClick(char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + { addKeyEvent(QTest::Click, ascii, modifiers, msecs); } + inline void addKeyPress(char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + { addKeyEvent(QTest::Press, ascii, modifiers, msecs); } + inline void addKeyRelease(char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + { addKeyEvent(QTest::Release, ascii, modifiers, msecs); } + inline void addKeyClicks(const QString &keys, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + { append(new HbTestKeyClicksEvent(keys, modifiers, msecs)); } + inline void addKeyEvent(QTest::KeyAction action, char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) + { append(new HbTestKeyEvent(action, ascii, modifiers, msecs)); } + + inline void addDelay(int msecs) + { append(new HbTestDelayEvent(msecs)); } + + inline void simulate(QWidget *w) + { + for (int i = 0; i < count(); ++i) + at(i)->simulate(w); + } +}; + +class HbAutoTestMainWindow : public HbMainWindow +{ +public: + HbAutoTestMainWindow() : HbMainWindow() {} + + void mousePressEvent(QMouseEvent *event) + { + if ( dynamic_cast(event) ) { + HbMainWindow::mousePressEvent(event); + } else { + ;//Do nothing + } + } + + void mouseMoveEvent(QMouseEvent *event) + { + if ( dynamic_cast(event) ) { + HbMainWindow::mouseMoveEvent(event); + } else { + ;//Do nothing + } + } + + void mouseReleaseEvent(QMouseEvent *event) + { + if ( dynamic_cast(event) ) { + HbMainWindow::mouseReleaseEvent(event); + } else { + ;//Do nothing + } + } + + void keyPressEvent(QKeyEvent *event) + { + if ( dynamic_cast(event) ) { + HbMainWindow::keyPressEvent(event); + } else { + ;//Do nothing + } + } + void keyReleaseEvent(QKeyEvent *event) + { + if ( dynamic_cast(event) ) { + HbMainWindow::keyReleaseEvent(event); + } else { + ;//Do nothing + } + } + + void mouseDoubleClickEvent(QMouseEvent *event) + { + Q_UNUSED(event); + //Just ignore, not supported in Orbit + } +}; + + +Q_DECLARE_METATYPE(HbTestEventList) +#endif //HBAUTOTEST_H + diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/unit/startupHG.jpg Binary file ganeswidgets/tsrc/unit/startupHG.jpg has changed diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/unit/unittest_ganeswidgets.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/unit/unittest_ganeswidgets.cpp Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,1848 @@ +/* +* Copyright (c) 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: Container for pan (drag) gesture -related data and logic. +* +*/ + +#include +#include +#include +#include "hbautotest.h" +#include +#include +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QItemSelection) +Q_DECLARE_METATYPE(QModelIndex) + +static const QPointF grid_portrait_pos0(70, 30); +static const QPointF grid_portrait_pos1(180, 30); +static const QPointF grid_portrait_pos2(280, 30); +static const QPointF grid_portrait_pos3(70, 120); +static const QPointF grid_portrait_pos4(180, 120); +static const QPointF grid_portrait_pos5(280, 120); +static const QPointF grid_portrait_pos6(70, 200); +static const QPointF grid_portrait_pos7(180, 200); +static const QPointF grid_portrait_pos8(280, 200); + +class TestGanesWidgets : public QObject +{ + Q_OBJECT + +public: + + TestGanesWidgets(); + virtual ~TestGanesWidgets(); + +private slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void test_panGridLandscape(); + void test_panGridPortrait(); + void test_panCoverFlowLandscape(); + void test_panCoverFlowPortrait(); + void test_scrollbarGridLandscape(); + void test_scrollbarGridPortrait(); + void test_scrollbarCoverFlowLandscape(); + void test_scrollbarCoverFlowPortrait(); + void test_addRemoveItemsGrid(); + void test_addRemoveItemsCoverflow(); + void test_updateData(); + void test_tap(); + void test_currentItemCoverflow(); + void test_currentItemGrid(); + void test_selectionMode(); + void test_selectionModel(); + void test_scrollTo(); + void test_addItemsCoverFlow(); + void test_removeItemsCoverFlow(); + void test_moveItemsCoverFlow(); + +private: + + void pan( Qt::Orientation, TBool begin ); + +private: + + HbMainWindow* mWindow; + HgWidget* mWidget; + +}; + +class TestModel : public QAbstractListModel +{ + Q_OBJECT + +public: + + explicit TestModel(QList *requestedIndexes = 0); + virtual ~TestModel(); + + int rowCount(const QModelIndex &parent=QModelIndex()) const; + QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const; + + void generateItems(int count); + void appendItem(); + void insertItems(int index, int count=1); + void removeItems(int index, int count=1); + void moveItems(int from, int to, int count=1); + void changeItem(int index); + void reset(); + + QImage mImage; + QStringList mItems; + bool mValidData; + + QList *mRequestedIndexes; +}; + +TestModel::TestModel(QList *requestedIndexes) : + mValidData(true), + mRequestedIndexes(requestedIndexes) +{ + mImage = QImage(":icons/startupHG.jpg"); +} + +TestModel::~TestModel() +{ + +} + +void TestModel::generateItems(int count) +{ + for (int i=0; i= 0 && index < mItems.count()) { + beginRemoveRows(QModelIndex(), index, index+count-1); // Inclusive + int end = index+count; + for (; index= 0 && index < mItems.count() ) { + QModelIndex modelIndex = QAbstractItemModel::createIndex(index, 0); + emit dataChanged(modelIndex, modelIndex); + } +} + +int TestModel::rowCount(const QModelIndex &parent) const +{ + return mItems.count(); +} + +QVariant TestModel::data(const QModelIndex &index, int role) const +{ + QVariant returnValue; + + if( !mValidData) + return returnValue; + + int row = index.row(); + + switch ( role ) + { + case Qt::DisplayRole: + { + QStringList texts; + QString text("Primary %0"); + text.arg(row); + texts << text; + text = "Secondary %0"; + text.arg(row); + texts << text; + returnValue = texts; + break; + } + case Qt::DecorationRole: + { + returnValue = mImage; + if (mRequestedIndexes && !mRequestedIndexes->contains(index)) { + mRequestedIndexes->append(index); + qSort(*mRequestedIndexes); + } + break; + } + default: + break; + + } + + return returnValue; +} + + +TestGanesWidgets::TestGanesWidgets() +{ +} + +TestGanesWidgets::~TestGanesWidgets() +{ + +} + +void TestGanesWidgets::initTestCase() +{ + +} + +void TestGanesWidgets::cleanupTestCase() +{ + +} + +void TestGanesWidgets::init() +{ + +} + +void TestGanesWidgets::cleanup() +{ + +} + +void TestGanesWidgets::pan( Qt::Orientation orientation, TBool begin ) +{ + QPointF start(100,100); + QPointF move; + QPointF end; + if (orientation==Qt::Horizontal){ + move = QPointF(100,0); + } + else { + move = QPointF(0,100); + } + + if( begin ) + end = start - move; + else + end = start + move; + + HbAutoTest::mousePress( (HbAutoTestMainWindow*)mWindow, mWidget, start, -1 ); + HbAutoTest::mouseMove( (HbAutoTestMainWindow*)mWindow, mWidget, end, -1 ); + HbAutoTest::mouseRelease( (HbAutoTestMainWindow*)mWindow, mWidget, end, 100 ); +} + +void TestGanesWidgets::test_panGridLandscape() +{ + mWindow = new HbMainWindow; + mWidget = new HgGrid(Qt::Horizontal); + TestModel model; + model.generateItems(30); + mWindow->addView( mWidget ); + QVERIFY( mWidget->model() == 0 ); + mWidget->setModel( &model ); + QVERIFY( &model == mWidget->model() ); + + mWindow->show(); + + QTest::qWait( 2000 ); + + pan( Qt::Horizontal, true ); + + model.reset(); + model.generateItems(5); + + QTest::qWait( 2000 ); + + pan( Qt::Horizontal, false ); + + model.reset(); + + QTest::qWait( 2000 ); + + pan( Qt::Horizontal, true ); + + QTest::qWait(4000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_panGridPortrait() +{ + mWindow = new HbMainWindow; + mWidget = new HgGrid(Qt::Vertical ); + TestModel model; + model.generateItems(30); + mWindow->addView( mWidget ); + QVERIFY( mWidget->model() == 0 ); + mWidget->setModel( &model ); + QVERIFY( &model == mWidget->model() ); + mWindow->show(); + + QTest::qWait( 2000 ); + + pan( Qt::Vertical, true ); + + model.reset(); + model.generateItems(5); + + QTest::qWait( 2000 ); + + pan( Qt::Vertical, false ); + + model.reset(); + + QTest::qWait( 2000 ); + + pan( Qt::Vertical, true ); + + QTest::qWait(4000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_panCoverFlowLandscape() +{ + mWindow = new HbMainWindow; + mWidget = new HgMediawall(); + TestModel model; + model.generateItems(30); + mWindow->addView( mWidget ); + QVERIFY( mWidget->model() == 0 ); + mWidget->setModel( &model ); + QVERIFY( &model == mWidget->model() ); + mWindow->show(); + + QTest::qWait( 2000 ); + + pan( Qt::Horizontal, true ); + + model.reset(); + model.generateItems(5); + + QTest::qWait( 2000 ); + + pan( Qt::Horizontal, false ); + + model.reset(); + + QTest::qWait( 2000 ); + + pan( Qt::Horizontal, true ); + + QTest::qWait(4000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_panCoverFlowPortrait() +{ + mWindow = new HbMainWindow; + mWidget = new HgMediawall(); + TestModel model; + model.generateItems(30); + mWindow->addView( mWidget ); + QVERIFY( mWidget->model() == 0 ); + mWidget->setModel( &model ); + QVERIFY( &model == mWidget->model() ); + mWindow->show(); + + QTest::qWait( 2000 ); + + pan( Qt::Vertical, true ); + + model.reset(); + model.generateItems(5); + + QTest::qWait( 2000 ); + + pan( Qt::Vertical, false ); + + model.reset(); + + QTest::qWait( 2000 ); + + pan( Qt::Vertical, true ); + + QTest::qWait(4000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_scrollbarGridLandscape() +{ + mWindow = new HbMainWindow; + mWidget = new HgMediawall(); + TestModel model; + model.generateItems(200); + mWindow->addView( mWidget ); + mWidget->setModel( &model ); + mWindow->show(); + + QTest::qWait( 2000 ); + + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAutoHide); + + mWidget->setScrollBarPolicy(HgWidget::ScrollBarAlwaysOn); + mWidget->scrollBar()->setInteractive(true); + QRectF rect = mWidget->scrollBar()->rect(); + + QTest::qWait(1000); + + QPointF move( 20,0 ); + + HbAutoTest::mousePress( (HbAutoTestMainWindow*)mWindow, mWidget->scrollBar(), rect.topLeft()+move, -1 ); + HbAutoTest::mouseMove( (HbAutoTestMainWindow*)mWindow, mWidget->scrollBar(), rect.topRight()-move, 50 ); + HbAutoTest::mouseRelease( (HbAutoTestMainWindow*)mWindow, mWidget->scrollBar(), rect.topRight()-move, 100 ); + + QTest::qWait(3000); + + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOn ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAlwaysOn); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOff ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAlwaysOff); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAutoHide ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAutoHide); + + QVERIFY(mWidget->scrollBar() != 0); + HbScrollBar* scrollBar = new HbScrollBar(); + mWidget->setScrollBar(scrollBar); + QVERIFY(mWidget->scrollBar()==scrollBar); + mWidget->setScrollBar(0); + QVERIFY(mWidget->scrollBar()!= 0); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; + +} + +void TestGanesWidgets::test_scrollbarGridPortrait() +{ + mWindow = new HbMainWindow; + mWidget = new HgMediawall(); + TestModel model; + model.generateItems(200); + mWindow->addView( mWidget ); + mWidget->setModel( &model ); + mWindow->show(); + + QTest::qWait( 2000 ); + + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAutoHide); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOn ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAlwaysOn); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOff ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAlwaysOff); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAutoHide ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAutoHide); + + QVERIFY(mWidget->scrollBar() != 0); + HbScrollBar* scrollBar = new HbScrollBar(); + mWidget->setScrollBar(scrollBar); + QVERIFY(mWidget->scrollBar()==scrollBar); + mWidget->setScrollBar(0); + QVERIFY(mWidget->scrollBar()!= 0); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; + +} + +void TestGanesWidgets::test_scrollbarCoverFlowLandscape() +{ + mWindow = new HbMainWindow; + mWidget = new HgMediawall(); + TestModel model; + model.generateItems(200); + mWindow->addView( mWidget ); + mWidget->setModel( &model ); + mWindow->show(); + + QTest::qWait( 2000 ); + + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAutoHide); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOn ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAlwaysOn); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOff ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAlwaysOff); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAutoHide ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAutoHide); + + QVERIFY(mWidget->scrollBar() != 0); + HbScrollBar* scrollBar = new HbScrollBar(); + mWidget->setScrollBar(scrollBar); + QVERIFY(mWidget->scrollBar()==scrollBar); + mWidget->setScrollBar(0); + QVERIFY(mWidget->scrollBar()!= 0); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; + +} + +void TestGanesWidgets::test_scrollbarCoverFlowPortrait() +{ + mWindow = new HbMainWindow; + mWidget = new HgMediawall(); + TestModel model; + model.generateItems(200); + mWindow->addView( mWidget ); + mWidget->setModel( &model ); + mWindow->show(); + + QTest::qWait( 2000 ); + + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAutoHide); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOn ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAlwaysOn); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOff ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAlwaysOff); + mWidget->setScrollBarPolicy( HgWidget::ScrollBarAutoHide ); + QVERIFY(mWidget->scrollBarPolicy() == HgWidget::ScrollBarAutoHide); + + QVERIFY(mWidget->scrollBar() != 0); + HbScrollBar* scrollBar = new HbScrollBar(); + mWidget->setScrollBar(scrollBar); + QVERIFY(mWidget->scrollBar()==scrollBar); + mWidget->setScrollBar(0); + QVERIFY(mWidget->scrollBar()!= 0); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; + +} + +void TestGanesWidgets::test_addRemoveItemsGrid() +{ + mWindow = new HbMainWindow; + mWidget = new HgMediawall(); + TestModel model; + model.generateItems(2); + mWindow->addView( mWidget ); + mWidget->setModel( &model ); + mWindow->show(); + + QTest::qWait( 2000 ); + + model.appendItem(); + model.appendItem(); + model.removeItems(0); + model.removeItems(3); + model.removeItems(0); + model.removeItems(0); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_addRemoveItemsCoverflow() +{ + mWindow = new HbMainWindow; + mWidget = new HgMediawall(); + TestModel model; + model.generateItems(2); + mWindow->addView( mWidget ); + mWidget->setModel( &model ); + mWindow->show(); + + QTest::qWait( 2000 ); + + model.appendItem(); + model.appendItem(); + model.removeItems(0); + model.removeItems(3); + model.removeItems(0); + model.removeItems(0); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_tap() +{ + mWindow = new HbMainWindow; + mWidget = new HgMediawall(); + TestModel model; + model.generateItems(50); + mWindow->addView( mWidget ); + mWidget->setModel( &model ); + mWindow->show(); + + QTest::qWait( 2000 ); + + QSignalSpy stateSpy( mWidget, SIGNAL( activated(QModelIndex) ) ); + QSignalSpy stateSpy2( mWidget, SIGNAL( longPressed(QModelIndex) ) ); + + QPointF pos(100,100); + HbAutoTest::mouseClick( (HbAutoTestMainWindow*)mWindow, mWidget, pos, 100 ); + + QTest::qWait(1000); + + // Generating gestures doesn't work so enable this condition later. +// QCOMPARE(stateSpy.count(),1); + + QVERIFY(!mWidget->longPressEnabled()); + mWidget->setLongPressEnabled(true); + QVERIFY(mWidget->longPressEnabled()); + + HbAutoTest::mousePress( (HbAutoTestMainWindow*)mWindow, mWidget, pos, -1 ); + HbAutoTest::mouseRelease( (HbAutoTestMainWindow*)mWindow, mWidget, pos, 2000 ); + + // Generating gestures doesn't work so enable this condition later. +// QCOMPARE( stateSpy2.count(),1 ); + + mWidget->setLongPressEnabled(false); + QVERIFY(!mWidget->longPressEnabled()); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_updateData() +{ + mWindow = new HbMainWindow; + mWidget = new HgGrid( Qt::Vertical ); + TestModel model; + model.generateItems(50); + mWindow->addView( mWidget ); + model.mValidData = false; + mWidget->setModel( &model ); + mWindow->show(); + + QTest::qWait( 2000 ); + + model.mValidData = true; + for(int i=0;i<50;i++){ + model.changeItem(i); + } + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_currentItemCoverflow() +{ + const QPointF pos1(160, 300); + const QPointF pos2(300, 300); + const QPointF pos3(20, 300); + + mWindow = new HbMainWindow; + mWindow->viewport()->grabGesture(Qt::PanGesture); + mWindow->viewport()->grabGesture(Qt::TapGesture); // Add TapAndHoldGesture once it's working + mWidget = new HgMediawall(); + + TestModel model; + model.generateItems(50); + mWindow->addView(mWidget); + mWidget->setModel(&model); + mWindow->show(); + + QVERIFY(mWidget->selectionModel()); + qRegisterMetaType("QModelIndex"); + QSignalSpy currentItemSpy(mWidget->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex))); + + QTest::qWait(2000); + + QVERIFY(mWidget->currentIndex() == model.index(0, 0)); + + mWidget->setCurrentIndex(model.index(7, 0)); + QVERIFY(mWidget->currentIndex() == model.index(7, 0)); + + mWidget->setCurrentIndex(QModelIndex()); + QVERIFY(!mWidget->currentIndex().isValid()); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, pos1, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(0, 0)); + QVERIFY(currentItemSpy.count() == 1); + QVERIFY(currentItemSpy.at(0).count() > 0); + QVERIFY(qvariant_cast(currentItemSpy.at(0).at(0)) == model.index(0, 0)); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, pos2, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(1, 0)); + QVERIFY(currentItemSpy.count() == 1); + QVERIFY(currentItemSpy.at(0).count() > 0); + QVERIFY(qvariant_cast(currentItemSpy.at(0).at(0)) == model.index(1, 0)); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, pos2, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(2, 0)); + QVERIFY(currentItemSpy.count() == 1); + QVERIFY(currentItemSpy.at(0).count() > 0); + QVERIFY(qvariant_cast(currentItemSpy.at(0).at(0)) == model.index(2, 0)); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, pos2, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(3, 0)); + QVERIFY(currentItemSpy.count() == 1); + QVERIFY(currentItemSpy.at(0).count() > 0); + QVERIFY(qvariant_cast(currentItemSpy.at(0).at(0)) == model.index(3, 0)); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, pos3, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(2, 0)); + QVERIFY(currentItemSpy.count() == 1); + QVERIFY(currentItemSpy.at(0).count() > 0); + QVERIFY(qvariant_cast(currentItemSpy.at(0).at(0)) == model.index(2, 0)); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, pos3, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(1, 0)); + QVERIFY(currentItemSpy.count() == 1); + QVERIFY(currentItemSpy.at(0).count() > 0); + QVERIFY(qvariant_cast(currentItemSpy.at(0).at(0)) == model.index(1, 0)); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, pos3, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(0, 0)); + QVERIFY(currentItemSpy.count() == 1); + QVERIFY(currentItemSpy.at(0).count() > 0); + QVERIFY(qvariant_cast(currentItemSpy.at(0).at(0)) == model.index(0, 0)); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, pos3, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(0, 0)); + QVERIFY(currentItemSpy.count() == 0); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_currentItemGrid() +{ + mWindow = new HbMainWindow; + mWindow->viewport()->grabGesture(Qt::PanGesture); + mWindow->viewport()->grabGesture(Qt::TapGesture); // Add TapAndHoldGesture once it's working + mWidget = new HgGrid( Qt::Vertical); + + TestModel model; + model.generateItems(50); + mWindow->addView(mWidget); + mWidget->setModel(&model); + mWindow->show(); + + QVERIFY(mWidget->selectionModel()); + qRegisterMetaType("QModelIndex"); + QSignalSpy currentItemSpy(mWidget->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex))); + + QTest::qWait(2000); + + QVERIFY(mWidget->currentIndex() == model.index(0, 0)); + + mWidget->setCurrentIndex(model.index(7, 0)); + QVERIFY(mWidget->currentIndex() == model.index(7, 0)); + + mWidget->setCurrentIndex(QModelIndex()); + QVERIFY(!mWidget->currentIndex().isValid()); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos1, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(1, 0)); + QVERIFY(currentItemSpy.count() == 1); + QVERIFY(currentItemSpy.at(0).count() > 0); + QVERIFY(qvariant_cast(currentItemSpy.at(0).at(0)) == model.index(1, 0)); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos4, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(4, 0)); + QVERIFY(currentItemSpy.count() == 1); + QVERIFY(currentItemSpy.at(0).count() > 0); + QVERIFY(qvariant_cast(currentItemSpy.at(0).at(0)) == model.index(4, 0)); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos4, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(4, 0)); + QVERIFY(currentItemSpy.count() == 0); + + currentItemSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos8, 100); + QTest::qWait(1000); + QVERIFY(mWidget->currentIndex() == model.index(8, 0)); + QVERIFY(currentItemSpy.count() == 1); + QVERIFY(currentItemSpy.at(0).count() > 0); + QVERIFY(qvariant_cast(currentItemSpy.at(0).at(0)) == model.index(8, 0)); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_selectionMode() +{ + mWindow = new HbMainWindow; + mWindow->viewport()->grabGesture(Qt::PanGesture); + mWindow->viewport()->grabGesture(Qt::TapGesture); // Add TapAndHoldGesture once it's working + mWidget = new HgGrid( Qt::Vertical); + + mWindow->addView(mWidget); + mWindow->show(); + + QTest::qWait(2000); + + // Widget does not have selection model yet + QVERIFY(mWidget->selectionModel() == 0); + + // Selection methods should have no effect unless there is a model + mWidget->setSelectionMode(HgWidget::MultiSelection); + QVERIFY(mWidget->selectionMode() == HgWidget::MultiSelection); + QVERIFY(mWidget->selectionModel() == 0); + mWidget->selectAll(); + QVERIFY(mWidget->selectionModel() == 0); + + TestModel model; + model.generateItems(9); + mWidget->setModel(&model); + QVERIFY(mWidget->selectionModel() != 0); + + qRegisterMetaType("QItemSelection"); + QSignalSpy selectionSpy(mWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection))); + + QTest::qWait(2000); + + mWidget->setSelectionMode(HgWidget::NoSelection); + QVERIFY(mWidget->selectionMode() == HgWidget::NoSelection); + // Default selection mode: no selection + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos0, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 0); + QVERIFY(selectionSpy.count() == 0); + + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos1, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 0); + QVERIFY(selectionSpy.count() == 0); + + mWidget->selectAll(); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 0); + QVERIFY(selectionSpy.count() == 0); + + // Single selection mode: at most 1 item selected at a time + mWidget->setSelectionMode(HgWidget::SingleSelection); + QVERIFY(mWidget->selectionMode() == HgWidget::SingleSelection); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 0); + + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos1, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 1); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(1, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + QItemSelection selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 1); + QVERIFY(selection.contains(model.index(1, 0))); + + selectionSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos3, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 1); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(3, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 1); + selection = qvariant_cast(selectionSpy.at(0).at(0)); // new selected + QVERIFY(selection.indexes().count() == 1); + QVERIFY(selection.contains(model.index(3, 0))); + selection = qvariant_cast(selectionSpy.at(0).at(1)); // deselected + QVERIFY(selection.indexes().count() == 1); + QVERIFY(selection.contains(model.index(1, 0))); + + selectionSpy.clear(); + mWidget->clearSelection(); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 0); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 0); + + selectionSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos8, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 1); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(8, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 1); + QVERIFY(selection.contains(model.index(8, 0))); + + selectionSpy.clear(); + // Changing selection mode with default parameter should clear the selection + mWidget->setSelectionMode(HgWidget::ContiguousSelection); + QVERIFY(mWidget->selectionMode() == HgWidget::ContiguousSelection); + + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 0); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 0); + + selectionSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos2, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 1); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(2, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 1); + QVERIFY(selection.contains(model.index(2, 0))); + + selectionSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos3, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 2); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(3, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 1); + QVERIFY(selection.contains(model.index(3, 0))); + + selectionSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos5, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 4); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(4, 0))); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(5, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 2); + QVERIFY(selection.contains(model.index(4, 0))); + QVERIFY(selection.contains(model.index(5, 0))); + + selectionSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos0, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 6); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(0, 0))); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(1, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 2); + QVERIFY(selection.contains(model.index(0, 0))); + QVERIFY(selection.contains(model.index(1, 0))); + + // In contiguous selection mode, clicking a selected item does nothing + selectionSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos5, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 6); + QVERIFY(selectionSpy.count() == 0); + + selectionSpy.clear(); + mWidget->selectAll(); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 9); + QVERIFY(selectionSpy.count() == 1); + + selectionSpy.clear(); + // Changing selection mode with resetSelection = false should NOT clear the selection + mWidget->setSelectionMode(HgWidget::MultiSelection, false); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 9); + QVERIFY(selectionSpy.count() == 0); + + selectionSpy.clear(); + // In multiselection mode, clicking a selected item deselects it + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos5, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 8); + QVERIFY(!(mWidget->selectionModel()->isSelected(model.index(5, 0)))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 1); + selection = qvariant_cast(selectionSpy.at(0).at(0)); // new selected + QVERIFY(selection.indexes().count() == 0); + selection = qvariant_cast(selectionSpy.at(0).at(1)); // deselected + QVERIFY(selection.indexes().count() == 1); + QVERIFY(selection.contains(model.index(5, 0))); + + selectionSpy.clear(); + mWidget->clearSelection(); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 0); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 1); + selection = qvariant_cast(selectionSpy.at(0).at(0)); // new selected + QVERIFY(selection.indexes().count() == 0); + selection = qvariant_cast(selectionSpy.at(0).at(1)); // deselected + QVERIFY(selection.indexes().count() == 8); + + selectionSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos3, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 1); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(3, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 1); + + selectionSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos5, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 2); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(5, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 1); + QVERIFY(selection.contains(model.index(5, 0))); + + selectionSpy.clear(); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos8, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 3); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(8, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 0); + selection = qvariant_cast(selectionSpy.at(0).at(0)); + QVERIFY(selection.indexes().count() == 1); + QVERIFY(selection.contains(model.index(8, 0))); + + selectionSpy.clear(); + // Setting the same mode does nothing + mWidget->setSelectionMode(HgWidget::MultiSelection); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 3); + QVERIFY(selectionSpy.count() == 0); + + selectionSpy.clear(); + // Keep the selection, even if it is not suitable for the new selection mode + mWidget->setSelectionMode(HgWidget::SingleSelection, false); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 3); + QVERIFY(selectionSpy.count() == 0); + + selectionSpy.clear(); + // First click resets the selection to a valid setup + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos5, 100); + QTest::qWait(1000); + QVERIFY(mWidget->selectionModel()->selectedIndexes().count() == 1); + QVERIFY(mWidget->selectionModel()->isSelected(model.index(5, 0))); + QVERIFY(selectionSpy.count() == 1); + QVERIFY(selectionSpy.at(0).count() > 1); + selection = qvariant_cast(selectionSpy.at(0).at(0)); // new selected + QVERIFY(selection.indexes().count() == 0); + selection = qvariant_cast(selectionSpy.at(0).at(1)); // deselected + QVERIFY(selection.indexes().count() == 2); + QVERIFY(selection.contains(model.index(3, 0))); + QVERIFY(selection.contains(model.index(8, 0))); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_selectionModel() +{ + mWindow = new HbMainWindow; + mWindow->viewport()->grabGesture(Qt::PanGesture); + mWindow->viewport()->grabGesture(Qt::TapGesture); // Add TapAndHoldGesture once it's working + mWidget = new HgGrid( Qt::Vertical); + TestModel model; + model.generateItems(9); + mWidget->setModel(&model); + mWindow->addView(mWidget); + mWindow->show(); + QTest::qWait(2000); + + QVERIFY(mWidget->selectionModel() != 0); + + QItemSelectionModel *defaultSelectionModel = mWidget->selectionModel(); + QSignalSpy defaultSelectionSpy(defaultSelectionModel, SIGNAL(selectionChanged(QItemSelection, QItemSelection))); + + QItemSelectionModel *testSelectionModel1 = new QItemSelectionModel(&model); + QSignalSpy testSelectionSpy1(testSelectionModel1, SIGNAL(selectionChanged(QItemSelection, QItemSelection))); + + QItemSelectionModel *testSelectionModel2 = new QItemSelectionModel(&model); + QSignalSpy testSelectionSpy2(testSelectionModel2, SIGNAL(selectionChanged(QItemSelection, QItemSelection))); + + mWidget->setSelectionMode(HgWidget::MultiSelection); + + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos2, 100); + QTest::qWait(1000); + QVERIFY(defaultSelectionModel->selectedIndexes().count() == 1); + QVERIFY(defaultSelectionSpy.count() == 1); + QVERIFY(testSelectionModel1->selectedIndexes().count() == 0); + QVERIFY(testSelectionSpy1.count() == 0); + QVERIFY(testSelectionModel2->selectedIndexes().count() == 0); + QVERIFY(testSelectionSpy2.count() == 0); + + defaultSelectionSpy.clear(); + testSelectionSpy1.clear(); + testSelectionSpy2.clear(); + + mWidget->setSelectionModel(testSelectionModel1); + HbAutoTest::mouseClick((HbAutoTestMainWindow*)mWindow, mWidget, grid_portrait_pos5, 100); + QTest::qWait(1000); + // Default selection model is not valid any more + QVERIFY(defaultSelectionSpy.count() == 0); + QVERIFY(testSelectionModel1->selectedIndexes().count() == 1); + QVERIFY(testSelectionSpy1.count() == 1); + QVERIFY(testSelectionModel2->selectedIndexes().count() == 0); + QVERIFY(testSelectionSpy2.count() == 0); + + defaultSelectionSpy.clear(); + testSelectionSpy1.clear(); + testSelectionSpy2.clear(); + + mWidget->setSelectionModel(testSelectionModel2); + mWidget->selectAll(); + QVERIFY(testSelectionModel1->selectedIndexes().count() == 1); + QVERIFY(testSelectionSpy1.count() == 0); + QVERIFY(testSelectionModel2->selectedIndexes().count() == 9); + QVERIFY(testSelectionSpy2.count() == 1); + + defaultSelectionSpy.clear(); + testSelectionSpy1.clear(); + testSelectionSpy2.clear(); + + // Setting the same selection model again does nothing + mWidget->setSelectionModel(testSelectionModel2); + QVERIFY(testSelectionModel1->selectedIndexes().count() == 1); + QVERIFY(testSelectionSpy1.count() == 0); + QVERIFY(testSelectionModel2->selectedIndexes().count() == 9); + QVERIFY(testSelectionSpy2.count() == 0); + + defaultSelectionSpy.clear(); + testSelectionSpy1.clear(); + testSelectionSpy2.clear(); + + mWidget->setSelectionModel(testSelectionModel1); + mWidget->clearSelection(); + QVERIFY(testSelectionModel1->selectedIndexes().count() == 0); + QVERIFY(testSelectionSpy1.count() == 1); + QVERIFY(testSelectionModel2->selectedIndexes().count() == 9); + QVERIFY(testSelectionSpy2.count() == 0); + + QTest::qWait(2000); + + delete testSelectionModel1; + delete testSelectionModel2; + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_scrollTo() +{ + qRegisterMetaType("QModelIndex"); + qRegisterMetaType("QItemSelection"); + // TODO: How to verify that items are freed? + + mWindow = new HbMainWindow; + mWindow->viewport()->grabGesture(Qt::PanGesture); + mWindow->viewport()->grabGesture(Qt::TapGesture); // Add TapAndHoldGesture once it's working + mWidget = new HgGrid( Qt::Vertical); + QList requestedIndexes; + TestModel model(&requestedIndexes); + model.generateItems(1024); + mWidget->setModel(&model); + mWindow->addView(mWidget); + mWindow->show(); + QTest::qWait(2000); + + QVERIFY(requestedIndexes.count() == 120); // Scroll buffer size in grid mode is assumed to be 120 + QVERIFY(requestedIndexes.front() == model.index(0, 0)); + QVERIFY(requestedIndexes.back() == model.index(119, 0)); + requestedIndexes.clear(); + + QSignalSpy activatedSpy(mWidget, SIGNAL(activated(QModelIndex))); + QSignalSpy currentSpy(mWidget->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex))); + QSignalSpy selectionSpy(mWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection))); + + mWidget->scrollTo(model.index(100, 0)); + QTest::qWait(1000); + QVERIFY(activatedSpy.count() == 0); // scrollto doesn't activate item + QVERIFY(currentSpy.count() == 0); // scrollto doesn't change the current + QVERIFY(selectionSpy.count() == 0); // scrollto doesn't change the selection + QVERIFY(requestedIndexes.count() == 40); // The whole scroll buffer should be updated + QVERIFY(requestedIndexes.front() == model.index(120, 0)); + QVERIFY(requestedIndexes.back() == model.index(159, 0)); + requestedIndexes.clear(); + + mWidget->scrollTo(model.index(1023, 0)); + QTest::qWait(1000); + QVERIFY(activatedSpy.count() == 0); // scrollto doesn't activate item + QVERIFY(currentSpy.count() == 0); // scrollto doesn't change the current + QVERIFY(selectionSpy.count() == 0); // scrollto doesn't change the selection + QVERIFY(requestedIndexes.count() == 120); // The whole scroll buffer should be updated + QVERIFY(requestedIndexes.front() == model.index(904, 0)); + QVERIFY(requestedIndexes.back() == model.index(1023, 0)); + requestedIndexes.clear(); + + mWidget->scrollTo(QModelIndex()); + QTest::qWait(1000); + QVERIFY(activatedSpy.count() == 0); // scrollto doesn't activate item + QVERIFY(currentSpy.count() == 0); // scrollto doesn't change the current + QVERIFY(selectionSpy.count() == 0); // scrollto doesn't change the selection + QVERIFY(requestedIndexes.count() == 0); // Items are not re-fetched from model + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_addItemsCoverFlow() +{ + // TODO: How to verify that items are freed? + + mWindow = new HbMainWindow; + mWindow->viewport()->grabGesture(Qt::PanGesture); + mWindow->viewport()->grabGesture(Qt::TapGesture); // Add TapAndHoldGesture once it's working + mWidget = new HgMediawall(); + + QList requestedIndexes; + TestModel model(&requestedIndexes); + model.generateItems(120); + mWidget->setModel(&model); + mWindow->addView(mWidget); + mWindow->show(); + + QTest::qWait(2000); + + QVERIFY(requestedIndexes.count() == 40); // Scroll buffer size in coverflow mode is assumed to be 40 + QVERIFY(requestedIndexes.front() == model.index(0, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + requestedIndexes.clear(); + + // Move buffer to the end of items + mWidget->scrollTo(model.index(119, 0)); + QTest::qWait(1000); + requestedIndexes.clear(); + + // Add one item to beginning of buffer + model.insertItems(80, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New item falls outside of buffer as buffer is moved up + requestedIndexes.clear(); + // Last item is now 120 + + // Add many items to beginning of buffer + model.insertItems(81, 4); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items falls outside of buffer as buffer is moved up + requestedIndexes.clear(); + // Last item is now 124 + + // Add one item to the end + model.insertItems(124, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // The new item is requested + QVERIFY(requestedIndexes.front() == model.index(124, 0)); + requestedIndexes.clear(); + // Last item is now 125 + + // Add many items to the end + model.insertItems(125, 4); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 4); // The new items are requested + QVERIFY(requestedIndexes.front() == model.index(125, 0)); + QVERIFY(requestedIndexes.back() == model.index(128, 0)); + requestedIndexes.clear(); + // Last item is now 129 + + // Add one item to middle of buffer + model.insertItems(110, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // The new item is requested + QVERIFY(requestedIndexes.front() == model.index(110, 0)); + requestedIndexes.clear(); + // Last item is now 130 + + // Add many items to middle of buffer + model.insertItems(110, 4); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 4); // The new items are requested + QVERIFY(requestedIndexes.front() == model.index(110, 0)); + QVERIFY(requestedIndexes.back() == model.index(113, 0)); + requestedIndexes.clear(); + // Last item is now 134 + + // Add items to the buffer limit (beginning of buffer) + model.insertItems(90, 20); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New item falls outside of buffer as buffer is moved up + // Last item is now 154 + + // Add items to outside of buffer (before buffer) + model.insertItems(0, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // The new items are not requested + requestedIndexes.clear(); + + // Move buffer to the beginning of items + mWidget->scrollTo(model.index(0, 0)); + QTest::qWait(1000); + requestedIndexes.clear(); + + // Add one item to beginning + model.insertItems(0, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // The new item is requested + QVERIFY(requestedIndexes.front() == model.index(0, 0)); + requestedIndexes.clear(); + + // Add many items to beginning + model.insertItems(0, 5); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // The new items are requested + QVERIFY(requestedIndexes.front() == model.index(0, 0)); + QVERIFY(requestedIndexes.back() == model.index(4, 0)); + requestedIndexes.clear(); + + // Add one item to middle of buffer + model.insertItems(20, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // The new item is requested + QVERIFY(requestedIndexes.front() == model.index(20, 0)); + requestedIndexes.clear(); + + // Add many items to middle of buffer + model.insertItems(20, 5); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // The new items are requested + QVERIFY(requestedIndexes.front() == model.index(20, 0)); + QVERIFY(requestedIndexes.back() == model.index(24, 0)); + requestedIndexes.clear(); + + // Add one item to end of buffer + model.insertItems(39, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // The new item is requested + QVERIFY(requestedIndexes.front() == model.index(39, 0)); + requestedIndexes.clear(); + + // Add many items to end of buffer + model.insertItems(30, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 10); // The new items are requested + QVERIFY(requestedIndexes.front() == model.index(30, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + requestedIndexes.clear(); + + // Add items to outside of buffer (after buffer) + model.insertItems(40, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // The new items are not requested + requestedIndexes.clear(); + + // Add items to the buffer limit (end of buffer) + model.insertItems(35, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // The new items inside buffer are requested + QVERIFY(requestedIndexes.front() == model.index(35, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + + // Move buffer to the middle of items + mWidget->scrollTo(model.index(60, 0)); + QTest::qWait(1000); + requestedIndexes.clear(); + + // Add items to the buffer limit (beginning of buffer) + model.insertItems(35, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // The new items inside buffer are requested + QVERIFY(requestedIndexes.front() == model.index(40, 0)); + QVERIFY(requestedIndexes.back() == model.index(44, 0)); + + // Add items over the whole buffer + model.insertItems(35, 50); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 40); // The new items inside buffer are requested + QVERIFY(requestedIndexes.front() == model.index(40, 0)); + QVERIFY(requestedIndexes.back() == model.index(79, 0)); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_removeItemsCoverFlow() +{ + // TODO: How to verify that items are freed? + + mWindow = new HbMainWindow; + mWindow->viewport()->grabGesture(Qt::PanGesture); + mWindow->viewport()->grabGesture(Qt::TapGesture); // Add TapAndHoldGesture once it's working + mWidget = new HgMediawall(); + + QList requestedIndexes; + TestModel model(&requestedIndexes); + model.generateItems(240); + mWidget->setModel(&model); + mWindow->addView(mWidget); + mWindow->show(); + + QTest::qWait(2000); + + QVERIFY(requestedIndexes.count() == 40); // Scroll buffer size in coverflow mode is assumed to be 40 + QVERIFY(requestedIndexes.front() == model.index(0, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + requestedIndexes.clear(); + + // Move buffer to the end of items + mWidget->scrollTo(model.index(239, 0)); + QTest::qWait(1000); + requestedIndexes.clear(); + + // Remove one item from the beginning of buffer + model.removeItems(200, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // New item is fetched to replace the removed one + QVERIFY(requestedIndexes.front() == model.index(199, 0)); + requestedIndexes.clear(); + // Last item is now 238 + + // Remove many items from beginning of buffer + model.removeItems(199, 4); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 4); // New items are fetched to replace the removed ones + QVERIFY(requestedIndexes.front() == model.index(195, 0)); + QVERIFY(requestedIndexes.back() == model.index(198, 0)); + requestedIndexes.clear(); + // Last item is now 234 + + // Remove one item from the end + model.removeItems(234, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // New item is fetched to replace the removed one + QVERIFY(requestedIndexes.front() == model.index(194, 0)); + requestedIndexes.clear(); + // Last item is now 233 + + // Remove many items from the end + model.removeItems(230, 4); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 4); // New items are fetched to replace the removed ones + QVERIFY(requestedIndexes.front() == model.index(190, 0)); + QVERIFY(requestedIndexes.back() == model.index(193, 0)); + requestedIndexes.clear(); + // Last item is now 229 + + // Remove one item from the middle of buffer + model.removeItems(210, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // New item is fetched to replace the removed one + QVERIFY(requestedIndexes.front() == model.index(189, 0)); + requestedIndexes.clear(); + // Last item is now 228 + + // Remove many items from the middle of buffer + model.removeItems(210, 4); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 4); // New items are fetched to replace the removed ones + QVERIFY(requestedIndexes.front() == model.index(185, 0)); + QVERIFY(requestedIndexes.back() == model.index(188, 0)); + requestedIndexes.clear(); + // Last item is now 224 + + // Remove items from the buffer limit (beginning of buffer) + model.removeItems(180, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // New items are fetched to replace the removed ones + QVERIFY(requestedIndexes.front() == model.index(175, 0)); + QVERIFY(requestedIndexes.back() == model.index(179, 0)); + requestedIndexes.clear(); + // Last item is now 214 + + // Remove items from outside of buffer (before buffer) + model.removeItems(0, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // Buffer is not moved + requestedIndexes.clear(); + // Last item is now 204 + + // Move buffer to the beginning of items + mWidget->scrollTo(model.index(0, 0)); + QTest::qWait(1000); + requestedIndexes.clear(); + + // Remove one item from beginning + model.removeItems(0, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // New item is fetched to replace the removed one + QVERIFY(requestedIndexes.front() == model.index(39, 0)); + requestedIndexes.clear(); + // Last item is now 203 + + // Remove many items from beginning + model.removeItems(0, 5); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // New items are fetched to replace the removed ones + QVERIFY(requestedIndexes.front() == model.index(35, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + requestedIndexes.clear(); + // Last item is now 198 + + // Remove one item from the middle of buffer + model.removeItems(20, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // New item is fetched to replace the removed one + QVERIFY(requestedIndexes.front() == model.index(39, 0)); + requestedIndexes.clear(); + // Last item is now 197 + + // Remove many items from the middle of buffer + model.removeItems(20, 5); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // New items are fetched to replace the removed ones + QVERIFY(requestedIndexes.front() == model.index(35, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + requestedIndexes.clear(); + // Last item is now 192 + + // Remove one item from the end of buffer + model.removeItems(39, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // New item is fetched to replace the removed one + QVERIFY(requestedIndexes.front() == model.index(39, 0)); + requestedIndexes.clear(); + // Last item is now 191 + + // Remove many items from the end of buffer + model.removeItems(30, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 10); // New items are fetched to replace the removed ones + QVERIFY(requestedIndexes.front() == model.index(30, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + requestedIndexes.clear(); + // Last item is now 181 + + // Remove items from outside of buffer (after buffer) + model.removeItems(50, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // Buffer is not updated + requestedIndexes.clear(); + // Last item is now 171 + + // Remove items from the buffer limit (end of buffer) + model.insertItems(35, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // The new items inside buffer are requested + QVERIFY(requestedIndexes.front() == model.index(35, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + // Last item is now 161 + + // Move buffer to the middle of items + mWidget->scrollTo(model.index(80, 0)); + QTest::qWait(1000); + requestedIndexes.clear(); + + // Remove items from the buffer limit (beginning of buffer) + model.removeItems(59, 2); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 1); // New item is fetched to replace the one removed from the buffer + QVERIFY(requestedIndexes.front() == model.index(99, 0)); + // Last item is now 159 + + // Remove items over the whole buffer + model.removeItems(55, 50); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 40); // Whole buffer is updated + QVERIFY(requestedIndexes.front() == model.index(60, 0)); + QVERIFY(requestedIndexes.back() == model.index(99, 0)); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +void TestGanesWidgets::test_moveItemsCoverFlow() +{ + // TODO: How to verify that items are freed? + + mWindow = new HbMainWindow; + mWindow->viewport()->grabGesture(Qt::PanGesture); + mWindow->viewport()->grabGesture(Qt::TapGesture); // Add TapAndHoldGesture once it's working + mWidget = new HgMediawall(); + + QList requestedIndexes; + TestModel model(&requestedIndexes); + model.generateItems(120); + mWidget->setModel(&model); + mWindow->addView(mWidget); + mWindow->show(); + + QTest::qWait(2000); + + QVERIFY(requestedIndexes.count() == 40); // Scroll buffer size in coverflow mode is assumed to be 40 + QVERIFY(requestedIndexes.front() == model.index(0, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + requestedIndexes.clear(); + + // Move one item forward + model.moveItems(0, 20, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + model.moveItems(0, 2, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + model.moveItems(0, 39, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + // Move many items forward + model.moveItems(0, 20, 5); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + // Move one item backward + model.moveItems(39, 20, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + model.moveItems(39, 38, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + model.moveItems(39, 0, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + // Move many items backward + model.moveItems(30, 20, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + // This should do nothing + model.moveItems(20, 20, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + // Move items from the border of the buffer forward + model.moveItems(35, 50, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // New items are fetched to replace the moved ones + QVERIFY(requestedIndexes.front() == model.index(35, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + requestedIndexes.clear(); + + // Move items from the border of the buffer backward + model.moveItems(35, 20, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // Items that were originally outside of buffer are fetched + QVERIFY(requestedIndexes.front() == model.index(25, 0)); + QVERIFY(requestedIndexes.back() == model.index(29, 0)); + requestedIndexes.clear(); + + // Move items from the buffer outside it + model.moveItems(20, 90, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 10); // New items are fetched to replace the moved ones + QVERIFY(requestedIndexes.front() == model.index(30, 0)); + QVERIFY(requestedIndexes.back() == model.index(39, 0)); + requestedIndexes.clear(); + + // Move items from outside the buffer inside it + model.moveItems(90, 20, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 10); // Moved items are fetched + QVERIFY(requestedIndexes.front() == model.index(20, 0)); + QVERIFY(requestedIndexes.back() == model.index(29, 0)); + requestedIndexes.clear(); + + // Move buffer to the end of items + mWidget->scrollTo(model.index(119, 0)); + QTest::qWait(1000); + requestedIndexes.clear(); + + // Move one item forward + model.moveItems(80, 100, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + model.moveItems(80, 82, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + model.moveItems(80, 119, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + // Move many items forward + model.moveItems(80, 100, 5); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + // Move one item backward + model.moveItems(119, 100, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + model.moveItems(119, 118, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + model.moveItems(119, 80, 1); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + // Move many items backward + model.moveItems(110, 95, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 0); // New items are not fetched as the changes happened inside the buffer + + // Move items from the border of the buffer backward + model.moveItems(75, 60, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // New items are fetched to replace the moved ones + QVERIFY(requestedIndexes.front() == model.index(80, 0)); + QVERIFY(requestedIndexes.back() == model.index(84, 0)); + requestedIndexes.clear(); + + // Move items from the border of the buffer forward + model.moveItems(75, 100, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 5); // Items that were originally outside of buffer are fetched + QVERIFY(requestedIndexes.front() == model.index(100, 0)); + QVERIFY(requestedIndexes.back() == model.index(104, 0)); + requestedIndexes.clear(); + + // Move items from the buffer outside it + model.moveItems(100, 10, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 10); // New items are fetched to replace the moved ones + QVERIFY(requestedIndexes.front() == model.index(80, 0)); + QVERIFY(requestedIndexes.back() == model.index(89, 0)); + requestedIndexes.clear(); + + // Move items from outside the buffer inside it + model.moveItems(10, 100, 10); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 10); // Moved items are fetched + QVERIFY(requestedIndexes.front() == model.index(100, 0)); + QVERIFY(requestedIndexes.back() == model.index(109, 0)); + requestedIndexes.clear(); + + // Move buffer to the middle of items + mWidget->scrollTo(model.index(60, 0)); + QTest::qWait(1000); + requestedIndexes.clear(); + + // Move items over the whole buffer forward + model.moveItems(35, 110, 50); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 40); // Whole buffer is updated + QVERIFY(requestedIndexes.front() == model.index(40, 0)); + QVERIFY(requestedIndexes.back() == model.index(79, 0)); + + // Move items over the whole buffer backward + model.moveItems(35, 10, 50); + QTest::qWait(1000); + QVERIFY(requestedIndexes.count() == 40); // Whole buffer is updated + QVERIFY(requestedIndexes.front() == model.index(40, 0)); + QVERIFY(requestedIndexes.back() == model.index(79, 0)); + + QTest::qWait(2000); + + delete mWindow; + mWindow = 0; +} + +#ifdef _UNITTEST_GANESWIDGETS_LOG_TO_C_ + int main (int argc, char* argv[]) + { + HbApplication app(argc, argv); + TestGanesWidgets tc; +// int c = 3; +// char* v[] = {argv[0], "-o", "c:/test.txt"}; + return QTest::qExec(&tc, argc, argv); +// return QTest::qExec(&tc, c, v); + } +#else + QTEST_MAIN(TestGanesWidgets) +#endif + +#include "unittest_ganeswidgets.moc" + +// EOF diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/unit/unittest_ganeswidgets.pro --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/unit/unittest_ganeswidgets.pro Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,31 @@ +# Copyright (c) 2009 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: + +TEMPLATE = app +CONFIG += qtestlib \ + hb +TARGET = unittest_ganeswidgets +DEFINES += _UNITTEST_GANESWIDGETS_LOG_TO_C_ +TARGET.CAPABILITY = All \ + -TCB +INCLUDEPATH += . \ + inc \ + $$APP_LAYER_SYSTEMINCLUDE \ + $$MW_LAYER_SYSTEMINCLUDE \ + /sf/mw/hb/src/hbcore/gui +LIBS += -lestor.dll \ + -lganeswidgets.dll + +# Input +SOURCES += hbautotest.cpp \ + unittest_ganeswidgets.cpp +RESOURCES = unittest_ganeswidgets.qrc +HEADERS = diff -r 000000000000 -r 89c329efa980 ganeswidgets/tsrc/unit/unittest_ganeswidgets.qrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ganeswidgets/tsrc/unit/unittest_ganeswidgets.qrc Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,5 @@ + + + startupHG.jpg + + diff -r 000000000000 -r 89c329efa980 hgwidgets.pro --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgwidgets.pro Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,25 @@ +# +# Copyright (c) 2009 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: +# + +TEMPLATE = subdirs + +# Platforms +SYMBIAN_PLATFORMS = WINSCW ARMV5 + +CONFIG += ordered + +SUBDIRS += hgwidgets_plat/hgwidgets_plat.pro +SUBDIRS += ganeswidgets/ganeswidgets.pro diff -r 000000000000 -r 89c329efa980 hgwidgets_plat/ganeswidgets_api/ganeswidgets_api.pri --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgwidgets_plat/ganeswidgets_api/ganeswidgets_api.pri Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,20 @@ +# +# Copyright (c) 2009 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: +# + +PUBLIC_HEADERS += ganeswidgets_api/inc/hgwidgets.h \ + ganeswidgets_api/inc/hggrid.h \ + ganeswidgets_api/inc/hgmediawall.h + \ No newline at end of file diff -r 000000000000 -r 89c329efa980 hgwidgets_plat/ganeswidgets_api/inc/hggrid.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgwidgets_plat/ganeswidgets_api/inc/hggrid.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,39 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGGRID_H +#define HGGRID_H + +#include + +class HgGridPrivate; + +class HG_WIDGETS_EXPORT HgGrid : public HgWidget +{ + Q_OBJECT +public: + + HgGrid(Qt::Orientation scrollDirection, QGraphicsItem *parent = 0 ); + virtual ~HgGrid(); + +private: + Q_DECLARE_PRIVATE_D(d_ptr, HgGrid) + Q_DISABLE_COPY(HgGrid) +}; + +#endif //HGGRID_H + diff -r 000000000000 -r 89c329efa980 hgwidgets_plat/ganeswidgets_api/inc/hgmediawall.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgwidgets_plat/ganeswidgets_api/inc/hgmediawall.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,60 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGMEDIAWALL_H +#define HGMEDIAWALL_H + +#include + +class HgMediawallPrivate; + +class HG_WIDGETS_EXPORT HgMediawall : public HgWidget +{ + Q_OBJECT + Q_PROPERTY(LabelPosition titlePosition READ titlePosition WRITE setTitlePosition) + Q_PROPERTY(LabelPosition descriptionPosition READ descriptionPosition WRITE setDescriptionPosition) + Q_PROPERTY(HbFontSpec titleFontSpec READ titleFontSpec WRITE setTitleFontSpec) + Q_PROPERTY(HbFontSpec descriptionFontSpec READ descriptionFontSpec WRITE setDescriptionFontSpec) + Q_ENUMS(LabelPosition) + +public: + + HgMediawall(QGraphicsItem *parent = 0 ); + virtual ~HgMediawall(); + + enum LabelPosition { + PositionNone = 0, + PositionAboveImage, + PositionBelowImage + }; + + void setTitlePosition(LabelPosition position); + LabelPosition titlePosition() const; + void setDescriptionPosition(LabelPosition position); + LabelPosition descriptionPosition() const; + void setTitleFontSpec(const HbFontSpec &fontSpec); + HbFontSpec titleFontSpec() const; + void setDescriptionFontSpec(const HbFontSpec &fontSpec); + HbFontSpec descriptionFontSpec() const; + +private: + Q_DECLARE_PRIVATE_D(d_ptr, HgMediawall) + Q_DISABLE_COPY(HgMediawall) +}; + +#endif //HGMEDIAWALL_H + diff -r 000000000000 -r 89c329efa980 hgwidgets_plat/ganeswidgets_api/inc/hgwidgets.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgwidgets_plat/ganeswidgets_api/inc/hgwidgets.h Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,148 @@ +/* +* Copyright (c) 2009 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: +* +*/ + +#ifndef HGWIDGET_H +#define HGWIDGET_H + +#include +#include +#include +#include + +#ifdef BUILD_HG_WIDGETS +# define HG_WIDGETS_EXPORT Q_DECL_EXPORT +# define HG_WIDGETS_PRIVATE_EXPORT Q_DECL_EXPORT +#else +# define HG_WIDGETS_EXPORT Q_DECL_IMPORT +# define HG_WIDGETS_PRIVATE_EXPORT Q_DECL_IMPORT +#endif // BUILD_HG_WIDGETS + +class HgWidgetPrivate; +class HbScrollBar; + +class HG_WIDGETS_EXPORT HgWidget : public HbWidget +{ + Q_OBJECT + Q_PROPERTY(bool longPressEnabled READ longPressEnabled WRITE setLongPressEnabled ) + Q_PROPERTY(ScrollBarPolicy scrollBarPolicy READ scrollBarPolicy WRITE setScrollBarPolicy) + Q_PROPERTY(SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(IndexFeedbackPolicy IndexFeedbackPolicy READ indexFeedbackPolicy WRITE setIndexFeedbackPolicy) + Q_ENUMS(ScrollBarPolicy) + Q_ENUMS(HgWidgetType) + Q_ENUMS(SelectionMode) + Q_ENUMS(IndexFeedbackPolicy) +public: + + enum HgDataRole + { + HgVisibilityRole = Qt::UserRole + 1 + }; + + enum IndexFeedbackPolicy { + IndexFeedbackNone = 0, + IndexFeedbackSingleCharacter, + IndexFeedbackThreeCharacter, + IndexFeedbackString + }; + + virtual ~HgWidget (); + + enum ScrollBarPolicy { + ScrollBarAsNeeded = Qt::ScrollBarAsNeeded, + ScrollBarAlwaysOff = Qt::ScrollBarAlwaysOff, + ScrollBarAlwaysOn = Qt::ScrollBarAlwaysOn, + ScrollBarAutoHide + }; + + virtual void setModel(QAbstractItemModel *model); + QAbstractItemModel *model() const; + + void setSelectionModel(QItemSelectionModel *selectionModel); + QItemSelectionModel *selectionModel() const; + + enum SelectionMode { + NoSelection = 0, + SingleSelection, + MultiSelection, + ContiguousSelection + }; + + SelectionMode selectionMode() const; + void setSelectionMode(SelectionMode mode, bool resetSelection = true); + void selectAll(); + void clearSelection(); + + QModelIndex currentIndex() const; + void setCurrentIndex(const QModelIndex &index, + QItemSelectionModel::SelectionFlags selectionFlag=QItemSelectionModel::NoUpdate); + + void scrollTo(const QModelIndex &index); + + bool longPressEnabled() const; + void setLongPressEnabled(bool value); + + ScrollBarPolicy scrollBarPolicy() const; + void setScrollBarPolicy(ScrollBarPolicy policy); + HbScrollBar *scrollBar() const; + void setScrollBar(HbScrollBar *scrollBar); + + bool getItemOutline(const QModelIndex& index, QPolygonF& points); + Qt::Orientation scrollDirection() const; + + QList getVisibleItemIndices() const; + + void setIndexFeedbackPolicy( IndexFeedbackPolicy policy); + IndexFeedbackPolicy indexFeedbackPolicy() const; + +signals: + void activated(const QModelIndex &index); + void longPressed(const QModelIndex &index, const QPointF &coords); + void scrollingStarted(); + void scrollingEnded(); +public slots: + + void aboutToChangeOrientation(); + void orientationChanged(Qt::Orientation orientation); + +protected slots: + + void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + +protected: + + bool eventFilter(QObject *obj,QEvent *event); + + bool event(QEvent *event); + + HgWidget(HbWidgetPrivate* widgetPrivate, QGraphicsItem *parent = 0); + +private: + Q_DECLARE_PRIVATE_D(d_ptr, HgWidget) + Q_DISABLE_COPY(HgWidget) + Q_PRIVATE_SLOT(d_func(), void _q_scrollPositionChanged(qreal index, bool scrollBarAnimation)) + Q_PRIVATE_SLOT(d_func(), void _q_releaseItems(int releaseStart, int releaseEnd)) + Q_PRIVATE_SLOT(d_func(), void _q_requestItems(int requestStart, int requestEnd)) + Q_PRIVATE_SLOT(d_func(), void _q_hideScrollBars() ) + Q_PRIVATE_SLOT(d_func(), void _q_thumbPositionChanged(qreal value, Qt::Orientation orientation)) + Q_PRIVATE_SLOT(d_func(), void _q_insertRows(const QModelIndex &parent, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_removeRows(const QModelIndex &parent, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_moveRows(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)) + Q_PRIVATE_SLOT(d_func(), void _q_groovePressed(qreal, Qt::Orientation)) +}; + +#endif //HGWIDGET_H + diff -r 000000000000 -r 89c329efa980 hgwidgets_plat/hgwidgets_plat.pro --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgwidgets_plat/hgwidgets_plat.pro Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,32 @@ +# +# Copyright (c) 2009 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: +# + +TEMPLATE = subdirs + +SYMBIAN_PLATFORMS = WINSCW ARMV5 + +CONFIG += ordered + +include(ganeswidgets_api/ganeswidgets_api.pri) + +symbian { + headers.sources = $$PUBLIC_HEADERS + BLD_INF_RULES.prj_exports += "$${LITERAL_HASH}include " + for(header, headers.sources) { + FILENAME = $$basename(header) + BLD_INF_RULES.prj_exports += "$$header MW_LAYER_PUBLIC_EXPORT_PATH(hgwidgets/$$FILENAME)" + } +} \ No newline at end of file diff -r 000000000000 -r 89c329efa980 layers.sysdef.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layers.sysdef.xml Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,24 @@ + +]> + + + + + + + + + + + + + + + + + + + + + + diff -r 000000000000 -r 89c329efa980 sysdef_1_5_1.dtd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sysdef_1_5_1.dtd Mon Apr 19 14:40:06 2010 +0300 @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +