src/hbcore/layouts/hbanchorlayout.cpp
changeset 7 923ff622b8b9
parent 6 c3690ec91ef8
child 21 4633027730f5
equal deleted inserted replaced
6:c3690ec91ef8 7:923ff622b8b9
    22 ** Nokia at developer.feedback@nokia.com.
    22 ** Nokia at developer.feedback@nokia.com.
    23 **
    23 **
    24 ****************************************************************************/
    24 ****************************************************************************/
    25 
    25 
    26 #include "hbanchorlayout.h"
    26 #include "hbanchorlayout.h"
       
    27 #include "hbanchor.h"
    27 #include "hbanchor_p.h"
    28 #include "hbanchor_p.h"
    28 #include "hbanchorlayoutdebug_p.h"
       
    29 #include "hbanchorlayoutengine_p.h"
    29 #include "hbanchorlayoutengine_p.h"
    30 
    30 
    31 #include <QLayout>
    31 #include <QLayout>
    32 #include <QDebug>
    32 #include <QDebug>
    33 
    33 
    36 
    36 
    37 //Uncomment next define in order to get more debug prints.
    37 //Uncomment next define in order to get more debug prints.
    38 //Similar define exists also in the engine side.
    38 //Similar define exists also in the engine side.
    39 //#define HBANCHORLAYOUT_DEBUG
    39 //#define HBANCHORLAYOUT_DEBUG
    40 
    40 
    41 #ifdef HBANCHORLAYOUT_DEBUG
       
    42 #ifndef Q_WS_S60
       
    43 #include "hbspaceritem_p.h"
       
    44 #endif
       
    45 #endif
       
    46 
       
    47 /*!
    41 /*!
    48     \class HbAnchorLayout
    42     \class HbAnchorLayout
    49     \brief HbAnchorLayout manages geometries of its child items with anchors
    43     \brief HbAnchorLayout manages geometries of its child items with anchors
    50     that connect the layout items with each other.
    44     that connect the layout items with each other.
    51 
    45 
    52     It also allows layout items to be missing and can fix anchor attachments.
    46     It also allows layout items to be missing and can fix anchor attachments.
    53     Here are some simple rules how anchor fixation can be created (the example
    47     Here is an example and some simple rules how anchor fixing works (the example is
    54     is only for horizontal direction - the same needs to be done for portrait as well).
    48     only for horizontal direction - the same needs to be done for portrait as well).
    55 
    49 
    56     If anchors set allow ambiguos positioning of items, then layout tries to set items size as
    50     If anchors set allow ambiguos positioning of items, then layout tries to set items
    57     close to preferred as possible.
    51     size as close to preferred as possible.
    58 
    52 
    59     \image html hbmeshlayout1.png
    53     \image html hbanchorlayout1.png
    60 
    54 
    61     From the image above, we have decided that the green node is always present. This
    55     From the image above, we have decided that the green node is always present. This
    62     means that all the other nodes in the horizontal graph can be optional.
    56     means that all the other nodes in the horizontal graph can be optional.
    63 
    57 
    64     \image html hbmeshlayout2.png
    58     \image html hbanchorlayout2.png
    65 
    59 
    66     Then, we create the anchors starting from the non-optional node and point towards
    60     Then, we create the anchors starting from the non-optional node and point towards
    67     the edges of the layout. The mesh layout definition in the WidgetML would look like:
    61     the edges of the layout. The anchor layout definition in the WidgetML would look like:
    68 
    62 
    69     \code
    63     \code
    70 
    64 
    71     <meshitem src="green_item" srcEdge="LEFT" dst="blue_item" dstEdge="RIGHT" />
    65     <anchoritem srcId="green_item" srcEdge="LEFT" dstId="blue_item" dstEdge="RIGHT" />
    72     <meshitem src="blue_item" srcEdge="LEFT" dst="" dstEdge="LEFT" />
    66     <anchoritem srcId="blue_item" srcEdge="LEFT" dstId="" dstEdge="LEFT" />
    73     <meshitem src="green_item" srcEdge="RIGHT" dst="red_item" dstEdge="LEFT" />
    67     <anchoritem srcId="green_item" srcEdge="RIGHT" dstId="red_item" dstEdge="LEFT" />
    74     <meshitem src="red_item" srcEdge="RIGHT" dst="yellow_item" dstEdge="LEFT" />
    68     <anchoritem srcId="red_item" srcEdge="RIGHT" dstId="yellow_item" dstEdge="LEFT" />
    75     <meshitem src="yellow_item" srcEdge="RIGHT" dst="" dstEdge="RIGHT" />
    69     <anchoritem srcId="yellow_item" srcEdge="RIGHT" dstId="" dstEdge="RIGHT" />
    76 
    70 
    77     \endcode
    71     \endcode
    78 
    72 
    79     As mentioned, the green node needs be present always. In practice, this means that the
    73     As mentioned, the green node needs be present always. In practice, this means that the
    80     parent widget, which owns this anchor layout, needs to have a child widget with item
    74     parent widget, which owns this anchor layout, needs to have a child widget with item
    81     name "green_item". \c HbStyle::setItemName for more details.
    75     name "green_item". \c HbStyle::setItemName for more details.
    82 
    76 
    83     If an optional node is missing, the anchors pointing to the node are
    77     If an optional node is missing, the anchors pointing to the node are
    84     changed to point to the node after (=towards the parent layout) the missing one - this
    78     changed to point to the node after (=towards the parent layout) the missing one.
    85     is called "fixing the mesh".
    79 
    86 
    80     \image html hbanchorlayout3.png
    87     \image html hbmeshlayout3.png
       
    88 
    81 
    89     In the picture above, the blue and yellow items are missing. The anchor is fixed by removing
    82     In the picture above, the blue and yellow items are missing. The anchor is fixed by removing
    90     the anchor definitions starting from the missing nodes.
    83     the anchor definitions starting from the missing nodes.
    91 
    84 
    92     \stable
    85     \stable
   109 
   102 
   110 /*
   103 /*
   111     Type for mapping from layout item to node identifier.
   104     Type for mapping from layout item to node identifier.
   112     \internal
   105     \internal
   113 */
   106 */
   114 typedef QMap<QGraphicsLayoutItem*, QString> HbMeshItemMap;
   107 typedef QMap<QGraphicsLayoutItem*, QString> ItemToNodeIdMap;
   115 typedef HbMeshItemMap::iterator HbMeshItemMapIterator;
   108 typedef ItemToNodeIdMap::iterator ItemToNodeIdMapIterator;
   116 typedef HbMeshItemMap::const_iterator HbMeshItemMapConstIterator;
   109 typedef ItemToNodeIdMap::const_iterator ItemToNodeIdMapConstIterator;
   117 
   110 
   118 
   111 
   119 /*
   112 /*
   120     Result of findEndItem.
   113     Result of findEndItem.
   121 */
   114 */
   122 struct HbMeshEndItemResult
   115 struct HbFixedEndItemResult
   123 {
   116 {
   124     QGraphicsLayoutItem *mItem;
   117     QGraphicsLayoutItem *mItem;
   125     HbAnchorLayout::Edge mEdge;
   118     HbAnchorLayout::Edge mEdge;
   126     qreal mValue;
   119     qreal mMin;
       
   120     qreal mPref;
       
   121     qreal mMax;
       
   122     QSizePolicy::Policy mPolicy;
       
   123     HbAnchor::Direction mDirection;
   127 };
   124 };
   128 
   125 
   129 class HbAnchorLayoutPrivate
   126 class HbAnchorLayoutPrivate
   130 {
   127 {
   131 public:
   128 public:
   143     void createEquations( EdgeType type );
   140     void createEquations( EdgeType type );
   144 
   141 
   145     int getEdgeIndex(QGraphicsLayoutItem *item, Hb::Edge edge);
   142     int getEdgeIndex(QGraphicsLayoutItem *item, Hb::Edge edge);
   146 
   143 
   147     bool findEndItem(
   144     bool findEndItem(
   148         QList<HbMeshEndItemResult> &resultList,
   145         QList<HbFixedEndItemResult> &resultList,
   149         const HbAnchor *anchor,
   146         const HbAnchor *anchor,
   150         QStringList &ids) const;
   147         QStringList &ids) const;
   151     void resolveAnchors();
   148     void resolveAnchors();
   152     void removeItemIfNeeded( QGraphicsLayoutItem *item );
   149     void removeItemIfNeeded( QGraphicsLayoutItem *item );
   153 
   150 
   154     bool setAnchor( HbAnchor *anchor );
   151     HbAnchor *setAnchor( HbAnchor *anchor );
   155 
   152 
   156     void setSizeProp( SizeProperty *v, QGraphicsLayoutItem *item, EdgeType type );
   153     void setSizeProp( SizeProperty *v, QGraphicsLayoutItem *item, EdgeType type );
       
   154     void setSizeProp( SizeProperty *v, HbAnchor *item );
   157     GraphVertex *createCenterEdge( EdgeType type, QGraphicsLayoutItem *item,  Hb::Edge edge );
   155     GraphVertex *createCenterEdge( EdgeType type, QGraphicsLayoutItem *item,  Hb::Edge edge );
   158     void defineNextGeometry( const int itemIndexStart, const int itemIndexEnd, const int anchorIndex, const int definedItemIndex );
   156     void defineNextGeometry( const int itemIndexStart, const int itemIndexEnd, const int anchorIndex, const int definedItemIndex );
   159 
   157 
   160 
   158 
   161     QSizeF sizeHint(Qt::SizeHint which);
   159     QSizeF sizeHint(Qt::SizeHint which);
   171     QList<HbAnchor*> mAllAnchors; // anchors that are set by user
   169     QList<HbAnchor*> mAllAnchors; // anchors that are set by user
   172     QList<HbAnchor*> mResolvedDynamicAnchors; //  references to generated anchors
   170     QList<HbAnchor*> mResolvedDynamicAnchors; //  references to generated anchors
   173     QList<HbAnchor*> mResolvedStaticAnchors; // references to anchors, that remains the same after resolving
   171     QList<HbAnchor*> mResolvedStaticAnchors; // references to anchors, that remains the same after resolving
   174     QList<HbAnchor*> mResolvedAnchors; // anchors that are passed to engine
   172     QList<HbAnchor*> mResolvedAnchors; // anchors that are passed to engine
   175 
   173 
   176     // mesh layout data
       
   177     QList<QGraphicsLayoutItem*> mItems; // for addItem
   174     QList<QGraphicsLayoutItem*> mItems; // for addItem
   178     QList<QGraphicsLayoutItem*> mActualItems; // layouted items
   175     QList<QGraphicsLayoutItem*> mActualItems; // layouted items
   179     HbMeshItemMap mMeshMap;
   176     ItemToNodeIdMap mItemToNodeIdMap;
   180 
   177 
   181     QRectF mUsedRect;
   178     QRectF mUsedRect;
   182 
   179 
   183     // new items
   180     // new items
   184 
   181 
   209 
   206 
   210 };
   207 };
   211 
   208 
   212 
   209 
   213 
   210 
   214 
   211 /*!
   215 
   212     \internal functions
   216 
   213 */
   217 /*!
   214 
   218     \internal
   215 inline bool idConditionStartStart( HbAnchor *anchor1, HbAnchor *anchor2 )
   219 */
   216 {
   220 HbAnchor::HbAnchor()
   217     return ( !anchor1->startNodeId().isNull() ) && ( anchor1->startNodeId() == anchor2->startNodeId() );
   221     : mStartItem(0),
   218 }
   222     mStartEdge(Hb::LeftEdge),
   219 inline bool idConditionEndEnd( HbAnchor *anchor1, HbAnchor *anchor2 )
   223     mEndItem(0),
   220 {
   224     mEndEdge(Hb::LeftEdge),
   221     return ( !anchor1->endNodeId().isNull() ) && ( anchor1->endNodeId() == anchor2->endNodeId() );
   225     mValue(0)
   222 }
   226 {
   223 inline bool idConditionStartEnd( HbAnchor *anchor1, HbAnchor *anchor2 )
   227 }
   224 {
   228 
   225     return ( !anchor1->startNodeId().isNull() ) && ( anchor1->startNodeId() == anchor2->endNodeId() );
   229 HbAnchor::HbAnchor(const HbAnchor &anchor)
   226 }
   230 : mStartItem(anchor.mStartItem),
   227 inline bool idConditionEndStart( HbAnchor *anchor1, HbAnchor *anchor2 )
   231   mStartEdge(anchor.mStartEdge),
   228 {
   232   mStartId(anchor.mStartId),
   229     return ( !anchor1->endNodeId().isNull() ) && ( anchor1->endNodeId() == anchor2->startNodeId() );
   233   mEndItem(anchor.mEndItem),
   230 }
   234   mEndEdge(anchor.mEndEdge),
   231 
   235   mEndId(anchor.mEndId),
   232 inline bool itemConditionStartStart( HbAnchor *anchor1, HbAnchor *anchor2 )
   236   mValue(anchor.mValue)
   233 {
   237 {
   234     return ( anchor1->startItem() != 0 ) && ( anchor1->startItem() == anchor2->startItem() );
   238 }
   235 }
   239 
   236 inline bool itemConditionEndEnd( HbAnchor *anchor1, HbAnchor *anchor2 )
   240 HbAnchor::HbAnchor( QGraphicsLayoutItem *startItem,
   237 {
   241                    HbAnchorLayout::Edge startEdge,
   238     return ( anchor1->endItem() != 0 ) && ( anchor1->endItem() == anchor2->endItem() );
   242                    QGraphicsLayoutItem *endItem,
   239 }
   243                    HbAnchorLayout::Edge endEdge,
   240 inline bool itemConditionStartEnd( HbAnchor *anchor1, HbAnchor *anchor2 )
   244                    qreal value )
   241 {
   245     : mStartItem(startItem),
   242     return ( anchor1->startItem() != 0 ) && ( anchor1->startItem() == anchor2->endItem() );
   246     mStartEdge(startEdge),
   243 }
   247     mEndItem(endItem),
   244 inline bool itemConditionEndStart( HbAnchor *anchor1, HbAnchor *anchor2 )
   248     mEndEdge(endEdge),
   245 {
   249     mValue(value)
   246     return ( anchor1->endItem() != 0 ) && ( anchor1->endItem() == anchor2->startItem() );
   250 {
   247 }
   251 }
   248 
   252 
   249 inline bool edgeConditionStartStart( HbAnchor *anchor1, HbAnchor *anchor2 )
   253 
   250 {
   254 HbAnchor &HbAnchor::operator=(const HbAnchor &anchor)
   251     return anchor1->startEdge() == anchor2->startEdge();
   255 {
   252 }
   256     if (this != &anchor) {
   253 inline bool edgeConditionEndEnd( HbAnchor *anchor1, HbAnchor *anchor2 )
   257         mStartItem = anchor.mStartItem;
   254 {
   258         mStartId = anchor.mStartId;
   255     return anchor1->endEdge() == anchor2->endEdge();
   259         mStartEdge = anchor.mStartEdge;
   256 }
   260         mEndItem = anchor.mEndItem;
   257 inline bool edgeConditionStartEnd( HbAnchor *anchor1, HbAnchor *anchor2 )
   261         mEndId = anchor.mEndId;
   258 {
   262         mEndEdge = anchor.mEndEdge;
   259     return anchor1->startEdge() == anchor2->endEdge();
   263         mValue = anchor.mValue;
   260 }
   264     }
   261 inline bool edgeConditionEndStart( HbAnchor *anchor1, HbAnchor *anchor2 )
   265     return *this;
   262 {
   266 }
   263     return anchor1->endEdge() == anchor2->startEdge();
   267 
   264 }
   268 
   265 
   269 
   266 inline int directionMultiplier( HbAnchor *anchor )
   270 
   267 {
   271 
   268     return ( ( anchor->direction() == HbAnchor::Positive )?(1):(-1) );
   272 /*!
   269 }
   273     \internal
   270 
   274 */
   271 
   275 QList<HbAnchor*> HbAnchorLayoutDebug::getAnchors( HbAnchorLayout* layout )
   272 /*!
   276 {
   273     Returns list of effective anchors - those which has mappings to QGraphicsItem
   277     layout->d_ptr->resolveAnchors();
   274     \return list of effective anchors.
   278     return layout->d_ptr->mResolvedAnchors;
   275 */
   279 }
   276 QList<HbAnchor*> HbAnchorLayout::effectiveAnchors()
   280 
   277 {
   281 QList<HbAnchor*> HbAnchorLayoutDebug::getOriginalAnchors( HbAnchorLayout* layout )
   278     Q_D( HbAnchorLayout );
   282 {
   279     d->resolveAnchors();
   283     return layout->d_ptr->mAllAnchors;
   280     return d->mResolvedAnchors;
       
   281 }
       
   282 
       
   283 /*!
       
   284     Returns list of all anchors set to this layout
       
   285     \return list of all anchors.
       
   286 */
       
   287 QList<HbAnchor*> HbAnchorLayout::anchors() const
       
   288 {
       
   289     Q_D( const HbAnchorLayout );
       
   290     return d->mAllAnchors;
   284 }
   291 }
   285 
   292 
   286 /*
   293 /*
   287     \class HbAnchorLayoutPrivate
   294     \class HbAnchorLayoutPrivate
   288     \internal
   295     \internal
   372         QGraphicsItem *gItem = item->graphicsItem();
   379         QGraphicsItem *gItem = item->graphicsItem();
   373         if (gItem) {
   380         if (gItem) {
   374             if (gItem->isWidget()) {
   381             if (gItem->isWidget()) {
   375                 result = static_cast<QGraphicsWidget*>(gItem)->metaObject()->className();
   382                 result = static_cast<QGraphicsWidget*>(gItem)->metaObject()->className();
   376             }
   383             }
   377 #ifndef Q_WS_S60
       
   378         } else {
       
   379             HbSpacerItem *spacer = dynamic_cast<HbSpacerItem *>(item);
       
   380             if ( spacer ) {
       
   381                 result = "HbSpacerItem";
       
   382             }
       
   383 #endif
       
   384         }
   384         }
   385     }
   385     }
   386     return result;
   386     return result;
   387 }
   387 }
   388 
   388 
   397     resolveAnchors();
   397     resolveAnchors();
   398 
   398 
   399 #ifdef HBANCHORLAYOUT_DEBUG
   399 #ifdef HBANCHORLAYOUT_DEBUG
   400     QGraphicsWidget* w = HbLayoutUtils::parentWidget( q );
   400     QGraphicsWidget* w = HbLayoutUtils::parentWidget( q );
   401     if ( w ) {
   401     if ( w ) {
   402         qDebug() << "MeshLayout: Mesh anchors for" << w->metaObject()->className();
   402         qDebug() << "AnchorLayout: Updating anchors for" << w->metaObject()->className();
   403     }
   403     }
   404     const QString parentId =
   404     const QString parentId =
   405         mMeshMap.contains(q) ? mMeshMap.value(q) : QString();
   405         mItemToNodeIdMap.contains(q) ? mItemToNodeIdMap.value(q) : QString();
   406     qDebug() << "-- -- resolved";
   406     qDebug() << "-- -- resolved";
   407     qDebug() << "-- count: " << mResolvedAnchors.size() << ", parent: " << parentId;
   407     qDebug() << "-- count: " << mResolvedAnchors.size() << ", parent: " << parentId;
   408     foreach (const HbAnchor *item, mResolvedAnchors) {
   408     foreach (const HbAnchor *item, mResolvedAnchors) {
   409         const QString itemTemplate("-- (%1 [%2], %3) - (%4 [%5], %6) = %7");
   409         const QString itemTemplate("-- (%1 [%2], %3) - (%4 [%5], %6) = %7");
   410         qDebug() <<
   410         qDebug() <<
   411             itemTemplate
   411             itemTemplate
   412             .arg(item->mStartId)
   412             .arg(item->startNodeId())
   413             .arg(itemAsText(item->mStartItem, q))
   413             .arg(itemAsText(item->startItem(), q))
   414             .arg(edgeAsText(item->mStartEdge))
   414             .arg(edgeAsText(item->startEdge()))
   415             .arg(item->mEndId)
   415             .arg(item->endNodeId())
   416             .arg(itemAsText(item->mEndItem, q))
   416             .arg(itemAsText(item->endItem(), q))
   417             .arg(edgeAsText(item->mEndEdge))
   417             .arg(edgeAsText(item->endEdge()))
   418             .arg(item->mValue).toAscii().data();
   418             .arg(item->preferredLength()).toAscii().data();
   419     }
   419     }
   420     qDebug() << "-- -- all";
   420     qDebug() << "-- -- all";
   421     qDebug() << "-- count: " << mAllAnchors.size() << ", parent: " << parentId;
   421     qDebug() << "-- count: " << mAllAnchors.size() << ", parent: " << parentId;
   422     foreach (const HbAnchor *item, mAllAnchors) {
   422     foreach (const HbAnchor *item, mAllAnchors) {
   423         const QString itemTemplate("-- (%1 [%2], %3) - (%4 [%5], %6) = %7");
   423         const QString itemTemplate("-- (%1 [%2], %3) - (%4 [%5], %6) = %7");
   424         qDebug() <<
   424         qDebug() <<
   425             itemTemplate
   425             itemTemplate
   426             .arg(item->mStartId)
   426             .arg(item->startNodeId())
   427             .arg(itemAsText(item->mStartItem, q))
   427             .arg(itemAsText(item->startItem(), q))
   428             .arg(edgeAsText(item->mStartEdge))
   428             .arg(edgeAsText(item->startEdge()))
   429             .arg(item->mEndId)
   429             .arg(item->endNodeId())
   430             .arg(itemAsText(item->mEndItem, q))
   430             .arg(itemAsText(item->endItem(), q))
   431             .arg(edgeAsText(item->mEndEdge))
   431             .arg(edgeAsText(item->endEdge()))
   432             .arg(item->mValue).toAscii().data();
   432             .arg(item->preferredLength()).toAscii().data();
   433     }
   433     }
   434     qDebug() << "-- ";
   434     qDebug() << "-- ";
   435 #endif // HBANCHORLAYOUT_DEBUG
   435 #endif // HBANCHORLAYOUT_DEBUG
   436 
   436 
   437     // HbAnchorLayout will only touch items that have anchors defined.
   437     // HbAnchorLayout will only touch items that have anchors defined.
   440          it != mResolvedAnchors.constEnd();
   440          it != mResolvedAnchors.constEnd();
   441          ++it) {
   441          ++it) {
   442 
   442 
   443         const HbAnchor* item = *it;
   443         const HbAnchor* item = *it;
   444 
   444 
   445         if (item->mStartItem != q && !mActualItems.contains(item->mStartItem)) {
   445         if (item->startItem() != q && !mActualItems.contains(item->startItem())) {
   446             mActualItems.append(item->mStartItem);
   446             mActualItems.append(item->startItem());
   447         }
   447         }
   448         if (item->mEndItem != q && !mActualItems.contains(item->mEndItem)) {
   448         if (item->endItem() != q && !mActualItems.contains(item->endItem())) {
   449             mActualItems.append(item->mEndItem);
   449             mActualItems.append(item->endItem());
   450         }
   450         }
   451     }
   451     }
   452 
   452 
   453 }
   453 }
       
   454 
       
   455 void HbAnchorLayoutPrivate::setSizeProp( SizeProperty *v, HbAnchor *item )
       
   456 {
       
   457     const QSizePolicy::Policy policy = item->sizePolicy();
       
   458 
       
   459     if ( policy & QSizePolicy::ShrinkFlag ) {
       
   460         v->min = item->minimumLength();
       
   461     } else {
       
   462         v->min = item->preferredLength();
       
   463     }
       
   464 
       
   465     if ( policy & (QSizePolicy::GrowFlag | QSizePolicy::ExpandFlag) ) {
       
   466         v->max = item->maximumLength();
       
   467     } else {
       
   468         v->max = item->preferredLength();
       
   469     }
       
   470 
       
   471     v->pref = qBound( v->min, item->preferredLength(), v->max );
       
   472 
       
   473     v->flags |= (v->min == v->max) ? SizeProperty::FlagFixed : 0;
       
   474     v->flags |= (policy & QSizePolicy::ExpandFlag) ? SizeProperty::FlagExpanding : 0;
       
   475 
       
   476     if( policy & QSizePolicy::IgnoreFlag ) {
       
   477         v->pref = v->min;
       
   478         v->flags |= SizeProperty::FlagExpanding;
       
   479     }
       
   480 }
       
   481 
   454 
   482 
   455 
   483 
   456 void HbAnchorLayoutPrivate::setSizeProp( SizeProperty *v, QGraphicsLayoutItem *item, EdgeType type )
   484 void HbAnchorLayoutPrivate::setSizeProp( SizeProperty *v, QGraphicsLayoutItem *item, EdgeType type )
   457 {
   485 {
   458     if( type == Vertical ) {
   486     if( type == Vertical ) {
   616 {
   644 {
   617     ItemGeometry *knownItemGeom, *unKnownItemGeom;
   645     ItemGeometry *knownItemGeom, *unKnownItemGeom;
   618     Hb::Edge knownEdge, unKnownEdge;
   646     Hb::Edge knownEdge, unKnownEdge;
   619     int sign;
   647     int sign;
   620     qreal itemSize;
   648     qreal itemSize;
       
   649     qreal anchorSize;
   621     bool isHorizontal;
   650     bool isHorizontal;
   622     HbAnchor *anchor = mResolvedAnchors.at( anchorIndex );
   651     HbAnchor *anchor = mResolvedAnchors.at( anchorIndex );
   623     qreal leftPoint(0), rightPoint(0), sourcePoint(0), dstPointLeft(0);
   652     qreal leftPoint(0), rightPoint(0), sourcePoint(0), dstPointLeft(0);
   624 
   653 
   625     mAnchorsVisited[ anchorIndex ] = true;
   654     mAnchorsVisited[ anchorIndex ] = true;
   626 
   655 
   627     if( edgeType( anchor->mStartEdge ) == Horizontal ) {
   656     if( edgeType( anchor->startEdge() ) == Horizontal ) {
   628         isHorizontal = true;
   657         isHorizontal = true;
   629     } else {
   658     } else {
   630         isHorizontal = false;
   659         isHorizontal = false;
   631     }
   660     }
   632 
   661 
   633     if( itemIndexEnd != definedItemIndex ) {
   662     if( itemIndexEnd != definedItemIndex ) {
   634         knownEdge = anchor->mStartEdge;
   663         knownEdge = anchor->startEdge();
   635         unKnownEdge =  anchor->mEndEdge;
   664         unKnownEdge =  anchor->endEdge();
   636 
   665 
   637         knownItemGeom = &mItemsGeometry[itemIndexStart];
   666         knownItemGeom = &mItemsGeometry[itemIndexStart];
   638         unKnownItemGeom = &mItemsGeometry[itemIndexEnd];
   667         unKnownItemGeom = &mItemsGeometry[itemIndexEnd];
   639 
   668 
   640         if( isHorizontal ) {
   669         if( isHorizontal ) {
   641             mGeometryDefinedH[itemIndexEnd] = true;
   670             mGeometryDefinedH[itemIndexEnd] = true;
   642             itemSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( mActualItems.at(itemIndexEnd) ) );
   671             itemSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( mActualItems.at(itemIndexEnd) ) );
       
   672             anchorSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( anchor ) ) * directionMultiplier( anchor );
   643         } else {
   673         } else {
   644             mGeometryDefinedV[itemIndexEnd] = true;
   674             mGeometryDefinedV[itemIndexEnd] = true;
   645             itemSize = mSolutionVertical.value( mVariablesVertical.findVariable( mActualItems.at(itemIndexEnd) ) );
   675             itemSize = mSolutionVertical.value( mVariablesVertical.findVariable( mActualItems.at(itemIndexEnd) ) );
       
   676             anchorSize = mSolutionVertical.value( mVariablesVertical.findVariable( anchor ) ) * directionMultiplier( anchor );
   646         }
   677         }
   647 
   678 
   648         sign = 1;
   679         sign = 1;
   649     } else {
   680     } else {
   650         knownEdge =  anchor->mEndEdge;
   681         knownEdge =  anchor->endEdge();
   651         unKnownEdge = anchor->mStartEdge;
   682         unKnownEdge = anchor->startEdge();
   652 
   683 
   653         knownItemGeom = &mItemsGeometry[itemIndexEnd];
   684         knownItemGeom = &mItemsGeometry[itemIndexEnd];
   654         unKnownItemGeom = &mItemsGeometry[itemIndexStart];
   685         unKnownItemGeom = &mItemsGeometry[itemIndexStart];
   655 
   686 
   656         if( isHorizontal ) {
   687         if( isHorizontal ) {
   657             mGeometryDefinedH[itemIndexStart] = true;
   688             mGeometryDefinedH[itemIndexStart] = true;
   658             itemSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( mActualItems.at(itemIndexStart) ) );
   689             itemSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( mActualItems.at(itemIndexStart) ) );
       
   690             anchorSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( anchor ) ) * directionMultiplier( anchor );
   659         } else {
   691         } else {
   660             mGeometryDefinedV[itemIndexStart] = true;
   692             mGeometryDefinedV[itemIndexStart] = true;
   661             itemSize = mSolutionVertical.value( mVariablesVertical.findVariable( mActualItems.at(itemIndexStart) ) );
   693             itemSize = mSolutionVertical.value( mVariablesVertical.findVariable( mActualItems.at(itemIndexStart) ) );
       
   694             anchorSize = mSolutionVertical.value( mVariablesVertical.findVariable( anchor ) ) * directionMultiplier( anchor );
   662         }
   695         }
   663 
   696 
   664         sign = -1;
   697         sign = -1;
   665     }
   698     }
   666 
   699 
   695 
   728 
   696     switch( unKnownEdge ) {
   729     switch( unKnownEdge ) {
   697         case Hb::LeftEdge:
   730         case Hb::LeftEdge:
   698         case Hb::TopEdge:
   731         case Hb::TopEdge:
   699         {
   732         {
   700             dstPointLeft = sourcePoint + sign * anchor->mValue;
   733             dstPointLeft = sourcePoint + sign * anchorSize;
   701             break;
   734             break;
   702         }
   735         }
   703         case Hb::CenterHEdge:
   736         case Hb::CenterHEdge:
   704         case Hb::CenterVEdge:
   737         case Hb::CenterVEdge:
   705         {
   738         {
   706             dstPointLeft = sourcePoint + sign * anchor->mValue - itemSize / 2;
   739             dstPointLeft = sourcePoint + sign * anchorSize - itemSize / 2;
   707             break;
   740             break;
   708         }
   741         }
   709         case Hb::RightEdge:
   742         case Hb::RightEdge:
   710         case Hb::BottomEdge:
   743         case Hb::BottomEdge:
   711         {
   744         {
   712             dstPointLeft = sourcePoint + sign * anchor->mValue - itemSize;
   745             dstPointLeft = sourcePoint + sign * anchorSize - itemSize;
   713             break;
   746             break;
   714         }
   747         }
   715     }
   748     }
   716 
   749 
   717 
   750 
   721         unKnownItemGeom->x2 = dstPointLeft + itemSize;
   754         unKnownItemGeom->x2 = dstPointLeft + itemSize;
   722     } else {
   755     } else {
   723         unKnownItemGeom->y1 = dstPointLeft;
   756         unKnownItemGeom->y1 = dstPointLeft;
   724         unKnownItemGeom->y2 = dstPointLeft + itemSize;
   757         unKnownItemGeom->y2 = dstPointLeft + itemSize;
   725     }
   758     }
   726 
       
   727 }
   759 }
   728 
   760 
   729 
   761 
   730 /*
   762 /*
   731     \internal
   763     \internal
   826                 mGeometryDefinedV[i] = false;
   858                 mGeometryDefinedV[i] = false;
   827             }
   859             }
   828 
   860 
   829             int layoutIndex = mActualItems.size();
   861             int layoutIndex = mActualItems.size();
   830 
   862 
   831             mItemsGeometry[ layoutIndex ].x1 = 0;//newRect.left();
   863             mItemsGeometry[ layoutIndex ].x1 = 0;
   832             mItemsGeometry[ layoutIndex ].x2 = newRect.width();//newRect.right();
   864             mItemsGeometry[ layoutIndex ].x2 = newRect.width();
   833             mItemsGeometry[ layoutIndex ].y1 = 0;//newRect.top();
   865             mItemsGeometry[ layoutIndex ].y1 = 0;
   834             mItemsGeometry[ layoutIndex ].y2 = newRect.height();//newRect.bottom();
   866             mItemsGeometry[ layoutIndex ].y2 = newRect.height();
   835             mGeometryDefinedH[ layoutIndex ] = true;
   867             mGeometryDefinedH[ layoutIndex ] = true;
   836             mGeometryDefinedV[ layoutIndex ] = true;
   868             mGeometryDefinedV[ layoutIndex ] = true;
   837 
   869 
   838 
   870 
   839             for( int i = 0; i < mAnchorsVisited.size(); i++ ) {
   871             for( int i = 0; i < mAnchorsVisited.size(); i++ ) {
   840 
   872 
   841                 HbAnchor *anchor = mResolvedAnchors.at(i);
   873                 HbAnchor *anchor = mResolvedAnchors.at(i);
   842 
   874 
   843 
   875 
   844                 if( ( anchor->mStartItem != q ) && ( anchor->mEndItem != q ) ) {
   876                 if( ( anchor->startItem() != q ) && ( anchor->endItem() != q ) ) {
   845                     continue;
   877                     continue;
   846                 }
   878                 }
   847 
   879 
   848                 int startIndex = mActualItems.indexOf( anchor->mStartItem ); // returns -1 if not found => this is layout
   880                 int startIndex = mActualItems.indexOf( anchor->startItem() ); // returns -1 if not found => this is layout
   849                 int endIndex = mActualItems.indexOf( anchor->mEndItem );
   881                 int endIndex = mActualItems.indexOf( anchor->endItem() );
   850 
   882 
   851                 mAnchorsVisited[i] = true; // Temporary overkill, if both anchors connected to layout. Must be restricted on setAnchor() level
   883                 mAnchorsVisited[i] = true;
   852 
   884 
   853                 if( edgeType( anchor->mStartEdge ) == Horizontal ) {
   885                 if( edgeType( anchor->startEdge() ) == Horizontal ) {
   854                     if( startIndex > -1 ) {
   886                     if( startIndex > -1 ) {
   855                         if( ! mGeometryDefinedH.at( startIndex ) ) {
   887                         if( ! mGeometryDefinedH.at( startIndex ) ) {
   856                             defineNextGeometry( startIndex, layoutIndex, i, layoutIndex );
   888                             defineNextGeometry( startIndex, layoutIndex, i, layoutIndex );
   857                         }
   889                         }
   858                     } else if( endIndex > -1 ) {
   890                     } else if( endIndex > -1 ) {
   885                     if( mAnchorsVisited.at(i) ) {
   917                     if( mAnchorsVisited.at(i) ) {
   886                         continue;
   918                         continue;
   887                     }
   919                     }
   888                     HbAnchor *anchor = mResolvedAnchors.at(i);
   920                     HbAnchor *anchor = mResolvedAnchors.at(i);
   889 
   921 
   890                     startIndex = mActualItems.indexOf( anchor->mStartItem );
   922                     startIndex = mActualItems.indexOf( anchor->startItem() );
   891                     endIndex = mActualItems.indexOf( anchor->mEndItem );
   923                     endIndex = mActualItems.indexOf( anchor->endItem() );
   892 #ifdef HBANCHORLAYOUT_DEBUG
   924 #ifdef HBANCHORLAYOUT_DEBUG
   893                     qDebug() << "startIndex:" << startIndex << "  endIndex" << endIndex;
   925                     qDebug() << "startIndex:" << startIndex << "  endIndex" << endIndex;
   894 #endif //HBANCHORLAYOUT_DEBUG
   926 #endif //HBANCHORLAYOUT_DEBUG
   895                     if( edgeType( anchor->mStartEdge ) == Horizontal ) {
   927                     if( edgeType( anchor->startEdge() ) == Horizontal ) {
   896                         startDefined = mGeometryDefinedH.at( startIndex );
   928                         startDefined = mGeometryDefinedH.at( startIndex );
   897                         endDefined = mGeometryDefinedH.at( endIndex );
   929                         endDefined = mGeometryDefinedH.at( endIndex );
   898                     } else {
   930                     } else {
   899                         startDefined = mGeometryDefinedV.at( startIndex );
   931                         startDefined = mGeometryDefinedV.at( startIndex );
   900                         endDefined = mGeometryDefinedV.at( endIndex );
   932                         endDefined = mGeometryDefinedV.at( endIndex );
   939 
   971 
   940                 HbLayoutUtils::visualRect( layoutDir, geom, newRect );
   972                 HbLayoutUtils::visualRect( layoutDir, geom, newRect );
   941 
   973 
   942 #ifdef HBANCHORLAYOUT_DEBUG
   974 #ifdef HBANCHORLAYOUT_DEBUG
   943                 qDebug( "Item %d: (%lf, %lf) : (%lf %lf)", i, calcGeom.x1, calcGeom.y1, calcGeom.x2, calcGeom.y2 );
   975                 qDebug( "Item %d: (%lf, %lf) : (%lf %lf)", i, calcGeom.x1, calcGeom.y1, calcGeom.x2, calcGeom.y2 );
   944         //        qDebug() << "Item " <<  i << "(" << ((QGraphicsWidget*)mActualItems.at(i))->metaObject()->className() << ")" << " geom " << geom;
       
   945 #endif // HBANCHORLAYOUT_DEBUG
   976 #endif // HBANCHORLAYOUT_DEBUG
   946                 mActualItems.at(i)->setGeometry( geom );
   977                 mActualItems.at(i)->setGeometry( geom );
   947             }
   978             }
   948         }
   979         }
   949     }
   980     }
  1059         v1->sizeProp.flags = SizeProperty::FlagFixed;
  1090         v1->sizeProp.flags = SizeProperty::FlagFixed;
  1060 
  1091 
  1061 
  1092 
  1062         for( int i = 0; i < mResolvedAnchors.count(); i++) {
  1093         for( int i = 0; i < mResolvedAnchors.count(); i++) {
  1063             HbAnchor* anchor = mResolvedAnchors.at(i);
  1094             HbAnchor* anchor = mResolvedAnchors.at(i);
  1064             if ( edgeType( anchor->mStartEdge ) == type ) {
  1095             if ( edgeType( anchor->startEdge() ) == type ) {
  1065                 itemStart = 0;
  1096                 itemStart = 0;
  1066                 itemEnd = 0;
  1097                 itemEnd = 0;
  1067                 for( int j = 0; j < vertices->size(); j++ ) {
  1098                 for( int j = 0; j < vertices->size(); j++ ) {
  1068                     if( ( vertices->at(j)->itemRef == anchor->mStartItem ) &&
  1099                     if( ( vertices->at(j)->itemRef == anchor->startItem() ) &&
  1069                             ( vertices->at(j)->itemSide == anchor->mStartEdge ) ) {
  1100                             ( vertices->at(j)->itemSide == anchor->startEdge() ) ) {
  1070                         itemStart = vertices->at(j);
  1101                         itemStart = vertices->at(j);
  1071                     } else if( ( vertices->at(j)->itemRef == anchor->mEndItem ) &&
  1102                     } else if( ( vertices->at(j)->itemRef == anchor->endItem() ) &&
  1072                         ( vertices->at(j)->itemSide == anchor->mEndEdge ) ) {
  1103                         ( vertices->at(j)->itemSide == anchor->endEdge() ) ) {
  1073                         itemEnd = vertices->at(j);
  1104                         itemEnd = vertices->at(j);
  1074                     }
  1105                     }
  1075                 }
  1106                 }
  1076 
  1107 
  1077                 if( !itemStart ) {
  1108                 if( !itemStart ) {
  1078                     itemStart = createCenterEdge( type, anchor->mStartItem,  anchor->mStartEdge );
  1109                     itemStart = createCenterEdge( type, anchor->startItem(),  anchor->startEdge() );
  1079                 }
  1110                 }
  1080                 if( !itemEnd ) {
  1111                 if( !itemEnd ) {
  1081                     itemEnd = createCenterEdge( type, anchor->mEndItem,  anchor->mEndEdge );
  1112                     itemEnd = createCenterEdge( type, anchor->endItem(),  anchor->endEdge() );
  1082                 }
  1113                 }
  1083 
  1114 
  1084                 if( !itemStart ){
  1115                 if( !itemStart ){
  1085                     qWarning() << "HbAnchorLayout: internal error, line " << __LINE__;
  1116                     qWarning() << "HbAnchorLayout: internal error, line " << __LINE__;
  1086                     mWrongAnchors = true;
  1117                     mWrongAnchors = true;
  1098                 itemStart->edges.append( newEdge );
  1129                 itemStart->edges.append( newEdge );
  1099                 itemEnd->edges.append( newEdge );
  1130                 itemEnd->edges.append( newEdge );
  1100 
  1131 
  1101                 newEdge->startVertex = itemStart;
  1132                 newEdge->startVertex = itemStart;
  1102                 newEdge->endVertex = itemEnd;
  1133                 newEdge->endVertex = itemEnd;
  1103                 se.mVar = v1;
  1134 
  1104                 se.mCoef = anchor->mValue;
  1135                 se.mVar = vs->createVariable(anchor);
       
  1136                 se.mCoef = directionMultiplier( anchor );
       
  1137                 setSizeProp( &(se.mVar->sizeProp), anchor );
  1105                 newEdge->expr->plusSimpleExpression( se );
  1138                 newEdge->expr->plusSimpleExpression( se );
       
  1139 
  1106                 edges->append( newEdge );
  1140                 edges->append( newEdge );
  1107             }
  1141             }
  1108         }
  1142         }
  1109 
  1143 
  1110         if( layoutStart->edges.isEmpty() ) {
  1144         if( layoutStart->edges.isEmpty() ) {
  1209         \a ids must be the exactly same in return. It is the array
  1243         \a ids must be the exactly same in return. It is the array
  1210         which nodes have already been visited - so in order to avoid
  1244         which nodes have already been visited - so in order to avoid
  1211         infinite recursion, don't visit already visited.
  1245         infinite recursion, don't visit already visited.
  1212 */
  1246 */
  1213 bool HbAnchorLayoutPrivate::findEndItem(
  1247 bool HbAnchorLayoutPrivate::findEndItem(
  1214     QList<HbMeshEndItemResult> &resultList,
  1248     QList<HbFixedEndItemResult> &resultList,
  1215     const HbAnchor *problem,
  1249     const HbAnchor *problem,
  1216     QStringList &ids) const
  1250     QStringList &ids) const
  1217 {
  1251 {
  1218     HbMeshEndItemResult result;
  1252     HbFixedEndItemResult result;
  1219     bool found = false;
  1253     bool found = false;
  1220 
  1254 
  1221     for (QList<HbAnchor*>::const_iterator it = mAllAnchors.constBegin();
  1255     for (QList<HbAnchor*>::const_iterator it = mAllAnchors.constBegin();
  1222          it != mAllAnchors.constEnd();
  1256          it != mAllAnchors.constEnd();
  1223          ++it) {
  1257          ++it) {
  1224 
  1258 
  1225         const HbAnchor* currentItem = *it;
  1259         const HbAnchor* currentItem = *it;
  1226 
  1260 
  1227         if (!currentItem->mStartId.isNull() &&
  1261         if (!currentItem->startNodeId().isNull() &&
  1228             currentItem->mStartId == problem->mEndId &&
  1262             currentItem->startNodeId() == problem->endNodeId() &&
  1229             currentItem->mStartEdge == problem->mStartEdge &&
  1263             currentItem->startEdge() == problem->startEdge() &&
  1230             !ids.contains(currentItem->mStartId)) {
  1264             !ids.contains(currentItem->startNodeId())) {
  1231 
  1265 
  1232             qreal currentSpacing = currentItem->mValue;
  1266             QGraphicsLayoutItem *item = currentItem->endItem();
  1233 
       
  1234             QGraphicsLayoutItem *item = currentItem->mEndItem;
       
  1235 
       
  1236 
  1267 
  1237             if (item) {
  1268             if (item) {
  1238                 found = true;
  1269                 found = true;
  1239                 result.mEdge = currentItem->mEndEdge;
  1270                 result.mEdge = currentItem->endEdge();
  1240                 result.mItem = item;
  1271                 result.mItem = item;
  1241                 result.mValue = currentSpacing;
  1272                 result.mMin = currentItem->minimumLength();
       
  1273                 result.mPref = currentItem->preferredLength();
       
  1274                 result.mMax = currentItem->maximumLength();
       
  1275                 result.mPolicy = currentItem->sizePolicy();
       
  1276                 result.mDirection = currentItem->direction();
  1242                 resultList.append( result );
  1277                 resultList.append( result );
  1243             } else {
  1278             } else {
  1244                 ids.append(currentItem->mStartId);
  1279                 ids.append(currentItem->startNodeId());
  1245                 found |= findEndItem(resultList, currentItem, ids);
  1280                 found |= findEndItem(resultList, currentItem, ids);
  1246                 ids.takeLast();
  1281                 ids.takeLast();
  1247             }
  1282             }
  1248             /*
       
  1249             if (found) {
       
  1250                 // We have found an end item. There can be multiple end items,
       
  1251                 // but (for now) the first one is selected.
       
  1252                 return true;
       
  1253             }*/
       
  1254         }
  1283         }
  1255     }
  1284     }
  1256 
  1285 
  1257     return found;
  1286     return found;
  1258 }
  1287 }
  1284 
  1313 
  1285     for ( int i = 0; i < mAllAnchors.size(); i++ ) {
  1314     for ( int i = 0; i < mAllAnchors.size(); i++ ) {
  1286 
  1315 
  1287         HbAnchor *anchor = mAllAnchors.at(i);
  1316         HbAnchor *anchor = mAllAnchors.at(i);
  1288 
  1317 
  1289         if( ( anchor->mStartItem ) && ( anchor->mEndItem ) ) {
  1318         if( ( anchor->startItem() ) && ( anchor->endItem() ) ) {
  1290             mResolvedStaticAnchors.append( anchor );
  1319             mResolvedStaticAnchors.append( anchor );
  1291             continue;
  1320             continue;
  1292         }
  1321         }
  1293 
  1322 
  1294         if (anchor->mStartItem && !anchor->mEndId.isNull()) {
  1323         if (anchor->startItem() && !anchor->endNodeId().isNull()) {
  1295             QList<HbMeshEndItemResult> resultList;
  1324             QList<HbFixedEndItemResult> resultList;
  1296 
  1325 
  1297             QStringList ids;
  1326             QStringList ids;
  1298             ids.append(anchor->mStartId);
  1327             ids.append(anchor->startNodeId());
  1299 
  1328 
  1300             if (findEndItem(resultList, anchor, ids)) {
  1329             if (findEndItem(resultList, anchor, ids)) {
  1301                 for( int j = 0; j < resultList.size(); j++ ) {
  1330                 for( int j = 0; j < resultList.size(); j++ ) {
  1302                     item = new HbAnchor();
  1331                     item = new HbAnchor( anchor->startItem(), anchor->startEdge(), resultList.at(j).mItem, resultList.at(j).mEdge );
  1303                     item->mStartItem = anchor->mStartItem;
  1332                     item->setMinimumLength( resultList.at(j).mMin );
  1304                     item->mStartId = anchor->mStartId;
  1333                     item->setPreferredLength( resultList.at(j).mPref );
  1305                     item->mStartEdge = anchor->mStartEdge;
  1334                     item->setMaximumLength( resultList.at(j).mMax );
  1306                     item->mEndEdge = resultList.at(j).mEdge;
  1335                     item->setSizePolicy( resultList.at(j).mPolicy );
  1307                     item->mEndItem = resultList.at(j).mItem;
  1336                     item->setDirection( resultList.at(j).mDirection );
  1308                     item->mValue = resultList.at(j).mValue;
       
  1309                     mResolvedDynamicAnchors.append(item);
  1337                     mResolvedDynamicAnchors.append(item);
  1310                 }
  1338                 }
  1311             }
  1339             }
  1312         } else {
  1340         } else {
  1313             // Nothing needed.
  1341             // Nothing needed.
  1315     }
  1343     }
  1316 
  1344 
  1317     mResolvedAnchors = mResolvedDynamicAnchors + mResolvedStaticAnchors;
  1345     mResolvedAnchors = mResolvedDynamicAnchors + mResolvedStaticAnchors;
  1318 }
  1346 }
  1319 
  1347 
  1320 bool HbAnchorLayoutPrivate::setAnchor( HbAnchor *anchor )
  1348 HbAnchor *HbAnchorLayoutPrivate::setAnchor( HbAnchor *anchor )
  1321 {
  1349 {
       
  1350     Q_Q( HbAnchorLayout );
  1322     // This method is called from HbAnchorLayout::setAnchor.
  1351     // This method is called from HbAnchorLayout::setAnchor.
  1323 
  1352 
  1324     if (HbAnchorLayoutPrivate::edgeType(anchor->mStartEdge) !=
  1353     if (HbAnchorLayoutPrivate::edgeType(anchor->startEdge()) !=
  1325         HbAnchorLayoutPrivate::edgeType(anchor->mEndEdge)) {
  1354         HbAnchorLayoutPrivate::edgeType(anchor->endEdge())) {
  1326         qWarning() << "HbAnchorLayout::setAnchor : You can't connect different type of edges";
  1355         qWarning() << "HbAnchorLayout::setAnchor : You can't connect different type of edges";
  1327         return false;
  1356         return 0;
  1328     }
  1357     }
  1329 
  1358 
  1330     if ( ( anchor->mStartId.isNull() && ( anchor->mStartItem == 0 ) ) ||
  1359     if ( ( anchor->startNodeId().isNull() && ( anchor->startItem() == 0 ) ) ||
  1331         ( anchor->mEndId.isNull() && ( anchor->mEndItem == 0 ) ) ){
  1360         ( anchor->endNodeId().isNull() && ( anchor->endItem() == 0 ) ) ){
  1332         qWarning() << "HbAnchorLayout::setAnchor : Both ids must be valid";
  1361         qWarning() << "HbAnchorLayout::setAnchor : Both ids must be valid";
  1333         return false;
  1362         return 0;
  1334     }
  1363     }
  1335 
  1364 
  1336     if ( ( anchor->mStartId == anchor->mEndId ) && ( ( anchor->mStartItem == anchor->mEndItem ) ) &&
  1365     if ( ( anchor->startNodeId() == anchor->endNodeId() ) && ( ( anchor->startItem() == anchor->endItem() ) ) &&
  1337         ( anchor->mStartEdge == anchor->mEndEdge ) ) {
  1366         ( anchor->startEdge() == anchor->endEdge() ) ) {
  1338         qWarning() << "HbAnchorLayout::setAnchor : You cannot set anchor between the same edge";
  1367         qWarning() << "HbAnchorLayout::setAnchor : You cannot set anchor between the same edge";
  1339         return false;
  1368         return 0;
  1340     }
  1369     }
  1341 
       
  1342     bool modified = false;
       
  1343 
  1370 
  1344     const int count = mAllAnchors.size();
  1371     const int count = mAllAnchors.size();
  1345     for (int i = 0; i < count; ++i) {
  1372     for (int i = 0; i < count; ++i) {
  1346         HbAnchor *item = mAllAnchors.at(i);
  1373         HbAnchor *item = mAllAnchors.at(i);
  1347 
  1374 
  1348 
  1375         if( ( idConditionStartStart( item, anchor ) || itemConditionStartStart( item, anchor ) ) &&
  1349         bool idConditionStartStart = ( !item->mStartId.isNull() ) && ( item->mStartId == anchor->mStartId );
  1376             ( idConditionEndEnd( item, anchor ) || itemConditionEndEnd( item, anchor ) ) &&
  1350         bool idConditionEndEnd = ( !item->mEndId.isNull() ) && ( item->mEndId == anchor->mEndId );
  1377             ( edgeConditionStartStart( item, anchor ) ) &&
  1351         bool idConditionStartEnd = ( !item->mStartId.isNull() ) && ( item->mStartId == anchor->mEndId );
  1378             ( edgeConditionEndEnd( item, anchor ) ) ){
  1352         bool idConditionEndStart = ( !item->mEndId.isNull() ) && ( item->mEndId == anchor->mStartId );
  1379                 item->setSizePolicy( anchor->sizePolicy() );
  1353 
  1380                 item->setMinimumLength( anchor->minimumLength() );
  1354         bool itemConditionStartStart = ( item->mStartItem != 0 ) && ( item->mStartItem == anchor->mStartItem );
  1381                 item->setPreferredLength( anchor->preferredLength() );
  1355         bool itemConditionEndEnd = ( item->mEndItem != 0 ) && ( item->mEndItem == anchor->mEndItem );
  1382                 item->setMaximumLength( anchor->maximumLength() );
  1356         bool itemConditionStartEnd = ( item->mStartItem != 0 ) && ( item->mStartItem == anchor->mEndItem );
  1383                 item->setDirection( anchor->direction() );
  1357         bool itemConditionEndStart = ( item->mEndItem != 0 ) && ( item->mEndItem == anchor->mStartItem );
       
  1358 
       
  1359         bool edgeConditionStartStart = item->mStartEdge == anchor->mStartEdge;
       
  1360         bool edgeConditionEndEnd = item->mEndEdge == anchor->mEndEdge;
       
  1361         bool edgeConditionStartEnd = item->mStartEdge == anchor->mEndEdge;
       
  1362         bool edgeConditionEndStart = item->mEndEdge == anchor->mStartEdge;
       
  1363 
       
  1364 
       
  1365         if((idConditionStartStart || itemConditionStartStart) &&
       
  1366             (idConditionEndEnd || itemConditionEndEnd) &&
       
  1367             (edgeConditionStartStart) &&
       
  1368             (edgeConditionEndEnd) ){
       
  1369                 modified = true;
       
  1370                 item->mValue = anchor->mValue;
       
  1371                 delete anchor;
  1384                 delete anchor;
  1372                 break;
  1385                 return item;
  1373         } else if( (idConditionStartEnd || itemConditionStartEnd) &&
  1386         } else if( ( idConditionStartEnd( item, anchor ) || itemConditionStartEnd( item, anchor ) ) &&
  1374             (idConditionEndStart || itemConditionEndStart) &&
  1387             ( idConditionEndStart( item, anchor )  || itemConditionEndStart( item, anchor ) ) &&
  1375             (edgeConditionStartEnd) &&
  1388             ( edgeConditionStartEnd( item, anchor ) ) &&
  1376             (edgeConditionEndStart) ){
  1389             ( edgeConditionEndStart( item, anchor ) ) ){
  1377                 modified = true;
  1390                 item->setSizePolicy( anchor->sizePolicy() );
  1378                 item->mValue = -anchor->mValue;
  1391                 item->setMinimumLength( anchor->minimumLength() );
       
  1392                 item->setPreferredLength( anchor->preferredLength() );
       
  1393                 item->setMaximumLength( anchor->maximumLength() );
       
  1394                 item->setDirection( ( anchor->direction() == HbAnchor::Positive )?( HbAnchor::Negative ):( HbAnchor::Positive ) );
  1379                 delete anchor;
  1395                 delete anchor;
  1380                 break;
  1396                 return item;
  1381         }
  1397         }
  1382     }
  1398     }
  1383 
  1399 
  1384     if (!modified) {
  1400     if( anchor->startItem() != 0 ){
  1385         if( anchor->mStartItem != 0 ){
  1401         anchor->d_ptr->mStartId = mItemToNodeIdMap.value( anchor->startItem() );
  1386             anchor->mStartId = mMeshMap.value( anchor->mStartItem );
  1402     } else if( ! anchor->startNodeId().isNull() ) {
  1387         } else if( ! anchor->mStartId.isNull() ) {
  1403         anchor->d_ptr->mStartItem = mItemToNodeIdMap.key( anchor->startNodeId() );
  1388             anchor->mStartItem = mMeshMap.key( anchor->mStartId );
  1404     }
  1389         }
  1405 
  1390 
  1406     if( anchor->endItem() != 0 ){
  1391         if( anchor->mEndItem != 0 ){
  1407         anchor->d_ptr->mEndId = mItemToNodeIdMap.value( anchor->endItem() );
  1392             anchor->mEndId = mMeshMap.value( anchor->mEndItem );
  1408     } else if( ! anchor->endNodeId().isNull() ) {
  1393         } else if( ! anchor->mEndId.isNull() ) {
  1409         anchor->d_ptr->mEndItem = mItemToNodeIdMap.key( anchor->endNodeId() );
  1394             anchor->mEndItem = mMeshMap.key( anchor->mEndId );
  1410     }
  1395         }
  1411 
  1396 
  1412     addItemIfNeeded( anchor->startItem() );
  1397         addItemIfNeeded( anchor->mStartItem );
  1413     addItemIfNeeded( anchor->endItem() );
  1398         addItemIfNeeded( anchor->mEndItem );
  1414 
  1399 
  1415     anchor->d_ptr->mParent = q;
  1400         mAllAnchors.append(anchor);
  1416 
  1401     }
  1417     mAllAnchors.append(anchor);
  1402 
  1418 
  1403     return true;
  1419     return anchor;
  1404 }
  1420 }
  1405 
  1421 
  1406 void HbAnchorLayoutPrivate::removeItemIfNeeded( QGraphicsLayoutItem *item )
  1422 void HbAnchorLayoutPrivate::removeItemIfNeeded( QGraphicsLayoutItem *item )
  1407 {
  1423 {
  1408     Q_Q( HbAnchorLayout );
  1424     Q_Q( HbAnchorLayout );
  1411         return;
  1427         return;
  1412     }
  1428     }
  1413 
  1429 
  1414     for ( int i = 0; i < mAllAnchors.size(); i++ ) {
  1430     for ( int i = 0; i < mAllAnchors.size(); i++ ) {
  1415         HbAnchor *anchor = mAllAnchors.at(i);
  1431         HbAnchor *anchor = mAllAnchors.at(i);
  1416         if ( ( anchor->mStartItem == item ) || ( anchor->mEndItem == item ) ) {
  1432         if ( ( anchor->startItem() == item ) || ( anchor->endItem() == item ) ) {
  1417             return;
  1433             return;
  1418         }
  1434         }
  1419     }
  1435     }
  1420 
  1436 
  1421     item->setParentLayoutItem( 0 );
  1437     item->setParentLayoutItem( 0 );
  1488     \param startItem source item.
  1504     \param startItem source item.
  1489     \param startEdge source edge.
  1505     \param startEdge source edge.
  1490     \param endItem target item.
  1506     \param endItem target item.
  1491     \param endEdge target edge.
  1507     \param endEdge target edge.
  1492     \param length spacing (in pixels).
  1508     \param length spacing (in pixels).
  1493     \return true if anchor was successfully added, false otherwise
  1509     \return created anchor if it was successfully added, or zero otherwise
  1494 */
  1510 */
  1495 bool HbAnchorLayout::setAnchor( QGraphicsLayoutItem *startItem, Edge startEdge, QGraphicsLayoutItem *endItem, Edge endEdge, qreal length )
  1511 HbAnchor *HbAnchorLayout::setAnchor( QGraphicsLayoutItem *startItem, Edge startEdge, QGraphicsLayoutItem *endItem, Edge endEdge, qreal length )
  1496 {
  1512 {
  1497     Q_D( HbAnchorLayout );
  1513     Q_D( HbAnchorLayout );
  1498 
  1514 
  1499     HbAnchor *anchor = new HbAnchor();
  1515 
  1500     anchor->mStartItem = startItem;
  1516     HbAnchor *anchor = new HbAnchor( startItem, startEdge, endItem, endEdge, length );
  1501     anchor->mStartEdge = startEdge;
  1517 
  1502     anchor->mEndItem = endItem;
  1518     HbAnchor *result = d->setAnchor( anchor );
  1503     anchor->mEndEdge = endEdge;
  1519 
  1504     anchor->mValue = length;
  1520     if( result ) {
  1505 
       
  1506     if (d->setAnchor(anchor)) {
       
  1507         invalidate();
  1521         invalidate();
  1508         return true;
  1522         return result;
  1509     }
  1523     }
  1510 
  1524 
  1511     delete anchor;
  1525     delete anchor;
  1512 
  1526 
  1513     return false;
  1527     return 0;
  1514 }
  1528 }
  1515 
  1529 
  1516 /*!
  1530 /*!
  1517     Same as previous, but here it operates with node ids, instead of items itself.
  1531     Same as previous, but here it operates with node ids, instead of items itself.
  1518 
  1532 
  1519     \param startId start id.
  1533     \param startId start id.
  1520     \param startEdge start edge.
  1534     \param startEdge start edge.
  1521     \param endId end id.
  1535     \param endId end id.
  1522     \param endEdge end edge.
  1536     \param endEdge end edge.
  1523     \param length spacing value for all edges starting from (\a startId, \a startEdge).
  1537     \param length spacing value for all edges starting from (\a startId, \a startEdge).
  1524     \return true if success, false otherwise.
  1538     \return created anchor if it was successfully added, or zero otherwise
  1525 */
  1539 */
  1526 bool HbAnchorLayout::setAnchor( const QString& startId, Edge startEdge, const QString& endId, Edge endEdge, qreal length )
  1540 HbAnchor *HbAnchorLayout::setAnchor( const QString& startId, Edge startEdge, const QString& endId, Edge endEdge, qreal length )
  1527 {
  1541 {
  1528     Q_D( HbAnchorLayout );
  1542     Q_D( HbAnchorLayout );
  1529 
  1543 
  1530     HbAnchor *anchor = new HbAnchor();
  1544     HbAnchor *anchor = new HbAnchor( startId, startEdge, endId, endEdge, length );
  1531     anchor->mStartId = startId;
  1545 
  1532     anchor->mStartEdge = startEdge;
  1546     HbAnchor *result = d->setAnchor( anchor );
  1533     anchor->mEndId = endId;
  1547 
  1534     anchor->mEndEdge = endEdge;
  1548     if( result ) {
  1535     anchor->mValue = length;
       
  1536 
       
  1537     if (d->setAnchor(anchor)) {
       
  1538         invalidate();
  1549         invalidate();
  1539         return true;
  1550         return result;
  1540     }
  1551     }
  1541 
  1552 
  1542     delete anchor;
  1553     delete anchor;
  1543 
  1554 
  1544     return false;
  1555     return 0;
       
  1556 }
       
  1557 
       
  1558 
       
  1559 /*!
       
  1560     Set previously created anchor. Ownership is passed to layout.
       
  1561 
       
  1562     \param anchor anchor, created somewhere outside
       
  1563     \return reference to updated/created anchor (not necessary the same as in input parameter), or zero if something was wrong.
       
  1564 */
       
  1565 HbAnchor *HbAnchorLayout::setAnchor( HbAnchor *anchor )
       
  1566 {
       
  1567     Q_D( HbAnchorLayout );
       
  1568 
       
  1569     HbAnchor *result = d->setAnchor( anchor );
       
  1570 
       
  1571     if( result ) {
       
  1572         invalidate();
       
  1573         return result;
       
  1574     }
       
  1575 
       
  1576     return 0;
  1545 }
  1577 }
  1546 
  1578 
  1547 
  1579 
  1548 /*!
  1580 /*!
  1549     Removes anchor (\a startId, \a startEdge, \a endNodeId, \a endEdge).
  1581     Removes anchor (\a startId, \a startEdge, \a endNodeId, \a endEdge).
  1559     Q_D( HbAnchorLayout );
  1591     Q_D( HbAnchorLayout );
  1560     bool modified = false;
  1592     bool modified = false;
  1561 
  1593 
  1562     for (int i = d->mAllAnchors.size() - 1; i >= 0; --i) {
  1594     for (int i = d->mAllAnchors.size() - 1; i >= 0; --i) {
  1563         HbAnchor* anchor = d->mAllAnchors[i];
  1595         HbAnchor* anchor = d->mAllAnchors[i];
  1564         if( ( anchor->mStartId == startNodeId && anchor->mStartEdge == startEdge &&
  1596         if( ( anchor->startNodeId() == startNodeId && anchor->startEdge() == startEdge &&
  1565                 anchor->mEndId == endNodeId && anchor->mEndEdge == endEdge ) ||
  1597                 anchor->endNodeId() == endNodeId && anchor->endEdge() == endEdge ) ||
  1566             ( anchor->mStartId == endNodeId && anchor->mStartEdge == endEdge &&
  1598             ( anchor->startNodeId() == endNodeId && anchor->startEdge() == endEdge &&
  1567                 anchor->mEndId == startNodeId && anchor->mEndEdge == startEdge ) ){
  1599                 anchor->endNodeId() == startNodeId && anchor->endEdge() == startEdge ) ){
  1568             delete d->mAllAnchors.takeAt(i);
  1600             delete d->mAllAnchors.takeAt(i);
  1569             modified = true;
  1601             modified = true;
  1570             break;
       
  1571         }
  1602         }
  1572     }
  1603     }
  1573 
  1604 
  1574     if (modified) {
  1605     if (modified) {
  1575         d->removeItemIfNeeded( d->mMeshMap.key( startNodeId ) );
  1606         d->removeItemIfNeeded( d->mItemToNodeIdMap.key( startNodeId ) );
  1576         d->removeItemIfNeeded( d->mMeshMap.key( endNodeId ) );
  1607         d->removeItemIfNeeded( d->mItemToNodeIdMap.key( endNodeId ) );
  1577         invalidate();
  1608         invalidate();
  1578         return true;
  1609         return true;
  1579     }
  1610     }
  1580     return false;
  1611     return false;
  1581 }
  1612 }
  1599     Q_D( HbAnchorLayout );
  1630     Q_D( HbAnchorLayout );
  1600     bool modified = false;
  1631     bool modified = false;
  1601 
  1632 
  1602     for (int i = d->mAllAnchors.size() - 1; i >= 0; --i) {
  1633     for (int i = d->mAllAnchors.size() - 1; i >= 0; --i) {
  1603         HbAnchor* anchor = d->mAllAnchors[i];
  1634         HbAnchor* anchor = d->mAllAnchors[i];
  1604         if( ( anchor->mStartItem == startItem && anchor->mStartEdge == startEdge &&
  1635         if( ( anchor->startItem() == startItem && anchor->startEdge() == startEdge &&
  1605                 anchor->mEndItem == endItem && anchor->mEndEdge == endEdge ) ||
  1636                 anchor->endItem() == endItem && anchor->endEdge() == endEdge ) ||
  1606                 ( anchor->mStartItem == endItem && anchor->mStartEdge == endEdge &&
  1637                 ( anchor->startItem() == endItem && anchor->startEdge() == endEdge &&
  1607                 anchor->mEndItem == startItem && anchor->mEndEdge == startEdge ) ){
  1638                 anchor->endItem() == startItem && anchor->endEdge() == startEdge ) ){
  1608             delete d->mAllAnchors.takeAt(i);
  1639             delete d->mAllAnchors.takeAt(i);
  1609             modified = true;
  1640             modified = true;
  1610             break;
       
  1611         }
  1641         }
  1612     }
  1642     }
  1613 
  1643 
  1614     if (modified) {
  1644     if (modified) {
  1615         d->removeItemIfNeeded( startItem );
  1645         d->removeItemIfNeeded( startItem );
  1619     }
  1649     }
  1620     return false;
  1650     return false;
  1621 }
  1651 }
  1622 
  1652 
  1623 
  1653 
       
  1654 /*!
       
  1655 
       
  1656     Removes and deletes an anchor (\a anchor) from layout.
       
  1657 
       
  1658     If layout contains exactly the same anchor, with the same reference, then only this
       
  1659     one is removed and deleted. Otherwise all anchors with the same start and end points
       
  1660     are removed and deleted ( \a anchor is not deleted in this case because this instance
       
  1661     is not in layout ).
       
  1662 
       
  1663     Notice: The item will be removed from the layout if this is the last
       
  1664     anchor connecting the item.
       
  1665 
       
  1666     \param anchor anchor to be removed.
       
  1667     \return true if anchor was successfully removed, false otherwise
       
  1668 */
       
  1669 bool HbAnchorLayout::removeAnchor( HbAnchor *anchor )
       
  1670 {
       
  1671     Q_D( HbAnchorLayout );
       
  1672 
       
  1673     if( d->mAllAnchors.removeOne( anchor ) ) {
       
  1674         d->removeItemIfNeeded( anchor->startItem() );
       
  1675         d->removeItemIfNeeded( anchor->endItem() );
       
  1676         delete anchor;
       
  1677         invalidate();
       
  1678         return true;
       
  1679     }
       
  1680 
       
  1681     bool modified = true;
       
  1682 
       
  1683     for (int i = d->mAllAnchors.size() - 1; i >= 0; --i) {
       
  1684         HbAnchor* item = d->mAllAnchors[i];
       
  1685         if( ( ( idConditionStartStart( item, anchor ) || itemConditionStartStart( item, anchor ) ) &&
       
  1686             ( idConditionEndEnd( item, anchor ) || itemConditionEndEnd( item, anchor ) ) &&
       
  1687             ( edgeConditionStartStart( item, anchor ) ) &&
       
  1688             ( edgeConditionEndEnd( item, anchor ) ) )    // condition for same direction anchor
       
  1689 
       
  1690             ||
       
  1691 
       
  1692             ( ( idConditionStartEnd( item, anchor ) || itemConditionStartEnd( item, anchor ) ) &&
       
  1693             ( idConditionEndStart( item, anchor )  || itemConditionEndStart( item, anchor ) ) &&
       
  1694             ( edgeConditionStartEnd( item, anchor ) ) &&
       
  1695             ( edgeConditionEndStart( item, anchor ) ) ) ){  // condition for opposite direction anchor
       
  1696             delete d->mAllAnchors.takeAt(i);
       
  1697             modified = true;
       
  1698             break;
       
  1699         }
       
  1700     }
       
  1701 
       
  1702     if( modified ) {
       
  1703         d->removeItemIfNeeded( anchor->startItem() );
       
  1704         d->removeItemIfNeeded( anchor->endItem() );
       
  1705         invalidate();
       
  1706         return true;
       
  1707     }
       
  1708 
       
  1709 
       
  1710     return modified;
       
  1711 }
  1624 
  1712 
  1625 /*!
  1713 /*!
  1626     Removes all anchors starting or ending to \a nodeId.
  1714     Removes all anchors starting or ending to \a nodeId.
  1627     Same is done with associated item
  1715     Same is done with associated item
  1628 
  1716 
  1636 
  1724 
  1637     // if association, do removal
  1725     // if association, do removal
  1638 
  1726 
  1639     for (int i = d->mAllAnchors.size() - 1; i >= 0; --i) {
  1727     for (int i = d->mAllAnchors.size() - 1; i >= 0; --i) {
  1640         HbAnchor *anchor = d->mAllAnchors.at(i);
  1728         HbAnchor *anchor = d->mAllAnchors.at(i);
  1641         if (anchor->mStartId == nodeId || anchor->mEndId == nodeId) {
  1729         if (anchor->startNodeId() == nodeId || anchor->endNodeId() == nodeId) {
  1642             QGraphicsLayoutItem *startItem = anchor->mStartItem;
  1730             QGraphicsLayoutItem *startItem = anchor->startItem();
  1643             QGraphicsLayoutItem *endItem = anchor->mEndItem;
  1731             QGraphicsLayoutItem *endItem = anchor->endItem();
  1644 
  1732 
  1645             delete d->mAllAnchors.takeAt(i);
  1733             delete d->mAllAnchors.takeAt(i);
  1646             d->removeItemIfNeeded( startItem );
  1734             d->removeItemIfNeeded( startItem );
  1647             d->removeItemIfNeeded( endItem );
  1735             d->removeItemIfNeeded( endItem );
  1648 
  1736 
  1692 
  1780 
  1693     if ( !nodeId.isNull() && ( item != 0 ) ) {
  1781     if ( !nodeId.isNull() && ( item != 0 ) ) {
  1694 
  1782 
  1695         for( int i = 0; i < d->mAllAnchors.size(); i++ ) {
  1783         for( int i = 0; i < d->mAllAnchors.size(); i++ ) {
  1696             HbAnchor *anchor = d->mAllAnchors.at(i);
  1784             HbAnchor *anchor = d->mAllAnchors.at(i);
  1697             if( anchor->mStartItem == item ) {
  1785             if( anchor->startItem() == item ) {
  1698                 anchor->mStartId = nodeId;
  1786                 anchor->d_ptr->mStartId = nodeId;
  1699                 modified = true;
  1787                 modified = true;
  1700             } else if( anchor->mStartId == nodeId ) {
  1788             } else if( anchor->startNodeId() == nodeId ) {
  1701                 anchor->mStartItem = item;
  1789                 anchor->d_ptr->mStartItem = item;
  1702                 modified = true;
  1790                 modified = true;
  1703             }
  1791             }
  1704 
  1792 
  1705             if( anchor->mEndItem == item ) {
  1793             if( anchor->endItem() == item ) {
  1706                 anchor->mEndId = nodeId;
  1794                 anchor->d_ptr->mEndId = nodeId;
  1707                 modified = true;
  1795                 modified = true;
  1708             } else if( anchor->mEndId == nodeId ) {
  1796             } else if( anchor->endNodeId() == nodeId ) {
  1709                 anchor->mEndItem = item;
  1797                 anchor->d_ptr->mEndItem = item;
  1710                 modified = true;
  1798                 modified = true;
  1711             }
  1799             }
  1712 
  1800 
  1713         }
  1801         }
  1714 
  1802 
  1715         // Remove previous item -> id.
  1803         // Remove previous item -> id.
  1716         HbMeshItemMapIterator it = d->mMeshMap.begin();
  1804         ItemToNodeIdMapIterator it = d->mItemToNodeIdMap.begin();
  1717         while ( it != d->mMeshMap.end() ) {
  1805         while ( it != d->mItemToNodeIdMap.end() ) {
  1718             if ( it.value() == nodeId ) {
  1806             if ( it.value() == nodeId ) {
  1719                 it = d->mMeshMap.erase( it );
  1807                 it = d->mItemToNodeIdMap.erase( it );
  1720             } else {
  1808             } else {
  1721                 ++it;
  1809                 ++it;
  1722             }
  1810             }
  1723         }
  1811         }
  1724         d->addItemIfNeeded( item );
  1812         d->addItemIfNeeded( item );
  1725         d->mMeshMap.insert( item, nodeId );
  1813         d->mItemToNodeIdMap.insert( item, nodeId );
  1726     } else {
  1814     } else {
  1727         return false;
  1815         return false;
  1728     }
  1816     }
  1729 
  1817 
  1730     if( modified ){
  1818     if( modified ){
  1752     }
  1840     }
  1753 
  1841 
  1754     for( int i = 0; i < d->mAllAnchors.size(); i++ ) {
  1842     for( int i = 0; i < d->mAllAnchors.size(); i++ ) {
  1755         HbAnchor *anchor = d->mAllAnchors.at(i);
  1843         HbAnchor *anchor = d->mAllAnchors.at(i);
  1756 
  1844 
  1757         if( anchor->mStartItem == item ) {
  1845         if( anchor->startItem() == item ) {
  1758             anchor->mStartId = QString();
  1846             anchor->d_ptr->mStartId = QString();
  1759             modified = true;
  1847             modified = true;
  1760         }
  1848         }
  1761 
  1849 
  1762         if( anchor->mEndItem == item ) {
  1850         if( anchor->endItem() == item ) {
  1763             anchor->mEndId = QString();
  1851             anchor->d_ptr->mEndId = QString();
  1764             modified = true;
  1852             modified = true;
  1765         }
  1853         }
  1766     }
  1854     }
  1767 
  1855 
  1768 
  1856 
  1769     d->mMeshMap.remove(item);
  1857     d->mItemToNodeIdMap.remove(item);
  1770 
  1858 
  1771     if( modified ){
  1859     if( modified ){
  1772         invalidate();
  1860         invalidate();
  1773     }
  1861     }
  1774     return true;
  1862     return true;
  1793     }
  1881     }
  1794 
  1882 
  1795     for( int i = 0; i < d->mAllAnchors.size(); i++ ) {
  1883     for( int i = 0; i < d->mAllAnchors.size(); i++ ) {
  1796         HbAnchor *anchor = d->mAllAnchors.at(i);
  1884         HbAnchor *anchor = d->mAllAnchors.at(i);
  1797 
  1885 
  1798         if( anchor->mStartId == nodeId ) {
  1886         if( anchor->startNodeId() == nodeId ) {
  1799             anchor->mStartItem = 0;
  1887             anchor->d_ptr->mStartItem = 0;
  1800             modified = true;
  1888             modified = true;
  1801         }
  1889         }
  1802 
  1890 
  1803         if( anchor->mEndId == nodeId ) {
  1891         if( anchor->endNodeId() == nodeId ) {
  1804             anchor->mEndItem = 0;
  1892             anchor->d_ptr->mEndItem = 0;
  1805             modified = true;
  1893             modified = true;
  1806         }
  1894         }
  1807     }
  1895     }
  1808 
  1896 
  1809 
  1897 
  1810     HbMeshItemMapIterator it = d->mMeshMap.begin();
  1898     ItemToNodeIdMapIterator it = d->mItemToNodeIdMap.begin();
  1811     while ( it != d->mMeshMap.end() ) {
  1899     while ( it != d->mItemToNodeIdMap.end() ) {
  1812         if ( it.value() == nodeId ) {
  1900         if ( it.value() == nodeId ) {
  1813             it = d->mMeshMap.erase( it );
  1901             it = d->mItemToNodeIdMap.erase( it );
  1814         } else {
  1902         } else {
  1815             ++it;
  1903             ++it;
  1816         }
  1904         }
  1817     }
  1905     }
  1818 
  1906 
  1827     Clears all item id mappings.
  1915     Clears all item id mappings.
  1828 */
  1916 */
  1829 void HbAnchorLayout::removeMappings()
  1917 void HbAnchorLayout::removeMappings()
  1830 {
  1918 {
  1831     Q_D( HbAnchorLayout );
  1919     Q_D( HbAnchorLayout );
  1832     d->mMeshMap.clear();
  1920     d->mItemToNodeIdMap.clear();
  1833 
  1921 
  1834     for( int i = 0; i < d->mAllAnchors.size(); i++ ) {
  1922     for( int i = 0; i < d->mAllAnchors.size(); i++ ) {
  1835         HbAnchor *anchor = d->mAllAnchors.at(i);
  1923         HbAnchor *anchor = d->mAllAnchors.at(i);
  1836 
  1924 
  1837         if( !anchor->mStartId.isNull() ) {
  1925         if( !anchor->startNodeId().isNull() ) {
  1838             anchor->mStartItem = 0;
  1926             anchor->d_ptr->mStartItem = 0;
  1839         }
  1927         }
  1840 
  1928 
  1841         if( !anchor->mEndId.isNull() ) {
  1929         if( !anchor->endNodeId().isNull() ) {
  1842             anchor->mEndItem = 0;
  1930             anchor->d_ptr->mEndItem = 0;
  1843         }
  1931         }
  1844 
  1932 
  1845     }
  1933     }
  1846 }
  1934 }
  1847 
  1935 
  1854 void HbAnchorLayoutPrivate::addItemIfNeeded(QGraphicsLayoutItem *item)
  1942 void HbAnchorLayoutPrivate::addItemIfNeeded(QGraphicsLayoutItem *item)
  1855 {
  1943 {
  1856     Q_Q(HbAnchorLayout);
  1944     Q_Q(HbAnchorLayout);
  1857 
  1945 
  1858     if (!item) {
  1946     if (!item) {
  1859         //qWarning() << "HbAnchorLayout::addItemIfNeeded : item is NULL";
       
  1860         return;
  1947         return;
  1861     }
  1948     }
  1862 
  1949 
  1863     if (item == q) {
  1950     if (item == q) {
  1864         //qWarning() << "HbAnchorLayout::addItemIfNeeded : layout cannot be added";
       
  1865         return;
  1951         return;
  1866     }
  1952     }
  1867 
  1953 
  1868     if (mItems.contains(item)) {
  1954     if (mItems.contains(item)) {
  1869         //qWarning() << "HbAnchorLayout::addItemIfNeeded : item is already in layout";
       
  1870         return;
  1955         return;
  1871     }
  1956     }
  1872 
  1957 
  1873     HbLayoutUtils::addChildItem(q, item);
  1958     HbLayoutUtils::addChildItem(q, item);
  1874     mItems.append(item);
  1959     mItems.append(item);
  1920     \return node id for given item.
  2005     \return node id for given item.
  1921 */
  2006 */
  1922 QString HbAnchorLayout::nodeId( QGraphicsLayoutItem *item ) const
  2007 QString HbAnchorLayout::nodeId( QGraphicsLayoutItem *item ) const
  1923 {
  2008 {
  1924     Q_D( const HbAnchorLayout );
  2009     Q_D( const HbAnchorLayout );
  1925     if( d->mMeshMap.contains( item ) ) {
  2010     if( d->mItemToNodeIdMap.contains( item ) ) {
  1926         return d->mMeshMap.value( item );
  2011         return d->mItemToNodeIdMap.value( item );
  1927     }
  2012     }
  1928     return QString();
  2013     return QString();
  1929 }
  2014 }
  1930 
  2015 
  1931 /*!
  2016 /*!
  1936 {
  2021 {
  1937     Q_D( const HbAnchorLayout );
  2022     Q_D( const HbAnchorLayout );
  1938     QStringList list;
  2023     QStringList list;
  1939     int c = d->mAllAnchors.count();
  2024     int c = d->mAllAnchors.count();
  1940     while (c--) {
  2025     while (c--) {
  1941         QString id = d->mAllAnchors.at(c)->mStartId;
  2026         QString id = d->mAllAnchors.at(c)->startNodeId();
  1942         if (!list.contains(id) && !id.isNull()) {
  2027         if (!list.contains(id) && !id.isNull()) {
  1943             list.append(id);
  2028             list.append(id);
  1944         }
  2029         }
  1945         id = d->mAllAnchors.at(c)->mEndId;
  2030         id = d->mAllAnchors.at(c)->endNodeId();
  1946         if (!list.contains(id) && !id.isNull()) {
  2031         if (!list.contains(id) && !id.isNull()) {
  1947             list.append(id);
  2032             list.append(id);
  1948         }
  2033         }
  1949     }
  2034     }
  1950     return list;
  2035     return list;
  1956     \return item reference for given item.
  2041     \return item reference for given item.
  1957 */
  2042 */
  1958 QGraphicsLayoutItem *HbAnchorLayout::itemByNodeId( const QString& nodeId ) const
  2043 QGraphicsLayoutItem *HbAnchorLayout::itemByNodeId( const QString& nodeId ) const
  1959 {
  2044 {
  1960     Q_D( const HbAnchorLayout );
  2045     Q_D( const HbAnchorLayout );
  1961     return d->mMeshMap.key( nodeId );
  2046     return d->mItemToNodeIdMap.key( nodeId );
  1962 }
  2047 }
  1963 
  2048 
  1964 
  2049 
  1965 /*!
  2050 /*!
  1966     \reimp
  2051     \reimp
  1972         return;
  2057         return;
  1973     }
  2058     }
  1974     QGraphicsLayoutItem *item = itemAt( index );
  2059     QGraphicsLayoutItem *item = itemAt( index );
  1975     if ( item ) {
  2060     if ( item ) {
  1976         for ( int i = d->mAllAnchors.count() - 1; i >= 0; i-- ) {
  2061         for ( int i = d->mAllAnchors.count() - 1; i >= 0; i-- ) {
  1977             if ( ( ( d->mAllAnchors.at(i)->mStartItem == item ) && ( d->mAllAnchors.at(i)->mStartId.isNull() ) ) ||
  2062             if ( ( ( d->mAllAnchors.at(i)->startItem() == item ) && ( d->mAllAnchors.at(i)->startNodeId().isNull() ) ) ||
  1978                  ( ( d->mAllAnchors.at(i)->mEndItem == item ) && ( d->mAllAnchors.at(i)->mEndId.isNull() ) ) ) {
  2063                  ( ( d->mAllAnchors.at(i)->endItem() == item ) && ( d->mAllAnchors.at(i)->endNodeId().isNull() ) ) ) {
  1979                     delete d->mAllAnchors.takeAt(i);
  2064                     delete d->mAllAnchors.takeAt(i);
  1980             }
  2065             }
  1981         }
  2066         }
  1982 
  2067 
  1983         removeMapping( d->mMeshMap.value(item) );
  2068         removeMapping( d->mItemToNodeIdMap.value(item) );
  1984         item->setParentLayoutItem( 0 );
  2069         item->setParentLayoutItem( 0 );
  1985         d->mItems.removeAt( index );
  2070         d->mItems.removeAt( index );
  1986     }
  2071     }
  1987 
  2072 
  1988     invalidate();
  2073     invalidate();