ganeswidgets/src/HgContainer.cpp
branchGCC_SURGE
changeset 10 c348b9772569
parent 9 dde80bf4a8c7
child 13 8bf920201dea
--- a/ganeswidgets/src/HgContainer.cpp	Fri Jun 11 16:25:05 2010 +0100
+++ b/ganeswidgets/src/HgContainer.cpp	Thu Jul 22 16:36:56 2010 +0100
@@ -18,8 +18,7 @@
 #include <QGesture>
 #include <QPainter>
 #include <QTimer>
-#include <hbgridviewitem>
-#include <hbmainwindow>
+#include <HbMainWindow>
 #include "hgcontainer.h"
 #include "hgmediawallrenderer.h"
 #include "hgquad.h"
@@ -28,12 +27,12 @@
 #include "hgwidgetitem.h"
 #include "trace.h"
 
-//#include <hbstyleoptioncheckbox.h>
-//#include <hbcheckbox>
-#include <hbgridviewitem>
-#include <hbgridview>
-#include <hbiconitem>
-#include <qabstractitemmodel>
+#include <HbCheckBox>
+#include <HbGridViewItem>
+#include <HbGridView>
+#include <HbIconItem>
+#include <QAbstractItemModel>
+#include <HbTapGesture>
 #include "hglongpressvisualizer.h"
 
 static const qreal KSpringKScrolling(50.0);
@@ -64,13 +63,14 @@
     mItemSizePolicy(HgWidget::ItemSizeAutomatic),
     mOrientation(Qt::Vertical),
     mDelayedScrollToIndex(),
-    mIgnoreTap(false)
+    mIgnoreGestureAction(false)
 {
     FUNC_LOG;
 
+    setFlag(QGraphicsItem::ItemHasNoContents, false);
+
     grabGesture(Qt::PanGesture);
     grabGesture(Qt::TapGesture);
-    grabGesture(Qt::TapAndHoldGesture);
 }
 
 HgContainer::~HgContainer()
@@ -134,24 +134,32 @@
     Ownership is not transferred.
     Widget is redrawn to make new selection visible.
 */
-void HgContainer::setSelectionModel(QItemSelectionModel *selectionModel)
+void HgContainer::setSelectionModel(QItemSelectionModel *selectionModel, const QModelIndex &defaultItem)
 {
     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 == selectionModel) return;
+
+    bool defaultCurrentSet(false);
 
-            if (mSelectionModel->currentIndex().isValid() &&
-                !(selectionModel->currentIndex().isValid())) {
-                selectionModel->setCurrentIndex(mSelectionModel->currentIndex(),
-                    QItemSelectionModel::Current);
-            }
+    if (!selectionModel->currentIndex().isValid()) { // If there is valid current item, do not change it
+        if (!mSelectionModel && defaultItem.isValid()) { // mSelectionModel is 0 when called first time
+            selectionModel->setCurrentIndex(defaultItem, QItemSelectionModel::Current);
+            defaultCurrentSet = true;
+        }
+        else if (mSelectionModel && mSelectionModel->currentIndex().isValid()) {
+            selectionModel->setCurrentIndex(mSelectionModel->currentIndex(),
+            QItemSelectionModel::Current);
         }
-        mSelectionModel = selectionModel;
-        connect(mSelectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
-                                 SLOT(updateByCurrentIndex(QModelIndex)));
+    }
+
+    mSelectionModel = selectionModel;
+
+    if (mSelectionModel->currentIndex().isValid() && !defaultCurrentSet) {
+        scrollTo(mSelectionModel->currentIndex());
+    }
+    else {
         update();
     }
 }
@@ -219,13 +227,14 @@
 void HgContainer::setOrientation(Qt::Orientation orientation, bool animate)
 {
     FUNC_LOG;
-    
+
     mOrientation = orientation;
     mRenderer->setOrientation(orientation);
     mRenderer->setScrollDirection(orientation, animate);
-    if (!mSpring.isActive() && mSpring.pos().x() > worldWidth())
-        boundSpring();
-
+    if (mSpring.isActive()) {
+        // Need to stop scrolling.
+        mSpring.cancel();
+    }
 }
 
 void HgContainer::scrollToPosition(qreal value, bool animate)
@@ -251,20 +260,22 @@
 void HgContainer::scrollTo(const QModelIndex &index)
 {
     FUNC_LOG;
+    INFO("Scrolling to" << index);
 
     if (index.isValid() && mRenderer->getRowCount() > 0 ) {
-    
+
         QRectF containerRect(rect());
         if (containerRect.isNull()) {
             // Container hasn't been resized yet. We need to know the container
             // size before we can calculate if index we are scrolling to is valid.
             // Store scrollTo index and scrolling is performed when container is resized.
             mDelayedScrollToIndex = index;
+            return;
         }
-        
+
         // Container has some size. We can try to calculate if scrollto index is valid.
         // ScrollTo index will be the top item in grid and left item on coverflow.
-        
+
         if (!mRenderer->coverflowModeEnabled()) {
             // Grid case
             int itemsOnScreen = 0;
@@ -277,12 +288,12 @@
                 itemsOnScreen *= rowCount();
                 if (itemsOnScreen + index.row() > mItems.count()) {
                     int newItem = mItems.count()-itemsOnScreen;
-                    
-                    if (mItems.count()%rowCount()) 
+
+                    if (mItems.count()%rowCount())
                         newItem += rowCount() - (mItems.count()%rowCount());
-                    if (newItem < 0) 
+                    if (newItem < 0)
                         newItem = 0;
-                    
+
                     scrollToPosition(QPointF(newItem/mRenderer->getRowCount(),0), false);
                 } else {
                     scrollToPosition(QPointF(index.row()/mRenderer->getRowCount(), 0), false);
@@ -298,21 +309,21 @@
                 if (itemsOnScreen + index.row() > mItems.count()) {
                     int newItem = mItems.count()-itemsOnScreen;
 
-                    if (mItems.count()%rowCount()) 
+                    if (mItems.count()%rowCount())
                         newItem += rowCount() - (mItems.count()%rowCount());
                     if (newItem < 0) newItem = 0;
-                    
+
                     scrollToPosition(QPointF(newItem/mRenderer->getRowCount(),0), false);
                 } else {
                     scrollToPosition(QPointF(index.row()/mRenderer->getRowCount(), 0), false);
                 }
             }
-            updateBySpringPosition();            
+            updateBySpringPosition();
         } else {
             // Coverflow case. TODO, this will need some finetuning.
             scrollToPosition(QPointF(index.row()/mRenderer->getRowCount(), 0), false);
-            updateBySpringPosition();            
-        }                    
+            updateBySpringPosition();
+        }
     }
 }
 
@@ -396,11 +407,10 @@
 {
     if (index >= 0 && index < itemCount()) {
         if (mSelectionMode != HgWidget::NoSelection) {
-            // TODO, fix these returns values when we can use the checkbox indicators.
             if (mSelectionModel && mSelectionModel->isSelected(mSelectionModel->model()->index(index, 0))) {
                 return 1; // TODO: Assign flag to mark indicator
             } else
-                return 0;        
+                return 2;
         }
     }
     return 0;
@@ -438,20 +448,20 @@
 {
     Q_UNUSED(option)
     Q_UNUSED(widget)
-    
-    // update spring position at paint if needed, 
-    // this is hack for scrollbar, since dragging it 
+
+    // update spring position at paint if needed,
+    // this is hack for scrollbar, since dragging it
     // causes also paint events in here
     if (mSpring.updatePositionIfNeeded())
     {
         qreal pos = mSpring.pos().x();
         onScrollPositionChanged(pos);
-        emit scrollPositionChanged(pos, true);        
+        emit scrollPositionChanged(pos, true);
     }
-    
+
     QPainter::RenderHints hints = painter->renderHints();
     painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
-    
+
 
     // interpolate spring velocity towards zero, this is done
     // so that spring velocity for rendering doesn't drop directly to
@@ -469,7 +479,7 @@
     mRenderer->draw(mSpring.startPos(), mSpring.pos(), mSpring.endPos(),
                     springVel, painter, sceneTransform(), rect());
 
-    painter->setRenderHint(QPainter::SmoothPixmapTransform, false);
+    painter->setRenderHint(QPainter::SmoothPixmapTransform, (hints.testFlag(QPainter::SmoothPixmapTransform)) );
 }
 
 void HgContainer::resizeEvent(QGraphicsSceneResizeEvent *event)
@@ -489,50 +499,43 @@
 void HgContainer::mousePressEvent(QGraphicsSceneMouseEvent *event)
 {
     Q_UNUSED(event);
-    if (mSpring.isActive() && !mRenderer->coverflowModeEnabled()) {
-        // We could do some small animation when scrolling is stopped.
-        mSpring.cancel();
-        update();
-        mIgnoreTap = true;
-    } else {
-        mIgnoreTap = false;
-    }
 }
 
 void HgContainer::gestureEvent(QGestureEvent *event)
 {
     FUNC_LOG;
 
+    if (mItems.count() == 0) {
+        // we have no items so no need to handle the gesture.
+        event->ignore();
+        return;
+    }
+    
     bool eventHandled(false);
     // Event may contain more than one gesture type
-    if (QGesture *gesture = event->gesture(Qt::TapAndHoldGesture)) {
-        QTapAndHoldGesture *tapAndHold = static_cast<QTapAndHoldGesture *>(gesture);
-        if (handleLongTap(tapAndHold->state(),
-                mapFromScene(event->mapToGraphicsScene(tapAndHold->position())))) {
+    HbTapGesture *tap = 0;
+    if (QGesture *gesture = event->gesture(Qt::TapGesture)) {
+        tap = static_cast<HbTapGesture *>(event->gesture(Qt::TapGesture));
+        if (tap->tapStyleHint() == HbTapGesture::TapAndHold) {
+            eventHandled = handleLongTap(tap->state(),
+                    mapFromScene(event->mapToGraphicsScene(tap->hotSpot())));
+        
+        } else {
+            eventHandled = handleTap(tap->state(),
+                    mapFromScene(event->mapToGraphicsScene(tap->hotSpot())));
         }
     }
-    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<QTapGesture *>(gesture);
-        eventHandled = handleTap(tap->state(),
-            mapFromScene(event->mapToGraphicsScene(tap->position())));
-    }
-    else if (QGesture *pan = event->gesture(Qt::PanGesture)) {
+    if (QGesture *pan = event->gesture(Qt::PanGesture)) {
         eventHandled = handlePanning(static_cast<QPanGesture*>(pan));
+    } else if( mIgnoreGestureAction && tap && tap->state() == Qt::GestureCanceled ) {
+        // user has tapped or long pressed in grid while scrolling so we need to
+        // stop the 3d effect.
+        mSpring.resetVelocity();
+        update();
+        mIgnoreGestureAction = false;
     }
 
-    if (eventHandled) {
-        event->accept();
-        event->accept(Qt::TapAndHoldGesture);
-        event->accept(Qt::TapGesture);
-        event->accept(Qt::PanGesture);
-    }
-    else {
-        event->ignore();
-        event->ignore(Qt::TapAndHoldGesture);
-        event->ignore(Qt::TapGesture);
-        event->ignore(Qt::PanGesture);
-    }
+    eventHandled ? event->accept() : event->ignore();    
 }
 
 void HgContainer::init(Qt::Orientation scrollDirection)
@@ -544,40 +547,35 @@
 
     mQuadRenderer = mRenderer->getRenderer();
 
-    QImage markImage(":/images/mark.svg");
-    if (markImage.isNull()) {
-        ERROR("Failed to load :/images/mark.svg");
-    }
+    // Fetch icons for marking mode (on and off states).
+
     mMarkImageOn = mQuadRenderer->createNativeImage();
     HANDLE_ERROR_NULL(mMarkImageOn);
-    if (mMarkImageOn) {
-        mMarkImageOn->setImage(markImage);
-    }
-    
-/*    mMarkImageOn = mQuadRenderer->createNativeImage();
-    HANDLE_ERROR_NULL(mMarkImageOn);
     mMarkImageOff = mQuadRenderer->createNativeImage();
     HANDLE_ERROR_NULL(mMarkImageOff);
-    
-    // Fetch icons for marking mode (on and off states).
-    QGraphicsItem* checkBox = style()->createPrimitive(HbStyle::P_CheckBox_icon, this); 
-    HbIconItem* iconItem = static_cast<HbIconItem*>(checkBox);    
-    HbStyleOptionCheckBox checkBoxOption;
-    checkBoxOption.state = QStyle::State_On;
-    style()->updatePrimitive(iconItem, HbStyle::P_CheckBox_icon, &checkBoxOption);
-    
-    if (mMarkImageOn) {
-        mMarkImageOn->setPixmap(iconItem->icon().pixmap());
+
+    // Since there is no way to create the icons directly currently
+    // lets create HbCheckBox and ask primitives from it.
+    HbCheckBox* checkBox = new HbCheckBox();
+    checkBox->setCheckState(Qt::Checked);
+    QGraphicsItem *icon = checkBox->HbWidget::primitive("icon");
+    HbIconItem *iconItem = 0;
+    if (icon) {
+        iconItem = static_cast<HbIconItem*>(icon);    
+        if (mMarkImageOn) {
+            mMarkImageOn->setPixmap(iconItem->icon().pixmap());
+        }
     }
+    checkBox->setCheckState(Qt::Unchecked);
+    icon = checkBox->HbWidget::primitive("icon");    
+    if (icon) {
+        iconItem = static_cast<HbIconItem*>(icon);
+        if (mMarkImageOff) {
+            mMarkImageOff->setPixmap(iconItem->icon().pixmap());
+        }
+    }    
+    delete checkBox;
 
-    checkBoxOption.state = QStyle::State_Off;
-    style()->updatePrimitive(iconItem, HbStyle::P_CheckBox_icon, &checkBoxOption);
-    if (mMarkImageOff) {
-        mMarkImageOff->setPixmap(iconItem->icon().pixmap());
-    }
-
-    delete checkBox;
-*/    
     connect(&mSpring, SIGNAL(updated()), SLOT(updateBySpringPosition()));
     connect(&mSpring, SIGNAL(started()), SIGNAL(scrollingStarted()));
     connect(&mSpring, SIGNAL(started()), SLOT(onScrollingStarted()));
@@ -665,11 +663,14 @@
             emit scrollingStarted();
 
             qreal newPosition = mDrag.update(delta, pos, itemSide);
-            if (qAbs(newPosition - mSpring.pos().x()) > 0.01f)
-            {
+            if (qAbs(newPosition - mSpring.pos().x()) > 0.01f) {
                 mSpring.gotoPos(QPointF(newPosition, 0));
-                emit scrollPositionChanged(newPosition,true);
-                update();
+                if (mRenderer->coverflowModeEnabled()) {
+                    emit scrollPositionChanged(newPosition,true);
+                    update();                
+                } else {
+                    updateBySpringPosition();
+                }
             }
         }
     }
@@ -688,6 +689,12 @@
             boundSpring();
         }
     }
+    else if(!mDragged && gesture->state() == Qt::GestureFinished) {
+        if (!mRenderer->coverflowModeEnabled()) {
+            mSpring.resetVelocity();
+            update();
+        }
+    }
     else if (gesture->state() == Qt::GestureCanceled) {
         boundSpring();
     }
@@ -698,47 +705,64 @@
 bool HgContainer::handleTap(Qt::GestureState state, const QPointF &pos)
 {
     FUNC_LOG;
+    
+    bool handleGesture = false;
 
-    if (state == Qt::GestureStarted) {
-        if (hasItemAt(pos)) {
-            mTapDuration.start();
-            startLongPressWatcher(pos);
-            return true;
-        }
-        return false;
-    }
-    else if (state == Qt::GestureCanceled)
-    {
-        stopLongPressWatcher();
-
-        if (hasItemAt(pos)) {
-            return true;
-        }
-        return false;
-    }
-    else if (state == Qt::GestureFinished) {
-        stopLongPressWatcher();
-        return handleItemAction(pos, mTapDuration.elapsed() > KLongTapDuration ? LongTap : NormalTap);
-    }
-
-    return false;
+    if (hasItemAt(pos)) {
+        switch (state) 
+            {
+            case Qt::GestureStarted:
+                {
+                if (mRenderer->coverflowModeEnabled() || !mSpring.isActive()) {
+                    mIgnoreGestureAction = false;
+                    startLongPressWatcher(pos);
+                } else if(mSpring.isActive()) {
+                    mSpring.cancel();
+                    mIgnoreGestureAction = true;
+                }
+                break;
+                }
+            case Qt::GestureFinished:
+                handleGesture = handleItemAction(pos, NormalTap);
+            case Qt::GestureUpdated:
+            case Qt::GestureCanceled:
+            default:
+                stopLongPressWatcher();
+                break;
+            }
+        
+        handleGesture = true;
+    } else {
+       mIgnoreGestureAction = true;
+    }    
+    return handleGesture;
 }
 
 bool HgContainer::handleLongTap(Qt::GestureState state, const QPointF &pos)
 {
     FUNC_LOG;
 
+    bool handleGesture = false;
+    
     if (hasItemAt(pos)) {
-        mAnimateUsingScrollBar = false;
-        initSpringForScrolling();
 
-        if (state == Qt::GestureFinished) {
-            handleItemAction(pos, LongTap);
-        }
-        return true;
+        switch (state) 
+            {
+            case Qt::GestureUpdated:
+                handleItemAction(pos,LongTap);
+            case Qt::GestureStarted:
+            case Qt::GestureCanceled:
+            case Qt::GestureFinished:
+            default:
+                stopLongPressWatcher();
+                break;                
+            }
+        handleGesture = true;
+    } else {
+        mIgnoreGestureAction = true;        
     }
 
-    return false;
+    return handleGesture;
 }
 
 /*!
@@ -763,12 +787,19 @@
             if (action == LongTap) {
                 INFO("Long tap:" << item->modelIndex().row());
                 
-                mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
-                
-                if (!mRenderer->coverflowModeEnabled())
+                if (!mRenderer->coverflowModeEnabled()) {
                     selectItem(index);
-                
-                emit longPressed(item->modelIndex(), pos);
+                } else {
+                    mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
+                }
+
+                if (!mIgnoreGestureAction) {
+                    emit longPressed(item->modelIndex(), pos);
+                } else {
+                    mSpring.resetVelocity();
+                    update();
+                    mIgnoreGestureAction = false;
+                }
             }
             else if (mSelectionMode == HgWidget::MultiSelection) {
                 mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
@@ -817,10 +848,15 @@
                     }
                 }
                 else {   //grid mode
-                    if (!mIgnoreTap) {
-                        mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
+                    if (!mIgnoreGestureAction) {
+                        // Current should be topleft item.
+//                        mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
                         selectItem(index);
                         emit activated(item->modelIndex());                        
+                    } else {
+                        mSpring.resetVelocity();
+                        update();
+                        mIgnoreGestureAction = false;
                     }
                 }
             }
@@ -848,7 +884,9 @@
     for (int i = 0; i < quads.count(); i++) {
         bool ok;
         int index = quads.at(i)->userData().toInt(&ok);
-        result.append(itemByIndex(index)->modelIndex());
+        HgWidgetItem *item = itemByIndex(index);
+        if (item)
+            result.append(item->modelIndex());
     }
     qSort(result);
     return result;
@@ -857,7 +895,7 @@
 void HgContainer::itemDataChanged(const int &firstIndex, const int &lastIndex)
 {
     FUNC_LOG;
-
+    
     int firstItemOnScreen = 0, lastItemOnScreen = 0;
     firstItemOnScreen = mSpring.pos().x();
     firstItemOnScreen *= rowCount();
@@ -865,14 +903,15 @@
     int itemsOnScreen = mRenderer->getVisibleQuads().count();
     lastItemOnScreen = firstItemOnScreen+itemsOnScreen;
 
-    if ((firstIndex >= firstItemOnScreen && firstIndex < lastItemOnScreen) ||
+    if ( itemsOnScreen == 0 || (firstIndex >= firstItemOnScreen && firstIndex < lastItemOnScreen) ||
         (lastIndex >= firstItemOnScreen && lastIndex < lastItemOnScreen)) {
         update();
-    }
+    }    
 }
 
 void HgContainer::selectItem(int index)
 {
+    Q_UNUSED(index)
     // TODO: replace this with own selection implementation
 /*    if (index < 0 && index >= mItems.count())
         return;
@@ -966,11 +1005,6 @@
     }
 }
 
-void HgContainer::updateByCurrentIndex(const QModelIndex &current)
-{
-    handleCurrentChanged(current);
-}
-
 bool HgContainer::hasItemAt(const QPointF& pos)
 {
     int dummy;
@@ -1066,12 +1100,6 @@
     // By default do nothing
 }
 
-void HgContainer::handleCurrentChanged(const QModelIndex &current)
-{
-    Q_UNUSED(current)
-    // By default do nothing
-}
-
 void HgContainer::setDefaultImage(QImage defaultImage)
 {
     HgQuadRenderer *renderer = mRenderer->getRenderer();
@@ -1147,3 +1175,4 @@
     return mSpring.pos().x();
 }
 
+// EOF