Warning, file /education/labplot/src/backend/datasources/filters/MatioFilter.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 File : MatioFilter.cpp 0003 Project : LabPlot 0004 Description : Matio I/O-filter 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2021-2022 Stefan Gerlach <stefan.gerlach@uni.kn> 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "MatioFilter.h" 0010 #include "MatioFilterPrivate.h" 0011 #include "backend/core/column/Column.h" 0012 #include "backend/lib/XmlStreamReader.h" 0013 #include "backend/lib/macros.h" 0014 #include "backend/lib/trace.h" 0015 #include "backend/matrix/Matrix.h" 0016 0017 #include <KLocalizedString> 0018 0019 #include <cmath> 0020 0021 ///////////// macros /////////////////////////////////////////////// 0022 0023 // see NetCDFFilter.cpp 0024 // type - var data type, dtype - container data type 0025 #define MAT_READ_VAR(type, dtype) \ 0026 { \ 0027 if (var->isComplex) { \ 0028 auto* complex_data = (mat_complex_split_t*)var->data; \ 0029 auto* re = (type*)complex_data->Re; \ 0030 auto* im = (type*)complex_data->Im; \ 0031 if (dataSource) { \ 0032 for (size_t i = 0; i < actualRows; i++) \ 0033 for (size_t j = 0; j < actualCols / 2; j++) { \ 0034 const size_t index = i + startRow - 1 + (j + startColumn - 1) * rows; \ 0035 static_cast<QVector<dtype>*>(dataContainer[(int)(2 * j)])->operator[](i) = re[index]; \ 0036 static_cast<QVector<dtype>*>(dataContainer[(int)(2 * j + 1)])->operator[](i) = im[index]; \ 0037 } \ 0038 } else { /* preview */ \ 0039 QStringList header; \ 0040 for (size_t j = 0; j < actualCols / 2; j++) { \ 0041 header << QLatin1String("Re ") + QString::number(j + 1) << QLatin1String("Im ") + QString::number(j + 1); \ 0042 } \ 0043 dataStrings << header; \ 0044 for (size_t i = 0; i < std::min(actualRows, lines); i++) { \ 0045 QStringList row; \ 0046 for (size_t j = 0; j < actualCols / 2; j++) { \ 0047 const size_t index = i + startRow - 1 + (j + startColumn - 1) * rows; \ 0048 row << QString::number(re[index]) << QString::number(im[index]); \ 0049 } \ 0050 dataStrings << row; \ 0051 } \ 0052 } \ 0053 } else { \ 0054 const auto* data = static_cast<const type*>(var->data); \ 0055 if (dataSource) { \ 0056 for (size_t i = 0; i < actualRows; i++) \ 0057 for (size_t j = 0; j < actualCols; j++) { \ 0058 const size_t index = i + startRow - 1 + (j + startColumn - 1) * rows; \ 0059 static_cast<QVector<dtype>*>(dataContainer[(int)j + (dynamic_cast<Matrix*>(dataSource) ? columnOffset : 0)])->operator[](i) = \ 0060 data[index]; \ 0061 } \ 0062 } else { /* preview */ \ 0063 for (size_t i = 0; i < std::min(actualRows, lines); i++) { \ 0064 QStringList row; \ 0065 for (size_t j = 0; j < actualCols; j++) \ 0066 row << QString::number(data[i + startRow - 1 + (j + startColumn - 1) * rows]); \ 0067 dataStrings << row; \ 0068 } \ 0069 } \ 0070 } \ 0071 } 0072 0073 // type - cell data type, dtype - container data type 0074 // TODO: complex 0075 #define MAT_READ_CELL(type, dtype) \ 0076 { \ 0077 const auto* data = (const type*)cell->data; \ 0078 if (dataSource) { \ 0079 if (i + startRow - 1 < cellsize) \ 0080 static_cast<QVector<dtype>*>(dataContainer[j])->operator[](i) = data[i + startRow - 1]; \ 0081 else \ 0082 static_cast<QVector<dtype>*>(dataContainer[j])->operator[](i) = qQNaN(); \ 0083 } else { /* preview */ \ 0084 if (i + startRow - 1 < cellsize) \ 0085 row << QString::number(data[i + startRow - 1]); \ 0086 else \ 0087 row << QString(); \ 0088 } \ 0089 } 0090 0091 // type - sparse data type, dtype - container data type 0092 #define MAT_READ_SPARSE(type, dtype) \ 0093 { \ 0094 /* set default values */ \ 0095 QVector<QVector<type>> matrix; /* for preview */ \ 0096 if (dataSource) { \ 0097 for (size_t i = 0; i < actualRows; i++) \ 0098 for (size_t j = 0; j < actualCols; j++) \ 0099 static_cast<QVector<dtype>*>(dataContainer[j])->operator[](i) = 0; \ 0100 } else { /* preview (full matrix need to store values) */ \ 0101 for (size_t i = 0; i < actualEndRow; i++) { \ 0102 QVector<type> tmp; \ 0103 for (size_t j = 0; j < actualEndColumn; j++) \ 0104 tmp.append(0); \ 0105 matrix.append(tmp); \ 0106 } \ 0107 } \ 0108 if (var->isComplex) { \ 0109 auto* complex_data = (mat_complex_split_t*)sparse->data; \ 0110 auto* re = (type*)complex_data->Re; \ 0111 auto* im = (type*)complex_data->Im; \ 0112 if (dataSource) { \ 0113 for (size_t i = 0; i < std::min((size_t)sparse->njc - 1, actualCols / 2); i++) \ 0114 for (size_t j = sparse->jc[i]; j < (size_t)sparse->jc[i + 1] && j < (size_t)sparse->ndata; j++) { \ 0115 if (sparse->ir[j] >= (size_t)startRow - 1 && sparse->ir[j] < actualEndRow) { /* only read requested rows */ \ 0116 static_cast<QVector<dtype>*>(dataContainer[(int)2 * i])->operator[](sparse->ir[j] - startRow + 1) = \ 0117 *(re + j * stride / sizeof(type)); \ 0118 static_cast<QVector<dtype>*>(dataContainer[(int)2 * i + 1])->operator[](sparse->ir[j] - startRow + 1) = \ 0119 *(im + j * stride / sizeof(type)); \ 0120 } \ 0121 } \ 0122 } else { /* preview */ \ 0123 for (size_t i = 0; i < std::min((size_t)sparse->njc - 1, actualEndColumn / 2 + 1); i++) \ 0124 for (size_t j = sparse->jc[i]; j < (size_t)sparse->jc[i + 1] && j < (size_t)sparse->ndata; j++) { \ 0125 if (sparse->ir[j] >= (size_t)startRow - 1 && sparse->ir[j] < actualEndRow) { /* only read requested rows */ \ 0126 if (2 * i < actualEndColumn) /* Im may be last col */ \ 0127 matrix[sparse->ir[j]][2 * i] = *(re + j * stride / sizeof(type)); \ 0128 if (2 * i + 1 < actualEndColumn) /* Re may be last col */ \ 0129 matrix[sparse->ir[j]][2 * i + 1] = *(im + j * stride / sizeof(type)); \ 0130 } \ 0131 } \ 0132 } \ 0133 } else { /* real */ \ 0134 auto* data = (type*)sparse->data; \ 0135 if (dataSource) { \ 0136 for (size_t i = startColumn - 1; i < std::min((size_t)sparse->njc - 1, actualEndColumn); i++) \ 0137 for (size_t j = sparse->jc[i]; j < (size_t)sparse->jc[i + 1] && j < (size_t)sparse->ndata; j++) { \ 0138 if (sparse->ir[j] >= (size_t)startRow - 1 && sparse->ir[j] < actualEndRow) /* only read requested rows */ \ 0139 static_cast<QVector<dtype>*>(dataContainer[(int)i - startColumn + 1])->operator[](sparse->ir[j] - startRow + 1) = \ 0140 *(data + j * stride / sizeof(type)); \ 0141 } \ 0142 } else { /* preview */ \ 0143 for (size_t i = 0; i < std::min((size_t)sparse->njc - 1, actualEndColumn); i++) \ 0144 for (size_t j = sparse->jc[i]; j < (size_t)sparse->jc[i + 1] && j < (size_t)sparse->ndata; j++) \ 0145 if (sparse->ir[j] < actualEndRow) /* don't read beyond last row */ \ 0146 matrix[sparse->ir[j]][i] = *(data + j * stride / sizeof(type)); \ 0147 } \ 0148 } \ 0149 if (!dataSource) { /* preview */ \ 0150 for (size_t i = startRow - 1; i < std::min(actualEndRow, lines); i++) { \ 0151 QStringList row; \ 0152 for (size_t j = startColumn - 1; j < actualEndColumn; j++) \ 0153 row << QString::number(matrix[i][j]); \ 0154 dataStrings << row; \ 0155 } \ 0156 } \ 0157 } 0158 0159 // type - struct data type 0160 #define MAT_READ_STRUCT(type) \ 0161 { \ 0162 if (fields[i]->isComplex) { \ 0163 auto* complex_data = (mat_complex_split_t*)fields[i]->data; \ 0164 auto* re = (type*)complex_data->Re; \ 0165 auto* im = (type*)complex_data->Im; \ 0166 \ 0167 DEBUG(Q_FUNC_INFO << " rank = 2 (" << fields[i]->dims[0] << " x " << fields[i]->dims[1] << ")") \ 0168 if (dataSource) { \ 0169 for (size_t j = 0; j < actualRows; j++) { \ 0170 static_cast<QVector<type>*>(dataContainer[colIndex])->operator[](j) = re[j + startRow - 1]; \ 0171 static_cast<QVector<type>*>(dataContainer[colIndex + 1])->operator[](j) = im[j + startRow - 1]; \ 0172 } \ 0173 } else { /* preview */ \ 0174 for (size_t j = 0; j < std::min(actualRows, lines); j++) { \ 0175 /* TODO: use when complex column mode is supported */ \ 0176 /* if (im[j] < 0) \ 0177 dataStrings[j+1][field] = QString::number(re[j]) + QLatin1String(" - ") \ 0178 + QString::number(fabs(im[j])) + QLatin1String("i"); \ 0179 else if (im[j] == 0) \ 0180 dataStrings[j+1][field] = QString::number(re[j]); \ 0181 else if (re[j] == 0) \ 0182 dataStrings[j+1][field] = QString::number(im[j]) + QLatin1String("i"); \ 0183 else \ 0184 dataStrings[j+1][field] = QString::number(re[j]) + QLatin1String(" + ") \ 0185 + QString::number(im[j]) + QLatin1String("i"); \ 0186 */ \ 0187 dataStrings[j + 1][colIndex] = QString::number(re[j + startRow - 1]); \ 0188 dataStrings[j + 1][colIndex + 1] = QString::number(im[j + startRow - 1]); \ 0189 } \ 0190 } \ 0191 colIndex++; /* complex uses two columns atm */ \ 0192 } else { /* real */ \ 0193 auto* data = (type*)fields[i]->data; \ 0194 DEBUG(Q_FUNC_INFO << " rank = 2 (" << fields[i]->dims[0] << " x " << fields[i]->dims[1] << ")") \ 0195 if (dataSource) { \ 0196 for (size_t j = 0; j < actualRows; j++) \ 0197 static_cast<QVector<type>*>(dataContainer[colIndex])->operator[](j) = data[j + startRow - 1]; \ 0198 } else { /* preview */ \ 0199 for (size_t j = 0; j < std::min(actualRows, lines); j++) \ 0200 dataStrings[j + 1][colIndex] = QString::number(data[j + startRow - 1]); \ 0201 } \ 0202 } \ 0203 } 0204 ////////////////////////////////////////////////////////////////////// 0205 0206 /*! 0207 \class MatioFilter 0208 \brief Manages the import/export of data from/to a Matio file. 0209 0210 \ingroup datasources 0211 */ 0212 MatioFilter::MatioFilter() 0213 : AbstractFileFilter(FileType::MATIO) 0214 , d(new MatioFilterPrivate(this)) { 0215 } 0216 0217 MatioFilter::~MatioFilter() = default; 0218 0219 /*! 0220 parses the content of the file \c ileName. 0221 */ 0222 void MatioFilter::parse(const QString& fileName) { 0223 d->parse(fileName); 0224 } 0225 0226 /*! 0227 reads the content of the current variable from file \c fileName. 0228 */ 0229 QVector<QStringList> 0230 MatioFilter::readCurrentVar(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode, int lines) { 0231 return d->readCurrentVar(fileName, dataSource, importMode, (size_t)lines); 0232 } 0233 0234 /*! 0235 reads the content of the file \c fileName to the data source \c dataSource. 0236 */ 0237 void MatioFilter::readDataFromFile(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode mode) { 0238 d->readDataFromFile(fileName, dataSource, mode); 0239 } 0240 0241 /*! 0242 writes the content of the data source \c dataSource to the file \c fileName. 0243 */ 0244 void MatioFilter::write(const QString& fileName, AbstractDataSource* dataSource) { 0245 d->write(fileName, dataSource); 0246 // emit() 0247 } 0248 0249 /////////////////////////////////////////////////////////////////////// 0250 0251 void MatioFilter::setCurrentVarName(const QString& name) { 0252 d->currentVarName = name; 0253 d->selectedVarNames = QStringList() << name; 0254 } 0255 void MatioFilter::setSelectedVarNames(const QStringList& names) { 0256 d->currentVarName = names.first(); 0257 d->selectedVarNames = names; 0258 } 0259 const QStringList MatioFilter::selectedVarNames() const { 0260 return d->selectedVarNames; 0261 } 0262 size_t MatioFilter::varCount() const { 0263 return d->varCount; 0264 } 0265 QVector<QStringList> MatioFilter::varsInfo() const { 0266 return d->varsInfo; 0267 } 0268 0269 void MatioFilter::setStartRow(const int s) { 0270 d->startRow = s; 0271 } 0272 0273 int MatioFilter::startRow() const { 0274 return d->startRow; 0275 } 0276 0277 void MatioFilter::setEndRow(const int e) { 0278 d->endRow = e; 0279 } 0280 0281 int MatioFilter::endRow() const { 0282 return d->endRow; 0283 } 0284 0285 void MatioFilter::setStartColumn(const int c) { 0286 d->startColumn = c; 0287 } 0288 0289 int MatioFilter::startColumn() const { 0290 return d->startColumn; 0291 } 0292 0293 void MatioFilter::setEndColumn(const int c) { 0294 d->endColumn = c; 0295 } 0296 0297 int MatioFilter::endColumn() const { 0298 return d->endColumn; 0299 } 0300 0301 QString MatioFilter::fileInfoString(const QString& fileName) { 0302 DEBUG(Q_FUNC_INFO << ", fileName = " << qPrintable(fileName)) 0303 0304 QString info; 0305 #ifdef HAVE_MATIO 0306 mat_t* matfp = Mat_Open(qPrintable(fileName), MAT_ACC_RDONLY); 0307 0308 if (!matfp) 0309 return i18n("Error getting file info"); 0310 0311 int version = Mat_GetVersion(matfp); 0312 const char* header = Mat_GetHeader(matfp); 0313 DEBUG(Q_FUNC_INFO << ", Header: " << header) 0314 info += QLatin1String(header); 0315 info += QStringLiteral("<br>"); 0316 switch (version) { 0317 case MAT_FT_MAT73: 0318 info += i18n("Matlab version 7.3"); 0319 break; 0320 case MAT_FT_MAT5: 0321 info += i18n("Matlab version 5"); 0322 break; 0323 case MAT_FT_MAT4: 0324 info += i18n("Matlab version 4"); 0325 break; 0326 case MAT_FT_UNDEFINED: 0327 info += i18n("Matlab version undefined"); 0328 } 0329 info += QLatin1String("<br>"); 0330 0331 size_t n; 0332 char** dir = Mat_GetDir(matfp, &n); 0333 info += i18n("Number of variables: ") + QString::number(n); 0334 info += QStringLiteral("<br>"); 0335 if (dir && n < 10) { // only show variable info when there are not too many 0336 info += i18n("Variables:"); 0337 for (size_t i = 0; i < n; ++i) { 0338 if (dir[i]) { 0339 info += QStringLiteral(" \"") + QLatin1String(dir[i]) + QStringLiteral("\""); 0340 matvar_t* var = Mat_VarReadInfo(matfp, dir[i]); 0341 if (var) 0342 info += QStringLiteral(" (") + QString::number(Mat_VarGetNumberOfFields(var)) + QStringLiteral(" fields, ") 0343 + QString::number(Mat_VarGetSize(var)) + QStringLiteral(" byte)"); 0344 Mat_VarFree(var); 0345 } 0346 } 0347 } 0348 0349 Mat_Close(matfp); 0350 #else 0351 Q_UNUSED(fileName) 0352 #endif 0353 0354 return info; 0355 } 0356 0357 // ##################################################################### 0358 // ################### Private implementation ########################## 0359 // ##################################################################### 0360 0361 MatioFilterPrivate::MatioFilterPrivate(MatioFilter*) { 0362 } 0363 0364 // helper functions 0365 #ifdef HAVE_MATIO 0366 // see matio.h 0367 QString MatioFilterPrivate::className(matio_classes classType) { 0368 switch (classType) { 0369 case MAT_C_EMPTY: 0370 return i18n("Empty"); 0371 case MAT_C_CELL: 0372 return i18n("Cell"); 0373 case MAT_C_STRUCT: 0374 return i18n("Struct"); 0375 case MAT_C_OBJECT: 0376 return i18n("Object"); 0377 case MAT_C_CHAR: 0378 return i18n("Char"); 0379 case MAT_C_SPARSE: 0380 return i18n("Sparse"); 0381 case MAT_C_DOUBLE: 0382 return i18n("Double"); 0383 case MAT_C_SINGLE: 0384 return i18n("Single"); 0385 case MAT_C_INT8: 0386 return i18n("Int8"); 0387 case MAT_C_UINT8: 0388 return i18n("UInt8"); 0389 case MAT_C_INT16: 0390 return i18n("Int16"); 0391 case MAT_C_UINT16: 0392 return i18n("UInt16"); 0393 case MAT_C_INT32: 0394 return i18n("Int32"); 0395 case MAT_C_UINT32: 0396 return i18n("UInt32"); 0397 case MAT_C_INT64: 0398 return i18n("Int64"); 0399 case MAT_C_UINT64: 0400 return i18n("UInt64"); 0401 case MAT_C_FUNCTION: 0402 return i18n("Function"); 0403 case MAT_C_OPAQUE: 0404 return i18n("Opaque"); 0405 } 0406 0407 return i18n("Undefined"); 0408 } 0409 QString MatioFilterPrivate::typeName(matio_types dataType) { 0410 switch (dataType) { 0411 case MAT_T_UNKNOWN: 0412 return i18n("Unknown"); 0413 case MAT_T_INT8: 0414 return i18n("Int8"); 0415 case MAT_T_UINT8: 0416 return i18n("UInt8"); 0417 case MAT_T_INT16: 0418 return i18n("Int16"); 0419 case MAT_T_UINT16: 0420 return i18n("UInt16"); 0421 case MAT_T_INT32: 0422 return i18n("Int32"); 0423 case MAT_T_UINT32: 0424 return i18n("UInt32"); 0425 case MAT_T_SINGLE: 0426 return i18n("Single"); 0427 case MAT_T_DOUBLE: 0428 return i18n("Double"); 0429 case MAT_T_INT64: 0430 return i18n("Int64"); 0431 case MAT_T_UINT64: 0432 return i18n("UInt64"); 0433 case MAT_T_MATRIX: 0434 return i18n("Matrix"); 0435 case MAT_T_COMPRESSED: 0436 return i18n("Compressed"); 0437 case MAT_T_UTF8: 0438 return i18n("UTF8"); 0439 case MAT_T_UTF16: 0440 return i18n("UTF16"); 0441 case MAT_T_UTF32: 0442 return i18n("UTF32"); 0443 case MAT_T_STRING: 0444 return i18n("String"); 0445 case MAT_T_CELL: 0446 return i18n("Cell"); 0447 case MAT_T_STRUCT: 0448 return i18n("Struct"); 0449 case MAT_T_ARRAY: 0450 return i18n("Array"); 0451 case MAT_T_FUNCTION: 0452 return i18n("Function"); 0453 } 0454 0455 return i18n("Undefined"); 0456 } 0457 0458 AbstractColumn::ColumnMode MatioFilterPrivate::classMode(matio_classes classType) { 0459 switch (classType) { 0460 case MAT_C_INT8: 0461 case MAT_C_UINT8: 0462 case MAT_C_INT16: 0463 case MAT_C_UINT16: 0464 case MAT_C_INT32: 0465 case MAT_C_UINT32: 0466 return AbstractColumn::ColumnMode::Integer; 0467 break; 0468 case MAT_C_INT64: 0469 case MAT_C_UINT64: 0470 return AbstractColumn::ColumnMode::BigInt; 0471 break; 0472 case MAT_C_CHAR: 0473 return AbstractColumn::ColumnMode::Text; 0474 break; 0475 case MAT_C_EMPTY: 0476 case MAT_C_CELL: 0477 case MAT_C_STRUCT: 0478 case MAT_C_OBJECT: 0479 case MAT_C_SPARSE: 0480 case MAT_C_DOUBLE: 0481 case MAT_C_SINGLE: 0482 case MAT_C_FUNCTION: 0483 case MAT_C_OPAQUE: 0484 break; 0485 } 0486 0487 return AbstractColumn::ColumnMode::Double; 0488 } 0489 0490 AbstractColumn::ColumnMode MatioFilterPrivate::typeMode(matio_types dataType) { 0491 switch (dataType) { 0492 case MAT_T_INT8: 0493 case MAT_T_UINT8: 0494 case MAT_T_INT16: 0495 case MAT_T_UINT16: 0496 case MAT_T_INT32: 0497 case MAT_T_UINT32: 0498 return AbstractColumn::ColumnMode::Integer; 0499 break; 0500 case MAT_T_INT64: 0501 case MAT_T_UINT64: 0502 return AbstractColumn::ColumnMode::BigInt; 0503 break; 0504 case MAT_T_SINGLE: 0505 case MAT_T_DOUBLE: 0506 case MAT_T_UNKNOWN: 0507 case MAT_T_MATRIX: 0508 case MAT_T_COMPRESSED: 0509 case MAT_T_UTF8: 0510 case MAT_T_UTF16: 0511 case MAT_T_UTF32: 0512 case MAT_T_STRING: 0513 case MAT_T_CELL: 0514 case MAT_T_STRUCT: 0515 case MAT_T_ARRAY: 0516 case MAT_T_FUNCTION: 0517 break; 0518 } 0519 0520 return AbstractColumn::ColumnMode::Double; 0521 } 0522 0523 #endif 0524 0525 /*! 0526 parses the content of the file \c fileName 0527 */ 0528 void MatioFilterPrivate::parse(const QString& fileName) { 0529 #ifdef HAVE_MATIO 0530 DEBUG(Q_FUNC_INFO << ", fileName = " << qPrintable(fileName)); 0531 0532 mat_t* matfp = Mat_Open(qPrintable(fileName), MAT_ACC_RDONLY); 0533 if (!matfp) { 0534 DEBUG(Q_FUNC_INFO << ", ERROR getting file info") 0535 return; 0536 } 0537 0538 // get names of all vars 0539 char** dir = Mat_GetDir(matfp, &varCount); 0540 DEBUG(Q_FUNC_INFO << ", found " << varCount << " vars") 0541 0542 varsInfo.clear(); 0543 for (size_t i = 0; i < varCount; ++i) { 0544 if (dir[i]) { 0545 QStringList info; 0546 0547 // name 0548 info << QLatin1String(dir[i]); 0549 // Mat_VarReadInfo() does not determine the data type of sparse 0550 // Don't use Mat_VarRead(matfp, dir[i]). It searches the whole file for every var 0551 matvar_t* var = Mat_VarReadNext(matfp); 0552 0553 // rank 0554 const int rank = var->rank; 0555 info << QString::number(rank); 0556 0557 // dims 0558 QString dims; 0559 for (int j = 0; j < rank; j++) { 0560 if (j > 0) 0561 dims += QStringLiteral(", "); 0562 dims += QString::number(var->dims[j]); 0563 } 0564 info << dims; 0565 0566 // class_type 0567 info << className(var->class_type); 0568 0569 // data_type 0570 info << typeName(var->data_type); 0571 0572 // complex/logical 0573 if (var->isComplex) 0574 info << i18n("Yes"); 0575 else 0576 info << i18n("No"); 0577 if (var->isLogical) 0578 info << i18n("Yes"); 0579 else 0580 info << i18n("No"); 0581 0582 Mat_VarFree(var); 0583 varsInfo.append(info); 0584 } 0585 } 0586 Mat_Close(matfp); 0587 #else 0588 Q_UNUSED(fileName) 0589 #endif 0590 } 0591 0592 /*! 0593 reads the content of the current selected variable from file \c fileName to the data source \c dataSource. 0594 (Not used for preview) 0595 Uses the settings defined in the data source. 0596 */ 0597 void MatioFilterPrivate::readDataFromFile(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode) { 0598 PERFTRACE(QLatin1String(Q_FUNC_INFO)); 0599 0600 if (currentVarName.isEmpty()) { 0601 DEBUG(Q_FUNC_INFO << ", no variable selected"); 0602 return; 0603 } 0604 0605 QDEBUG(Q_FUNC_INFO << ", selected var names:" << selectedVarNames) 0606 #ifdef HAVE_MATIO 0607 // open file only once 0608 if (!selectedVarNames.isEmpty()) 0609 matfp = Mat_Open(qPrintable(fileName), MAT_ACC_RDONLY); 0610 #endif 0611 for (const auto& var : selectedVarNames) { 0612 currentVarName = var; 0613 readCurrentVar(fileName, dataSource, importMode); 0614 importMode = AbstractFileFilter::ImportMode::Append; // append other vars 0615 } 0616 #ifdef HAVE_MATIO 0617 if (matfp) { // only if opened 0618 Mat_Close(matfp); 0619 matfp = nullptr; 0620 } 0621 #endif 0622 } 0623 0624 /*! 0625 reads the content of the current variable in the file \c fileName to a string (for preview) or to the data source. 0626 */ 0627 QVector<QStringList> 0628 MatioFilterPrivate::readCurrentVar(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode, size_t lines) { 0629 PERFTRACE(QLatin1String(Q_FUNC_INFO)); 0630 QVector<QStringList> dataStrings; 0631 0632 if (currentVarName.isEmpty()) { 0633 DEBUG(Q_FUNC_INFO << ", WARNING: current var name is empty!") 0634 return dataStrings << (QStringList() << i18n("No variable selected")); 0635 } 0636 DEBUG(Q_FUNC_INFO << ", current variable: " << STDSTRING(currentVarName)); 0637 0638 #ifdef HAVE_MATIO 0639 bool openedFile = false; 0640 if (!matfp) { // file not open 0641 matfp = Mat_Open(qPrintable(fileName), MAT_ACC_RDONLY); 0642 openedFile = true; 0643 } 0644 if (!matfp) // open failed 0645 return dataStrings << (QStringList() << i18n("File not found")); 0646 0647 // read info and data 0648 matvar_t* var = Mat_VarReadNext(matfp); // try next first (faster) 0649 if (QLatin1String(var->name) != currentVarName) 0650 var = Mat_VarRead(matfp, qPrintable(currentVarName)); 0651 // else 0652 // DEBUG(Q_FUNC_INFO << ", was NEXT!") 0653 if (!var) 0654 return dataStrings << (QStringList() << i18n("Variable not found")); 0655 if (!var->data) 0656 return dataStrings << (QStringList() << i18n("Variable contains no data")); 0657 0658 // DEBUG(Q_FUNC_INFO << ", start/end row = " << startRow << '/' << endRow) 0659 // DEBUG(Q_FUNC_INFO << ", start/end col = " << startColumn << '/' << endColumn) 0660 0661 size_t actualRows = 0, actualCols = 0; 0662 int columnOffset = 0; 0663 std::vector<void*> dataContainer; 0664 QStringList vectorNames; 0665 if (var->rank == 2) { // rank is always >= 2 0666 // read data 0667 size_t rows = var->dims[0], cols = var->dims[1]; 0668 if (var->class_type == MAT_C_CELL) 0669 cols = var->nbytes / var->data_size; 0670 else if (rows == 1) { // only one row: read as column 0671 rows = cols; 0672 cols = 1; 0673 } 0674 size_t actualEndRow = (endRow == -1 || endRow > (int)rows) ? rows : endRow; 0675 actualRows = actualEndRow - startRow + 1; 0676 size_t actualEndColumn = (endColumn == -1 || endColumn > (int)cols) ? cols : endColumn; 0677 actualCols = actualEndColumn - startColumn + 1; 0678 if (var->class_type == MAT_C_STRUCT) { 0679 if (endRow != -1) 0680 actualRows = endRow - startRow + 1; 0681 } else if (var->class_type == MAT_C_CELL) { // calculated later 0682 actualEndRow = 0; 0683 actualRows = 0; 0684 } 0685 // DEBUG(Q_FUNC_INFO << ", start row = " << startRow << ", actual end row = " << actualEndRow << ", actual rows = " << actualRows) 0686 // DEBUG(Q_FUNC_INFO << ", start col = " << startColumn << ", actual end col = " << actualEndColumn << ", actual cols = " << actualCols) 0687 0688 if (lines == 0) 0689 lines = actualRows; 0690 // double the number of cols for complex data (not for CELL or STRUCT) 0691 if (var->isComplex && var->class_type != MAT_C_CELL && var->class_type != MAT_C_STRUCT) { 0692 if (endColumn == -1) { 0693 actualCols *= 2; 0694 actualEndColumn *= 2; 0695 } 0696 for (size_t j = startColumn - 1; j < actualEndColumn; j++) { 0697 if (j % 2) 0698 vectorNames << QLatin1String("Im ") + QString::number(j / 2 + 1); 0699 else 0700 vectorNames << QLatin1String("Re ") + QString::number(j / 2 + 1); 0701 } 0702 } 0703 0704 // column modes 0705 QVector<AbstractColumn::ColumnMode> columnModes; 0706 columnModes.resize(actualCols); 0707 0708 // A: set column modes 0709 switch (var->class_type) { 0710 case MAT_C_CHAR: 0711 case MAT_C_INT8: 0712 case MAT_C_UINT8: 0713 case MAT_C_INT16: 0714 case MAT_C_UINT16: 0715 case MAT_C_INT32: 0716 case MAT_C_UINT32: 0717 for (auto& col : columnModes) 0718 col = AbstractColumn::ColumnMode::Integer; 0719 break; 0720 case MAT_C_INT64: 0721 case MAT_C_UINT64: 0722 for (auto& col : columnModes) 0723 col = AbstractColumn::ColumnMode::BigInt; 0724 break; 0725 case MAT_C_DOUBLE: 0726 case MAT_C_SINGLE: 0727 for (auto& col : columnModes) 0728 col = AbstractColumn::ColumnMode::Double; 0729 break; 0730 case MAT_C_EMPTY: 0731 return dataStrings << (QStringList() << i18n("Empty")); 0732 break; 0733 case MAT_C_CELL: { 0734 DEBUG(Q_FUNC_INFO << ", found CELL. name = " << var->name << ", nbytes = " << var->nbytes << ", size = " << var->data_size) 0735 // Each element of the cell array can be a different type: one column per cell 0736 if (var->nbytes == 0 || var->data_size == 0 || var->data == nullptr) 0737 break; 0738 // const int ncells = var->nbytes / var->data_size; 0739 // DEBUG(Q_FUNC_INFO << ", found " << ncells << " cells") 0740 columnModes.resize(actualCols); 0741 0742 // find out number of rows 0743 for (size_t i = 0; i < actualCols; i++) { 0744 matvar_t* cell = Mat_VarGetCell(var, i + startColumn - 1); 0745 if (cell->rank == 2 && cell->dims[0] <= 1) { // read only rank 2 and cells with one row, omit strings 0746 if (rows < cell->dims[1] && cell->class_type != MAT_C_CHAR) // find max row count 0747 rows = cell->dims[1]; 0748 0749 if (cell->name) 0750 vectorNames << QLatin1String(cell->name); 0751 else 0752 vectorNames << QLatin1String("Column ") + QString::number(i + 1); 0753 0754 auto mode = classMode(cell->class_type); 0755 if (dynamic_cast<Matrix*>(dataSource) && mode == AbstractColumn::ColumnMode::Text) // text not supported for matrix 0756 mode = AbstractColumn::ColumnMode::Double; 0757 0758 columnModes[i] = mode; 0759 } 0760 } 0761 // calculate from startRow and endRow 0762 actualEndRow = (endRow == -1 || endRow > (int)rows) ? rows : endRow; 0763 actualRows = actualEndRow - startRow + 1; 0764 DEBUG(Q_FUNC_INFO << ", start row = " << startRow << ", actual end row = " << actualEndRow << ", actual rows = " << actualRows) 0765 break; 0766 } 0767 case MAT_C_SPARSE: 0768 DEBUG(Q_FUNC_INFO << ", found SPARSE. name = " << var->name << ", type = " << STDSTRING(typeName(var->data_type)) << ", nbytes = " << var->nbytes 0769 << ", size = " << var->data_size) 0770 DEBUG(Q_FUNC_INFO << ", rank " << var->rank << ", dim = " << var->dims[0] << " x " << var->dims[1]) 0771 0772 if (dataSource) { 0773 columnModes.resize(actualCols); 0774 auto mode = typeMode(var->data_type); 0775 for (size_t i = 0; i < actualCols; i++) 0776 columnModes[i] = mode; 0777 } 0778 break; 0779 case MAT_C_STRUCT: { 0780 DEBUG(Q_FUNC_INFO << ", found STRUCT. name = " << var->name << ", nbytes = " << var->nbytes << ", size = " << var->data_size) 0781 DEBUG(Q_FUNC_INFO << ", data type = " << STDSTRING(typeName(var->data_type)) << ", dims = " << var->dims[0] << " x " << var->dims[1]) 0782 const int nelem = var->dims[0] * var->dims[1]; 0783 const int nfields = Mat_VarGetNumberOfFields(var); 0784 DEBUG(Q_FUNC_INFO << ", nelements = " << nelem << ", nfields = " << nfields) 0785 if (endColumn == -1) 0786 endColumn = nfields; 0787 actualCols = endColumn - startColumn + 1; 0788 0789 if (nfields <= 0) 0790 return dataStrings << (QStringList() << i18n("Struct contains no fields")); 0791 0792 if (nelem < 1) { 0793 DEBUG(Q_FUNC_INFO << ", no elements") 0794 char* const* fieldnames = Mat_VarGetStructFieldnames(var); 0795 if (fieldnames) { 0796 for (int i = 0; i < nfields; i++) 0797 DEBUG(Q_FUNC_INFO << ", field " << i << " name = " << fieldnames[i]) 0798 } 0799 } 0800 0801 // set actualRows 0802 auto** fields = (matvar_t**)var->data; 0803 for (int i = startColumn - 1; i < std::min(nfields, endColumn); i++) { 0804 if (fields[i]->name) { 0805 // TODO: not needed when supporting complex column mode 0806 if (fields[i]->isComplex) 0807 vectorNames << QLatin1String(fields[i]->name) + QStringLiteral(" - Re") << QLatin1String(fields[i]->name) + QStringLiteral(" - Im"); 0808 else 0809 vectorNames << QLatin1String(fields[i]->name); 0810 } else 0811 vectorNames << QLatin1String("Column ") + QString::number(i); 0812 } 0813 for (int i = 0; i < nfields * nelem; i++) { 0814 const int field = i % nfields; 0815 if (field < startColumn - 1 || field > endColumn - 1) 0816 continue; 0817 0818 if (fields[i]->rank == 2) { 0819 DEBUG(Q_FUNC_INFO << ", dims = " << fields[i]->dims[0] << " x " << fields[i]->dims[1]) 0820 size_t size; 0821 if (fields[i]->class_type == MAT_C_CHAR) // read as string 0822 size = fields[i]->dims[0]; 0823 else { 0824 if (endRow == -1) 0825 size = fields[i]->dims[0] * fields[i]->dims[1] - startRow + 1; 0826 else 0827 size = std::min(fields[i]->dims[0] * fields[i]->dims[1], actualRows); 0828 } 0829 0830 if (actualRows < size) 0831 actualRows = size; 0832 } else 0833 DEBUG(Q_FUNC_INFO << " rank = " << fields[i]->rank) 0834 0835 // TODO: not needed when supporting complex column mode 0836 if (fields[i]->isComplex) // if complex: add column 0837 actualCols++; 0838 } 0839 DEBUG(Q_FUNC_INFO << ", Setting rows/cols to: " << actualRows << "/" << actualCols) 0840 if (dataSource) { 0841 columnModes.resize(actualCols); 0842 int index = 0; 0843 for (int i = startColumn - 1; i < std::min(nfields, endColumn); i++) { 0844 auto mode = classMode(fields[i]->class_type); 0845 if (dynamic_cast<Matrix*>(dataSource) && mode == AbstractColumn::ColumnMode::Text) // text not supported for matrix 0846 mode = AbstractColumn::ColumnMode::Double; 0847 0848 // TODO: not needed when supporting complex column mode 0849 if (fields[i]->isComplex) // additional column for complex 0850 columnModes[index++] = mode; 0851 columnModes[index++] = mode; 0852 } 0853 } else { // preview 0854 if (actualRows > lines) 0855 actualRows = lines; 0856 0857 dataStrings.resize(actualRows + 1); // + 1 for header 0858 for (auto& string : dataStrings) { 0859 string.reserve(actualCols); 0860 for (size_t j = 0; j < actualCols; j++) 0861 string << QString(); 0862 } 0863 } 0864 break; 0865 } 0866 case MAT_C_OBJECT: // not available (not supported by matio yet) 0867 DEBUG(Q_FUNC_INFO << ", found OBJECT. name = " << var->name << ", nbytes = " << var->nbytes << ", size = " << var->data_size) 0868 return dataStrings << (QStringList() << i18n("Not implemented yet")); 0869 case MAT_C_FUNCTION: // not available (not supported by matio yet) 0870 DEBUG(Q_FUNC_INFO << ", found FUNCTION. name = " << var->name << ", nbytes = " << var->nbytes << ", size = " << var->data_size) 0871 QDEBUG(Q_FUNC_INFO << ", data: " << (const char*)var->data) 0872 return dataStrings << (QStringList() << i18n("Not implemented yet")); 0873 case MAT_C_OPAQUE: 0874 return dataStrings << (QStringList() << i18n("Not implemented yet")); 0875 } 0876 0877 // prepare import 0878 if (dataSource) 0879 columnOffset = dataSource->prepareImport(dataContainer, importMode, actualRows, actualCols, vectorNames, columnModes); 0880 DEBUG(Q_FUNC_INFO << ", column offset = " << columnOffset) 0881 0882 // B: read data 0883 switch (var->class_type) { 0884 case MAT_C_CHAR: 0885 MAT_READ_VAR(char, int); 0886 break; 0887 case MAT_C_DOUBLE: 0888 MAT_READ_VAR(double, double); 0889 break; 0890 case MAT_C_SINGLE: 0891 MAT_READ_VAR(float, double); 0892 break; 0893 case MAT_C_INT8: 0894 MAT_READ_VAR(qint8, int); 0895 break; 0896 case MAT_C_UINT8: 0897 MAT_READ_VAR(quint8, int); 0898 break; 0899 case MAT_C_INT16: 0900 MAT_READ_VAR(qint16, int); 0901 break; 0902 case MAT_C_UINT16: 0903 MAT_READ_VAR(quint16, int); 0904 break; 0905 case MAT_C_INT32: 0906 MAT_READ_VAR(qint32, int); 0907 break; 0908 case MAT_C_UINT32: 0909 MAT_READ_VAR(quint32, int); 0910 break; 0911 case MAT_C_INT64: 0912 MAT_READ_VAR(qint64, qint64); 0913 break; 0914 case MAT_C_UINT64: 0915 MAT_READ_VAR(quint64, qint64); 0916 break; 0917 case MAT_C_EMPTY: 0918 break; 0919 case MAT_C_CELL: { 0920 if (var->nbytes == 0 || var->data_size == 0 || var->data == nullptr) 0921 break; 0922 0923 // TODO: complex not supported yet 0924 0925 for (size_t i = 0; i < actualCols; i++) { 0926 matvar_t* cell = Mat_VarGetCell(var, i + startColumn - 1); 0927 // cell->name can be NULL 0928 QString dims; 0929 for (int j = 0; j < cell->rank; j++) 0930 dims += QString::number(cell->dims[j]) + QStringLiteral(" "); 0931 DEBUG(Q_FUNC_INFO << ", cell " << i + 1 << " : class = " << STDSTRING(className(cell->class_type)) 0932 << ", type = " << STDSTRING(typeName(cell->data_type)) << ", rank = " << cell->rank << ", dims = " << STDSTRING(dims) 0933 << ", nbytes = " << cell->nbytes << ", size = " << cell->data_size) 0934 } 0935 0936 // read cell data (see MAT_READ_VAR) 0937 for (size_t i = 0; i < actualRows; i++) { 0938 QStringList row; 0939 for (size_t j = 0; j < actualCols; j++) { 0940 matvar_t* cell = Mat_VarGetCell(var, j + startColumn - 1); 0941 const size_t cellsize = cell->dims[1]; 0942 if (cell->rank == 2 && cell->dims[0] <= 1) { // read only rank 2 and cells with zero/one row 0943 switch (cell->class_type) { 0944 case MAT_C_CHAR: 0945 if (dataSource) { 0946 if (dynamic_cast<Matrix*>(dataSource)) { 0947 QDEBUG(Q_FUNC_INFO << ", WARNING: string import into matrix not supported.") 0948 continue; 0949 } 0950 if (i == 0) { // first line 0951 if (cell->data_type == MAT_T_UINT16 || cell->data_type == MAT_T_INT16) // valgrind: invalid read of size 2 0952 static_cast<QVector<QString>*>(dataContainer[j])->operator[](0) = QString::fromUtf16((const mat_uint16_t*)cell->data); 0953 else if (cell->data_type == MAT_T_UTF8) 0954 static_cast<QVector<QString>*>(dataContainer[j])->operator[](0) = QString::fromUtf8((const char*)cell->data); 0955 else 0956 static_cast<QVector<QString>*>(dataContainer[j])->operator[](0) = QLatin1String((const char*)cell->data); 0957 } 0958 } else { // preview 0959 if (i == 0) { // first line 0960 if (cell->data_type == MAT_T_UINT16 || cell->data_type == MAT_T_INT16) 0961 row << QString::fromUtf16((const mat_uint16_t*)cell->data); 0962 else if (cell->data_type == MAT_T_UTF8) 0963 row << QString::fromUtf8((const char*)cell->data); 0964 else 0965 row << QLatin1String((const char*)cell->data); 0966 } else 0967 row << QString(); 0968 } 0969 break; 0970 case MAT_C_DOUBLE: 0971 MAT_READ_CELL(double, double); 0972 break; 0973 case MAT_C_SINGLE: 0974 MAT_READ_CELL(float, double) 0975 break; 0976 case MAT_C_INT8: 0977 MAT_READ_CELL(qint8, int); 0978 break; 0979 case MAT_C_UINT8: 0980 MAT_READ_CELL(quint8, int); 0981 break; 0982 case MAT_C_INT16: 0983 MAT_READ_CELL(qint16, int); 0984 break; 0985 case MAT_C_UINT16: 0986 MAT_READ_CELL(quint16, int); 0987 break; 0988 case MAT_C_INT32: 0989 MAT_READ_CELL(qint32, int); 0990 break; 0991 case MAT_C_UINT32: 0992 MAT_READ_CELL(quint32, int); 0993 break; 0994 case MAT_C_INT64: 0995 MAT_READ_CELL(qint64, qint64); 0996 break; 0997 case MAT_C_UINT64: 0998 MAT_READ_CELL(quint64, qint64); 0999 break; 1000 case MAT_C_CELL: 1001 case MAT_C_STRUCT: 1002 case MAT_C_OBJECT: 1003 case MAT_C_SPARSE: 1004 case MAT_C_FUNCTION: 1005 case MAT_C_OPAQUE: 1006 DEBUG(Q_FUNC_INFO << ", class type \"" << STDSTRING(className(cell->class_type)) << "\" not supported yet") 1007 break; 1008 case MAT_C_EMPTY: 1009 break; 1010 } 1011 } 1012 } 1013 dataStrings << row; 1014 } 1015 break; 1016 } 1017 case MAT_C_SPARSE: { 1018 // TODO: not needed when supporting complex column mode 1019 if (var->isComplex && !dataSource) { // header for preview 1020 QStringList row; 1021 for (size_t j = startColumn - 1; j < actualEndColumn; j++) 1022 if (j % 2) 1023 row << QLatin1String("Im ") + QString::number(j / 2 + 1); 1024 else 1025 row << QLatin1String("Re ") + QString::number(j / 2 + 1); 1026 dataStrings << row; 1027 } 1028 1029 auto* sparse = (mat_sparse_t*)var->data; 1030 size_t stride = Mat_SizeOf(var->data_type); 1031 // DEBUG(Q_FUNC_INFO << ", stride = " << stride << ", njc = " << sparse->njc << ", ndata = " << sparse->ndata) 1032 1033 switch (var->data_type) { 1034 case MAT_T_INT8: 1035 MAT_READ_SPARSE(qint8, int) 1036 break; 1037 case MAT_T_UINT8: 1038 MAT_READ_SPARSE(quint8, int) 1039 break; 1040 case MAT_T_INT16: 1041 MAT_READ_SPARSE(qint16, int) 1042 break; 1043 case MAT_T_UINT16: 1044 MAT_READ_SPARSE(quint16, int) 1045 break; 1046 case MAT_T_INT32: 1047 MAT_READ_SPARSE(qint32, int) 1048 break; 1049 case MAT_T_UINT32: 1050 MAT_READ_SPARSE(quint32, int) 1051 break; 1052 case MAT_T_INT64: 1053 MAT_READ_SPARSE(qint64, qint64) 1054 break; 1055 case MAT_T_UINT64: 1056 MAT_READ_SPARSE(quint64, qint64) 1057 break; 1058 case MAT_T_SINGLE: 1059 MAT_READ_SPARSE(float, double) 1060 break; 1061 case MAT_T_DOUBLE: 1062 MAT_READ_SPARSE(double, double) 1063 break; 1064 case MAT_T_MATRIX: 1065 case MAT_T_CELL: 1066 case MAT_T_STRUCT: 1067 case MAT_T_FUNCTION: 1068 case MAT_T_COMPRESSED: 1069 case MAT_T_UTF8: 1070 case MAT_T_UTF16: 1071 case MAT_T_UTF32: 1072 case MAT_T_STRING: 1073 case MAT_T_ARRAY: 1074 case MAT_T_UNKNOWN: 1075 DEBUG(Q_FUNC_INFO << ", data type " << var->data_type << " not supported yet") 1076 break; 1077 } 1078 1079 break; 1080 } 1081 case MAT_C_STRUCT: { 1082 const int nelem = var->dims[0] * var->dims[1]; 1083 const int nfields = Mat_VarGetNumberOfFields(var); 1084 1085 if (nelem < 1) { 1086 DEBUG(Q_FUNC_INFO << ", WARNING: nr of elements is zero") 1087 break; 1088 } 1089 1090 DEBUG(Q_FUNC_INFO << ", Reading data ...") 1091 auto** fields = (matvar_t**)var->data; 1092 1093 if (!dataSource) 1094 dataStrings[0] = vectorNames; 1095 1096 int colIndex = 1; // count cols (only needed since complex uses two cols atm) 1097 1098 for (int i = 0; i < nfields * nelem; i++) { 1099 if (fields[i]->rank > 2) { 1100 DEBUG(Q_FUNC_INFO << " rank = " << fields[i]->rank << " not supported") 1101 continue; 1102 } 1103 const int field = i % nfields; 1104 if (field < startColumn - 1 || field > endColumn - 1) 1105 continue; 1106 if (field == startColumn - 1) 1107 colIndex = 0; 1108 #ifndef NDEBUG 1109 const int elem = i / nfields; 1110 DEBUG(Q_FUNC_INFO << ", var " << i + 1 << "(field " << field + 1 << ", elem " << elem + 1 << "): name = " << fields[i]->name 1111 << ", type = " << STDSTRING(className(fields[i]->class_type))) 1112 #endif 1113 switch (fields[i]->class_type) { 1114 case MAT_C_INT8: 1115 MAT_READ_STRUCT(qint8); 1116 break; 1117 case MAT_C_UINT8: 1118 MAT_READ_STRUCT(quint8); 1119 break; 1120 case MAT_C_INT16: 1121 MAT_READ_STRUCT(qint16); 1122 break; 1123 case MAT_C_UINT16: 1124 MAT_READ_STRUCT(quint16); 1125 break; 1126 case MAT_C_INT32: 1127 MAT_READ_STRUCT(qint32); 1128 break; 1129 case MAT_C_UINT32: 1130 MAT_READ_STRUCT(quint32); 1131 break; 1132 case MAT_C_INT64: 1133 MAT_READ_STRUCT(qint64); 1134 break; 1135 case MAT_C_UINT64: 1136 MAT_READ_STRUCT(quint64); 1137 break; 1138 case MAT_C_SINGLE: 1139 MAT_READ_STRUCT(float); 1140 break; 1141 case MAT_C_DOUBLE: 1142 MAT_READ_STRUCT(double); 1143 break; 1144 case MAT_C_CHAR: 1145 if (dynamic_cast<Matrix*>(dataSource)) { 1146 QDEBUG(Q_FUNC_INFO << ", WARNING: string import into matrix not supported.") 1147 break; 1148 } 1149 1150 if (fields[i]->rank == 2) 1151 DEBUG(Q_FUNC_INFO << " rank = 2 (" << fields[i]->dims[0] << " x " << fields[i]->dims[1] << ")") 1152 else 1153 DEBUG(Q_FUNC_INFO << " rank = " << fields[i]->rank) 1154 1155 if (fields[i]->data_type == MAT_T_UINT16 || fields[i]->data_type == MAT_T_INT16) { 1156 auto* data = (mat_uint16_t*)fields[i]->data; 1157 1158 QString s = QString::fromUtf16(data); 1159 DEBUG(Q_FUNC_INFO << ", UTF16 data: \"" << STDSTRING(s) << "\"") 1160 // TODO: row 1161 if (dataSource) 1162 (*static_cast<QVector<QString>*>(dataContainer[colIndex]))[0] = s; 1163 else 1164 dataStrings[1][colIndex] = s; 1165 } else { 1166 char* data = (char*)fields[i]->data; 1167 if (fields[i]->data_type == MAT_T_UTF8) { 1168 QString s; 1169 if (fields[i]->rank == 2) 1170 s = QString::fromUtf8(data, fields[i]->dims[1]); 1171 else 1172 s = QString::fromUtf8(data); 1173 DEBUG(Q_FUNC_INFO << ", UTF8 data: \"" << STDSTRING(s) << "\"") 1174 // TODO: row 1175 if (dataSource) 1176 (*static_cast<QVector<QString>*>(dataContainer[colIndex]))[0] = s; 1177 else 1178 dataStrings[1][colIndex] = s; 1179 } else { 1180 DEBUG(Q_FUNC_INFO << ", STRING data: \"" << STDSTRING(QString::fromLatin1(data)) << "\"") 1181 // TODO: row 1182 if (dataSource) 1183 (*static_cast<QVector<QString>*>(dataContainer[colIndex]))[0] = QLatin1String(data); 1184 else 1185 dataStrings[1][colIndex] = QLatin1String(data); 1186 } 1187 } 1188 break; 1189 case MAT_C_CELL: 1190 case MAT_C_STRUCT: 1191 case MAT_C_OBJECT: 1192 case MAT_C_SPARSE: 1193 case MAT_C_FUNCTION: 1194 case MAT_C_OPAQUE: 1195 DEBUG(Q_FUNC_INFO << ", not support struct field class type " << STDSTRING(className(fields[i]->class_type))) 1196 break; 1197 case MAT_C_EMPTY: 1198 break; 1199 } 1200 1201 colIndex++; 1202 } 1203 break; 1204 } 1205 case MAT_C_OBJECT: // unsupported (s.a.) 1206 case MAT_C_FUNCTION: // unsupported (s.a.) 1207 case MAT_C_OPAQUE: // ??? 1208 break; 1209 } 1210 } 1211 if (var->rank > 2) // TODO 1212 return dataStrings << (QStringList() << i18n("Not implemented yet")); 1213 1214 Mat_VarFree(var); 1215 if (openedFile) { 1216 Mat_Close(matfp); 1217 matfp = nullptr; 1218 } 1219 1220 if (dataSource) 1221 dataSource->finalizeImport(columnOffset, 1, actualCols, QString(), importMode); 1222 #else 1223 Q_UNUSED(fileName) 1224 Q_UNUSED(dataSource) 1225 Q_UNUSED(importMode) 1226 Q_UNUSED(lines) 1227 #endif 1228 1229 return dataStrings; 1230 } 1231 1232 /*! 1233 writes the content of \c dataSource to the file \c fileName. 1234 */ 1235 void MatioFilterPrivate::write(const QString& /*fileName*/, AbstractDataSource* /*dataSource*/) { 1236 // TODO: writing MAT files not implemented yet 1237 } 1238 1239 // ############################################################################## 1240 // ################## Serialization/Deserialization ########################### 1241 // ############################################################################## 1242 1243 /*! 1244 Saves as XML. 1245 */ 1246 void MatioFilter::save(QXmlStreamWriter* writer) const { 1247 writer->writeStartElement(QStringLiteral("matioFilter")); 1248 writer->writeEndElement(); 1249 } 1250 1251 /*! 1252 Loads from XML. 1253 */ 1254 bool MatioFilter::load(XmlStreamReader*) { 1255 return true; 1256 }