File indexing completed on 2024-06-23 05:48:59
0001 /* 0002 This file is part of the Okteta Kasten Framework, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2009, 2010, 2011, 2012 Alex Richardson <alex.richardson@gmx.de> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "datainformationwithchildren.hpp" 0010 0011 #include "topleveldatainformation.hpp" 0012 #include "../parsers/scriptvalueconverter.hpp" 0013 #include "../script/scripthandlerinfo.hpp" 0014 #include "../script/classes/structunionscriptclass.hpp" 0015 #include "../script/scriptlogger.hpp" 0016 // KF 0017 #include <KLocalizedString> 0018 // Qt 0019 #include <QLineEdit> 0020 // Std 0021 #include <utility> 0022 0023 DataInformationWithChildren::DataInformationWithChildren(const QString& name, 0024 const QVector<DataInformation*>& children, DataInformation* parent) 0025 : DataInformation(name, parent) 0026 , mChildren(children) 0027 { 0028 for (auto* child : std::as_const(mChildren)) { 0029 child->setParent(this); 0030 } 0031 } 0032 0033 DataInformationWithChildren::DataInformationWithChildren(const DataInformationWithChildren& d) 0034 : DataInformation(d) 0035 , mChildren(cloneList(d.mChildren, this)) 0036 { 0037 } 0038 0039 DataInformationWithChildren::~DataInformationWithChildren() 0040 { 0041 qDeleteAll(mChildren); 0042 } 0043 0044 DataInformation* DataInformationWithChildren::childAt(unsigned int index) const 0045 { 0046 if (index >= (unsigned) mChildren.size()) { 0047 return nullptr; 0048 } 0049 return mChildren[index]; 0050 } 0051 0052 bool DataInformationWithChildren::setData(const QVariant&, Okteta::AbstractByteArrayModel*, 0053 Okteta::Address, BitCount64, quint8) 0054 { 0055 Q_ASSERT_X(false, "DataInformationWithChildren::setData()", "this should never be called"); 0056 return false; 0057 } 0058 0059 QWidget* DataInformationWithChildren::createEditWidget(QWidget* parent) const 0060 { 0061 Q_ASSERT(false); 0062 auto* editWidget = new QLineEdit(parent); 0063 editWidget->setClearButtonEnabled(true); 0064 return editWidget; 0065 } 0066 0067 QVariant DataInformationWithChildren::dataFromWidget(const QWidget* w) const 0068 { 0069 Q_UNUSED(w); 0070 Q_ASSERT(false); 0071 return {}; 0072 } 0073 0074 void DataInformationWithChildren::setWidgetData(QWidget* w) const 0075 { 0076 Q_ASSERT(false); 0077 Q_UNUSED(w) 0078 } 0079 0080 BitCount32 DataInformationWithChildren::size() const 0081 { 0082 BitCount32 size = 0; 0083 for (unsigned int i = 0; i < childCount(); ++i) { 0084 size += childAt(i)->size(); 0085 } 0086 0087 return size; 0088 } 0089 0090 void DataInformationWithChildren::resetValidationState() 0091 { 0092 DataInformation::resetValidationState(); 0093 for (auto* child : std::as_const(mChildren)) { 0094 child->resetValidationState(); 0095 } 0096 } 0097 0098 void DataInformationWithChildren::calculateValidationState() 0099 { 0100 if (childCount() > 0) { 0101 bool hasValidatedChildren = false; 0102 bool allChildrenValid = true; 0103 for (uint i = 0; i < childCount(); ++i) { 0104 DataInformation* child = childAt(i); 0105 DataInformationWithChildren* childWithChildren = child->asDataInformationWithChildren(); 0106 if (childWithChildren) { 0107 childWithChildren->calculateValidationState(); 0108 } 0109 // first make sure the child item validation state has been set 0110 if (child->hasBeenValidated()) { 0111 hasValidatedChildren = true; 0112 if (!child->validationSuccessful()) { 0113 allChildrenValid = false; 0114 break; // one is invalid -> whole structure is invalid 0115 } 0116 } 0117 } 0118 0119 if (hasValidatedChildren) { 0120 mValidationSuccessful = allChildrenValid; 0121 } 0122 } 0123 } 0124 0125 void DataInformationWithChildren::setChildren(const QVector<DataInformation*>& newChildren) 0126 { 0127 // since we are replacing the children and the first few may be different emit 0128 // change to length zero and then to new length so that model gets updated correctly 0129 uint numChildren = childCount(); 0130 topLevelDataInformation()->_childCountAboutToChange(this, numChildren, 0); 0131 qDeleteAll(mChildren); 0132 mChildren.clear(); 0133 topLevelDataInformation()->_childCountChanged(this, numChildren, 0); 0134 0135 const uint count = newChildren.size(); 0136 topLevelDataInformation()->_childCountAboutToChange(this, 0, count); 0137 mChildren = newChildren; 0138 for (auto* child : std::as_const(mChildren)) { 0139 child->setParent(this); 0140 } 0141 0142 topLevelDataInformation()->_childCountChanged(this, 0, count); 0143 } 0144 0145 void DataInformationWithChildren::setChildren(const QScriptValue& children) 0146 { 0147 if (children.isNull() || children.isUndefined()) { 0148 logError() << "attempting to set children to null/undefined."; 0149 return; 0150 } 0151 QVector<DataInformation*> convertedVals = 0152 ScriptValueConverter::convertValues(children, topLevelDataInformation()->logger()); 0153 setChildren(convertedVals); 0154 } 0155 0156 int DataInformationWithChildren::indexOf(const DataInformation* const data) const 0157 { 0158 const int size = mChildren.size(); 0159 for (int i = 0; i < size; ++i) { 0160 if (mChildren.at(i) == data) { 0161 return i; 0162 } 0163 } 0164 0165 Q_ASSERT(false); // should never reach this 0166 return -1; 0167 } 0168 0169 QVariant DataInformationWithChildren::childData(int row, int column, int role) const 0170 { 0171 Q_ASSERT(row >= 0 && row < mChildren.size()); 0172 // just delegate to child 0173 return mChildren.at(row)->data(column, role); 0174 } 0175 0176 void DataInformationWithChildren::appendChild(DataInformation* newChild, bool emitSignal) 0177 { 0178 if (emitSignal) { 0179 topLevelDataInformation()->_childCountAboutToChange(this, mChildren.size(), mChildren.size() + 1); 0180 } 0181 newChild->setParent(this); 0182 mChildren.append(newChild); 0183 if (emitSignal) { 0184 topLevelDataInformation()->_childCountChanged(this, mChildren.size(), mChildren.size() + 1); 0185 } 0186 } 0187 0188 void DataInformationWithChildren::appendChildren(const QVector<DataInformation*>& newChildren, bool emitSignal) 0189 { 0190 if (newChildren.isEmpty()) { 0191 return; 0192 } 0193 const int added = newChildren.size(); 0194 if (emitSignal) { 0195 topLevelDataInformation()->_childCountAboutToChange(this, mChildren.size(), mChildren.size() + added); 0196 } 0197 for (auto* child : newChildren) { 0198 child->setParent(this); 0199 } 0200 0201 mChildren << newChildren; 0202 if (emitSignal) { 0203 topLevelDataInformation()->_childCountChanged(this, mChildren.size(), mChildren.size() + added); 0204 } 0205 } 0206 0207 bool DataInformationWithChildren::replaceChildAt(unsigned int index, DataInformation* newChild) 0208 { 0209 Q_ASSERT(index < uint(mChildren.size())); 0210 Q_CHECK_PTR(newChild); 0211 if (index >= uint(mChildren.size())) { 0212 return false; 0213 } 0214 0215 delete mChildren.at(index); 0216 mChildren[index] = newChild; 0217 return true; 0218 } 0219 0220 QScriptClass* DataInformationWithChildren::scriptClass(ScriptHandlerInfo* handlerInfo) const 0221 { 0222 return handlerInfo->mStructUnionClass.get(); 0223 } 0224 0225 QString DataInformationWithChildren::tooltipString() const 0226 { 0227 QString valueStr = mWasAbleToRead ? valueString() : eofReachedData(Qt::DisplayRole).toString(); 0228 QString validationMsg; 0229 if (mHasBeenValidated && !mValidationSuccessful) { 0230 validationMsg = validationError(); 0231 if (validationMsg.isEmpty()) { 0232 validationMsg = i18nc("not all values in this structure" 0233 " are as they should be", "Validation failed."); 0234 } else { 0235 validationMsg = i18nc("not all values in this structure" 0236 " are as they should be", "Validation failed: \"%1\"", validationMsg); 0237 } 0238 } 0239 0240 return DataInformation::tooltipString(name(), valueStr, typeName(), sizeString(), childCount(), 0241 validationMsg); 0242 } 0243 0244 QVector<DataInformation*> DataInformationWithChildren::cloneList(const QVector<DataInformation*>& other, 0245 DataInformation* parent) 0246 { 0247 int count = other.size(); 0248 QVector<DataInformation*> ret; 0249 ret.reserve(count); 0250 for (int i = 0; i < count; ++i) { 0251 DataInformation* dat = other.at(i); 0252 DataInformation* newChild = dat->clone(); 0253 newChild->setParent(parent); 0254 ret.append(newChild); 0255 } 0256 0257 return ret; 0258 } 0259 0260 unsigned int DataInformationWithChildren::childCount() const 0261 { 0262 return mChildren.size(); 0263 } 0264 0265 bool DataInformationWithChildren::isDataInformationWithChildren() const 0266 { 0267 return true; 0268 }