/* SPDX-FileCopyrightText: 2021 Michail Vourlakos SPDX-License-Identifier: GPL-2.0-or-later */ #include "layoutmanager.h" // local #include // Qt #include // KDE #include // Plasma #include namespace Latte{ namespace Containment{ LayoutManager::LayoutManager(QObject *parent) : QObject(parent) { m_option["lockZoom"] = "lockedZoomApplets"; m_option["userBlocksColorizing"] = "userBlocksColorizingApplets"; connect(this, &LayoutManager::rootItemChanged, this, &LayoutManager::onRootItemChanged); m_hasRestoredAppletsTimer.setInterval(2000); m_hasRestoredAppletsTimer.setSingleShot(true); connect(&m_hasRestoredAppletsTimer, &QTimer::timeout, this, [&]() { m_hasRestoredApplets = true; emit hasRestoredAppletsChanged(); }); } bool LayoutManager::hasRestoredApplets() const { return m_hasRestoredApplets; } int LayoutManager::splitterPosition() const { return m_splitterPosition; } void LayoutManager::setSplitterPosition(const int &position) { if (m_splitterPosition == position) { return; } m_splitterPosition = position; emit splitterPositionChanged(); } int LayoutManager::splitterPosition2() const { return m_splitterPosition2; } void LayoutManager::setSplitterPosition2(const int &position) { if (m_splitterPosition2 == position) { return; } m_splitterPosition2 = position; emit splitterPosition2Changed(); } QString LayoutManager::appletOrder() const { return m_appletOrder; } void LayoutManager::setAppletOrder(const QString &order) { if (m_appletOrder == order) { return; } m_appletOrder = order; emit appletOrderChanged(); } QString LayoutManager::lockedZoomApplets() const { return m_lockedZoomApplets; } void LayoutManager::setLockedZoomApplets(const QString &applets) { if (m_lockedZoomApplets == applets) { return; } m_lockedZoomApplets = applets; emit lockedZoomAppletsChanged(); } QString LayoutManager::userBlocksColorizingApplets() const { return m_userBlocksColorizingApplets; } void LayoutManager::setUserBlocksColorizingApplets(const QString &applets) { if (m_userBlocksColorizingApplets == applets) { return; } m_userBlocksColorizingApplets = applets; emit userBlocksColorizingAppletsChanged(); } QObject *LayoutManager::plasmoid() const { return m_plasmoid; } void LayoutManager::setPlasmoid(QObject *plasmoid) { if (m_plasmoid == plasmoid) { return; } m_plasmoid = plasmoid; if (m_plasmoid) { m_configuration = qobject_cast(m_plasmoid->property("configuration").value()); } emit plasmoidChanged(); } QQuickItem *LayoutManager::rootItem() const { return m_rootItem; } void LayoutManager::setRootItem(QQuickItem *root) { if (m_rootItem == root) { return; } m_rootItem = root; emit rootItemChanged(); } QQuickItem *LayoutManager::dndSpacer() const { return m_dndSpacer; } void LayoutManager::setDndSpacer(QQuickItem *dnd) { if (m_dndSpacer == dnd) { return; } m_dndSpacer = dnd; emit dndSpacerChanged(); } QQuickItem *LayoutManager::mainLayout() const { return m_mainLayout; } void LayoutManager::setMainLayout(QQuickItem *main) { if (main == m_mainLayout) { return; } m_mainLayout = main; emit mainLayoutChanged(); } QQuickItem *LayoutManager::startLayout() const { return m_startLayout; } void LayoutManager::setStartLayout(QQuickItem *start) { if (m_startLayout == start) { return; } m_startLayout = start; emit startLayoutChanged(); } QQuickItem *LayoutManager::endLayout() const { return m_endLayout; } void LayoutManager::setEndLayout(QQuickItem *end) { if (m_endLayout == end) { return; } m_endLayout = end; emit endLayoutChanged(); } QQuickItem *LayoutManager::metrics() const { return m_metrics; } void LayoutManager::setMetrics(QQuickItem *metrics) { if (m_metrics == metrics) { return; } m_metrics = metrics; emit metricsChanged(); } void LayoutManager::onRootItemChanged() { if (!m_rootItem) { return; } auto rootMetaObject = m_rootItem->metaObject(); int createAppletItemIndex = rootMetaObject->indexOfMethod("createAppletItem(QVariant)"); m_createAppletItemMethod = rootMetaObject->method(createAppletItemIndex); int createJustifySplitterIndex = rootMetaObject->indexOfMethod("createJustifySplitter()"); m_createJustifySplitterMethod = rootMetaObject->method(createJustifySplitterIndex); } bool LayoutManager::isValidApplet(const int &id) { //! should be loaded after m_plasmoid has been set properly if (!m_plasmoid) { return false; } QList applets = m_plasmoid->property("applets").value>(); for(int i=0; iproperty("id").toUInt(); if (id>0 && appletid == (uint)id) { return true; } } return false; } //! Actions void LayoutManager::restore() { QStringList appletStringIdsOrder = (*m_configuration)["appletOrder"].toString().split(";"); QList applets = m_plasmoid->property("applets").value>(); Latte::Types::Alignment alignment = static_cast((*m_configuration)["alignment"].toInt()); int splitterPosition = (*m_configuration)["splitterPosition"].toInt(); int splitterPosition2 = (*m_configuration)["splitterPosition2"].toInt(); QList appletIdsOrder; for (int i=0; i invalidApplets; //! track invalid applets, meaning applets that have not be loaded properly for (int i=0; i0 && !isValidApplet(aid)) { invalidApplets << aid; } } //! remove invalid applets from the ids order for (int i=0; i orderedApplets; for (int i=0; iproperty("id").toInt() == appletIdsOrder[i]) { orderedApplets << applets[j]; break; } } } QStringList orphanedIds; for(int i=0; iproperty("id").toUInt(); if (!appletIdsOrder.contains(id)) { orphanedIds << QString::number(id); } } //Validator QList validateAppletsOrder; for (int i=0; iproperty("id").toUInt(); } for(int i=0; i(); appletItem->setParentItem(m_mainLayout); } } else { QQuickItem *parentlayout = m_startLayout; for (int i=0; i(); if (parentlayout == m_startLayout) { //! first splitter as last child in startlayout splitterItem->setParentItem(parentlayout); parentlayout = m_mainLayout; } else if (parentlayout == m_mainLayout) { //! second splitter as first child in endlayout parentlayout = m_endLayout; splitterItem->setParentItem(parentlayout); } continue; } QVariant appletItemVariant; QVariant appletVariant; appletVariant.setValue(orderedApplets[i]); m_createAppletItemMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, appletItemVariant), Q_ARG(QVariant, appletVariant)); QQuickItem *appletItem = appletItemVariant.value(); appletItem->setParentItem(parentlayout); } } restoreOptions(); save(); m_hasRestoredAppletsTimer.start(); } void LayoutManager::restoreOptions() { restoreOption("lockZoom"); restoreOption("userBlocksColorizing"); } void LayoutManager::restoreOption(const char *option) { QStringList applets = (*m_configuration)[m_option[option]].toString().split(";"); if (!m_startLayout || !m_mainLayout || !m_endLayout) { return; } for (int i=0; i<=2; ++i) { QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout)); for (int j=layout->childItems().count()-1; j>=0; --j) { QQuickItem *item = layout->childItems()[j]; bool issplitter = item->property("isInternalViewSplitter").toBool(); if (!issplitter) { QVariant appletVariant = item->property("applet"); if (!appletVariant.isValid()) { continue; } QObject *applet = appletVariant.value(); uint id = applet->property("id").toUInt(); item->setProperty(option, applets.contains(QString::number(id))); } } } } void LayoutManager::save() { QStringList appletIds; int startChilds{0}; for(int i=0; ichildItems().count(); ++i) { QQuickItem *item = m_startLayout->childItems()[i]; bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); if (!isInternalSplitter) { QVariant appletVariant = item->property("applet"); if (!appletVariant.isValid()) { continue; } QObject *applet = appletVariant.value(); if (!applet) { continue; } uint id = applet->property("id").toUInt(); if (id>0) { startChilds++; appletIds << QString::number(id); } } } int mainChilds{0}; for(int i=0; ichildItems().count(); ++i) { QQuickItem *item = m_mainLayout->childItems()[i]; bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); if (!isInternalSplitter) { QVariant appletVariant = item->property("applet"); if (!appletVariant.isValid()) { continue; } QObject *applet = appletVariant.value(); if (!applet) { continue; } uint id = applet->property("id").toUInt(); if (id>0) { mainChilds++; appletIds << QString::number(id); } } } int endChilds{0}; for(int i=0; ichildItems().count(); ++i) { QQuickItem *item = m_endLayout->childItems()[i]; bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); if (!isInternalSplitter) { QVariant appletVariant = item->property("applet"); if (!appletVariant.isValid()) { continue; } QObject *applet = appletVariant.value(); if (!applet) { continue; } uint id = applet->property("id").toUInt(); if (id>0) { endChilds++; appletIds << QString::number(id); } } } Latte::Types::Alignment alignment = static_cast((*m_configuration)["alignment"].toInt()); if (alignment == Latte::Types::Justify) { setSplitterPosition(startChilds + 1); setSplitterPosition2(startChilds + 1 + mainChilds + 1); } else { int splitterPosition = (*m_configuration)["splitterPosition"].toInt(); int splitterPosition2 = (*m_configuration)["splitterPosition2"].toInt(); setSplitterPosition(splitterPosition); setSplitterPosition2(splitterPosition2); } //! are not writing in config file for some cases mentioned in class header so they are not used //(*m_configuration)["splitterPosition"] = QVariant(startChilds + 1); //(*m_configuration)["splitterPosition2"] = QVariant(startChilds + 1 + mainChilds + 1); //(*m_configuration)["appletOrder"] = appletIds.join(";"); setAppletOrder(appletIds.join(";")); //qDebug() << "org.kde.latte saving applets:: " << appletOrder() << " :: " << splitterPosition() << " : " << splitterPosition2(); saveOptions(); } void LayoutManager::saveOptions() { saveOption("lockZoom"); saveOption("userBlocksColorizing"); //qDebug() << "org.kde.latte saving properties:: " << lockedZoomApplets() << " :: " << userBlocksColorizingApplets(); } void LayoutManager::saveOption(const char *option) { if (!m_startLayout || !m_mainLayout || !m_endLayout) { return; } QStringList applets; for (int i=0; i<=2; ++i) { QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout)); for (int j=0; jchildItems().count(); ++j) { QQuickItem *item = layout->childItems()[j]; bool issplitter = item->property("isInternalViewSplitter").toBool(); if (issplitter) { continue; } bool enabled = item->property(option).toBool(); if (enabled) { QVariant appletVariant = item->property("applet"); if (!appletVariant.isValid()) { continue; } QObject *applet = appletVariant.value(); uint id = applet->property("id").toUInt(); applets << QString::number(id); } } } if (option == "lockZoom") { setLockedZoomApplets(applets.join(";")); } else if (option == "userBlocksColorizing") { setUserBlocksColorizingApplets(applets.join(";")); } } void LayoutManager::insertBefore(QQuickItem *hoveredItem, QQuickItem *item) { if (!hoveredItem || !item || hoveredItem == item) { return; } item->setParentItem(hoveredItem->parentItem()); item->stackBefore(hoveredItem); } void LayoutManager::insertAfter(QQuickItem *hoveredItem, QQuickItem *item) { if (!hoveredItem || !item || hoveredItem == item) { return; } item->setParentItem(hoveredItem->parentItem()); item->stackAfter(hoveredItem); } void LayoutManager::insertAtLayoutTail(QQuickItem *layout, QQuickItem *item) { if (!layout || !item) { return; } if (layout->childItems().count() > 0) { insertBefore(layout->childItems()[0], item); return; } item->setParentItem(layout); } void LayoutManager::insertAtLayoutHead(QQuickItem *layout, QQuickItem *item) { if (!layout || !item) { return; } int count = layout->childItems().count(); if (count > 0) { insertAfter(layout->childItems()[count-1], item); return; } item->setParentItem(layout); } bool LayoutManager::insertAtLayoutCoordinates(QQuickItem *layout, QQuickItem *item, int x, int y) { if (!layout || !item || !m_plasmoid || !layout->contains(QPointF(x,y))) { return false; } bool horizontal = (m_plasmoid->property("formFactor").toInt() != Plasma::Types::Vertical); bool vertical = !horizontal; int rowspacing = qMax(0, layout->property("rowSpacing").toInt()); int columnspacing = qMax(0, layout->property("columnSpacing").toInt()); if (horizontal) { y = layout->height() / 2; } else { x = layout->width() / 2; } //! child renamed at hovered QQuickItem *hovered = layout->childAt(x, y); //if we got a place inside the space between 2 applets, we have to find it manually if (!hovered) { int size = layout->childItems().count(); if (horizontal) { for (int i = 0; i < size; ++i) { if (i>=layout->childItems().count()) { break; } QQuickItem *candidate = layout->childItems()[i]; int right = candidate->x() + candidate->width() + rowspacing; if (x>=candidate->x() && x=layout->childItems().count()) { break; } QQuickItem *candidate = layout->childItems()[i]; int bottom = candidate->y() + candidate->height() + columnspacing; if (y>=candidate->y() && yparentItem() == layout) { //! already hovered and in correct position return true; } if (hovered) { if ((vertical && y < (hovered->y() + hovered->height()/2)) || (horizontal && x < hovered->x() + hovered->width()/2)) { insertBefore(hovered, item); } else { insertAfter(hovered, item); } return true; } return false; } int LayoutManager::distanceFromTail(QQuickItem *layout, QPointF pos) const { return (int)qSqrt(qPow(pos.x() - 0, 2) + qPow(pos.y() - 0, 2)); } int LayoutManager::distanceFromHead(QQuickItem *layout, QPointF pos) const { float rightX = layout->width() - 1; float rightY = layout->height() - 1; return (int)qSqrt(qPow(pos.x() - rightX, 2) + qPow(pos.y() - rightY, 2)); } void LayoutManager::insertAtCoordinates(QQuickItem *item, const int &x, const int &y) { if (!m_configuration || !item) { return; } Latte::Types::Alignment alignment = static_cast((*m_configuration)["alignment"].toInt()); bool result{false}; if (alignment == Latte::Types::Justify) { QPointF startPos = m_startLayout->mapFromItem(m_rootItem, QPointF(x, y)); result = insertAtLayoutCoordinates(m_startLayout, item, startPos.x(), startPos.y()); if (!result) { QPointF endPos = m_endLayout->mapFromItem(m_rootItem, QPointF(x, y)); result = insertAtLayoutCoordinates(m_endLayout, item, endPos.x(), endPos.y()); } } if (!result) { QPointF mainPos = m_mainLayout->mapFromItem(m_rootItem, QPointF(x, y)); //! in javascript direct insertAtCoordinates was usedd ??? result = insertAtLayoutCoordinates(m_mainLayout, item, mainPos.x(), mainPos.y()); } if (result) { return; } //! item was not added because it does not hover any of the layouts and layout items //! so the place that will be added is specified by the distance of the item from the layouts QPointF startrelpos = m_startLayout->mapFromItem(m_rootItem, QPointF(x, y)); QPointF endrelpos = m_endLayout->mapFromItem(m_rootItem, QPointF(x, y)); QPointF mainrelpos = m_mainLayout->mapFromItem(m_rootItem, QPointF(x, y)); int starttaildistance = distanceFromTail(m_startLayout, startrelpos); int startheaddistance = distanceFromHead(m_startLayout, startrelpos); int maintaildistance = distanceFromTail(m_mainLayout, mainrelpos); int mainheaddistance = distanceFromHead(m_mainLayout, mainrelpos); int endtaildistance = distanceFromTail(m_endLayout, endrelpos); int endheaddistance = distanceFromHead(m_endLayout, endrelpos); int startdistance = qMin(starttaildistance, startheaddistance); int maindistance = qMin(maintaildistance, mainheaddistance); int enddistance = qMin(endtaildistance, endheaddistance); if (alignment != Latte::Types::Justify || (maindistance < startdistance && maindistance < enddistance)) { if (maintaildistance <= mainheaddistance) { insertAtLayoutTail(m_mainLayout, item); } else { insertAtLayoutHead(m_mainLayout, item); } } else if (startdistance < maindistance && startdistance < enddistance) { if (maintaildistance <= mainheaddistance) { insertAtLayoutTail(m_startLayout, item); } else { insertAtLayoutHead(m_startLayout, item); } } else { if (endtaildistance <= endheaddistance) { insertAtLayoutTail(m_endLayout, item); } else { insertAtLayoutHead(m_endLayout, item); } } } void LayoutManager::addAppletItem(QObject *applet, int x, int y) { if (!m_startLayout || !m_mainLayout || !m_endLayout) { return; } QVariant appletItemVariant; QVariant appletVariant; appletVariant.setValue(applet); m_createAppletItemMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, appletItemVariant), Q_ARG(QVariant, appletVariant)); QQuickItem *appletItem = appletItemVariant.value(); if (m_dndSpacer->parentItem() == m_mainLayout || m_dndSpacer->parentItem() == m_startLayout || m_dndSpacer->parentItem() == m_endLayout) { insertBefore(m_dndSpacer, appletItem); QQuickItem *currentlayout = m_dndSpacer->parentItem(); m_dndSpacer->setParentItem(m_rootItem); if (currentlayout == m_startLayout) { reorderSplitterInStartLayout(); } else if (currentlayout ==m_endLayout) { reorderSplitterInEndLayout(); } } else if (x >= 0 && y >= 0) { // If the provided position is valid, use it. insertAtCoordinates(appletItem, x , y); } else { // Fall through to adding at the end of main layout. appletItem->setParentItem(m_mainLayout); } save(); } void LayoutManager::removeAppletItem(QObject *applet) { if (!m_startLayout || !m_mainLayout || !m_endLayout) { return; } for (int i=0; i<=2; ++i) { QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout)); if (layout->childItems().count() > 0) { int size = layout->childItems().count(); for (int j=size-1; j>=0; --j) { QQuickItem *item = layout->childItems()[j]; bool issplitter = item->property("isInternalViewSplitter").toBool(); if (!issplitter) { QVariant appletVariant = item->property("applet"); if (!appletVariant.isValid()) { continue; } QObject *currentapplet = appletVariant.value(); if (currentapplet == applet) { item->deleteLater(); return; } } } } } save(); } void LayoutManager::reorderSplitterInStartLayout() { Latte::Types::Alignment alignment = static_cast((*m_configuration)["alignment"].toInt()); if (alignment != Latte::Types::Justify) { return; } int size = m_startLayout->childItems().count(); if (size > 0) { QQuickItem *splitter{nullptr}; for (int i=0; ichildItems()[i]; bool issplitter = item->property("isInternalViewSplitter").toBool(); if (issplitter && ichildItems()[size-1],splitter); } } } void LayoutManager::reorderSplitterInEndLayout() { Latte::Types::Alignment alignment = static_cast((*m_configuration)["alignment"].toInt()); if (alignment != Latte::Types::Justify) { return; } int size = m_endLayout->childItems().count(); if (size > 0) { QQuickItem *splitter{nullptr}; for (int i=0; ichildItems()[i]; bool issplitter = item->property("isInternalViewSplitter").toBool(); if (issplitter && i!=0) { splitter = item; break; } } if (splitter) { insertBefore(m_endLayout->childItems()[0],splitter); } } } void LayoutManager::addJustifySplittersInMainLayout() { if (!m_configuration || !m_mainLayout) { return; } destroyJustifySplitters(); int splitterPosition = (*m_configuration)["splitterPosition"].toInt(); int splitterPosition2 = (*m_configuration)["splitterPosition2"].toInt(); int splitterIndex = (splitterPosition >= 1 ? splitterPosition - 1 : -1); int splitterIndex2 = (splitterPosition2 >= 1 ? splitterPosition2 - 1 : -1); //! First Splitter QVariant splitterItemVariant; m_createJustifySplitterMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, splitterItemVariant)); QQuickItem *splitterItem = splitterItemVariant.value(); int size = m_mainLayout->childItems().count(); splitterItem->setParentItem(m_mainLayout); if (size>0 && splitterIndex>=0) { bool atend = (splitterIndex >= size); int validindex = atend ? size-1 : splitterIndex; QQuickItem *currentitem = m_mainLayout->childItems()[validindex]; if (atend) { splitterItem->stackAfter(currentitem); } else { splitterItem->stackBefore(currentitem); } } else if (size>0) { //! add in first position QQuickItem *currentitem = m_mainLayout->childItems()[0]; splitterItem->stackBefore(currentitem); } //! Second Splitter QVariant splitterItemVariant2; m_createJustifySplitterMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, splitterItemVariant2)); QQuickItem *splitterItem2 = splitterItemVariant2.value(); int size2 = m_mainLayout->childItems().count(); splitterItem2->setParentItem(m_mainLayout); if (size2>0 && splitterIndex2>=0) { bool atend = (splitterIndex2 >= size2); int validindex2 = atend ? size2-1 : splitterIndex2; QQuickItem *currentitem2 = m_mainLayout->childItems()[validindex2]; if (atend) { splitterItem2->stackAfter(currentitem2); } else { splitterItem2->stackBefore(currentitem2); } } else if (size2>1){ //! add in last position QQuickItem *currentitem2 = m_mainLayout->childItems()[size2-1]; splitterItem2->stackAfter(currentitem2); } } void LayoutManager::destroyJustifySplitters() { if (!m_startLayout || !m_mainLayout || !m_endLayout) { return; } for (int i=0; i<=2; ++i) { QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout)); if (layout->childItems().count() > 0) { int size = layout->childItems().count(); for (int j=size-1; j>=0; --j) { QQuickItem *item = layout->childItems()[j]; bool issplitter = item->property("isInternalViewSplitter").toBool(); if (issplitter) { item->deleteLater(); } } } } } void LayoutManager::joinLayoutsToMainLayout() { if (!m_startLayout || !m_mainLayout || !m_endLayout) { return; } if (m_startLayout->childItems().count() > 0) { int size = m_startLayout->childItems().count(); for (int i=size-1; i>=0; --i) { QQuickItem *lastStartLayoutItem = m_startLayout->childItems()[i]; QQuickItem *firstMainLayoutItem = m_mainLayout->childItems().count() > 0 ? m_mainLayout->childItems()[0] : nullptr; lastStartLayoutItem->setParentItem(m_mainLayout); if (firstMainLayoutItem) { lastStartLayoutItem->stackBefore(firstMainLayoutItem); } } } if (m_endLayout->childItems().count() > 0) { int size = m_endLayout->childItems().count(); for (int i=0; ichildItems()[0]; QQuickItem *lastMainLayoutItem = m_mainLayout->childItems().count() > 0 ? m_mainLayout->childItems()[m_mainLayout->childItems().count()-1] : nullptr; firstEndLayoutItem->setParentItem(m_mainLayout); if (lastMainLayoutItem) { firstEndLayoutItem->stackAfter(lastMainLayoutItem); } } } destroyJustifySplitters(); } void LayoutManager::moveAppletsBasedOnJustifyAlignment() { if (!m_startLayout || !m_mainLayout || !m_endLayout) { return; } QList appletlist; appletlist << m_startLayout->childItems(); appletlist << m_mainLayout->childItems(); appletlist << m_endLayout->childItems(); bool firstSplitterFound{false}; bool secondSplitterFound{false}; int splitter1{-1}; int splitter2{-1}; for(int i=0; iproperty("isInternalViewSplitter").toBool(); if (!firstSplitterFound) { appletlist[i]->setParentItem(m_startLayout); if (issplitter) { firstSplitterFound = true; splitter1 = i; } } else if (firstSplitterFound && !secondSplitterFound) { if (issplitter) { secondSplitterFound = true; splitter2 = i; appletlist[i]->setParentItem(m_endLayout); } else { appletlist[i]->setParentItem(m_mainLayout); } } else if (firstSplitterFound && secondSplitterFound) { appletlist[i]->setParentItem(m_endLayout); } } for(int i=0; iparentItem() == after->parentItem()) { before->stackBefore(after); } } //! Confirm Last item of End Layout if (m_endLayout->childItems().count() > 0) { QQuickItem *lastItem = m_endLayout->childItems()[m_endLayout->childItems().count()-1]; int correctpos{-1}; for(int i=0; i=0) { lastItem->stackBefore(appletlist[correctpos+1]); } } } } }