summaryrefslogtreecommitdiffstats
path: root/shoplist
diff options
context:
space:
mode:
authorChenca <renato.chencarek@openbossa.org>2009-10-23 14:12:37 -0300
committerChenca <renato.chencarek@openbossa.org>2009-10-23 14:12:37 -0300
commitce6fd7f4f07ba0addc1a384043ca62ef7957aa43 (patch)
tree9e2aec3948ccbd4701402eb3505641da1040486c /shoplist
parentcabc1ff0197b818948199daab771cdfa75a53d3f (diff)
First version of ShopList added
Signed-off-by: Chenca <renato.chencarek@openbossa.org>
Diffstat (limited to 'shoplist')
-rw-r--r--shoplist/images/background.pngbin0 -> 88217 bytes
-rw-r--r--shoplist/images/background_landscape.pngbin0 -> 203276 bytes
-rw-r--r--shoplist/images/button_close.pngbin0 -> 448 bytes
-rw-r--r--shoplist/images/list_alldone_background.pngbin0 -> 89834 bytes
-rw-r--r--shoplist/images/list_alldone_bt_startagain_off.pngbin0 -> 8795 bytes
-rw-r--r--shoplist/images/list_alldone_bt_startagain_on.pngbin0 -> 8951 bytes
-rw-r--r--shoplist/images/list_background.pngbin0 -> 285222 bytes
-rw-r--r--shoplist/images/list_button_check.pngbin0 -> 369 bytes
-rw-r--r--shoplist/images/list_button_checked.pngbin0 -> 1372 bytes
-rw-r--r--shoplist/images/list_feather.pngbin0 -> 7603 bytes
-rw-r--r--shoplist/images/list_icon_beverages.pngbin0 -> 7257 bytes
-rw-r--r--shoplist/images/list_icon_cleaning.pngbin0 -> 6696 bytes
-rw-r--r--shoplist/images/list_icon_garden.pngbin0 -> 6499 bytes
-rw-r--r--shoplist/images/list_icon_groceries.pngbin0 -> 4027 bytes
-rw-r--r--shoplist/images/list_icon_pet.pngbin0 -> 9713 bytes
-rw-r--r--shoplist/images/list_icon_toiletries.pngbin0 -> 5099 bytes
-rw-r--r--shoplist/images/list_landscape_scrollbar.pngbin0 -> 4346 bytes
-rw-r--r--shoplist/images/list_line.pngbin0 -> 139 bytes
-rw-r--r--shoplist/images/list_portrait_scrollbar.pngbin0 -> 8405 bytes
-rw-r--r--shoplist/images/list_scrollbar_knob.pngbin0 -> 1189 bytes
-rw-r--r--shoplist/images/list_selecteditem_background.pngbin0 -> 394 bytes
-rw-r--r--shoplist/images/list_shadow_beverages_50.pngbin0 -> 4269 bytes
-rw-r--r--shoplist/images/list_shadow_cleaning_50.pngbin0 -> 4769 bytes
-rw-r--r--shoplist/images/list_shadow_garden_50.pngbin0 -> 4728 bytes
-rw-r--r--shoplist/images/list_shadow_groceries_50.pngbin0 -> 4233 bytes
-rw-r--r--shoplist/images/list_shadow_pet_50.pngbin0 -> 4708 bytes
-rw-r--r--shoplist/images/list_shadow_toiletries_50.pngbin0 -> 4679 bytes
-rw-r--r--shoplist/images/list_title_beverages.pngbin0 -> 28760 bytes
-rw-r--r--shoplist/images/list_title_cleaning.pngbin0 -> 25977 bytes
-rw-r--r--shoplist/images/list_title_garden.pngbin0 -> 23352 bytes
-rw-r--r--shoplist/images/list_title_groceries.pngbin0 -> 26872 bytes
-rw-r--r--shoplist/images/list_title_pet.pngbin0 -> 15431 bytes
-rw-r--r--shoplist/images/list_title_toiletries.pngbin0 -> 28496 bytes
-rw-r--r--shoplist/resources.qrc37
-rw-r--r--shoplist/shoplist.pro21
-rw-r--r--shoplist/src/contentlist.cpp408
-rw-r--r--shoplist/src/contentlist.h235
-rw-r--r--shoplist/src/designinformation.cpp361
-rw-r--r--shoplist/src/designinformation.h55
-rw-r--r--shoplist/src/gesturebox.cpp359
-rw-r--r--shoplist/src/gesturebox.h33
-rw-r--r--shoplist/src/gesturebox_p.h89
-rw-r--r--shoplist/src/listshadow.cpp58
-rw-r--r--shoplist/src/listshadow.h34
-rw-r--r--shoplist/src/main.cpp54
-rw-r--r--shoplist/src/maincontainer.cpp261
-rw-r--r--shoplist/src/maincontainer.h91
-rw-r--r--shoplist/src/popup.cpp73
-rw-r--r--shoplist/src/popup.h39
-rw-r--r--shoplist/src/scrollbar.cpp162
-rw-r--r--shoplist/src/scrollbar.h59
-rw-r--r--shoplist/src/shoppinglist.cpp265
-rw-r--r--shoplist/src/shoppinglist.h89
-rw-r--r--shoplist/src/shoppinglistcategoryui.cpp266
-rw-r--r--shoplist/src/shoppinglistcategoryui.h81
-rw-r--r--shoplist/src/shoppinglistview.cpp79
-rw-r--r--shoplist/src/shoppinglistview.h26
-rw-r--r--shoplist/src/src.pri22
58 files changed, 3257 insertions, 0 deletions
diff --git a/shoplist/images/background.png b/shoplist/images/background.png
new file mode 100644
index 0000000..b1496b7
--- /dev/null
+++ b/shoplist/images/background.png
Binary files differ
diff --git a/shoplist/images/background_landscape.png b/shoplist/images/background_landscape.png
new file mode 100644
index 0000000..4300059
--- /dev/null
+++ b/shoplist/images/background_landscape.png
Binary files differ
diff --git a/shoplist/images/button_close.png b/shoplist/images/button_close.png
new file mode 100644
index 0000000..8bb6b9a
--- /dev/null
+++ b/shoplist/images/button_close.png
Binary files differ
diff --git a/shoplist/images/list_alldone_background.png b/shoplist/images/list_alldone_background.png
new file mode 100644
index 0000000..62b581f
--- /dev/null
+++ b/shoplist/images/list_alldone_background.png
Binary files differ
diff --git a/shoplist/images/list_alldone_bt_startagain_off.png b/shoplist/images/list_alldone_bt_startagain_off.png
new file mode 100644
index 0000000..3b59375
--- /dev/null
+++ b/shoplist/images/list_alldone_bt_startagain_off.png
Binary files differ
diff --git a/shoplist/images/list_alldone_bt_startagain_on.png b/shoplist/images/list_alldone_bt_startagain_on.png
new file mode 100644
index 0000000..fe67abf
--- /dev/null
+++ b/shoplist/images/list_alldone_bt_startagain_on.png
Binary files differ
diff --git a/shoplist/images/list_background.png b/shoplist/images/list_background.png
new file mode 100644
index 0000000..534a626
--- /dev/null
+++ b/shoplist/images/list_background.png
Binary files differ
diff --git a/shoplist/images/list_button_check.png b/shoplist/images/list_button_check.png
new file mode 100644
index 0000000..295485d
--- /dev/null
+++ b/shoplist/images/list_button_check.png
Binary files differ
diff --git a/shoplist/images/list_button_checked.png b/shoplist/images/list_button_checked.png
new file mode 100644
index 0000000..0b2b6a7
--- /dev/null
+++ b/shoplist/images/list_button_checked.png
Binary files differ
diff --git a/shoplist/images/list_feather.png b/shoplist/images/list_feather.png
new file mode 100644
index 0000000..f248385
--- /dev/null
+++ b/shoplist/images/list_feather.png
Binary files differ
diff --git a/shoplist/images/list_icon_beverages.png b/shoplist/images/list_icon_beverages.png
new file mode 100644
index 0000000..721fe20
--- /dev/null
+++ b/shoplist/images/list_icon_beverages.png
Binary files differ
diff --git a/shoplist/images/list_icon_cleaning.png b/shoplist/images/list_icon_cleaning.png
new file mode 100644
index 0000000..4497ad2
--- /dev/null
+++ b/shoplist/images/list_icon_cleaning.png
Binary files differ
diff --git a/shoplist/images/list_icon_garden.png b/shoplist/images/list_icon_garden.png
new file mode 100644
index 0000000..6c3215c
--- /dev/null
+++ b/shoplist/images/list_icon_garden.png
Binary files differ
diff --git a/shoplist/images/list_icon_groceries.png b/shoplist/images/list_icon_groceries.png
new file mode 100644
index 0000000..361da1f
--- /dev/null
+++ b/shoplist/images/list_icon_groceries.png
Binary files differ
diff --git a/shoplist/images/list_icon_pet.png b/shoplist/images/list_icon_pet.png
new file mode 100644
index 0000000..5b16ab1
--- /dev/null
+++ b/shoplist/images/list_icon_pet.png
Binary files differ
diff --git a/shoplist/images/list_icon_toiletries.png b/shoplist/images/list_icon_toiletries.png
new file mode 100644
index 0000000..48cecd3
--- /dev/null
+++ b/shoplist/images/list_icon_toiletries.png
Binary files differ
diff --git a/shoplist/images/list_landscape_scrollbar.png b/shoplist/images/list_landscape_scrollbar.png
new file mode 100644
index 0000000..b5c8947
--- /dev/null
+++ b/shoplist/images/list_landscape_scrollbar.png
Binary files differ
diff --git a/shoplist/images/list_line.png b/shoplist/images/list_line.png
new file mode 100644
index 0000000..81cdf11
--- /dev/null
+++ b/shoplist/images/list_line.png
Binary files differ
diff --git a/shoplist/images/list_portrait_scrollbar.png b/shoplist/images/list_portrait_scrollbar.png
new file mode 100644
index 0000000..2bd647b
--- /dev/null
+++ b/shoplist/images/list_portrait_scrollbar.png
Binary files differ
diff --git a/shoplist/images/list_scrollbar_knob.png b/shoplist/images/list_scrollbar_knob.png
new file mode 100644
index 0000000..79b7d87
--- /dev/null
+++ b/shoplist/images/list_scrollbar_knob.png
Binary files differ
diff --git a/shoplist/images/list_selecteditem_background.png b/shoplist/images/list_selecteditem_background.png
new file mode 100644
index 0000000..e075a02
--- /dev/null
+++ b/shoplist/images/list_selecteditem_background.png
Binary files differ
diff --git a/shoplist/images/list_shadow_beverages_50.png b/shoplist/images/list_shadow_beverages_50.png
new file mode 100644
index 0000000..311a62e
--- /dev/null
+++ b/shoplist/images/list_shadow_beverages_50.png
Binary files differ
diff --git a/shoplist/images/list_shadow_cleaning_50.png b/shoplist/images/list_shadow_cleaning_50.png
new file mode 100644
index 0000000..45e1368
--- /dev/null
+++ b/shoplist/images/list_shadow_cleaning_50.png
Binary files differ
diff --git a/shoplist/images/list_shadow_garden_50.png b/shoplist/images/list_shadow_garden_50.png
new file mode 100644
index 0000000..960b37a
--- /dev/null
+++ b/shoplist/images/list_shadow_garden_50.png
Binary files differ
diff --git a/shoplist/images/list_shadow_groceries_50.png b/shoplist/images/list_shadow_groceries_50.png
new file mode 100644
index 0000000..82e02de
--- /dev/null
+++ b/shoplist/images/list_shadow_groceries_50.png
Binary files differ
diff --git a/shoplist/images/list_shadow_pet_50.png b/shoplist/images/list_shadow_pet_50.png
new file mode 100644
index 0000000..a4a237e
--- /dev/null
+++ b/shoplist/images/list_shadow_pet_50.png
Binary files differ
diff --git a/shoplist/images/list_shadow_toiletries_50.png b/shoplist/images/list_shadow_toiletries_50.png
new file mode 100644
index 0000000..74e872f
--- /dev/null
+++ b/shoplist/images/list_shadow_toiletries_50.png
Binary files differ
diff --git a/shoplist/images/list_title_beverages.png b/shoplist/images/list_title_beverages.png
new file mode 100644
index 0000000..6d69a90
--- /dev/null
+++ b/shoplist/images/list_title_beverages.png
Binary files differ
diff --git a/shoplist/images/list_title_cleaning.png b/shoplist/images/list_title_cleaning.png
new file mode 100644
index 0000000..eeeb27a
--- /dev/null
+++ b/shoplist/images/list_title_cleaning.png
Binary files differ
diff --git a/shoplist/images/list_title_garden.png b/shoplist/images/list_title_garden.png
new file mode 100644
index 0000000..c844dcb
--- /dev/null
+++ b/shoplist/images/list_title_garden.png
Binary files differ
diff --git a/shoplist/images/list_title_groceries.png b/shoplist/images/list_title_groceries.png
new file mode 100644
index 0000000..4ecb14a
--- /dev/null
+++ b/shoplist/images/list_title_groceries.png
Binary files differ
diff --git a/shoplist/images/list_title_pet.png b/shoplist/images/list_title_pet.png
new file mode 100644
index 0000000..45912b3
--- /dev/null
+++ b/shoplist/images/list_title_pet.png
Binary files differ
diff --git a/shoplist/images/list_title_toiletries.png b/shoplist/images/list_title_toiletries.png
new file mode 100644
index 0000000..8e1a1b3
--- /dev/null
+++ b/shoplist/images/list_title_toiletries.png
Binary files differ
diff --git a/shoplist/resources.qrc b/shoplist/resources.qrc
new file mode 100644
index 0000000..f5ce512
--- /dev/null
+++ b/shoplist/resources.qrc
@@ -0,0 +1,37 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/background.png</file>
+ <file>images/button_close.png</file>
+ <file>images/list_alldone_background.png</file>
+ <file>images/list_alldone_bt_startagain_off.png</file>
+ <file>images/list_alldone_bt_startagain_on.png</file>
+ <file>images/list_background.png</file>
+ <file>images/list_button_checked.png</file>
+ <file>images/list_button_check.png</file>
+ <file>images/list_feather.png</file>
+ <file>images/list_icon_beverages.png</file>
+ <file>images/list_icon_cleaning.png</file>
+ <file>images/list_icon_garden.png</file>
+ <file>images/list_icon_groceries.png</file>
+ <file>images/list_icon_pet.png</file>
+ <file>images/list_icon_toiletries.png</file>
+ <file>images/list_landscape_scrollbar.png</file>
+ <file>images/list_line.png</file>
+ <file>images/list_portrait_scrollbar.png</file>
+ <file>images/list_scrollbar_knob.png</file>
+ <file>images/list_selecteditem_background.png</file>
+ <file>images/list_title_beverages.png</file>
+ <file>images/list_title_cleaning.png</file>
+ <file>images/list_title_garden.png</file>
+ <file>images/list_title_groceries.png</file>
+ <file>images/list_title_pet.png</file>
+ <file>images/list_title_toiletries.png</file>
+ <file>images/list_shadow_beverages_50.png</file>
+ <file>images/list_shadow_cleaning_50.png</file>
+ <file>images/list_shadow_garden_50.png</file>
+ <file>images/list_shadow_groceries_50.png</file>
+ <file>images/list_shadow_pet_50.png</file>
+ <file>images/list_shadow_toiletries_50.png</file>
+ <file>images/background_landscape.png</file>
+ </qresource>
+</RCC>
diff --git a/shoplist/shoplist.pro b/shoplist/shoplist.pro
new file mode 100644
index 0000000..4df7a52
--- /dev/null
+++ b/shoplist/shoplist.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+TARGET =
+
+include(src/src.pri)
+
+target.path = $$PREFIX/bin
+INSTALLS += target
+
+RESOURCES += resources.qrc
+QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.5
+
+symbian {
+ HEADERS += src/sym_iap_util.h
+ LIBS += -lesock -lconnmon -lcone -lavkon
+ TARGET.CAPABILITY = NetworkServices
+ addFiles.sources = symbian.ini
+ addFiles.path = e:\resources\apps
+ DEPLOYMENT += addFiles
+ ICON = images/icon.svg
+ TARGET.UID3 = 0xe1234567
+}
diff --git a/shoplist/src/contentlist.cpp b/shoplist/src/contentlist.cpp
new file mode 100644
index 0000000..ba2d405
--- /dev/null
+++ b/shoplist/src/contentlist.cpp
@@ -0,0 +1,408 @@
+#include "contentlist.h"
+#include <QPointer>
+
+// ContentListItem
+
+ContentListItem::ContentListItem(QGraphicsItem *parent)
+ : QGraphicsItem(parent)
+ , m_geometry(QRectF(0.0, 0.0, 0.0, 0.0))
+{
+ setFlag(QGraphicsItem::ItemHasNoContents, true);
+ setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+ updateGeometry();
+}
+
+QRectF ContentListItem::boundingRect() const
+{
+ return m_geometry;
+}
+
+void ContentListItem::updateGeometry()
+{
+ if (!parentItem())
+ return;
+ QRectF geometry(0.0, 0.0, parentItem()->boundingRect().width() - pos().x(), 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));
+}
diff --git a/shoplist/src/contentlist.h b/shoplist/src/contentlist.h
new file mode 100644
index 0000000..122fa3d
--- /dev/null
+++ b/shoplist/src/contentlist.h
@@ -0,0 +1,235 @@
+#ifndef CONTENTLIST_H
+#define CONTENTLIST_H
+
+#include <QList>
+#include <QObject>
+#include <QGraphicsObject>
+#include <QAbstractAnimation>
+#include <QPointer>
+
+#define ITEM_TOP_PROPERTY_NAME "top"
+
+class ContentListItem : public QObject, public QGraphicsItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal top READ getTop WRITE setTop);
+#ifndef Q_OS_MAC
+ Q_INTERFACES(QGraphicsItem);
+#endif
+public:
+ ContentListItem(QGraphicsItem *parent = 0);
+ virtual qreal contentHeight() const = 0;
+ QRectF boundingRect() const;
+
+ virtual QAbstractAnimation *getShowAnimation() = 0;
+ virtual QAbstractAnimation *getHideAnimation() = 0;
+
+protected:
+ void updateGeometry();
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+private:
+ friend class ContentList;
+ QRectF m_geometry;
+ qreal getTop() { return pos().y(); }
+ void setTop(qreal top) { setPos(pos().x(), top); }
+
+};
+
+class ContentListActivity;
+class RemoveActivity;
+class InsertActivity;
+
+class ContentList
+ : public QObject
+ , public QGraphicsItem
+{
+ Q_OBJECT
+#ifndef Q_OS_MAC
+ Q_INTERFACES(QGraphicsItem);
+#endif
+public:
+ ContentList(QGraphicsItem *parent = 0);
+ ContentList(QList<ContentListItem*> items, QGraphicsItem *parent = 0);
+ ~ContentList();
+
+ bool insertItem(int idx, ContentListItem*);
+ bool addItem(ContentListItem *item) { return insertItem(m_items.count(), item); }
+ bool removeItem(int idx);
+ bool removeItem(ContentListItem* item) { return removeItem(getItemIndex(item)); }
+ bool moveItem(int from, int to);
+ bool moveItem(ContentListItem* item, int to) { return moveItem(getItemIndex(item), to); }
+ void appendItems(QList<ContentListItem*> items);
+
+ int itemCount() const { return m_items.count(); }
+ ContentListItem* getItem(int idx) { return m_items.at(idx); }
+ int getItemIndex(ContentListItem* item) { return m_items.indexOf(item); }
+
+ bool busy() { return m_queue.count() > 0; }
+ void addActivity(ContentListActivity *);
+
+ void updateItems();
+
+ QRectF boundingRect() const;
+ qreal width() const;
+ void setWidth(qreal width);
+
+signals:
+ void newContentItem(QGraphicsItem *item);
+ void contentItemRemoved(QGraphicsItem *item);
+
+protected:
+ virtual QAbstractAnimation *getInsertAnimation(int idx, qreal height) = 0;
+ virtual QAbstractAnimation *getRemoveAnimation(int idx) = 0;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ QList<ContentListItem*> getItems() { return m_items; }
+
+ typedef bool (*ContentListItemCompare)(const ContentListItem* s1, const ContentListItem* s2);
+ void sortItems(ContentListItemCompare compare);
+
+private:
+ friend class ContentListActivity;
+ friend class RemoveActivity;
+ friend class InsertActivity;
+ friend class SortActivity;
+ friend class AppendItemsActivity;
+ QList<ContentListItem*> m_items;
+ QList<ContentListActivity*> m_queue;
+
+ QRectF m_boundingRect;
+
+ void updateGeometry();
+
+ void checkQueue();
+ void activityEnd();
+ void doRemoveItem(int idx, bool notify);
+ void doInsertItem(int idx, ContentListItem* item, bool notify);
+ void doAppendItems(QList<ContentListItem*> items, bool notify);
+
+};
+
+class ContentListActivity : public QObject
+{
+ Q_OBJECT
+public:
+ ContentListActivity(ContentList &list) : m_list(list), m_insertPos(0) {}
+ virtual bool run() = 0;
+ virtual bool active();
+
+protected:
+ ContentList &m_list;
+ void addActivity(ContentListActivity*);
+
+protected slots:
+ void activityEnd() { m_list.activityEnd(); }
+
+private:
+ int m_insertPos;
+
+};
+
+class SignalActivity : public ContentListActivity
+{
+ Q_OBJECT
+public:
+ SignalActivity(ContentList &list) : ContentListActivity(list) {}
+ bool run();
+
+signals:
+ void notify();
+};
+
+class SortActivity : public ContentListActivity
+{
+ Q_OBJECT
+public:
+ SortActivity(ContentList &list, ContentList::ContentListItemCompare compare)
+ : ContentListActivity(list), m_compare(compare) {}
+ bool run();
+
+private:
+ ContentList::ContentListItemCompare m_compare;
+};
+
+class AppendItemsActivity : public ContentListActivity
+{
+ Q_OBJECT
+public:
+ AppendItemsActivity(ContentList &list, QList<ContentListItem*> items)
+ : ContentListActivity(list), m_items(items) {}
+ bool run();
+
+private:
+ QList<ContentListItem*> m_items;
+};
+
+class AnimationActivity : public ContentListActivity
+{
+ Q_OBJECT
+public:
+ AnimationActivity(QAbstractAnimation *animation, ContentList &list);
+ ~AnimationActivity();
+ bool run();
+ bool active() { return m_animation && m_animation->state() != QAbstractAnimation::Stopped; }
+
+private slots:
+ void animationEnd();
+
+private:
+ QAbstractAnimation *m_animation;
+
+};
+
+class RemoveActivity : public ContentListActivity
+{
+ Q_OBJECT
+public:
+ RemoveActivity(int idx, bool destroyItem, bool notify, ContentList &list);
+ bool run();
+ bool active() { return m_active; }
+
+private slots:
+ void hideEnd();
+
+private:
+ int m_idx;
+ bool m_destroyItem;
+ ContentListItem *m_item;
+ bool m_active;
+ const bool m_notify;
+
+};
+
+class InsertActivity : public ContentListActivity
+{
+ Q_OBJECT
+public:
+ InsertActivity(int idx, ContentListItem* item, bool notify, ContentList &list);
+ bool run();
+ bool active() { return m_active; }
+
+private slots:
+ void showItem();
+
+private:
+ int m_idx;
+ QPointer<ContentListItem> m_item;
+ bool m_active;
+ const bool m_notify;
+
+};
+
+class MoveActivity : public ContentListActivity
+{
+public:
+ MoveActivity(int from, int to, ContentList &list);
+ bool run();
+
+private:
+ int m_from;
+ int m_to;
+
+};
+
+#endif // CONTENTLIST_H
diff --git a/shoplist/src/designinformation.cpp b/shoplist/src/designinformation.cpp
new file mode 100644
index 0000000..b803835
--- /dev/null
+++ b/shoplist/src/designinformation.cpp
@@ -0,0 +1,361 @@
+#include "designinformation.h"
+#include <QDebug>
+#include <cmath>
+
+static const char *groceriesItemsText[] = {
+ "Apples","Avocado","Bacon","Bagels","Baking powder","Balsamic vinegar","Bananas",
+ "Basil","Basmati rice","Beans","Beef","Bell peppers","Biscuits","Blackberries","Blueberries",
+ "Brats","Bread (not white)","Broccoli","Brownie mix","Brussels sprouts","Burger patties",
+ "Butter","Cabbage","Cake mix","Canned tomatoes","Cantaloupe","Carrots","Cauliflower","Cereal",
+ "Cheddar","Cheese sticks","Cherries","Chicken","Chips","Chocolate chips","Cookie dough",
+ "Cookie mix","Cookies","Corn","Cottage cheese","Couscous","Crackers","Cream cheese",
+ "Cucumbers","Eggs","English muffins","Fish","Flour","Fruit snacks","Garlic","Ginger",
+ "Graham crackers","Granola bars","Grapefruit","Grapes","Green beans","Ground beef",
+ "Ground turkey","Ham","Hamburger buns","Honey","Hot cereal","Hot dogs","Hot-dog buns",
+ "Jello","Kiwi","Lasagna noodles","Lemons","Lettuce","Limes","Mac & Cheese","Marshmallow",
+ "Melon","Mozzarella","Muffin mix","Mushrooms","Mustard","Nectarines","Noodle & Sauce Mix",
+ "Oatmeal","Olive Oil","Onions","Oranges","Pancake mix","Pancake syrup","Parmesan",
+ "Pasta (whole wheat)","Peaches","Peanut butter","Pears","Peas","Peppers","Pizza sauce",
+ "Plums","Popcorn","Pork chops","Pork roast","Potatoes","Pudding","Quinoa","Raisins",
+ "Raspberries","Raw nuts","Rice","RiceARoni","Risotto","Sausage","Shredded cheese",
+ "Sliced cheese","Snap peas","Soup","Sour cream","Spaghetti sauce","Spaghetti",
+ "Squash","Steaks","Strawberries","String beans","Sugar","Tomato sauce","Tomatoes",
+ "Tortillas","Tuna","Veal","White bread","White vinegar","Whole wheat bread","Yogurt","Zucchini",
+ 0
+};
+
+static const char *toiletriesItemsText[] = {
+ "Antiseptic cream","Baby lotion","Band aids","Bath soap","Body wash ","Conditioner",
+ "Contact solution","Deodorant","Facial soap","Facial tissue","Floss","Hair dye",
+ "Hand lotion","Leave-in conditioner","Moisturizer","Mouthwash","Pads","Rash creams",
+ "Razors","Shampoo","Shaving cream","Soap","Suntan lotion","Tampons","Toilet paper",
+ "Toothpaste","Vitamins","Wipes","Scented toilet paper",
+ 0
+};
+
+static const char *cleaningItemsText[] = {
+ "Aluminum foil","Bleach","Cleanser","Dishwasher soap","Disinfectant","Dixie cups",
+ "Dusting spray","Fabric softener","Kleenex","Laundry detergent","Napkins","Paper towels",
+ "Plastic wrap","Toilet paper","Trash bags","Ziplock bags","Wax paper","Floor wax",
+ 0
+};
+
+static const char *beveragesItemsText[] = {
+ "Apple juice","Beer","Black tea","Bottled water","Champagne","Cordial","Green tea","Ice tea",
+ "Juice boxes","KoolAid","Lemonade","Milk","Orange juice","Coca-Cola","Powerade",
+ "Raspberry juice","Red wine","Skinned milk","Sparkling water","Tea","Vodka","White wine",
+ "Coke Zero",
+ 0
+};
+
+static const char *petItemsText[] = {
+ "Bird food","Bone","Cat food","Cat Litter","Catnip","Dog biscuit","Dog food","Dog toys",
+ "Dog treats","Fish food","Fish tanks pebbles","Hamster food","Hamster hammock","Pet wash",
+ "Turtle soap",
+ 0
+};
+
+static const char *gardenItemsText[] = {
+ "Fertilizer","Flower seeds","Hose","Leaf bags","Manure","Scissors","Shovel","Vegetable seeds",
+ "Pesticide","Mouse trap",
+ 0
+};
+
+DesignInformation::DesignInformation()
+ : m_scaleFactor(1, 1)
+{
+
+ m_stringLists["category.string_list.beverages"] = beveragesItemsText;
+ m_stringLists["category.string_list.cleaning"] = cleaningItemsText;
+ m_stringLists["category.string_list.garden"] = gardenItemsText;
+ m_stringLists["category.string_list.groceries"] = groceriesItemsText;
+ m_stringLists["category.string_list.pet"] = petItemsText;
+ m_stringLists["category.string_list.toiletries"] = toiletriesItemsText;
+
+ m_pixmaps["category.pic.beverages"] = new ValueData<QPixmap, QString>(":/images/list_icon_beverages.png");
+ m_pixmaps["category.shadow.beverages"] = new ValueData<QPixmap, QString>(":/images/list_shadow_beverages_50.png");
+ m_pixmaps["category.header.beverages"] = new ValueData<QPixmap, QString>(":/images/list_title_beverages.png");
+
+ m_pixmaps["category.pic.cleaning"] = new ValueData<QPixmap, QString>(":/images/list_icon_cleaning.png");
+ m_pixmaps["category.shadow.cleaning"] = new ValueData<QPixmap, QString>(":/images/list_shadow_cleaning_50.png");
+ m_pixmaps["category.header.cleaning"] = new ValueData<QPixmap, QString>(":/images/list_title_cleaning.png");
+
+ m_pixmaps["category.pic.garden"] = new ValueData<QPixmap, QString>(":/images/list_icon_garden.png");
+ m_pixmaps["category.shadow.garden"] = new ValueData<QPixmap, QString>(":/images/list_shadow_garden_50.png");
+ m_pixmaps["category.header.garden"] = new ValueData<QPixmap, QString>(":/images/list_title_garden.png");
+
+ m_pixmaps["category.pic.groceries"] = new ValueData<QPixmap, QString>(":/images/list_icon_groceries.png");
+ m_pixmaps["category.shadow.groceries"] = new ValueData<QPixmap, QString>(":/images/list_shadow_groceries_50.png");
+ m_pixmaps["category.header.groceries"] = new ValueData<QPixmap, QString>(":/images/list_title_groceries.png");
+
+ m_pixmaps["category.pic.pet"] = new ValueData<QPixmap, QString>(":/images/list_icon_pet.png");
+ m_pixmaps["category.shadow.pet"] = new ValueData<QPixmap, QString>(":/images/list_shadow_pet_50.png");
+ m_pixmaps["category.header.pet"] = new ValueData<QPixmap, QString>(":/images/list_title_pet.png");
+
+ m_pixmaps["category.pic.toiletries"] = new ValueData<QPixmap, QString>(":/images/list_icon_toiletries.png");
+ m_pixmaps["category.shadow.toiletries"] = new ValueData<QPixmap, QString>(":/images/list_shadow_toiletries_50.png");
+ m_pixmaps["category.header.toiletries"] = new ValueData<QPixmap, QString>(":/images/list_title_toiletries.png");
+
+ m_pixmaps["category.background"] = new ValueData<QPixmap, QString>(":/images/list_background.png");
+ m_pixmaps["category.feather"] = new ValueData<QPixmap, QString>(":/images/list_feather.png");
+
+ m_positions["category.pic"] = new ValueData<QPointF>(QPointF(3, 0));
+ m_positions["category.header"] = new ValueData<QPointF>(QPointF(110, 54));
+ m_positions["category.background"] = new ValueData<QPointF>(QPointF(0, 39));
+ m_positions["category.shadow"] = new ValueData<QPointF>(QPointF(3, -1));
+ m_positions["category.list"] = new ValueData<QPointF>(QPointF(2, m_listTop));
+ m_positions["category.feather"] = new ValueData<QPointF>(QPointF(3, m_listTop));
+ m_positions["category.scrollbar"] = new ValueData<QPointF>(QPointF(415, 154));
+
+ m_verticalSizes["category.list_height"] = new ValueData<qreal>(800.0);
+
+ // ---------------------------------------------------------------------
+
+ m_pixmaps["list_item.checked"] = new ValueData<QPixmap, QString>(":/images/list_button_checked.png");
+ m_positions["list_item.checked"] = new ValueData<QPointF>(QPointF(27, 28));
+
+ m_pixmaps["list_item.not_checked"] = new ValueData<QPixmap, QString>(":/images/list_button_check.png");
+ m_positions["list_item.not_checked"] = new ValueData<QPointF>(QPointF(27, 28));
+
+ m_pixmaps["list_item.bottom_line"] = new ValueData<QPixmap, QString>(":/images/list_line.png");
+ m_positions["list_item.bottom_line"] = new ValueData<QPointF>(QPointF(1, 88));
+
+ m_pixmaps["list_item.selected"] = new ValueData<QPixmap, QString>(":/images/list_selecteditem_background.png");
+ m_positions["list_item.selected"] = new ValueData<QPointF>(QPointF(1, 0));
+
+ m_horizontalSizes["list_item.text_offset"] = new ValueData<qreal>(20.0);
+
+ m_verticalSizes["list_item.height"] = new ValueData<qreal>(m_referenceItemHeight);
+
+ m_fontSizes["list_item.font_size"] = new ValueData<int>(30);
+
+ m_verticalSizes["list.vertical_speed"] = new ValueData<qreal>(1500.0);
+
+
+ // ---------------------------------------------------------------------
+
+ m_pixmaps["background"] = new ValueData<QPixmap, QString>(":/images/background.png");
+
+ m_fontSizes["title"] = new ValueData<int>(18);
+ m_positions["title"] = new ValueData<QPointF>(QPointF(184, 7));
+
+ m_pixmaps["closeButton"] = new ValueData<QPixmap, QString>(":/images/button_close.png");
+ m_positions["closeButton"] = new ValueData<QPointF>(QPointF(426, 8));
+ m_horizontalSizes["close_button_spacing"] = new ValueData<qreal>(28.0);
+
+ m_horizontalSizes["listset.center_position"] = new ValueData<qreal>(17.0);
+
+ m_pixmaps["list.scrollbar.landscape"] = new ValueData<QPixmap, QString>(":/images/list_landscape_scrollbar.png");
+ m_pixmaps["list.scrollbar.portrait"] = new ValueData<QPixmap, QString>(":/images/list_portrait_scrollbar.png");
+ m_pixmaps["list.scrollbar.knob"] = new ValueData<QPixmap, QString>(":/images/list_scrollbar_knob.png");
+
+ // ---------------------------------------------------------------------
+
+ m_pixmaps["alldone.background"] = new ValueData<QPixmap, QString>(":/images/list_alldone_background.png");
+
+ m_pixmaps["alldone.startagain_off"] = new ValueData<QPixmap, QString>(":/images/list_alldone_bt_startagain_off.png");
+ m_positions["alldone.startagain_off"] = new ValueData<QPointF>(QPointF(-4, 54));
+
+ m_pixmaps["alldone.close_button"] = new ValueData<QPixmap, QString>(":/images/button_close.png");
+ m_positions["alldone.close_button"] = new ValueData<QPointF>(QPointF(100, -95));
+}
+
+DesignInformation::~DesignInformation()
+{
+ qDeleteAll(m_pixmaps.values());
+ qDeleteAll(m_positions.values());
+ qDeleteAll(m_verticalSizes.values());
+ qDeleteAll(m_horizontalSizes.values());
+ qDeleteAll(m_fontSizes.values());
+}
+
+template<class T, class R>
+void DesignInformation::resetValues(QMap<QString, ValueData<T,R>* > map)
+{
+ QList<ValueData<T,R>*> values = map.values();
+ for (int i = 0; i < values.count(); ++i) {
+ values[i]->m_upToDate = false;
+ values[i]->m_value = T();
+ }
+
+}
+
+void DesignInformation::setScaleFactor(QSizeF factor)
+{
+ DesignInformation *obj = DesignInformation::instance();
+ resetValues(obj->m_pixmaps);
+ resetValues(obj->m_positions);
+ resetValues(obj->m_verticalSizes);
+ resetValues(obj->m_horizontalSizes);
+ resetValues(obj->m_fontSizes);
+ obj->m_scaleFactor = QSizeF(factor.width(), 1.0);
+
+ DesignInformation::getPixmap("list_item.bottom_line");
+ obj->m_scaleFactor = factor;
+}
+
+qreal DesignInformation::calculateScaleFactor(QSizeF screenSize)
+{
+ qreal result = 1.0;
+ if (screenSize.width() < m_referenceWidth) {
+ result = m_referenceWidth / screenSize.width();
+ screenSize.setWidth(result * screenSize.width());
+ screenSize.setHeight(result * screenSize.height());
+ }
+
+ qreal referenceHeight = m_listTop + m_minimumVisibleItems * m_referenceItemHeight;
+
+ if (screenSize.height() < referenceHeight) {
+ result *= referenceHeight / screenSize.height();
+ screenSize.setWidth(result * screenSize.width());
+ screenSize.setHeight(result * screenSize.height());
+ }
+ return qMin(qreal(1.0) / result, qreal(1.0));
+}
+
+QSizeF DesignInformation::getScaleFactor(QSizeF screenSize)
+{
+ qreal scale1 = calculateScaleFactor(screenSize);
+ qreal scale2 = calculateScaleFactor(QSizeF(screenSize.height(), screenSize.width()));
+
+ qreal factor = qMin(scale1, scale2);
+ return QSizeF(factor, factor);
+}
+
+static QPixmap pixmapScale(QString reference, QSizeF scale)
+{
+ QPixmap ref(reference);
+ return ref.scaled(scale.width() * ref.width(), scale.height() * ref.height(),
+ Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+}
+
+void DesignInformation::setScreenSize(QSizeF size)
+{
+ DesignInformation *obj = DesignInformation::instance();
+ if (obj->m_pixmaps.contains("background")) {
+ ValueData<QPixmap, QString>* data = obj->m_pixmaps["background"];
+ QString file = size.width() > size.height() ? ":/images/background.png"
+ : ":/images/background_landscape.png";
+ QPixmap ref = QPixmap(file);
+ data->m_value = ref.scaled(size.width(), size.height(),
+ Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ data->m_upToDate = true;
+ }
+
+ QPixmap pixmap = getPixmap("category.background");
+
+ if (obj->m_horizontalSizes.contains("listset.center_position")) {
+ ValueData<qreal> *data = obj->m_horizontalSizes["listset.center_position"];
+ data->m_value = (size.width() - pixmap.width()) / 2;
+ data->m_upToDate = true;
+ }
+
+ if (obj->m_verticalSizes.contains("category.list_height")) {
+ ValueData<qreal> *data = obj->m_verticalSizes["category.list_height"];
+
+ QPointF backgroundPos = getPosition("category.background");
+ QPointF listPos = getPosition("category.list");
+
+ data->m_value = backgroundPos.y() + pixmap.height() - listPos.y();
+ data->m_value = qMin(size.height() - listPos.y(), data->m_value);
+ data->m_upToDate = true;
+ }
+
+ if (obj->m_pixmaps.contains("list.scrollbar.portrait")) {
+ ValueData<QPixmap, QString>* data = obj->m_pixmaps["list.scrollbar.portrait"];
+ QPixmap ref = QPixmap(":images/list_portrait_scrollbar.png");
+ QSizeF scale = obj->m_scaleFactor;
+ data->m_value = ref.scaled(scale.width() * ref.width(),
+ getVerticalSize("category.list_height") - 20,
+ Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ data->m_upToDate = true;
+ }
+
+
+}
+
+DesignInformation *DesignInformation::instance()
+{
+ static DesignInformation *obj(new DesignInformation());
+ return obj;
+}
+
+template<class T, class R, class F>
+T DesignInformation::getValue(QMap<QString, ValueData<T,R>* > map,
+ QString key, F factory, QSizeF scale)
+{
+ if (map.contains(key)) {
+ ValueData<T,R> *data = map.value(key);
+ if (data->m_upToDate)
+ return data->m_value;
+ data->m_value = factory(data->m_reference, scale);
+ data->m_upToDate = true;
+ return data->m_value;
+ }
+ qWarning() << "key" << key << "not found";
+ return T();
+}
+
+QPixmap DesignInformation::getPixmap(const QString &name)
+{
+ DesignInformation *obj = DesignInformation::instance();
+ return getValue(obj->m_pixmaps, name, pixmapScale, obj->m_scaleFactor);
+}
+
+static QPointF pointFScale(QPointF reference, QSizeF scale)
+{
+ return QPointF(reference.x() * scale.width(), reference.y() * scale.height());
+}
+
+QPointF DesignInformation::getPosition(const QString &name)
+{
+ DesignInformation *obj = DesignInformation::instance();
+ return getValue(obj->m_positions, name, pointFScale, obj->m_scaleFactor);
+}
+
+static qreal verticalScale(qreal reference, QSizeF scale)
+{
+ return reference * scale.height();
+}
+
+qreal DesignInformation::getVerticalSize(const QString &name)
+{
+ DesignInformation *obj = DesignInformation::instance();
+ return getValue(obj->m_verticalSizes, name, verticalScale, obj->m_scaleFactor);
+}
+
+static qreal horizontalScale(qreal reference, QSizeF scale)
+{
+ return reference * scale.width();
+}
+
+qreal DesignInformation::getHorizontalSize(const QString &name)
+{
+ DesignInformation *obj = DesignInformation::instance();
+ return getValue(obj->m_horizontalSizes, name, horizontalScale, obj->m_scaleFactor);
+}
+
+static int fontSizeScale(int reference, QSizeF scale)
+{
+ return reference * sqrt(scale.width() * scale.height());
+}
+
+int DesignInformation::getFontSize(const QString name)
+{
+ DesignInformation *obj = DesignInformation::instance();
+ return getValue(obj->m_fontSizes, name, fontSizeScale, obj->m_scaleFactor);
+
+}
+
+QStringList DesignInformation::getStringList(const QString &name)
+{
+ DesignInformation *obj = DesignInformation::instance();
+ if (obj && obj->m_stringLists.contains(name)) {
+ QStringList result;
+ for (const char **item = obj->m_stringLists.value(name); *item; ++item)
+ result << *item;
+ return result;
+ }
+ qWarning() << "position" << name << "not found";
+ return QStringList();
+}
diff --git a/shoplist/src/designinformation.h b/shoplist/src/designinformation.h
new file mode 100644
index 0000000..698f9a6
--- /dev/null
+++ b/shoplist/src/designinformation.h
@@ -0,0 +1,55 @@
+#ifndef DESIGNINFORMATION_H
+#define DESIGNINFORMATION_H
+
+#include <QString>
+#include <QMap>
+#include <QPixmap>
+
+class DesignInformation
+{
+public:
+ static QPixmap getPixmap(const QString &name);
+ static QPointF getPosition(const QString &name);
+ static qreal getVerticalSize(const QString &name);
+ static qreal getHorizontalSize(const QString &name);
+ static int getFontSize(const QString name);
+ static QStringList getStringList(const QString &name);
+ static void setScaleFactor(QSizeF factor);
+ static QSizeF getScaleFactor(QSizeF screenSize);
+ static void setScreenSize(QSizeF size);
+private:
+ template<class T, class R = T> class ValueData
+ {
+ public:
+ ValueData(R reference) : m_upToDate(false), m_reference(reference) {}
+ bool m_upToDate;
+ const R m_reference;
+ T m_value;
+ };
+private:
+ QSizeF m_scaleFactor;
+ QMap<QString, ValueData<QPixmap, QString>* > m_pixmaps;
+ QMap<QString, ValueData<QPointF>* > m_positions;
+ QMap<QString, ValueData<qreal>* > m_verticalSizes;
+ QMap<QString, ValueData<qreal>* > m_horizontalSizes;
+ QMap<QString, ValueData<int>* > m_fontSizes;
+
+ QMap<QString, const char**> m_stringLists;
+
+ static const int m_listTop = 142;
+ static const int m_referenceWidth = 480;
+ static const int m_minimumVisibleItems = 3;
+ static const int m_referenceItemHeight = 90;
+
+ DesignInformation();
+ ~DesignInformation();
+ static inline DesignInformation *instance();
+ static qreal calculateScaleFactor(QSizeF screenSize);
+
+ template<class T, class R, class F>
+ static T getValue(QMap<QString, ValueData<T,R>* > map, QString key, F factory, QSizeF scale);
+ template<class T, class R>
+ static void resetValues(QMap<QString, ValueData<T,R>* > map);
+};
+
+#endif // DESIGNINFORMATION_H
diff --git a/shoplist/src/gesturebox.cpp b/shoplist/src/gesturebox.cpp
new file mode 100644
index 0000000..9fefe0e
--- /dev/null
+++ b/shoplist/src/gesturebox.cpp
@@ -0,0 +1,359 @@
+#include "gesturebox.h"
+
+#include <QApplication>
+#include <QGraphicsView>
+#include <QMouseEvent>
+#include <QDebug>
+#include <QPointer>
+#include <QTime>
+
+#include "gesturebox_p.h"
+
+// GestureData
+
+#ifdef Q_OS_SYMBIAN
+static const int move_threshold = 20;
+#else
+static const int move_threshold = 5;
+#endif
+
+GestureData::GestureData(QPoint pos, const QList<GestureBox*> &boxes,
+ QGraphicsView *view, QList<QEvent*> &ignoreList, bool sendClickEvents)
+ : m_state(Pressed)
+ , m_view(view)
+ , m_pressPos(pos)
+ , m_scenePressPos(m_view->mapToScene(m_pressPos))
+ , m_boxes(boxes)
+ , m_ignoreList(ignoreList)
+ , m_time(QTime::currentTime())
+ , m_currentScenePos(m_scenePressPos)
+ , m_speed(0.0, 0.0)
+ , m_sendClickEvents(sendClickEvents)
+{
+}
+
+void GestureData::sendClick()
+{
+ if (m_sendClickEvents) {
+ QMouseEvent *press = new QMouseEvent(QEvent::MouseButtonPress,
+ m_pressPos, Qt::LeftButton,
+ Qt::LeftButton, Qt::NoModifier);
+ QMouseEvent *release = new QMouseEvent(QEvent::MouseButtonRelease,
+ m_pressPos, Qt::LeftButton,
+ Qt::LeftButton, Qt::NoModifier);
+ m_ignoreList << press;
+ m_ignoreList << release;
+ QApplication::postEvent(m_view->viewport(), press);
+ QApplication::postEvent(m_view->viewport(), release);
+ }
+}
+
+void GestureData::release(QPoint pos)
+{
+ Q_UNUSED(pos);
+ switch (m_state) {
+ case Pressed:
+ sendClick();
+ break;
+ case Moving:
+ foreach(GestureBox *box, m_boxes)
+ box->gestureEnd(box->mapFromScene(m_currentScenePos), m_speed);
+ break;
+ default:
+ break;
+ }
+ m_state = Ended;
+ deleteLater();
+}
+
+void GestureData::move(QPoint pos)
+{
+ if (m_state == Pressed &&
+ abs(pos.x() - m_pressPos.x()) < move_threshold &&
+ abs(pos.y() - m_pressPos.y()) < move_threshold) {
+ return;
+ }
+ QTime time(QTime::currentTime());
+ QPointF scenePos = m_view->mapToScene(pos);
+ QPointF move = scenePos - m_currentScenePos;
+ qreal secs = (qreal)(m_time.msecsTo(time)) / 1000;
+ m_currentScenePos = scenePos;
+ m_speed = QPointF(move.x() / secs, move.y() / secs);
+ m_time = time;
+
+ switch (m_state) {
+ case Pressed:
+ foreach(GestureBox *box, m_boxes) {
+ box->gestureStart(box->mapFromScene(m_scenePressPos));
+ box->gestureMove(box->mapFromScene(m_currentScenePos), move, m_speed);
+ }
+ m_state = Moving;
+ break;
+ case Moving:
+ foreach(GestureBox *box, m_boxes)
+ box->gestureMove(box->mapFromScene(m_currentScenePos), move, m_speed);
+ break;
+ default:
+ break;
+ }
+}
+
+// ViewData
+
+ViewData::~ViewData()
+{
+ if (m_gesture)
+ m_gesture->deleteLater();
+}
+
+bool ViewData::ignoreEvent(QEvent *event)
+{
+ return m_ignored.removeAll(event);
+}
+
+bool ViewData::startGesture(GestureBox *box, QPointF scenePos, bool &sendClick)
+{
+ bool result = true;
+ bool click = true;
+ box->gestureMousePress(box->mapFromScene(scenePos), result, click);
+ if (result && !click)
+ sendClick = false;
+ return result;
+}
+
+bool ViewData::press(QPoint pos)
+{
+ if (m_gesture && !m_gesture->ended()) {
+ qWarning() << "ERROR: unexpected mouse press during gesture.";
+ return false;
+ }
+
+ if (!m_view || !m_view->scene())
+ return false;
+
+ QList<GestureBox*> boxes;
+ bool sendClick = true;
+ QPointF scenePos = m_view->mapToScene(pos);
+
+ QList<QGraphicsItem*> itemList = m_view->scene()->items(scenePos,
+ Qt::IntersectsItemBoundingRect,
+ Qt::AscendingOrder);
+
+ foreach(QGraphicsItem *item, itemList) {
+ GestureBox *box = dynamic_cast<GestureBox*>(item);
+ if (box && startGesture(box, scenePos, sendClick))
+ boxes.append(box);
+ }
+
+ if (boxes.isEmpty())
+ return false;
+
+ m_gesture = new GestureData(pos, boxes, m_view, m_ignored, sendClick);
+ return true;
+
+}
+
+bool ViewData::release(QPoint pos)
+{
+ if (!m_gesture || m_gesture->ended())
+ return false;
+
+ m_gesture->release(pos);
+ return true;
+}
+
+bool ViewData::move(QPoint pos)
+{
+ if (!m_gesture || m_gesture->ended())
+ return false;
+
+ m_gesture->move(pos);
+ return true;
+}
+
+QList<GestureBox*> ViewData::getBoxList(QPoint pos) {
+ QList<GestureBox*> result;
+ if (m_view->scene()) {
+ QPointF scenePos = m_view->mapToScene(pos);
+ QGraphicsItem *item = m_view->scene()->itemAt(scenePos);
+ while (item) {
+ GestureBox *box = dynamic_cast<GestureBox*>(item);
+ if (box && box->boundingRect().contains(box->mapFromScene(scenePos)))
+ result.append(box);
+ item = item->parentItem();
+ }
+ }
+ return result;
+}
+
+// GestureObserver
+
+GestureObserver *GestureObserver::instance()
+{
+ static GestureObserver *obj = new GestureObserver();
+ return obj;
+}
+
+void GestureObserver::addBox(GestureBox *box)
+{
+ if (box->scene()) {
+ foreach(QGraphicsView *view, box->scene()->views()) {
+ ViewData *data = getViewData(view);
+ if (data->m_boxes.indexOf(box) < 0) {
+ data->m_boxes.append(box);
+ m_boxes.insertMulti(box, data);
+ }
+ }
+ }
+}
+
+void GestureObserver::removeBox(GestureBox *box)
+{
+ QList<ViewData*> dataList = m_boxes.values(box);
+ foreach(ViewData* data, dataList) {
+ data->m_boxes.removeAll(box);
+ if (data->m_boxes.count() == 0) {
+ m_views.remove(data->view()->viewport());
+ data->view()->viewport()->removeEventFilter(this);
+ delete data;
+ }
+ }
+ m_boxes.remove(box);
+}
+
+
+ViewData *GestureObserver::getViewData(QGraphicsView *view)
+{
+ if (m_views.contains(view->viewport()))
+ return m_views.value(view->viewport());
+ ViewData *data = new ViewData(view);
+ view->viewport()->installEventFilter(this);
+ connect(view->viewport(), SIGNAL(destroyed()), this, SLOT(viewDestroyed()));
+ m_views.insert(view->viewport(), data);
+ return data;
+}
+
+void GestureObserver::viewDestroyed()
+{
+ if (!sender()->isWidgetType())
+ return;
+ QWidget *viewport = qobject_cast<QWidget*>(sender());
+ if (viewport || m_views.contains(viewport)) {
+ ViewData *data = m_views.take(viewport);
+ foreach (GestureBox *box, data->m_boxes) {
+ QList<ViewData*> boxes = m_boxes.values(box);
+ m_boxes.remove(box);
+
+ foreach(ViewData *viewData, boxes) {
+ if (viewData->widget() != viewport)
+ m_boxes.insertMulti(box, viewData);
+ }
+ }
+ delete data;
+ }
+
+}
+
+bool GestureObserver::eventFilter(QObject *object, QEvent *event)
+{
+ if (!object->isWidgetType())
+ return false;
+
+ QEvent::Type type = event->type();
+ if (type != QEvent::MouseButtonPress && type != QEvent::MouseButtonRelease &&
+ type != QEvent::MouseMove)
+ return false;
+
+ QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
+ if (!mouseEvent || mouseEvent->modifiers() != Qt::NoModifier)
+ return false;
+
+ QWidget *view = dynamic_cast<QWidget*>(object);
+ if (!view || !m_views.contains(view))
+ return false;
+
+ ViewData *data = m_views[view];
+ if (!data || data->ignoreEvent(event))
+ return false;
+
+ bool consumed = false;
+
+ switch (mouseEvent->type()) {
+ case QEvent::MouseButtonPress:
+ consumed = mouseEvent->buttons() == Qt::LeftButton && data->press(mouseEvent->pos());
+ break;
+ case QEvent::MouseButtonRelease:
+ consumed = data->release(mouseEvent->pos());
+ break;
+ case QEvent::MouseMove:
+ consumed = data->move(mouseEvent->pos());
+ break;
+ default:
+ break;
+ }
+ return consumed;
+}
+
+// GestureBox
+
+GestureBox::GestureBox(QGraphicsItem *parent)
+ : QGraphicsItem(parent)
+{
+ GestureObserver::instance()->addBox(this);
+}
+
+GestureBox::~GestureBox()
+{
+ GestureObserver::instance()->removeBox(this);
+}
+
+QRectF GestureBox::rect() const
+{
+ QRectF result(m_boundingRect);
+ result.moveTo(pos());
+ return result;
+}
+
+void GestureBox::setRect(QRectF value)
+{
+ setPos(value.topLeft());
+ value.moveTo(0.0, 0.0);
+ if (value != m_boundingRect) {
+ prepareGeometryChange();
+ m_boundingRect = value;
+ update();
+ }
+}
+
+void GestureBox::setRect(qreal x, qreal y, qreal width, qreal height)
+{
+ setRect(QRectF(x, y, width, height));
+}
+
+QRectF GestureBox::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+void GestureBox::paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+}
+
+QVariant GestureBox::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ switch (change) {
+ case QGraphicsItem::ItemSceneHasChanged:
+ case QGraphicsItem::ItemParentHasChanged:
+ GestureObserver::instance()->addBox(this);
+ break;
+ default:
+ break;
+ }
+ return value;
+}
+
+
diff --git a/shoplist/src/gesturebox.h b/shoplist/src/gesturebox.h
new file mode 100644
index 0000000..302f65c
--- /dev/null
+++ b/shoplist/src/gesturebox.h
@@ -0,0 +1,33 @@
+#ifndef GESTUREBOX_H
+#define GESTUREBOX_H
+
+#include <QGraphicsItem>
+
+class GestureBox : public QGraphicsItem
+{
+public:
+ GestureBox(QGraphicsItem *parent = 0);
+ ~GestureBox();
+
+ QRectF rect() const;
+ void setRect(QRectF);
+ void setRect(qreal, qreal, qreal, qreal);
+ QRectF boundingRect() const;
+
+protected:
+ virtual void gestureMousePress(QPointF pos, bool &startGesture, bool &acceptClick) = 0;
+ virtual void gestureStart(QPointF pos) = 0;
+ virtual void gestureMove(QPointF pos, QPointF movement, QPointF speed) = 0;
+ virtual void gestureEnd(QPointF pos, QPointF speed) = 0;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+
+private:
+ friend class GestureData;
+ friend class ViewData;
+ QRectF m_boundingRect;
+
+};
+
+#endif // GESTUREBOX_H
diff --git a/shoplist/src/gesturebox_p.h b/shoplist/src/gesturebox_p.h
new file mode 100644
index 0000000..f4f8452
--- /dev/null
+++ b/shoplist/src/gesturebox_p.h
@@ -0,0 +1,89 @@
+#ifndef GESTUREBOX_P_H
+#define GESTUREBOX_P_H
+
+#include <QObject>
+#include <QPointer>
+#include <QTime>
+#include <QPoint>
+#include <QPointF>
+#include <QGraphicsView>
+
+#include "gesturebox.h"
+
+class GestureData : public QObject
+{
+public:
+ inline GestureData(QPoint pos, const QList<GestureBox*> &boxes, QGraphicsView *view,
+ QList<QEvent*> &ignoreList, bool sendClickEvents);
+
+ inline void release(QPoint pos);
+ inline void move(QPoint pos);
+ inline bool ended() const { return m_state == Ended; }
+
+private:
+ enum State {Pressed, Moving, Ended};
+ State m_state;
+ QGraphicsView * const m_view;
+ const QPoint m_pressPos;
+ const QPointF m_scenePressPos;
+ const QList<GestureBox*> m_boxes;
+ QList<QEvent*> &m_ignoreList;
+ QTime m_time;
+ QPointF m_currentScenePos;
+ QPointF m_speed;
+ bool m_sendClickEvents;
+
+ void sendClick();
+};
+
+class ViewData
+{
+public:
+ ViewData(QGraphicsView *view) : m_view(view), m_gesture(0), m_widget(view->viewport()) {}
+ inline ~ViewData();
+
+ inline bool press(QPoint pos);
+ inline bool release(QPoint pos);
+ inline bool move(QPoint pos);
+
+ QGraphicsView *view() { return m_view; }
+ QWidget *widget() { return m_widget; }
+ inline bool ignoreEvent(QEvent *event);
+
+ QList<GestureBox*> m_boxes;
+
+private:
+ QGraphicsView *const m_view;
+ QPointer<GestureData> m_gesture;
+ QList<QEvent*> m_ignored;
+ QWidget * const m_widget;
+
+ inline QList<GestureBox*> getBoxList(QPoint pos);
+ inline bool startGesture(GestureBox *box, QPointF scenePos, bool &sendClick);
+};
+
+class GestureObserver : public QObject
+{
+ Q_OBJECT
+public:
+ static inline GestureObserver *instance();
+ inline void addBox(GestureBox *box);
+ inline void removeBox(GestureBox *box);
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event);
+
+private:
+ QHash<QWidget*, ViewData*> m_views;
+ QHash<GestureBox*, ViewData*> m_boxes;
+
+ GestureObserver() {}
+ ~GestureObserver() {}
+ ViewData *getViewData(QGraphicsView *view);
+
+private slots:
+ void viewDestroyed();
+
+};
+
+#endif // GESTUREBOX_P_H
diff --git a/shoplist/src/listshadow.cpp b/shoplist/src/listshadow.cpp
new file mode 100644
index 0000000..d6e3126
--- /dev/null
+++ b/shoplist/src/listshadow.cpp
@@ -0,0 +1,58 @@
+#include "listshadow.h"
+#include <QPropertyAnimation>
+#include "designinformation.h"
+
+ListShadow::ListShadow(QGraphicsItem *parent)
+ : QGraphicsPixmapItem(parent)
+ , m_focused(false)
+ , m_completed(false)
+ , m_animation(0)
+{
+ setOpacity(getTargetOpacity());
+ setVisible(opacity() != 0.0);
+}
+
+ListShadow::~ListShadow()
+{
+ if (m_animation)
+ m_animation->deleteLater();
+}
+
+void ListShadow::setFocused(bool focused)
+{
+ if (focused != m_focused) {
+ m_focused = focused;
+ createAnimation(getTargetOpacity());
+ }
+}
+
+void ListShadow::setCompleted(bool completed)
+{
+ if (m_completed != completed) {
+ m_completed = completed;
+ createAnimation(getTargetOpacity());
+ }
+}
+
+qreal ListShadow::getTargetOpacity()
+{
+ return !m_focused ? 1.0 : m_completed ? 0.2 : 0.0;
+}
+
+void ListShadow::createAnimation(qreal target)
+{
+ if (m_animation)
+ m_animation->deleteLater();
+
+ QPropertyAnimation* animation = new QPropertyAnimation(this, "opacity");
+ animation->setEasingCurve(QEasingCurve::OutExpo);
+ animation->setEndValue(target);
+ animation->setDuration(500);
+ if (target == 0.0)
+ connect(animation, SIGNAL(finished()), this, SLOT(doHide()));
+ connect(animation, SIGNAL(finished()), this, SLOT(animationEnd()));
+
+ m_animation = animation;
+ m_animation->start(QAbstractAnimation::DeleteWhenStopped);
+ show();
+}
diff --git a/shoplist/src/listshadow.h b/shoplist/src/listshadow.h
new file mode 100644
index 0000000..faa913f
--- /dev/null
+++ b/shoplist/src/listshadow.h
@@ -0,0 +1,34 @@
+#ifndef LISTSHADOW_H
+#define LISTSHADOW_H
+
+#include <QAbstractAnimation>
+#include <QGraphicsPixmapItem>
+
+class ListShadow : public QObject, public QGraphicsPixmapItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity);
+public:
+ ListShadow(QGraphicsItem *parent = 0);
+ ~ListShadow();
+
+ bool focused() const { return m_focused; }
+ bool completed() const { return m_completed; }
+
+ void setFocused(bool);
+ void setCompleted(bool);
+
+private slots:
+ void doHide() { hide(); }
+ void animationEnd() { m_animation = 0; }
+
+private:
+ bool m_focused;
+ bool m_completed;
+ QAbstractAnimation *m_animation;
+
+ qreal getTargetOpacity();
+ void createAnimation(qreal opacity);
+};
+
+#endif // LISTSHADOW_H
diff --git a/shoplist/src/main.cpp b/shoplist/src/main.cpp
new file mode 100644
index 0000000..c42b5c0
--- /dev/null
+++ b/shoplist/src/main.cpp
@@ -0,0 +1,54 @@
+#include <QtGui>
+#include <QDebug>
+
+#include "maincontainer.h"
+#include "designinformation.h"
+#include "shoppinglistcategoryui.h"
+#include "shoppinglistview.h"
+
+static ShoppingListCategoryUI *createList(const QString &category, int itemCount)
+{
+ ShoppingListCategoryUI *result = new ShoppingListCategoryUI(category);
+ QString textsKey = "category.string_list." + category;
+ QStringList texts = DesignInformation::getStringList(textsKey);
+
+ QList<ContentListItem*> items;
+
+ for (int i = 0; i < itemCount && i < texts.count(); ++i) {
+ ShoppingListItem *item = new ShoppingListItem(QString::number(i + 1) + " - " + texts[i],
+ result->list(), i);
+ items.append(item);
+ }
+ result->list()->appendItems(items);
+
+ return result;
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ MainContainer* lists = new MainContainer();
+
+ QGraphicsScene scene;
+ ShoppingListView view(lists);
+ view.setScene(&scene);
+
+
+ QObject::connect(QApplication::desktop(), SIGNAL(resized(int)), &view, SLOT(resized(int)));
+
+ view.adjustScalingFactor();
+ view.adjustScreenSize();
+
+ lists->add(createList("groceries", 60));
+ lists->add(createList("beverages", 20));
+ lists->add(createList("cleaning", 60));
+ lists->add(createList("garden", 80));
+ lists->add(createList("pet", 100));
+ lists->add(createList("toiletries", 200));
+
+ scene.addItem(lists);
+
+ view.show();
+ return app.exec();
+}
diff --git a/shoplist/src/maincontainer.cpp b/shoplist/src/maincontainer.cpp
new file mode 100644
index 0000000..1c35a58
--- /dev/null
+++ b/shoplist/src/maincontainer.cpp
@@ -0,0 +1,261 @@
+#include <QKeyEvent>
+#include <QPointF>
+#include <QPixmap>
+#include <QGraphicsPixmapItem>
+#include <QEvent>
+#include <QGraphicsSceneMouseEvent>
+#include <QCoreApplication>
+#include <QGraphicsTextItem>
+#include <QFont>
+
+#include <QAbstractAnimation>
+#include <QPropertyAnimation>
+#include <QParallelAnimationGroup>
+#include <cmath>
+#include <QDebug>
+#include <QPainter>
+
+#include "maincontainer.h"
+#include "designinformation.h"
+
+static const qreal listOffset = -1;
+
+// CloseButton
+
+CloseButton::CloseButton(QGraphicsItem *parent)
+ : QGraphicsPixmapItem(parent)
+{
+ setShapeMode(BoundingRectShape);
+ updateUI();
+}
+
+void CloseButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(event);
+ QCoreApplication::instance()->quit();
+}
+
+void CloseButton::updateUI()
+{
+ setPixmap(DesignInformation::getPixmap("closeButton"));
+ if (parentItem()) {
+ qreal top = DesignInformation::getPosition("closeButton").y();
+ qreal left = parentItem()->boundingRect().width() - pixmap().width();
+ left -= DesignInformation::getHorizontalSize("close_button_spacing");
+ setPos(left, top);
+ }
+ else
+ setPos(DesignInformation::getPosition("closeButton"));
+ prepareGeometryChange();
+ update();
+}
+
+QPainterPath CloseButton::shape() const
+{
+ return QGraphicsItem::shape();
+}
+
+QRectF CloseButton::boundingRect() const
+{
+ static const qreal minSize = 80.0;
+ QRectF result(QGraphicsPixmapItem::boundingRect());
+ qreal hMargin = minSize < result.width() ? 0 : (minSize - result.width()) / 2;
+ qreal vMargin = minSize < result.height() ? 0 : (minSize - result.height()) / 2;
+ result.adjust(-hMargin, -vMargin, hMargin, vMargin);
+ return result;
+}
+
+// ListChangeGestureBox
+
+static const int max_gesture_time_ms = 500;
+static const qreal degrees = 30.0;
+static const qreal limit_angle_tg = tan(degrees * 3.141592 / 180.0);
+static const qreal min_gesture_length = 60.0;
+
+ListChangeGestureBox::ListChangeGestureBox(QGraphicsItem *parent)
+ : GestureBox(parent)
+ , m_active(true)
+ , m_startPoint(0.0, 0.0)
+{
+}
+
+void ListChangeGestureBox::setActivate(bool active)
+{
+ m_active = active;
+}
+
+void ListChangeGestureBox::gestureMousePress(QPointF pos, bool &startGesture, bool &acceptClick)
+{
+ Q_UNUSED(pos);
+ Q_UNUSED(acceptClick);
+ startGesture = m_active;
+}
+
+void ListChangeGestureBox::gestureStart(QPointF pos)
+{
+ m_startPoint = pos;
+ m_startTime = QTime::currentTime();
+}
+
+void ListChangeGestureBox::gestureMove(QPointF pos, QPointF movement, QPointF speed)
+{
+ Q_UNUSED(pos);
+ Q_UNUSED(movement);
+ Q_UNUSED(speed);
+}
+
+void ListChangeGestureBox::gestureEnd(QPointF pos, QPointF speed)
+{
+ Q_UNUSED(speed);
+ qreal x = pos.x() - m_startPoint.x();
+ qreal y = pos.y() - m_startPoint.y();
+ if (!m_active
+ || fabs(y / x) > limit_angle_tg
+ || m_startTime.msecsTo(QTime::currentTime()) > max_gesture_time_ms
+ || fabs(x) < min_gesture_length) {
+ return;
+ }
+
+ if (x > 0)
+ emit moveLeft();
+ else
+ emit moveRight();
+}
+
+// MainContainer
+
+MainContainer::MainContainer()
+ : m_animation(0)
+ , m_lists()
+ , m_current(0)
+ , m_hold(new QGraphicsRectItem(this))
+ , m_closeButton(new CloseButton(this))
+ , m_gestureBox(new ListChangeGestureBox(this))
+{
+ setPixmap(DesignInformation::getPixmap("background"));
+ m_hold->setFlags(QGraphicsItem::ItemHasNoContents);
+ m_hold->setPos(DesignInformation::getHorizontalSize("listset.center_position"), 0.0);
+
+ m_gestureBox->setRect(boundingRect());
+
+ m_title = new QGraphicsTextItem(this);
+ QString html = "<span style=\"font-family:Nokia sans; color:#f8f8f8\">";
+ html += "Shopping List </span>";
+ m_title->setHtml(html);
+
+ connect(m_gestureBox,SIGNAL(moveLeft()), this, SLOT(moveLeft()));
+ connect(m_gestureBox,SIGNAL(moveRight()), this, SLOT(moveRight()));
+}
+
+void MainContainer::adjustGestureBox()
+{
+ m_gestureBox->setActivate(m_current >= 0 && m_current < m_lists.count());
+}
+
+void MainContainer::add(ShoppingListCategoryUI *list)
+{
+
+ if (m_lists.indexOf(list) >= 0)
+ return;
+
+ list->setParentItem(m_hold);
+ m_lists.append(list);
+ if (m_lists.count() == 1)
+ m_lists[0]->setFocused(true);
+
+ adjustListsPositions();
+ adjustGestureBox();
+}
+
+void MainContainer::adjustListsPositions()
+{
+ qreal listPos = 0.0;
+
+ for (int i = 0; i < m_lists.count(); ++i) {
+ m_lists[i]->setPos(listPos, 0);
+ listPos += m_lists[i]->boundingRect().width() + listOffset;
+ m_lists[i]->setFocused(i == m_current);
+ }
+}
+
+void MainContainer::updateUI()
+{
+ setPixmap(DesignInformation::getPixmap("background"));
+ foreach(ShoppingListCategoryUI *list, m_lists)
+ list->updateUI();
+
+ QFont font = m_title->font();
+ font.setPixelSize(DesignInformation::getFontSize("title"));
+ m_title->setFont(font);
+ QPointF titlePos = DesignInformation::getPosition("title");
+ qreal titleLeft = (boundingRect().width() - m_title->boundingRect().width()) / 2;
+ m_title->setPos(titleLeft, titlePos.y());
+
+ m_closeButton->updateUI();
+
+ adjustListsPositions();
+
+ qreal holdOffset = DesignInformation::getHorizontalSize("listset.center_position");
+ if (m_current >= 0 && m_current < m_lists.count()) {
+ for (int i = 0; i < m_current; ++i)
+ holdOffset -= m_lists[i]->boundingRect().width();
+ }
+ m_hold->setPos(holdOffset, 0);
+
+ m_gestureBox->setRect(boundingRect());
+ adjustGestureBox();
+}
+
+void MainContainer::moveLeft()
+{
+ startMovement(false);
+}
+
+void MainContainer::moveRight()
+{
+ startMovement(true);
+}
+
+void MainContainer::startMovement(bool leftToRight)
+{
+ int target = m_current + (leftToRight ? 1 : -1);
+ if (m_animation || target < 0 || target >= m_lists.count())
+ return;
+
+ QAbstractAnimation* anim = sideAnimation(leftToRight);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ m_animation = anim;
+ m_current = target;
+
+ m_gestureBox->setActivate(false);
+ m_lists[m_current]->setFocused(true);
+ if (m_current > 0)
+ m_lists[m_current - 1]->setFocused(false);
+ if (m_current < m_lists.count() - 1)
+ m_lists[m_current + 1]->setFocused(false);
+}
+
+void MainContainer::animationFinished()
+{
+ m_animation = 0;
+ adjustGestureBox();
+}
+
+QAbstractAnimation* MainContainer::sideAnimation(bool leftToRight)
+{
+ QParallelAnimationGroup* group = new QParallelAnimationGroup();
+
+ qreal left = m_lists[m_current]->boundingRect().width() + listOffset;
+ left = m_hold->pos().x() +(leftToRight ? -left : left);
+
+ QPropertyAnimation* anim = new QPropertyAnimation(this, "position");
+ anim->setEasingCurve(QEasingCurve::OutExpo);
+ anim->setDuration(500);
+ anim->setEndValue(QPointF(left, 0));
+
+ group->addAnimation(anim);
+
+ connect(group, SIGNAL(finished()), this, SLOT(animationFinished()));
+
+ return group;
+}
diff --git a/shoplist/src/maincontainer.h b/shoplist/src/maincontainer.h
new file mode 100644
index 0000000..4ec67e7
--- /dev/null
+++ b/shoplist/src/maincontainer.h
@@ -0,0 +1,91 @@
+#ifndef _MAINCONTAINER_H_
+#define _MAINCONTAINER_H_
+
+#include <QPointF>
+#include <QObject>
+#include <QKeyEvent>
+#include <QAbstractAnimation>
+#include <QPropertyAnimation>
+
+#include <QGraphicsRectItem>
+#include <QGraphicsPixmapItem>
+
+#include "shoppinglistcategoryui.h"
+#include "gesturebox.h"
+
+class CloseButton: public QGraphicsPixmapItem
+{
+public:
+ CloseButton(QGraphicsItem *parent = 0);
+ QRectF boundingRect() const;
+ QPainterPath shape() const;
+ void updateUI();
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+};
+
+class ListChangeGestureBox : public QObject, public GestureBox
+{
+ Q_OBJECT
+public:
+ ListChangeGestureBox(QGraphicsItem *parent = 0);
+ void setActivate(bool active);
+
+signals:
+ void moveLeft();
+ void moveRight();
+
+protected:
+ void gestureMousePress(QPointF pos, bool &startGesture, bool &acceptClick);
+ void gestureStart(QPointF pos);
+ void gestureMove(QPointF pos, QPointF movement, QPointF speed);
+ void gestureEnd(QPointF pos, QPointF speed);
+
+private:
+ bool m_active;
+ QPointF m_startPoint;
+ QTime m_startTime;
+};
+
+class MainContainer: public QObject, public QGraphicsPixmapItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QPointF position READ position WRITE setPosition);
+
+public:
+ MainContainer();
+ virtual ~MainContainer() {};
+
+ void add(ShoppingListCategoryUI *);
+
+ void updateUI();
+
+
+
+public slots:
+ void moveLeft();
+ void moveRight();
+
+private slots:
+ void animationFinished();
+
+private:
+ QPointF position() { return m_hold->pos(); }
+ void setPosition(QPointF pos) { m_hold->setPos(pos); }
+
+ QAbstractAnimation* m_animation;
+ QAbstractAnimation* sideAnimation(bool leftToRight);
+
+ QList<ShoppingListCategoryUI*> m_lists;
+ int m_current;
+ QGraphicsRectItem* m_hold;
+ CloseButton *m_closeButton;
+ ListChangeGestureBox *m_gestureBox;
+ QGraphicsTextItem* m_title;
+
+ void adjustGestureBox();
+ void startMovement(bool leftToRight);
+ void adjustListsPositions();
+};
+
+#endif /* _MAINCONTAINER_H_ */
diff --git a/shoplist/src/popup.cpp b/shoplist/src/popup.cpp
new file mode 100644
index 0000000..27196ba
--- /dev/null
+++ b/shoplist/src/popup.cpp
@@ -0,0 +1,73 @@
+#include <QBrush>
+#include <QEvent>
+#include <QPointF>
+#include <QGraphicsPixmapItem>
+
+#include "popup.h"
+#include "designinformation.h"
+
+// PopupCloseButton
+
+PopupCloseButton::PopupCloseButton(QGraphicsItem *parent)
+ : QGraphicsPixmapItem(parent)
+{
+ setShapeMode(BoundingRectShape);
+}
+
+QPainterPath PopupCloseButton::shape() const
+{
+ return QGraphicsItem::shape();
+}
+
+QRectF PopupCloseButton::boundingRect() const
+{
+ static const qreal minSize = 80.0;
+ QRectF result(QGraphicsPixmapItem::boundingRect());
+ qreal hMargin = minSize < result.width() ? 0 : (minSize - result.width()) / 2;
+ qreal vMargin = minSize < result.height() ? 0 : (minSize - result.height()) / 2;
+ result.adjust(-hMargin, -vMargin, hMargin, vMargin);
+ return result;
+}
+
+// PopUp
+
+PopUp::PopUp(QGraphicsItem* parent)
+ : QGraphicsRectItem(parent)
+{
+ m_allDone = new QGraphicsPixmapItem(this);
+ m_allDone->installSceneEventFilter(this);
+
+ m_startAgain = new QGraphicsPixmapItem(m_allDone);
+ m_startAgain->installSceneEventFilter(this);
+
+ m_close = new PopupCloseButton(m_allDone);
+ m_close->installSceneEventFilter(this);
+
+ updateUI();
+}
+
+void PopUp::updateUI()
+{
+ m_allDone->setPixmap(DesignInformation::getPixmap("alldone.background"));
+ m_allDone->setPos((parentItem()->boundingRect().bottomRight()/2) -
+ (m_allDone->boundingRect().bottomRight()/2));
+
+ m_startAgain->setPixmap(DesignInformation::getPixmap("alldone.startagain_off"));
+ m_startAgain->setPos((m_allDone->boundingRect().bottomRight()/2) -
+ (m_startAgain->boundingRect().bottomRight()/2) +
+ DesignInformation::getPosition("alldone.startagain_off"));
+
+ m_close->setPixmap(DesignInformation::getPixmap("alldone.close_button"));
+ m_close->setPos((m_allDone->boundingRect().bottomRight()/2) -
+ (m_close->boundingRect().bottomRight()/2) +
+ DesignInformation::getPosition("alldone.close_button"));
+}
+
+bool PopUp::sceneEventFilter(QGraphicsItem *item, QEvent *event)
+{
+ if ((event->type() == QEvent::GraphicsSceneMousePress) and (item == m_startAgain))
+ emit listStartAgain();
+ else if ((event->type() == QEvent::GraphicsSceneMousePress) and (item == m_close))
+ emit deletePopUp();
+ return true;
+}
diff --git a/shoplist/src/popup.h b/shoplist/src/popup.h
new file mode 100644
index 0000000..1a89e0a
--- /dev/null
+++ b/shoplist/src/popup.h
@@ -0,0 +1,39 @@
+#ifndef POPUP_H
+#define POPUP_H
+
+#include <QObject>
+#include <QRect>
+#include <QGraphicsObject>
+
+class PopupCloseButton: public QGraphicsPixmapItem
+{
+public:
+ PopupCloseButton(QGraphicsItem *parent = 0);
+ QRectF boundingRect() const;
+ QPainterPath shape() const;
+};
+
+class PopUp : public QObject, public QGraphicsRectItem
+{
+ Q_OBJECT
+
+public:
+ PopUp(QGraphicsItem* parent = 0);
+ ~PopUp() {}
+
+ void updateUI();
+
+signals:
+ void listStartAgain();
+ void deletePopUp();
+
+protected:
+ bool sceneEventFilter(QGraphicsItem *item, QEvent *event);
+
+private:
+ QGraphicsPixmapItem* m_allDone;
+ QGraphicsPixmapItem* m_startAgain;
+ PopupCloseButton* m_close;
+};
+
+#endif // POPUP_H
diff --git a/shoplist/src/scrollbar.cpp b/shoplist/src/scrollbar.cpp
new file mode 100644
index 0000000..355e6dd
--- /dev/null
+++ b/shoplist/src/scrollbar.cpp
@@ -0,0 +1,162 @@
+#include <QObject>
+#include <QString>
+#include <QTimer>
+#include <QGraphicsPixmapItem>
+#include <QPropertyAnimation>
+#include <QAbstractAnimation>
+
+#include "designinformation.h"
+#include "scrollbar.h"
+
+/*! \class ScrollBar
+ *
+ * \brief Fade in/out animations and position update callback
+ *
+ * Stick this over your items viewport and send \c updatePosition notifications
+ * to render the knob into the new position. It doesn't handle user input.
+ */
+ScrollBar::ScrollBar(QGraphicsItem* parent)
+ : QObject()
+ , QGraphicsPixmapItem(parent)
+ , m_state(Hidden)
+ , m_maximum(0)
+ , m_value(0)
+ , m_timer()
+ , m_animation(0)
+ , m_knob(this)
+{
+ hide();
+ setValue(m_value);
+ setOpacity(0);
+
+ m_timer.setSingleShot(true);
+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
+
+ updateUI();
+}
+
+void ScrollBar::updateUI()
+{
+ setPixmap(DesignInformation::getPixmap("list.scrollbar.portrait"));
+ m_knob.setPixmap(DesignInformation::getPixmap("list.scrollbar.knob"));
+}
+
+qreal ScrollBar::maximum() { return m_maximum; }
+
+void ScrollBar::setMaximum(qreal max)
+{
+ if (max >= 0)
+ m_maximum = max;
+}
+
+qreal ScrollBar::value() { return m_value; }
+
+void ScrollBar::setValue(qreal value)
+{
+ if (value < 0 || value > m_maximum)
+ return;
+
+ m_value = value;
+
+ int min = boundingRect().topLeft().y();
+ int max = boundingRect().bottomLeft().y() - m_knob.boundingRect().height();
+
+ m_knob.setPos(0, (value * (max - min)) / m_maximum);
+}
+
+void ScrollBar::updatePosition(qreal value)
+{
+ switch (m_state) {
+ case Visible:
+ startTimer();
+ case ShowAnimation:
+ break;
+ case HideAnimation:
+ m_animation->stop();
+ case Hidden:
+ QAbstractAnimation* anim = showAnimation();
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ m_state = ShowAnimation;
+ break;
+ }
+
+ show();
+ setValue(value);
+}
+
+void ScrollBar::setLandscapeOrientation()
+{
+ setPixmap(DesignInformation::getPixmap("list.scrollbar.landscape"));
+ setValue(m_value);
+}
+
+void ScrollBar::setPortraitOrientation()
+{
+ setPixmap(DesignInformation::getPixmap("list.scrollbar.portrait"));
+ setValue(m_value);
+}
+
+void ScrollBar::startTimer()
+{
+ if (m_timer.isActive())
+ m_timer.stop();
+
+ m_timer.start(1000);
+}
+
+void ScrollBar::timeout()
+{
+ if (Visible != m_state)
+ return;
+
+ m_state = HideAnimation;
+ QAbstractAnimation* anim = hideAnimation();
+ m_animation = anim;
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
+void ScrollBar::animationFinished()
+{
+ switch(m_state) {
+ case ShowAnimation:
+ startTimer();
+ m_state = Visible;
+ break;
+ case HideAnimation:
+ hide();
+ m_state = Hidden;
+ m_animation = 0;
+ break;
+ default:
+ break;
+ }
+}
+
+QPropertyAnimation* ScrollBar::propertyAnimation(const char* name)
+{
+ QPropertyAnimation* anim = new QPropertyAnimation();
+ anim->setTargetObject(this);
+ anim->setPropertyName(name);
+ anim->setEasingCurve(QEasingCurve::OutExpo);
+ anim->setDuration(500);
+
+ connect(anim, SIGNAL(finished()), this, SLOT(animationFinished()));
+
+ return anim;
+}
+
+QAbstractAnimation* ScrollBar::showAnimation()
+{
+ QPropertyAnimation* anim = propertyAnimation("opacity");
+ anim->setEndValue(1);
+
+ return anim;
+}
+
+QAbstractAnimation* ScrollBar::hideAnimation()
+{
+ QPropertyAnimation* anim = propertyAnimation("opacity");
+ anim->setEndValue(0);
+
+ return anim;
+}
diff --git a/shoplist/src/scrollbar.h b/shoplist/src/scrollbar.h
new file mode 100644
index 0000000..5536a61
--- /dev/null
+++ b/shoplist/src/scrollbar.h
@@ -0,0 +1,59 @@
+#ifndef SCROLLBAR_H
+#define SCROLLBAR_H
+
+#include <QObject>
+#include <QString>
+#include <QTimer>
+#include <QGraphicsPixmapItem>
+#include <QPropertyAnimation>
+#include <QAbstractAnimation>
+
+class ScrollBar: public QObject, public QGraphicsPixmapItem
+{
+ Q_OBJECT
+public:
+ ScrollBar(QGraphicsItem* parent);
+ virtual ~ScrollBar() {}
+
+ void updateUI();
+
+ qreal maximum();
+ void setMaximum(qreal max);
+
+ qreal value();
+ void setValue(qreal);
+
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity);
+
+public slots:
+ void updatePosition(qreal);
+ void setLandscapeOrientation();
+ void setPortraitOrientation();
+
+private slots:
+ void animationFinished();
+ void timeout();
+
+private:
+ QPropertyAnimation* propertyAnimation(const char* name);
+ QAbstractAnimation* showAnimation();
+ QAbstractAnimation* hideAnimation();
+
+ void startTimer();
+
+ enum State {
+ Hidden,
+ ShowAnimation,
+ Visible,
+ HideAnimation
+ };
+ State m_state;
+
+ qreal m_maximum;
+ qreal m_value;
+ QTimer m_timer;
+ QAbstractAnimation* m_animation;
+ QGraphicsPixmapItem m_knob;
+};
+
+#endif /* SCROLLBAR_H */
diff --git a/shoplist/src/shoppinglist.cpp b/shoplist/src/shoppinglist.cpp
new file mode 100644
index 0000000..4c61830
--- /dev/null
+++ b/shoplist/src/shoppinglist.cpp
@@ -0,0 +1,265 @@
+#include "shoppinglist.h"
+#include <QPropertyAnimation>
+#include <QParallelAnimationGroup>
+#include <QSequentialAnimationGroup>
+#include <QGraphicsSceneMouseEvent>
+#include <QFont>
+#include <QDebug>
+#include "designinformation.h"
+
+class ShoppingListItemClickActivity : public ContentListActivity
+{
+public:
+ ShoppingListItemClickActivity(ShoppingListItem *item, bool check, ContentList &list)
+ : ContentListActivity(list)
+ , m_item(item)
+ , m_check(check)
+ {}
+ bool run();
+private:
+ ShoppingListItem *m_item;
+ const bool m_check;
+};
+
+bool ShoppingListItemClickActivity::run()
+{
+ int idx = m_list.getItemIndex(m_item);
+ if (idx >= 0 && m_item->checked() != m_check) {
+
+ m_item->m_list->m_checkedItems += m_item->checked() ? -1 : 1;
+
+ addActivity(new AnimationActivity(m_item->getSwitchAnimation(),m_list));
+
+ if (m_check)
+ addActivity(new MoveActivity(idx, m_list.itemCount(), m_list));
+
+ if (!m_check) {
+ int target = m_list.itemCount();
+ for (int i = 0; target == m_list.itemCount() && i < m_list.itemCount(); ++i) {
+ ShoppingListItem *item = dynamic_cast<ShoppingListItem*>(m_list.getItem(i));
+ if (!item || item == m_item)
+ continue;
+ if (item->checked()) {
+ if (idx > i)
+ addActivity(new MoveActivity(idx, i, m_list));
+ break;
+ }
+ if (item->listPos() > m_item->listPos()) {
+ addActivity(new MoveActivity(idx, i, m_list));
+ break;
+ }
+ }
+ }
+
+ if (m_item->m_list->m_checkedItems == m_item->m_list->itemCount()) {
+ SignalActivity *activity = new SignalActivity(m_list);
+ connect(activity, SIGNAL(notify()), m_item->m_list, SIGNAL(completed()));
+ addActivity(activity);
+ }
+ }
+ return false;
+}
+
+// ShoppingListItem
+
+ShoppingListItem::ShoppingListItem(const QString& text, ShoppingList *list,
+ int pos, QGraphicsItem *parent)
+ : ContentListItem(parent)
+ , m_list(list)
+ , m_pos(pos)
+ , m_contentHeight(DesignInformation::getVerticalSize("list_item.height"))
+{
+ m_image1 = new ShoppingListPixmap(this);
+ m_image2 = new ShoppingListPixmap(this);
+ m_line = new ShoppingListPixmap(this);
+ m_selected = new ShoppingListPixmap(this);
+
+ m_image2->hide();
+ m_image2->setOpacity(0);
+ m_selected->hide();
+ m_selected->setOpacity(0);
+
+ m_text = new QGraphicsTextItem(this);
+ QString html = "<span style=\"font-family:Nokia sans; color:#616161\">";
+ html += text + "</span>";
+ m_text->setHtml(html);
+
+ updateUI();
+}
+
+void ShoppingListItem::updateUI()
+{
+ m_contentHeight = DesignInformation::getVerticalSize("list_item.height");
+
+ updatePixmapItem(m_image1, "list_item.not_checked", 1);
+ updatePixmapItem(m_image2, "list_item.checked", 1);
+ updatePixmapItem(m_line, "list_item.bottom_line", 1);
+ updatePixmapItem(m_selected, "list_item.selected", 0);
+
+ QFont font = m_text->font();
+ font.setPixelSize(DesignInformation::getFontSize("list_item.font_size"));
+ m_text->setFont(font);
+
+ qreal textOffset = m_image1->pos().x() + m_image1->pixmap().width() +
+ DesignInformation::getHorizontalSize("list_item.text_offset");
+
+ qreal textTop = (contentHeight() - m_text->boundingRect().height()) / 2;
+
+ m_text->setPos(textOffset, textTop);
+}
+
+void ShoppingListItem::updatePixmapItem(ShoppingListPixmap *item, const QString &key, qreal zValue)
+{
+ item->setPixmap(DesignInformation::getPixmap(key));
+ item->setPos(DesignInformation::getPosition(key));
+ item->setZValue(zValue);
+}
+
+qreal ShoppingListItem::contentHeight() const
+{
+ return m_contentHeight;
+}
+
+QAbstractAnimation *ShoppingListItem::getShowAnimation()
+{
+ return getFadeAnimation(this, false, 150);
+}
+
+QAbstractAnimation *ShoppingListItem::getHideAnimation()
+{
+ return getFadeAnimation(this, true, 150);
+}
+
+template<class T>
+QAbstractAnimation *ShoppingListItem::getFadeAnimation(T *target, bool hide, int msecs)
+{
+
+ target->setOpacity(hide ? 1.0 : 0.0);
+ target->show();
+
+ QPropertyAnimation* lResult = new QPropertyAnimation(target, "opacity");
+ lResult->setEasingCurve(QEasingCurve::OutExpo);
+ lResult->setStartValue(hide ? 1.0 : 0.0);
+ lResult->setEndValue(hide ? 0.0 : 1.0);
+ lResult->setDuration(msecs);
+ if (hide)
+ connect(lResult, SIGNAL(finished()), target, SLOT(doHide()));
+ return lResult;
+}
+
+QAbstractAnimation *ShoppingListItem::getSwitchAnimation()
+{
+ ShoppingListPixmap *in = checked() ? m_image1 : m_image2;
+ ShoppingListPixmap *out = in == m_image1 ? m_image2 : m_image1;
+
+ QParallelAnimationGroup *result = new QParallelAnimationGroup();
+
+ QAbstractAnimation *background = getFadeAnimation(m_selected, checked(), 150);
+ result->addAnimation(addAnimationPause(background, 50));
+
+ result->addAnimation(getFadeAnimation(in, false, 150));
+ result->addAnimation(getFadeAnimation(out, true, 150));
+
+ return result;
+}
+
+QAbstractAnimation *ShoppingListItem::addAnimationPause(QAbstractAnimation *animation, int msecs)
+{
+ QSequentialAnimationGroup *result = new QSequentialAnimationGroup();
+ result->addPause(msecs);
+ result->addAnimation(animation);
+ return result;
+}
+
+void ShoppingListItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(event);
+ if (m_list && !m_list->busy() && m_list->active())
+ m_list->addActivity(new ShoppingListItemClickActivity(this, !checked(), *m_list));
+}
+
+void ShoppingListItem::uncheck()
+{
+ m_image1->show();
+ m_image1->setOpacity(1.0);
+ m_image2->hide();
+ m_image2->setOpacity(0);
+ m_selected->hide();
+ m_selected->setOpacity(0);
+}
+
+// ShoppingList
+
+ShoppingList::ShoppingList(QGraphicsItem *parent)
+ : ContentList(parent)
+ , m_checkedItems(0)
+ , m_active(true)
+{
+}
+
+QAbstractAnimation *ShoppingList::getInsertAnimation(int idx, qreal height)
+{
+ if (idx < 0 || idx >= itemCount())
+ return 0;
+ QList<QAbstractAnimation*> list;
+ for (int i = idx; i < itemCount(); ++i)
+ list.append(getItemMoveAnimation(i, height));
+ return createCompoundAnimation(list);
+}
+
+QAbstractAnimation *ShoppingList::getRemoveAnimation(int idx)
+{
+ if (idx < 0 || idx >= itemCount())
+ return 0;
+ qreal offset = -getItem(idx)->contentHeight();
+ QList<QAbstractAnimation*> list;
+ for (int i = idx + 1; i < itemCount(); ++i)
+ list.append(getItemMoveAnimation(i, offset));
+ return createCompoundAnimation(list);
+}
+
+QAbstractAnimation *ShoppingList::createCompoundAnimation(QList<QAbstractAnimation*> list)
+{
+ if (list.count() == 0)
+ return 0;
+ if (list.count() == 1)
+ return list[0];
+ QParallelAnimationGroup *result = new QParallelAnimationGroup();
+ for (int i = 0; i < list.count(); ++i)
+ result->addAnimation(list[i]);
+ return result;
+
+}
+
+QAbstractAnimation *ShoppingList::getItemMoveAnimation(int idx, qreal offset)
+{
+ ContentListItem *item = getItem(idx);
+ if (!item)
+ return 0;
+
+ qreal itemTop = item->property(ITEM_TOP_PROPERTY_NAME).toReal();
+
+ QPropertyAnimation* lResult = new QPropertyAnimation(item, ITEM_TOP_PROPERTY_NAME);
+
+ lResult->setEasingCurve(QEasingCurve::OutExpo);
+ lResult->setStartValue(itemTop);
+ lResult->setEndValue(itemTop + offset);
+ lResult->setDuration(150);
+ return lResult;
+}
+
+static bool shoppingListItemCompare(const ContentListItem* s1, const ContentListItem* s2)
+{
+ const ShoppingListItem *item1 =dynamic_cast<const ShoppingListItem*>(s1);
+ const ShoppingListItem *item2 =dynamic_cast<const ShoppingListItem*>(s2);
+ return !item1 || !item2 ? false : item1->listPos() < item2->listPos();
+}
+
+void ShoppingList::clearChecks()
+{
+ foreach(ContentListItem *item, getItems())
+ dynamic_cast<ShoppingListItem*>(item)->uncheck();
+ m_checkedItems = 0;
+ sortItems(shoppingListItemCompare);
+}
+
diff --git a/shoplist/src/shoppinglist.h b/shoplist/src/shoppinglist.h
new file mode 100644
index 0000000..e05138b
--- /dev/null
+++ b/shoplist/src/shoppinglist.h
@@ -0,0 +1,89 @@
+#ifndef SHOPPINGLIST_H
+#define SHOPPINGLIST_H
+
+#include <QGraphicsPixmapItem>
+#include <QGraphicsTextItem>
+#include "contentlist.h"
+
+class ShoppingListPixmap : public QObject, public QGraphicsPixmapItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity);
+public:
+ ShoppingListPixmap(QGraphicsItem *parent = 0)
+ : QGraphicsPixmapItem(parent) {}
+public slots:
+ void doHide() { hide(); }
+};
+
+class ShoppingList : public ContentList
+{
+ Q_OBJECT
+public:
+ ShoppingList(QGraphicsItem *parent = 0);
+ QAbstractAnimation *getInsertAnimation(int idx, qreal height);
+ QAbstractAnimation *getRemoveAnimation(int idx);
+
+ void setActive(bool active) { m_active = active; }
+ bool active() const { return m_active; }
+
+signals:
+ void completed();
+
+public slots:
+ void clearChecks();
+
+private:
+ friend class ShoppingListItemClickActivity;
+
+ int m_checkedItems;
+ bool m_active;
+
+ QAbstractAnimation *getItemMoveAnimation(int idx, qreal offset);
+ QAbstractAnimation *createCompoundAnimation(QList<QAbstractAnimation*>);
+};
+
+class ShoppingListItem : public ContentListItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity);
+public:
+ ShoppingListItem(const QString& text, ShoppingList *list,
+ int pos, QGraphicsItem *parent = 0);
+
+ qreal contentHeight() const;
+ QAbstractAnimation *getShowAnimation();
+ QAbstractAnimation *getHideAnimation();
+
+ bool checked() const { return m_image2->isVisible(); }
+ int listPos() const { return m_pos; }
+ void uncheck();
+
+ void updateUI();
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+
+private:
+ ShoppingListPixmap *m_image1;
+ ShoppingListPixmap *m_image2;
+ ShoppingListPixmap *m_line;
+ ShoppingListPixmap *m_selected;
+ QGraphicsTextItem *m_text;
+ QAbstractAnimation *getSwitchAnimation();
+ QAbstractAnimation *addAnimationPause(QAbstractAnimation *animation, int msecs);
+ template<class T> QAbstractAnimation *getFadeAnimation(T *target, bool hide, int msecs);
+ void updatePixmapItem(ShoppingListPixmap *item, const QString &key, qreal zValue);
+
+private slots:
+ void doHide() { hide(); }
+
+private:
+ friend class ShoppingListItemClickActivity;
+ QPointer<ShoppingList> m_list;
+ const int m_pos;
+ qreal m_contentHeight;
+
+};
+
+#endif // SHOPPINGLIST_H
diff --git a/shoplist/src/shoppinglistcategoryui.cpp b/shoplist/src/shoppinglistcategoryui.cpp
new file mode 100644
index 0000000..59a8ba5
--- /dev/null
+++ b/shoplist/src/shoppinglistcategoryui.cpp
@@ -0,0 +1,266 @@
+#include "shoppinglistcategoryui.h"
+#include "designinformation.h"
+#include "scrollbar.h"
+
+#include <QDebug>
+#include <QtGlobal>
+#include <cmath>
+
+// ShoppingListScrollBox
+
+#ifdef Q_OS_SYMBIAN
+static const int acceleration_factor = 12;
+#else
+static const int acceleration_factor = 64;
+#endif
+
+
+static const int max_gesture_time_ms = 500;
+static const qreal degrees = 30.0;
+static const qreal limit_angle_tg = tan(degrees * 3.141592 / 180.0);
+static const qreal min_gesture_length = 100.0;
+
+ShoppingListScrollBox::ShoppingListScrollBox(QGraphicsItem *content, QGraphicsItem *parent)
+ : GestureBox(parent)
+ , m_content(content)
+ , m_active(true)
+{
+ setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
+ if (m_content)
+ m_content->setParentItem(this);
+
+ QObject* obj = dynamic_cast<QObject*>(parent);
+ if (obj)
+ connect(this, SIGNAL(updated(qreal, qreal, qreal)),
+ obj, SLOT(updated(qreal, qreal, qreal)));
+}
+
+void ShoppingListScrollBox::gestureMousePress(QPointF pos, bool &startGesture, bool &acceptClick)
+{
+ Q_UNUSED(pos);
+ startGesture = m_active;
+ acceptClick = !m_ticker.isActive();
+ if (m_ticker.isActive()) {
+ m_ticker.stop();
+ m_speed = 0.0;
+ }
+}
+
+void ShoppingListScrollBox::gestureStart(QPointF pos)
+{
+ m_startPoint = pos;
+}
+
+void ShoppingListScrollBox::contentPositionUpdated()
+{
+ qreal max = m_content->boundingRect().height();
+
+ QPointF delta = boundingRect().topLeft() - mapFromItem(m_content, QPointF(0, 0));
+ qreal cur = delta.y();
+
+ qreal step = boundingRect().height();
+
+ emit updated(max, cur, step);
+}
+
+bool ShoppingListScrollBox::move(QPointF movement)
+{
+ if (m_content && m_content->boundingRect().height() > boundingRect().height()) {
+
+ qreal dist = movement.y();
+
+ if (dist > 0 && m_content->pos().y() < 0) {
+ qreal top = m_content->pos().y() + dist;
+ m_content->setPos(m_content->pos().x(), top > 0 ? 0 : top);
+ contentPositionUpdated();
+ return true;
+ }
+
+ if (dist < 0) {
+ qreal top = m_content->pos().y() + dist;
+ if (top + m_content->boundingRect().height() >= boundingRect().height()) {
+ m_content->setPos(m_content->pos().x(), top);
+ contentPositionUpdated();
+ return true;
+ }
+ }
+
+ }
+ return false;
+}
+
+void ShoppingListScrollBox::gestureMove(QPointF pos, QPointF movement, QPointF speed)
+{
+ Q_UNUSED(pos);
+ Q_UNUSED(speed);
+ move(movement);
+}
+
+void ShoppingListScrollBox::gestureEnd(QPointF pos, QPointF speed)
+{
+ qreal x = pos.x() - m_startPoint.x();
+ qreal y = pos.y() - m_startPoint.y();
+ if (fabs(x / y) > limit_angle_tg || fabs(y) < min_gesture_length)
+ return;
+
+ qreal topSpeed = DesignInformation::getVerticalSize("list.vertical_speed");
+ m_acceleration = topSpeed / acceleration_factor;
+ m_speed = qBound(-topSpeed, speed.y(), topSpeed);
+ if (m_speed != 0) {
+ m_time = QTime::currentTime();
+ m_ticker.start(20, this);
+ }
+}
+
+void ShoppingListScrollBox::timerEvent(QTimerEvent *event)
+{
+ bool stopTimer = true;
+ if (m_speed != 0.0) {
+ QTime now(QTime::currentTime());
+ qreal movement = m_speed * (qreal)m_time.msecsTo(now) / 1000.0;
+ m_time = now;
+ stopTimer = !move(QPointF(0, movement));
+ if (!stopTimer) {
+ m_speed = m_speed > 0.0 ? qMax(qreal(0.0), m_speed - m_acceleration)
+ : qMin(qreal(0.0), m_speed + m_acceleration);
+ stopTimer = m_speed == 0.0;
+ }
+ }
+ if (stopTimer)
+ m_ticker.stop();
+ QObject::timerEvent(event);
+}
+
+// ShoppingListCategoryUI
+
+ShoppingListCategoryUI::ShoppingListCategoryUI(const QString &category, QGraphicsItem *parent)
+ : QGraphicsRectItem(parent)
+ , m_pic(0)
+ , m_header(0)
+ , m_background(0)
+ , m_shoppingList(0)
+ , m_scroll(0)
+ , m_scrollBox(0)
+ , m_popup(0)
+ , m_shadow(0)
+ , m_category(category)
+{
+ setFlag(QGraphicsItem::ItemHasNoContents, true);
+
+ m_background = new QGraphicsPixmapItem(this);
+ m_pic = new QGraphicsPixmapItem(this);
+ m_header = new QGraphicsPixmapItem(this);
+ m_feather = new QGraphicsPixmapItem(this);
+ m_shoppingList = new ShoppingList(0);
+ m_scrollBox = new ShoppingListScrollBox(m_shoppingList, this);
+ m_shadow = new ListShadow(this);
+ m_scroll = new ScrollBar(this);
+
+ m_shadow->setZValue(3);
+ m_background->setZValue(0);
+ m_pic->setZValue(1);
+ m_header->setZValue(1);
+ m_feather->setZValue(2);
+ m_scrollBox->setZValue(1);
+ m_scroll->setZValue(2);
+
+ connect(m_shoppingList, SIGNAL(completed()), this, SLOT(showPopup()));
+
+ updateUI();
+}
+
+void ShoppingListCategoryUI::updateUI()
+{
+ m_shadow->setPixmap(DesignInformation::getPixmap("category.shadow." + m_category));
+ m_shadow->setPos(DesignInformation::getPosition("category.shadow"));
+
+ m_background->setPixmap(DesignInformation::getPixmap("category.background"));
+ m_background->setPos(DesignInformation::getPosition("category.background"));
+
+ m_pic->setPixmap(DesignInformation::getPixmap("category.pic." + m_category));
+ m_pic->setPos(DesignInformation::getPosition("category.pic"));
+
+ m_header->setPixmap(DesignInformation::getPixmap("category.header." + m_category));
+ m_header->setPos(DesignInformation::getPosition("category.header"));
+
+ m_feather->setPixmap(DesignInformation::getPixmap("category.feather"));
+ m_feather->setPos(DesignInformation::getPosition("category.feather"));
+
+ QPointF listPos = DesignInformation::getPosition("category.list");
+
+ qreal listHeight = DesignInformation::getVerticalSize("category.list_height");
+
+ m_scrollBox->setRect(listPos.x(), listPos.y(),
+ m_background->pixmap().width() - listPos.x(), listHeight);
+
+ m_shoppingList->setPos(0.0, 0.0);
+ m_shoppingList->setWidth(m_background->pixmap().width() - listPos.x());
+
+ setRect(0, 0, m_background->pixmap().width(), listPos.y() + listHeight);
+
+ m_scroll->setPos(DesignInformation::getPosition("category.scrollbar"));
+ m_scroll->updateUI();
+
+ for (int i = 0; i < m_shoppingList->itemCount(); ++i) {
+ ShoppingListItem *item = dynamic_cast<ShoppingListItem*>(m_shoppingList->getItem(i));
+ if (item)
+ item->updateUI();
+ }
+ m_shoppingList->updateItems();
+
+ if (m_popup)
+ m_popup->updateUI();
+}
+
+void ShoppingListCategoryUI::updated(qreal max, qreal cur, qreal step)
+{
+ m_scroll->setMaximum(max - step);
+ m_scroll->updatePosition(cur);
+}
+
+void ShoppingListCategoryUI::showPopup()
+{
+ if (m_popup)
+ return;
+
+ m_popup = new PopUp(this);
+ m_popup->setZValue(10);
+
+ connect(m_popup, SIGNAL(listStartAgain()), this, SLOT(clearList()));
+ connect(m_popup, SIGNAL(deletePopUp()), this, SLOT(hidePopup()));
+ setCompleted(true);
+}
+
+void ShoppingListCategoryUI::clearList()
+{
+ m_shoppingList->clearChecks();
+ hidePopup();
+}
+
+void ShoppingListCategoryUI::hidePopup()
+{
+ if (!m_popup)
+ return;
+ setCompleted(false);
+ m_popup->deleteLater();
+ m_popup = 0;
+}
+
+void ShoppingListCategoryUI::updateListState()
+{
+ m_scrollBox->setActive(m_shadow->focused() && !m_shadow->completed());
+ m_shoppingList->setActive(m_shadow->focused() && !m_shadow->completed());
+
+}
+
+void ShoppingListCategoryUI::setFocused(bool focused)
+{
+ m_shadow->setFocused(focused);
+ updateListState();
+}
+
+void ShoppingListCategoryUI::setCompleted(bool completed)
+{
+ m_shadow->setCompleted(completed);
+ updateListState();
+}
diff --git a/shoplist/src/shoppinglistcategoryui.h b/shoplist/src/shoppinglistcategoryui.h
new file mode 100644
index 0000000..195fd3e
--- /dev/null
+++ b/shoplist/src/shoppinglistcategoryui.h
@@ -0,0 +1,81 @@
+#ifndef SHOPPINGLISTCATEGORYUI_H
+#define SHOPPINGLISTCATEGORYUI_H
+
+#include <QObject>
+#include <QGraphicsRectItem>
+#include <QGraphicsPixmapItem>
+#include <QBasicTimer>
+#include <QTime>
+#include "shoppinglist.h"
+#include "scrollbar.h"
+#include "gesturebox.h"
+#include "popup.h"
+#include "listshadow.h"
+
+class ShoppingListScrollBox : public QObject, public GestureBox
+{
+ Q_OBJECT
+public:
+ ShoppingListScrollBox(QGraphicsItem *content, QGraphicsItem *parent = 0);
+ void setActive(bool active) { m_active = active; }
+ bool active() const { return m_active; }
+
+signals:
+ void updated(qreal, qreal, qreal);
+
+protected:
+ void gestureMousePress(QPointF pos, bool &startGesture, bool &acceptClick);
+ void gestureStart(QPointF pos);
+ void gestureMove(QPointF pos, QPointF movement, QPointF speed);
+ void gestureEnd(QPointF pos, QPointF speed);
+
+ void timerEvent(QTimerEvent *event);
+
+private:
+ QGraphicsItem * const m_content;
+ QBasicTimer m_ticker;
+ qreal m_speed;
+ qreal m_acceleration;
+ QTime m_time;
+ bool m_active;
+ QPointF m_startPoint;
+ bool move(QPointF movement);
+ void contentPositionUpdated();
+};
+
+class ShoppingListCategoryUI : public QObject, public QGraphicsRectItem
+{
+ Q_OBJECT
+public:
+ ShoppingListCategoryUI(const QString &category, QGraphicsItem *parent = 0);
+ ShoppingList *list() { return m_shoppingList; }
+ void updateUI();
+
+ bool focused() const { return m_shadow->focused(); }
+ void setFocused(bool focused);
+
+public slots:
+ void updated(qreal, qreal, qreal);
+
+private:
+ QGraphicsPixmapItem *m_pic;
+ QGraphicsPixmapItem *m_header;
+ QGraphicsPixmapItem *m_background;
+ QGraphicsPixmapItem *m_feather;
+ ShoppingList *m_shoppingList;
+ ScrollBar* m_scroll;
+ ShoppingListScrollBox *m_scrollBox;
+ PopUp *m_popup;
+ ListShadow *m_shadow;
+ const QString m_category;
+
+ void updateListState();
+ void setCompleted(bool completed);
+
+private slots:
+ void showPopup();
+ void hidePopup();
+ void clearList();
+};
+
+#endif // SHOPPINGLISTCATEGORYUI_H
diff --git a/shoplist/src/shoppinglistview.cpp b/shoplist/src/shoppinglistview.cpp
new file mode 100644
index 0000000..9867574
--- /dev/null
+++ b/shoplist/src/shoppinglistview.cpp
@@ -0,0 +1,79 @@
+#include "shoppinglistview.h"
+
+#include <QApplication>
+#include <QDesktopWidget>
+
+ShoppingListView::ShoppingListView(MainContainer *container)
+ : m_mainContainer(container)
+{
+ setRenderHints(QPainter::TextAntialiasing);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setFrameShape(QFrame::NoFrame);
+ setWindowTitle("Shopping List");
+ setViewportUpdateMode(BoundingRectViewportUpdate);
+
+}
+
+void ShoppingListView::keyPressEvent(QKeyEvent *event)
+{
+ event->ignore();
+ if (event->key() == Qt::Key_F5)
+ adjustScreenSize();
+ if (event->key() == Qt::Key_Left)
+ m_mainContainer->moveLeft();
+ if (event->key() == Qt::Key_Right)
+ m_mainContainer->moveRight();
+}
+
+void ShoppingListView::adjustScreenSize()
+{
+
+ QSizeF screenSize(QApplication::desktop()->screenGeometry().size());
+ if (screenSize.width() > 480)
+ screenSize.setWidth(480);
+ if (screenSize.height() > 864)
+ screenSize.setHeight(864);
+
+ /*
+#ifdef Q_OS_SYMBIAN
+ QSizeF screenSize(QApplication::desktop()->screenGeometry().size());
+#else
+ QSizeF screenSize(geometry().size());
+#endif
+ */
+ DesignInformation::setScreenSize(screenSize);
+ setGeometry(0, 0, screenSize.width(), screenSize.height());
+ if (scene())
+ scene()->setSceneRect(0.0, 0.0, screenSize.width(), screenSize.height());
+ centerOn(m_mainContainer);
+ m_mainContainer->updateUI();
+}
+
+void ShoppingListView::adjustScalingFactor()
+{
+
+ QSizeF screenSize(QApplication::desktop()->screenGeometry().size());
+ if (screenSize.width() > 480)
+ screenSize.setWidth(480);
+ if (screenSize.height() > 864)
+ screenSize.setHeight(864);
+
+ /*
+#ifdef Q_OS_SYMBIAN
+ QSizeF screenSize(QApplication::desktop()->screenGeometry().size());
+#else
+ QSizeF screenSize(geometry().size());
+#endif
+*/
+ screenSize.setWidth(qMin(int(screenSize.width()), 480));
+ screenSize.setHeight(qMin(int(screenSize.height()), 864));
+ DesignInformation::setScaleFactor(DesignInformation::getScaleFactor(screenSize));
+}
+
+void ShoppingListView::resized(int screen)
+{
+ Q_UNUSED(screen);
+ adjustScreenSize();
+}
+
diff --git a/shoplist/src/shoppinglistview.h b/shoplist/src/shoppinglistview.h
new file mode 100644
index 0000000..4e35dee
--- /dev/null
+++ b/shoplist/src/shoppinglistview.h
@@ -0,0 +1,26 @@
+#ifndef SHOPPINGLISTVIEW_H
+#define SHOPPINGLISTVIEW_H
+
+#include <QGraphicsView>
+#include "maincontainer.h"
+#include "designinformation.h"
+
+class ShoppingListView : public QGraphicsView
+{
+ Q_OBJECT
+public:
+ ShoppingListView(MainContainer *container);
+ void adjustScreenSize();
+ void adjustScalingFactor();
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+
+private:
+ MainContainer *m_mainContainer;
+
+private slots:
+ void resized(int screen);
+};
+
+#endif // SHOPPINGLISTVIEW_H
diff --git a/shoplist/src/src.pri b/shoplist/src/src.pri
new file mode 100644
index 0000000..a20ff8f
--- /dev/null
+++ b/shoplist/src/src.pri
@@ -0,0 +1,22 @@
+HEADERS = src/scrollbar.h \
+ src/maincontainer.h \
+ src/designinformation.h \
+ src/contentlist.h \
+ src/shoppinglist.h \
+ src/shoppinglistcategoryui.h \
+ src/popup.h \
+ src/gesturebox.h \
+ src/listshadow.h \
+ src/gesturebox_p.h \
+ src/shoppinglistview.h
+SOURCES = src/scrollbar.cpp \
+ src/main.cpp \
+ src/maincontainer.cpp \
+ src/contentlist.cpp \
+ src/designinformation.cpp \
+ src/shoppinglist.cpp \
+ src/shoppinglistcategoryui.cpp \
+ src/popup.cpp \
+ src/gesturebox.cpp \
+ src/listshadow.cpp \
+ src/shoppinglistview.cpp