File indexing completed on 2025-09-14 05:48:34
0001 /* 0002 This file is part of the Okteta Kasten module, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2010, 2012 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "bytearrayviewprofilemanager.hpp" 0010 0011 // library 0012 #include "bytearrayviewprofilelock.hpp" 0013 #include <logging.hpp> 0014 // KF 0015 #include <KConfigGroup> 0016 #include <KConfig> 0017 #include <KDirWatch> 0018 // Qt 0019 #include <QFileInfo> 0020 #include <QDir> 0021 #include <QUuid> 0022 // Std 0023 #include <utility> 0024 0025 namespace Kasten { 0026 QStringList viewProfileFileNameFilter() { return QStringList { QStringLiteral("*.obavp"), QStringLiteral("*.olock") }; } 0027 inline QLatin1String viewProfileFileSuffix() { return QLatin1String(".obavp"); } 0028 inline QLatin1String viewProfileDirSubPath() { return QLatin1String("/okteta/viewprofiles"); } 0029 inline QLatin1String defaultViewProfileFileSubPath() { return QLatin1String("/okteta/defaultviewprofile"); } 0030 static constexpr int DefaultNoOfBytesPerLine = 16; 0031 static constexpr int DefaultNoOfBytesPerGroup = 4; 0032 static constexpr int DefaultLayoutStyle = 0; 0033 static constexpr int DefaultViewModus = 0; 0034 static constexpr int DefaultVisibleByteArrayCodings = 3; 0035 static constexpr int DefaultOffsetCoding = 0; 0036 static constexpr int DefaultValueCoding = 0; 0037 QString DefaultCharCoding() { return {}; } 0038 0039 static QVector<ByteArrayViewProfile::Id> 0040 lockedViewProfileIds(const ByteArrayViewProfileFileInfoLookup& viewProfileFileInfoLookup) 0041 { 0042 QVector<ByteArrayViewProfile::Id> result; 0043 0044 ByteArrayViewProfileFileInfoLookup::ConstIterator end = 0045 viewProfileFileInfoLookup.constEnd(); 0046 for (ByteArrayViewProfileFileInfoLookup::ConstIterator it = 0047 viewProfileFileInfoLookup.constBegin(); 0048 it != end; 0049 ++it) { 0050 if (it.value().isLocked()) { 0051 result.append(it.key()); 0052 } 0053 } 0054 0055 return result; 0056 } 0057 0058 static void 0059 updateLockStatus(ByteArrayViewProfileFileInfoLookup& viewProfileFileInfoLookup, 0060 const QVector<ByteArrayViewProfile::Id>& lockedViewProfileIds, 0061 const QVector<ByteArrayViewProfile::Id>& unlockedViewProfileIds) 0062 { 0063 if (lockedViewProfileIds.isEmpty() && unlockedViewProfileIds.isEmpty()) { 0064 return; 0065 } 0066 0067 ByteArrayViewProfileFileInfoLookup::Iterator end = 0068 viewProfileFileInfoLookup.end(); 0069 for (ByteArrayViewProfileFileInfoLookup::Iterator it = viewProfileFileInfoLookup.begin(); 0070 it != end; 0071 ++it) { 0072 bool isLocked; 0073 0074 if (lockedViewProfileIds.contains(it.key())) { 0075 isLocked = true; 0076 } else if (unlockedViewProfileIds.contains(it.key())) { 0077 isLocked = false; 0078 } else { 0079 continue; 0080 } 0081 0082 it.value().setLocked(isLocked); 0083 } 0084 } 0085 0086 static QString 0087 defaultViewProfileFilePath() 0088 { 0089 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + defaultViewProfileFileSubPath(); 0090 } 0091 0092 static QString 0093 viewProfileFilePath(const ByteArrayViewProfile::Id& viewProfileId) 0094 { 0095 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) 0096 + viewProfileDirSubPath() + QLatin1Char('/') + viewProfileId + viewProfileFileSuffix(); 0097 } 0098 0099 static QString 0100 viewProfileFileName(const ByteArrayViewProfile::Id& viewProfileId) 0101 { 0102 return viewProfileId + viewProfileFileSuffix(); 0103 } 0104 0105 // TODO: add global lock 0106 // TODO: make calls async 0107 // TODO: only load view profiles on demand 0108 ByteArrayViewProfileManager::ByteArrayViewProfileManager() 0109 { 0110 mViewProfileFileWatcher = new KDirWatch(this); 0111 connect(mViewProfileFileWatcher, &KDirWatch::dirty, 0112 this, &ByteArrayViewProfileManager::onViewProfilesFolderChanged); 0113 0114 // get all folder where viewProfiles could be stored 0115 const QStringList dataFolderPaths = 0116 QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); 0117 0118 for (const QString& dataFolderPath : dataFolderPaths) { 0119 const QString viewProfileFolderPath = dataFolderPath + viewProfileDirSubPath(); 0120 // watch folder for changes 0121 mViewProfileFileWatcher->addDir(viewProfileFolderPath, KDirWatch::WatchDirOnly); 0122 0123 // read current files 0124 onViewProfilesFolderChanged(viewProfileFolderPath); 0125 } 0126 0127 // default view profile 0128 // While there is no proper config syncing offer in the used frameworks, use a 0129 // single file with the id as content as workaround and watch for it changing 0130 auto* defaultViewProfileWatcher = new KDirWatch(this); 0131 connect(defaultViewProfileWatcher, &KDirWatch::created, 0132 this, &ByteArrayViewProfileManager::onDefaultViewProfileChanged); 0133 connect(defaultViewProfileWatcher, &KDirWatch::dirty, 0134 this, &ByteArrayViewProfileManager::onDefaultViewProfileChanged); 0135 const QString _defaultViewProfileFilePath = defaultViewProfileFilePath(); 0136 0137 defaultViewProfileWatcher->addFile(_defaultViewProfileFilePath); 0138 0139 onDefaultViewProfileChanged(_defaultViewProfileFilePath); 0140 0141 // report any problems with existing view profiles? 0142 } 0143 0144 ByteArrayViewProfileManager::~ByteArrayViewProfileManager() = default; 0145 0146 int 0147 ByteArrayViewProfileManager::viewProfilesCount() const 0148 { 0149 return mViewProfiles.size(); 0150 } 0151 0152 QVector<ByteArrayViewProfile> 0153 ByteArrayViewProfileManager::viewProfiles() const 0154 { 0155 return mViewProfiles; 0156 } 0157 0158 ByteArrayViewProfile 0159 ByteArrayViewProfileManager::viewProfile(const ByteArrayViewProfile::Id& viewProfileId) const 0160 { 0161 ByteArrayViewProfile result; 0162 0163 for (const ByteArrayViewProfile& viewProfile : mViewProfiles) { 0164 if (viewProfile.id() == viewProfileId) { 0165 result = viewProfile; 0166 break; 0167 } 0168 } 0169 0170 return result; 0171 } 0172 0173 ByteArrayViewProfile::Id 0174 ByteArrayViewProfileManager::defaultViewProfileId() const 0175 { 0176 return mDefaultViewProfileId; 0177 } 0178 0179 ByteArrayViewProfile 0180 ByteArrayViewProfileManager::defaultViewProfile() const 0181 { 0182 return viewProfile(mDefaultViewProfileId); 0183 } 0184 0185 bool 0186 ByteArrayViewProfileManager::isViewProfileLocked(const ByteArrayViewProfile::Id& viewProfileId) const 0187 { 0188 bool result = false; 0189 0190 // search in all folders for the info 0191 for (const ByteArrayViewProfileFileInfoLookup& viewProfileFileInfoLookup : mViewProfileFileInfoLookupPerFolder) { 0192 ByteArrayViewProfileFileInfoLookup::ConstIterator it = 0193 viewProfileFileInfoLookup.find(viewProfileId); 0194 if (it != viewProfileFileInfoLookup.constEnd()) { 0195 result = it->isLocked(); 0196 break; 0197 } 0198 } 0199 0200 return result; 0201 } 0202 0203 void ByteArrayViewProfileManager::saveViewProfiles(QVector<ByteArrayViewProfile>& viewProfiles) 0204 { 0205 // TODO: do not save if locked by someone else -> needs passing of our lock? or just registering our own and check? 0206 // create and set unique id 0207 std::for_each(viewProfiles.begin(), viewProfiles.end(), [this](ByteArrayViewProfile& viewProfile) { 0208 const ByteArrayViewProfile::Id viewProfileId = viewProfile.id(); 0209 0210 bool needsId = true; 0211 if (!viewProfileId.isEmpty()) { 0212 // already existing? 0213 auto hasViewProfileId = [&viewProfileId] (const ByteArrayViewProfile& existingProfile) { 0214 return (viewProfileId == existingProfile.id()); 0215 }; 0216 if (std::any_of(mViewProfiles.constBegin(), mViewProfiles.constEnd(), hasViewProfileId)) { 0217 needsId = false; 0218 } 0219 } 0220 0221 // set new uuid for non-existing 0222 if (needsId) { 0223 viewProfile.setId(QUuid::createUuid().toString()); 0224 } 0225 0226 saveViewProfile(viewProfile); 0227 }); 0228 } 0229 0230 void 0231 ByteArrayViewProfileManager::removeViewProfiles(const QVector<ByteArrayViewProfile::Id>& viewProfileIds) 0232 { 0233 for (const ByteArrayViewProfile::Id& viewProfileId : viewProfileIds) { 0234 removeViewProfile(viewProfileId); 0235 } 0236 } 0237 0238 void 0239 ByteArrayViewProfileManager::setDefaultViewProfile(const ByteArrayViewProfile::Id& viewProfileId) 0240 { 0241 QFile defaultViewProfileFile(defaultViewProfileFilePath()); 0242 defaultViewProfileFile.open(QIODevice::WriteOnly); 0243 0244 defaultViewProfileFile.write(viewProfileId.toUtf8()); 0245 defaultViewProfileFile.close(); 0246 } 0247 0248 ByteArrayViewProfileLock 0249 ByteArrayViewProfileManager::createLock(const ByteArrayViewProfile::Id& viewProfileId) 0250 { 0251 const QString viewProfileFilePath = filePathOfViewProfile(viewProfileId); 0252 0253 return ByteArrayViewProfileLock(viewProfileFilePath, viewProfileId); 0254 } 0255 0256 /* 0257 bool 0258 ByteArrayViewProfileManager::lockViewProfile( const Kasten::ByteArrayViewProfile::Id& viewProfileId ) 0259 { 0260 bool isSuccessfull; 0261 0262 const QString viewProfileFilePath = filePathOfViewProfile( viewProfileId ); 0263 0264 // viewProfile known 0265 if( not viewProfileFilePath.isEmpty() ) 0266 { 0267 const QString lockFilePath = viewProfileFileLockPath( viewProfileFilePath ); 0268 KLockFile::Ptr lock = new KLockFile( lockFilePath ); 0269 const KLockFile::LockResult lockResult = 0270 lock->lock(KLockFile::NoBlockFlag | KLockFile::ForceFlag); 0271 isSuccessfull = (lockResult == KLockFile::LockOK ); 0272 } 0273 // if found 0274 // try to create lock file 0275 return isSuccessfull; 0276 } 0277 */ 0278 // bool 0279 // ByteArrayViewProfileManager::unlockViewProfile( const Kasten::ByteArrayViewProfile::Id& viewProfileId ) 0280 // { 0281 // const QString filePath = filePathOfViewProfile( viewProfileId ); 0282 // 0283 // if( filePath.isEmpty() ) 0284 // return false; 0285 // } 0286 0287 ByteArrayViewProfile 0288 ByteArrayViewProfileManager::loadViewProfile(const QString& absoluteFilePath) const 0289 { 0290 ByteArrayViewProfile result; 0291 0292 KConfig configFile(absoluteFilePath, KConfig::SimpleConfig); 0293 0294 // check version 0295 KConfigGroup formatConfigGroup = configFile.group("OBAVP"); 0296 const QString formatVersion = formatConfigGroup.readEntry("Version"); 0297 if (!formatVersion.startsWith(QLatin1String("1."))) { 0298 return result; 0299 } 0300 0301 result.setId(QFileInfo(absoluteFilePath).baseName()); 0302 0303 KConfigGroup generalConfigGroup = configFile.group("General"); 0304 result.setViewProfileTitle(generalConfigGroup.readEntry("Title")); 0305 0306 KConfigGroup layoutConfigGroup = configFile.group("Layout"); 0307 result.setNoOfBytesPerLine(layoutConfigGroup.readEntry("NoOfBytesPerLine", DefaultNoOfBytesPerLine)); 0308 result.setNoOfGroupedBytes(layoutConfigGroup.readEntry("NoOfBytesPerGroup", DefaultNoOfBytesPerGroup)); 0309 result.setLayoutStyle(layoutConfigGroup.readEntry("LayoutStyle", DefaultLayoutStyle)); 0310 0311 KConfigGroup displayConfigGroup = configFile.group("Display"); 0312 result.setOffsetColumnVisible(displayConfigGroup.readEntry("OffsetColumnVisible", true)); 0313 result.setOffsetCoding(displayConfigGroup.readEntry("OffsetCoding", DefaultOffsetCoding)); 0314 result.setViewModus(displayConfigGroup.readEntry("ViewModus", DefaultViewModus)); 0315 result.setVisibleByteArrayCodings(displayConfigGroup.readEntry("VisibleByteArrayCodings", DefaultVisibleByteArrayCodings)); 0316 0317 KConfigGroup interpretationConfigGroup = configFile.group("Interpretation"); 0318 0319 KConfigGroup valuesConfigGroup = interpretationConfigGroup.group("Values"); 0320 result.setValueCoding(valuesConfigGroup.readEntry("Coding", DefaultValueCoding)); 0321 0322 KConfigGroup charsConfigGroup = interpretationConfigGroup.group("Chars"); 0323 result.setCharCoding(charsConfigGroup.readEntry("Coding", DefaultCharCoding())); 0324 result.setShowsNonprinting(charsConfigGroup.readEntry("NonprintingShown", false)); 0325 result.setSubstituteChar(charsConfigGroup.readEntry("SubstituteChar", ".").at(0)); 0326 result.setUndefinedChar(charsConfigGroup.readEntry("UndefinedChar", "?").at(0)); 0327 0328 return result; 0329 } 0330 0331 void 0332 ByteArrayViewProfileManager::saveViewProfile(const ByteArrayViewProfile& viewProfile) const 0333 { 0334 const QString fileName = viewProfileFilePath(viewProfile.id()); 0335 KConfig configFile(fileName, KConfig::SimpleConfig); 0336 0337 KConfigGroup formatConfigGroup = configFile.group("OBAVP"); 0338 formatConfigGroup.writeEntry("Version", "1.1"); 0339 0340 KConfigGroup generalConfigGroup = configFile.group("General"); 0341 generalConfigGroup.writeEntry("Title", viewProfile.viewProfileTitle()); 0342 0343 KConfigGroup layoutConfigGroup = configFile.group("Layout"); 0344 layoutConfigGroup.writeEntry("NoOfBytesPerLine", viewProfile.noOfBytesPerLine()); 0345 layoutConfigGroup.writeEntry("NoOfBytesPerGroup", viewProfile.noOfGroupedBytes()); 0346 layoutConfigGroup.writeEntry("LayoutStyle", viewProfile.layoutStyle()); 0347 0348 KConfigGroup displayConfigGroup = configFile.group("Display"); 0349 displayConfigGroup.writeEntry("OffsetColumnVisible", viewProfile.offsetColumnVisible()); 0350 displayConfigGroup.writeEntry("OffsetCoding", viewProfile.offsetCoding()); 0351 displayConfigGroup.writeEntry("ViewModus", viewProfile.viewModus()); 0352 displayConfigGroup.writeEntry("VisibleByteArrayCodings", viewProfile.visibleByteArrayCodings()); 0353 0354 KConfigGroup interpretationConfigGroup = configFile.group("Interpretation"); 0355 0356 KConfigGroup valuesConfigGroup = interpretationConfigGroup.group("Values"); 0357 valuesConfigGroup.writeEntry("Coding", viewProfile.valueCoding()); 0358 0359 KConfigGroup charsConfigGroup = interpretationConfigGroup.group("Chars"); 0360 charsConfigGroup.writeEntry("Coding", viewProfile.charCodingName()); 0361 charsConfigGroup.writeEntry("NonprintingShown", viewProfile.showsNonprinting()); 0362 charsConfigGroup.writeEntry("SubstituteChar", QString(viewProfile.substituteChar())); 0363 charsConfigGroup.writeEntry("UndefinedChar", QString(viewProfile.undefinedChar())); 0364 } 0365 0366 void 0367 ByteArrayViewProfileManager::removeViewProfile(const ByteArrayViewProfile::Id& viewProfileId) 0368 { 0369 const QString filePath = filePathOfViewProfile(viewProfileId); 0370 if (!filePath.isEmpty()) { 0371 QFile::remove(filePath); 0372 } 0373 } 0374 0375 QString 0376 ByteArrayViewProfileManager::filePathOfViewProfile(const ByteArrayViewProfile::Id& viewProfileId) const 0377 { 0378 QString result; 0379 0380 for (QHash<QString, ByteArrayViewProfileFileInfoLookup>::ConstIterator foldersIt = 0381 mViewProfileFileInfoLookupPerFolder.constBegin(); 0382 foldersIt != mViewProfileFileInfoLookupPerFolder.constEnd() && result.isEmpty(); 0383 ++foldersIt) { 0384 const ByteArrayViewProfileFileInfoLookup& fileInfoList = foldersIt.value(); 0385 for (ByteArrayViewProfileFileInfoLookup::ConstIterator folderIt = fileInfoList.constBegin(); 0386 folderIt != fileInfoList.constEnd(); 0387 ++folderIt) { 0388 if (folderIt.key() == viewProfileId) { 0389 result = foldersIt.key() + QLatin1Char('/') + viewProfileFileName(viewProfileId); 0390 break; 0391 } 0392 } 0393 } 0394 0395 return result; 0396 } 0397 0398 void 0399 ByteArrayViewProfileManager::onViewProfilesFolderChanged(const QString& viewProfileFolderPath) 0400 { 0401 ByteArrayViewProfileFileInfoLookup& viewProfileFileInfoLookup = 0402 mViewProfileFileInfoLookupPerFolder[viewProfileFolderPath]; 0403 0404 // TODO: reparse for new, removed and changed files 0405 // assume all are removed and unlocked in the beginning 0406 QVector<ByteArrayViewProfile::Id> removedViewProfileIds = viewProfileFileInfoLookup.keys().toVector(); 0407 QVector<ByteArrayViewProfile> newViewProfiles; 0408 QVector<ByteArrayViewProfile> changedViewProfiles; 0409 0410 QVector<ByteArrayViewProfile::Id> newUnlockedViewProfileIds = lockedViewProfileIds(viewProfileFileInfoLookup); 0411 QVector<ByteArrayViewProfile::Id> newLockedViewProfileIds; 0412 // iterate all files in folder 0413 const QFileInfoList viewProfileFileInfoList = 0414 QDir(viewProfileFolderPath).entryInfoList(viewProfileFileNameFilter(), QDir::Files); 0415 0416 for (const QFileInfo& viewProfileFileInfo : viewProfileFileInfoList) { 0417 // a lock file ? 0418 if (viewProfileFileInfo.suffix() == QLatin1String("olock")) { 0419 const ByteArrayViewProfile::Id lockedViewProfileId = viewProfileFileInfo.baseName(); 0420 // if not in old locks, is a new lock 0421 if (!newUnlockedViewProfileIds.removeOne(lockedViewProfileId)) { 0422 newLockedViewProfileIds.append(lockedViewProfileId); 0423 } 0424 continue; 0425 } 0426 0427 // not a viewprofile file ? 0428 if (viewProfileFileInfo.suffix() != QLatin1String("obavp")) { 0429 continue; 0430 } 0431 0432 // all other files assumed to be viewProfile files 0433 const ByteArrayViewProfile::Id viewProfileId = viewProfileFileInfo.baseName(); 0434 // load file 0435 const ByteArrayViewProfile viewProfile = loadViewProfile(viewProfileFileInfo.absoluteFilePath()); 0436 // loading failed? Treat as not existing 0437 if (viewProfile.id().isEmpty()) { 0438 continue; 0439 } 0440 0441 const ByteArrayViewProfileFileInfoLookup::Iterator infoIt = 0442 viewProfileFileInfoLookup.find(viewProfileId); 0443 const bool isKnown = (infoIt != viewProfileFileInfoLookup.end()); 0444 const QDateTime fileInfoLastModified = viewProfileFileInfo.lastModified(); 0445 // is known? 0446 if (isKnown) { 0447 removedViewProfileIds.removeOne(viewProfileId); 0448 0449 // check timestamp 0450 if (fileInfoLastModified == infoIt->lastModified()) { 0451 continue; 0452 } 0453 0454 // update timestamp 0455 infoIt->setLastModified(fileInfoLastModified); 0456 } else { 0457 ByteArrayViewProfileFileInfo info(fileInfoLastModified, false); 0458 viewProfileFileInfoLookup.insert(viewProfileId, info); 0459 } 0460 0461 if (isKnown) { 0462 auto it = std::find_if(mViewProfiles.begin(), mViewProfiles.end(), 0463 [&viewProfileId](const ByteArrayViewProfile& existingProfile) { 0464 return (existingProfile.id() == viewProfileId); 0465 }); 0466 if (it != mViewProfiles.end()) { 0467 *it = viewProfile; 0468 } 0469 } else { 0470 newViewProfiles.append(viewProfile); 0471 } 0472 changedViewProfiles.append(viewProfile); 0473 } 0474 0475 // remove all removed viewprofiles 0476 { 0477 auto isProfileToRemove = [&removedViewProfileIds](const ByteArrayViewProfile& profile) { 0478 return removedViewProfileIds.contains(profile.id()); 0479 }; 0480 mViewProfiles.erase(std::remove_if(mViewProfiles.begin(), mViewProfiles.end(), isProfileToRemove), 0481 mViewProfiles.end()); 0482 } 0483 0484 for (const ByteArrayViewProfile::Id& viewProfileId : std::as_const(removedViewProfileIds)) { 0485 viewProfileFileInfoLookup.remove(viewProfileId); 0486 if (viewProfileId == mDefaultViewProfileId) { 0487 mDefaultViewProfileId.clear(); 0488 } 0489 // TODO: how to select new one? 0490 } 0491 0492 // add new viewprofiles 0493 mViewProfiles.append(newViewProfiles); 0494 // if there was no default viewprofile before, set default to first 0495 const bool isDefaultViewProfileChanged = (mDefaultViewProfileId.isEmpty() && !mViewProfiles.isEmpty()); 0496 if (isDefaultViewProfileChanged) { 0497 mDefaultViewProfileId = mViewProfiles.at(0).id(); 0498 } 0499 0500 // update lock info 0501 updateLockStatus(viewProfileFileInfoLookup, newLockedViewProfileIds, newUnlockedViewProfileIds); 0502 0503 // signal changes 0504 if (!changedViewProfiles.isEmpty()) { 0505 Q_EMIT viewProfilesChanged(changedViewProfiles); 0506 } 0507 if (!removedViewProfileIds.isEmpty()) { 0508 Q_EMIT viewProfilesRemoved(removedViewProfileIds); 0509 } 0510 0511 if (!newUnlockedViewProfileIds.isEmpty()) { 0512 Q_EMIT viewProfilesUnlocked(newUnlockedViewProfileIds); 0513 } 0514 if (!newLockedViewProfileIds.isEmpty()) { 0515 Q_EMIT viewProfilesLocked(newLockedViewProfileIds); 0516 } 0517 if (isDefaultViewProfileChanged) { 0518 Q_EMIT defaultViewProfileChanged(mDefaultViewProfileId); 0519 } 0520 } 0521 0522 void ByteArrayViewProfileManager::onDefaultViewProfileChanged(const QString& path) 0523 { 0524 QFile defaultViewProfileFile(path); 0525 if (!defaultViewProfileFile.open(QIODevice::ReadOnly)) { 0526 qCDebug(LOG_KASTEN_OKTETA_GUI) << "Failed to open view profiles file " << path; 0527 return; 0528 } 0529 0530 const QByteArray fileContent = defaultViewProfileFile.readAll(); 0531 const QString viewProfileId = QString::fromUtf8(fileContent); 0532 defaultViewProfileFile.close(); 0533 0534 // no id set? 0535 if (viewProfileId.isEmpty()) { 0536 return; 0537 } 0538 0539 // no change? 0540 if (mDefaultViewProfileId == viewProfileId) { 0541 return; 0542 } 0543 0544 bool isExisting = false; 0545 for (const ByteArrayViewProfile& viewProfile : std::as_const(mViewProfiles)) { 0546 if (viewProfile.id() == viewProfileId) { 0547 isExisting = true; 0548 break; 0549 } 0550 } 0551 0552 if (isExisting) { 0553 mDefaultViewProfileId = viewProfileId; 0554 Q_EMIT defaultViewProfileChanged(mDefaultViewProfileId); 0555 } 0556 } 0557 0558 } 0559 0560 #include "moc_bytearrayviewprofilemanager.cpp"