39 mSelectionModel(0), |
39 mSelectionModel(0), |
40 mDefaultSelectionModel(0), |
40 mDefaultSelectionModel(0), |
41 mScrollBar(0), |
41 mScrollBar(0), |
42 mAbleToScroll(false), |
42 mAbleToScroll(false), |
43 mHandleLongPress(false), |
43 mHandleLongPress(false), |
44 mBufferSize(DEFAULT_BUFFER_SIZE) |
44 mBufferSize(DEFAULT_BUFFER_SIZE), |
|
45 mStaticScrollDirection(false) |
45 { |
46 { |
46 FUNC_LOG; |
47 FUNC_LOG; |
47 } |
48 } |
48 |
49 |
49 HgWidgetPrivate::~HgWidgetPrivate() |
50 HgWidgetPrivate::~HgWidgetPrivate() |
50 { |
51 { |
51 FUNC_LOG; |
52 FUNC_LOG; |
52 |
53 |
|
54 delete mScrollBarHideTimer; |
53 delete mDefaultSelectionModel; |
55 delete mDefaultSelectionModel; |
54 delete mBufferManager; |
56 delete mBufferManager; |
55 } |
57 } |
56 |
58 |
57 void HgWidgetPrivate::init(HgContainer *container) |
59 void HgWidgetPrivate::init(HgContainer *container) |
58 { |
60 { |
59 FUNC_LOG; |
61 FUNC_LOG; |
60 Q_Q(HgWidget); |
62 Q_Q(HgWidget); |
61 |
63 |
62 mScrollBarHideTimer.setParent(q); |
64 mScrollBarHideTimer = new QTimer(); |
63 mScrollBarHideTimer.setSingleShot(true); |
65 mScrollBarHideTimer->setSingleShot(true); |
64 |
66 |
65 q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
67 q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
66 q->setFlag( QGraphicsItem::ItemClipsChildrenToShape, true ); |
68 q->setFlag( QGraphicsItem::ItemClipsChildrenToShape, true ); |
67 q->setFocusPolicy(Qt::StrongFocus); |
69 q->setFocusPolicy(Qt::StrongFocus); |
68 |
70 |
69 createScrollBar(container->orientation()); |
71 createScrollBar(container->scrollDirection()); |
70 |
72 |
71 QObject::connect(&(mScrollBarHideTimer), SIGNAL(timeout()), q, SLOT(_q_hideScrollBars())); |
73 //QObject::connect(&(mScrollBarHideTimer), SIGNAL(timeout()), q, SLOT(_q_hideScrollBars())); |
72 |
74 |
73 mContainer = container; |
75 mContainer = container; |
74 |
76 |
75 mScrollBarPolicy = HgWidget::ScrollBarAutoHide; |
77 mScrollBarPolicy = HgWidget::ScrollBarAutoHide; |
76 |
78 |
80 q, SIGNAL(activated(const QModelIndex&))); |
82 q, SIGNAL(activated(const QModelIndex&))); |
81 q->connect(mContainer, SIGNAL(longPressed(const QModelIndex&, const QPointF &)), |
83 q->connect(mContainer, SIGNAL(longPressed(const QModelIndex&, const QPointF &)), |
82 q, SIGNAL(longPressed(const QModelIndex&, const QPointF &))); |
84 q, SIGNAL(longPressed(const QModelIndex&, const QPointF &))); |
83 q->connect(mContainer, SIGNAL(scrollingStarted()), q, SIGNAL(scrollingStarted())); |
85 q->connect(mContainer, SIGNAL(scrollingStarted()), q, SIGNAL(scrollingStarted())); |
84 q->connect(mContainer, SIGNAL(scrollingEnded()), q, SIGNAL(scrollingEnded())); |
86 q->connect(mContainer, SIGNAL(scrollingEnded()), q, SIGNAL(scrollingEnded())); |
|
87 q->connect(mScrollBarHideTimer, SIGNAL(timeout()), q, SLOT(_q_hideScrollBars())); |
85 |
88 |
86 mIndexFeedback = new HgIndexFeedback(q); |
89 mIndexFeedback = new HgIndexFeedback(q); |
87 mIndexFeedback->setWidget(q); |
90 mIndexFeedback->setWidget(q); |
88 |
91 |
89 } |
92 } |
242 SLOT(_q_insertRows(QModelIndex, int, int))); |
246 SLOT(_q_insertRows(QModelIndex, int, int))); |
243 q->connect(mModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), |
247 q->connect(mModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), |
244 SLOT(_q_removeRows(QModelIndex, int, int))); |
248 SLOT(_q_removeRows(QModelIndex, int, int))); |
245 q->connect(mModel, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)), |
249 q->connect(mModel, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)), |
246 SLOT(_q_moveRows(QModelIndex, int, int, QModelIndex, int))); |
250 SLOT(_q_moveRows(QModelIndex, int, int, QModelIndex, int))); |
247 |
251 q->connect(mModel, SIGNAL(modelReset()),SLOT(_q_modelReset())); |
|
252 |
248 mContainer->setItemCount(mModel->rowCount(QModelIndex())); |
253 mContainer->setItemCount(mModel->rowCount(QModelIndex())); |
249 QList<HgWidgetItem*> items = mContainer->items(); |
254 QList<HgWidgetItem*> items = mContainer->items(); |
250 |
255 |
251 // set model indexes for the items firsts |
256 // set model indexes for the items firsts |
252 int itemCount = items.count(); |
257 const int itemCount = items.count(); |
253 for( int i=0; i<itemCount; i++) |
258 for( int i=0; i<itemCount; i++) |
254 { |
259 { |
255 items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); |
260 items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); |
256 } |
261 } |
257 |
262 |
258 if( mBufferManager ) |
263 initBufferManager(itemCount); |
259 { |
264 |
260 delete mBufferManager; |
|
261 mBufferManager = 0; |
|
262 } |
|
263 |
|
264 mBufferManager = new HgScrollBufferManager(mBufferSize,mBufferSize/4,0,itemCount); |
|
265 q->connect( mBufferManager, SIGNAL(releaseItems(int,int)), q, SLOT(_q_releaseItems(int,int))); |
|
266 q->connect( mBufferManager, SIGNAL(requestItems(int,int)), q, SLOT(_q_requestItems(int,int))); |
|
267 mBufferManager->resetBuffer(0, itemCount); |
|
268 |
|
269 setSelectionModel(0); // Default |
265 setSelectionModel(0); // Default |
270 |
266 |
271 if (mModel->rowCount() > 0) |
267 if (mModel->rowCount() > 0) |
272 { |
268 { |
273 setCurrentIndex(mModel->index(0, 0)); |
269 setCurrentIndex(mModel->index(0, 0)); |
284 if (mModel) { |
280 if (mModel) { |
285 mModel->disconnect(q, SLOT(dataChanged(QModelIndex, QModelIndex))); |
281 mModel->disconnect(q, SLOT(dataChanged(QModelIndex, QModelIndex))); |
286 mModel->disconnect(q, SLOT(_q_insertRows(QModelIndex, int, int))); |
282 mModel->disconnect(q, SLOT(_q_insertRows(QModelIndex, int, int))); |
287 mModel->disconnect(q, SLOT(_q_removeRows(QModelIndex, int, int))); |
283 mModel->disconnect(q, SLOT(_q_removeRows(QModelIndex, int, int))); |
288 mModel->disconnect(q, SLOT(_q_moveRows(QModelIndex, int, int, QModelIndex, int))); |
284 mModel->disconnect(q, SLOT(_q_moveRows(QModelIndex, int, int, QModelIndex, int))); |
|
285 mModel->disconnect(q, SLOT(_q_modelReset())); |
289 mModel = 0; |
286 mModel = 0; |
290 } |
287 } |
291 |
288 else if (mContainer) { |
|
289 mContainer->setItemCount(0); |
|
290 } |
292 // TODO: setSelectionModel(0); |
291 // TODO: setSelectionModel(0); |
293 |
292 |
294 } |
293 } |
295 void HgWidgetPrivate::_q_releaseItems( int releaseStart, int releaseEnd ) |
294 void HgWidgetPrivate::_q_releaseItems( int releaseStart, int releaseEnd ) |
296 { |
295 { |
389 else if((!mAbleToScroll || mScrollBarPolicy == HgWidget::ScrollBarAlwaysOff) |
388 else if((!mAbleToScroll || mScrollBarPolicy == HgWidget::ScrollBarAlwaysOff) |
390 && mScrollBar->isVisible()){ |
389 && mScrollBar->isVisible()){ |
391 mScrollBar->setVisible(false); |
390 mScrollBar->setVisible(false); |
392 } |
391 } |
393 |
392 |
394 if (scrollBarsVisible && !mScrollBarHideTimer.isActive()) { |
393 if (scrollBarsVisible) { |
395 mScrollBarHideTimer.start(INITIAL_SCROLLBAR_HIDE_TIMEOUT); |
394 mScrollBarHideTimer->stop(); |
|
395 mScrollBarHideTimer->start(INITIAL_SCROLLBAR_HIDE_TIMEOUT); |
396 } |
396 } |
397 } |
397 } |
398 |
398 |
399 void HgWidgetPrivate::displayScrollBar(qreal pos) |
399 void HgWidgetPrivate::displayScrollBar(qreal pos) |
400 { |
400 { |
428 |
428 |
429 // TODO, do we need to know if scrollbar was pressed? we cannot access the private methods, since |
429 // TODO, do we need to know if scrollbar was pressed? we cannot access the private methods, since |
430 // only scrollareaprivate is a friend class. |
430 // only scrollareaprivate is a friend class. |
431 if (false/*scrollBarPressed(mHorizontalScrollBar) || |
431 if (false/*scrollBarPressed(mHorizontalScrollBar) || |
432 scrollBarPressed(mVerticalScrollBar)*/) { |
432 scrollBarPressed(mVerticalScrollBar)*/) { |
433 mScrollBarHideTimer.start(); |
433 mScrollBarHideTimer->start(); |
434 } else if(mScrollBarPolicy != HgWidget::ScrollBarAlwaysOn |
434 } else if(mScrollBarPolicy != HgWidget::ScrollBarAlwaysOn |
435 && mScrollBar->isVisible()){ |
435 && mScrollBar->isVisible()){ |
436 mScrollBar->setVisible(false); |
436 mScrollBar->setVisible(false); |
437 |
437 |
438 } |
438 } |
448 |
448 |
449 mContainer->scrollToPosition( value, true ); |
449 mContainer->scrollToPosition( value, true ); |
450 |
450 |
451 // TODO, stop all scrolling and animations |
451 // TODO, stop all scrolling and animations |
452 |
452 |
453 if (mScrollBarHideTimer.isActive()) { |
453 if (mScrollBarHideTimer->isActive()) { |
454 mScrollBarHideTimer.stop(); |
454 mScrollBarHideTimer->stop(); |
455 mScrollBarHideTimer.start(); |
455 mScrollBarHideTimer->start(); |
456 } |
456 } |
457 } |
457 } |
458 |
458 |
459 void HgWidgetPrivate::_q_insertRows(const QModelIndex &parent, int start, int end) |
459 void HgWidgetPrivate::_q_insertRows(const QModelIndex &parent, int start, int end) |
460 { |
460 { |
462 INFO("Insert rows" << start << "-" << end); |
462 INFO("Insert rows" << start << "-" << end); |
463 Q_UNUSED(parent) |
463 Q_UNUSED(parent) |
464 Q_Q(HgWidget); |
464 Q_Q(HgWidget); |
465 |
465 |
466 if (mContainer) { |
466 if (mContainer) { |
|
467 int oldItemCount = mContainer->itemCount(); |
|
468 mBufferManager->addItems(start, end); |
467 mContainer->addItems(start, end); |
469 mContainer->addItems(start, end); |
468 // re-set model indexes for the items including and after the added indexes |
470 // re-set model indexes for the items including and after the added indexes |
469 QList<HgWidgetItem *> items = mContainer->items(); |
471 QList<HgWidgetItem *> items = mContainer->items(); |
470 int newItemCount = items.count(); |
472 int newItemCount = items.count(); |
471 for (int i = start; i < newItemCount; i++) { |
473 for (int i = start; i < newItemCount; i++) { |
472 items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); |
474 items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); |
473 } |
475 } |
474 mBufferManager->addItems(start, end, newItemCount); |
476 mBufferManager->flushRequestBuffers(); |
|
477 if (oldItemCount == 0 && newItemCount > 0) { |
|
478 setCurrentIndex(mModel->index(0, 0)); |
|
479 } |
475 q->update(); |
480 q->update(); |
476 } |
481 } |
477 } |
482 } |
478 |
483 |
479 void HgWidgetPrivate::_q_removeRows(const QModelIndex &parent, int start, int end) |
484 void HgWidgetPrivate::_q_removeRows(const QModelIndex &parent, int start, int end) |
482 INFO("Remove rows" << start << "-" << end); |
487 INFO("Remove rows" << start << "-" << end); |
483 Q_UNUSED(parent) |
488 Q_UNUSED(parent) |
484 Q_Q(HgWidget); |
489 Q_Q(HgWidget); |
485 |
490 |
486 if (mContainer && mBufferManager) { |
491 if (mContainer && mBufferManager) { |
487 mContainer->removeItems(start, end); |
492 int itemCount = mContainer->itemCount(); |
|
493 int first= qBound(0, start, itemCount-1); |
|
494 int last = qBound(0, end, itemCount-1); |
|
495 |
|
496 mBufferManager->removeItems(first, last); |
|
497 mContainer->removeItems(first, last); |
488 // re-set model indexes for the items after the removed indexes |
498 // re-set model indexes for the items after the removed indexes |
489 QList<HgWidgetItem *> items = mContainer->items(); |
499 QList<HgWidgetItem *> items = mContainer->items(); |
490 int newItemCount = items.count(); |
500 int newItemCount = items.count(); |
491 for (int i = start; i < newItemCount; i++) { |
501 for (int i = first; i < newItemCount; i++) { |
492 items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); |
502 items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); |
493 } |
503 } |
494 mBufferManager->removeItems(start, end, newItemCount); |
504 mBufferManager->flushRequestBuffers(); |
495 q->update(); |
505 q->update(); |
496 } |
506 } |
497 } |
507 } |
498 |
508 |
499 void HgWidgetPrivate::_q_moveRows(const QModelIndex &sourceParent, |
509 void HgWidgetPrivate::_q_moveRows(const QModelIndex &sourceParent, |
506 Q_UNUSED(destinationParent) |
516 Q_UNUSED(destinationParent) |
507 Q_Q(HgWidget); |
517 Q_Q(HgWidget); |
508 |
518 |
509 if (mContainer) { |
519 if (mContainer) { |
510 mContainer->moveItems(sourceStart, sourceEnd, destinationRow); |
520 mContainer->moveItems(sourceStart, sourceEnd, destinationRow); |
|
521 mBufferManager->moveItems(sourceStart, sourceEnd, destinationRow); |
511 // re-set model indexes for the items after the removed indexes |
522 // re-set model indexes for the items after the removed indexes |
512 QList<HgWidgetItem *> items = mContainer->items(); |
523 QList<HgWidgetItem *> items = mContainer->items(); |
513 int itemCount = items.count(); |
524 int itemCount = items.count(); |
514 for (int i = qMin(sourceStart, destinationRow); i < itemCount; i++) { |
525 for (int i = qMin(sourceStart, destinationRow); i < itemCount; i++) { |
515 items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); |
526 items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); |
516 } |
527 } |
517 mBufferManager->moveItems(sourceStart, sourceEnd, destinationRow, itemCount); |
528 mBufferManager->flushRequestBuffers(); |
518 q->update(); |
529 q->update(); |
|
530 } |
|
531 } |
|
532 |
|
533 void HgWidgetPrivate::_q_modelReset() |
|
534 { |
|
535 if (mContainer && mBufferManager) { |
|
536 const int oldItemCount = mContainer->itemCount(); |
|
537 const int newItemCount = mModel->rowCount(); |
|
538 if (newItemCount == oldItemCount) { |
|
539 // Model is reseted but itemcount is still the same. |
|
540 // Just reload all data for current buffer. |
|
541 mBufferManager->resetBuffer(mContainer->scrollPosition(), newItemCount); |
|
542 } |
|
543 else { |
|
544 // Container destroyes all old items when new itemcount is set. |
|
545 mContainer->setItemCount(newItemCount); |
|
546 |
|
547 // set model indexes for the items |
|
548 QList<HgWidgetItem*> items = mContainer->items(); |
|
549 const int itemCount = items.count(); |
|
550 for( int i=0; i<itemCount; i++) { |
|
551 items.at(i)->setModelIndex(mModel->index(i, 0, QModelIndex())); |
|
552 } |
|
553 |
|
554 // Buffermanager requests items to be updated. |
|
555 mBufferManager->resetBuffer(0, newItemCount); |
|
556 if (mModel->rowCount() > 0) { |
|
557 setCurrentIndex(mModel->index(0, 0)); |
|
558 scrollTo(mModel->index(0, 0)); |
|
559 } |
|
560 } |
519 } |
561 } |
520 } |
562 } |
521 |
563 |
522 void HgWidgetPrivate::setScrollBarMetrics(qreal pos) |
564 void HgWidgetPrivate::setScrollBarMetrics(qreal pos) |
523 { |
565 { |
688 HgWidget::IndexFeedbackPolicy HgWidgetPrivate::indexFeedbackPolicy() const |
729 HgWidget::IndexFeedbackPolicy HgWidgetPrivate::indexFeedbackPolicy() const |
689 { |
730 { |
690 return mIndexFeedback->indexFeedbackPolicy(); |
731 return mIndexFeedback->indexFeedbackPolicy(); |
691 } |
732 } |
692 |
733 |
|
734 void HgWidgetPrivate::setDefaultImage(QImage defaultImage) |
|
735 { |
|
736 mContainer->setDefaultImage(defaultImage); |
|
737 } |
|
738 |
|
739 void HgWidgetPrivate::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) |
|
740 { |
|
741 FUNC_LOG; |
|
742 |
|
743 // TODO,take columns into count |
|
744 for( int i = topLeft.row(); i <= bottomRight.row(); i++ ){ |
|
745 // if data for item outside our current buffer has changed |
|
746 // we just have to ignore it since we dont have resources |
|
747 // to handle it(or we dont want to waste resources). |
|
748 if (mBufferManager->positionInsideBuffer(i)) { |
|
749 HgWidgetItem* item = mContainer->itemByIndex( i ); |
|
750 if (item) { |
|
751 item->updateItemData(); |
|
752 } |
|
753 } |
|
754 } |
|
755 mContainer->itemDataChanged(topLeft, bottomRight); |
|
756 } |
|
757 |
|
758 void HgWidgetPrivate::setItemSizePolicy(HgWidget::ItemSizePolicy policy) |
|
759 { |
|
760 mContainer->setItemSizePolicy(policy); |
|
761 } |
|
762 |
|
763 HgWidget::ItemSizePolicy HgWidgetPrivate::itemSizePolicy() const |
|
764 { |
|
765 return mContainer->itemSizePolicy(); |
|
766 } |
|
767 |
|
768 void HgWidgetPrivate::setItemSize(const QSizeF& size) |
|
769 { |
|
770 mContainer->setItemSize(size); |
|
771 } |
|
772 |
|
773 QSizeF HgWidgetPrivate::itemSize() const |
|
774 { |
|
775 return mContainer->itemSize(); |
|
776 } |
|
777 |
|
778 void HgWidgetPrivate::setItemSpacing(const QSizeF& spacing) |
|
779 { |
|
780 mContainer->setItemSpacing(spacing); |
|
781 } |
|
782 |
|
783 QSizeF HgWidgetPrivate::itemSpacing() const |
|
784 { |
|
785 return mContainer->itemSpacing(); |
|
786 } |
|
787 |
|
788 void HgWidgetPrivate::initBufferManager(int itemCount) |
|
789 { |
|
790 Q_Q(HgWidget); |
|
791 if (mBufferManager) { |
|
792 q->disconnect( mBufferManager, SIGNAL(releaseItems(int,int)), q, SLOT(_q_releaseItems(int,int))); |
|
793 q->disconnect( mBufferManager, SIGNAL(requestItems(int,int)), q, SLOT(_q_requestItems(int,int))); |
|
794 delete mBufferManager; |
|
795 mBufferManager = 0; |
|
796 } |
|
797 |
|
798 mBufferManager = new HgScrollBufferManager(mBufferSize,qMax(mContainer->rowCount()*2,3),0,itemCount); |
|
799 q->connect( mBufferManager, SIGNAL(releaseItems(int,int)), q, SLOT(_q_releaseItems(int,int))); |
|
800 q->connect( mBufferManager, SIGNAL(requestItems(int,int)), q, SLOT(_q_requestItems(int,int))); |
|
801 mBufferManager->resetBuffer(0, itemCount); |
|
802 } |
|
803 |
693 #include "moc_hgwidgets.cpp" |
804 #include "moc_hgwidgets.cpp" |