File indexing completed on 2024-05-12 17:08:55

0001 /*
0002     SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "itemcontainer.h"
0008 #include "configoverlay.h"
0009 #include "containmentlayoutmanager_debug.h"
0010 
0011 #include <QGuiApplication>
0012 #include <QQmlContext>
0013 #include <QQmlEngine>
0014 #include <QQuickWindow>
0015 #include <QStyleHints>
0016 #include <QTimer>
0017 #include <cmath>
0018 
0019 #include <PlasmaQuick/AppletQuickItem>
0020 #include <chrono>
0021 
0022 using namespace std::chrono_literals;
0023 
0024 ItemContainer::ItemContainer(QQuickItem *parent)
0025     : QQuickItem(parent)
0026 {
0027     setFiltersChildMouseEvents(true);
0028     setFlags(QQuickItem::ItemIsFocusScope);
0029     setActiveFocusOnTab(true);
0030     setAcceptedMouseButtons(Qt::LeftButton);
0031 
0032     setLayout(qobject_cast<AppletsLayout *>(parent));
0033 
0034     m_editModeTimer = new QTimer(this);
0035     m_editModeTimer->setSingleShot(true);
0036 
0037     connect(this, &QQuickItem::parentChanged, this, [this]() {
0038         setLayout(qobject_cast<AppletsLayout *>(parentItem()));
0039     });
0040 
0041     connect(m_editModeTimer, &QTimer::timeout, this, [this]() {
0042         setEditMode(true);
0043     });
0044 
0045     setKeepMouseGrab(true);
0046     m_sizeHintAdjustTimer = new QTimer(this);
0047     m_sizeHintAdjustTimer->setSingleShot(true);
0048     m_sizeHintAdjustTimer->setInterval(0);
0049 
0050     connect(m_sizeHintAdjustTimer, &QTimer::timeout, this, &ItemContainer::sizeHintsChanged);
0051 }
0052 
0053 ItemContainer::~ItemContainer()
0054 {
0055     disconnect(this, &QQuickItem::parentChanged, this, nullptr);
0056 
0057     if (m_contentItem) {
0058         m_contentItem->setEnabled(true);
0059     }
0060 }
0061 
0062 QString ItemContainer::key() const
0063 {
0064     return m_key;
0065 }
0066 
0067 void ItemContainer::setKey(const QString &key)
0068 {
0069     if (m_key == key) {
0070         return;
0071     }
0072 
0073     m_key = key;
0074 
0075     Q_EMIT keyChanged();
0076 }
0077 
0078 bool ItemContainer::editMode() const
0079 {
0080     return m_editMode;
0081 }
0082 
0083 bool ItemContainer::dragActive() const
0084 {
0085     return m_dragActive;
0086 }
0087 
0088 void ItemContainer::cancelEdit()
0089 {
0090     m_editModeTimer->stop();
0091     m_mouseDown = false;
0092     setEditMode(false);
0093 }
0094 
0095 void ItemContainer::setEditMode(bool editMode)
0096 {
0097     if (m_editMode == editMode) {
0098         return;
0099     }
0100 
0101     if (editMode && editModeCondition() == Locked) {
0102         return;
0103     }
0104 
0105     m_editMode = editMode;
0106 
0107     if (m_contentItem && (m_editModeCondition != AfterMouseOver || (m_layout && m_layout->editMode()))) {
0108         m_contentItem->setEnabled(!editMode);
0109     }
0110 
0111     if (editMode) {
0112         setZ(1);
0113     } else {
0114         setZ(0);
0115     }
0116 
0117     if (m_mouseDown) {
0118         sendUngrabRecursive(m_contentItem);
0119         grabMouse();
0120     }
0121 
0122     if (m_dragActive != editMode && m_mouseDown) {
0123         m_dragActive = editMode && m_mouseDown;
0124         Q_EMIT dragActiveChanged();
0125     }
0126 
0127     setConfigOverlayVisible(editMode);
0128 
0129     Q_EMIT editModeChanged(editMode);
0130 }
0131 
0132 ItemContainer::EditModeCondition ItemContainer::editModeCondition() const
0133 {
0134     if (m_layout && m_layout->editModeCondition() == AppletsLayout::Locked) {
0135         return Locked;
0136     }
0137 
0138     return m_editModeCondition;
0139 }
0140 
0141 void ItemContainer::setEditModeCondition(EditModeCondition condition)
0142 {
0143     if (condition == m_editModeCondition) {
0144         return;
0145     }
0146 
0147     if (condition == Locked) {
0148         setEditMode(false);
0149     }
0150 
0151     m_editModeCondition = condition;
0152 
0153     setAcceptHoverEvents(condition == AfterMouseOver || (m_layout && m_layout->editMode()));
0154 
0155     Q_EMIT editModeConditionChanged();
0156 }
0157 
0158 AppletsLayout::PreferredLayoutDirection ItemContainer::preferredLayoutDirection() const
0159 {
0160     return m_preferredLayoutDirection;
0161 }
0162 
0163 void ItemContainer::setPreferredLayoutDirection(AppletsLayout::PreferredLayoutDirection direction)
0164 {
0165     if (direction == m_preferredLayoutDirection) {
0166         return;
0167     }
0168 
0169     m_preferredLayoutDirection = direction;
0170 
0171     Q_EMIT preferredLayoutDirectionChanged();
0172 }
0173 
0174 void ItemContainer::setLayout(AppletsLayout *layout)
0175 {
0176     if (m_layout == layout) {
0177         return;
0178     }
0179 
0180     if (m_layout) {
0181         disconnect(m_layout, &AppletsLayout::editModeConditionChanged, this, nullptr);
0182         disconnect(m_layout, &AppletsLayout::editModeChanged, this, nullptr);
0183 
0184         if (m_editMode) {
0185             m_layout->hidePlaceHolder();
0186         }
0187     }
0188 
0189     m_layout = layout;
0190 
0191     if (!layout) {
0192         Q_EMIT layoutChanged();
0193         return;
0194     }
0195 
0196     if (parentItem() != layout) {
0197         setParentItem(layout);
0198     }
0199 
0200     connect(m_layout, &AppletsLayout::editModeConditionChanged, this, [this]() {
0201         if (m_layout->editModeCondition() == AppletsLayout::Locked) {
0202             setEditMode(false);
0203         }
0204         if ((m_layout->editModeCondition() == AppletsLayout::Locked) != (m_editModeCondition == ItemContainer::Locked)) {
0205             Q_EMIT editModeConditionChanged();
0206         }
0207     });
0208     connect(m_layout, &AppletsLayout::editModeChanged, this, [this]() {
0209         setAcceptHoverEvents(m_editModeCondition == AfterMouseOver || m_layout->editMode());
0210     });
0211     Q_EMIT layoutChanged();
0212 }
0213 
0214 AppletsLayout *ItemContainer::layout() const
0215 {
0216     return m_layout;
0217 }
0218 
0219 void ItemContainer::syncChildItemsGeometry(const QSizeF &size)
0220 {
0221     if (m_contentItem) {
0222         m_contentItem->setPosition(QPointF(m_leftPadding, m_topPadding));
0223 
0224         m_contentItem->setSize(QSizeF(size.width() - m_leftPadding - m_rightPadding, size.height() - m_topPadding - m_bottomPadding));
0225     }
0226 
0227     if (m_backgroundItem) {
0228         m_backgroundItem->setPosition(QPointF(0, 0));
0229         m_backgroundItem->setSize(size);
0230     }
0231 
0232     if (m_configOverlay) {
0233         m_configOverlay->setPosition(QPointF(0, 0));
0234         m_configOverlay->setSize(size);
0235     }
0236 }
0237 
0238 QQmlComponent *ItemContainer::configOverlayComponent() const
0239 {
0240     return m_configOverlayComponent;
0241 }
0242 
0243 void ItemContainer::setConfigOverlayComponent(QQmlComponent *component)
0244 {
0245     if (component == m_configOverlayComponent) {
0246         return;
0247     }
0248 
0249     m_configOverlayComponent = component;
0250     if (m_configOverlay) {
0251         m_configOverlay->deleteLater();
0252         m_configOverlay = nullptr;
0253     }
0254 
0255     Q_EMIT configOverlayComponentChanged();
0256 }
0257 
0258 ConfigOverlay *ItemContainer::configOverlayItem() const
0259 {
0260     return m_configOverlay;
0261 }
0262 
0263 QSizeF ItemContainer::initialSize() const
0264 {
0265     return m_initialSize;
0266 }
0267 
0268 void ItemContainer::setInitialSize(const QSizeF &size)
0269 {
0270     if (m_initialSize == size) {
0271         return;
0272     }
0273 
0274     m_initialSize = size;
0275 
0276     Q_EMIT initialSizeChanged();
0277 }
0278 
0279 bool ItemContainer::configOverlayVisible() const
0280 {
0281     return m_configOverlay && m_configOverlay->open();
0282 }
0283 
0284 void ItemContainer::setConfigOverlayVisible(bool visible)
0285 {
0286     if (!m_configOverlayComponent) {
0287         return;
0288     }
0289 
0290     if (visible == configOverlayVisible()) {
0291         return;
0292     }
0293 
0294     if (visible && !m_configOverlay) {
0295         QQmlContext *context = QQmlEngine::contextForObject(this);
0296         Q_ASSERT(context);
0297         QObject *instance = m_configOverlayComponent->beginCreate(context);
0298         m_configOverlay = qobject_cast<ConfigOverlay *>(instance);
0299 
0300         if (!m_configOverlay) {
0301             qCWarning(CONTAINMENTLAYOUTMANAGER_DEBUG) << "Error: Applet configOverlay not of ConfigOverlay type";
0302             if (instance) {
0303                 instance->deleteLater();
0304             }
0305             return;
0306         }
0307 
0308         m_configOverlay->setVisible(false);
0309         m_configOverlay->setItemContainer(this);
0310         m_configOverlay->setParentItem(this);
0311         m_configOverlay->setTouchInteraction(m_mouseSynthetizedFromTouch);
0312         m_configOverlay->setZ(999);
0313         m_configOverlay->setPosition(QPointF(0, 0));
0314         m_configOverlay->setSize(size());
0315 
0316         m_configOverlayComponent->completeCreate();
0317 
0318         connect(m_configOverlay, &ConfigOverlay::openChanged, this, [this]() {
0319             Q_EMIT configOverlayVisibleChanged(m_configOverlay->open());
0320         });
0321 
0322         Q_EMIT configOverlayItemChanged();
0323     }
0324 
0325     if (m_configOverlay) {
0326         m_configOverlay->setOpen(visible);
0327     }
0328 }
0329 
0330 void ItemContainer::contentData_append(QQmlListProperty<QObject> *prop, QObject *object)
0331 {
0332     ItemContainer *container = static_cast<ItemContainer *>(prop->object);
0333     if (!container) {
0334         return;
0335     }
0336 
0337     //    QQuickItem *item = qobject_cast<QQuickItem *>(object);
0338     container->m_contentData.append(object);
0339 }
0340 
0341 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0342 int ItemContainer::contentData_count(QQmlListProperty<QObject> *prop)
0343 #else
0344 qsizetype ItemContainer::contentData_count(QQmlListProperty<QObject> *prop)
0345 #endif
0346 {
0347     ItemContainer *container = static_cast<ItemContainer *>(prop->object);
0348     if (!container) {
0349         return 0;
0350     }
0351 
0352     return container->m_contentData.count();
0353 }
0354 
0355 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0356 QObject *ItemContainer::contentData_at(QQmlListProperty<QObject> *prop, int index)
0357 #else
0358 QObject *ItemContainer::contentData_at(QQmlListProperty<QObject> *prop, qsizetype index)
0359 #endif
0360 {
0361     ItemContainer *container = static_cast<ItemContainer *>(prop->object);
0362     if (!container) {
0363         return nullptr;
0364     }
0365 
0366     if (index < 0 || index >= container->m_contentData.count()) {
0367         return nullptr;
0368     }
0369     return container->m_contentData.value(index);
0370 }
0371 
0372 void ItemContainer::contentData_clear(QQmlListProperty<QObject> *prop)
0373 {
0374     ItemContainer *container = static_cast<ItemContainer *>(prop->object);
0375     if (!container) {
0376         return;
0377     }
0378 
0379     return container->m_contentData.clear();
0380 }
0381 
0382 QQmlListProperty<QObject> ItemContainer::contentData()
0383 {
0384     return QQmlListProperty<QObject>(this, nullptr, contentData_append, contentData_count, contentData_at, contentData_clear);
0385 }
0386 
0387 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0388 void ItemContainer::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
0389 #else
0390 void ItemContainer::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
0391 #endif
0392 {
0393     syncChildItemsGeometry(newGeometry.size());
0394 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0395     QQuickItem::geometryChanged(newGeometry, oldGeometry);
0396 #else
0397     QQuickItem::geometryChange(newGeometry, oldGeometry);
0398 #endif
0399     Q_EMIT contentWidthChanged();
0400     Q_EMIT contentHeightChanged();
0401 }
0402 
0403 void ItemContainer::componentComplete()
0404 {
0405     if (!m_contentItem) {
0406         // qWarning()<<"Creating default contentItem";
0407         m_contentItem = new QQuickItem(this);
0408         syncChildItemsGeometry(size());
0409     }
0410 
0411     for (auto *o : qAsConst(m_contentData)) {
0412         QQuickItem *item = qobject_cast<QQuickItem *>(o);
0413         if (item) {
0414             item->setParentItem(m_contentItem);
0415         }
0416     }
0417 
0418     // Search for the Layout attached property
0419     // Qt6: this should become public api
0420     // https://bugreports.qt.io/browse/QTBUG-77103
0421     for (auto *o : children()) {
0422         if (o->inherits("QQuickLayoutAttached")) {
0423             m_layoutAttached = o;
0424         }
0425     }
0426 
0427     if (m_layoutAttached) {
0428         // NOTE: new syntax cannot be used because we don't have access to the QQuickLayoutAttached class
0429         connect(m_layoutAttached, SIGNAL(minimumHeightChanged()), m_sizeHintAdjustTimer, SLOT(start()));
0430         connect(m_layoutAttached, SIGNAL(minimumWidthChanged()), m_sizeHintAdjustTimer, SLOT(start()));
0431 
0432         connect(m_layoutAttached, SIGNAL(preferredHeightChanged()), m_sizeHintAdjustTimer, SLOT(start()));
0433         connect(m_layoutAttached, SIGNAL(preferredWidthChanged()), m_sizeHintAdjustTimer, SLOT(start()));
0434 
0435         connect(m_layoutAttached, SIGNAL(maximumHeightChanged()), m_sizeHintAdjustTimer, SLOT(start()));
0436         connect(m_layoutAttached, SIGNAL(maximumWidthChanged()), m_sizeHintAdjustTimer, SLOT(start()));
0437     }
0438     QQuickItem::componentComplete();
0439 }
0440 
0441 void ItemContainer::sendUngrabRecursive(QQuickItem *item)
0442 {
0443     if (!item || !item->window()) {
0444         return;
0445     }
0446 
0447     for (auto *child : item->childItems()) {
0448         sendUngrabRecursive(child);
0449     }
0450 
0451     QEvent ev(QEvent::UngrabMouse);
0452 
0453     QCoreApplication::sendEvent(item, &ev);
0454 }
0455 
0456 bool ItemContainer::childMouseEventFilter(QQuickItem *item, QEvent *event)
0457 {
0458     // Don't filter the configoverlay
0459     if (item == m_configOverlay || (m_configOverlay && m_configOverlay->isAncestorOf(item)) || (!m_editMode && m_editModeCondition == Manual)) {
0460         return QQuickItem::childMouseEventFilter(item, event);
0461     }
0462 
0463     // give more time before closing
0464     if (m_closeEditModeTimer && m_closeEditModeTimer->isActive()) {
0465         m_closeEditModeTimer->start();
0466     }
0467     if (event->type() == QEvent::MouseButtonPress) {
0468         QMouseEvent *me = static_cast<QMouseEvent *>(event);
0469         if (me->button() != Qt::LeftButton && !(me->buttons() & Qt::LeftButton)) {
0470             return QQuickItem::childMouseEventFilter(item, event);
0471         }
0472         forceActiveFocus(Qt::MouseFocusReason);
0473         m_mouseDown = true;
0474         m_mouseSynthetizedFromTouch = me->source() == Qt::MouseEventSynthesizedBySystem || me->source() == Qt::MouseEventSynthesizedByQt;
0475         if (m_configOverlay) {
0476             m_configOverlay->setTouchInteraction(m_mouseSynthetizedFromTouch);
0477         }
0478 
0479         const bool wasEditMode = m_editMode;
0480         if (m_layout && m_layout->editMode()) {
0481             setEditMode(true);
0482         } else if (m_editModeCondition == AfterPressAndHold) {
0483             m_editModeTimer->start(QGuiApplication::styleHints()->mousePressAndHoldInterval());
0484         }
0485         m_lastMousePosition = me->windowPos();
0486         m_mouseDownPosition = me->windowPos();
0487 
0488         if (m_editMode && !wasEditMode) {
0489             event->accept();
0490             return true;
0491         }
0492 
0493     } else if (event->type() == QEvent::MouseMove) {
0494         QMouseEvent *me = static_cast<QMouseEvent *>(event);
0495 
0496         if (!m_editMode && QPointF(me->windowPos() - m_mouseDownPosition).manhattanLength() >= QGuiApplication::styleHints()->startDragDistance()) {
0497             m_editModeTimer->stop();
0498         } else if (m_editMode) {
0499             event->accept();
0500         }
0501 
0502     } else if (event->type() == QEvent::MouseButtonRelease) {
0503         m_editModeTimer->stop();
0504         m_mouseDown = false;
0505         m_mouseSynthetizedFromTouch = false;
0506         ungrabMouse();
0507         event->accept();
0508         m_dragActive = false;
0509         if (m_editMode) {
0510             Q_EMIT dragActiveChanged();
0511         }
0512     }
0513 
0514     return QQuickItem::childMouseEventFilter(item, event);
0515 }
0516 
0517 void ItemContainer::mousePressEvent(QMouseEvent *event)
0518 {
0519     forceActiveFocus(Qt::MouseFocusReason);
0520 
0521     if (!m_editMode && m_editModeCondition == Manual) {
0522         return;
0523     }
0524 
0525     m_mouseDown = true;
0526     m_mouseSynthetizedFromTouch = event->source() == Qt::MouseEventSynthesizedBySystem || event->source() == Qt::MouseEventSynthesizedByQt;
0527     if (m_configOverlay) {
0528         m_configOverlay->setTouchInteraction(m_mouseSynthetizedFromTouch);
0529     }
0530 
0531     if (m_layout && m_layout->editMode()) {
0532         setEditMode(true);
0533     }
0534 
0535     if (m_editMode) {
0536         grabMouse();
0537         setCursor(Qt::ClosedHandCursor);
0538         m_dragActive = true;
0539         Q_EMIT dragActiveChanged();
0540     } else if (m_editModeCondition == AfterPressAndHold) {
0541         m_editModeTimer->start(QGuiApplication::styleHints()->mousePressAndHoldInterval());
0542     }
0543 
0544     m_lastMousePosition = event->windowPos();
0545     m_mouseDownPosition = event->windowPos();
0546     event->accept();
0547 }
0548 
0549 void ItemContainer::mouseReleaseEvent(QMouseEvent *event)
0550 {
0551     Q_UNUSED(event);
0552 
0553     if (!m_layout || (!m_editMode && m_editModeCondition == Manual)) {
0554         return;
0555     }
0556 
0557     m_mouseDown = false;
0558     m_mouseSynthetizedFromTouch = false;
0559     m_editModeTimer->stop();
0560     ungrabMouse();
0561 
0562     if (m_editMode && !m_layout->itemIsManaged(this)) {
0563         m_layout->hidePlaceHolder();
0564         m_layout->positionItem(this);
0565     }
0566 
0567     m_dragActive = false;
0568     if (m_editMode) {
0569         Q_EMIT dragActiveChanged();
0570         setCursor(Qt::OpenHandCursor);
0571     }
0572     event->accept();
0573 }
0574 
0575 void ItemContainer::mouseMoveEvent(QMouseEvent *event)
0576 {
0577     if ((event->button() == Qt::NoButton && event->buttons() == Qt::NoButton) || (!m_editMode && m_editModeCondition == Manual)) {
0578         return;
0579     }
0580 
0581     if (!m_editMode && QPointF(event->windowPos() - m_mouseDownPosition).manhattanLength() >= QGuiApplication::styleHints()->startDragDistance()) {
0582         if (m_editModeCondition == AfterPress) {
0583             setEditMode(true);
0584         } else {
0585             m_editModeTimer->stop();
0586         }
0587     }
0588 
0589     if (!m_editMode) {
0590         return;
0591     }
0592 
0593     if (m_layout && m_layout->itemIsManaged(this)) {
0594         m_layout->releaseSpace(this);
0595         grabMouse();
0596         m_dragActive = true;
0597         Q_EMIT dragActiveChanged();
0598 
0599     } else {
0600         setPosition(QPointF(x() + event->windowPos().x() - m_lastMousePosition.x(), y() + event->windowPos().y() - m_lastMousePosition.y()));
0601 
0602         if (m_layout) {
0603             m_layout->showPlaceHolderForItem(this);
0604         }
0605 
0606         Q_EMIT userDrag(QPointF(x(), y()), event->pos());
0607     }
0608     m_lastMousePosition = event->windowPos();
0609     event->accept();
0610 }
0611 
0612 void ItemContainer::mouseUngrabEvent()
0613 {
0614     m_mouseDown = false;
0615     m_mouseSynthetizedFromTouch = false;
0616     m_editModeTimer->stop();
0617     ungrabMouse();
0618 
0619     if (m_layout && m_editMode && !m_layout->itemIsManaged(this)) {
0620         m_layout->hidePlaceHolder();
0621         m_layout->positionItem(this);
0622     }
0623 
0624     m_dragActive = false;
0625     if (m_editMode) {
0626         Q_EMIT dragActiveChanged();
0627     }
0628 }
0629 
0630 void ItemContainer::hoverEnterEvent(QHoverEvent *event)
0631 {
0632     Q_UNUSED(event);
0633 
0634     if (m_editModeCondition != AfterMouseOver && !m_layout->editMode()) {
0635         return;
0636     }
0637 
0638     if (m_closeEditModeTimer) {
0639         m_closeEditModeTimer->stop();
0640     }
0641 
0642     if (m_layout->editMode()) {
0643         setCursor(Qt::OpenHandCursor);
0644         setEditMode(true);
0645     } else {
0646         m_editModeTimer->start(QGuiApplication::styleHints()->mousePressAndHoldInterval());
0647     }
0648 }
0649 
0650 void ItemContainer::hoverLeaveEvent(QHoverEvent *event)
0651 {
0652     Q_UNUSED(event);
0653 
0654     if (m_editModeCondition != AfterMouseOver && !m_layout->editMode()) {
0655         return;
0656     }
0657 
0658     m_editModeTimer->stop();
0659     if (!m_closeEditModeTimer) {
0660         m_closeEditModeTimer = new QTimer(this);
0661         m_closeEditModeTimer->setSingleShot(true);
0662         m_closeEditModeTimer->setInterval(500ms);
0663         connect(m_closeEditModeTimer, &QTimer::timeout, this, [this]() {
0664             setEditMode(false);
0665         });
0666     }
0667     m_closeEditModeTimer->start();
0668 }
0669 
0670 QQuickItem *ItemContainer::contentItem() const
0671 {
0672     return m_contentItem;
0673 }
0674 
0675 void ItemContainer::setContentItem(QQuickItem *item)
0676 {
0677     if (m_contentItem == item) {
0678         return;
0679     }
0680 
0681     m_contentItem = item;
0682     item->setParentItem(this);
0683     m_contentItem->setPosition(QPointF(m_leftPadding, m_topPadding));
0684 
0685     m_contentItem->setSize(QSizeF(width() - m_leftPadding - m_rightPadding, height() - m_topPadding - m_bottomPadding));
0686 
0687     Q_EMIT contentItemChanged();
0688 }
0689 
0690 QQuickItem *ItemContainer::background() const
0691 {
0692     return m_backgroundItem;
0693 }
0694 
0695 void ItemContainer::setBackground(QQuickItem *item)
0696 {
0697     if (m_backgroundItem == item) {
0698         return;
0699     }
0700 
0701     m_backgroundItem = item;
0702     m_backgroundItem->setParentItem(this);
0703     m_backgroundItem->setPosition(QPointF(0, 0));
0704     m_backgroundItem->setSize(size());
0705 
0706     Q_EMIT backgroundChanged();
0707 }
0708 
0709 int ItemContainer::leftPadding() const
0710 {
0711     return m_leftPadding;
0712 }
0713 
0714 void ItemContainer::setLeftPadding(int padding)
0715 {
0716     if (m_leftPadding == padding) {
0717         return;
0718     }
0719 
0720     m_leftPadding = padding;
0721     syncChildItemsGeometry(size());
0722     Q_EMIT leftPaddingChanged();
0723     Q_EMIT contentWidthChanged();
0724 }
0725 
0726 int ItemContainer::topPadding() const
0727 {
0728     return m_topPadding;
0729 }
0730 
0731 void ItemContainer::setTopPadding(int padding)
0732 {
0733     if (m_topPadding == padding) {
0734         return;
0735     }
0736 
0737     m_topPadding = padding;
0738     syncChildItemsGeometry(size());
0739     Q_EMIT topPaddingChanged();
0740     Q_EMIT contentHeightChanged();
0741 }
0742 
0743 int ItemContainer::rightPadding() const
0744 {
0745     return m_rightPadding;
0746 }
0747 
0748 void ItemContainer::setRightPadding(int padding)
0749 {
0750     if (m_rightPadding == padding) {
0751         return;
0752     }
0753 
0754     m_rightPadding = padding;
0755     syncChildItemsGeometry(size());
0756     Q_EMIT rightPaddingChanged();
0757     Q_EMIT contentWidthChanged();
0758 }
0759 
0760 int ItemContainer::bottomPadding() const
0761 {
0762     return m_bottomPadding;
0763 }
0764 
0765 void ItemContainer::setBottomPadding(int padding)
0766 {
0767     if (m_bottomPadding == padding) {
0768         return;
0769     }
0770 
0771     m_bottomPadding = padding;
0772     syncChildItemsGeometry(size());
0773     Q_EMIT bottomPaddingChanged();
0774     Q_EMIT contentHeightChanged();
0775 }
0776 
0777 int ItemContainer::contentWidth() const
0778 {
0779     return width() - m_leftPadding - m_rightPadding;
0780 }
0781 
0782 int ItemContainer::contentHeight() const
0783 {
0784     return height() - m_topPadding - m_bottomPadding;
0785 }
0786 
0787 #include "moc_itemcontainer.cpp"