src/hbwidgets/itemviews/hbgridlayout_p_p.cpp
changeset 0 16d8024aca5e
child 23 e6ad4ef83b23
child 34 ed14f46c0e55
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbWidgets module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 #include <hbgridlayout_p_p.h>
       
    26 #include <hbgridlayout_p.h>
       
    27 #include <hbabstractviewitem.h>
       
    28 #include <hblayoututils_p.h>
       
    29 
       
    30 #include <QGraphicsItem>
       
    31 #include <QWidget> // for QWIDGETSIZE_MAX
       
    32 #include <QTimer>
       
    33 #include <QDebug>
       
    34 
       
    35 namespace {
       
    36 static const int ANIMATION_TIMEOUT = 20;
       
    37 static const qreal ANIMATION_DELAY_RESOLUTION = 0.1;
       
    38 }
       
    39 
       
    40 HbGridLayoutPrivate::HbGridLayoutPrivate():
       
    41         mMaxVisRows(1),
       
    42         mMaxVisColumns(1),
       
    43         mScrollDirection(Qt::Vertical),
       
    44         mItemSize(QSize(0,0)),
       
    45         mPreferedSizeHint(QSize(0,0)),
       
    46         mMaxSizeHint(QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)),
       
    47         mSpacing(0),
       
    48         mLeftMargin(0),
       
    49         mRightMargin(0),
       
    50         mTopMargin(0),
       
    51         mBottomMargin(0),
       
    52         mClearCacheHint(false),
       
    53         mClearGeometry(false),
       
    54         mRecycling(false),
       
    55         mGeometry(QRectF()),
       
    56         q_ptr(0),
       
    57         mTimer(0),
       
    58         mEffectLoaded(false)
       
    59 
       
    60 {
       
    61 }
       
    62 
       
    63 HbGridLayoutPrivate::~HbGridLayoutPrivate()
       
    64 {
       
    65 
       
    66 }
       
    67 
       
    68 void HbGridLayoutPrivate::init()
       
    69 {
       
    70     Q_Q(HbGridLayout);
       
    71 
       
    72     mTimer = new QTimer(q);
       
    73     q->connect(mTimer, SIGNAL(timeout()), q, SLOT(_q_timerUpdate()));
       
    74 
       
    75     mEffectLoaded = HbEffect::add("gridviewitem", "gridviewitem_reposition", "reposition");
       
    76 }
       
    77 
       
    78 void HbGridLayoutPrivate::setSize(const QSizeF &size,int &targetCount)
       
    79 {
       
    80     qreal newHeight = size.height() - (mMaxVisRows * mSpacing) - mTopMargin - mBottomMargin;
       
    81     qreal newWidth = size.width() - (mMaxVisColumns * mSpacing) - mLeftMargin - mRightMargin;
       
    82     if(newHeight <0)
       
    83         newHeight = 0;
       
    84     if(newWidth <0)
       
    85         newWidth = 0;
       
    86     mItemSize.setHeight(newHeight/ mMaxVisRows);
       
    87     mItemSize.setWidth(newWidth/ mMaxVisColumns);
       
    88     targetCount = mMaxVisColumns * mMaxVisRows;
       
    89     reset();
       
    90 }
       
    91 
       
    92 void HbGridLayoutPrivate::setMargins(qreal topMargin, qreal bottomMargin, qreal leftMargin, qreal rightMargin)
       
    93 {
       
    94     mLeftMargin = leftMargin;
       
    95     mRightMargin = rightMargin;
       
    96     mTopMargin = topMargin;
       
    97     mBottomMargin = bottomMargin;
       
    98 }
       
    99 
       
   100 void HbGridLayoutPrivate::setGeometry(const QRectF &effectiveRect)
       
   101 {
       
   102         QRectF adjustRect(effectiveRect);
       
   103         adjustRect.adjust(+mLeftMargin, +mTopMargin, -mRightMargin, -mBottomMargin);
       
   104         if(Qt::Vertical == mScrollDirection)
       
   105             setVerticalGeometry(adjustRect);
       
   106         else
       
   107             setHorizontalGeometry(adjustRect);
       
   108         mClearGeometry = false;
       
   109 }
       
   110 
       
   111 /*!
       
   112     From QGraphicsLayout.
       
   113 
       
   114     The minimum size hint is the minimum size of the first child layout item.
       
   115 
       
   116     The preferred size hint is the sum of the preferred size hints of the
       
   117     child layout items.
       
   118 
       
   119     The maximum size hint "unlimited", i.e. the child layout items do not
       
   120     affect the maximum size hint.
       
   121  */
       
   122 QSizeF HbGridLayoutPrivate::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
       
   123 {
       
   124     QSizeF sizeHint( 0, 0 );
       
   125     if(which == Qt::MaximumSize) {
       
   126         // Sub items do not affect the maximum size hint.
       
   127         sizeHint = mMaxSizeHint;
       
   128     } else if(which == Qt::PreferredSize) {
       
   129         if(!mClearCacheHint){
       
   130             sizeHint = mPreferedSizeHint;
       
   131         }
       
   132         else {
       
   133             constraint.boundedTo(QSizeF(0,0));
       
   134             sizeHint = Qt::Vertical ==mScrollDirection?verSizeHint()
       
   135                                                               :horSizeHint();
       
   136             const_cast<HbGridLayoutPrivate*>( this )->mPreferedSizeHint = sizeHint;
       
   137             const_cast<HbGridLayoutPrivate*>( this )->mClearCacheHint = false;
       
   138         }
       
   139         
       
   140     }
       
   141     else {
       
   142         if(mItemSize.isValid()) {
       
   143          sizeHint = mItemSize;
       
   144         }
       
   145     }
       
   146     return sizeHint;
       
   147 }
       
   148 
       
   149 /*!
       
   150     From QGraphicsLayout.
       
   151  */
       
   152 void HbGridLayoutPrivate::setVerticalGeometry( const QRectF &effectiveRect ){
       
   153 
       
   154     Q_Q( HbGridLayout );
       
   155     qreal y (effectiveRect.y());
       
   156     qreal x (effectiveRect.x());
       
   157     int dinamicCount(mMaxVisColumns);
       
   158     int itemCount(q->count());
       
   159     int r (0);
       
   160     qreal tempheight(0);
       
   161     for(int i=0;i<itemCount;i++) {
       
   162         if (r%dinamicCount == 0){
       
   163             r=0;
       
   164             x =effectiveRect.x();
       
   165         }
       
   166         QGraphicsLayoutItem *item = q->itemAt(i);
       
   167         if(item){
       
   168             item->setPreferredSize(mItemSize.width(),mItemSize.height());
       
   169             item->setMinimumSize(mItemSize.width(),mItemSize.height());
       
   170             item->setMaximumSize(mItemSize.width(),mItemSize.height());
       
   171             item->setGeometry( QRectF(x,
       
   172                                       y,
       
   173                                       mItemSize.width(),
       
   174                                       mItemSize.height() ));
       
   175             tempheight = qMax(tempheight,mItemSize.height());
       
   176             x += mItemSize.width()+mSpacing;
       
   177             if (r == dinamicCount-1) {
       
   178                 y += tempheight+mSpacing;
       
   179             }
       
   180             ++r;
       
   181         }
       
   182     }
       
   183 }
       
   184 
       
   185 /*!
       
   186     From QGraphicsLayout.
       
   187  */
       
   188 void HbGridLayoutPrivate::setHorizontalGeometry(const QRectF &effectiveRect){
       
   189 
       
   190     Q_Q(HbGridLayout);
       
   191     qreal y (effectiveRect.y());
       
   192     qreal x (effectiveRect.x());
       
   193     int dinamicCount(mMaxVisRows);
       
   194     int itemCount(q->count());
       
   195     int r(0);
       
   196     qreal tempWidth(0);
       
   197     for (int i = 0; i < itemCount; i++) {
       
   198         if (r%dinamicCount == 0){
       
   199             if(r!=0)
       
   200                 r=0;
       
   201             y =effectiveRect.y();
       
   202         }
       
   203         QGraphicsLayoutItem *item = q->itemAt(i);
       
   204         if(item){
       
   205             item->setPreferredSize(mItemSize.width(),mItemSize.height());
       
   206             item->setMinimumSize(mItemSize.width(),mItemSize.height());
       
   207             item->setMaximumSize(mItemSize.width(),mItemSize.height());
       
   208             item->setGeometry(QRectF(x,
       
   209                                      y,
       
   210                                      mItemSize.width(),
       
   211                                      mItemSize.height()));
       
   212             tempWidth = qMax(tempWidth,mItemSize.width());
       
   213             y += mItemSize.height()+mSpacing;
       
   214             if (r == dinamicCount-1) {
       
   215                 x += tempWidth+mSpacing;
       
   216             }
       
   217             ++r;
       
   218         }
       
   219     }
       
   220 }
       
   221 
       
   222 QSizeF HbGridLayoutPrivate::verSizeHint() const{
       
   223 
       
   224     Q_Q( const HbGridLayout );
       
   225     int dinamicCount(mMaxVisColumns);
       
   226     int itemCount(q->count());
       
   227     QSizeF tempSize(0,0);
       
   228     int r(0);
       
   229     QSizeF sizeHint(0,0);
       
   230     for (int i=0;i<itemCount;i++) {
       
   231         if ((r%dinamicCount == 0)||(i == itemCount -1 )){
       
   232             r=0;
       
   233             sizeHint.rwidth() = qMax( tempSize.width(), sizeHint.width() );
       
   234             tempSize.setWidth(0);
       
   235         }
       
   236         QGraphicsLayoutItem *item = q->itemAt(i);
       
   237         if(item){
       
   238             if(mItemSize.isValid()) {
       
   239                 tempSize.rwidth() += (mItemSize.width()+mSpacing);
       
   240                 tempSize.rheight() = qMax(tempSize.height(),(mItemSize.height()+mSpacing));
       
   241             }
       
   242         }
       
   243         if((r == dinamicCount-1) ||(i == itemCount -1)) {
       
   244             sizeHint.rheight() = sizeHint.height() + tempSize.height();
       
   245         }
       
   246         ++r;
       
   247     }
       
   248     sizeHint.rheight() += mTopMargin + mBottomMargin;
       
   249     sizeHint.rwidth() += mLeftMargin + mRightMargin;
       
   250     return sizeHint;
       
   251 }
       
   252 
       
   253 QSizeF HbGridLayoutPrivate::horSizeHint() const{
       
   254 
       
   255     Q_Q(const HbGridLayout);
       
   256     int dinamicCount(mMaxVisRows);
       
   257     int itemCount(q->count());
       
   258     QSizeF tempSize( 0, 0 );
       
   259     QSizeF sizeHint( 0, 0 );
       
   260     int r(0);
       
   261     for (int i=0;i<itemCount;i++) {
       
   262         if ((r%dinamicCount == 0)||(i == itemCount -1)){
       
   263             r=0;
       
   264             sizeHint.rheight() = qMax(tempSize.height(),sizeHint.height());
       
   265             tempSize.setHeight(0);
       
   266         }
       
   267         QGraphicsLayoutItem *item = q->itemAt(i);
       
   268         if(item){
       
   269             if(mItemSize.isValid()) {
       
   270                 tempSize.rheight() += (mItemSize.height()+mSpacing);
       
   271                 tempSize.rwidth() = qMax(tempSize.width(),(mItemSize.width()+mSpacing));
       
   272             }
       
   273         }
       
   274         if((r == dinamicCount-1) ||(i == itemCount -1)) {
       
   275             sizeHint.rwidth() = sizeHint.width() + tempSize.width();
       
   276         }
       
   277         ++r;
       
   278     }
       
   279     sizeHint.rheight() +=mLeftMargin + mRightMargin;
       
   280     sizeHint.rwidth() += mTopMargin + mBottomMargin;
       
   281     return sizeHint;
       
   282 }
       
   283 
       
   284 
       
   285 void HbGridLayoutPrivate::reset()
       
   286 {
       
   287     mClearCacheHint = true;
       
   288     mClearGeometry = true;
       
   289 }
       
   290 
       
   291 void HbGridLayoutPrivate::insertItem(QGraphicsLayoutItem *item, int index, bool animate, bool reset)
       
   292 {
       
   293     index = qMin(index, mItems.count());
       
   294     if (index < 0) {
       
   295         index = mItems.count();
       
   296     }
       
   297     HbLayoutUtils::addChildItem(q_ptr, item);
       
   298 
       
   299     if (animate) {
       
   300         updateAnimationList(item, index - 1, HbGridLayout::InsertAnimation);
       
   301     }
       
   302 
       
   303     mItems.insert(index, item);
       
   304 
       
   305     if (reset) {
       
   306         this->reset();
       
   307     }
       
   308 
       
   309     if (animate && !mAnimatedItems.isEmpty()) {
       
   310         if (!mTimer->isActive()) {
       
   311             mTimer->start(ANIMATION_TIMEOUT);
       
   312         }
       
   313 
       
   314         q_ptr->invalidate();
       
   315         q_ptr->activate();
       
   316 
       
   317         _q_timerUpdate(false);
       
   318     } else if (mAnimatedItems.isEmpty()) {
       
   319         mTimer->stop();
       
   320     }
       
   321 }
       
   322 
       
   323 void HbGridLayoutPrivate::removeItem(QGraphicsLayoutItem *item, int index, bool animate)
       
   324 {
       
   325     for (int i = mAnimatedItems.count() - 1; i >= 0; --i) {
       
   326         AnimationData *itemData = mAnimatedItems.at(i);
       
   327         if (itemData->item == item->graphicsItem()) {
       
   328             stopAnimation(itemData);
       
   329         } 
       
   330         
       
   331         if (itemData->startItem == item) {
       
   332             itemData->startItem = 0;
       
   333         }
       
   334     }
       
   335 
       
   336     if (animate) {
       
   337         updateAnimationList(item, index, HbGridLayout::RemoveAnimation);
       
   338     }
       
   339 
       
   340     mItems.removeAt(index);
       
   341 
       
   342     item->setParentLayoutItem(0);
       
   343     reset();
       
   344 
       
   345     if (animate && !mAnimatedItems.isEmpty()) {
       
   346         if (!mTimer->isActive()) {
       
   347             mTimer->start(ANIMATION_TIMEOUT);
       
   348         }
       
   349 
       
   350         q_ptr->invalidate();
       
   351         q_ptr->activate();
       
   352 
       
   353         _q_timerUpdate(false);
       
   354     } else if (mAnimatedItems.isEmpty()) {
       
   355         mTimer->stop();
       
   356     }
       
   357 }
       
   358 
       
   359 /*!
       
   360     First stops the current item animation if it was animated. Then creates a new animation data for next index
       
   361     items if not already present.
       
   362 */
       
   363 void HbGridLayoutPrivate::updateAnimationList(QGraphicsLayoutItem *item, int index, HbGridLayout::AnimationType type)
       
   364 {
       
   365     if (!mEffectLoaded) {
       
   366         emit q_ptr->animationFinished(item, type);
       
   367         return;
       
   368     }
       
   369 
       
   370 
       
   371     q_ptr->activate();
       
   372 
       
   373     int itemCount = mItems.count();
       
   374     if ((index + 1) >= itemCount) {
       
   375         emit q_ptr->animationFinished(item, type);
       
   376     } else {
       
   377         for (int i = index + 1; i < itemCount; ++i) {
       
   378             HbAbstractViewItem *viewItem = qobject_cast<HbAbstractViewItem *>(static_cast<QGraphicsWidget *>(mItems.at(i)->graphicsItem()));
       
   379             if (!viewItem->modelIndex().isValid()) {
       
   380                 if (i == (index + 1)) {
       
   381                     emit q_ptr->animationFinished(item, type);
       
   382                 }
       
   383                 break;
       
   384             }
       
   385 
       
   386             AnimationData *data = animationData(viewItem);            
       
   387             if (!data) {
       
   388                 data = new AnimationData;
       
   389                 mAnimatedItems.append(data);
       
   390 
       
   391                 data->item = viewItem;
       
   392                 QTransform itemTransform = data->item->transform();
       
   393                 data->originalM31 = itemTransform.m31();
       
   394                 data->originalM32 = itemTransform.m32();
       
   395                 data->originalZValue = data->item->zValue();
       
   396                 data->item->setZValue(data->originalZValue + 1);
       
   397                
       
   398                 data->startDelay = (i - index - 1) * ANIMATION_DELAY_RESOLUTION;
       
   399                 data->startPos = data->item->pos();
       
   400                 data->startScenePos = data->item->scenePos();
       
   401 
       
   402                 if (i == (index + 1)) {
       
   403                     if (type == HbGridLayout::RemoveAnimation) {
       
   404                         data->startItem = mItems.at(i);
       
   405                     } else {
       
   406                         data->startItem = item;
       
   407                     }
       
   408                     data->type = type;
       
   409                 } else {
       
   410                     data->startItem = 0;
       
   411                 }
       
   412             } else {
       
   413                 if (i == (index + 1)) {
       
   414                     if (data->startItem) {
       
   415                         emit q_ptr->animationFinished(data->startItem, data->type);
       
   416                     }
       
   417 
       
   418                     if (type == HbGridLayout::RemoveAnimation) {
       
   419                         data->startItem = mItems.at(i);
       
   420                     } else {
       
   421                         data->startItem = item;
       
   422                     }
       
   423 
       
   424                 data->type = type;
       
   425                 }
       
   426                 break;
       
   427             }
       
   428         }
       
   429     }
       
   430 }
       
   431 
       
   432 void HbGridLayoutPrivate::_q_timerUpdate(bool updateProgress)
       
   433 {
       
   434     bool stopTimer = true;
       
   435 
       
   436     int itemCount = mAnimatedItems.count();
       
   437     for (int i = itemCount - 1; i >= 0; --i) {
       
   438         AnimationData *data = mAnimatedItems.at(i);
       
   439         
       
   440         if (!HbEffect::effectRunning(data->item, "reposition")) {
       
   441             if (updateProgress) {
       
   442                 if (data->startDelay <= 0) {
       
   443                     QTransform transform;
       
   444                     transform.setMatrix(transform.m11(), transform.m12(), transform.m13(), 
       
   445                         transform.m21(), transform.m22(), transform.m23(),
       
   446                         data->originalM31, data->originalM32, transform.m33());
       
   447                     data->item->setTransform(transform);
       
   448 
       
   449                     QRectF extRect(data->startScenePos, data->item->boundingRect().size());
       
   450                     HbEffect::start(data->item, "gridviewitem", "reposition", q_ptr, "effectFinished", QVariant(), extRect);
       
   451                 } else {
       
   452 	                data->startDelay -= ANIMATION_DELAY_RESOLUTION;
       
   453                     stopTimer = false;
       
   454 			    }
       
   455             } else {
       
   456                 QPointF delta = data->startPos - data->item->pos();
       
   457                 data->item->setTransform(QTransform::fromTranslate(delta.x(), delta.y()), false);
       
   458                 stopTimer = false;
       
   459             }
       
   460         } 
       
   461     }
       
   462 
       
   463     if (stopTimer) {
       
   464         mTimer->stop();
       
   465     }
       
   466 }
       
   467 
       
   468 void HbGridLayoutPrivate::stopAnimation(AnimationData *data)
       
   469 {
       
   470     if (data) {
       
   471         QTransform transform;
       
   472         transform.setMatrix(transform.m11(), transform.m12(), transform.m13(), 
       
   473             transform.m21(), transform.m22(), transform.m23(),
       
   474             data->originalM31, data->originalM32, transform.m33());
       
   475         data->item->setTransform(transform);
       
   476 
       
   477         if (HbEffect::effectRunning(data->item, "reposition")) {
       
   478             HbEffect::cancel(data->item, "reposition", false, false, true);
       
   479         }
       
   480 
       
   481         data->item->setZValue(data->originalZValue);
       
   482 
       
   483         if (data->startItem) {
       
   484             emit q_ptr->animationFinished(data->startItem, data->type);
       
   485         }
       
   486 
       
   487         mAnimatedItems.removeOne(data);
       
   488         delete data;
       
   489     }
       
   490 }
       
   491 
       
   492 HbGridLayoutPrivate::AnimationData *HbGridLayoutPrivate::animationData(QGraphicsLayoutItem *item) const
       
   493 {   
       
   494     if (item) {
       
   495         QGraphicsItem *graphicsItem = item->graphicsItem();
       
   496 
       
   497         int animateItemsCount = mAnimatedItems.count();
       
   498         for (int j = animateItemsCount - 1; j >= 0; --j) {
       
   499             AnimationData *currentData = mAnimatedItems.at(j);
       
   500             
       
   501             if (currentData->item == graphicsItem) {
       
   502                 return currentData;
       
   503             }
       
   504         }
       
   505     }
       
   506 
       
   507     return 0;
       
   508 }
       
   509