File indexing completed on 2024-04-21 16:17:08
0001 /* 0002 * Copyright 2019 Michail Vourlakos <mvourlakos@gmail.com> 0003 * 0004 * This file is part of Latte-Dock 0005 * 0006 * Latte-Dock is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU General Public License as 0008 * published by the Free Software Foundation; either version 2 of 0009 * the License, or (at your option) any later version. 0010 * 0011 * Latte-Dock is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "storage.h" 0021 0022 // local 0023 #include "../lattecorona.h" 0024 #include "../screenpool.h" 0025 #include "../layouts/manager.h" 0026 #include "../layouts/importer.h" 0027 #include "../view/view.h" 0028 // Qt 0029 #include <QDir> 0030 #include <QFile> 0031 #include <QFileInfo> 0032 0033 // KDE 0034 #include <KConfigGroup> 0035 #include <KSharedConfig> 0036 0037 // Plasma 0038 #include <Plasma> 0039 #include <Plasma/Applet> 0040 #include <Plasma/Containment> 0041 0042 namespace Latte { 0043 namespace Layout { 0044 0045 Storage::Storage(GenericLayout *parent) 0046 : QObject(parent), 0047 m_layout(parent) 0048 { 0049 } 0050 0051 Storage::~Storage() 0052 { 0053 } 0054 0055 bool Storage::isWritable() const 0056 { 0057 QFileInfo layoutFileInfo(m_layout->file()); 0058 0059 if (layoutFileInfo.exists() && !layoutFileInfo.isWritable()) { 0060 return false; 0061 } else { 0062 return true; 0063 } 0064 } 0065 0066 bool Storage::isLatteContainment(Plasma::Containment *containment) const 0067 { 0068 if (!containment) { 0069 return false; 0070 } 0071 0072 if (containment->pluginMetaData().pluginId() == "org.kde.latte.containment") { 0073 return true; 0074 } 0075 0076 return false; 0077 } 0078 0079 bool Storage::isLatteContainment(const KConfigGroup &group) const 0080 { 0081 QString pluginId = group.readEntry("plugin", ""); 0082 return pluginId == "org.kde.latte.containment"; 0083 } 0084 0085 void Storage::lock() 0086 { 0087 QFileInfo layoutFileInfo(m_layout->file()); 0088 0089 if (layoutFileInfo.exists() && layoutFileInfo.isWritable()) { 0090 QFile(m_layout->file()).setPermissions(QFileDevice::ReadUser | QFileDevice::ReadGroup | QFileDevice::ReadOther); 0091 } 0092 } 0093 0094 void Storage::unlock() 0095 { 0096 QFileInfo layoutFileInfo(m_layout->file()); 0097 0098 if (layoutFileInfo.exists() && !layoutFileInfo.isWritable()) { 0099 QFile(m_layout->file()).setPermissions(QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ReadGroup | QFileDevice::ReadOther); 0100 } 0101 } 0102 0103 void Storage::importToCorona() 0104 { 0105 if (!m_layout->corona()) { 0106 return; 0107 } 0108 0109 //! Setting mutable for create a containment 0110 m_layout->corona()->setImmutability(Plasma::Types::Mutable); 0111 0112 QString temp1FilePath = QDir::homePath() + "/.config/lattedock.copy1.bak"; 0113 //! we need to copy first the layout file because the kde cache 0114 //! may not have yet been updated (KSharedConfigPtr) 0115 //! this way we make sure at the latest changes stored in the layout file 0116 //! will be also available when changing to Multiple Layouts 0117 QString tempLayoutFilePath = QDir::homePath() + "/.config/lattedock.layout.bak"; 0118 0119 //! WE NEED A WAY TO COPY A CONTAINMENT!!!! 0120 QFile tempLayoutFile(tempLayoutFilePath); 0121 QFile copyFile(temp1FilePath); 0122 QFile layoutOriginalFile(m_layout->file()); 0123 0124 if (tempLayoutFile.exists()) { 0125 tempLayoutFile.remove(); 0126 } 0127 0128 if (copyFile.exists()) 0129 copyFile.remove(); 0130 0131 layoutOriginalFile.copy(tempLayoutFilePath); 0132 0133 KSharedConfigPtr filePtr = KSharedConfig::openConfig(tempLayoutFilePath); 0134 KSharedConfigPtr newFile = KSharedConfig::openConfig(temp1FilePath); 0135 KConfigGroup copyGroup = KConfigGroup(newFile, "Containments"); 0136 KConfigGroup current_containments = KConfigGroup(filePtr, "Containments"); 0137 0138 current_containments.copyTo(©Group); 0139 0140 copyGroup.sync(); 0141 0142 //! update ids to unique ones 0143 QString temp2File = newUniqueIdsLayoutFromFile(temp1FilePath); 0144 0145 0146 //! Finally import the configuration 0147 importLayoutFile(temp2File); 0148 } 0149 0150 void Storage::syncToLayoutFile(bool removeLayoutId) 0151 { 0152 if (!m_layout->corona() || !isWritable()) { 0153 return; 0154 } 0155 0156 KSharedConfigPtr filePtr = KSharedConfig::openConfig(m_layout->file()); 0157 0158 KConfigGroup oldContainments = KConfigGroup(filePtr, "Containments"); 0159 oldContainments.deleteGroup(); 0160 oldContainments.sync(); 0161 0162 qDebug() << " LAYOUT :: " << m_layout->name() << " is syncing its original file."; 0163 0164 for (const auto containment : *m_layout->containments()) { 0165 if (removeLayoutId) { 0166 containment->config().writeEntry("layoutId", ""); 0167 } 0168 0169 KConfigGroup newGroup = oldContainments.group(QString::number(containment->id())); 0170 containment->config().copyTo(&newGroup); 0171 0172 if (!removeLayoutId) { 0173 newGroup.writeEntry("layoutId", ""); 0174 newGroup.sync(); 0175 } 0176 } 0177 0178 oldContainments.sync(); 0179 } 0180 0181 void Storage::copyView(Plasma::Containment *containment) 0182 { 0183 if (!containment || !m_layout->corona()) 0184 return; 0185 0186 qDebug() << "copying containment layout"; 0187 //! Setting mutable for create a containment 0188 m_layout->corona()->setImmutability(Plasma::Types::Mutable); 0189 0190 QString temp1File = QDir::homePath() + "/.config/lattedock.copy1.bak"; 0191 0192 //! WE NEED A WAY TO COPY A CONTAINMENT!!!! 0193 QFile copyFile(temp1File); 0194 0195 if (copyFile.exists()) 0196 copyFile.remove(); 0197 0198 KSharedConfigPtr newFile = KSharedConfig::openConfig(temp1File); 0199 KConfigGroup copied_conts = KConfigGroup(newFile, "Containments"); 0200 KConfigGroup copied_c1 = KConfigGroup(&copied_conts, QString::number(containment->id())); 0201 0202 containment->config().copyTo(&copied_c1); 0203 0204 //!investigate if there multiple systray(s) in the containment to copy also 0205 0206 //! systrayId, systrayAppletId 0207 QHash<int, QString> systraysInfo; 0208 auto applets = containment->config().group("Applets"); 0209 0210 for (const auto &applet : applets.groupList()) { 0211 KConfigGroup appletSettings = applets.group(applet).group("Configuration"); 0212 0213 int tSysId = appletSettings.readEntry("SystrayContainmentId", -1); 0214 0215 if (tSysId != -1) { 0216 systraysInfo[tSysId] = applet; 0217 qDebug() << "systray with id "<< tSysId << " was found in the containment... ::: " << tSysId; 0218 } 0219 } 0220 0221 if (systraysInfo.count() > 0) { 0222 for(const auto systrayId : systraysInfo.keys()) { 0223 Plasma::Containment *systray{nullptr}; 0224 0225 for (const auto containment : m_layout->corona()->containments()) { 0226 if (containment->id() == systrayId) { 0227 systray = containment; 0228 break; 0229 } 0230 } 0231 0232 if (systray) { 0233 KConfigGroup copied_systray = KConfigGroup(&copied_conts, QString::number(systray->id())); 0234 systray->config().copyTo(&copied_systray); 0235 } 0236 } 0237 } 0238 //! end of systray specific code 0239 0240 //! update ids to unique ones 0241 QString temp2File = newUniqueIdsLayoutFromFile(temp1File); 0242 0243 0244 //! Don't create LatteView when the containment is created because we must update 0245 //! its screen settings first 0246 m_layout->setBlockAutomaticLatteViewCreation(true); 0247 //! Finally import the configuration 0248 QList<Plasma::Containment *> importedDocks = importLayoutFile(temp2File); 0249 0250 Plasma::Containment *newContainment{nullptr}; 0251 0252 if (importedDocks.size() == 1) { 0253 newContainment = importedDocks[0]; 0254 } 0255 0256 if (!newContainment || !newContainment->kPackage().isValid()) { 0257 qWarning() << "the requested containment plugin can not be located or loaded"; 0258 return; 0259 } 0260 0261 auto config = newContainment->config(); 0262 0263 //in multi-screen environment the copied dock is moved to alternative screens first 0264 const auto screens = qGuiApp->screens(); 0265 auto dock = m_layout->viewForContainment(containment); 0266 0267 bool setOnExplicitScreen = false; 0268 0269 int dockScrId = -1; 0270 int copyScrId = -1; 0271 0272 if (dock) { 0273 dockScrId = dock->positioner()->currentScreenId(); 0274 qDebug() << "COPY DOCK SCREEN ::: " << dockScrId; 0275 0276 if (dockScrId != -1 && screens.count() > 1) { 0277 for (const auto scr : screens) { 0278 copyScrId = m_layout->corona()->screenPool()->id(scr->name()); 0279 0280 //the screen must exist and not be the same with the original dock 0281 if (copyScrId > -1 && copyScrId != dockScrId) { 0282 QList<Plasma::Types::Location> fEdges = m_layout->freeEdges(copyScrId); 0283 0284 if (fEdges.contains((Plasma::Types::Location)containment->location())) { 0285 ///set this containment to an explicit screen 0286 config.writeEntry("onPrimary", false); 0287 config.writeEntry("lastScreen", copyScrId); 0288 newContainment->setLocation(containment->location()); 0289 0290 qDebug() << "COPY DOCK SCREEN NEW SCREEN ::: " << copyScrId; 0291 0292 setOnExplicitScreen = true; 0293 break; 0294 } 0295 } 0296 } 0297 } 0298 } 0299 0300 if (!setOnExplicitScreen) { 0301 QList<Plasma::Types::Location> edges = m_layout->freeEdges(newContainment->screen()); 0302 0303 if (edges.count() > 0) { 0304 newContainment->setLocation(edges.at(0)); 0305 } else { 0306 newContainment->setLocation(Plasma::Types::BottomEdge); 0307 } 0308 0309 config.writeEntry("onPrimary", true); 0310 config.writeEntry("lastScreen", dockScrId); 0311 } 0312 0313 newContainment->config().sync(); 0314 0315 if (setOnExplicitScreen && copyScrId > -1) { 0316 qDebug() << "Copy Dock in explicit screen ::: " << copyScrId; 0317 m_layout->addView(newContainment, false, copyScrId); 0318 newContainment->reactToScreenChange(); 0319 } else { 0320 qDebug() << "Copy Dock in current screen..."; 0321 m_layout->addView(newContainment, false, dockScrId); 0322 } 0323 0324 m_layout->setBlockAutomaticLatteViewCreation(false); 0325 } 0326 0327 QList<Plasma::Containment *> Storage::importLayoutFile(QString file) 0328 { 0329 KSharedConfigPtr filePtr = KSharedConfig::openConfig(file); 0330 auto newContainments = m_layout->corona()->importLayout(KConfigGroup(filePtr, "")); 0331 0332 ///Find latte and systray containments 0333 qDebug() << " imported containments ::: " << newContainments.length(); 0334 0335 QList<Plasma::Containment *> importedDocks; 0336 //QList<Plasma::Containment *> systrays; 0337 0338 for (const auto containment : newContainments) { 0339 if (isLatteContainment(containment)) { 0340 qDebug() << "new latte containment id: " << containment->id(); 0341 importedDocks << containment; 0342 } 0343 } 0344 0345 return importedDocks; 0346 } 0347 0348 void Storage::systraysInformation(QHash<int, QList<int>> &systrays, QList<int> &assignedSystrays, QList<int> &orphanSystrays) 0349 { 0350 systrays.clear(); 0351 assignedSystrays.clear(); 0352 orphanSystrays.clear(); 0353 0354 KSharedConfigPtr lFile = KSharedConfig::openConfig(m_layout->file()); 0355 KConfigGroup containmentGroups = KConfigGroup(lFile, "Containments"); 0356 0357 //! assigned systrays 0358 for (const auto &cId : containmentGroups.groupList()) { 0359 if (isLatteContainment(containmentGroups.group(cId))) { 0360 auto applets = containmentGroups.group(cId).group("Applets"); 0361 0362 for (const auto &applet : applets.groupList()) { 0363 KConfigGroup appletSettings = applets.group(applet).group("Configuration"); 0364 int tSysId = appletSettings.readEntry("SystrayContainmentId", -1); 0365 0366 if (tSysId != -1) { 0367 assignedSystrays << tSysId; 0368 systrays[cId.toInt()].append(tSysId); 0369 } 0370 } 0371 } 0372 } 0373 0374 //! orphan systrays 0375 for (const auto &cId : containmentGroups.groupList()) { 0376 if (!isLatteContainment(containmentGroups.group(cId)) && !assignedSystrays.contains(cId.toInt())) { 0377 orphanSystrays << cId.toInt(); 0378 } 0379 } 0380 } 0381 0382 QList<ViewData> Storage::viewsData(const QHash<int, QList<int>> &systrays) 0383 { 0384 QList<ViewData> viewsData; 0385 0386 KSharedConfigPtr lFile = KSharedConfig::openConfig(m_layout->file()); 0387 KConfigGroup containmentGroups = KConfigGroup(lFile, "Containments"); 0388 0389 for (const auto &cId : containmentGroups.groupList()) { 0390 if (isLatteContainment(containmentGroups.group(cId))) { 0391 ViewData vData; 0392 int id = cId.toInt(); 0393 0394 //! id 0395 vData.id = id; 0396 0397 //! active 0398 vData.active = false; 0399 0400 //! onPrimary 0401 vData.onPrimary = containmentGroups.group(cId).readEntry("onPrimary", true); 0402 0403 //! Screen 0404 vData.screenId = containmentGroups.group(cId).readEntry("lastScreen", -1); 0405 0406 //! location 0407 vData.location = containmentGroups.group(cId).readEntry("location", (int)Plasma::Types::BottomEdge); 0408 0409 //! systrays 0410 vData.systrays = systrays[id]; 0411 0412 viewsData << vData; 0413 } 0414 } 0415 0416 return viewsData; 0417 } 0418 0419 QList<int> Storage::viewsScreens() 0420 { 0421 QList<int> screens; 0422 0423 KSharedConfigPtr lFile = KSharedConfig::openConfig(m_layout->file()); 0424 0425 KConfigGroup containmentGroups = KConfigGroup(lFile, "Containments"); 0426 0427 for (const auto &cId : containmentGroups.groupList()) { 0428 if (isLatteContainment(containmentGroups.group(cId))) { 0429 int screenId = containmentGroups.group(cId).readEntry("lastScreen", -1); 0430 0431 if (screenId != -1 && !screens.contains(screenId)) { 0432 screens << screenId; 0433 } 0434 } 0435 } 0436 0437 return screens; 0438 } 0439 0440 QString Storage::availableId(QStringList all, QStringList assigned, int base) 0441 { 0442 bool found = false; 0443 0444 int i = base; 0445 0446 while (!found && i < 32000) { 0447 QString iStr = QString::number(i); 0448 0449 if (!all.contains(iStr) && !assigned.contains(iStr)) { 0450 return iStr; 0451 } 0452 0453 i++; 0454 } 0455 0456 return QString(""); 0457 } 0458 0459 QString Storage::newUniqueIdsLayoutFromFile(QString file) 0460 { 0461 if (!m_layout->corona()) { 0462 return QString(); 0463 } 0464 0465 QString tempFile = QDir::homePath() + "/.config/lattedock.copy2.bak"; 0466 0467 QFile copyFile(tempFile); 0468 0469 if (copyFile.exists()) { 0470 copyFile.remove(); 0471 } 0472 0473 //! BEGIN updating the ids in the temp file 0474 QStringList allIds; 0475 allIds << m_layout->corona()->containmentsIds(); 0476 allIds << m_layout->corona()->appletsIds(); 0477 0478 QStringList toInvestigateContainmentIds; 0479 QStringList toInvestigateAppletIds; 0480 QStringList toInvestigateSystrayContIds; 0481 0482 //! first is the systray containment id 0483 QHash<QString, QString> systrayParentContainmentIds; 0484 QHash<QString, QString> systrayAppletIds; 0485 0486 //qDebug() << "Ids:" << allIds; 0487 0488 //qDebug() << "to copy containments: " << toCopyContainmentIds; 0489 //qDebug() << "to copy applets: " << toCopyAppletIds; 0490 0491 QStringList assignedIds; 0492 QHash<QString, QString> assigned; 0493 0494 KSharedConfigPtr filePtr = KSharedConfig::openConfig(file); 0495 KConfigGroup investigate_conts = KConfigGroup(filePtr, "Containments"); 0496 0497 //! Record the containment and applet ids 0498 for (const auto &cId : investigate_conts.groupList()) { 0499 toInvestigateContainmentIds << cId; 0500 auto appletsEntries = investigate_conts.group(cId).group("Applets"); 0501 toInvestigateAppletIds << appletsEntries.groupList(); 0502 0503 //! investigate for systrays 0504 for (const auto &appletId : appletsEntries.groupList()) { 0505 KConfigGroup appletSettings = appletsEntries.group(appletId).group("Configuration"); 0506 0507 int tSysId = appletSettings.readEntry("SystrayContainmentId", -1); 0508 0509 //! It is a systray !!! 0510 if (tSysId != -1) { 0511 QString tSysIdStr = QString::number(tSysId); 0512 toInvestigateSystrayContIds << tSysIdStr; 0513 systrayParentContainmentIds[tSysIdStr] = cId; 0514 systrayAppletIds[tSysIdStr] = appletId; 0515 qDebug() << "systray was found in the containment..."; 0516 } 0517 } 0518 } 0519 0520 //! Reassign containment and applet ids to unique ones 0521 for (const auto &contId : toInvestigateContainmentIds) { 0522 QString newId = availableId(allIds, assignedIds, 12); 0523 0524 assignedIds << newId; 0525 assigned[contId] = newId; 0526 } 0527 0528 for (const auto &appId : toInvestigateAppletIds) { 0529 QString newId = availableId(allIds, assignedIds, 40); 0530 0531 assignedIds << newId; 0532 assigned[appId] = newId; 0533 } 0534 0535 qDebug() << "ALL CORONA IDS ::: " << allIds; 0536 qDebug() << "FULL ASSIGNMENTS ::: " << assigned; 0537 0538 for (const auto &cId : toInvestigateContainmentIds) { 0539 QString value = assigned[cId]; 0540 0541 if (assigned.contains(value)) { 0542 QString value2 = assigned[value]; 0543 0544 if (cId != assigned[cId] && !value2.isEmpty() && cId == value2) { 0545 qDebug() << "PROBLEM APPEARED !!!! FOR :::: " << cId << " .. fixed .."; 0546 assigned[cId] = cId; 0547 assigned[value] = value; 0548 } 0549 } 0550 } 0551 0552 for (const auto &aId : toInvestigateAppletIds) { 0553 QString value = assigned[aId]; 0554 0555 if (assigned.contains(value)) { 0556 QString value2 = assigned[value]; 0557 0558 if (aId != assigned[aId] && !value2.isEmpty() && aId == value2) { 0559 qDebug() << "PROBLEM APPEARED !!!! FOR :::: " << aId << " .. fixed .."; 0560 assigned[aId] = aId; 0561 assigned[value] = value; 0562 } 0563 } 0564 } 0565 0566 qDebug() << "FIXED FULL ASSIGNMENTS ::: " << assigned; 0567 0568 //! update applet ids in their containment order and in MultipleLayouts update also the layoutId 0569 for (const auto &cId : investigate_conts.groupList()) { 0570 //! Update options that contain applet ids 0571 //! (appletOrder) and (lockedZoomApplets) and (userBlocksColorizingApplets) 0572 QStringList options; 0573 options << "appletOrder" << "lockedZoomApplets" << "userBlocksColorizingApplets"; 0574 0575 for (const auto &settingStr : options) { 0576 QString order1 = investigate_conts.group(cId).group("General").readEntry(settingStr, QString()); 0577 0578 if (!order1.isEmpty()) { 0579 QStringList order1Ids = order1.split(";"); 0580 QStringList fixedOrder1Ids; 0581 0582 for (int i = 0; i < order1Ids.count(); ++i) { 0583 fixedOrder1Ids.append(assigned[order1Ids[i]]); 0584 } 0585 0586 QString fixedOrder1 = fixedOrder1Ids.join(";"); 0587 investigate_conts.group(cId).group("General").writeEntry(settingStr, fixedOrder1); 0588 } 0589 } 0590 0591 if (m_layout->corona()->layoutsManager()->memoryUsage() == Types::MultipleLayouts) { 0592 investigate_conts.group(cId).writeEntry("layoutId", m_layout->name()); 0593 } 0594 } 0595 0596 //! must update also the systray id in its applet 0597 for (const auto &systrayId : toInvestigateSystrayContIds) { 0598 KConfigGroup systrayParentContainment = investigate_conts.group(systrayParentContainmentIds[systrayId]); 0599 systrayParentContainment.group("Applets").group(systrayAppletIds[systrayId]).group("Configuration").writeEntry("SystrayContainmentId", assigned[systrayId]); 0600 systrayParentContainment.sync(); 0601 } 0602 0603 investigate_conts.sync(); 0604 0605 //! Copy To Temp 2 File And Update Correctly The Ids 0606 KSharedConfigPtr file2Ptr = KSharedConfig::openConfig(tempFile); 0607 KConfigGroup fixedNewContainmets = KConfigGroup(file2Ptr, "Containments"); 0608 0609 for (const auto &contId : investigate_conts.groupList()) { 0610 QString pluginId = investigate_conts.group(contId).readEntry("plugin", ""); 0611 0612 if (pluginId != "org.kde.desktopcontainment") { //!don't add ghost containments 0613 KConfigGroup newContainmentGroup = fixedNewContainmets.group(assigned[contId]); 0614 investigate_conts.group(contId).copyTo(&newContainmentGroup); 0615 0616 newContainmentGroup.group("Applets").deleteGroup(); 0617 0618 for (const auto &appId : investigate_conts.group(contId).group("Applets").groupList()) { 0619 KConfigGroup appletGroup = investigate_conts.group(contId).group("Applets").group(appId); 0620 KConfigGroup newAppletGroup = fixedNewContainmets.group(assigned[contId]).group("Applets").group(assigned[appId]); 0621 appletGroup.copyTo(&newAppletGroup); 0622 } 0623 } 0624 } 0625 0626 fixedNewContainmets.sync(); 0627 0628 return tempFile; 0629 } 0630 0631 bool Storage::appletGroupIsValid(KConfigGroup appletGroup) 0632 { 0633 return !( appletGroup.keyList().count() == 0 0634 && appletGroup.groupList().count() == 1 0635 && appletGroup.groupList().at(0) == "Configuration" 0636 && appletGroup.group("Configuration").keyList().count() == 1 0637 && appletGroup.group("Configuration").hasKey("PreloadWeight") ); 0638 } 0639 0640 bool Storage::layoutIsBroken(QStringList &errors) const 0641 { 0642 if (m_layout->file().isEmpty() || !QFile(m_layout->file()).exists()) { 0643 return false; 0644 } 0645 0646 QStringList ids; 0647 QStringList conts; 0648 QStringList applets; 0649 0650 KSharedConfigPtr lFile = KSharedConfig::openConfig(m_layout->file()); 0651 0652 if (!m_layout->corona()) { 0653 KConfigGroup containmentsEntries = KConfigGroup(lFile, "Containments"); 0654 ids << containmentsEntries.groupList(); 0655 conts << ids; 0656 0657 for (const auto &cId : containmentsEntries.groupList()) { 0658 auto appletsEntries = containmentsEntries.group(cId).group("Applets"); 0659 0660 QStringList validAppletIds; 0661 bool updated{false}; 0662 0663 for (const auto &appletId : appletsEntries.groupList()) { 0664 KConfigGroup appletGroup = appletsEntries.group(appletId); 0665 0666 if (appletGroupIsValid(appletGroup)) { 0667 validAppletIds << appletId; 0668 } else { 0669 updated = true; 0670 //! heal layout file by removing applet config records that are not used any more 0671 qDebug() << "Layout: " << m_layout->name() << " removing deprecated applet : " << appletId; 0672 appletsEntries.deleteGroup(appletId); 0673 } 0674 } 0675 0676 if (updated) { 0677 appletsEntries.sync(); 0678 } 0679 0680 ids << validAppletIds; 0681 applets << validAppletIds; 0682 } 0683 } else { 0684 for (const auto containment : *m_layout->containments()) { 0685 ids << QString::number(containment->id()); 0686 conts << QString::number(containment->id()); 0687 0688 for (const auto applet : containment->applets()) { 0689 ids << QString::number(applet->id()); 0690 applets << QString::number(applet->id()); 0691 } 0692 } 0693 } 0694 0695 QSet<QString> idsSet = QSet<QString>::fromList(ids); 0696 0697 /* a different way to count duplicates 0698 QMap<QString, int> countOfStrings; 0699 0700 for (int i = 0; i < ids.count(); i++) { 0701 countOfStrings[ids[i]]++; 0702 }*/ 0703 0704 if (idsSet.count() != ids.count()) { 0705 qDebug() << " ---- ERROR - BROKEN LAYOUT :: " << m_layout->name() << " ----"; 0706 0707 if (!m_layout->corona()) { 0708 qDebug() << " --- storaged file : " << m_layout->file(); 0709 } else { 0710 if (m_layout->corona()->layoutsManager()->memoryUsage() == Types::MultipleLayouts) { 0711 qDebug() << " --- in multiple layouts hidden file : " << Layouts::Importer::layoutFilePath(AbstractLayout::MultipleLayoutsName); 0712 } else { 0713 qDebug() << " --- in active layout file : " << m_layout->file(); 0714 } 0715 } 0716 0717 qDebug() << "Containments :: " << conts; 0718 qDebug() << "Applets :: " << applets; 0719 0720 for (const QString &c : conts) { 0721 if (applets.contains(c)) { 0722 QString errorStr = i18n("Same applet and containment id found ::: ") + c; 0723 qDebug() << "Error: " << errorStr; 0724 errors << errorStr; 0725 } 0726 } 0727 0728 for (int i = 0; i < ids.count(); ++i) { 0729 for (int j = i + 1; j < ids.count(); ++j) { 0730 if (ids[i] == ids[j]) { 0731 QString errorStr = i18n("Different applets with same id ::: ") + ids[i]; 0732 qDebug() << "Error: " << errorStr; 0733 errors << errorStr; 0734 } 0735 } 0736 } 0737 0738 qDebug() << " -- - -- - -- - -- - - -- - - - - -- - - - - "; 0739 0740 if (!m_layout->corona()) { 0741 KConfigGroup containmentsEntries = KConfigGroup(lFile, "Containments"); 0742 0743 for (const auto &cId : containmentsEntries.groupList()) { 0744 auto appletsEntries = containmentsEntries.group(cId).group("Applets"); 0745 0746 qDebug() << " CONTAINMENT : " << cId << " APPLETS : " << appletsEntries.groupList(); 0747 } 0748 } else { 0749 for (const auto containment : *m_layout->containments()) { 0750 QStringList appletsIds; 0751 0752 for (const auto applet : containment->applets()) { 0753 appletsIds << QString::number(applet->id()); 0754 } 0755 0756 qDebug() << " CONTAINMENT : " << containment->id() << " APPLETS : " << appletsIds.join(","); 0757 } 0758 } 0759 0760 return true; 0761 } 0762 0763 return false; 0764 } 0765 0766 0767 } 0768 }