File indexing completed on 2024-03-24 05:34:14
0001 /* 0002 SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "layoutmanager.h" 0007 0008 // local 0009 #include <plugin/lattetypes.h> 0010 0011 // Qt 0012 #include <QtMath> 0013 0014 // KDE 0015 #include <KDeclarative/ConfigPropertyMap> 0016 0017 // Plasma 0018 #include <Plasma> 0019 #include <Plasma/Applet> 0020 #include <PlasmaQuick/AppletQuickItem> 0021 0022 #define ISAPPLETLOCKEDOPTION "lockZoom" 0023 #define ISCOLORINGBLOCKEDOPTION "userBlocksColorizing" 0024 0025 namespace Latte{ 0026 namespace Containment{ 0027 0028 const int LayoutManager::JUSTIFYSPLITTERID; 0029 0030 LayoutManager::LayoutManager(QObject *parent) 0031 : QObject(parent) 0032 { 0033 m_option[ISAPPLETLOCKEDOPTION] = "lockedZoomApplets"; 0034 m_option[ISCOLORINGBLOCKEDOPTION] = "userBlocksColorizingApplets"; 0035 0036 connect(this, &LayoutManager::rootItemChanged, this, &LayoutManager::onRootItemChanged); 0037 0038 m_hasRestoredAppletsTimer.setInterval(2000); 0039 m_hasRestoredAppletsTimer.setSingleShot(true); 0040 connect(&m_hasRestoredAppletsTimer, &QTimer::timeout, this, [&]() { 0041 m_hasRestoredApplets = true; 0042 emit hasRestoredAppletsChanged(); 0043 }); 0044 } 0045 0046 bool LayoutManager::hasRestoredApplets() const 0047 { 0048 return m_hasRestoredApplets; 0049 } 0050 0051 int LayoutManager::splitterPosition() const 0052 { 0053 return m_splitterPosition; 0054 } 0055 0056 void LayoutManager::setSplitterPosition(const int &position) 0057 { 0058 if (m_splitterPosition == position) { 0059 return; 0060 } 0061 0062 m_splitterPosition = position; 0063 emit splitterPositionChanged(); 0064 } 0065 0066 int LayoutManager::splitterPosition2() const 0067 { 0068 return m_splitterPosition2; 0069 } 0070 0071 void LayoutManager::setSplitterPosition2(const int &position) 0072 { 0073 if (m_splitterPosition2 == position) { 0074 return; 0075 } 0076 0077 m_splitterPosition2 = position; 0078 emit splitterPosition2Changed(); 0079 } 0080 0081 QList<int> LayoutManager::appletOrder() const 0082 { 0083 return m_appletOrder; 0084 } 0085 0086 void LayoutManager::setAppletOrder(const QList<int> &order) 0087 { 0088 if (m_appletOrder == order) { 0089 return; 0090 } 0091 0092 m_appletOrder = order; 0093 emit appletOrderChanged(); 0094 } 0095 0096 QList<int> LayoutManager::lockedZoomApplets() const 0097 { 0098 return m_lockedZoomApplets; 0099 } 0100 0101 void LayoutManager::setLockedZoomApplets(const QList<int> &applets) 0102 { 0103 if (m_lockedZoomApplets == applets) { 0104 return; 0105 } 0106 0107 m_lockedZoomApplets = applets; 0108 emit lockedZoomAppletsChanged(); 0109 } 0110 0111 QList<int> LayoutManager::order() const 0112 { 0113 return m_order; 0114 } 0115 0116 void LayoutManager::setOrder(const QList<int> &order) 0117 { 0118 if (m_order == order) { 0119 return; 0120 } 0121 0122 m_order = order; 0123 emit orderChanged(); 0124 } 0125 0126 QList<int> LayoutManager::userBlocksColorizingApplets() const 0127 { 0128 return m_userBlocksColorizingApplets; 0129 } 0130 0131 void LayoutManager::setUserBlocksColorizingApplets(const QList<int> &applets) 0132 { 0133 if (m_userBlocksColorizingApplets == applets) { 0134 return; 0135 } 0136 0137 m_userBlocksColorizingApplets = applets; 0138 emit userBlocksColorizingAppletsChanged(); 0139 } 0140 0141 QList<int> LayoutManager::appletsInScheduledDestruction() const 0142 { 0143 return m_appletsInScheduledDestruction.keys(); 0144 } 0145 0146 void LayoutManager::setAppletInScheduledDestruction(const int &id, const bool &enabled) 0147 { 0148 if (m_appletsInScheduledDestruction.contains(id) && !enabled) { 0149 m_appletsInScheduledDestruction.remove(id); 0150 emit appletsInScheduledDestructionChanged(); 0151 } else if (!m_appletsInScheduledDestruction.contains(id) && enabled) { 0152 m_appletsInScheduledDestruction[id] = appletItem(id); 0153 emit appletsInScheduledDestructionChanged(); 0154 } 0155 } 0156 0157 0158 QObject *LayoutManager::plasmoid() const 0159 { 0160 return m_plasmoid; 0161 } 0162 0163 void LayoutManager::setPlasmoid(QObject *plasmoid) 0164 { 0165 if (m_plasmoid == plasmoid) { 0166 return; 0167 } 0168 0169 m_plasmoid = plasmoid; 0170 0171 if (m_plasmoid) { 0172 m_configuration = qobject_cast<KDeclarative::ConfigPropertyMap *>(m_plasmoid->property("configuration").value<QObject *>()); 0173 } 0174 0175 emit plasmoidChanged(); 0176 } 0177 0178 QQuickItem *LayoutManager::rootItem() const 0179 { 0180 return m_rootItem; 0181 } 0182 0183 void LayoutManager::setRootItem(QQuickItem *root) 0184 { 0185 if (m_rootItem == root) { 0186 return; 0187 } 0188 0189 m_rootItem = root; 0190 emit rootItemChanged(); 0191 } 0192 0193 QQuickItem *LayoutManager::dndSpacer() const 0194 { 0195 return m_dndSpacer; 0196 } 0197 0198 void LayoutManager::setDndSpacer(QQuickItem *dnd) 0199 { 0200 if (m_dndSpacer == dnd) { 0201 return; 0202 } 0203 0204 m_dndSpacer = dnd; 0205 emit dndSpacerChanged(); 0206 } 0207 0208 QQuickItem *LayoutManager::mainLayout() const 0209 { 0210 return m_mainLayout; 0211 } 0212 0213 void LayoutManager::setMainLayout(QQuickItem *main) 0214 { 0215 if (main == m_mainLayout) { 0216 return; 0217 } 0218 0219 m_mainLayout = main; 0220 emit mainLayoutChanged(); 0221 } 0222 0223 QQuickItem *LayoutManager::startLayout() const 0224 { 0225 return m_startLayout; 0226 } 0227 0228 void LayoutManager::setStartLayout(QQuickItem *start) 0229 { 0230 if (m_startLayout == start) { 0231 return; 0232 } 0233 0234 m_startLayout = start; 0235 emit startLayoutChanged(); 0236 } 0237 0238 QQuickItem *LayoutManager::endLayout() const 0239 { 0240 return m_endLayout; 0241 } 0242 0243 void LayoutManager::setEndLayout(QQuickItem *end) 0244 { 0245 if (m_endLayout == end) { 0246 return; 0247 } 0248 0249 m_endLayout = end; 0250 emit endLayoutChanged(); 0251 } 0252 0253 QQuickItem *LayoutManager::metrics() const 0254 { 0255 return m_metrics; 0256 } 0257 0258 void LayoutManager::setMetrics(QQuickItem *metrics) 0259 { 0260 if (m_metrics == metrics) { 0261 return; 0262 } 0263 0264 m_metrics = metrics; 0265 emit metricsChanged(); 0266 } 0267 0268 void LayoutManager::updateOrder() 0269 { 0270 Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt()); 0271 0272 auto nextorder = m_appletOrder; 0273 0274 if (alignment==Latte::Types::Justify) { 0275 nextorder.insert(m_splitterPosition-1, JUSTIFYSPLITTERID); 0276 nextorder.insert(m_splitterPosition2-1, JUSTIFYSPLITTERID); 0277 } 0278 0279 setOrder(nextorder); 0280 } 0281 0282 void LayoutManager::onRootItemChanged() 0283 { 0284 if (!m_rootItem) { 0285 return; 0286 } 0287 0288 auto rootMetaObject = m_rootItem->metaObject(); 0289 int createAppletItemIndex = rootMetaObject->indexOfMethod("createAppletItem(QVariant)"); 0290 m_createAppletItemMethod = rootMetaObject->method(createAppletItemIndex); 0291 0292 int createJustifySplitterIndex = rootMetaObject->indexOfMethod("createJustifySplitter()"); 0293 m_createJustifySplitterMethod = rootMetaObject->method(createJustifySplitterIndex); 0294 0295 int initAppletContainerIndex = rootMetaObject->indexOfMethod("initAppletContainer(QVariant,QVariant)"); 0296 m_initAppletContainerMethod = rootMetaObject->method(initAppletContainerIndex); 0297 } 0298 0299 bool LayoutManager::isValidApplet(const int &id) 0300 { 0301 //! should be loaded after m_plasmoid has been set properly 0302 if (!m_plasmoid) { 0303 return false; 0304 } 0305 0306 QList<QObject *> applets = m_plasmoid->property("applets").value<QList<QObject *>>(); 0307 0308 for(int i=0; i<applets.count(); ++i) { 0309 uint appletid = applets[i]->property("id").toUInt(); 0310 if (id>0 && appletid == (uint)id) { 0311 return true; 0312 } 0313 } 0314 0315 return false; 0316 } 0317 0318 //! Actions 0319 void LayoutManager::restore() 0320 { 0321 QList<int> appletIdsOrder = toIntList((*m_configuration)["appletOrder"].toString()); 0322 QList<QObject *> applets = m_plasmoid->property("applets").value<QList<QObject *>>(); 0323 0324 Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt()); 0325 int splitterPosition = (*m_configuration)["splitterPosition"].toInt(); 0326 int splitterPosition2 = (*m_configuration)["splitterPosition2"].toInt(); 0327 0328 if (alignment==Latte::Types::Justify) { 0329 if (splitterPosition!=-1 && splitterPosition2!=-1) { 0330 appletIdsOrder.insert(splitterPosition-1, -1); 0331 appletIdsOrder.insert(splitterPosition2-1, -1); 0332 } else { 0333 appletIdsOrder.insert(0, -1); 0334 appletIdsOrder << -1; 0335 } 0336 } 0337 0338 QList<int> invalidApplets; 0339 0340 //! track invalid applets, meaning applets that have not be loaded properly 0341 for (int i=0; i<appletIdsOrder.count(); ++i) { 0342 int aid = appletIdsOrder[i]; 0343 0344 if (aid>0 && !isValidApplet(aid)) { 0345 invalidApplets << aid; 0346 } 0347 } 0348 0349 //! remove invalid applets from the ids order 0350 for (int i=0; i<invalidApplets.count(); ++i) { 0351 appletIdsOrder.removeAll(invalidApplets[i]); 0352 } 0353 0354 //! order valid applets based on the cleaned applet ids order 0355 QList<QObject *> orderedApplets; 0356 0357 for (int i=0; i<appletIdsOrder.count(); ++i) { 0358 if (appletIdsOrder[i] == -1) { 0359 orderedApplets << nullptr; 0360 continue; 0361 } 0362 0363 for(int j=0; j<applets.count(); ++j) { 0364 if (applets[j]->property("id").toInt() == appletIdsOrder[i]) { 0365 orderedApplets << applets[j]; 0366 break; 0367 } 0368 } 0369 } 0370 0371 QList<int> orphanedIds; 0372 for(int i=0; i<applets.count(); ++i) { 0373 uint id = applets[i]->property("id").toUInt(); 0374 0375 if (!appletIdsOrder.contains(id)) { 0376 orphanedIds << id; 0377 } 0378 } 0379 0380 //Validator 0381 QList<int> validateAppletsOrder; 0382 for (int i=0; i<orderedApplets.count(); ++i) { 0383 if (orderedApplets[i] == nullptr) { 0384 validateAppletsOrder << -1; 0385 continue; 0386 } 0387 0388 validateAppletsOrder << orderedApplets[i]->property("id").toUInt(); 0389 } 0390 0391 for(int i=0; i<applets.count(); ++i) { 0392 if (!orderedApplets.contains(applets[i])) { 0393 //! after order has been loaded correctly all renaming applets that do not have specified position are added in the end 0394 orderedApplets<<applets[i]; 0395 } 0396 } 0397 0398 qDebug() << "org.kde.latte ::: applets found :: " << applets.count() << " : " << appletIdsOrder << " :: " << splitterPosition << " : " << splitterPosition2 << " | " << alignment; 0399 qDebug() << "org.kde.latte ::: applets orphaned added in the end:: " << orphanedIds; 0400 qDebug() << "org.kde.latte ::: applets recorded order :: " << appletIdsOrder; 0401 qDebug() << "org.kde.latte ::: applets produced order ?? " << validateAppletsOrder; 0402 0403 if (alignment != Latte::Types::Justify) { 0404 for (int i=0; i<orderedApplets.count(); ++i) { 0405 if (orderedApplets[i] == nullptr) { 0406 continue; 0407 } 0408 0409 QVariant appletItemVariant; 0410 QVariant appletVariant; appletVariant.setValue(orderedApplets[i]); 0411 m_createAppletItemMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, appletItemVariant), Q_ARG(QVariant, appletVariant)); 0412 QQuickItem *appletItem = appletItemVariant.value<QQuickItem *>(); 0413 appletItem->setParentItem(m_mainLayout); 0414 } 0415 } else { 0416 QQuickItem *parentlayout = m_startLayout; 0417 0418 for (int i=0; i<orderedApplets.count(); ++i) { 0419 if (orderedApplets[i] == nullptr) { 0420 QVariant splitterItemVariant; 0421 m_createJustifySplitterMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, splitterItemVariant)); 0422 QQuickItem *splitterItem = splitterItemVariant.value<QQuickItem *>(); 0423 0424 if (parentlayout == m_startLayout) { 0425 //! first splitter as last child in startlayout 0426 splitterItem->setParentItem(parentlayout); 0427 parentlayout = m_mainLayout; 0428 } else if (parentlayout == m_mainLayout) { 0429 //! second splitter as first child in endlayout 0430 parentlayout = m_endLayout; 0431 splitterItem->setParentItem(parentlayout); 0432 } 0433 0434 continue; 0435 } 0436 0437 QVariant appletItemVariant; 0438 QVariant appletVariant; appletVariant.setValue(orderedApplets[i]); 0439 m_createAppletItemMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, appletItemVariant), Q_ARG(QVariant, appletVariant)); 0440 QQuickItem *appletItem = appletItemVariant.value<QQuickItem *>(); 0441 appletItem->setParentItem(parentlayout); 0442 } 0443 } 0444 0445 restoreOptions(); 0446 save(); //will restore also a valid applets ids order 0447 cleanupOptions(); 0448 initSaveConnections(); 0449 m_hasRestoredAppletsTimer.start(); 0450 } 0451 0452 void LayoutManager::initSaveConnections() 0453 { 0454 connect(this, &LayoutManager::appletOrderChanged, this, &LayoutManager::cleanupOptions); 0455 connect(this, &LayoutManager::splitterPositionChanged, this, &LayoutManager::saveOptions); 0456 connect(this, &LayoutManager::splitterPosition2Changed, this, &LayoutManager::saveOptions); 0457 connect(this, &LayoutManager::lockedZoomAppletsChanged, this, &LayoutManager::saveOptions); 0458 connect(this, &LayoutManager::userBlocksColorizingAppletsChanged, this, &LayoutManager::saveOptions); 0459 } 0460 0461 void LayoutManager::restoreOptions() 0462 { 0463 restoreOption(ISAPPLETLOCKEDOPTION); 0464 restoreOption(ISCOLORINGBLOCKEDOPTION); 0465 } 0466 0467 void LayoutManager::restoreOption(const char *option) 0468 { 0469 QList<int> applets = toIntList((*m_configuration)[m_option[option]].toString()); 0470 0471 if (option == ISAPPLETLOCKEDOPTION) { 0472 setLockedZoomApplets(applets); 0473 } else if (option == ISCOLORINGBLOCKEDOPTION) { 0474 setUserBlocksColorizingApplets(applets); 0475 } 0476 } 0477 0478 bool LayoutManager::isJustifySplitter(const QQuickItem *item) const 0479 { 0480 return item && (item->property("isInternalViewSplitter").toBool() == true); 0481 } 0482 0483 bool LayoutManager::isMasqueradedIndex(const int &x, const int &y) 0484 { 0485 return (x==y && x<=MASQUERADEDINDEXTOPOINTBASE && y<=MASQUERADEDINDEXTOPOINTBASE); 0486 } 0487 0488 int LayoutManager::masquearadedIndex(const int &x, const int &y) 0489 { 0490 return qAbs(x - MASQUERADEDINDEXTOPOINTBASE); 0491 } 0492 0493 QPoint LayoutManager::indexToMasquearadedPoint(const int &index) 0494 { 0495 return QPoint(MASQUERADEDINDEXTOPOINTBASE-index, MASQUERADEDINDEXTOPOINTBASE-index); 0496 } 0497 0498 void LayoutManager::reorderParabolicSpacers() 0499 { 0500 QQuickItem *startParabolicSpacer = m_mainLayout->property("startParabolicSpacer").value<QQuickItem *>(); 0501 QQuickItem *endParabolicSpacer = m_mainLayout->property("endParabolicSpacer").value<QQuickItem *>(); 0502 0503 if (!startParabolicSpacer || !endParabolicSpacer) { 0504 return; 0505 } 0506 0507 insertAtLayoutTail(m_mainLayout, startParabolicSpacer); 0508 insertAtLayoutHead(m_mainLayout, endParabolicSpacer); 0509 } 0510 0511 void LayoutManager::save() 0512 { 0513 QList<int> appletIds; 0514 0515 reorderParabolicSpacers(); 0516 0517 auto collectLayoutAppletIds = [](QQuickItem *layout, QList<int> &appletIds) { 0518 int childCount = 0; 0519 for (int i=0; i<layout->childItems().count(); ++i) { 0520 QQuickItem *item = layout->childItems()[i]; 0521 bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); 0522 bool isParabolicEdgeSpacer = item->property("isParabolicEdgeSpacer").toBool(); 0523 if (!isInternalSplitter && !isParabolicEdgeSpacer) { 0524 QVariant appletVariant = item->property("applet"); 0525 if (!appletVariant.isValid()) { 0526 continue; 0527 } 0528 0529 QObject *applet = appletVariant.value<QObject *>(); 0530 0531 if (!applet) { 0532 continue; 0533 } 0534 0535 uint id = applet->property("id").toUInt(); 0536 0537 if (id>0) { 0538 childCount++; 0539 appletIds << id; 0540 } 0541 } 0542 } 0543 return childCount; 0544 }; 0545 0546 int startChilds = collectLayoutAppletIds(m_startLayout, appletIds); 0547 int mainChilds = collectLayoutAppletIds(m_mainLayout, appletIds); 0548 int endChilds = collectLayoutAppletIds(m_endLayout, appletIds); 0549 0550 Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt()); 0551 0552 if (alignment == Latte::Types::Justify) { 0553 setSplitterPosition(startChilds + 1); 0554 setSplitterPosition2(startChilds + 1 + mainChilds + 1); 0555 } else { 0556 int splitterPosition = (*m_configuration)["splitterPosition"].toInt(); 0557 int splitterPosition2 = (*m_configuration)["splitterPosition2"].toInt(); 0558 0559 setSplitterPosition(splitterPosition); 0560 setSplitterPosition2(splitterPosition2); 0561 } 0562 0563 //! are not writing in config file for some cases mentioned in class header so they are not used 0564 //(*m_configuration)["splitterPosition"] = QVariant(startChilds + 1); 0565 //(*m_configuration)["splitterPosition2"] = QVariant(startChilds + 1 + mainChilds + 1); 0566 //(*m_configuration)["appletOrder"] = appletIds.join(";"); 0567 0568 setAppletOrder(appletIds); 0569 0570 //! publish updated order 0571 updateOrder(); 0572 0573 //! save applet order 0574 QString appletsserialized = toStr(appletIds); 0575 0576 if ((*m_configuration)["appletOrder"] != appletsserialized) { 0577 m_configuration->insert("appletOrder", appletsserialized); 0578 emit m_configuration->valueChanged("appletOrder", appletsserialized); 0579 } 0580 } 0581 0582 void LayoutManager::saveOptions() 0583 { 0584 QString lockedserialized = toStr(m_lockedZoomApplets); 0585 if ((*m_configuration)[m_option[ISAPPLETLOCKEDOPTION]] != lockedserialized) { 0586 m_configuration->insert(m_option[ISAPPLETLOCKEDOPTION], lockedserialized); 0587 emit m_configuration->valueChanged(m_option[ISAPPLETLOCKEDOPTION], lockedserialized); 0588 } 0589 0590 QString colorsserialized = toStr(m_userBlocksColorizingApplets); 0591 if ((*m_configuration)[m_option[ISCOLORINGBLOCKEDOPTION]] != colorsserialized) { 0592 m_configuration->insert(m_option[ISCOLORINGBLOCKEDOPTION], colorsserialized); 0593 emit m_configuration->valueChanged(m_option[ISCOLORINGBLOCKEDOPTION], colorsserialized); 0594 } 0595 0596 if ((*m_configuration)["splitterPosition"] != m_splitterPosition) { 0597 m_configuration->insert("splitterPosition", m_splitterPosition); 0598 emit m_configuration->valueChanged(m_option["splitterPosition"], m_splitterPosition); 0599 } 0600 0601 if ((*m_configuration)["splitterPosition2"] != m_splitterPosition2) { 0602 m_configuration->insert("splitterPosition2", m_splitterPosition2); 0603 emit m_configuration->valueChanged(m_option["splitterPosition2"], m_splitterPosition2); 0604 } 0605 } 0606 0607 void LayoutManager::setOption(const int &appletId, const QString &property, const QVariant &value) 0608 { 0609 if (property == ISAPPLETLOCKEDOPTION) { 0610 bool enabled = value.toBool(); 0611 0612 if (enabled && !m_lockedZoomApplets.contains(appletId)) { 0613 QList<int> applets = m_lockedZoomApplets; applets << appletId; 0614 setLockedZoomApplets(applets); 0615 } else if (!enabled && m_lockedZoomApplets.contains(appletId)) { 0616 QList<int> applets = m_lockedZoomApplets; applets.removeAll(appletId); 0617 setLockedZoomApplets(applets); 0618 } 0619 } else if (property == ISCOLORINGBLOCKEDOPTION) { 0620 bool enabled = value.toBool(); 0621 0622 if (enabled && !m_userBlocksColorizingApplets.contains(appletId)) { 0623 QList<int> applets = m_userBlocksColorizingApplets; applets << appletId; 0624 setUserBlocksColorizingApplets(applets); 0625 } else if (!enabled && m_userBlocksColorizingApplets.contains(appletId)) { 0626 QList<int> applets = m_userBlocksColorizingApplets; applets.removeAll(appletId); 0627 setUserBlocksColorizingApplets(applets); 0628 } 0629 } 0630 } 0631 0632 void LayoutManager::insertBefore(QQuickItem *hoveredItem, QQuickItem *item) 0633 { 0634 if (!hoveredItem || !item || hoveredItem == item) { 0635 return; 0636 } 0637 0638 item->setParentItem(hoveredItem->parentItem()); 0639 item->stackBefore(hoveredItem); 0640 } 0641 0642 void LayoutManager::insertAfter(QQuickItem *hoveredItem, QQuickItem *item) 0643 { 0644 if (!hoveredItem || !item || hoveredItem == item) { 0645 return; 0646 } 0647 0648 item->setParentItem(hoveredItem->parentItem()); 0649 item->stackAfter(hoveredItem); 0650 } 0651 0652 void LayoutManager::insertAtLayoutTail(QQuickItem *layout, QQuickItem *item) 0653 { 0654 if (!layout || !item) { 0655 return; 0656 } 0657 0658 if (layout->childItems().count() > 0) { 0659 if (layout == m_endLayout && isJustifySplitter(layout->childItems()[0])) { 0660 //! this way we ignore the justify splitter in start layout 0661 insertAfter(layout->childItems()[0], item); 0662 } else { 0663 insertBefore(layout->childItems()[0], item); 0664 } 0665 return; 0666 } 0667 0668 item->setParentItem(layout); 0669 } 0670 0671 void LayoutManager::insertAtLayoutHead(QQuickItem *layout, QQuickItem *item) 0672 { 0673 if (!layout || !item) { 0674 return; 0675 } 0676 0677 int count = layout->childItems().count(); 0678 0679 if (count > 0) { 0680 if (layout == m_startLayout && isJustifySplitter(layout->childItems()[count-1])) { 0681 //! this way we ignore the justify splitter in end layout 0682 insertBefore(layout->childItems()[count-1], item); 0683 } else { 0684 insertAfter(layout->childItems()[count-1], item); 0685 } 0686 return; 0687 } 0688 0689 item->setParentItem(layout); 0690 } 0691 0692 void LayoutManager::insertAtLayoutIndex(QQuickItem *layout, QQuickItem *item, const int &index) 0693 { 0694 if (!layout || !item) { 0695 return; 0696 } 0697 0698 if (index == 0) { 0699 insertAtLayoutTail(layout, item); 0700 } else if (index >= layout->childItems().count()) { 0701 insertAtLayoutHead(layout, item); 0702 } else { 0703 insertBefore(layout->childItems()[index], item); 0704 } 0705 } 0706 0707 bool LayoutManager::insertAtLayoutCoordinates(QQuickItem *layout, QQuickItem *item, int x, int y) 0708 { 0709 if (!layout || !item || !m_plasmoid || !layout->contains(QPointF(x,y))) { 0710 return false; 0711 } 0712 0713 bool horizontal = (m_plasmoid->property("formFactor").toInt() != Plasma::Types::Vertical); 0714 bool vertical = !horizontal; 0715 int rowspacing = qMax(0, layout->property("rowSpacing").toInt()); 0716 int columnspacing = qMax(0, layout->property("columnSpacing").toInt()); 0717 0718 if (horizontal) { 0719 y = layout->height() / 2; 0720 } else { 0721 x = layout->width() / 2; 0722 } 0723 0724 //! child renamed at hovered 0725 QQuickItem *hovered = layout->childAt(x, y); 0726 0727 //if we got a place inside the space between 2 applets, we have to find it manually 0728 if (!hovered) { 0729 int size = layout->childItems().count(); 0730 if (horizontal) { 0731 for (int i = 0; i < size; ++i) { 0732 if (i>=layout->childItems().count()) { 0733 break; 0734 } 0735 0736 QQuickItem *candidate = layout->childItems()[i]; 0737 int right = candidate->x() + candidate->width() + rowspacing; 0738 if (x>=candidate->x() && x<right) { 0739 hovered = candidate; 0740 break; 0741 } 0742 } 0743 } else { 0744 for (int i = 0; i < size; ++i) { 0745 if (i>=layout->childItems().count()) { 0746 break; 0747 } 0748 0749 QQuickItem *candidate = layout->childItems()[i]; 0750 int bottom = candidate->y() + candidate->height() + columnspacing; 0751 if (y>=candidate->y() && y<bottom) { 0752 hovered = candidate; 0753 break; 0754 } 0755 } 0756 } 0757 } 0758 0759 if (hovered == item && item->parentItem() == layout) { 0760 //! already hovered and in correct position 0761 return true; 0762 } 0763 0764 if (hovered) { 0765 if ((vertical && y < (hovered->y() + hovered->height()/2) && hovered->height() > 1) || 0766 (horizontal && x < (hovered->x() + hovered->width()/2) && hovered->width() > 1)) { 0767 insertBefore(hovered, item); 0768 } else { 0769 insertAfter(hovered, item); 0770 } 0771 0772 return true; 0773 } 0774 0775 return false; 0776 } 0777 0778 QQuickItem *LayoutManager::firstSplitter() 0779 { 0780 for(int i=0; i<m_startLayout->childItems().count(); ++i) { 0781 QQuickItem *item = m_startLayout->childItems()[i]; 0782 bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); 0783 if (isInternalSplitter) { 0784 return item; 0785 } 0786 } 0787 0788 for(int i=0; i<m_mainLayout->childItems().count(); ++i) { 0789 QQuickItem *item = m_mainLayout->childItems()[i]; 0790 bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); 0791 if (isInternalSplitter) { 0792 return item; 0793 } 0794 } 0795 0796 for(int i=0; i<m_endLayout->childItems().count(); ++i) { 0797 QQuickItem *item = m_endLayout->childItems()[i]; 0798 bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); 0799 if (isInternalSplitter) { 0800 return item; 0801 } 0802 } 0803 0804 return nullptr; 0805 } 0806 0807 QQuickItem *LayoutManager::lastSplitter() 0808 { 0809 for(int i=m_endLayout->childItems().count()-1; i>=0; --i) { 0810 QQuickItem *item = m_endLayout->childItems()[i]; 0811 bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); 0812 if (isInternalSplitter) { 0813 return item; 0814 } 0815 } 0816 0817 for(int i=m_mainLayout->childItems().count()-1; i>=0; --i) { 0818 QQuickItem *item = m_mainLayout->childItems()[i]; 0819 bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); 0820 if (isInternalSplitter) { 0821 return item; 0822 } 0823 } 0824 0825 for(int i=m_endLayout->childItems().count()-1; i>=0; --i) { 0826 QQuickItem *item = m_endLayout->childItems()[i]; 0827 bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); 0828 if (isInternalSplitter) { 0829 return item; 0830 } 0831 } 0832 0833 return nullptr; 0834 } 0835 0836 QQuickItem *LayoutManager::appletItemInLayout(QQuickItem *layout, const int &id) 0837 { 0838 if (!layout) { 0839 return nullptr; 0840 } 0841 0842 for(int i=0; i<layout->childItems().count(); ++i) { 0843 QQuickItem *item = layout->childItems()[i]; 0844 bool isInternalSplitter = item->property("isInternalViewSplitter").toBool(); 0845 bool isParabolicEdgeSpacer = item->property("isParabolicEdgeSpacer").toBool(); 0846 if (!isInternalSplitter && !isParabolicEdgeSpacer) { 0847 QVariant appletVariant = item->property("applet"); 0848 if (!appletVariant.isValid()) { 0849 continue; 0850 } 0851 0852 QObject *applet = appletVariant.value<QObject *>(); 0853 0854 if (!applet) { 0855 continue; 0856 } 0857 0858 int tempid = applet->property("id").toInt(); 0859 0860 if (id == tempid) { 0861 return item; 0862 } 0863 } 0864 } 0865 0866 return nullptr; 0867 } 0868 0869 QQuickItem *LayoutManager::appletItem(const int &id) 0870 { 0871 QQuickItem *item = appletItemInLayout(m_mainLayout, id); 0872 0873 if (!item) { 0874 item = appletItemInLayout(m_startLayout, id); 0875 } 0876 0877 if (!item) { 0878 item = appletItemInLayout(m_endLayout, id); 0879 } 0880 0881 return item; 0882 } 0883 0884 int LayoutManager::dndSpacerIndex() 0885 { 0886 if (m_dndSpacer->parentItem() != m_startLayout 0887 && m_dndSpacer->parentItem() != m_mainLayout 0888 && m_dndSpacer->parentItem() != m_endLayout) { 0889 return -1; 0890 } 0891 0892 Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt()); 0893 int index = -1; 0894 0895 if (alignment == Latte::Types::Justify) { 0896 for(int i=0; i<m_startLayout->childItems().count(); ++i) { 0897 QQuickItem *item = m_startLayout->childItems()[i]; 0898 bool isparabolicspacer = item->property("isParabolicEdgeSpacer").toBool(); 0899 0900 if (isparabolicspacer) { 0901 continue; 0902 } 0903 0904 index++; 0905 if (item == m_dndSpacer) { 0906 return index; 0907 } 0908 } 0909 } 0910 0911 for(int i=0; i<m_mainLayout->childItems().count(); ++i) { 0912 QQuickItem *item = m_mainLayout->childItems()[i]; 0913 bool isparabolicspacer = item->property("isParabolicEdgeSpacer").toBool(); 0914 0915 if (isparabolicspacer) { 0916 continue; 0917 } 0918 0919 index++; 0920 if (item == m_dndSpacer) { 0921 return index; 0922 } 0923 } 0924 0925 if (alignment == Latte::Types::Justify) { 0926 for(int i=0; i<m_endLayout->childItems().count(); ++i) { 0927 QQuickItem *item = m_endLayout->childItems()[i]; 0928 bool isparabolicspacer = item->property("isParabolicEdgeSpacer").toBool(); 0929 0930 if (isparabolicspacer) { 0931 continue; 0932 } 0933 0934 index++; 0935 if (item == m_dndSpacer) { 0936 return index; 0937 } 0938 } 0939 } 0940 0941 return -1; 0942 } 0943 0944 0945 void LayoutManager::requestAppletsOrder(const QList<int> &order) 0946 { 0947 Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt()); 0948 QQuickItem *nextlayout = alignment != Latte::Types::Justify ? m_mainLayout : m_startLayout; 0949 QQuickItem *previousitem = nullptr; 0950 0951 int addedsplitters{0}; 0952 0953 for (int i=0; i<order.count(); ++i) { 0954 QQuickItem *currentitem; 0955 0956 if (alignment != Latte::Types::Justify || order[i] != JUSTIFYSPLITTERID) { 0957 currentitem = appletItem(order[i]); 0958 } else if (alignment == Latte::Types::Justify && order[i] == JUSTIFYSPLITTERID) { 0959 currentitem = addedsplitters == 0 ? firstSplitter() : lastSplitter(); 0960 addedsplitters++; 0961 } 0962 0963 0964 if (previousitem) { 0965 insertAfter(previousitem, currentitem); 0966 } else { 0967 insertAtLayoutTail(nextlayout, currentitem); 0968 } 0969 0970 previousitem = currentitem; 0971 0972 if (alignment == Latte::Types::Justify && order[i] == JUSTIFYSPLITTERID) { 0973 nextlayout = addedsplitters == 1 ? m_mainLayout : m_endLayout; 0974 } 0975 } 0976 0977 if (alignment == Latte::Types::Justify) { 0978 moveAppletsBasedOnJustifyAlignment(); 0979 save(); 0980 } 0981 } 0982 0983 void LayoutManager::requestAppletsInLockedZoom(const QList<int> &applets) 0984 { 0985 setLockedZoomApplets(applets); 0986 } 0987 0988 void LayoutManager::requestAppletsDisabledColoring(const QList<int> &applets) 0989 { 0990 setUserBlocksColorizingApplets(applets); 0991 } 0992 0993 int LayoutManager::distanceFromTail(QQuickItem *layout, QPointF pos) const 0994 { 0995 return (int)qSqrt(qPow(pos.x() - 0, 2) + qPow(pos.y() - 0, 2)); 0996 } 0997 0998 int LayoutManager::distanceFromHead(QQuickItem *layout, QPointF pos) const 0999 { 1000 float rightX = layout->width() - 1; 1001 float rightY = layout->height() - 1; 1002 return (int)qSqrt(qPow(pos.x() - rightX, 2) + qPow(pos.y() - rightY, 2)); 1003 } 1004 1005 void LayoutManager::insertAtCoordinates(QQuickItem *item, const int &x, const int &y) 1006 { 1007 if (!m_configuration || !item) { 1008 return; 1009 } 1010 1011 Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt()); 1012 1013 bool result{false}; 1014 1015 if (alignment == Latte::Types::Justify) { 1016 QPointF startPos = m_startLayout->mapFromItem(m_rootItem, QPointF(x, y)); 1017 result = insertAtLayoutCoordinates(m_startLayout, item, startPos.x(), startPos.y()); 1018 1019 if (!result) { 1020 QPointF endPos = m_endLayout->mapFromItem(m_rootItem, QPointF(x, y)); 1021 result = insertAtLayoutCoordinates(m_endLayout, item, endPos.x(), endPos.y()); 1022 } 1023 } 1024 1025 if (!result) { 1026 QPointF mainPos = m_mainLayout->mapFromItem(m_rootItem, QPointF(x, y)); 1027 //! in javascript direct insertAtCoordinates was usedd ??? 1028 result = insertAtLayoutCoordinates(m_mainLayout, item, mainPos.x(), mainPos.y()); 1029 } 1030 1031 if (result) { 1032 return; 1033 } 1034 1035 //! item was not added because it does not hover any of the layouts and layout items 1036 //! so the place that will be added is specified by the distance of the item from the layouts 1037 1038 QPointF startrelpos = m_startLayout->mapFromItem(m_rootItem, QPointF(x, y)); 1039 QPointF endrelpos = m_endLayout->mapFromItem(m_rootItem, QPointF(x, y)); 1040 QPointF mainrelpos = m_mainLayout->mapFromItem(m_rootItem, QPointF(x, y)); 1041 1042 int starttaildistance = distanceFromTail(m_startLayout, startrelpos); 1043 int startheaddistance = distanceFromHead(m_startLayout, startrelpos); 1044 int maintaildistance = distanceFromTail(m_mainLayout, mainrelpos); 1045 int mainheaddistance = distanceFromHead(m_mainLayout, mainrelpos); 1046 int endtaildistance = distanceFromTail(m_endLayout, endrelpos); 1047 int endheaddistance = distanceFromHead(m_endLayout, endrelpos); 1048 1049 int startdistance = qMin(starttaildistance, startheaddistance); 1050 int maindistance = qMin(maintaildistance, mainheaddistance); 1051 int enddistance = qMin(endtaildistance, endheaddistance); 1052 1053 if (alignment != Latte::Types::Justify || (maindistance < startdistance && maindistance < enddistance)) { 1054 if (maintaildistance <= mainheaddistance) { 1055 insertAtLayoutTail(m_mainLayout, item); 1056 } else { 1057 insertAtLayoutHead(m_mainLayout, item); 1058 } 1059 } else if (startdistance < maindistance && startdistance < enddistance) { 1060 if (maintaildistance <= mainheaddistance) { 1061 insertAtLayoutTail(m_startLayout, item); 1062 } else { 1063 insertAtLayoutHead(m_startLayout, item); 1064 } 1065 } else { 1066 if (endtaildistance <= endheaddistance) { 1067 insertAtLayoutTail(m_endLayout, item); 1068 } else { 1069 insertAtLayoutHead(m_endLayout, item); 1070 } 1071 } 1072 } 1073 1074 void LayoutManager::cleanupOptions() 1075 { 1076 auto inlockedzoomcurrent = m_lockedZoomApplets; 1077 QList<int> inlockedzoomnext; 1078 for(int i=0; i<inlockedzoomcurrent.count(); ++i) { 1079 if (m_appletOrder.contains(inlockedzoomcurrent[i])) { 1080 inlockedzoomnext << inlockedzoomcurrent[i]; 1081 } 1082 } 1083 setLockedZoomApplets(inlockedzoomnext); 1084 1085 auto disabledcoloringcurrent = m_userBlocksColorizingApplets; 1086 QList <int> disabledcoloringnext; 1087 for(int i=0; i<disabledcoloringcurrent.count(); ++i) { 1088 if (m_appletOrder.contains(disabledcoloringcurrent[i])) { 1089 disabledcoloringnext << disabledcoloringcurrent[i]; 1090 } 1091 } 1092 setUserBlocksColorizingApplets(disabledcoloringnext); 1093 } 1094 1095 void LayoutManager::addAppletItem(QObject *applet, int index) 1096 { 1097 if (!m_startLayout || !m_mainLayout || !m_endLayout || index < 0) { 1098 return; 1099 } 1100 1101 Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt()); 1102 QVariant appletItemVariant; 1103 QVariant appletVariant; appletVariant.setValue(applet); 1104 m_createAppletItemMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, appletItemVariant), Q_ARG(QVariant, appletVariant)); 1105 QQuickItem *aitem = appletItemVariant.value<QQuickItem *>(); 1106 1107 if (m_dndSpacer) { 1108 m_dndSpacer->setParentItem(m_rootItem); 1109 } 1110 1111 QQuickItem *previousItem{nullptr}; 1112 1113 if (index >= m_order.count()) { 1114 // do nothing it should be added at the end 1115 } else { 1116 if (alignment == Latte::Types::Justify && m_order[index] == JUSTIFYSPLITTERID) { 1117 if (index<m_splitterPosition2-1) { 1118 previousItem = firstSplitter(); 1119 } else { 1120 previousItem = lastSplitter(); 1121 } 1122 } else { 1123 previousItem = appletItem(m_order[index]); 1124 } 1125 } 1126 1127 if (previousItem) { 1128 insertBefore(previousItem, aitem); 1129 } else { 1130 if (alignment == Latte::Types::Justify) { 1131 insertAtLayoutHead(m_endLayout, aitem); 1132 } else { 1133 insertAtLayoutHead(m_mainLayout, aitem); 1134 } 1135 } 1136 1137 if (alignment == Latte::Types::Justify) { 1138 moveAppletsBasedOnJustifyAlignment(); 1139 } 1140 1141 save(); 1142 } 1143 1144 void LayoutManager::addAppletItem(QObject *applet, int x, int y) 1145 { 1146 if (!m_startLayout || !m_mainLayout || !m_endLayout) { 1147 return; 1148 } 1149 1150 PlasmaQuick::AppletQuickItem *aqi = qobject_cast<PlasmaQuick::AppletQuickItem *>(applet); 1151 1152 if (aqi && aqi->applet() && !aqi->applet()->destroyed() && m_appletsInScheduledDestruction.contains(aqi->applet()->id())) { 1153 int id = aqi->applet()->id(); 1154 QVariant appletContainerVariant; appletContainerVariant.setValue(m_appletsInScheduledDestruction[id]); 1155 QVariant appletVariant; appletVariant.setValue(applet); 1156 m_initAppletContainerMethod.invoke(m_rootItem, Q_ARG(QVariant, appletContainerVariant), Q_ARG(QVariant, appletVariant)); 1157 setAppletInScheduledDestruction(id, false); 1158 return; 1159 } 1160 1161 QVariant appletItemVariant; 1162 QVariant appletVariant; appletVariant.setValue(applet); 1163 m_createAppletItemMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, appletItemVariant), Q_ARG(QVariant, appletVariant)); 1164 QQuickItem *appletItem = appletItemVariant.value<QQuickItem *>(); 1165 1166 if (m_dndSpacer->parentItem() == m_mainLayout 1167 || m_dndSpacer->parentItem() == m_startLayout 1168 || m_dndSpacer->parentItem() == m_endLayout) { 1169 insertBefore(m_dndSpacer, appletItem); 1170 1171 QQuickItem *currentlayout = m_dndSpacer->parentItem(); 1172 m_dndSpacer->setParentItem(m_rootItem); 1173 1174 if (currentlayout == m_startLayout) { 1175 reorderSplitterInStartLayout(); 1176 } else if (currentlayout ==m_endLayout) { 1177 reorderSplitterInEndLayout(); 1178 } 1179 } else if (x >= 0 && y >= 0) { 1180 // If the provided position is valid, use it. 1181 insertAtCoordinates(appletItem, x , y); 1182 } else { 1183 // Fall through to adding at the end of main layout. 1184 appletItem->setParentItem(m_mainLayout); 1185 } 1186 1187 save(); 1188 } 1189 1190 void LayoutManager::removeAppletItem(QObject *applet) 1191 { 1192 if (!m_startLayout || !m_mainLayout || !m_endLayout) { 1193 return; 1194 } 1195 1196 PlasmaQuick::AppletQuickItem *aqi = qobject_cast<PlasmaQuick::AppletQuickItem *>(applet); 1197 1198 if (!aqi) { 1199 return; 1200 } 1201 1202 int id = aqi->applet()->id(); 1203 1204 if (aqi->applet() && aqi->applet()->destroyed() && !m_appletsInScheduledDestruction.contains(id)/*this way we really delete it in the end*/) { 1205 setAppletInScheduledDestruction(id, true); 1206 return; 1207 } 1208 1209 destroyAppletContainer(aqi->applet()); 1210 } 1211 1212 void LayoutManager::destroyAppletContainer(QObject *applet) 1213 { 1214 if (!applet || !m_startLayout || !m_mainLayout || !m_endLayout) { 1215 return; 1216 } 1217 1218 Plasma::Applet *ca = qobject_cast<Plasma::Applet *>(applet); 1219 1220 if (!ca) { 1221 qDebug() << "org.kde.destroy destroying applet could not succeed Plasma/Applet was not identified..."; 1222 return; 1223 } 1224 1225 int id = ca->id(); 1226 1227 bool destroyed{false}; 1228 1229 if (m_appletsInScheduledDestruction.contains(id)) { 1230 //! when deleted from scheduled destruction 1231 m_appletsInScheduledDestruction[id]->setVisible(false); 1232 m_appletsInScheduledDestruction[id]->setParentItem(m_rootItem); 1233 m_appletsInScheduledDestruction[id]->deleteLater(); 1234 setAppletInScheduledDestruction(id, false); 1235 destroyed = true; 1236 } else { 1237 //! when deleted directly for Plasma::Applet destruction e.g. synced applets 1238 for (int i=0; i<=2; ++i) { 1239 if (destroyed) { 1240 break; 1241 } 1242 1243 QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout)); 1244 1245 if (layout->childItems().count() > 0) { 1246 int size = layout->childItems().count(); 1247 for (int j=size-1; j>=0; --j) { 1248 QQuickItem *item = layout->childItems()[j]; 1249 bool issplitter = item->property("isInternalViewSplitter").toBool(); 1250 if (issplitter) { 1251 continue; 1252 } 1253 1254 QVariant appletVariant = item->property("applet"); 1255 if (!appletVariant.isValid()) { 1256 continue; 1257 } 1258 PlasmaQuick::AppletQuickItem *appletitem = appletVariant.value<PlasmaQuick::AppletQuickItem *>(); 1259 1260 if (appletitem && appletitem->applet() == applet) { 1261 item->setVisible(false); 1262 item->setParentItem(m_rootItem); 1263 item->deleteLater(); 1264 destroyed = true; 1265 break; 1266 } 1267 } 1268 } 1269 } 1270 } 1271 1272 if (destroyed) { 1273 save(); 1274 } 1275 } 1276 1277 void LayoutManager::reorderSplitterInStartLayout() 1278 { 1279 Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt()); 1280 1281 if (alignment != Latte::Types::Justify) { 1282 return; 1283 } 1284 1285 int size = m_startLayout->childItems().count(); 1286 1287 if (size > 0) { 1288 QQuickItem *splitter{nullptr}; 1289 1290 for (int i=0; i<size; ++i) { 1291 QQuickItem *item = m_startLayout->childItems()[i]; 1292 bool issplitter = item->property("isInternalViewSplitter").toBool(); 1293 1294 if (issplitter && i<size-1) { 1295 splitter = item; 1296 break; 1297 } 1298 } 1299 1300 if (splitter) { 1301 insertAfter(m_startLayout->childItems()[size-1],splitter); 1302 } 1303 } 1304 } 1305 1306 void LayoutManager::reorderSplitterInEndLayout() 1307 { 1308 Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt()); 1309 1310 if (alignment != Latte::Types::Justify) { 1311 return; 1312 } 1313 1314 int size = m_endLayout->childItems().count(); 1315 1316 if (size > 0) { 1317 QQuickItem *splitter{nullptr}; 1318 1319 for (int i=0; i<size; ++i) { 1320 QQuickItem *item = m_endLayout->childItems()[i]; 1321 bool issplitter = item->property("isInternalViewSplitter").toBool(); 1322 1323 if (issplitter && i!=0) { 1324 splitter = item; 1325 break; 1326 } 1327 } 1328 1329 if (splitter) { 1330 insertBefore(m_endLayout->childItems()[0],splitter); 1331 } 1332 } 1333 } 1334 1335 void LayoutManager::addJustifySplittersInMainLayout() 1336 { 1337 if (!m_configuration || !m_mainLayout) { 1338 return; 1339 } 1340 1341 destroyJustifySplitters(); 1342 1343 int splitterPosition = (*m_configuration)["splitterPosition"].toInt(); 1344 int splitterPosition2 = (*m_configuration)["splitterPosition2"].toInt(); 1345 1346 int splitterIndex = (splitterPosition >= 1 ? splitterPosition - 1 : -1); 1347 int splitterIndex2 = (splitterPosition2 >= 1 ? splitterPosition2 - 1 : -1); 1348 1349 //! First Splitter 1350 QVariant splitterItemVariant; 1351 m_createJustifySplitterMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, splitterItemVariant)); 1352 QQuickItem *splitterItem = splitterItemVariant.value<QQuickItem *>(); 1353 1354 int size = m_mainLayout->childItems().count()-2; //we need to remove parabolic spacers 1355 1356 splitterItem->setParentItem(m_mainLayout); 1357 1358 if (size>0 && splitterIndex>=0) { 1359 bool atend = (splitterIndex >= size); 1360 int validindex = (atend ? size-1 : splitterIndex) + 1; //we need to take into account first parabolic spacer 1361 QQuickItem *currentitem = m_mainLayout->childItems()[validindex]; 1362 1363 if (atend) { 1364 splitterItem->stackAfter(currentitem); 1365 } else { 1366 splitterItem->stackBefore(currentitem); 1367 } 1368 } else if (size>0) { 1369 //! add in first position 1370 QQuickItem *currentitem = m_mainLayout->childItems()[0]; 1371 splitterItem->stackBefore(currentitem); 1372 } 1373 1374 //! Second Splitter 1375 QVariant splitterItemVariant2; 1376 m_createJustifySplitterMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, splitterItemVariant2)); 1377 QQuickItem *splitterItem2 = splitterItemVariant2.value<QQuickItem *>(); 1378 1379 int size2 = m_mainLayout->childItems().count()-2; //we need to remove parabolic spacers 1380 1381 splitterItem2->setParentItem(m_mainLayout); 1382 1383 if (size2>0 && splitterIndex2>=0) { 1384 bool atend = (splitterIndex2 >= size2); 1385 int validindex2 = (atend ? size2-1 : splitterIndex2) + 1; //we need to take into account first parabolic spacer 1386 QQuickItem *currentitem2 = m_mainLayout->childItems()[validindex2]; 1387 1388 if (atend) { 1389 splitterItem2->stackAfter(currentitem2); 1390 } else { 1391 splitterItem2->stackBefore(currentitem2); 1392 } 1393 } else if (size2>1){ 1394 //! add in last position 1395 QQuickItem *currentitem2 = m_mainLayout->childItems()[size2-1+1]; //we need to take into account first parabolic spacer 1396 splitterItem2->stackAfter(currentitem2); 1397 } 1398 } 1399 1400 void LayoutManager::destroyJustifySplitters() 1401 { 1402 if (!m_startLayout || !m_mainLayout || !m_endLayout) { 1403 return; 1404 } 1405 1406 for (int i=0; i<=2; ++i) { 1407 QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout)); 1408 1409 if (layout->childItems().count() > 0) { 1410 int size = layout->childItems().count(); 1411 for (int j=size-1; j>=0; --j) { 1412 QQuickItem *item = layout->childItems()[j]; 1413 bool issplitter = item->property("isInternalViewSplitter").toBool(); 1414 if (issplitter) { 1415 item->deleteLater(); 1416 } 1417 } 1418 } 1419 } 1420 } 1421 1422 void LayoutManager::joinLayoutsToMainLayout() 1423 { 1424 if (!m_startLayout || !m_mainLayout || !m_endLayout) { 1425 return; 1426 } 1427 1428 if (m_startLayout->childItems().count() > 0) { 1429 int size = m_startLayout->childItems().count(); 1430 for (int i=size-1; i>=0; --i) { 1431 QQuickItem *lastStartLayoutItem = m_startLayout->childItems()[i]; 1432 QQuickItem *firstMainLayoutItem = m_mainLayout->childItems().count() > 0 ? m_mainLayout->childItems()[0] : nullptr; 1433 1434 lastStartLayoutItem->setParentItem(m_mainLayout); 1435 1436 if (firstMainLayoutItem) { 1437 lastStartLayoutItem->stackBefore(firstMainLayoutItem); 1438 } 1439 } 1440 } 1441 1442 if (m_endLayout->childItems().count() > 0) { 1443 int size = m_endLayout->childItems().count(); 1444 for (int i=0; i<size; ++i) { 1445 QQuickItem *firstEndLayoutItem = m_endLayout->childItems()[0]; 1446 QQuickItem *lastMainLayoutItem = m_mainLayout->childItems().count() > 0 ? m_mainLayout->childItems()[m_mainLayout->childItems().count()-1] : nullptr; 1447 1448 firstEndLayoutItem->setParentItem(m_mainLayout); 1449 1450 if (lastMainLayoutItem) { 1451 firstEndLayoutItem->stackAfter(lastMainLayoutItem); 1452 } 1453 } 1454 } 1455 1456 destroyJustifySplitters(); 1457 } 1458 1459 void LayoutManager::moveAppletsBasedOnJustifyAlignment() 1460 { 1461 if (!m_startLayout || !m_mainLayout || !m_endLayout) { 1462 return; 1463 } 1464 1465 reorderParabolicSpacers(); 1466 1467 QList<QQuickItem *> appletlist; 1468 1469 appletlist << m_startLayout->childItems(); 1470 appletlist << m_mainLayout->childItems(); 1471 appletlist << m_endLayout->childItems(); 1472 1473 bool firstSplitterFound{false}; 1474 bool secondSplitterFound{false}; 1475 int splitter1{-1}; 1476 int splitter2{-1}; 1477 1478 for(int i=0; i<appletlist.count(); ++i) { 1479 bool issplitter = appletlist[i]->property("isInternalViewSplitter").toBool(); 1480 bool isparabolicspacer = appletlist[i]->property("isParabolicEdgeSpacer").toBool(); 1481 1482 if (!firstSplitterFound) { 1483 insertAtLayoutIndex(m_startLayout, appletlist[i], i); 1484 if (issplitter) { 1485 firstSplitterFound = true; 1486 splitter1 = i; 1487 } 1488 } else if (firstSplitterFound && !secondSplitterFound) { 1489 if (issplitter) { 1490 secondSplitterFound = true; 1491 splitter2 = i; 1492 insertAtLayoutTail(m_endLayout, appletlist[i]); 1493 } else { 1494 insertAtLayoutIndex(m_mainLayout, appletlist[i], i-splitter1); 1495 } 1496 } else if (firstSplitterFound && secondSplitterFound) { 1497 insertAtLayoutIndex(m_endLayout, appletlist[i], i-splitter2); 1498 } 1499 } 1500 1501 reorderParabolicSpacers(); 1502 } 1503 1504 void LayoutManager::printAppletList(QList<QQuickItem *> list) 1505 { 1506 for(int i=0; i<list.count(); ++i) { 1507 bool issplitter = list[i]->property("isInternalViewSplitter").toBool(); 1508 bool isparabolicspacer = list[i]->property("isParabolicEdgeSpacer").toBool(); 1509 1510 if (issplitter) { 1511 qDebug() << i << " __ JUSTIFY SPLITTER"; 1512 continue; 1513 } 1514 1515 if (isparabolicspacer) { 1516 qDebug() << i << " __ PARABOLICSPACER"; 1517 continue; 1518 } 1519 1520 QVariant appletVariant = list[i]->property("applet"); 1521 if (!appletVariant.isValid()) { 1522 continue; 1523 } 1524 PlasmaQuick::AppletQuickItem *appletitem = appletVariant.value<PlasmaQuick::AppletQuickItem *>(); 1525 1526 if (appletitem) { 1527 qDebug() << i << " __ " << appletitem->applet()->pluginMetaData().pluginId(); 1528 } 1529 } 1530 } 1531 1532 QList<int> LayoutManager::toIntList(const QString &serialized) 1533 { 1534 QList<int> list; 1535 QStringList items = serialized.split(";"); 1536 items.removeAll(QString()); 1537 1538 for(const auto &item: items) { 1539 list << item.toInt(); 1540 } 1541 1542 return list; 1543 } 1544 1545 QString LayoutManager::toStr(const QList<int> &list) 1546 { 1547 QString str; 1548 QStringList strlist; 1549 1550 for(const auto &num: list) { 1551 strlist << QString::number(num); 1552 } 1553 1554 return strlist.join(";"); 1555 } 1556 1557 } 1558 }