ganeswidgets/src/hgcoverflowcontainer.cpp
changeset 3 c863538fcbb6
parent 2 49c70dcc3f17
child 5 4fa04caf0f43
equal deleted inserted replaced
2:49c70dcc3f17 3:c863538fcbb6
    20 #include <QPainter>
    20 #include <QPainter>
    21 #include <hblabel.h>
    21 #include <hblabel.h>
    22 #include "hgcoverflowcontainer.h"
    22 #include "hgcoverflowcontainer.h"
    23 #include "hgmediawallrenderer.h"
    23 #include "hgmediawallrenderer.h"
    24 #include "hgwidgetitem.h"
    24 #include "hgwidgetitem.h"
       
    25 #include "hgcenteritemarea.h"
    25 #include "trace.h"
    26 #include "trace.h"
    26 
    27 
    27 
    28 
    28 static const qreal KCameraMaxYAngle(20);
    29 static const qreal KCameraMaxYAngle(20);
    29 static const qreal KSpringVelocityToCameraYAngleFactor(2);
    30 static const qreal KSpringVelocityToCameraYAngleFactor(2);
    30 static const int   KLabelMargin(4);
       
    31 
    31 
    32 HgCoverflowContainer::HgCoverflowContainer(
    32 HgCoverflowContainer::HgCoverflowContainer(
    33     QGraphicsItem* parent) : HgContainer(parent),
    33     QGraphicsItem* parent) : HgContainer(parent),
    34     mTitleLabel(0),
       
    35     mDescriptionLabel(0),
       
    36     mTitlePosition(HgMediawall::PositionAboveImage),
       
    37     mDescriptionPosition(HgMediawall::PositionNone),
       
    38     mPrevPos(-1),
    34     mPrevPos(-1),
    39     mAspectRatio(1),
    35     mAnimationAboutToEndReacted(false),
    40     mAnimationAboutToEndReacted(false)
    36     mCenterItemArea(0)
    41 {
    37 {
    42     mTitleLabel = new HbLabel(this);
       
    43     mTitleLabel->setZValue(zValue()+1);
       
    44     mTitleLabel->setAlignment(Qt::AlignCenter);
       
    45     mTitleLabel->setVisible(false);
       
    46 
       
    47     mDescriptionLabel = new HbLabel(this);
       
    48     mDescriptionLabel->setZValue(zValue()+1);
       
    49     mDescriptionLabel->setAlignment(Qt::AlignCenter);
       
    50     mDescriptionLabel->setVisible(false);
       
    51 
       
    52     mUserItemSize = QSize(250,250);
    38     mUserItemSize = QSize(250,250);
    53     mUserItemSpacing = QSize(1,1);
    39     mUserItemSpacing = QSize(1,1);
    54 }
    40 }
    55 
    41 
    56 HgCoverflowContainer::~HgCoverflowContainer()
    42 HgCoverflowContainer::~HgCoverflowContainer()
    61 void HgCoverflowContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    47 void HgCoverflowContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    62 {
    48 {
    63     painter->setRenderHint(QPainter::Antialiasing, true);
    49     painter->setRenderHint(QPainter::Antialiasing, true);
    64     HgContainer::paint(painter, option, widget);
    50     HgContainer::paint(painter, option, widget);
    65     painter->setRenderHint(QPainter::Antialiasing, false);
    51     painter->setRenderHint(QPainter::Antialiasing, false);
    66 }
       
    67 
       
    68 void HgCoverflowContainer::resizeEvent(QGraphicsSceneResizeEvent *event)
       
    69 {
       
    70     FUNC_LOG;
       
    71 
       
    72     HbWidget::resizeEvent(event);
       
    73 
       
    74     updatePositions();
       
    75 }
    52 }
    76 
    53 
    77 // from HgContainer
    54 // from HgContainer
    78 HgMediaWallRenderer* HgCoverflowContainer::createRenderer(Qt::Orientation scrollDirection)
    55 HgMediaWallRenderer* HgCoverflowContainer::createRenderer(Qt::Orientation scrollDirection)
    79 {
    56 {
   123     HgContainer::onScrollPositionChanged(pos);
   100     HgContainer::onScrollPositionChanged(pos);
   124 
   101 
   125     if(!mAnimationAboutToEndReacted) {
   102     if(!mAnimationAboutToEndReacted) {
   126         qreal endPos = mSpring.endPos().x();
   103         qreal endPos = mSpring.endPos().x();
   127         qreal abs = qAbs(endPos - mSpring.pos().x());
   104         qreal abs = qAbs(endPos - mSpring.pos().x());
   128         
   105 
   129         if( abs <= 0.5f ) {
   106         if( abs <= 0.5f ) {
   130             HgWidgetItem* item = itemByIndex((int)endPos);
   107             HgWidgetItem* item = itemByIndex((int)endPos);
   131             if (item) {
   108             if (item) {
   132                 emit animationAboutToEnd( item->modelIndex() );
   109                 emit animationAboutToEnd( item->modelIndex() );
   133                 mAnimationAboutToEndReacted = true;
   110                 mAnimationAboutToEndReacted = true;
   134             }
   111             }
   135         }
   112         }
   136     }
   113     }
   137     
   114 
   138     qreal ipos = floorf(pos);
   115     qreal ipos = floorf(pos);
   139     qreal frac = pos - ipos;
   116     qreal frac = pos - ipos;
   140     qreal p = frac > 0.5 ? ipos + 1.0f : ipos;
   117     qreal p = frac > 0.5 ? ipos + 1.0f : ipos;
   141 
   118 
   142     if (mPrevPos != (int)p) {
   119     if (mPrevPos != (int)p) {
   156 void HgCoverflowContainer::onScrollingEnded()
   133 void HgCoverflowContainer::onScrollingEnded()
   157 {
   134 {
   158     mAnimationAboutToEndReacted = false;    //reset
   135     mAnimationAboutToEndReacted = false;    //reset
   159 }
   136 }
   160 
   137 
   161 void HgCoverflowContainer::handleCurrentChanged(const QModelIndex &current)
   138 void HgCoverflowContainer::calculateItemSize()
   162 {
   139 {
   163     FUNC_LOG;
   140     FUNC_LOG;
   164 
   141 
   165     if (current.isValid()) {
   142     QRectF containerRect = contentsRect();
   166         updateLabels(current.row());
   143     INFO("Container rect:" << containerRect);
   167     }
   144 
   168 }
   145     if (!mCenterItemArea) return;
   169 
   146 
   170 void HgCoverflowContainer::itemDataChanged(const int &firstIndex, const int &lastIndex)
   147     QRectF centerItemRect = mCenterItemArea->mapRectToParent(mCenterItemArea->contentsRect());
   171 {
   148     INFO("Center item rect:" << centerItemRect);
   172     FUNC_LOG;
   149     if (centerItemRect.isEmpty()) return;
   173     HANDLE_ERROR_NULL(mSelectionModel); // If model has been set, also is selection model
   150 
   174 
   151     QSizeF imageSize(1, 1); // Aspect ratio 1:1
   175     HgContainer::itemDataChanged(firstIndex, lastIndex);
   152     if (!mUserItemSize.isEmpty()) {
   176 
   153         imageSize = mUserItemSize; // Get aspect ration from user item size
   177     if (mSelectionModel->currentIndex().isValid()) {
   154     }
   178         int current = mSelectionModel->currentIndex().row();
   155     imageSize.scale(centerItemRect.size(), Qt::KeepAspectRatio);
   179         if (firstIndex <= current && current <= lastIndex) {
   156 
   180             updateLabels(current);
   157     QPointF delta = centerItemRect.center() - containerRect.center();
   181         }
   158     INFO("Setting image size to:" << imageSize << "delta:" << delta);
   182     }
   159 
   183 
   160     mRenderer->setImageSize(imageSize);
   184     if (firstIndex == 0) {
   161     mAutoSize = imageSize;
   185         // Take preferred aspect ratio from the first image
   162     setFrontItemPositionDelta(delta);
   186         const HgImage *firstImage = image(0);
       
   187         if (firstImage && firstImage->height() != 0) {
       
   188             mAspectRatio = qMax((qreal)0.1, (qreal)firstImage->width()/firstImage->height()); // Don't let aspect ratio go to 0
       
   189             updatePositions();
       
   190         }
       
   191     }
       
   192 }
       
   193 
       
   194 void HgCoverflowContainer::setTitlePosition(HgMediawall::LabelPosition position)
       
   195 {
       
   196     FUNC_LOG;
       
   197 
       
   198     if (mTitlePosition != position) {
       
   199         mTitlePosition = position;
       
   200         updatePositions();
       
   201     }
       
   202 }
       
   203 
       
   204 HgMediawall::LabelPosition HgCoverflowContainer::titlePosition() const
       
   205 {
       
   206     FUNC_LOG;
       
   207 
       
   208     return mTitlePosition;
       
   209 }
       
   210 
       
   211 void HgCoverflowContainer::setDescriptionPosition(HgMediawall::LabelPosition position)
       
   212 {
       
   213     FUNC_LOG;
       
   214 
       
   215     if (mDescriptionPosition != position) {
       
   216         mDescriptionPosition = position;
       
   217         updatePositions();
       
   218     }
       
   219 }
       
   220 
       
   221 HgMediawall::LabelPosition HgCoverflowContainer::descriptionPosition() const
       
   222 {
       
   223     FUNC_LOG;
       
   224 
       
   225     return mDescriptionPosition;
       
   226 }
       
   227 
       
   228 void HgCoverflowContainer::setTitleFontSpec(const HbFontSpec &fontSpec)
       
   229 {
       
   230     FUNC_LOG;
       
   231 
       
   232     if (!mTitleLabel) return;
       
   233     if (mTitleLabel->fontSpec() != fontSpec) {
       
   234         mTitleLabel->setFontSpec(fontSpec);
       
   235         updatePositions();
       
   236     }
       
   237 }
       
   238 
       
   239 HbFontSpec HgCoverflowContainer::titleFontSpec() const
       
   240 {
       
   241     FUNC_LOG;
       
   242 
       
   243     if (!mTitleLabel) return HbFontSpec();
       
   244     return mTitleLabel->fontSpec();
       
   245 }
       
   246 
       
   247 void HgCoverflowContainer::setDescriptionFontSpec(const HbFontSpec &fontSpec)
       
   248 {
       
   249     FUNC_LOG;
       
   250 
       
   251     if (!mDescriptionLabel) return;
       
   252     if (mDescriptionLabel->fontSpec() != fontSpec) {
       
   253         mDescriptionLabel->setFontSpec(fontSpec);
       
   254         updatePositions();
       
   255     }
       
   256 }
       
   257 
       
   258 HbFontSpec HgCoverflowContainer::descriptionFontSpec() const
       
   259 {
       
   260     FUNC_LOG;
       
   261 
       
   262     if (!mDescriptionLabel) return HbFontSpec();
       
   263     return mDescriptionLabel->fontSpec();
       
   264 }
       
   265 
       
   266 void HgCoverflowContainer::calculatePositions()
       
   267 {
       
   268     FUNC_LOG;
       
   269     HANDLE_ERROR_NULL(mTitleLabel);
       
   270     HANDLE_ERROR_NULL(mDescriptionLabel);
       
   271 
       
   272     int height = size().height();
       
   273     int width = size().width();
       
   274     int titleHeight = QFontMetrics(mTitleLabel->effectiveFontSpec().font()).height();
       
   275     int descriptionHeight = QFontMetrics(mDescriptionLabel->effectiveFontSpec().font()).height();
       
   276     qreal usableHeight = height-KLabelMargin;
       
   277     if (mTitlePosition != HgMediawall::PositionNone) {
       
   278         usableHeight -= (titleHeight+KLabelMargin);
       
   279     }
       
   280     if (mDescriptionPosition != HgMediawall::PositionNone) {
       
   281         usableHeight -= (descriptionHeight+KLabelMargin);
       
   282     }
       
   283 
       
   284     if (usableHeight <= 0) return;
       
   285 
       
   286     qreal usableWidth = width/1.4;
       
   287     if (usableWidth <= 0) return;
       
   288 
       
   289     QRectF imageRect = rect();
       
   290     if (usableWidth/usableHeight > mAspectRatio) {
       
   291         imageRect.setHeight(usableHeight);
       
   292         imageRect.setWidth(mAspectRatio*usableHeight);
       
   293         imageRect.moveLeft((width-imageRect.width())/2);
       
   294     }
       
   295     else {
       
   296         imageRect.setWidth(usableWidth);
       
   297         imageRect.setHeight(usableWidth/mAspectRatio);
       
   298         imageRect.moveTop((usableHeight-imageRect.height())/2);
       
   299         imageRect.moveLeft((width-imageRect.width())/2);
       
   300     }
       
   301 
       
   302     QRectF titleGeometry(0, imageRect.top()+KLabelMargin, width, titleHeight);
       
   303     QRectF descriptionGeometry(0, imageRect.top()+KLabelMargin, width, descriptionHeight);
       
   304 
       
   305     if (mTitlePosition == HgMediawall::PositionAboveImage &&
       
   306         mDescriptionPosition == HgMediawall::PositionAboveImage) {
       
   307         // titleGeometry default is ok
       
   308         descriptionGeometry.moveTop(titleGeometry.bottom()+KLabelMargin);
       
   309         imageRect.moveTop(descriptionGeometry.bottom()+KLabelMargin);
       
   310     }
       
   311     else if (mTitlePosition == HgMediawall::PositionBelowImage &&
       
   312              mDescriptionPosition == HgMediawall::PositionBelowImage) {
       
   313         titleGeometry.moveTop(imageRect.bottom()+KLabelMargin);
       
   314         descriptionGeometry.moveTop(titleGeometry.bottom()+KLabelMargin);
       
   315     }
       
   316     else {
       
   317         if (mTitlePosition == HgMediawall::PositionAboveImage) {
       
   318             // titleGeometry default is ok
       
   319             imageRect.moveTop(titleGeometry.bottom()+KLabelMargin);
       
   320         }
       
   321         else if (mDescriptionPosition == HgMediawall::PositionAboveImage) {
       
   322             // descriptionGeometry default is ok
       
   323             imageRect.moveTop(descriptionGeometry.bottom()+KLabelMargin);
       
   324         }
       
   325 
       
   326         if (mTitlePosition == HgMediawall::PositionBelowImage) {
       
   327             titleGeometry.moveTop(imageRect.bottom()+KLabelMargin);
       
   328         }
       
   329         else if (mDescriptionPosition == HgMediawall::PositionBelowImage) {
       
   330             descriptionGeometry.moveTop(imageRect.bottom()+KLabelMargin);
       
   331         }
       
   332     }
       
   333 
       
   334     INFO("Setting image rect to:" << imageRect << "(total size:" << QSize(width, height)
       
   335         << "usable size:" << QSizeF(usableWidth, usableHeight) << ", aspect ratio is:" << mAspectRatio << ")");
       
   336 
       
   337     mRenderer->setImageSize(imageRect.size());
       
   338     qreal diff = rect().center().y()-imageRect.center().y();
       
   339 
       
   340     INFO("Setting front item position to:" << QPointF(0, -diff) << "(rect:" << rect()
       
   341         << "imageRect:" << imageRect << ")");
       
   342     mRenderer->setFrontItemPosition(QPointF(0, -diff));
       
   343 
       
   344     mAutoSize = imageRect.size();
       
   345 
       
   346     if (mTitlePosition != HgMediawall::PositionNone) {
       
   347         INFO("Title geometry:" << titleGeometry);
       
   348         mTitleLabel->setGeometry(titleGeometry);
       
   349         mTitleLabel->setVisible(true);
       
   350     }
       
   351     else {
       
   352         mTitleLabel->setVisible(false);
       
   353     }
       
   354     if (mDescriptionPosition != HgMediawall::PositionNone) {
       
   355         INFO("Description geometry:" << descriptionGeometry);
       
   356         mDescriptionLabel->setGeometry(descriptionGeometry);
       
   357         mDescriptionLabel->setVisible(true);
       
   358     }
       
   359     else {
       
   360         mDescriptionLabel->setVisible(false);
       
   361     }
       
   362 
       
   363     // This may be called before selection model is set.
       
   364     if (mSelectionModel && mSelectionModel->currentIndex().isValid()) {
       
   365         updateLabels(mSelectionModel->currentIndex().row());
       
   366     }
       
   367 
       
   368     mRenderer->setSpacing(QSizeF(1,1));
   163     mRenderer->setSpacing(QSizeF(1,1));
   369 
       
   370 }
       
   371 
       
   372 void HgCoverflowContainer::positionLabels()
       
   373 {
       
   374     FUNC_LOG;
       
   375     HANDLE_ERROR_NULL(mTitleLabel);
       
   376     HANDLE_ERROR_NULL(mDescriptionLabel);
       
   377 
       
   378     int centerIconTop = (size().height() - mRenderer->getImageSize().height()) / 2;
       
   379 
       
   380     int height = size().height();
       
   381     int width = size().width();
       
   382     int titleHeight = QFontMetrics(mTitleLabel->effectiveFontSpec().font()).height();
       
   383     int descriptionHeight = QFontMetrics(mDescriptionLabel->effectiveFontSpec().font()).height();
       
   384 
       
   385     if (mTitlePosition == HgMediawall::PositionAboveImage &&
       
   386         mDescriptionPosition == HgMediawall::PositionAboveImage) {
       
   387         mTitleLabel->setGeometry(QRectF(
       
   388             0,
       
   389             qMax(KLabelMargin, centerIconTop-2*KLabelMargin-titleHeight-descriptionHeight),
       
   390             width, titleHeight));
       
   391         mDescriptionLabel->setGeometry(QRectF(
       
   392             0,
       
   393             mTitleLabel->geometry().bottom()+KLabelMargin,
       
   394             width, descriptionHeight));
       
   395     }
       
   396     else if (mTitlePosition == HgMediawall::PositionBelowImage &&
       
   397              mDescriptionPosition == HgMediawall::PositionBelowImage) {
       
   398         mDescriptionLabel->setGeometry(QRectF(
       
   399             0,
       
   400             height-descriptionHeight-KLabelMargin,
       
   401             width, descriptionHeight));
       
   402         mTitleLabel->setGeometry(QRectF(
       
   403             0,
       
   404             mDescriptionLabel->geometry().top()-titleHeight-KLabelMargin,
       
   405             width, titleHeight));
       
   406     }
       
   407     else {
       
   408         if (mTitlePosition == HgMediawall::PositionAboveImage) {
       
   409             mTitleLabel->setGeometry(QRectF(
       
   410                 0,
       
   411                 qMax(KLabelMargin, centerIconTop-KLabelMargin-titleHeight),
       
   412                 width, titleHeight));
       
   413         }
       
   414         else if (mTitlePosition == HgMediawall::PositionBelowImage) {
       
   415             mTitleLabel->setGeometry(QRectF(
       
   416                 0,
       
   417                 height-titleHeight-KLabelMargin,
       
   418                 width, titleHeight));
       
   419         }
       
   420 
       
   421         if (mDescriptionPosition == HgMediawall::PositionAboveImage) {
       
   422             mDescriptionLabel->setGeometry(QRectF(
       
   423                 0,
       
   424                 qMax(KLabelMargin, centerIconTop-KLabelMargin-descriptionHeight),
       
   425                 width, descriptionHeight));
       
   426         }
       
   427         else if (mDescriptionPosition == HgMediawall::PositionBelowImage) {
       
   428             mDescriptionLabel->setGeometry(QRectF(
       
   429                 0,
       
   430                 height-descriptionHeight-KLabelMargin,
       
   431                 width, descriptionHeight));
       
   432         }
       
   433     }
       
   434 
       
   435     mTitleLabel->setVisible(mTitlePosition != HgMediawall::PositionNone);
       
   436     mDescriptionLabel->setVisible(mDescriptionPosition != HgMediawall::PositionNone);
       
   437 
       
   438     INFO("Title geometry:" << mTitleLabel->geometry() << "visible:" << mTitleLabel->isVisible());
       
   439     INFO("Description geometry:" << mDescriptionLabel->geometry() << "visible:" << mDescriptionLabel->isVisible());
       
   440 
       
   441     if ( mSelectionModel &&  mSelectionModel->currentIndex().isValid()) {
       
   442         updateLabels(mSelectionModel->currentIndex().row());
       
   443     }
       
   444 }
       
   445 
       
   446 
       
   447 void HgCoverflowContainer::updateLabels(int itemIndex)
       
   448 {
       
   449     FUNC_LOG;
       
   450     HANDLE_ERROR_NULL(mTitleLabel);
       
   451     HANDLE_ERROR_NULL(mDescriptionLabel);
       
   452 
       
   453     if (itemIndex >= 0 && itemIndex < mItems.count()) {
       
   454         mTitleLabel->setPlainText(mItems.at(itemIndex)->title());
       
   455         mDescriptionLabel->setPlainText(mItems.at(itemIndex)->description());
       
   456     }
       
   457 }
   164 }
   458 
   165 
   459 void HgCoverflowContainer::scrollToPosition(const QPointF& pos, bool animate)
   166 void HgCoverflowContainer::scrollToPosition(const QPointF& pos, bool animate)
   460 {
   167 {
   461     QPointF p = pos;
   168     QPointF p = pos;
   462     p.setX((int)pos.x());
   169     p.setX((int)pos.x());
   463     HgContainer::scrollToPosition(p,animate);
   170     HgContainer::scrollToPosition(p,animate);
   464 }
   171 }
   465 
   172 
   466 void HgCoverflowContainer::setDefaultImage(QImage defaultImage)
       
   467 {
       
   468     HgContainer::setDefaultImage(defaultImage);
       
   469 
       
   470     if (!defaultImage.isNull()) {
       
   471         mAspectRatio = qMax((qreal)0.1, (qreal)defaultImage.width()/defaultImage.height()); // Don't let aspect ratio go to 0
       
   472         updatePositions();
       
   473     }
       
   474 }
       
   475 
       
   476 QSizeF HgCoverflowContainer::getAutoItemSize() const
   173 QSizeF HgCoverflowContainer::getAutoItemSize() const
   477 {
   174 {
   478     return mAutoSize;
   175     return mAutoSize;
   479 }
   176 }
   480 
   177 
   485 
   182 
   486 void HgCoverflowContainer::updateItemSizeAndSpacing()
   183 void HgCoverflowContainer::updateItemSizeAndSpacing()
   487 {
   184 {
   488     HgContainer::updateItemSizeAndSpacing();
   185     HgContainer::updateItemSizeAndSpacing();
   489 
   186 
   490     updatePositions();
   187     updateItemSize();
   491 }
   188 }
   492 
   189 
   493 
   190 
   494 void HgCoverflowContainer::updatePositions()
   191 void HgCoverflowContainer::updateItemSize()
   495 {
   192 {
   496     if (mItemSizePolicy == HgWidget::ItemSizeAutomatic) {
   193     if (mItemSizePolicy == HgWidget::ItemSizeAutomatic) {
   497         calculatePositions();
   194         calculateItemSize();
   498     }
       
   499     else {
       
   500         positionLabels();
       
   501     }
   195     }
   502 }
   196 }
   503 
   197 
   504 void HgCoverflowContainer::setFrontItemPositionDelta(const QPointF& position)
   198 void HgCoverflowContainer::setFrontItemPositionDelta(const QPointF& position)
   505 {
   199 {
   523 bool HgCoverflowContainer::reflectionsEnabled() const
   217 bool HgCoverflowContainer::reflectionsEnabled() const
   524 {
   218 {
   525     return mRenderer ? mRenderer->reflectionsEnabled() : false;
   219     return mRenderer ? mRenderer->reflectionsEnabled() : false;
   526 }
   220 }
   527 
   221 
   528 
   222 void HgCoverflowContainer::setCenterItemArea(HgCenterItemArea *centerItemArea)
       
   223 {
       
   224     FUNC_LOG;
       
   225 
       
   226     if (!mCenterItemArea) {
       
   227         mCenterItemArea = centerItemArea;
       
   228         connect(mCenterItemArea, SIGNAL(sizeChanged()), SLOT(updateItemSize()));
       
   229     }
       
   230 }
       
   231 
       
   232 
       
   233