summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview/qgraphicslayoutitem.cpp
blob: fb08b9e9849c80c9312104448517ab906608cea4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qglobal.h"

#ifndef QT_NO_GRAPHICSVIEW

#include "qgraphicslayout.h"
#include "qgraphicsscene.h"
#include "qgraphicslayoutitem.h"
#include "qgraphicslayoutitem_p.h"
#include "qwidget.h"
#include "qgraphicswidget.h"

#include <QtDebug>

QT_BEGIN_NAMESPACE

/*
    COMBINE_SIZE() is identical to combineSize(), except that it
    doesn't evaluate 'size' unless necessary.
*/
#define COMBINE_SIZE(result, size) \
    do { \
        if ((result).width() < 0 || (result).height() < 0) \
            combineSize((result), (size)); \
    } while (false)

static void combineSize(QSizeF &result, const QSizeF &size)
{
    if (result.width() < 0)
        result.setWidth(size.width());
    if (result.height() < 0)
        result.setHeight(size.height());
}

static void boundSize(QSizeF &result, const QSizeF &size)
{
    if (size.width() >= 0 && size.width() < result.width())
        result.setWidth(size.width());
    if (size.height() >= 0 && size.height() < result.height())
        result.setHeight(size.height());
}

static void expandSize(QSizeF &result, const QSizeF &size)
{
    if (size.width() >= 0 && size.width() > result.width())
        result.setWidth(size.width());
    if (size.height() >= 0 && size.height() > result.height())
        result.setHeight(size.height());
}

static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qreal &descent)
{
    if (minimum >= 0 && maximum >= 0 && minimum > maximum)
        minimum = maximum;

    if (preferred >= 0) {
        if (minimum >= 0 && preferred < minimum) {
            preferred = minimum;
        } else if (maximum >= 0 && preferred > maximum) {
            preferred = maximum;
        }
    }

    if (minimum >= 0 && descent > minimum)
        descent = minimum;
}

/*!
    \internal
*/
QGraphicsLayoutItemPrivate::QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *par, bool layout)
    : parent(par), userSizeHints(0), isLayout(layout), ownedByLayout(false), graphicsItem(0)
{
}

/*!
    \internal
*/
QGraphicsLayoutItemPrivate::~QGraphicsLayoutItemPrivate()
{
    // Remove any lazily allocated data
    delete[] userSizeHints;
}

/*!
    \internal
*/
void QGraphicsLayoutItemPrivate::init()
{
    sizeHintCacheDirty = true;
    sizeHintWithConstraintCacheDirty = true;
}

/*!
    \internal
*/
QSizeF *QGraphicsLayoutItemPrivate::effectiveSizeHints(const QSizeF &constraint) const
{
    Q_Q(const QGraphicsLayoutItem);
    QSizeF *sizeHintCache;
    const bool hasConstraint = constraint.width() >= 0 || constraint.height() >= 0;
    if (hasConstraint) {
        if (!sizeHintWithConstraintCacheDirty && constraint == cachedConstraint)
            return cachedSizeHintsWithConstraints;
        sizeHintCache = cachedSizeHintsWithConstraints;
    } else {
        if (!sizeHintCacheDirty)
            return cachedSizeHints;
        sizeHintCache = cachedSizeHints;
    }

    for (int i = 0; i < Qt::NSizeHints; ++i) {
        sizeHintCache[i] = constraint;
        if (userSizeHints)
            combineSize(sizeHintCache[i], userSizeHints[i]);
    }

    QSizeF &minS = sizeHintCache[Qt::MinimumSize];
    QSizeF &prefS = sizeHintCache[Qt::PreferredSize];
    QSizeF &maxS = sizeHintCache[Qt::MaximumSize];
    QSizeF &descentS = sizeHintCache[Qt::MinimumDescent];

    normalizeHints(minS.rwidth(), prefS.rwidth(), maxS.rwidth(), descentS.rwidth());
    normalizeHints(minS.rheight(), prefS.rheight(), maxS.rheight(), descentS.rheight());

    // if the minimum, preferred and maximum sizes contradict each other
    // (e.g. the minimum is larger than the maximum) we give priority to
    // the maximum size, then the minimum size and finally the preferred size
    COMBINE_SIZE(maxS, q->sizeHint(Qt::MaximumSize, maxS));
    combineSize(maxS, QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
    expandSize(maxS, prefS);
    expandSize(maxS, minS);
    boundSize(maxS, QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));

    COMBINE_SIZE(minS, q->sizeHint(Qt::MinimumSize, minS));
    expandSize(minS, QSizeF(0, 0));
    boundSize(minS, prefS);
    boundSize(minS, maxS);

    COMBINE_SIZE(prefS, q->sizeHint(Qt::PreferredSize, prefS));
    expandSize(prefS, minS);
    boundSize(prefS, maxS);

    // Not supported yet
    // COMBINE_SIZE(descentS, q->sizeHint(Qt::MinimumDescent, constraint));

    if (hasConstraint) {
        cachedConstraint = constraint;
        sizeHintWithConstraintCacheDirty = false;
    } else {
        sizeHintCacheDirty = false;
    }
    return sizeHintCache;
}


/*!
    \internal

    Returns the parent item of this layout, or 0 if this layout is
    not installed on any widget.

    If this is the item that the layout is installed on, it will return "itself".

    If the layout is a sub-layout, this function returns the parent
    widget of the parent layout.

    Note that it will traverse up the layout item hierarchy instead of just calling
    QGraphicsItem::parentItem(). This is on purpose.

    \sa parent()
*/
QGraphicsItem *QGraphicsLayoutItemPrivate::parentItem() const
{
    Q_Q(const QGraphicsLayoutItem);

    const QGraphicsLayoutItem *parent = q;
    while (parent && parent->isLayout()) {
        parent = parent->parentLayoutItem();
    }
    return parent ? parent->graphicsItem() : 0;
}

/*!
    \internal

     Ensures that userSizeHints is allocated.
     This function must be called before any dereferencing.
*/
void QGraphicsLayoutItemPrivate::ensureUserSizeHints()
{
    if (!userSizeHints)
        userSizeHints = new QSizeF[Qt::NSizeHints];
}

/*!
    \internal

    Sets the user size hint \a which to \a size. Use an invalid size to unset the size hint.
 */
void QGraphicsLayoutItemPrivate::setSize(Qt::SizeHint which, const QSizeF &size)
{
    Q_Q(QGraphicsLayoutItem);

    if (userSizeHints) {
        if (size == userSizeHints[which])
            return;
    } else if (size.width() < 0 && size.height() < 0) {
        return;
    }

    ensureUserSizeHints();
    userSizeHints[which] = size;
    q->updateGeometry();
}

/*!
    \internal

    Sets the width of the user size hint \a which to \a width.
 */
void QGraphicsLayoutItemPrivate::setSizeComponent(
    Qt::SizeHint which, SizeComponent component, qreal value)
{
    Q_Q(QGraphicsLayoutItem);
    ensureUserSizeHints();
    qreal &userValue = (component == Width)
        ? userSizeHints[which].rwidth()
        : userSizeHints[which].rheight();
    if (value == userValue)
        return;
    userValue = value;
    q->updateGeometry();
}


bool QGraphicsLayoutItemPrivate::hasHeightForWidth() const
{
    Q_Q(const QGraphicsLayoutItem);
    if (isLayout) {
        const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q);
        for (int i = l->count() - 1; i >= 0; --i) {
            if (QGraphicsLayoutItemPrivate::get(l->itemAt(i))->hasHeightForWidth())
                return true;
        }
    } else if (QGraphicsItem *item = q->graphicsItem()) {
        if (item->isWidget()) {
            QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
            if (w->layout()) {
                return QGraphicsLayoutItemPrivate::get(w->layout())->hasHeightForWidth();
            }
        }
    }
    return q->sizePolicy().hasHeightForWidth();
}

bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const
{
    // enable this code when we add QSizePolicy::hasWidthForHeight() (For 4.8)
#if 1
    return false;
#else
    Q_Q(const QGraphicsLayoutItem);
    if (isLayout) {
        const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q);
        for (int i = l->count() - 1; i >= 0; --i) {
            if (QGraphicsLayoutItemPrivate::get(l->itemAt(i))->hasWidthForHeight())
                return true;
        }
    } else if (QGraphicsItem *item = q->graphicsItem()) {
        if (item->isWidget()) {
            QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
            if (w->layout()) {
                return QGraphicsLayoutItemPrivate::get(w->layout())->hasWidthForHeight();
            }
        }
    }
    return q->sizePolicy().hasWidthForHeight();
#endif
}

/*!
    \class QGraphicsLayoutItem
    \brief The QGraphicsLayoutItem class can be inherited to allow your custom
    items to be managed by layouts.
    \since 4.4
    \ingroup graphicsview-api

    QGraphicsLayoutItem is an abstract class that defines a set of virtual
    functions describing sizes, size policies, and size hints for any object
    arranged by QGraphicsLayout. The API contains functions relevant
    for both the item itself and for the user of the item as most of
    QGraphicsLayoutItem's functions are also part of the subclass' public API.

    In most cases, existing layout-aware classes such as QGraphicsWidget and
    QGraphicsLayout already provide the functionality you require. However,
    subclassing these classes will enable you to create both graphical
    elements that work well with layouts (QGraphicsWidget) or custom layouts
    (QGraphicsLayout).

    \section1 Subclassing QGraphicsLayoutItem

    If you create a subclass of QGraphicsLayoutItem and reimplement its
    virtual functions, you will enable the layout to resize and position your
    item along with other QGraphicsLayoutItems including QGraphicsWidget
    and QGraphicsLayout.

    You can start by reimplementing important functions: the protected
    sizeHint() function, as well as the public setGeometry()
    function. If you want your items to be aware of immediate geometry
    changes, you can also reimplement updateGeometry().

    The geometry, size hint, and size policy affect the item's size and
    position. Calling setGeometry() will always resize and reposition the item
    immediately. Normally, this function is called by QGraphicsLayout after
    the layout has been activated, but it can also be called by the item's user
    at any time.

    The sizeHint() function returns the item' minimum, preferred and maximum
    size hints. You can override these properties by calling setMinimumSize(),
    setPreferredSize() or setMaximumSize(). You can also use functions such as
    setMinimumWidth() or setMaximumHeight() to set only the width or height
    component if desired.

    The effectiveSizeHint() function, on the other hand, returns a size hint
    for any given Qt::SizeHint, and guarantees that the returned size is bound
    to the minimum and maximum sizes and size hints. You can set the item's
    vertical and horizontal size policy by calling setSizePolicy(). The
    sizePolicy property is used by the layout system to describe how this item
    prefers to grow or shrink.

    \section1 Nesting QGraphicsLayoutItems

    QGraphicsLayoutItems can be nested within other QGraphicsLayoutItems,
    similar to layouts that can contain sublayouts. This is done either by
    passing a QGraphicsLayoutItem pointer to QGraphicsLayoutItem's
    protected constructor, or by calling setParentLayoutItem(). The
    parentLayoutItem() function returns a pointer to the item's layoutItem
    parent. If the item's parent is 0 or if the parent does not inherit
    from QGraphicsItem, the parentLayoutItem() function then returns 0.
    isLayout() returns true if the QGraphicsLayoutItem subclass is itself a
    layout, or false otherwise.

    Qt uses QGraphicsLayoutItem to provide layout functionality in the
    \l{Graphics View Framework}, but in the future its use may spread
    throughout Qt itself.

    \sa QGraphicsWidget, QGraphicsLayout, QGraphicsLinearLayout,
    QGraphicsGridLayout
*/

/*!
    Constructs the QGraphicsLayoutItem object. \a parent becomes the object's
    parent. If \a isLayout is true the item is a layout, otherwise
    \a isLayout is false.
*/
QGraphicsLayoutItem::QGraphicsLayoutItem(QGraphicsLayoutItem *parent, bool isLayout)
    : d_ptr(new QGraphicsLayoutItemPrivate(parent, isLayout))
{
    Q_D(QGraphicsLayoutItem);
    d->init();
    d->sizePolicy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    d->q_ptr = this;
}

/*!
    \internal
*/
QGraphicsLayoutItem::QGraphicsLayoutItem(QGraphicsLayoutItemPrivate &dd)
    : d_ptr(&dd)
{
    Q_D(QGraphicsLayoutItem);
    d->init();
    d->q_ptr = this;
}

/*!
    Destroys the QGraphicsLayoutItem object.
*/
QGraphicsLayoutItem::~QGraphicsLayoutItem()
{
    QGraphicsLayoutItem *parentLI = parentLayoutItem();
    if (parentLI && parentLI->isLayout()) {
        QGraphicsLayout *lay = static_cast<QGraphicsLayout*>(parentLI);
        // this is not optimal
        for (int i = lay->count() - 1; i >= 0; --i) {
            if (lay->itemAt(i) == this) {
                lay->removeAt(i);
                break;
            }
        }
    }
}

/*!
    \fn virtual QSizeF QGraphicsLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const = 0;

    This pure virtual function returns the size hint for \a which of the
    QGraphicsLayoutItem, using the width or height of \a constraint to
    constrain the output.

    Reimplement this function in a subclass of QGraphicsLayoutItem to
    provide the necessary size hints for your items.

    \sa effectiveSizeHint()
*/

/*!
    Sets the size policy to \a policy. The size policy describes how the item
    should grow horizontally and vertically when arranged in a layout.

    QGraphicsLayoutItem's default size policy is (QSizePolicy::Fixed,
    QSizePolicy::Fixed, QSizePolicy::DefaultType), but it is common for
    subclasses to change the default. For example, QGraphicsWidget defaults
    to (QSizePolicy::Preferred, QSizePolicy::Preferred,
    QSizePolicy::DefaultType).

    \sa sizePolicy(), QWidget::sizePolicy()
*/
void QGraphicsLayoutItem::setSizePolicy(const QSizePolicy &policy)
{
    Q_D(QGraphicsLayoutItem);
    if (d->sizePolicy == policy)
        return;
    d->sizePolicy = policy;
    updateGeometry();
}

/*!
    \overload

    This function is equivalent to calling
    setSizePolicy(QSizePolicy(\a hPolicy, \a vPolicy, \a controlType)).

    \sa sizePolicy(), QWidget::sizePolicy()
*/
void QGraphicsLayoutItem::setSizePolicy(QSizePolicy::Policy hPolicy,
                                        QSizePolicy::Policy vPolicy,
                                        QSizePolicy::ControlType controlType)
{
    setSizePolicy(QSizePolicy(hPolicy, vPolicy, controlType));
}

/*!
    Returns the current size policy.

    \sa setSizePolicy(), QWidget::sizePolicy()
*/
QSizePolicy QGraphicsLayoutItem::sizePolicy() const
{
    Q_D(const QGraphicsLayoutItem);
    return d->sizePolicy;
}

/*!
    Sets the minimum size to \a size. This property overrides sizeHint() for
    Qt::MinimumSize and ensures that effectiveSizeHint() will never return
    a size smaller than \a size. In order to unset the minimum size, use an
    invalid size.

    \sa minimumSize(), maximumSize(), preferredSize(), Qt::MinimumSize,
    sizeHint(), setMinimumWidth(), setMinimumHeight()
*/
void QGraphicsLayoutItem::setMinimumSize(const QSizeF &size)
{
    d_ptr->setSize(Qt::MinimumSize, size);
}

/*!
    \fn QGraphicsLayoutItem::setMinimumSize(qreal w, qreal h)

    This convenience function is equivalent to calling
    setMinimumSize(QSizeF(\a w, \a h)).

    \sa minimumSize(), setMaximumSize(), setPreferredSize(), sizeHint()
*/

/*!
    Returns the minimum size.

    \sa setMinimumSize(), preferredSize(), maximumSize(), Qt::MinimumSize,
    sizeHint()
*/
QSizeF QGraphicsLayoutItem::minimumSize() const
{
    return effectiveSizeHint(Qt::MinimumSize);
}

/*!
    Sets the minimum width to \a width.

    \sa minimumWidth(), setMinimumSize(), minimumSize()
*/
void QGraphicsLayoutItem::setMinimumWidth(qreal width)
{
    d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Width, width);
}

/*!
    Sets the minimum height to \a height.

    \sa minimumHeight(), setMinimumSize(), minimumSize()
*/
void QGraphicsLayoutItem::setMinimumHeight(qreal height)
{
    d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Height, height);
}


/*!
    Sets the preferred size to \a size. This property overrides sizeHint() for
    Qt::PreferredSize and provides the default value for effectiveSizeHint().
    In order to unset the preferred size, use an invalid size.

    \sa preferredSize(), minimumSize(), maximumSize(), Qt::PreferredSize,
    sizeHint()
*/
void QGraphicsLayoutItem::setPreferredSize(const QSizeF &size)
{
    d_ptr->setSize(Qt::PreferredSize, size);
}

/*!
    \fn QGraphicsLayoutItem::setPreferredSize(qreal w, qreal h)

    This convenience function is equivalent to calling
    setPreferredSize(QSizeF(\a w, \a h)).

    \sa preferredSize(), setMaximumSize(), setMinimumSize(), sizeHint()
*/

/*!
    Returns the preferred size.

    \sa setPreferredSize(), minimumSize(), maximumSize(), Qt::PreferredSize,
    sizeHint()
*/
QSizeF QGraphicsLayoutItem::preferredSize() const
{
    return effectiveSizeHint(Qt::PreferredSize);
}

/*!
    Sets the preferred height to \a height.

    \sa preferredWidth(), setPreferredSize(), preferredSize()
*/
void QGraphicsLayoutItem::setPreferredHeight(qreal height)
{
    d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Height, height);
}

/*!
    Sets the preferred width to \a width.

    \sa preferredHeight(), setPreferredSize(), preferredSize()
*/
void QGraphicsLayoutItem::setPreferredWidth(qreal width)
{
    d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Width, width);
}

/*!
    Sets the maximum size to \a size. This property overrides sizeHint() for
    Qt::MaximumSize and ensures that effectiveSizeHint() will never return a
    size larger than \a size. In order to unset the maximum size, use an
    invalid size.

    \sa maximumSize(), minimumSize(), preferredSize(), Qt::MaximumSize,
    sizeHint()
*/
void QGraphicsLayoutItem::setMaximumSize(const QSizeF &size)
{
    d_ptr->setSize(Qt::MaximumSize, size);
}

/*!
    \fn QGraphicsLayoutItem::setMaximumSize(qreal w, qreal h)

    This convenience function is equivalent to calling
    setMaximumSize(QSizeF(\a w, \a h)).

    \sa maximumSize(), setMinimumSize(), setPreferredSize(), sizeHint()
*/

/*!
    Returns the maximum size.

    \sa setMaximumSize(), minimumSize(), preferredSize(), Qt::MaximumSize,
    sizeHint()
*/
QSizeF QGraphicsLayoutItem::maximumSize() const
{
    return effectiveSizeHint(Qt::MaximumSize);
}

/*!
    Sets the maximum width to \a width.

    \sa maximumWidth(), setMaximumSize(), maximumSize()
*/
void QGraphicsLayoutItem::setMaximumWidth(qreal width)
{
    d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Width, width);
}

/*!
    Sets the maximum height to \a height.

    \sa maximumHeight(), setMaximumSize(), maximumSize()
*/
void QGraphicsLayoutItem::setMaximumHeight(qreal height)
{
    d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Height, height);
}

/*!
    \fn qreal QGraphicsLayoutItem::minimumWidth() const

    Returns the minimum width.

    \sa setMinimumWidth(), setMinimumSize(), minimumSize()
*/

/*!
    \fn qreal QGraphicsLayoutItem::minimumHeight() const

    Returns the minimum height.

    \sa setMinimumHeight(), setMinimumSize(), minimumSize()
*/

/*!
    \fn qreal QGraphicsLayoutItem::preferredWidth() const

    Returns the preferred width.

    \sa setPreferredWidth(), setPreferredSize(), preferredSize()
*/

/*!
    \fn qreal QGraphicsLayoutItem::preferredHeight() const

    Returns the preferred height.

    \sa setPreferredHeight(), setPreferredSize(), preferredSize()
*/

/*!
    \fn qreal QGraphicsLayoutItem::maximumWidth() const

    Returns the maximum width.

    \sa setMaximumWidth(), setMaximumSize(), maximumSize()
*/

/*!
    \fn qreal QGraphicsLayoutItem::maximumHeight() const

    Returns the maximum height.

    \sa setMaximumHeight(), setMaximumSize(), maximumSize()
*/

/*!
    \fn virtual void QGraphicsLayoutItem::setGeometry(const QRectF &rect)

    This virtual function sets the geometry of the QGraphicsLayoutItem to
    \a rect, which is in parent coordinates (e.g., the top-left corner of \a rect
    is equivalent to the item's position in parent coordinates).

    You must reimplement this function in a subclass of QGraphicsLayoutItem to
    receive geometry updates. The layout will call this function when it does a 
    rearrangement.

    If \a rect is outside of the bounds of minimumSize and maximumSize, it
    will be adjusted to its closest size so that it is within the legal
    bounds.

    \sa geometry()
*/
void QGraphicsLayoutItem::setGeometry(const QRectF &rect)
{
    Q_D(QGraphicsLayoutItem);
    QSizeF effectiveSize = rect.size().expandedTo(effectiveSizeHint(Qt::MinimumSize))
                                .boundedTo(effectiveSizeHint(Qt::MaximumSize));
    d->geom = QRectF(rect.topLeft(), effectiveSize);
}

/*!
    \fn QRectF QGraphicsLayoutItem::geometry() const

    Returns the item's geometry (e.g., position and size) as a
    QRectF. This function is equivalent to QRectF(pos(), size()).

    \sa setGeometry()
*/
QRectF QGraphicsLayoutItem::geometry() const
{
    Q_D(const QGraphicsLayoutItem);
    return d->geom;
}

/*!
    This virtual function provides the \a left, \a top, \a right and \a bottom
    contents margins for this QGraphicsLayoutItem. The default implementation
    assumes all contents margins are 0. The parameters point to values stored
    in qreals. If any of the pointers is 0, that value will not be updated.

    \sa QGraphicsWidget::setContentsMargins()
*/
void QGraphicsLayoutItem::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
{
    if (left)
        *left = 0;
    if (top)
        *top = 0;
    if (right)
        *right = 0;
    if (bottom)
        *bottom = 0;
}

/*!
    Returns the contents rect in local coordinates.

    The contents rect defines the subrectangle used by an associated layout
    when arranging subitems. This function is a convenience function that
    adjusts the item's geometry() by its contents margins. Note that
    getContentsMargins() is a virtual function that you can reimplement to
    return the item's contents margins.

    \sa getContentsMargins(), geometry()
*/
QRectF QGraphicsLayoutItem::contentsRect() const
{
    qreal left, top, right, bottom;
    getContentsMargins(&left, &top, &right, &bottom);
    return QRectF(QPointF(), geometry().size()).adjusted(+left, +top, -right, -bottom);
}

/*!
    Returns the effective size hint for this QGraphicsLayoutItem.

    \a which is the size hint in question.
    \a constraint is an optional argument that defines a special constrain
    when calculating the effective size hint. By default, \a constraint is
    QSizeF(-1, -1), which means there is no constraint to the size hint.

    If you want to specify the widget's size hint for a given width or height,
    you can provide the fixed dimension in \a constraint. This is useful for
    widgets that can grow only either vertically or horizontally, and need to
    set either their width or their height to a special value.

    For example, a text paragraph item fit into a column width of 200 may
    grow vertically. You can pass QSizeF(200, -1) as a constraint to get a
    suitable minimum, preferred and maximum height).

    You can adjust the effective size hint by reimplementing sizeHint()
    in a QGraphicsLayoutItem subclass, or by calling one of the following
    functions: setMinimumSize(), setPreferredSize, or setMaximumSize()
    (or a combination of both).

    This function caches each of the size hints and guarantees that
    sizeHint() will be called only once for each value of \a which - unless
    \a constraint is not specified and updateGeometry() has been called.

    \sa sizeHint()
*/
QSizeF QGraphicsLayoutItem::effectiveSizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    Q_D(const QGraphicsLayoutItem);

    if (!d->userSizeHints && constraint.isValid())
        return constraint;

    // ### should respect size policy???
    return d_ptr->effectiveSizeHints(constraint)[which];
}

/*!
    This virtual function discards any cached size hint information. You
    should always call this function if you change the return value of the
    sizeHint() function. Subclasses must always call the base implementation
    when reimplementing this function.

    \sa effectiveSizeHint()
*/
void QGraphicsLayoutItem::updateGeometry()
{
    Q_D(QGraphicsLayoutItem);
    d->sizeHintCacheDirty = true;
    d->sizeHintWithConstraintCacheDirty = true;
}

/*!
    Returns the parent of this QGraphicsLayoutItem, or 0 if there is no parent,
    or if the parent does not inherit from QGraphicsLayoutItem
    (QGraphicsLayoutItem is often used through multiple inheritance with
    QObject-derived classes).

    \sa setParentLayoutItem()
*/
QGraphicsLayoutItem *QGraphicsLayoutItem::parentLayoutItem() const
{
    return d_func()->parent;
}

/*!
    Sets the parent of this QGraphicsLayoutItem to \a parent.

    \sa parentLayoutItem()
*/
void QGraphicsLayoutItem::setParentLayoutItem(QGraphicsLayoutItem *parent)
{
    d_func()->parent = parent;
}

/*!
    Returns true if this QGraphicsLayoutItem is a layout (e.g., is inherited
    by an object that arranges other QGraphicsLayoutItem objects); otherwise
    returns false.

    \sa QGraphicsLayout
*/
bool QGraphicsLayoutItem::isLayout() const
{
    return d_func()->isLayout;
}

/*!
    \since 4.6

    Returns whether a layout should delete this item in its destructor.
    If its true, then the layout will delete it. If its false, then it is
    assumed that another object has the ownership of it, and the layout won't
    delete this item.

    If the item inherits both QGraphicsItem and QGraphicsLayoutItem (such
    as QGraphicsWidget does) the item is really part of two ownership
    hierarchies. This property informs what the layout should do with its
    child items when it is destructed. In the case of QGraphicsWidget, it
    is preferred that when the layout is deleted it won't delete its children
    (since they are also part of the graphics item hierarchy).

    By default this value is initialized to false in QGraphicsLayoutItem,
    but it is overridden by QGraphicsLayout to return true. This is because
    QGraphicsLayout is not normally part of the QGraphicsItem hierarchy, so the
    parent layout should delete it.
    Subclasses might override this default behaviour by calling
    setOwnedByLayout(true).

    \sa setOwnedByLayout()
*/
bool QGraphicsLayoutItem::ownedByLayout() const
{
    return d_func()->ownedByLayout;
}
/*!
    \since 4.6

    Sets whether a layout should delete this item in its destructor or not.
    \a ownership must be true to in order for the layout to delete it.
    \sa ownedByLayout()
*/
void QGraphicsLayoutItem::setOwnedByLayout(bool ownership)
{
    d_func()->ownedByLayout = ownership;
}

/*!
 * Returns the QGraphicsItem that this layout item represents.
 * For QGraphicsWidget it will return itself. For custom items it can return an
 * aggregated value.
 *
 * \sa setGraphicsItem()
 */
QGraphicsItem *QGraphicsLayoutItem::graphicsItem() const
{
    return d_func()->graphicsItem;
}

/*!
 * If the QGraphicsLayoutItem represents a QGraphicsItem, and it wants to take
 * advantage of the automatic reparenting capabilities of QGraphicsLayout it
 * should set this value.
 * Note that if you delete \a item and not delete the layout item, you are
 * responsible of calling setGraphicsItem(0) in order to avoid having a
 * dangling pointer.
 *
 * \sa graphicsItem()
 */
void QGraphicsLayoutItem::setGraphicsItem(QGraphicsItem *item)
{
    d_func()->graphicsItem = item;
}

QT_END_NAMESPACE

#endif //QT_NO_GRAPHICSVIEW