ganeswidgets/src/hgcoverflowcontainer.cpp
changeset 1 e48454f237ca
parent 0 89c329efa980
child 2 49c70dcc3f17
equal deleted inserted replaced
0:89c329efa980 1:e48454f237ca
    14 * Description:
    14 * Description:
    15 *
    15 *
    16 */
    16 */
    17 
    17 
    18 #include <QGesture>
    18 #include <QGesture>
       
    19 #include <QGraphicsSceneResizeEvent>
    19 #include <QPainter>
    20 #include <QPainter>
    20 #include <hblabel.h>
    21 #include <hblabel.h>
    21 #include "hgcoverflowcontainer.h"
    22 #include "hgcoverflowcontainer.h"
    22 #include "hgmediawallrenderer.h"
    23 #include "hgmediawallrenderer.h"
    23 #include "hgwidgetitem.h"
    24 #include "hgwidgetitem.h"
    32     QGraphicsItem* parent) : HgContainer(parent),
    33     QGraphicsItem* parent) : HgContainer(parent),
    33     mTitleLabel(0),
    34     mTitleLabel(0),
    34     mDescriptionLabel(0),
    35     mDescriptionLabel(0),
    35     mTitlePosition(HgMediawall::PositionAboveImage),
    36     mTitlePosition(HgMediawall::PositionAboveImage),
    36     mDescriptionPosition(HgMediawall::PositionNone),
    37     mDescriptionPosition(HgMediawall::PositionNone),
    37     mCenterIconTop(0),
    38     mPrevPos(-1),
    38     mPrevPos(-1)
    39     mAspectRatio(1),
       
    40     mDrawableRect(rect())
    39 {
    41 {
    40     mTitleLabel = new HbLabel(this);
    42     mTitleLabel = new HbLabel(this);
    41     mTitleLabel->setZValue(zValue()+1);
    43     mTitleLabel->setZValue(zValue()+1);
    42     mTitleLabel->setAlignment(Qt::AlignCenter);
    44     mTitleLabel->setAlignment(Qt::AlignCenter);
    43     mTitleLabel->setVisible(false);
    45     mTitleLabel->setVisible(false);
    44 
    46 
    45     mDescriptionLabel = new HbLabel(this);
    47     mDescriptionLabel = new HbLabel(this);
    46     mDescriptionLabel->setZValue(zValue()+1);
    48     mDescriptionLabel->setZValue(zValue()+1);
    47     mDescriptionLabel->setAlignment(Qt::AlignCenter);
    49     mDescriptionLabel->setAlignment(Qt::AlignCenter);
    48     mDescriptionLabel->setVisible(false);
    50     mDescriptionLabel->setVisible(false);
       
    51     
       
    52     mUserItemSize = QSize(250,250);
       
    53     mUserItemSpacing = QSize(1,1);
    49 }
    54 }
    50 
    55 
    51 HgCoverflowContainer::~HgCoverflowContainer()
    56 HgCoverflowContainer::~HgCoverflowContainer()
    52 {
    57 {
    53 }
    58 }
    62 {
    67 {
    63     FUNC_LOG;
    68     FUNC_LOG;
    64 
    69 
    65     HbWidget::resizeEvent(event);
    70     HbWidget::resizeEvent(event);
    66 
    71 
    67     QSizeF s(size());
    72     updatePositions();    
    68     qreal side = qMin(s.height()/1.8, s.width()/1.8);
       
    69     INFO("Setting image size to:" << side << "," << side);
       
    70     mRenderer->setImageSize(QSizeF(side, side));
       
    71     mCenterIconTop = (s.height()-side)/2;
       
    72 
       
    73     positionLabels();
       
    74 }
    73 }
    75 
    74 
    76 // from HgContainer
    75 // from HgContainer
    77 HgMediaWallRenderer* HgCoverflowContainer::createRenderer()
    76 HgMediaWallRenderer* HgCoverflowContainer::createRenderer(Qt::Orientation scrollDirection)
    78 {
    77 {
    79     HgMediaWallRenderer* renderer = new HgMediaWallRenderer(this);
    78     HgMediaWallRenderer* renderer = new HgMediaWallRenderer(this, scrollDirection, true);
    80     renderer->setImageSize(QSizeF(200, 200));
    79     renderer->setImageSize(mUserItemSize);
    81     renderer->enableCoverflowMode(true);
    80     renderer->enableCoverflowMode(true);
    82     renderer->setRowCount(1, renderer->getImageSize(), false);
    81     renderer->setRowCount(1, renderer->getImageSize(), false);
    83     renderer->enableReflections(true);
    82     renderer->enableReflections(true);
    84     renderer->setSpacing(QSizeF(1,1));
    83     renderer->setSpacing(mUserItemSpacing);
    85     renderer->setFrontCoverElevationFactor(0.5);
    84     renderer->setFrontCoverElevationFactor(0.5);
    86     return renderer;
    85     return renderer;
    87 }
    86 }
    88 
    87 
    89 qreal HgCoverflowContainer::getCameraDistance(qreal springVelocity)
    88 qreal HgCoverflowContainer::getCameraDistance(qreal springVelocity)
   119 
   118 
   120 void HgCoverflowContainer::onScrollPositionChanged(qreal pos)
   119 void HgCoverflowContainer::onScrollPositionChanged(qreal pos)
   121 {
   120 {
   122     HgContainer::onScrollPositionChanged(pos);
   121     HgContainer::onScrollPositionChanged(pos);
   123 
   122 
   124     if (mPrevPos != (int)pos) {
   123     qreal ipos = floorf(pos);
   125         mPrevPos = (int)pos;
   124     qreal frac = pos - ipos;
   126         HgWidgetItem* item = itemByIndex((int)pos);
   125     qreal p = frac > 0.5 ? ipos + 1.0f : ipos;
       
   126 
       
   127     if (mPrevPos != (int)p) {
       
   128         mPrevPos = (int)p;        
       
   129         HgWidgetItem* item = itemByIndex((int)p);
   127         if (item && item->modelIndex() != mSelectionModel->currentIndex()) {
   130         if (item && item->modelIndex() != mSelectionModel->currentIndex()) {
   128             mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
   131             mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
   129         }            
   132         }
   130     }
   133     }
   131 }
   134 }
   132 
   135 
   133 void HgCoverflowContainer::handleCurrentChanged(const QModelIndex &current)
   136 void HgCoverflowContainer::handleCurrentChanged(const QModelIndex &current)
   134 {
   137 {
   150         int current = mSelectionModel->currentIndex().row();
   153         int current = mSelectionModel->currentIndex().row();
   151         if (firstIndex <= current && current <= lastIndex) {
   154         if (firstIndex <= current && current <= lastIndex) {
   152             updateLabels(current);
   155             updateLabels(current);
   153         }
   156         }
   154     }
   157     }
       
   158 
       
   159     if (firstIndex == 0) {
       
   160         // Take preferred aspect ratio from the first image
       
   161         const HgImage *firstImage = image(0);
       
   162         if (firstImage && firstImage->height() != 0) {
       
   163             mAspectRatio = qMax((qreal)0.1, (qreal)firstImage->width()/firstImage->height()); // Don't let aspect ratio go to 0
       
   164             updatePositions();
       
   165         }
       
   166     }
   155 }
   167 }
   156 
   168 
   157 void HgCoverflowContainer::setTitlePosition(HgMediawall::LabelPosition position)
   169 void HgCoverflowContainer::setTitlePosition(HgMediawall::LabelPosition position)
   158 {
   170 {
   159     FUNC_LOG;
   171     FUNC_LOG;
   160 
   172 
   161     if (mTitlePosition != position) {
   173     if (mTitlePosition != position) {
   162         mTitlePosition = position;
   174         mTitlePosition = position;
   163         positionLabels();
   175         updatePositions();
   164     }
   176     }
   165 }
   177 }
   166 
   178 
   167 HgMediawall::LabelPosition HgCoverflowContainer::titlePosition() const
   179 HgMediawall::LabelPosition HgCoverflowContainer::titlePosition() const
   168 {
   180 {
   175 {
   187 {
   176     FUNC_LOG;
   188     FUNC_LOG;
   177 
   189 
   178     if (mDescriptionPosition != position) {
   190     if (mDescriptionPosition != position) {
   179         mDescriptionPosition = position;
   191         mDescriptionPosition = position;
   180         positionLabels();
   192         updatePositions();
   181     }
   193     }
   182 }
   194 }
   183 
   195 
   184 HgMediawall::LabelPosition HgCoverflowContainer::descriptionPosition() const
   196 HgMediawall::LabelPosition HgCoverflowContainer::descriptionPosition() const
   185 {
   197 {
   193     FUNC_LOG;
   205     FUNC_LOG;
   194 
   206 
   195     if (!mTitleLabel) return;
   207     if (!mTitleLabel) return;
   196     if (mTitleLabel->fontSpec() != fontSpec) {
   208     if (mTitleLabel->fontSpec() != fontSpec) {
   197         mTitleLabel->setFontSpec(fontSpec);
   209         mTitleLabel->setFontSpec(fontSpec);
   198         positionLabels();
   210         updatePositions();
   199     }
   211     }
   200 }
   212 }
   201 
   213 
   202 HbFontSpec HgCoverflowContainer::titleFontSpec() const
   214 HbFontSpec HgCoverflowContainer::titleFontSpec() const
   203 {
   215 {
   212     FUNC_LOG;
   224     FUNC_LOG;
   213 
   225 
   214     if (!mDescriptionLabel) return;
   226     if (!mDescriptionLabel) return;
   215     if (mDescriptionLabel->fontSpec() != fontSpec) {
   227     if (mDescriptionLabel->fontSpec() != fontSpec) {
   216         mDescriptionLabel->setFontSpec(fontSpec);
   228         mDescriptionLabel->setFontSpec(fontSpec);
   217         positionLabels();
   229         updatePositions();
   218     }
   230     }
   219 }
   231 }
   220 
   232 
   221 HbFontSpec HgCoverflowContainer::descriptionFontSpec() const
   233 HbFontSpec HgCoverflowContainer::descriptionFontSpec() const
   222 {
   234 {
   224 
   236 
   225     if (!mDescriptionLabel) return HbFontSpec();
   237     if (!mDescriptionLabel) return HbFontSpec();
   226     return mDescriptionLabel->fontSpec();
   238     return mDescriptionLabel->fontSpec();
   227 }
   239 }
   228 
   240 
   229 void HgCoverflowContainer::positionLabels()
   241 void HgCoverflowContainer::calculatePositions()
   230 {
   242 {
   231     FUNC_LOG;
   243     FUNC_LOG;
   232     HANDLE_ERROR_NULL(mTitleLabel);
   244     HANDLE_ERROR_NULL(mTitleLabel);
   233     HANDLE_ERROR_NULL(mDescriptionLabel);
   245     HANDLE_ERROR_NULL(mDescriptionLabel);
   234     HANDLE_ERROR_NULL(mSelectionModel);
   246     
   235 
       
   236     int height = size().height();
   247     int height = size().height();
   237     int width = size().width();
   248     int width = size().width();
   238     int titleHeight = QFontMetrics(mTitleLabel->effectiveFontSpec().font()).height();
   249     int titleHeight = QFontMetrics(mTitleLabel->effectiveFontSpec().font()).height();
   239     int descriptionHeight = QFontMetrics(mDescriptionLabel->effectiveFontSpec().font()).height();
   250     int descriptionHeight = QFontMetrics(mDescriptionLabel->effectiveFontSpec().font()).height();
       
   251     qreal usableHeight = height-KLabelMargin;
       
   252     if (mTitlePosition != HgMediawall::PositionNone) {
       
   253         usableHeight -= (titleHeight+KLabelMargin);
       
   254     }
       
   255     if (mDescriptionPosition != HgMediawall::PositionNone) {
       
   256         usableHeight -= (descriptionHeight+KLabelMargin);
       
   257     }
       
   258 
       
   259     usableHeight *= 0.8; // Leave some space for the reflection
       
   260     if (usableHeight <= 0) return;
       
   261 
       
   262     qreal usableWidth = width/2;
       
   263     if (usableWidth <= 0) return;
       
   264 
       
   265     mDrawableRect = rect();
       
   266     QSizeF imageSize;
       
   267     if (usableWidth/usableHeight > mAspectRatio) {
       
   268         imageSize.setHeight(usableHeight);
       
   269         imageSize.setWidth(mAspectRatio*usableHeight);
       
   270     }
       
   271     else {
       
   272         imageSize.setWidth(usableWidth);
       
   273         imageSize.setHeight(usableWidth/mAspectRatio);
       
   274         mDrawableRect.setTop((usableHeight-imageSize.height())/2);
       
   275     }
       
   276 
       
   277     QRectF titleGeometry(0, mDrawableRect.top()+KLabelMargin, width, titleHeight);
       
   278     QRectF descriptionGeometry(0, mDrawableRect.top()+KLabelMargin, width, descriptionHeight);
       
   279 
       
   280     if (mTitlePosition == HgMediawall::PositionAboveImage &&
       
   281         mDescriptionPosition == HgMediawall::PositionAboveImage) {
       
   282         // titleGeometry default is ok
       
   283         descriptionGeometry.moveTop(titleGeometry.bottom()+KLabelMargin);
       
   284         mDrawableRect.setTop(descriptionGeometry.bottom()+KLabelMargin);
       
   285     }
       
   286     else if (mTitlePosition == HgMediawall::PositionBelowImage &&
       
   287              mDescriptionPosition == HgMediawall::PositionBelowImage) {
       
   288         titleGeometry.moveTop(mDrawableRect.top()+imageSize.height()+KLabelMargin);
       
   289         descriptionGeometry.moveTop(titleGeometry.bottom()+KLabelMargin);
       
   290     }
       
   291     else {
       
   292         if (mTitlePosition == HgMediawall::PositionAboveImage) {
       
   293             // titleGeometry default is ok
       
   294             mDrawableRect.setTop(titleGeometry.bottom()+KLabelMargin);
       
   295         }
       
   296         else if (mDescriptionPosition == HgMediawall::PositionAboveImage) {
       
   297             // descriptionGeometry default is ok
       
   298             mDrawableRect.setTop(descriptionGeometry.bottom()+KLabelMargin);
       
   299         }
       
   300 
       
   301         if (mTitlePosition == HgMediawall::PositionBelowImage) {
       
   302             titleGeometry.moveTop(mDrawableRect.top()+imageSize.height()+KLabelMargin);
       
   303         }
       
   304         else if (mDescriptionPosition == HgMediawall::PositionBelowImage) {
       
   305             descriptionGeometry.moveTop(mDrawableRect.top()+imageSize.height()+KLabelMargin);
       
   306         }
       
   307     }
       
   308 
       
   309     INFO("Setting image size to:" << imageSize << "(total size:" << QSize(width, height)
       
   310         << "usable size:" << QSizeF(usableWidth, usableHeight) << ", aspect ratio is:" << mAspectRatio << ")" << "Drawable rect:" << mDrawableRect);
       
   311     mRenderer->setImageSize(imageSize);
       
   312     mAutoSize = imageSize;
       
   313     mDrawableRect.setHeight(imageSize.height()/0.8);
       
   314 
       
   315     if (mTitlePosition != HgMediawall::PositionNone) {
       
   316         INFO("Title geometry:" << titleGeometry);
       
   317         mTitleLabel->setGeometry(titleGeometry);
       
   318         mTitleLabel->setVisible(true);
       
   319     }
       
   320     else {
       
   321         mTitleLabel->setVisible(false);
       
   322     }
       
   323     if (mDescriptionPosition != HgMediawall::PositionNone) {
       
   324         INFO("Description geometry:" << descriptionGeometry);
       
   325         mDescriptionLabel->setGeometry(descriptionGeometry);
       
   326         mDescriptionLabel->setVisible(true);
       
   327     }
       
   328     else {
       
   329         mDescriptionLabel->setVisible(false);
       
   330     }
       
   331 
       
   332     // This may be called before selection model is set.
       
   333     if (mSelectionModel && mSelectionModel->currentIndex().isValid()) {
       
   334         updateLabels(mSelectionModel->currentIndex().row());
       
   335     }
       
   336     
       
   337     mRenderer->setSpacing(QSizeF(1,1));
       
   338         
       
   339 }
       
   340 
       
   341 void HgCoverflowContainer::positionLabels()
       
   342 {
       
   343     FUNC_LOG;
       
   344     HANDLE_ERROR_NULL(mTitleLabel);
       
   345     HANDLE_ERROR_NULL(mDescriptionLabel);
       
   346     HANDLE_ERROR_NULL(mSelectionModel);
       
   347 
       
   348     int centerIconTop = (size().height() - mRenderer->getImageSize().height()) / 2;
       
   349 
       
   350     int height = size().height();
       
   351     int width = size().width();
       
   352     int titleHeight = QFontMetrics(mTitleLabel->effectiveFontSpec().font()).height();
       
   353     int descriptionHeight = QFontMetrics(mDescriptionLabel->effectiveFontSpec().font()).height();
   240 
   354 
   241     if (mTitlePosition == HgMediawall::PositionAboveImage &&
   355     if (mTitlePosition == HgMediawall::PositionAboveImage &&
   242         mDescriptionPosition == HgMediawall::PositionAboveImage) {
   356         mDescriptionPosition == HgMediawall::PositionAboveImage) {
   243         mTitleLabel->setGeometry(QRectF(
   357         mTitleLabel->setGeometry(QRectF(
   244             0,
   358             0,
   245             qMax(KLabelMargin, mCenterIconTop-2*KLabelMargin-titleHeight-descriptionHeight),
   359             qMax(KLabelMargin, centerIconTop-2*KLabelMargin-titleHeight-descriptionHeight),
   246             width, titleHeight));
   360             width, titleHeight));
   247         mDescriptionLabel->setGeometry(QRectF(
   361         mDescriptionLabel->setGeometry(QRectF(
   248             0,
   362             0,
   249             mTitleLabel->geometry().bottom()+KLabelMargin,
   363             mTitleLabel->geometry().bottom()+KLabelMargin,
   250             width, descriptionHeight));
   364             width, descriptionHeight));
   262     }
   376     }
   263     else {
   377     else {
   264         if (mTitlePosition == HgMediawall::PositionAboveImage) {
   378         if (mTitlePosition == HgMediawall::PositionAboveImage) {
   265             mTitleLabel->setGeometry(QRectF(
   379             mTitleLabel->setGeometry(QRectF(
   266                 0,
   380                 0,
   267                 qMax(KLabelMargin, mCenterIconTop-KLabelMargin-titleHeight),
   381                 qMax(KLabelMargin, centerIconTop-KLabelMargin-titleHeight),
   268                 width, titleHeight));
   382                 width, titleHeight));
   269         }
   383         }
   270         else if (mTitlePosition == HgMediawall::PositionBelowImage) {
   384         else if (mTitlePosition == HgMediawall::PositionBelowImage) {
   271             mTitleLabel->setGeometry(QRectF(
   385             mTitleLabel->setGeometry(QRectF(
   272                 0,
   386                 0,
   275         }
   389         }
   276 
   390 
   277         if (mDescriptionPosition == HgMediawall::PositionAboveImage) {
   391         if (mDescriptionPosition == HgMediawall::PositionAboveImage) {
   278             mDescriptionLabel->setGeometry(QRectF(
   392             mDescriptionLabel->setGeometry(QRectF(
   279                 0,
   393                 0,
   280                 qMax(KLabelMargin, mCenterIconTop-KLabelMargin-descriptionHeight),
   394                 qMax(KLabelMargin, centerIconTop-KLabelMargin-descriptionHeight),
   281                 width, descriptionHeight));
   395                 width, descriptionHeight));
   282         }
   396         }
   283         else if (mDescriptionPosition == HgMediawall::PositionBelowImage) {
   397         else if (mDescriptionPosition == HgMediawall::PositionBelowImage) {
   284             mDescriptionLabel->setGeometry(QRectF(
   398             mDescriptionLabel->setGeometry(QRectF(
   285                 0,
   399                 0,
   292     mDescriptionLabel->setVisible(mDescriptionPosition != HgMediawall::PositionNone);
   406     mDescriptionLabel->setVisible(mDescriptionPosition != HgMediawall::PositionNone);
   293 
   407 
   294     INFO("Title geometry:" << mTitleLabel->geometry() << "visible:" << mTitleLabel->isVisible());
   408     INFO("Title geometry:" << mTitleLabel->geometry() << "visible:" << mTitleLabel->isVisible());
   295     INFO("Description geometry:" << mDescriptionLabel->geometry() << "visible:" << mDescriptionLabel->isVisible());
   409     INFO("Description geometry:" << mDescriptionLabel->geometry() << "visible:" << mDescriptionLabel->isVisible());
   296 
   410 
   297     if (mSelectionModel->currentIndex().isValid()) {
   411     if ( mSelectionModel &&  mSelectionModel->currentIndex().isValid()) {
   298         updateLabels(mSelectionModel->currentIndex().row());
   412         updateLabels(mSelectionModel->currentIndex().row());
   299     }
   413     }
   300 }
   414 }
       
   415 
   301 
   416 
   302 void HgCoverflowContainer::updateLabels(int itemIndex)
   417 void HgCoverflowContainer::updateLabels(int itemIndex)
   303 {
   418 {
   304     FUNC_LOG;
   419     FUNC_LOG;
   305     HANDLE_ERROR_NULL(mTitleLabel);
   420     HANDLE_ERROR_NULL(mTitleLabel);
   315 {
   430 {
   316     QPointF p = pos;
   431     QPointF p = pos;
   317     p.setX((int)pos.x());
   432     p.setX((int)pos.x());
   318     HgContainer::scrollToPosition(p,animate);
   433     HgContainer::scrollToPosition(p,animate);
   319 }
   434 }
       
   435 
       
   436 QRectF HgCoverflowContainer::drawableRect() const
       
   437 {
       
   438     if (mItemSizePolicy == HgWidget::ItemSizeAutomatic)
       
   439         return mDrawableRect;
       
   440     
       
   441     return rect();
       
   442 }
       
   443 
       
   444 void HgCoverflowContainer::setDefaultImage(QImage defaultImage)
       
   445 {
       
   446     HgContainer::setDefaultImage(defaultImage);
       
   447 
       
   448     if (!defaultImage.isNull()) {
       
   449         mAspectRatio = qMax((qreal)0.1, (qreal)defaultImage.width()/defaultImage.height()); // Don't let aspect ratio go to 0
       
   450         updatePositions();
       
   451     }
       
   452 }
       
   453 
       
   454 QSizeF HgCoverflowContainer::getAutoItemSize() const
       
   455 {
       
   456     return mAutoSize;
       
   457 }
       
   458 
       
   459 QSizeF HgCoverflowContainer::getAutoItemSpacing() const
       
   460 {    
       
   461     return QSizeF(1,1);
       
   462 }
       
   463 
       
   464 void HgCoverflowContainer::updateItemSizeAndSpacing()
       
   465 {
       
   466     HgContainer::updateItemSizeAndSpacing();
       
   467     
       
   468     updatePositions();
       
   469 }
       
   470 
       
   471 
       
   472 void HgCoverflowContainer::updatePositions()
       
   473 {
       
   474     if (mItemSizePolicy == HgWidget::ItemSizeAutomatic)
       
   475         calculatePositions();
       
   476     else
       
   477     {
       
   478         positionLabels();
       
   479     }
       
   480 }
       
   481 
       
   482 void HgCoverflowContainer::setFrontItemPositionDelta(const QPointF& position)
       
   483 {
       
   484     if (!mRenderer)
       
   485         return;
       
   486     
       
   487     mRenderer->setFrontItemPosition(position);
       
   488 }
       
   489 
       
   490 QPointF HgCoverflowContainer::frontItemPositionDelta() const
       
   491 {
       
   492     return mRenderer ? mRenderer->frontItemPosition() : QPointF();
       
   493 }
       
   494 
       
   495 void HgCoverflowContainer::enableReflections(bool enabled)
       
   496 {
       
   497     if (mRenderer)
       
   498         mRenderer->enableReflections(enabled);
       
   499 }
       
   500 
       
   501 bool HgCoverflowContainer::reflectionsEnabled() const
       
   502 {
       
   503     return mRenderer ? mRenderer->reflectionsEnabled() : false;
       
   504 }
       
   505 
       
   506