summaryrefslogtreecommitdiffstats
path: root/weather/src/contentlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'weather/src/contentlist.cpp')
-rw-r--r--weather/src/contentlist.cpp441
1 files changed, 441 insertions, 0 deletions
diff --git a/weather/src/contentlist.cpp b/weather/src/contentlist.cpp
new file mode 100644
index 0000000..8b054aa
--- /dev/null
+++ b/weather/src/contentlist.cpp
@@ -0,0 +1,441 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: openBossa - INdT (renato.chencarek@openbossa.org)
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** the openBossa stream from INdT (renato.chencarek@openbossa.org).
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "contentlist.h"
+#include <QPointer>
+
+// ContentListItem
+
+ContentListItem::ContentListItem(QGraphicsItem *parent)
+ : QGraphicsItem(parent)
+ , m_geometry(QRectF(0.0, 0.0, 0.0, 0.0))
+ , m_geometryReady(false)
+{
+ setFlag(QGraphicsItem::ItemHasNoContents, true);
+ setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+}
+
+QRectF ContentListItem::boundingRect() const
+{
+ if (!m_geometryReady)
+ return QRectF(0.0, 0.0, 0.0, contentHeight());
+ return m_geometry;
+}
+
+void ContentListItem::updateGeometry()
+{
+ m_geometryReady = parentItem() != 0;
+ qreal width = parentItem() ? parentItem()->boundingRect().width() - pos().x() : 0.0;
+ QRectF geometry(0.0, 0.0, width, contentHeight());
+ if (m_geometry != geometry) {
+ prepareGeometryChange();
+ m_geometry = geometry;
+ update();
+ }
+}
+
+QVariant ContentListItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ Q_UNUSED(value);
+ switch (change) {
+ case QGraphicsItem::ItemParentHasChanged:
+ case QGraphicsItem::ItemPositionHasChanged:
+ updateGeometry();
+ break;
+ default:
+ break;
+ }
+ return value;
+}
+
+void ContentListItem::paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+}
+
+// ContentListActivity
+
+void ContentListActivity::addActivity(ContentListActivity *activity)
+{
+ int idx = m_list.m_queue.indexOf(this) + 1;
+ if (idx > 0)
+ m_list.m_queue.insert(idx + m_insertPos++, activity);
+}
+
+bool ContentListActivity::active()
+{
+ return false;
+}
+
+// SignalActivity
+
+
+bool SignalActivity::run()
+{
+ emit notify();
+ return false;
+}
+
+// SortActivity
+
+bool SortActivity::run()
+{
+ qSort(m_list.m_items.begin(), m_list.m_items.end(), m_compare);
+ m_list.updateItems();
+ return false;
+}
+
+// AppendItemsActivity
+
+bool AppendItemsActivity::run()
+{
+ m_list.prepareGeometryChange();
+ m_list.doAppendItems(m_items, true);
+ m_list.update();
+ return false;
+}
+
+// AnimationActivity
+
+AnimationActivity::AnimationActivity(QAbstractAnimation *animation, ContentList &list)
+ : ContentListActivity(list)
+ , m_animation(animation)
+{
+}
+
+AnimationActivity::~AnimationActivity()
+{
+ if (m_animation && m_animation->state() == QAbstractAnimation::Stopped)
+ m_animation->deleteLater();
+}
+
+
+bool AnimationActivity::run()
+{
+ if (!m_animation || m_animation->state() != QAbstractAnimation::Stopped)
+ return false;
+
+ connect(m_animation, SIGNAL(finished()), this, SLOT(animationEnd()));
+ m_animation->start(QAbstractAnimation::DeleteWhenStopped);
+ return true;
+}
+
+void AnimationActivity::animationEnd()
+{
+ m_animation = 0;
+ activityEnd();
+}
+
+// RemoveActivity
+
+RemoveActivity::RemoveActivity(int idx, bool destroyItem, bool notify, ContentList &list)
+ : ContentListActivity(list)
+ , m_idx(idx)
+ , m_destroyItem(destroyItem)
+ , m_item(0)
+ , m_active(false)
+ , m_notify(notify)
+{
+}
+
+bool RemoveActivity::run()
+{
+ if (m_active)
+ return false;
+
+ m_item = m_list.getItem(m_idx);
+ if (!m_item)
+ return false;
+
+ QAbstractAnimation *animation = m_item->getHideAnimation();
+ if (animation) {
+ connect(animation, SIGNAL(finished()), this, SLOT(hideEnd()));
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+ m_active = true;
+ } else
+ hideEnd();
+
+ return m_active;
+}
+
+void RemoveActivity::hideEnd()
+{
+ m_item->hide();
+ QAbstractAnimation *animation = m_list.getRemoveAnimation(m_idx);
+ m_list.doRemoveItem(m_idx, m_notify);
+ if (m_destroyItem)
+ m_item->deleteLater();
+ m_active = animation != 0;
+ if (animation) {
+ connect(animation, SIGNAL(finished()), this, SLOT(activityEnd()));
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+ } else
+ activityEnd();
+}
+
+// InsertActivity
+
+InsertActivity::InsertActivity(int idx, ContentListItem* item, bool notify, ContentList &list)
+ : ContentListActivity(list)
+ , m_idx(idx)
+ , m_item(item)
+ , m_active(false)
+ , m_notify(notify)
+{
+}
+
+bool InsertActivity::run()
+{
+ if (m_active || !m_item)
+ return false;
+
+ m_idx = m_idx < 0 ? 0 : m_idx > m_list.itemCount() ? m_list.itemCount() : m_idx;
+
+
+ QAbstractAnimation *animation = m_list.getInsertAnimation(m_idx, m_item->contentHeight());
+ if (animation) {
+ connect(animation, SIGNAL(finished()), this, SLOT(showItem()));
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+ m_active = true;
+ } else
+ showItem();
+
+ return m_active;
+}
+
+void InsertActivity::showItem()
+{
+ m_list.doInsertItem(m_idx, m_item, m_notify);
+ m_item->show();
+ QAbstractAnimation *animation = m_item->getShowAnimation();
+ m_active = animation != 0;
+ if (animation) {
+ connect(animation, SIGNAL(finished()), this, SLOT(activityEnd()));
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+ } else
+ activityEnd();
+}
+
+// MoveActivity
+
+MoveActivity::MoveActivity(int from, int to, ContentList &list)
+ : ContentListActivity(list)
+ , m_from(from)
+ , m_to(to)
+{
+}
+
+bool MoveActivity::run()
+{
+ if (m_from < 0 || m_from >= m_list.itemCount())
+ return false;
+
+ m_to = m_to < 0 ? 0 : m_to > m_list.itemCount() ? m_list.itemCount() : m_to;
+
+ if (m_from == m_to || (m_from == m_list.itemCount() - 1 && m_to > m_from))
+ return false;
+
+ addActivity(new RemoveActivity(m_from, false, false, m_list));
+ addActivity(new InsertActivity(m_to, m_list.getItem(m_from), false, m_list));
+
+ return false;
+}
+
+// ContentList
+
+ContentList::ContentList(QGraphicsItem *parent)
+ : QGraphicsItem(parent)
+ , m_boundingRect(0.0, 0.0, 0.0, 0.0)
+{
+ setFlag(QGraphicsItem::ItemHasNoContents, true);
+}
+
+ContentList::ContentList(QList<ContentListItem*> items, QGraphicsItem *parent)
+ : QGraphicsItem(parent)
+ , m_boundingRect(0.0, 0.0, 0.0, 0.0)
+{
+ setFlag(QGraphicsItem::ItemHasNoContents, true);
+ doAppendItems(items, false);
+}
+
+void ContentList::doAppendItems(QList<ContentListItem*> items, bool notify)
+{
+ qreal top = 0;
+ foreach(ContentListItem *item, m_items)
+ top += item->contentHeight();
+ foreach(ContentListItem *item, items) {
+ item->setParentItem(this);
+ item->setPos(0, top);
+ top += item->contentHeight();
+ m_items.append(item);
+ m_boundingRect.setHeight(m_boundingRect.height() + item->contentHeight());
+ if (notify)
+ emit newContentItem(item);
+ }
+}
+
+ContentList::~ContentList()
+{
+ foreach(ContentListActivity *activity, m_queue)
+ activity->deleteLater();
+}
+
+qreal ContentList::width() const
+{
+ return m_boundingRect.width();
+}
+
+void ContentList::setWidth(qreal width)
+{
+ if (m_boundingRect.width() != width) {
+ prepareGeometryChange();
+ m_boundingRect.setWidth(width);
+ update();
+ foreach(ContentListItem *item, m_items)
+ item->updateGeometry();
+ }
+}
+
+QRectF ContentList::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void ContentList::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+}
+
+bool ContentList::insertItem(int idx, ContentListItem* item)
+{
+ if (getItemIndex(item) != -1)
+ return false;
+ addActivity(new InsertActivity(idx, item, true, *this));
+ return true;
+}
+
+bool ContentList::removeItem(int idx)
+{
+ if (idx < 0 || idx >= m_items.count())
+ return false;
+ addActivity(new RemoveActivity(idx, true, true, *this));
+ return true;
+}
+
+bool ContentList::moveItem(int from, int to)
+{
+ if (from < 0 || from >= m_items.count())
+ return false;
+
+ to = to < 0 ? 0 : to > m_items.count() ? m_items.count() : to;
+
+ if (from == to)
+ return true;
+ addActivity(new MoveActivity(from, to, *this));
+ return true;
+}
+
+void ContentList::addActivity(ContentListActivity *activity)
+{
+ m_queue.append(activity);
+ checkQueue();
+}
+
+void ContentList::checkQueue()
+{
+ while (m_queue.count() > 0 && !m_queue[0]->active())
+ if (!m_queue[0]->run())
+ m_queue.takeFirst()->deleteLater();
+}
+
+void ContentList::activityEnd()
+{
+ m_queue.takeFirst()->deleteLater();
+ checkQueue();
+}
+
+void ContentList::doRemoveItem(int idx, bool notify)
+{
+ if (idx >= 0 && idx < m_items.count()) {
+ ContentListItem *item = m_items[idx];
+ item->setParentItem(0);
+ m_items.removeAt(idx);
+ if (notify) {
+ prepareGeometryChange();
+ m_boundingRect.setHeight(m_boundingRect.height() - item->contentHeight());
+ update();
+ emit contentItemRemoved(item);
+ }
+ }
+}
+
+void ContentList::doInsertItem(int idx, ContentListItem * item, bool notify)
+{
+ if (idx >= 0 && idx <= m_items.count()) {
+ qreal top = 0;
+ for (int i = 0; i < idx; ++i)
+ top += m_items[i]->contentHeight();
+ item->setPos(0, top);
+ item->setParentItem(this);
+ if (notify) {
+ prepareGeometryChange();
+ m_boundingRect.setHeight(m_boundingRect.height() + item->contentHeight());
+ update();
+ emit newContentItem(item);
+ }
+ m_items.insert(idx, item);
+ }
+}
+
+void ContentList::updateItems()
+{
+ qreal top = 0;
+ foreach(ContentListItem *item, m_items) {
+ item->setPos(0, top);
+ top += item->contentHeight();
+ }
+ update();
+}
+
+void ContentList::sortItems(ContentListItemCompare compare)
+{
+ addActivity(new SortActivity(*this, compare));
+}
+
+void ContentList::appendItems(QList<ContentListItem*> items)
+{
+ addActivity(new AppendItemsActivity(*this, items));
+}