Warning, file /utilities/okteta/kasten/gui/system/bytearrayviewprofilemanager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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