--- a/homescreenapp/hsdomainmodel/src/hspage.cpp Tue Jul 06 14:06:53 2010 +0300
+++ b/homescreenapp/hsdomainmodel/src/hspage.cpp Wed Aug 18 09:40:07 2010 +0300
@@ -19,15 +19,18 @@
#include "hsdomainmodeldatastructures.h"
#include "hspage.h"
+#include "hspagevisual.h"
#include "hspagetoucharea.h"
#include "hspagenewwidgetlayout.h"
#include "hsscene.h"
#include "hsdatabase.h"
#include "hswidgethost.h"
+#include "hswidgethostvisual.h"
#include "hswallpaper.h"
#include "hswidgetpositioningonwidgetadd.h"
#include "hswidgetpositioningonorientationchange.h"
#include "hsconfiguration.h"
+#include "hsgui.h"
/*!
@@ -43,18 +46,18 @@
\a parent Owner.
\a aFlags Window flags.
*/
-HsPage::HsPage(QGraphicsItem* parent)
- : HbWidget(parent),
+HsPage::HsPage(QObject* parent)
+ : QObject(parent),
mDatabaseId(-1),
+ mPageVisual(new HsPageVisual),
mWallpaper(0),
mRemovable(true),
- mTouchArea(0)
+ mPageMargin(0.0)
{
- setFlag(QGraphicsItem::ItemHasNoContents);
- setSizePolicy(QSizePolicy(QSizePolicy::Ignored,
- QSizePolicy::Ignored));
-
- setupTouchArea();
+
+ //Page margin
+ mPageMargin = HSCONFIGURATION_GET(pageMargin);
+ connect(HsConfiguration::instance(), SIGNAL(propertyChanged(QString)), SLOT(onPageMarginChanged(QString)));
}
/*!
@@ -62,6 +65,36 @@
*/
HsPage::~HsPage()
{
+ // visuals are owned by widget host, detach those from page visual
+ HsWidgetHostVisual *visual(0);
+ foreach (HsWidgetHost *widget, mWidgets) {
+ visual = widget->visual();
+ visual->setParent(0);
+ if (visual->scene()) {
+ visual->scene()->removeItem(visual);
+ }
+ }
+
+ foreach (HsWidgetHost *widget, mNewWidgets) {
+ visual = widget->visual();
+ visual->setParent(0);
+ if (visual->scene()) {
+ visual->scene()->removeItem(visual);
+ }
+ }
+
+ foreach (HsWidgetHost *widget, mUnavailableWidgets) {
+ visual = widget->visual();
+ visual->setParent(0);
+ if (visual->scene()) {
+ visual->scene()->removeItem(visual);
+ }
+ }
+ qDeleteAll(mWidgets);
+ qDeleteAll(mNewWidgets);
+ qDeleteAll(mUnavailableWidgets);
+
+ delete mPageVisual;
delete mWallpaper;
}
@@ -80,7 +113,7 @@
{
mDatabaseId = id;
}
-
+/*
void HsPage::setGeometry(const QRectF &rect)
{
if (mTouchArea) {
@@ -89,7 +122,7 @@
HbWidget::setGeometry(rect);
}
-
+*/
/*!
Loads widgets.
*/
@@ -112,14 +145,23 @@
foreach (HsWidgetData data, datas) {
HsWidgetHost *widget = new HsWidgetHost(data.id);
- mWidgets.append(widget);
- connectWidget(widget);
- widget->setPage(this);
- widget->setParentItem(this);
- widget->startWidget(isDefaultPage());
+ if (!widget->loadPresentation(Qt::Horizontal) &&
+ !widget->loadPresentation(Qt::Vertical)) {
+ widget->setPage(this);
+ widget->visual()->hide();
+ connectWidget(widget);
+ mNewWidgets << widget;
+ }
+ else {
+ mWidgets.append(widget);
+ connectWidget(widget);
+ widget->setPage(this);
+ widget->visual()->setParentItem(this->visual());
+ widget->startWidget(isDefaultPage());
+ }
}
- connect(HsScene::mainWindow(),
+ connect(HsGui::instance(),
SIGNAL(orientationChanged(Qt::Orientation)),
SLOT(onOrientationChanged(Qt::Orientation)));
@@ -127,7 +169,7 @@
}
/*!
- Return wallpaper.
+ Return wallpaper.
*/
HsWallpaper *HsPage::wallpaper() const
{
@@ -152,10 +194,11 @@
connectWidget(widgetHost);
mWidgets << widgetHost;
- widgetHost->setParentItem(this);
+ widgetHost->visual()->setParentItem(visual());
return true;
}
+
/*!
Remove given \a widgetHost from a page. Widget is not deleted.
Returns true if successful
@@ -168,10 +211,11 @@
disconnectWidget(widgetHost);
mWidgets.removeOne(widgetHost);
- widgetHost->setParentItem(0);
+ widgetHost->visual()->setParentItem(0);
return true;
}
+
/*!
Returns list of new widgets belonging to a page. Widgets which are
not yet layouted are considered as new widgets.
@@ -195,19 +239,10 @@
if (mNewWidgets.contains(widgetHost)) {
return true;
}
+
+ widgetHost->setPage(this);
- HsWidgetPresentationData presentation;
- presentation.orientation = HsScene::orientation();
- if (!widgetHost->getPresentation(presentation)) {
- presentation.orientation = HsScene::orientation();
- presentation.setPos(mTouchPoint);
- presentation.zValue = 0;
- widgetHost->savePresentation(presentation);
- }
-
- widgetHost->hide();
- widgetHost->setPos(presentation.x, presentation.y);
- widgetHost->setZValue(presentation.zValue);
+ widgetHost->visual()->hide();
connectWidget(widgetHost);
mNewWidgets << widgetHost;
@@ -224,10 +259,10 @@
return;
}
- HsPageNewWidgetLayout *newWidgetLayout = static_cast<HsPageNewWidgetLayout *>(layout());
+ HsPageNewWidgetLayout *newWidgetLayout = static_cast<HsPageNewWidgetLayout *>(visual()->layout());
if (!newWidgetLayout) {
newWidgetLayout = new HsPageNewWidgetLayout(mTouchPoint);
- setLayout(newWidgetLayout);
+ visual()->setLayout(newWidgetLayout);
}
updateZValues();
HsWidgetHost *widget = 0;
@@ -235,36 +270,67 @@
widget = mNewWidgets.at(i);
newWidgetLayout->addItem(widget);
widget->setPage(this);
- widget->setParentItem(this);
+ widget->visual()->setParentItem(visual());
widget->showWidget();
- widget->show();
+ widget->visual()->show();
}
mWidgets << mNewWidgets;
mNewWidgets.clear();
}
/*!
+ Clears new widgets list and resets layout.
+*/
+void HsPage::resetNewWidgets()
+{
+ mNewWidgets.clear();
+ visual()->setLayout(0);
+}
+
+/*!
Remove page and all it's contained widgets from database
*/
bool HsPage::deleteFromDatabase()
{
+
+ HsWidgetHostVisual *visual(0);
foreach (HsWidgetHost *widget, mWidgets) {
+ visual = widget->visual();
+ visual->setParent(0);
+ if (visual->scene()) {
+ visual->scene()->removeItem(visual);
+ }
widget->remove();
}
mWidgets.clear();
+
foreach (HsWidgetHost *widget, mNewWidgets) {
+ visual = widget->visual();
+ visual->setParent(0);
+ if (visual->scene()) {
+ visual->scene()->removeItem(visual);
+ }
widget->remove();
}
mNewWidgets.clear();
foreach (HsWidgetHost *widget, mUnavailableWidgets) {
+ visual = widget->visual();
+ visual->setParent(0);
+ if (visual->scene()) {
+ visual->scene()->removeItem(visual);
+ }
widget->remove();
}
mUnavailableWidgets.clear();
-
+
+ if (mWallpaper) {
+ mWallpaper->remove();
+ }
return HsDatabase::instance()->deletePage(mDatabaseId);
}
+
/*!
Return list of widgets belonging to a page
*/
@@ -289,6 +355,7 @@
{
mRemovable = removable;
}
+
/*!
Return true if page is default page.
*/
@@ -296,6 +363,7 @@
{
return mDatabaseId == HSCONFIGURATION_GET(defaultPageId);
}
+
/*!
Return true if page is active page.
*/
@@ -303,6 +371,7 @@
{
return this == HsScene::instance()->activePage();
}
+
/*!
Create page into database and return instance of a new page.
*/
@@ -322,12 +391,75 @@
}
/*!
+ The widget is bounded in the rectangle which is smaller by pageMargin on all sides of page.
+*/
+QPointF HsPage::adjustedWidgetPosition(const QRectF &origWidgetRect)
+{
+ QRectF widgetAreaRect = contentGeometry();
+ qreal widgetX = qBound(widgetAreaRect.left(), origWidgetRect.x(), widgetAreaRect.right() - origWidgetRect.width());
+ qreal widgetY = qBound(widgetAreaRect.top(), origWidgetRect.y(), widgetAreaRect.bottom() - origWidgetRect.height());
+
+ return QPointF(widgetX, widgetY);
+}
+
+/*!
+ Returns rect of rectangular where widgets are allowed to be placed in the page.
+*/
+QRectF HsPage::contentGeometry()
+{
+ return contentGeometry(HsGui::instance()->orientation());
+}
+
+/*!
+ Returns rect of rectangular where widgets are allowed to be placed in the page.
+*/
+QRectF HsPage::contentGeometry(Qt::Orientation orientation)
+{
+ QRectF pageRect = HsGui::instance()->layoutRect();
+
+ if (orientation != HsGui::instance()->orientation()) {
+ qreal width = pageRect.width();
+ qreal height = pageRect.height();
+ pageRect.setWidth(height);
+ pageRect.setHeight(width);
+ }
+
+ //Take care of chrome in both orientation
+ pageRect.setTop(64);
+
+ //Shrink by page margins at each side
+ return pageRect.adjusted(mPageMargin, mPageMargin, -mPageMargin, -mPageMargin);
+}
+
+/*!
+ Returns rect of rectangular where widgets are allowed to be placed in the page.
+*/
+QRectF HsPage::contentRect()
+{
+ return contentRect(HsGui::instance()->orientation());
+}
+
+/*!
+ Returns rect of rectangular where widgets are allowed to be placed in the page.
+*/
+QRectF HsPage::contentRect(Qt::Orientation orientation)
+{
+ QRectF rect = contentGeometry(orientation);
+ rect.moveTopLeft(QPointF(0,0));
+ return rect;
+}
+
+HsPageVisual *HsPage::visual() const
+{
+ return mPageVisual;
+}
+/*!
Calls onShow() for contained widgets.
*/
void HsPage::showWidgets()
{
foreach (HsWidgetHost *widget, mWidgets) {
- if (widget->parentItem() == this) {
+ if (widget->visual()->parentItem() == visual()) {
widget->showWidget();
}
}
@@ -339,14 +471,14 @@
void HsPage::hideWidgets()
{
foreach (HsWidgetHost *widget, mWidgets) {
- if (widget->parentItem() == this) {
+ if (widget->visual()->parentItem() == visual()) {
widget->hideWidget();
}
}
}
/*!
- Propogate online state to widgets.
+ Propagate online state to widgets.
*/
void HsPage::setOnline(bool online)
{
@@ -357,6 +489,7 @@
widget->setOnline(online);
}
}
+
/*!
Update widgets z-values and persist those. Active widget has top most
z-value.
@@ -368,7 +501,7 @@
if (!mWidgets.isEmpty()) {
QMultiMap<qreal, HsWidgetHost *> map;
foreach (HsWidgetHost *widget, mWidgets) {
- map.insert(widget->zValue(), widget);
+ map.insert(widget->visual()->zValue(), widget);
}
QList<HsWidgetHost *> sortedWidgets = map.values();
@@ -380,14 +513,14 @@
}
foreach (HsWidgetHost *widget, sortedWidgets) {
- widget->setZValue(z++);
+ widget->visual()->setZValue(z++);
widget->savePresentation();
}
}
if (!mNewWidgets.isEmpty()) {
foreach (HsWidgetHost *widget, mNewWidgets) {
- widget->setZValue(z++);
+ widget->visual()->setZValue(z++);
widget->savePresentation();
}
}
@@ -402,11 +535,11 @@
/*!
Create touch area for page.
*/
-void HsPage::setupTouchArea()
+/*void HsPage::setupTouchArea()
{
mTouchArea = new HsPageTouchArea(this);
mTouchArea->setZValue(-1);
-}
+}*/
/*!
Utility to connect widget signals to page.
*/
@@ -414,7 +547,7 @@
{
connect(widget, SIGNAL(finished()), SLOT(onWidgetFinished()));
connect(widget, SIGNAL(faulted()), SLOT(onWidgetFaulted()));
- connect(widget, SIGNAL(resized()), SLOT(onWidgetResized()));
+ connect(widget->visual(), SIGNAL(resized()), SLOT(onWidgetResized()));
connect(widget, SIGNAL(available()), SLOT(onWidgetAvailable()));
connect(widget, SIGNAL(unavailable()), SLOT(onWidgetUnavailable()));
}
@@ -423,6 +556,7 @@
*/
void HsPage::disconnectWidget(HsWidgetHost *widget)
{
+ widget->visual()->disconnect(this);
widget->disconnect(this);
}
/*!
@@ -437,6 +571,14 @@
if (!mNewWidgets.removeOne(widget)) {
mWidgets.removeOne(widget);
}
+ if (widget){
+ HsWidgetHostVisual *visual = widget->visual();
+ visual->setParentItem(0);
+ if (visual->scene()) {
+ visual->scene()->removeItem(visual);
+ }
+ }
+
disconnectWidget(widget);
widget->remove();
@@ -455,15 +597,11 @@
*/
void HsPage::onWidgetResized()
{
- if ( !layout() ) {
- HsWidgetHost *widget = qobject_cast<HsWidgetHost *>(sender());
- QRectF widgetRect = widget->geometry();
- QRectF pageRect = HsScene::mainWindow()->layoutRect();
- qreal widgetX = qBound(qreal(0), widgetRect.x(), pageRect.width() - widgetRect.width());
- qreal widgetY = qBound(qreal(64), widgetRect.y(), pageRect.height() - widgetRect.height());
- widget->setPos(widgetX, widgetY);
+ if (!visual()->layout()) {
+ HsWidgetHostVisual *widgetVisual = qobject_cast<HsWidgetHostVisual *>(sender());
+ widgetVisual->setPos(adjustedWidgetPosition(widgetVisual->geometry()));
} else {
- layout()->invalidate();
+ visual()->layout()->invalidate();
}
}
/*!
@@ -472,13 +610,14 @@
void HsPage::onWidgetAvailable()
{
HsWidgetHost *widget = qobject_cast<HsWidgetHost *>(sender());
+ HsWidgetHostVisual *widgetVisual(widget->visual());
mUnavailableWidgets.removeOne(widget);
mWidgets.append(widget);
- widget->setParentItem(this);
+ widgetVisual->setParentItem(visual());
widget->startWidget(isActivePage());
- widget->show();
+ widgetVisual->show();
}
/*!
Update internal bookkeeping and hide widget
@@ -486,6 +625,7 @@
void HsPage::onWidgetUnavailable()
{
HsWidgetHost *widget = qobject_cast<HsWidgetHost *>(sender());
+ HsWidgetHostVisual *widgetVisual(widget->visual());
if (mWidgets.contains(widget)) {
mWidgets.removeOne(widget);
@@ -497,46 +637,154 @@
mUnavailableWidgets.append(widget);
- widget->hide();
- widget->setParentItem(0);
+ widgetVisual->hide();
+ widgetVisual->setParentItem(0);
}
+
/*!
Run positioning algorithm for widgets which don't have position on
target orientation. Otherwise set orientation positions for widgets.
*/
void HsPage::onOrientationChanged(Qt::Orientation orientation)
{
- QRectF rect = HsScene::mainWindow()->layoutRect();
-
HsWidgetPositioningOnOrientationChange *converter =
HsWidgetPositioningOnOrientationChange::instance();
- qreal chrome = 64;
- QRectF from(0, chrome, rect.height(), rect.width() - chrome);
- QRectF to(0, chrome, rect.width(), rect.height() - chrome);
+ Qt::Orientation orientationFrom = orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical;
+ QRectF from = contentGeometry(orientationFrom);
+ QRectF to = contentGeometry(orientation);
HsWidgetPresentationData presentation;
presentation.orientation = orientation;
-
+
+ HsWidgetHostVisual *visual(0);
+#ifdef HSWIDGETORGANIZER_ALGORITHM
+ QList<HsWidgetHost*> newWidgets;
+#endif //HSWIDGETORGANIZER_ALGORITHM
foreach (HsWidgetHost *widget, mWidgets) {
+ visual = widget->visual();
if (!widget->getPresentation(presentation)) {
+#ifndef HSWIDGETORGANIZER_ALGORITHM
QList<QRectF> geometries = converter->convert(
- from, QList<QRectF>() << widget->geometry(), to);
- widget->setGeometry(geometries.first());
+ from, QList<QRectF>() << visual->geometry(), to);
+ visual->setGeometry(geometries.first());
widget->savePresentation();
+#else //HSWIDGETORGANIZER_ALGORITHM
+ newWidgets << widget;
+#endif //HSWIDGETORGANIZER_ALGORITHM
} else {
- widget->setPos(presentation.pos());
- widget->setZValue(presentation.zValue);
+ QRectF adjustWidgetPosition;
+ adjustWidgetPosition = visual->geometry();
+ adjustWidgetPosition.moveTopLeft(presentation.pos());
+ visual->setPos(adjustedWidgetPosition(adjustWidgetPosition));
+ visual->setZValue(presentation.zValue);
+ widget->savePresentation(); //Needed to follow pageMargin dynamic change
+ }
+ }
+
+#ifdef HSWIDGETORGANIZER_ALGORITHM
+ // sort new widgets in order
+ if (newWidgets.count()) {
+ // TODO: read from configuration? or just use height for portrait and width for landscape (currently only height is used)
+ sortOrder order(height);
+ if(orientation == Qt::Horizontal) {
+ order = width;
+ }
+ sortWidgets(order, newWidgets);
+ // get rects for new widgets
+ QList<QRectF> newRects;
+ foreach (HsWidgetHost *newWidget, newWidgets) {
+ newRects << QRectF(QPointF(), newWidget->visual()->preferredSize());
+ }
+
+ // get page rect
+ QRectF pageRect = contentGeometry();
+
+ // scan existing widgets rects
+ QList<QRectF> existingRects;
+ foreach (HsWidgetHost *widget, mWidgets) {
+ if (!newWidgets.contains(widget)) {
+ existingRects << QRectF(widget->visual()->pos(), widget->visual()->preferredSize());
+ }
+ }
+
+ // calculate new widget positions with "stuck 'em all"-algorithm
+ HsWidgetPositioningOnWidgetAdd *algorithm =
+ HsWidgetPositioningOnWidgetAdd::instance();
+ QList<QRectF> calculatedRects =
+ algorithm->convert(pageRect, existingRects, newRects, QPointF());
+
+ for ( int i=0; i<newWidgets.count(); i++) {
+ int j = mWidgets.indexOf(newWidgets.at(i));
+ mWidgets.at(j)->visual()->setGeometry(calculatedRects.at(i));
+ mWidgets.at(j)->savePresentation();
+ }
+ }
+#endif //HSWIDGETORGANIZER_ALGORITHM
+
+}
+
+void HsPage::onPageMarginChanged(const QString &value)
+{
+ if (value == "pageMargin") {
+ mPageMargin = HSCONFIGURATION_GET(pageMargin);
+ HsWidgetHostVisual *visual(0);
+ if (!mWidgets.isEmpty()) {
+ foreach (HsWidgetHost *widget, mWidgets) {
+ visual = widget->visual();
+ visual->setPos(adjustedWidgetPosition(visual->geometry()));
+ widget->savePresentation();
+ }
+ }
+
+ if (!mNewWidgets.isEmpty()) {
+ foreach (HsWidgetHost *widget, mNewWidgets) {
+ visual = widget->visual();
+ visual->setPos(adjustedWidgetPosition(visual->geometry()));
+ widget->savePresentation();
+ }
}
}
}
-
+#ifdef HSWIDGETORGANIZER_ALGORITHM
+// TODO: sorting should be done in algorithm class, make widget<->rect mapping here and move sortWidgets function to algorithm side
/*!
- Clears new widgets list and resets layout.
+ Sorts widgets in height/width order
*/
-void HsPage::resetNewWidgets()
+void HsPage::sortWidgets(sortOrder order, QList<HsWidgetHost*> &widgets)
{
- mNewWidgets.clear();
- setLayout(0);
+ QList<HsWidgetHost*> tmpWidgets;
+
+ for ( int i = 0; i < widgets.count(); i++) {
+ int index = 0;
+ // add first widget to sorted list
+ if (i == 0) {
+ tmpWidgets << widgets.at(i);
+ } else {
+ // go through existing widgets in the sorted list
+ for ( int j = 0; j < tmpWidgets.count(); j++) {
+ // sort widgets in height order
+ if (order == height) {
+ /* if widgets heigth is smaller on already
+ existing ones in the list -> increment index
+ */
+ if (widgets.at(i)->visual()->preferredHeight() <= tmpWidgets.at(j)->visual()->preferredHeight()) {
+ index++;
+ }
+ // sort widgets in width order
+ } else {
+ /* if widgets width is smaller on already
+ existing ones in the sorted list -> increment index
+ */
+ if (widgets.at(i)->visual()->preferredWidth() <= tmpWidgets.at(j)->visual()->preferredWidth()) {
+ index++;
+ }
+ }
+ }
+ // add widget to its correct index in sorted list
+ tmpWidgets.insert(index, widgets.at(i));
+ }
+ }
+ widgets = tmpWidgets;
}
-
+#endif //HSWIDGETORGANIZER_ALGORITHM