--- a/ganeswidgets/src/HgContainer.cpp Fri May 14 16:57:01 2010 +0300
+++ b/ganeswidgets/src/HgContainer.cpp Thu May 27 13:59:05 2010 +0300
@@ -34,6 +34,7 @@
#include <hbgridview>
#include <hbiconitem>
#include <qabstractitemmodel>
+#include <hbtapgesture>
#include "hglongpressvisualizer.h"
static const qreal KSpringKScrolling(50.0);
@@ -64,13 +65,12 @@
mItemSizePolicy(HgWidget::ItemSizeAutomatic),
mOrientation(Qt::Vertical),
mDelayedScrollToIndex(),
- mIgnoreTap(false)
+ mIgnoreGestureAction(false)
{
FUNC_LOG;
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,7 +227,7 @@
void HgContainer::setOrientation(Qt::Orientation orientation, bool animate)
{
FUNC_LOG;
-
+
mOrientation = orientation;
mRenderer->setOrientation(orientation);
mRenderer->setScrollDirection(orientation, animate);
@@ -251,20 +259,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 +287,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 +308,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();
+ }
}
}
@@ -400,7 +410,7 @@
if (mSelectionModel && mSelectionModel->isSelected(mSelectionModel->model()->index(index, 0))) {
return 1; // TODO: Assign flag to mark indicator
} else
- return 0;
+ return 0;
}
}
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
@@ -489,14 +499,6 @@
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)
@@ -505,34 +507,29 @@
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)
@@ -553,19 +550,19 @@
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);
+ 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());
}
@@ -577,7 +574,7 @@
}
delete checkBox;
-*/
+*/
connect(&mSpring, SIGNAL(updated()), SLOT(updateBySpringPosition()));
connect(&mSpring, SIGNAL(started()), SIGNAL(scrollingStarted()));
connect(&mSpring, SIGNAL(started()), SLOT(onScrollingStarted()));
@@ -665,11 +662,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 +688,12 @@
boundSpring();
}
}
+ else if(!mDragged && gesture->state() == Qt::GestureFinished) {
+ if (!mRenderer->coverflowModeEnabled()) {
+ mSpring.resetVelocity();
+ update();
+ }
+ }
else if (gesture->state() == Qt::GestureCanceled) {
boundSpring();
}
@@ -698,47 +704,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 +786,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 +847,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;
}
}
}
@@ -966,11 +1001,6 @@
}
}
-void HgContainer::updateByCurrentIndex(const QModelIndex ¤t)
-{
- handleCurrentChanged(current);
-}
-
bool HgContainer::hasItemAt(const QPointF& pos)
{
int dummy;
@@ -1066,12 +1096,6 @@
// By default do nothing
}
-void HgContainer::handleCurrentChanged(const QModelIndex ¤t)
-{
- Q_UNUSED(current)
- // By default do nothing
-}
-
void HgContainer::setDefaultImage(QImage defaultImage)
{
HgQuadRenderer *renderer = mRenderer->getRenderer();
@@ -1147,3 +1171,4 @@
return mSpring.pos().x();
}
+// EOF