File indexing completed on 2025-01-19 05:20:18
0001 /* 0002 This file is part of the Okteta Kasten module, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2009, 2022 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 "bytearraypatterngenerator.hpp" 0010 0011 // KF 0012 #include <KConfigGroup> 0013 #include <KSharedConfig> 0014 #include <KLocalizedString> 0015 // Qt 0016 #include <QMimeData> 0017 #include <QByteArray> 0018 // Std 0019 #include <algorithm> 0020 #include <array> 0021 #include <iterator> 0022 0023 // TODO: deduplicate with kasten/controllers/libconfigentries/ 0024 static constexpr int codingCount = 0025 static_cast<int>(Kasten::ByteArrayPatternGeneratorSettings::_CodingCount); 0026 static const std::array<QString, codingCount> codingConfigValueList = { 0027 QStringLiteral("Hexadecimal"), 0028 QStringLiteral("Decimal"), 0029 QStringLiteral("Octal"), 0030 QStringLiteral("Binary"), 0031 QStringLiteral("Char"), 0032 QStringLiteral("UTF-8"), 0033 }; 0034 0035 0036 template <> 0037 inline Kasten::ByteArrayPatternGeneratorSettings::Coding 0038 KConfigGroup::readEntry(const char *key, 0039 const Kasten::ByteArrayPatternGeneratorSettings::Coding &defaultValue) const 0040 { 0041 const QString entry = readEntry(key, QString()); 0042 0043 auto it = std::find(codingConfigValueList.cbegin(), codingConfigValueList.cend(), entry); 0044 if (it == codingConfigValueList.cend()) { 0045 return defaultValue; 0046 } 0047 0048 const int listIndex = std::distance(codingConfigValueList.cbegin(), it); 0049 return static_cast<Kasten::ByteArrayPatternGeneratorSettings::Coding>(listIndex); 0050 } 0051 0052 template <> 0053 inline void KConfigGroup::writeEntry(const char *key, 0054 const Kasten::ByteArrayPatternGeneratorSettings::Coding &value, 0055 KConfigBase::WriteConfigFlags flags) 0056 { 0057 QString configValue; 0058 if (value == Kasten::ByteArrayPatternGeneratorSettings::InvalidCoding) { 0059 configValue = QStringLiteral("Invalid"); 0060 } else { 0061 const int listIndex = static_cast<int>(value); 0062 configValue = codingConfigValueList[listIndex]; 0063 } 0064 writeEntry(key, configValue, flags); 0065 } 0066 0067 namespace Kasten { 0068 0069 const QByteArray ByteArrayPatternGeneratorSettings::DefaultPattern = QByteArray(1, 0); 0070 0071 0072 ByteArrayPatternGeneratorSettings::ByteArrayPatternGeneratorSettings() = default; 0073 0074 bool ByteArrayPatternGeneratorSettings::operator==(const ByteArrayPatternGeneratorSettings& other) const 0075 { 0076 return (pattern == other.pattern) && (patternCoding == other.patternCoding) && (count == other.count); 0077 } 0078 0079 void ByteArrayPatternGeneratorSettings::loadConfig(const KConfigGroup& configGroup) 0080 { 0081 pattern = configGroup.readEntry(PatternConfigKey, DefaultPattern); 0082 count = configGroup.readEntry(CountConfigKey, DefaultCount); 0083 patternCoding = configGroup.readEntry(PatternCodingConfigKey, DefaultPatternCoding); 0084 } 0085 0086 void ByteArrayPatternGeneratorSettings::saveConfig(KConfigGroup& configGroup) const 0087 { 0088 configGroup.writeEntry(PatternConfigKey, pattern); 0089 configGroup.writeEntry(PatternCodingConfigKey, patternCoding); 0090 configGroup.writeEntry(CountConfigKey, count); 0091 } 0092 0093 // TODO: support insert to selection, cmp. fill in painting program 0094 // there are two kinds of generated datam fixed size (e.g. sequence) and endless size? 0095 // perhaps by option fill selection? or a separate menu entry fill, which only works on selections? 0096 0097 ByteArrayPatternGenerator::ByteArrayPatternGenerator() 0098 : AbstractModelDataGenerator( 0099 i18nc("name of the generated data", "Pattern..."), 0100 QStringLiteral("application/octet-stream"), 0101 DynamicGeneration) 0102 { 0103 const KConfigGroup configGroup(KSharedConfig::openConfig(), ConfigGroupId); 0104 0105 mSettings.loadConfig(configGroup); 0106 } 0107 0108 ByteArrayPatternGenerator::~ByteArrayPatternGenerator() = default; 0109 0110 void ByteArrayPatternGenerator::setSettings(const ByteArrayPatternGeneratorSettings& settings) 0111 { 0112 if (mSettings == settings) { 0113 return; 0114 } 0115 0116 mSettings = settings; 0117 0118 KConfigGroup configGroup(KSharedConfig::openConfig(), ConfigGroupId); 0119 mSettings.saveConfig(configGroup); 0120 // Q_EMIT settingsChanged(); 0121 } 0122 0123 // TODO: optimize and check if pattern is just one byte, so memset can be used 0124 // TODO: see if copying larger chunks with memcpy is faster, so 0125 QMimeData* ByteArrayPatternGenerator::generateData() 0126 { 0127 const int patternSize = mSettings.pattern.size(); 0128 0129 const int insertDataSize = mSettings.count * patternSize; 0130 0131 QByteArray insertData(insertDataSize, '\0'); 0132 0133 char* rawInsertData = insertData.data(); 0134 const char* rawPatternData = mSettings.pattern.constData(); 0135 0136 for (int i = 0; i < insertDataSize; i += patternSize) { 0137 memcpy(&rawInsertData[i], rawPatternData, patternSize); 0138 } 0139 0140 auto* mimeData = new QMimeData; 0141 mimeData->setData(mimeType(), insertData); 0142 0143 // TODO: a method to get the description of the change, e.g. 0144 #if 0 0145 Okteta::ChangesDescribable* changesDescribable = 0146 qobject_cast<Okteta::ChangesDescribable*>(mByteArrayModel); 0147 0148 if (changesDescribable) { 0149 changesDescribable->openGroupedChange(i18n("Pattern inserted.")); 0150 } 0151 mByteArrayView->insert(insertData); 0152 // mByteArrayModel->replace( filteredSection, filterResult ); 0153 if (changesDescribable) { 0154 changesDescribable->closeGroupedChange(); 0155 } 0156 #endif 0157 0158 return mimeData; 0159 } 0160 0161 } 0162 0163 #include "moc_bytearraypatterngenerator.cpp"