| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include <QMetaType> |
| #include <QRegularExpression> |
|
|
|
|
| #include <App/Application.h> |
| #include <Base/Quantity.h> |
| #include <Gui/MetaTypes.h> |
|
|
| #include "Exceptions.h" |
| #include "MaterialValue.h" |
|
|
|
|
| using namespace Materials; |
|
|
| |
|
|
| TYPESYSTEM_SOURCE(Materials::MaterialValue, Base::BaseClass) |
|
|
| QMap<QString, MaterialValue::ValueType> MaterialValue::_typeMap { |
| {QStringLiteral("String"), String}, |
| {QStringLiteral("Boolean"), Boolean}, |
| {QStringLiteral("Integer"), Integer}, |
| {QStringLiteral("Float"), Float}, |
| {QStringLiteral("Quantity"), Quantity}, |
| {QStringLiteral("Distribution"), Distribution}, |
| {QStringLiteral("List"), List}, |
| {QStringLiteral("2DArray"), Array2D}, |
| {QStringLiteral("3DArray"), Array3D}, |
| {QStringLiteral("Color"), Color}, |
| {QStringLiteral("Image"), Image}, |
| {QStringLiteral("File"), File}, |
| {QStringLiteral("URL"), URL}, |
| {QStringLiteral("MultiLineString"), MultiLineString}, |
| {QStringLiteral("FileList"), FileList}, |
| {QStringLiteral("ImageList"), ImageList}, |
| {QStringLiteral("SVG"), SVG}}; |
|
|
| MaterialValue::MaterialValue() |
| : _valueType(None) |
| { |
| this->setInitialValue(None); |
| } |
|
|
| MaterialValue::MaterialValue(const MaterialValue& other) |
| : _valueType(other._valueType) |
| , _value(other._value) |
| {} |
|
|
| MaterialValue::MaterialValue(ValueType type) |
| : _valueType(type) |
| { |
| this->setInitialValue(None); |
| } |
|
|
| MaterialValue::MaterialValue(ValueType type, ValueType inherited) |
| : _valueType(type) |
| { |
| this->setInitialValue(inherited); |
| } |
|
|
| MaterialValue& MaterialValue::operator=(const MaterialValue& other) |
| { |
| if (this == &other) { |
| return *this; |
| } |
|
|
| _valueType = other._valueType; |
| _value = other._value; |
|
|
| return *this; |
| } |
|
|
| bool MaterialValue::operator==(const MaterialValue& other) const |
| { |
| if (this == &other) { |
| return true; |
| } |
|
|
| return (_valueType == other._valueType) && (_value == other._value); |
| } |
|
|
| void MaterialValue::validate(const MaterialValue& other) const |
| { |
| if (_valueType != other._valueType) { |
| throw InvalidProperty("Material property value types don't match"); |
| } |
| if (_valueType == Quantity) { |
| auto q1 = _value.value<Base::Quantity>(); |
| auto q2 = other._value.value<Base::Quantity>(); |
| if (q1.isValid()) { |
| if (!q2.isValid()) { |
| throw InvalidProperty("Invalid remote Material property quantity value"); |
| } |
| if (q1.getUserString() != q2.getUserString()) { |
| |
| |
| } |
| } |
| else { |
| if (q2.isValid()) { |
| throw InvalidProperty("Remote Material property quantity should not have a value"); |
| } |
| } |
| } |
| else if (_valueType == Array2D) { |
| auto a1 = static_cast<const Materials::Array2D*>(this); |
| auto a2 = static_cast<const Materials::Array2D*>(&other); |
| a1->validate(*a2); |
| } |
| else if (_valueType == Array3D) { |
| auto a1 = static_cast<const Materials::Array3D*>(this); |
| auto a2 = static_cast<const Materials::Array3D*>(&other); |
| a1->validate(*a2); |
| } |
| else if (!(_value.isNull() && other._value.isNull()) && (_value != other._value)) { |
| throw InvalidProperty("Material property values don't match"); |
| } |
| } |
|
|
| QString MaterialValue::escapeString(const QString& source) |
| { |
| QString res = source; |
| res.replace(QStringLiteral("\\"), QStringLiteral("\\\\")); |
| res.replace(QStringLiteral("\""), QStringLiteral("\\\"")); |
| return res; |
| } |
|
|
| MaterialValue::ValueType MaterialValue::mapType(const QString& stringType) |
| { |
| |
| return _typeMap.value(stringType, None); |
| } |
|
|
| void MaterialValue::setInitialValue(ValueType inherited) |
| { |
| #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
| if (_valueType == String || _valueType == MultiLineString || _valueType == SVG) { |
| _value = QVariant(static_cast<QVariant::Type>(QMetaType::QString)); |
| } |
| else if (_valueType == Boolean) { |
| _value = QVariant(static_cast<QVariant::Type>(QMetaType::Bool)); |
| } |
| else if (_valueType == Integer) { |
| _value = QVariant(static_cast<QVariant::Type>(QMetaType::Int)); |
| } |
| else if (_valueType == Float) { |
| _value = QVariant(static_cast<QVariant::Type>(QMetaType::Float)); |
| } |
| else if (_valueType == URL) { |
| _value = QVariant(static_cast<QVariant::Type>(QMetaType::QString)); |
| } |
| else if (_valueType == Color) { |
| _value = QVariant(static_cast<QVariant::Type>(QMetaType::QString)); |
| } |
| else if (_valueType == File) { |
| _value = QVariant(static_cast<QVariant::Type>(QMetaType::QString)); |
| } |
| else if (_valueType == Image) { |
| _value = QVariant(static_cast<QVariant::Type>(QMetaType::QString)); |
| } |
| #else |
| if (_valueType == String || _valueType == MultiLineString || _valueType == SVG) { |
| _value = QVariant(QMetaType(QMetaType::QString)); |
| } |
| else if (_valueType == Boolean) { |
| _value = QVariant(QMetaType(QMetaType::Bool)); |
| } |
| else if (_valueType == Integer) { |
| _value = QVariant(QMetaType(QMetaType::Int)); |
| } |
| else if (_valueType == Float) { |
| _value = QVariant(QMetaType(QMetaType::Float)); |
| } |
| else if (_valueType == URL) { |
| _value = QVariant(QMetaType(QMetaType::QString)); |
| } |
| else if (_valueType == Color) { |
| _value = QVariant(QMetaType(QMetaType::QString)); |
| } |
| else if (_valueType == File) { |
| _value = QVariant(QMetaType(QMetaType::QString)); |
| } |
| else if (_valueType == Image) { |
| _value = QVariant(QMetaType(QMetaType::QString)); |
| } |
| #endif |
| else if (_valueType == Quantity) { |
| Base::Quantity qu; |
| qu.setInvalid(); |
| _value = QVariant::fromValue(qu); |
| } |
| else if (_valueType == List || _valueType == FileList || _valueType == ImageList) { |
| auto list = QList<QVariant>(); |
| _value = QVariant::fromValue(list); |
| } |
| else if (_valueType == Array2D) { |
| if (_valueType != inherited) { |
| throw InvalidMaterialType("Initializing a regular material value as a 2D Array"); |
| } |
|
|
| _value = QVariant(); |
| } |
| else if (_valueType == Array3D) { |
| if (_valueType != inherited) { |
| throw InvalidMaterialType("Initializing a regular material value as a 3D Array"); |
| } |
|
|
| _value = QVariant(); |
| } |
| else { |
| |
| _valueType = None; |
| _value = QVariant(); |
| } |
| } |
|
|
| void MaterialValue::setList(const QList<QVariant>& value) |
| { |
| _value = QVariant::fromValue(value); |
| } |
|
|
| bool MaterialValue::isNull() const |
| { |
| return isEmpty(); |
| } |
|
|
| bool MaterialValue::isEmpty() const |
| { |
| if (_value.isNull()) { |
| return true; |
| } |
|
|
| if (_valueType == Quantity) { |
| return !_value.value<Base::Quantity>().isValid(); |
| } |
|
|
| if (_valueType == List || _valueType == FileList || _valueType == ImageList) { |
| return _value.value<QList<QVariant>>().isEmpty(); |
| } |
|
|
| return false; |
| } |
|
|
| QString MaterialValue::getYAMLStringImage() const |
| { |
| QString yaml; |
| yaml = QStringLiteral(" |-2"); |
| QString base64 = getValue().toString(); |
| while (!base64.isEmpty()) { |
| yaml += QStringLiteral("\n ") + base64.left(74); |
| base64.remove(0, 74); |
| } |
| return yaml; |
| } |
|
|
| QString MaterialValue::getYAMLStringList() const |
| { |
| QString yaml; |
| for (auto& it : getList()) { |
| yaml += QStringLiteral("\n - \"") + escapeString(it.toString()) |
| + QStringLiteral("\""); |
| } |
| return yaml; |
| } |
|
|
| QString MaterialValue::getYAMLStringImageList() const |
| { |
| QString yaml; |
| for (auto& it : getList()) { |
| yaml += QStringLiteral("\n - |-2"); |
| QString base64 = it.toString(); |
| while (!base64.isEmpty()) { |
| yaml += QStringLiteral("\n ") + base64.left(72); |
| base64.remove(0, 72); |
| } |
| } |
| return yaml; |
| } |
|
|
| QString MaterialValue::getYAMLStringMultiLine() const |
| { |
| QString yaml; |
| yaml = QStringLiteral(" |2"); |
| auto list = |
| getValue().toString().split(QRegularExpression(QStringLiteral("[\r\n]")), Qt::SkipEmptyParts); |
| for (auto& it : list) { |
| yaml += QStringLiteral("\n ") + it; |
| } |
| return yaml; |
| } |
|
|
| QString MaterialValue::getYAMLString() const |
| { |
| QString yaml; |
| if (!isNull()) { |
| if (getType() == MaterialValue::Image) { |
| return getYAMLStringImage(); |
| } |
| if (getType() == MaterialValue::List || getType() == MaterialValue::FileList) { |
| return getYAMLStringList(); |
| } |
| if (getType() == MaterialValue::ImageList) { |
| return getYAMLStringImageList(); |
| } |
| if (getType() == MaterialValue::MultiLineString || getType() == MaterialValue::SVG) { |
| return getYAMLStringMultiLine(); |
| } |
| if (getType() == MaterialValue::Quantity) { |
| auto quantity = getValue().value<Base::Quantity>(); |
| yaml += QString::fromStdString(quantity.getUserString()); |
| } |
| else if (getType() == MaterialValue::Float) { |
| auto value = getValue(); |
| if (!value.isNull()) { |
| yaml += QStringLiteral("%1").arg(value.toFloat(), 0, 'g', 6); |
| } |
| } |
| else if (getType() == MaterialValue::List) { |
| for (auto& it : getList()) { |
| yaml += QStringLiteral("\n - \"") + escapeString(it.toString()) |
| + QStringLiteral("\""); |
| } |
| return yaml; |
| } |
| else { |
| yaml += getValue().toString(); |
| } |
| } |
| yaml = QStringLiteral(" \"") + escapeString(yaml) + QStringLiteral("\""); |
| return yaml; |
| } |
|
|
| const Base::QuantityFormat MaterialValue::getQuantityFormat() |
| { |
| return Base::QuantityFormat(Base::QuantityFormat::NumberFormat::Default, PRECISION); |
| } |
|
|
| |
|
|
| TYPESYSTEM_SOURCE(Materials::Array2D, Materials::MaterialValue) |
|
|
| Array2D::Array2D() |
| : MaterialValue(MaterialValue::Array2D, MaterialValue::Array2D) |
| , _columns(0) |
| { |
| |
| |
| } |
|
|
| Array2D::Array2D(const Array2D& other) |
| : MaterialValue(other) |
| , _columns(other._columns) |
| { |
| deepCopy(other); |
| } |
|
|
| Array2D& Array2D::operator=(const Array2D& other) |
| { |
| if (this == &other) { |
| return *this; |
| } |
|
|
| MaterialValue::operator=(other); |
| _columns = other._columns; |
|
|
| deepCopy(other); |
|
|
| return *this; |
| } |
|
|
| void Array2D::deepCopy(const Array2D& other) |
| { |
| |
| for (auto& row : other._rows) { |
| QList<QVariant> vv; |
| for (auto& col : *row) { |
| QVariant newVariant(col); |
| vv.push_back(newVariant); |
| } |
| addRow(std::make_shared<QList<QVariant>>(vv)); |
| } |
| } |
|
|
| bool Array2D::isNull() const |
| { |
| return isEmpty(); |
| } |
|
|
| bool Array2D::isEmpty() const |
| { |
| return rows() <= 0; |
| } |
|
|
| void Array2D::validateRow(int row) const |
| { |
| if (row < 0 || row >= rows()) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array2D::validateColumn(int column) const |
| { |
| if (column < 0 || column >= columns()) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array2D::validate(const Array2D& other) const |
| { |
| if (rows() != other.rows()) { |
| Base::Console().log("Local row count %d, remote %d\n", rows(), other.rows()); |
| throw InvalidProperty("Material property value row counts don't match"); |
| } |
| if (columns() != other.columns()) { |
| Base::Console().log("Local column count %d, remote %d\n", columns(), other.columns()); |
| throw InvalidProperty("Material property value column counts don't match"); |
| } |
| try { |
| for (int i = 0; i < rows(); i++) { |
| for (int j = 0; j < columns(); j++) { |
| if (getValue(i, j) != other.getValue(i, j)) { |
| throw InvalidProperty("Material property values don't match"); |
| } |
| } |
| } |
| } |
| catch (const InvalidIndex&) { |
| throw InvalidProperty("Material property value invalid array index"); |
| } |
| } |
|
|
| std::shared_ptr<QList<QVariant>> Array2D::getRow(int row) const |
| { |
| validateRow(row); |
|
|
| try { |
| return _rows.at(row); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| std::shared_ptr<QList<QVariant>> Array2D::getRow(int row) |
| { |
| validateRow(row); |
|
|
| try { |
| return _rows.at(row); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array2D::addRow(const std::shared_ptr<QList<QVariant>>& row) |
| { |
| _rows.push_back(row); |
| } |
|
|
| void Array2D::insertRow(int index, const std::shared_ptr<QList<QVariant>>& row) |
| { |
| _rows.insert(_rows.begin() + index, row); |
| } |
|
|
| void Array2D::deleteRow(int row) |
| { |
| if (row >= static_cast<int>(_rows.size()) || row < 0) { |
| throw InvalidIndex(); |
| } |
| _rows.erase(_rows.begin() + row); |
| } |
|
|
| void Array2D::setRows(int rowCount) |
| { |
| while (rows() < rowCount) { |
| auto row = std::make_shared<QList<QVariant>>(); |
| for (int i = 0; i < columns(); i++) { |
| row->append(QVariant()); |
| } |
| addRow(row); |
| } |
| } |
|
|
| void Array2D::setValue(int row, int column, const QVariant& value) |
| { |
| validateRow(row); |
| validateColumn(column); |
|
|
| auto val = getRow(row); |
| try { |
| val->replace(column, value); |
| } |
| catch (const std::out_of_range&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| QVariant Array2D::getValue(int row, int column) const |
| { |
| validateColumn(column); |
|
|
| auto val = getRow(row); |
| try { |
| return val->at(column); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array2D::dumpRow(const std::shared_ptr<QList<QVariant>>& row) |
| { |
| Base::Console().log("row: "); |
| for (auto& column : *row) { |
| Base::Console().log("'%s' ", column.toString().toStdString().c_str()); |
| } |
| Base::Console().log("\n"); |
| } |
|
|
| void Array2D::dump() const |
| { |
| for (auto& row : _rows) { |
| dumpRow(row); |
| } |
| } |
|
|
| QString Array2D::getYAMLString() const |
| { |
| if (isNull()) { |
| return QString(); |
| } |
|
|
| |
| QString pad; |
| pad.fill(QChar::fromLatin1(' '), 9); |
|
|
| |
| QString yaml = QStringLiteral("\n - ["); |
| bool firstRow = true; |
| for (auto& row : _rows) { |
| if (!firstRow) { |
| |
| yaml += QStringLiteral(",\n") + pad; |
| } |
| else { |
| firstRow = false; |
| } |
| yaml += QStringLiteral("["); |
|
|
| bool first = true; |
| for (auto& column : *row) { |
| if (!first) { |
| |
| yaml += QStringLiteral(", "); |
| } |
| else { |
| first = false; |
| } |
| yaml += QStringLiteral("\""); |
| auto quantity = column.value<Base::Quantity>(); |
| yaml += QString::fromStdString(quantity.getUserString()); |
| yaml += QStringLiteral("\""); |
| } |
|
|
| yaml += QStringLiteral("]"); |
| } |
| yaml += QStringLiteral("]"); |
| return yaml; |
| } |
|
|
| |
|
|
| TYPESYSTEM_SOURCE(Materials::Array3D, Materials::MaterialValue) |
|
|
| Array3D::Array3D() |
| : MaterialValue(MaterialValue::Array3D, MaterialValue::Array3D) |
| , _currentDepth(0) |
| , _columns(0) |
| { |
| |
| |
| } |
|
|
| Array3D::Array3D(const Array3D& other) |
| : MaterialValue(other) |
| , _currentDepth(other._currentDepth) |
| , _columns(other._columns) |
| { |
| deepCopy(other); |
| } |
|
|
| Array3D& Array3D::operator=(const Array3D& other) |
| { |
| if (this == &other) { |
| return *this; |
| } |
|
|
| MaterialValue::operator=(other); |
| _columns = other._columns; |
| _currentDepth = other._currentDepth; |
|
|
| deepCopy(other); |
|
|
| return *this; |
| } |
|
|
| void Array3D::deepCopy(const Array3D& other) |
| { |
| |
| _rowMap.clear(); |
| for (auto& depthTable : other._rowMap) { |
| auto depth = addDepth(depthTable.first); |
| auto rows = depthTable.second; |
| for (auto row : *rows) { |
| auto newRow = std::make_shared<QList<Base::Quantity>>(); |
| for (auto column : *row) { |
| newRow->append(column); |
| } |
| addRow(depth, newRow); |
| } |
| } |
| } |
|
|
| bool Array3D::isNull() const |
| { |
| return isEmpty(); |
| } |
|
|
| bool Array3D::isEmpty() const |
| { |
| return depth() <= 0; |
| } |
|
|
| void Array3D::validateDepth(int level) const |
| { |
| if (level < 0 || level >= depth()) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array3D::validateColumn(int column) const |
| { |
| if (column < 0 || column >= columns()) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array3D::validateRow(int level, int row) const |
| { |
| validateDepth(level); |
|
|
| if (row < 0 || row >= rows(level)) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array3D::validate(const Array3D& other) const |
| { |
| if (depth() != other.depth()) { |
| throw InvalidProperty("Material property value row counts don't match"); |
| } |
| if (columns() != other.columns()) { |
| throw InvalidProperty("Material property value column counts don't match"); |
| } |
| } |
|
|
| const std::shared_ptr<QList<std::shared_ptr<QList<Base::Quantity>>>>& |
| Array3D::getTable(const Base::Quantity& depth) const |
| { |
| for (auto& it : _rowMap) { |
| if (std::get<0>(it) == depth) { |
| return std::get<1>(it); |
| } |
| } |
|
|
| throw InvalidIndex(); |
| } |
|
|
| const std::shared_ptr<QList<std::shared_ptr<QList<Base::Quantity>>>>& |
| Array3D::getTable(int depthIndex) const |
| { |
| try { |
| return std::get<1>(_rowMap.at(depthIndex)); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| std::shared_ptr<QList<Base::Quantity>> Array3D::getRow(int depth, int row) const |
| { |
| validateRow(depth, row); |
|
|
| try { |
| return getTable(depth)->at(row); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| std::shared_ptr<QList<Base::Quantity>> Array3D::getRow(int row) const |
| { |
| |
| return getRow(_currentDepth, row); |
| } |
|
|
| std::shared_ptr<QList<Base::Quantity>> Array3D::getRow(int depth, int row) |
| { |
| validateRow(depth, row); |
|
|
| try { |
| return getTable(depth)->at(row); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| std::shared_ptr<QList<Base::Quantity>> Array3D::getRow(int row) |
| { |
| return getRow(_currentDepth, row); |
| } |
|
|
| void Array3D::addRow(int depth, const std::shared_ptr<QList<Base::Quantity>>& row) |
| { |
| try { |
| getTable(depth)->push_back(row); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array3D::addRow(const std::shared_ptr<QList<Base::Quantity>>& row) |
| { |
| addRow(_currentDepth, row); |
| } |
|
|
| int Array3D::addDepth(int depth, const Base::Quantity& value) |
| { |
| if (depth == this->depth()) { |
| |
| return addDepth(value); |
| } |
| if (depth > this->depth()) { |
| throw InvalidIndex(); |
| } |
| auto rowVector = std::make_shared<QList<std::shared_ptr<QList<Base::Quantity>>>>(); |
| auto entry = std::make_pair(value, rowVector); |
| _rowMap.insert(_rowMap.begin() + depth, entry); |
|
|
| return depth; |
| } |
|
|
| int Array3D::addDepth(const Base::Quantity& value) |
| { |
| auto rowVector = std::make_shared<QList<std::shared_ptr<QList<Base::Quantity>>>>(); |
| auto entry = std::make_pair(value, rowVector); |
| _rowMap.push_back(entry); |
|
|
| return depth() - 1; |
| } |
|
|
| void Array3D::deleteDepth(int depth) |
| { |
| deleteRows(depth); |
| _rowMap.erase(_rowMap.begin() + depth); |
| } |
|
|
| void Array3D::setDepth(int depthCount) |
| { |
| Base::Quantity dummy; |
| dummy.setInvalid(); |
| while (depth() < depthCount) { |
| addDepth(dummy); |
| } |
| } |
|
|
| void Array3D::insertRow(int depth, |
| int row, |
| const std::shared_ptr<QList<Base::Quantity>>& rowData) |
| { |
| try { |
| auto table = getTable(depth); |
| table->insert(table->begin() + row, rowData); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array3D::insertRow(int row, const std::shared_ptr<QList<Base::Quantity>>& rowData) |
| { |
| insertRow(_currentDepth, row, rowData); |
| } |
|
|
| void Array3D::deleteRow(int depth, int row) |
| { |
| auto table = getTable(depth); |
| if (row >= static_cast<int>(table->size()) || row < 0) { |
| throw InvalidIndex(); |
| } |
| table->erase(table->begin() + row); |
| } |
|
|
| void Array3D::deleteRow(int row) |
| { |
| deleteRow(_currentDepth, row); |
| } |
|
|
| void Array3D::deleteRows(int depth) |
| { |
| auto table = getTable(depth); |
| table->clear(); |
| } |
|
|
| void Array3D::deleteRows() |
| { |
| deleteRows(_currentDepth); |
| } |
|
|
| int Array3D::rows(int depth) const |
| { |
| if (depth < 0 || (depth == 0 && this->depth() == 0)) { |
| return 0; |
| } |
| validateDepth(depth); |
|
|
| return getTable(depth)->size(); |
| } |
|
|
| void Array3D::setRows(int depth, int rowCount) |
| { |
| Base::Quantity dummy; |
| dummy.setInvalid(); |
|
|
| while (rows(depth) < rowCount) { |
| auto row = std::make_shared<QList<Base::Quantity>>(); |
| for (int i = 0; i < columns(); i++) { |
| row->append(dummy); |
| } |
| addRow(depth, row); |
| } |
| } |
|
|
| void Array3D::setValue(int depth, int row, int column, const Base::Quantity& value) |
| { |
| validateRow(depth, row); |
| validateColumn(column); |
|
|
| auto val = getRow(depth, row); |
| try { |
| val->replace(column, value); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array3D::setValue(int row, int column, const Base::Quantity& value) |
| { |
| setValue(_currentDepth, row, column, value); |
| } |
|
|
| void Array3D::setDepthValue(int depth, const Base::Quantity& value) |
| { |
| try { |
| auto oldRows = getTable(depth); |
| _rowMap.replace(depth, std::pair(value, oldRows)); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| void Array3D::setDepthValue(const Base::Quantity& value) |
| { |
| setDepthValue(_currentDepth, value); |
| } |
|
|
|
|
| Base::Quantity Array3D::getValue(int depth, int row, int column) const |
| { |
| |
| auto val = getRow(depth, row); |
| validateColumn(column); |
|
|
| try { |
| return val->at(column); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| Base::Quantity Array3D::getValue(int row, int column) const |
| { |
| return getValue(_currentDepth, row, column); |
| } |
|
|
| Base::Quantity Array3D::getDepthValue(int depth) const |
| { |
| validateDepth(depth); |
|
|
| try { |
| return std::get<0>(_rowMap.at(depth)); |
| } |
| catch (std::out_of_range const&) { |
| throw InvalidIndex(); |
| } |
| } |
|
|
| int Array3D::currentDepth() const |
| { |
| return _currentDepth; |
| } |
|
|
| void Array3D::setCurrentDepth(int depth) |
| { |
| validateDepth(depth); |
|
|
| if (depth < 0 || _rowMap.empty()) { |
| _currentDepth = 0; |
| } |
| else if (depth >= static_cast<int>(_rowMap.size())) { |
| _currentDepth = _rowMap.size() - 1; |
| } |
| else { |
| _currentDepth = depth; |
| } |
| } |
|
|
| QString Array3D::getYAMLString() const |
| { |
| if (isNull()) { |
| return QString(); |
| } |
|
|
| |
| QString pad; |
| pad.fill(QChar::fromLatin1(' '), 9); |
|
|
| |
| QString yaml = QStringLiteral("\n - ["); |
| for (int depth = 0; depth < this->depth(); depth++) { |
| if (depth > 0) { |
| |
| yaml += QStringLiteral(",\n") + pad; |
| } |
|
|
| yaml += QStringLiteral("\""); |
| auto value = QString::fromStdString(getDepthValue(depth).getUserString()); |
| yaml += value; |
| yaml += QStringLiteral("\": ["); |
|
|
| QString pad2; |
| pad2.fill(QChar::fromLatin1(' '), 14 + value.length()); |
|
|
| bool firstRow = true; |
| auto rows = getTable(depth); |
| for (auto& row : *rows) { |
| if (!firstRow) { |
| |
| yaml += QStringLiteral(",\n") + pad2; |
| } |
| else { |
| firstRow = false; |
| } |
| yaml += QStringLiteral("["); |
|
|
| bool first = true; |
| for (auto& column : *row) { |
| if (!first) { |
| |
| yaml += QStringLiteral(", "); |
| } |
| else { |
| first = false; |
| } |
| yaml += QStringLiteral("\""); |
| |
| yaml += QString::fromStdString(column.getUserString()); |
| yaml += QStringLiteral("\""); |
| } |
|
|
| yaml += QStringLiteral("]"); |
| } |
| yaml += QStringLiteral("]"); |
| } |
| yaml += QStringLiteral("]"); |
| return yaml; |
| } |
|
|