File indexing completed on 2024-06-16 03:42:34

0001 /*
0002     File                 : ColumnPrivate.cpp
0003     Project              : AbstractColumn
0004     Description          : Private data class of Column
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2007-2008 Tilman Benkert <thzs@gmx.net>
0007     SPDX-FileCopyrightText: 2012-2022 Alexander Semke <alexander.semke@web.de>
0008     SPDX-FileCopyrightText: 2017-2022 Stefan Gerlach <stefan.gerlach@uni.kn>
0009 
0010     SPDX-License-Identifier: GPL-2.0-or-later
0011 */
0012 
0013 #include "ColumnPrivate.h"
0014 #include "Column.h"
0015 #include "ColumnStringIO.h"
0016 #include "backend/core/datatypes/filter.h"
0017 #include "backend/gsl/ExpressionParser.h"
0018 #include "backend/lib/trace.h"
0019 #include "backend/spreadsheet/Spreadsheet.h"
0020 
0021 #include "backend/nsl/nsl_stats.h"
0022 #include <gsl/gsl_math.h>
0023 #include <gsl/gsl_statistics.h>
0024 
0025 #include "functions.h"
0026 
0027 #include <array>
0028 #include <unordered_map>
0029 
0030 namespace {
0031 template<typename T>
0032 int indexForValueCommon(const T* obj,
0033                         double x,
0034                         const std::function<AbstractColumn::ColumnMode(const T*)> columnMode,
0035                         const std::function<int(const T*)> rowCount,
0036                         const std::function<double(const T*, int)> valueAt,
0037                         const std::function<QDateTime(const T*, int)> dateTimeAt,
0038                         const std::function<AbstractColumn::Properties(const T*)> properties,
0039                         const std::function<bool(const T*, int)> isValid,
0040                         const std::function<bool(const T*, int)> isMasked) {
0041     int rc = rowCount(obj);
0042     double prevValue = 0;
0043     qint64 prevValueDateTime = 0;
0044     auto mode = columnMode(obj);
0045     auto property = properties(obj);
0046     if (property == Column::Properties::MonotonicIncreasing || property == Column::Properties::MonotonicDecreasing) {
0047         // bisects the index every time, so it is possible to find the value in log_2(rowCount) steps
0048         bool increase = (property != Column::Properties::MonotonicDecreasing);
0049 
0050         int lowerIndex = 0;
0051         int higherIndex = rc - 1;
0052 
0053         unsigned int maxSteps = Column::calculateMaxSteps(static_cast<unsigned int>(rc)) + 1;
0054 
0055         switch (mode) {
0056         case Column::ColumnMode::Double:
0057         case Column::ColumnMode::Integer:
0058         case Column::ColumnMode::BigInt:
0059             for (unsigned int i = 0; i < maxSteps; i++) { // so no log_2(rowCount) needed
0060                 int index = lowerIndex + round(static_cast<double>(higherIndex - lowerIndex) / 2);
0061                 double value = valueAt(obj, index);
0062 
0063                 if (higherIndex - lowerIndex < 2) {
0064                     if (std::abs(valueAt(obj, lowerIndex) - x) < std::abs(valueAt(obj, higherIndex) - x))
0065                         index = lowerIndex;
0066                     else
0067                         index = higherIndex;
0068 
0069                     return index;
0070                 }
0071 
0072                 if (value > x && increase)
0073                     higherIndex = index;
0074                 else if (value >= x && !increase)
0075                     lowerIndex = index;
0076                 else if (value <= x && increase)
0077                     lowerIndex = index;
0078                 else if (value < x && !increase)
0079                     higherIndex = index;
0080             }
0081             break;
0082         case Column::ColumnMode::Text:
0083             break;
0084         case Column::ColumnMode::DateTime:
0085         case Column::ColumnMode::Month:
0086         case Column::ColumnMode::Day: {
0087             qint64 xInt64 = static_cast<qint64>(x);
0088             for (unsigned int i = 0; i < maxSteps; i++) { // so no log_2(rowCount) needed
0089                 int index = lowerIndex + round(static_cast<double>(higherIndex - lowerIndex) / 2);
0090                 qint64 value = dateTimeAt(obj, index).toMSecsSinceEpoch();
0091 
0092                 if (higherIndex - lowerIndex < 2) {
0093                     if (std::abs(dateTimeAt(obj, lowerIndex).toMSecsSinceEpoch() - xInt64)
0094                         < std::abs(dateTimeAt(obj, higherIndex).toMSecsSinceEpoch() - xInt64))
0095                         index = lowerIndex;
0096                     else
0097                         index = higherIndex;
0098 
0099                     return index;
0100                 }
0101 
0102                 if (value > xInt64 && increase)
0103                     higherIndex = index;
0104                 else if (value >= xInt64 && !increase)
0105                     lowerIndex = index;
0106                 else if (value <= xInt64 && increase)
0107                     lowerIndex = index;
0108                 else if (value < xInt64 && !increase)
0109                     higherIndex = index;
0110             }
0111         }
0112         }
0113 
0114     } else if (property == Column::Properties::Constant) {
0115         if (rc > 0)
0116             return 0;
0117         else
0118             return -1;
0119     } else {
0120         // naiv way
0121         int index = 0;
0122         switch (mode) {
0123         case Column::ColumnMode::Double:
0124         case Column::ColumnMode::Integer:
0125         case Column::ColumnMode::BigInt:
0126             for (int row = 0; row < rc; row++) {
0127                 if (!isValid(obj, row) || isMasked(obj, row))
0128                     continue;
0129                 if (row == 0)
0130                     prevValue = valueAt(obj, row);
0131 
0132                 double value = valueAt(obj, row);
0133                 if (std::abs(value - x) <= std::abs(prevValue - x)) { // <= prevents also that row - 1 become < 0
0134                     prevValue = value;
0135                     index = row;
0136                 }
0137             }
0138             return index;
0139         case Column::ColumnMode::Text:
0140             break;
0141         case Column::ColumnMode::DateTime:
0142         case Column::ColumnMode::Month:
0143         case Column::ColumnMode::Day: {
0144             qint64 xInt64 = static_cast<qint64>(x);
0145             for (int row = 0; row < rc; row++) {
0146                 if (!isValid(obj, row) || isMasked(obj, row))
0147                     continue;
0148 
0149                 if (row == 0)
0150                     prevValueDateTime = dateTimeAt(obj, row).toMSecsSinceEpoch();
0151 
0152                 qint64 value = dateTimeAt(obj, row).toMSecsSinceEpoch();
0153                 if (std::abs(value - xInt64) <= std::abs(prevValueDateTime - xInt64)) { // "<=" prevents also that row - 1 become < 0
0154                     prevValueDateTime = value;
0155                     index = row;
0156                 }
0157             }
0158             return index;
0159         }
0160         }
0161     }
0162     return -1;
0163 }
0164 } // anonymous namespace
0165 
0166 void ColumnPrivate::ValueLabels::setMode(AbstractColumn::ColumnMode mode) {
0167     if (!initialized())
0168         m_mode = mode;
0169     else
0170         migrateLabels(mode);
0171 }
0172 
0173 bool ColumnPrivate::ValueLabels::init(AbstractColumn::ColumnMode mode) {
0174     if (initialized())
0175         return false;
0176 
0177     invalidateStatistics();
0178 
0179     m_mode = mode;
0180     switch (m_mode) {
0181     case AbstractColumn::ColumnMode::Double:
0182         m_labels = new QVector<Column::ValueLabel<double>>();
0183         break;
0184     case AbstractColumn::ColumnMode::Integer:
0185         m_labels = new QVector<Column::ValueLabel<int>>();
0186         break;
0187     case AbstractColumn::ColumnMode::BigInt:
0188         m_labels = new QVector<Column::ValueLabel<qint64>>();
0189         break;
0190     case AbstractColumn::ColumnMode::Text:
0191         m_labels = new QVector<Column::ValueLabel<QString>>();
0192         break;
0193     case AbstractColumn::ColumnMode::DateTime:
0194     case AbstractColumn::ColumnMode::Month:
0195     case AbstractColumn::ColumnMode::Day:
0196         m_labels = new QVector<Column::ValueLabel<QDateTime>>();
0197         break;
0198     }
0199     return true;
0200 }
0201 
0202 void ColumnPrivate::ValueLabels::deinit() {
0203     invalidateStatistics();
0204     if (m_labels) {
0205         switch (m_mode) {
0206         case AbstractColumn::ColumnMode::Double:
0207             delete cast_vector<double>();
0208             break;
0209         case AbstractColumn::ColumnMode::Integer:
0210             delete cast_vector<int>();
0211             break;
0212         case AbstractColumn::ColumnMode::BigInt:
0213             delete cast_vector<qint64>();
0214             break;
0215         case AbstractColumn::ColumnMode::Text:
0216             delete cast_vector<QString>();
0217             break;
0218         case AbstractColumn::ColumnMode::DateTime:
0219         case AbstractColumn::ColumnMode::Month:
0220         case AbstractColumn::ColumnMode::Day:
0221             delete cast_vector<QDateTime>();
0222             break;
0223         }
0224 
0225         m_labels = nullptr;
0226     }
0227 }
0228 
0229 AbstractColumn::ColumnMode ColumnPrivate::ValueLabels::mode() const {
0230     return m_mode;
0231 }
0232 AbstractColumn::Properties ColumnPrivate::ValueLabels::properties() const {
0233     return AbstractColumn::Properties::No; // Performance improvements not yet implemented
0234 }
0235 
0236 double ColumnPrivate::ValueLabels::valueAt(int index) const {
0237     if (!initialized())
0238         return 0;
0239 
0240     switch (m_mode) {
0241     case AbstractColumn::ColumnMode::Double:
0242         return cast_vector<double>()->at(index).value;
0243     case AbstractColumn::ColumnMode::Integer:
0244         return cast_vector<int>()->at(index).value;
0245     case AbstractColumn::ColumnMode::BigInt:
0246         return cast_vector<qint64>()->at(index).value;
0247     case AbstractColumn::ColumnMode::Text:
0248         return std::nan("0");
0249     case AbstractColumn::ColumnMode::DateTime:
0250     case AbstractColumn::ColumnMode::Month:
0251     case AbstractColumn::ColumnMode::Day:
0252         return cast_vector<QDateTime>()->at(index).value.toMSecsSinceEpoch();
0253     }
0254     Q_ASSERT(false);
0255     return std::nan("0");
0256 }
0257 
0258 QDateTime ColumnPrivate::ValueLabels::dateTimeAt(int index) const {
0259     if (!initialized())
0260         return QDateTime();
0261 
0262     switch (m_mode) {
0263     case AbstractColumn::ColumnMode::DateTime:
0264     case AbstractColumn::ColumnMode::Month:
0265     case AbstractColumn::ColumnMode::Day:
0266         return cast_vector<QDateTime>()->at(index).value;
0267     case AbstractColumn::ColumnMode::Double:
0268     case AbstractColumn::ColumnMode::Integer:
0269     case AbstractColumn::ColumnMode::BigInt:
0270     case AbstractColumn::ColumnMode::Text:
0271         return QDateTime();
0272     }
0273     Q_ASSERT(false);
0274     return QDateTime();
0275 }
0276 
0277 void ColumnPrivate::ValueLabels::migrateLabels(AbstractColumn::ColumnMode newMode) {
0278     switch (mode()) {
0279     case AbstractColumn::ColumnMode::Double:
0280         migrateDoubleTo(newMode);
0281         break;
0282     case AbstractColumn::ColumnMode::Integer:
0283         migrateIntTo(newMode);
0284         break;
0285     case AbstractColumn::ColumnMode::BigInt:
0286         migrateBigIntTo(newMode);
0287         break;
0288     case AbstractColumn::ColumnMode::Text:
0289         migrateTextTo(newMode);
0290         break;
0291     case AbstractColumn::ColumnMode::DateTime:
0292     case AbstractColumn::ColumnMode::Month:
0293     case AbstractColumn::ColumnMode::Day:
0294         migrateDateTimeTo(newMode);
0295         break;
0296     }
0297 }
0298 
0299 void ColumnPrivate::ValueLabels::migrateDoubleTo(AbstractColumn::ColumnMode newMode) {
0300     if (newMode == AbstractColumn::ColumnMode::Double)
0301         return;
0302 
0303     auto vector = *cast_vector<double>();
0304     deinit();
0305     init(newMode);
0306     switch (newMode) {
0307     case AbstractColumn::ColumnMode::Double:
0308         break; // Nothing to do
0309     case AbstractColumn::ColumnMode::Integer:
0310         for (const auto& value : vector)
0311             add((int)value.value, value.label);
0312         break;
0313     case AbstractColumn::ColumnMode::BigInt:
0314         for (const auto& value : vector)
0315             add((qint64)value.value, value.label);
0316         break;
0317     case AbstractColumn::ColumnMode::Text:
0318         for (const auto& value : vector)
0319             add(QString::number(value.value), value.label);
0320         break;
0321     case AbstractColumn::ColumnMode::DateTime:
0322     case AbstractColumn::ColumnMode::Month:
0323     case AbstractColumn::ColumnMode::Day:
0324         // Not possible
0325         // All value labels deleted
0326         break;
0327     }
0328 }
0329 
0330 void ColumnPrivate::ValueLabels::migrateIntTo(AbstractColumn::ColumnMode newMode) {
0331     if (newMode == AbstractColumn::ColumnMode::Integer)
0332         return;
0333 
0334     auto vector = *cast_vector<int>();
0335     deinit();
0336     init(newMode);
0337     switch (newMode) {
0338     case AbstractColumn::ColumnMode::Double:
0339         for (const auto& value : vector)
0340             add((double)value.value, value.label);
0341         break;
0342     case AbstractColumn::ColumnMode::Integer:
0343         // nothing to do
0344         break;
0345     case AbstractColumn::ColumnMode::BigInt:
0346         for (const auto& value : vector)
0347             add((qint64)value.value, value.label);
0348         break;
0349     case AbstractColumn::ColumnMode::Text:
0350         for (const auto& value : vector)
0351             add(QString::number(value.value), value.label);
0352         break;
0353     case AbstractColumn::ColumnMode::DateTime:
0354     case AbstractColumn::ColumnMode::Month:
0355     case AbstractColumn::ColumnMode::Day:
0356         // Not possible
0357         // All value labels deleted
0358         break;
0359     }
0360 }
0361 
0362 void ColumnPrivate::ValueLabels::migrateBigIntTo(AbstractColumn::ColumnMode newMode) {
0363     if (newMode == AbstractColumn::ColumnMode::BigInt)
0364         return;
0365 
0366     auto vector = *cast_vector<qint64>();
0367     deinit();
0368     init(newMode);
0369     switch (newMode) {
0370     case AbstractColumn::ColumnMode::Double:
0371         for (const auto& value : vector)
0372             add((double)value.value, value.label);
0373         break;
0374     case AbstractColumn::ColumnMode::Integer:
0375         for (const auto& value : vector)
0376             add((int)value.value, value.label);
0377         break;
0378     case AbstractColumn::ColumnMode::BigInt:
0379         // Nothing to do
0380         break;
0381     case AbstractColumn::ColumnMode::Text:
0382         for (const auto& value : vector)
0383             add(QString::number(value.value), value.label);
0384         break;
0385     case AbstractColumn::ColumnMode::DateTime:
0386     case AbstractColumn::ColumnMode::Month:
0387     case AbstractColumn::ColumnMode::Day:
0388         // Not possible
0389         // All value labels deleted
0390         break;
0391     }
0392 }
0393 
0394 void ColumnPrivate::ValueLabels::migrateTextTo(AbstractColumn::ColumnMode newMode) {
0395     if (newMode == AbstractColumn::ColumnMode::Text)
0396         return;
0397 
0398     auto vector = *cast_vector<QString>();
0399     deinit();
0400     init(newMode);
0401     switch (newMode) {
0402     case AbstractColumn::ColumnMode::Double: {
0403         for (const auto& value : vector) {
0404             bool ok;
0405             double v = value.value.toDouble(&ok);
0406             if (ok)
0407                 add(v, value.label);
0408         }
0409         break;
0410     }
0411     case AbstractColumn::ColumnMode::Integer: {
0412         for (const auto& value : vector) {
0413             bool ok;
0414             int v = value.value.toInt(&ok);
0415             if (ok)
0416                 add(v, value.label);
0417         }
0418         break;
0419     }
0420     case AbstractColumn::ColumnMode::BigInt: {
0421         for (const auto& value : vector) {
0422             bool ok;
0423             qint64 v = value.value.toLongLong(&ok);
0424             if (ok)
0425                 add(v, value.label);
0426         }
0427         break;
0428     }
0429     case AbstractColumn::ColumnMode::Text:
0430         // Nothing to do
0431         break;
0432     case AbstractColumn::ColumnMode::DateTime:
0433     case AbstractColumn::ColumnMode::Month:
0434     case AbstractColumn::ColumnMode::Day:
0435         // Not supported
0436         break;
0437     }
0438 }
0439 
0440 int ColumnPrivate::ValueLabels::indexForValue(double value) const {
0441     return indexForValueCommon<ValueLabels>(this,
0442                                             value,
0443                                             std::mem_fn(&ValueLabels::mode),
0444                                             std::mem_fn<int() const>(&ValueLabels::count),
0445                                             std::mem_fn(&ValueLabels::valueAt),
0446                                             std::mem_fn(&ValueLabels::dateTimeAt),
0447                                             std::mem_fn(&ValueLabels::properties),
0448                                             std::mem_fn<bool(int) const>(&ValueLabels::isValid),
0449                                             std::mem_fn<bool(int) const>(&ValueLabels::isMasked));
0450 }
0451 
0452 bool ColumnPrivate::ValueLabels::isValid(int) const {
0453     return true;
0454 }
0455 
0456 bool ColumnPrivate::ValueLabels::isMasked(int) const {
0457     return false;
0458 }
0459 
0460 QString ColumnPrivate::ValueLabels::labelAt(int index) const {
0461     if (!initialized())
0462         return QStringLiteral();
0463 
0464     switch (m_mode) {
0465     case AbstractColumn::ColumnMode::Double:
0466         return cast_vector<double>()->at(index).label;
0467     case AbstractColumn::ColumnMode::Integer:
0468         return cast_vector<int>()->at(index).label;
0469     case AbstractColumn::ColumnMode::BigInt:
0470         return cast_vector<qint64>()->at(index).label;
0471     case AbstractColumn::ColumnMode::Text:
0472         return cast_vector<QString>()->at(index).label;
0473     case AbstractColumn::ColumnMode::DateTime:
0474     case AbstractColumn::ColumnMode::Month:
0475     case AbstractColumn::ColumnMode::Day:
0476         return cast_vector<QDateTime>()->at(index).label;
0477     }
0478     Q_ASSERT(false);
0479     return QStringLiteral();
0480 }
0481 
0482 double ColumnPrivate::ValueLabels::minimum() {
0483     if (!m_statistics.available)
0484         recalculateStatistics();
0485     return m_statistics.minimum;
0486 }
0487 
0488 double ColumnPrivate::ValueLabels::maximum() {
0489     if (!m_statistics.available)
0490         recalculateStatistics();
0491     return m_statistics.maximum;
0492 }
0493 
0494 void ColumnPrivate::ValueLabels::recalculateStatistics() {
0495     m_statistics.available = false;
0496     m_statistics.minimum = INFINITY;
0497     m_statistics.maximum = -INFINITY;
0498 
0499     const int rowValuesSize = count();
0500     for (int row = 0; row < rowValuesSize; ++row) {
0501         const double val = valueAt(row);
0502         if (val < m_statistics.minimum)
0503             m_statistics.minimum = val;
0504         if (val > m_statistics.maximum)
0505             m_statistics.maximum = val;
0506     }
0507 
0508     m_statistics.available = true;
0509 }
0510 
0511 void ColumnPrivate::ValueLabels::invalidateStatistics() {
0512     m_statistics.available = false;
0513 }
0514 
0515 void ColumnPrivate::ValueLabels::migrateDateTimeTo(AbstractColumn::ColumnMode newMode) {
0516     if (newMode == AbstractColumn::ColumnMode::DateTime || newMode == AbstractColumn::ColumnMode::Day || newMode == AbstractColumn::ColumnMode::Month)
0517         return;
0518 
0519     // auto vector = *cast_vector<QDateTime>();
0520     deinit();
0521     init(newMode);
0522     // switch (newMode) {
0523     // case AbstractColumn::ColumnMode::Double: {
0524     //     // Not possible
0525     //     break;
0526     // }
0527     // case AbstractColumn::ColumnMode::Integer: {
0528     //     // Not possible
0529     //     break;
0530     // }
0531     // case AbstractColumn::ColumnMode::BigInt: {
0532     //     // Not possible
0533     //     break;
0534     // }
0535     // case AbstractColumn::ColumnMode::Text:
0536     //     // Not supported
0537     //     break;
0538     // case AbstractColumn::ColumnMode::DateTime:
0539     // case AbstractColumn::ColumnMode::Month:
0540     // case AbstractColumn::ColumnMode::Day:
0541     //     // Nothing to do
0542     //     break;
0543     // }
0544 }
0545 
0546 int ColumnPrivate::ValueLabels::count() const {
0547     if (!initialized())
0548         return 0;
0549 
0550     switch (m_mode) {
0551     case AbstractColumn::ColumnMode::Double:
0552         return cast_vector<double>()->count();
0553     case AbstractColumn::ColumnMode::Integer:
0554         return cast_vector<int>()->count();
0555     case AbstractColumn::ColumnMode::BigInt:
0556         return cast_vector<qint64>()->count();
0557     case AbstractColumn::ColumnMode::Text:
0558         return cast_vector<QString>()->count();
0559     case AbstractColumn::ColumnMode::DateTime:
0560     case AbstractColumn::ColumnMode::Month:
0561     case AbstractColumn::ColumnMode::Day:
0562         return cast_vector<QDateTime>()->count();
0563     }
0564     return 0;
0565 }
0566 
0567 int ColumnPrivate::ValueLabels::count(double min, double max) const {
0568     if (!initialized())
0569         return 0;
0570 
0571     min = qMin(min, max);
0572     max = qMax(min, max);
0573 
0574     int counter = 0;
0575     switch (m_mode) {
0576     case AbstractColumn::ColumnMode::Double: {
0577         const auto* data = cast_vector<double>();
0578         for (const auto& d : *data) {
0579             if (d.value >= min && d.value <= max)
0580                 counter++;
0581         }
0582         break;
0583     }
0584     case AbstractColumn::ColumnMode::Integer: {
0585         const auto* data = cast_vector<int>();
0586         for (const auto& d : *data) {
0587             if (d.value >= min && d.value <= max)
0588                 counter++;
0589         }
0590         break;
0591     }
0592     case AbstractColumn::ColumnMode::BigInt: {
0593         const auto* data = cast_vector<qint64>();
0594         for (const auto& d : *data) {
0595             if (d.value >= min && d.value <= max)
0596                 counter++;
0597         }
0598         break;
0599     }
0600     case AbstractColumn::ColumnMode::Text:
0601         return 0;
0602     case AbstractColumn::ColumnMode::DateTime:
0603     case AbstractColumn::ColumnMode::Month:
0604     case AbstractColumn::ColumnMode::Day: {
0605         const auto* data = cast_vector<QDateTime>();
0606         for (const auto& d : *data) {
0607             const auto value = d.value.toMSecsSinceEpoch();
0608             if (value >= min && value <= max)
0609                 counter++;
0610         }
0611         break;
0612     }
0613     }
0614     return counter;
0615 }
0616 
0617 void ColumnPrivate::ValueLabels::add(const QString& value, const QString& label) {
0618     if (initialized() && m_mode != AbstractColumn::ColumnMode::Text)
0619         return;
0620 
0621     init(AbstractColumn::ColumnMode::Text);
0622     invalidateStatistics();
0623     cast_vector<QString>()->append({value, label});
0624 }
0625 
0626 void ColumnPrivate::ValueLabels::add(const QDateTime& value, const QString& label) {
0627     if (initialized() && m_mode != AbstractColumn::ColumnMode::DateTime && m_mode != AbstractColumn::ColumnMode::Day
0628         && m_mode != AbstractColumn::ColumnMode::Month)
0629         return;
0630 
0631     init(AbstractColumn::ColumnMode::Month);
0632     invalidateStatistics();
0633     cast_vector<QDateTime>()->append({value, label});
0634 }
0635 
0636 void ColumnPrivate::ValueLabels::add(double value, const QString& label) {
0637     if (initialized() && m_mode != AbstractColumn::ColumnMode::Double)
0638         return;
0639 
0640     init(AbstractColumn::ColumnMode::Double);
0641     invalidateStatistics();
0642     cast_vector<double>()->append({value, label});
0643 }
0644 
0645 void ColumnPrivate::ValueLabels::add(int value, const QString& label) {
0646     if (initialized() && m_mode != AbstractColumn::ColumnMode::Integer)
0647         return;
0648 
0649     init(AbstractColumn::ColumnMode::Integer);
0650     invalidateStatistics();
0651     cast_vector<int>()->append({value, label});
0652 }
0653 
0654 void ColumnPrivate::ValueLabels::add(qint64 value, const QString& label) {
0655     if (initialized() && m_mode != AbstractColumn::ColumnMode::BigInt)
0656         return;
0657 
0658     init(AbstractColumn::ColumnMode::BigInt);
0659     invalidateStatistics();
0660     cast_vector<qint64>()->append({value, label});
0661 }
0662 
0663 void ColumnPrivate::ValueLabels::removeAll() {
0664     if (!initialized())
0665         return;
0666 
0667     deinit();
0668     init(m_mode);
0669 }
0670 
0671 void ColumnPrivate::ValueLabels::remove(const QString& key) {
0672     if (!initialized())
0673         return;
0674 
0675     invalidateStatistics();
0676     bool ok;
0677     switch (m_mode) {
0678     case AbstractColumn::ColumnMode::Double: {
0679         double value = QLocale().toDouble(key, &ok);
0680         if (!ok)
0681             return;
0682         remove<double>(value);
0683         break;
0684     }
0685     case AbstractColumn::ColumnMode::Integer: {
0686         int value = QLocale().toInt(key, &ok);
0687         if (!ok)
0688             return;
0689         remove<int>(value);
0690         break;
0691     }
0692     case AbstractColumn::ColumnMode::BigInt: {
0693         qint64 value = QLocale().toLongLong(key, &ok);
0694         if (!ok)
0695             return;
0696         remove<qint64>(value);
0697         break;
0698     }
0699     case AbstractColumn::ColumnMode::Text: {
0700         remove<QString>(key);
0701         break;
0702     }
0703     case AbstractColumn::ColumnMode::Month:
0704     case AbstractColumn::ColumnMode::Day:
0705     case AbstractColumn::ColumnMode::DateTime: {
0706         DateTime2StringFilter f;
0707         if (m_mode == AbstractColumn::ColumnMode::Month) {
0708             f.setFormat(QStringLiteral("MMMM"));
0709         } else {
0710             f.setFormat(QStringLiteral("dddd"));
0711         }
0712         const auto ref = QDateTime::fromString(key, f.format());
0713         remove<QDateTime>(ref);
0714         break;
0715     }
0716     }
0717 }
0718 
0719 const QVector<Column::ValueLabel<QString>>* ColumnPrivate::ValueLabels::textValueLabels() const {
0720     if (!initialized() || m_mode != AbstractColumn::ColumnMode::Text)
0721         return nullptr;
0722     return cast_vector<QString>();
0723 }
0724 
0725 const QVector<Column::ValueLabel<QDateTime>>* ColumnPrivate::ValueLabels::dateTimeValueLabels() const {
0726     if (!initialized()
0727         || (m_mode != AbstractColumn::ColumnMode::DateTime && m_mode != AbstractColumn::ColumnMode::Day && m_mode != AbstractColumn::ColumnMode::Month))
0728         return nullptr;
0729     return cast_vector<QDateTime>();
0730 }
0731 
0732 const QVector<Column::ValueLabel<double>>* ColumnPrivate::ValueLabels::valueLabels() const {
0733     if (!initialized() || m_mode != AbstractColumn::ColumnMode::Double)
0734         return nullptr;
0735     return cast_vector<double>();
0736 }
0737 
0738 const QVector<Column::ValueLabel<int>>* ColumnPrivate::ValueLabels::intValueLabels() const {
0739     if (!initialized() || m_mode != AbstractColumn::ColumnMode::Integer)
0740         return nullptr;
0741     return cast_vector<int>();
0742 }
0743 
0744 const QVector<Column::ValueLabel<qint64>>* ColumnPrivate::ValueLabels::bigIntValueLabels() const {
0745     if (!initialized() || m_mode != AbstractColumn::ColumnMode::BigInt)
0746         return nullptr;
0747     return cast_vector<qint64>();
0748 }
0749 
0750 // ######################################################################################################
0751 // ######################################################################################################
0752 // ######################################################################################################
0753 
0754 ColumnPrivate::ColumnPrivate(Column* owner, AbstractColumn::ColumnMode mode)
0755     : m_columnMode(mode)
0756     , m_owner(owner) {
0757     initIOFilters();
0758 }
0759 
0760 /**
0761  * \brief Special ctor (to be called from Column only!)
0762  */
0763 ColumnPrivate::ColumnPrivate(Column* owner, AbstractColumn::ColumnMode mode, void* data)
0764     : m_columnMode(mode)
0765     , m_data(data)
0766     , m_owner(owner) {
0767     initIOFilters();
0768 }
0769 
0770 /*!
0771  * initializes the interal vector for data. This is where the actual allocation on the heap is happening.
0772  * If \c resize is set to \false, the vector is not resized after its creation. This should be used
0773  * if there is already a vector created somewhere and the content of the column is going to be replaced
0774  * with the existing content where the memory was already allocated.
0775  */
0776 bool ColumnPrivate::initDataContainer(bool resize) {
0777     switch (m_columnMode) {
0778     case AbstractColumn::ColumnMode::Double: {
0779         auto* vec = new QVector<double>();
0780         try {
0781             if (resize)
0782                 vec->resize(m_rowCount);
0783         } catch (std::bad_alloc&) { return false; }
0784         vec->fill(std::numeric_limits<double>::quiet_NaN());
0785         m_data = vec;
0786         break;
0787     }
0788     case AbstractColumn::ColumnMode::Integer: {
0789         auto* vec = new QVector<int>();
0790         try {
0791             if (resize)
0792                 vec->resize(m_rowCount);
0793         } catch (std::bad_alloc&) { return false; }
0794         m_data = vec;
0795         break;
0796     }
0797     case AbstractColumn::ColumnMode::BigInt: {
0798         auto* vec = new QVector<qint64>();
0799         try {
0800             if (resize)
0801                 vec->resize(m_rowCount);
0802         } catch (std::bad_alloc&) { return false; }
0803         m_data = vec;
0804         break;
0805     }
0806     case AbstractColumn::ColumnMode::Text: {
0807         auto* vec = new QVector<QString>();
0808         try {
0809             if (resize)
0810                 vec->resize(m_rowCount);
0811         } catch (std::bad_alloc&) { return false; }
0812         m_data = vec;
0813         break;
0814     }
0815     case AbstractColumn::ColumnMode::DateTime:
0816     case AbstractColumn::ColumnMode::Month:
0817     case AbstractColumn::ColumnMode::Day: {
0818         auto* vec = new QVector<QDateTime>();
0819         try {
0820             if (resize)
0821                 vec->resize(m_rowCount);
0822         } catch (std::bad_alloc&) { return false; }
0823         m_data = vec;
0824         break;
0825     }
0826     }
0827 
0828     return true;
0829 }
0830 
0831 void ColumnPrivate::initIOFilters() {
0832     const auto numberLocale = QLocale();
0833     switch (m_columnMode) {
0834     case AbstractColumn::ColumnMode::Double:
0835         m_inputFilter = new String2DoubleFilter();
0836         m_inputFilter->setNumberLocale(numberLocale);
0837         m_outputFilter = new Double2StringFilter();
0838         m_outputFilter->setNumberLocale(numberLocale);
0839         break;
0840     case AbstractColumn::ColumnMode::Integer:
0841         m_inputFilter = new String2IntegerFilter();
0842         m_inputFilter->setNumberLocale(numberLocale);
0843         m_outputFilter = new Integer2StringFilter();
0844         m_outputFilter->setNumberLocale(numberLocale);
0845         break;
0846     case AbstractColumn::ColumnMode::BigInt:
0847         m_inputFilter = new String2BigIntFilter();
0848         m_inputFilter->setNumberLocale(numberLocale);
0849         m_outputFilter = new BigInt2StringFilter();
0850         m_outputFilter->setNumberLocale(numberLocale);
0851         break;
0852     case AbstractColumn::ColumnMode::Text:
0853         m_inputFilter = new SimpleCopyThroughFilter();
0854         m_outputFilter = new SimpleCopyThroughFilter();
0855         break;
0856     case AbstractColumn::ColumnMode::DateTime:
0857         m_inputFilter = new String2DateTimeFilter();
0858         m_outputFilter = new DateTime2StringFilter();
0859         break;
0860     case AbstractColumn::ColumnMode::Month:
0861         m_inputFilter = new String2MonthFilter();
0862         m_outputFilter = new DateTime2StringFilter();
0863         static_cast<DateTime2StringFilter*>(m_outputFilter)->setFormat(QStringLiteral("MMMM"));
0864         break;
0865     case AbstractColumn::ColumnMode::Day:
0866         m_inputFilter = new String2DayOfWeekFilter();
0867         m_outputFilter = new DateTime2StringFilter();
0868         static_cast<DateTime2StringFilter*>(m_outputFilter)->setFormat(QStringLiteral("dddd"));
0869         break;
0870     }
0871 
0872     connect(m_outputFilter, &AbstractSimpleFilter::formatChanged, m_owner, &Column::handleFormatChange);
0873 }
0874 
0875 ColumnPrivate::~ColumnPrivate() {
0876     deleteData();
0877 }
0878 
0879 void ColumnPrivate::deleteData() {
0880     if (!m_data)
0881         return;
0882 
0883     switch (m_columnMode) {
0884     case AbstractColumn::ColumnMode::Double:
0885         delete static_cast<QVector<double>*>(m_data);
0886         break;
0887     case AbstractColumn::ColumnMode::Integer:
0888         delete static_cast<QVector<int>*>(m_data);
0889         break;
0890     case AbstractColumn::ColumnMode::BigInt:
0891         delete static_cast<QVector<qint64>*>(m_data);
0892         break;
0893     case AbstractColumn::ColumnMode::Text:
0894         delete static_cast<QVector<QString>*>(m_data);
0895         break;
0896     case AbstractColumn::ColumnMode::DateTime:
0897     case AbstractColumn::ColumnMode::Month:
0898     case AbstractColumn::ColumnMode::Day:
0899         delete static_cast<QVector<QDateTime>*>(m_data);
0900         break;
0901     }
0902     m_data = nullptr;
0903 }
0904 
0905 AbstractColumn::ColumnMode ColumnPrivate::columnMode() const {
0906     return m_columnMode;
0907 }
0908 
0909 /**
0910  * \brief Set the column mode
0911  *
0912  * This sets the column mode and, if
0913  * necessary, converts it to another datatype.
0914  * Remark: setting the mode back to undefined (the
0915  * initial value) is not supported.
0916  */
0917 void ColumnPrivate::setColumnMode(AbstractColumn::ColumnMode mode) {
0918     DEBUG(Q_FUNC_INFO << ", " << ENUM_TO_STRING(AbstractColumn, ColumnMode, m_columnMode) << " -> " << ENUM_TO_STRING(AbstractColumn, ColumnMode, mode))
0919     if (mode == m_columnMode)
0920         return;
0921 
0922     void* old_data = m_data;
0923     // remark: the deletion of the old data will be done in the dtor of a command
0924 
0925     AbstractSimpleFilter *filter{nullptr}, *new_in_filter{nullptr}, *new_out_filter{nullptr};
0926     bool filter_is_temporary = false; // it can also become outputFilter(), which we may not delete here
0927     Column* temp_col = nullptr;
0928 
0929     Q_EMIT m_owner->modeAboutToChange(m_owner);
0930 
0931     // determine the conversion filter and allocate the new data vector
0932     switch (m_columnMode) { // old mode
0933     case AbstractColumn::ColumnMode::Double: {
0934         disconnect(static_cast<Double2StringFilter*>(m_outputFilter), &Double2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
0935         switch (mode) {
0936         case AbstractColumn::ColumnMode::Double:
0937             break;
0938         case AbstractColumn::ColumnMode::Integer:
0939             filter = new Double2IntegerFilter();
0940             filter_is_temporary = true;
0941             if (m_data) {
0942                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<double>*>(old_data)));
0943                 m_data = new QVector<int>();
0944             }
0945             break;
0946         case AbstractColumn::ColumnMode::BigInt:
0947             filter = new Double2BigIntFilter();
0948             filter_is_temporary = true;
0949             if (m_data) {
0950                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<double>*>(old_data)));
0951                 m_data = new QVector<qint64>();
0952             }
0953             break;
0954         case AbstractColumn::ColumnMode::Text:
0955             filter = outputFilter();
0956             filter_is_temporary = false;
0957             if (m_data) {
0958                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<double>*>(old_data)));
0959                 m_data = new QVector<QString>();
0960             }
0961             break;
0962         case AbstractColumn::ColumnMode::DateTime:
0963             filter = new Double2DateTimeFilter();
0964             filter_is_temporary = true;
0965             if (m_data) {
0966                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<double>*>(old_data)));
0967                 m_data = new QVector<QDateTime>();
0968             }
0969             break;
0970         case AbstractColumn::ColumnMode::Month:
0971             filter = new Double2MonthFilter();
0972             filter_is_temporary = true;
0973             if (m_data) {
0974                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<double>*>(old_data)));
0975                 m_data = new QVector<QDateTime>();
0976             }
0977             break;
0978         case AbstractColumn::ColumnMode::Day:
0979             filter = new Double2DayOfWeekFilter();
0980             filter_is_temporary = true;
0981             if (m_data) {
0982                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<double>*>(old_data)));
0983                 m_data = new QVector<QDateTime>();
0984             }
0985             break;
0986         } // switch(mode)
0987 
0988         break;
0989     }
0990     case AbstractColumn::ColumnMode::Integer: {
0991         disconnect(static_cast<Integer2StringFilter*>(m_outputFilter), &Integer2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
0992         switch (mode) {
0993         case AbstractColumn::ColumnMode::Integer:
0994             break;
0995         case AbstractColumn::ColumnMode::BigInt:
0996             filter = new Integer2BigIntFilter();
0997             filter_is_temporary = true;
0998             if (m_data) {
0999                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<int>*>(old_data)));
1000                 m_data = new QVector<qint64>();
1001             }
1002             break;
1003         case AbstractColumn::ColumnMode::Double:
1004             filter = new Integer2DoubleFilter();
1005             filter_is_temporary = true;
1006             if (m_data) {
1007                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<int>*>(old_data)));
1008                 m_data = new QVector<double>();
1009             }
1010             break;
1011         case AbstractColumn::ColumnMode::Text:
1012             filter = outputFilter();
1013             filter_is_temporary = false;
1014             if (m_data) {
1015                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<int>*>(old_data)));
1016                 m_data = new QVector<QString>();
1017             }
1018             break;
1019         case AbstractColumn::ColumnMode::DateTime:
1020             DEBUG(Q_FUNC_INFO << ", int -> datetime")
1021             filter = new Integer2DateTimeFilter();
1022             filter_is_temporary = true;
1023             if (m_data) {
1024                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<int>*>(old_data)));
1025                 m_data = new QVector<QDateTime>();
1026             }
1027             DEBUG(Q_FUNC_INFO << ", int -> datetime done")
1028             break;
1029         case AbstractColumn::ColumnMode::Month:
1030             filter = new Integer2MonthFilter();
1031             filter_is_temporary = true;
1032             if (m_data) {
1033                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<int>*>(old_data)));
1034                 m_data = new QVector<QDateTime>();
1035             }
1036             break;
1037         case AbstractColumn::ColumnMode::Day:
1038             filter = new Integer2DayOfWeekFilter();
1039             filter_is_temporary = true;
1040             if (m_data) {
1041                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<int>*>(old_data)));
1042                 m_data = new QVector<QDateTime>();
1043             }
1044             break;
1045         } // switch(mode)
1046 
1047         break;
1048     }
1049     case AbstractColumn::ColumnMode::BigInt: {
1050         disconnect(static_cast<BigInt2StringFilter*>(m_outputFilter), &BigInt2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1051         switch (mode) {
1052         case AbstractColumn::ColumnMode::BigInt:
1053             break;
1054         case AbstractColumn::ColumnMode::Integer: // TODO: timeUnit
1055             filter = new BigInt2IntegerFilter();
1056             filter_is_temporary = true;
1057             if (m_data) {
1058                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<qint64>*>(old_data)));
1059                 m_data = new QVector<int>();
1060             }
1061             break;
1062         case AbstractColumn::ColumnMode::Double: // TODO: timeUnit
1063             filter = new BigInt2DoubleFilter();
1064             filter_is_temporary = true;
1065             if (m_data) {
1066                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<qint64>*>(old_data)));
1067                 m_data = new QVector<double>();
1068             }
1069             break;
1070         case AbstractColumn::ColumnMode::Text:
1071             filter = outputFilter();
1072             filter_is_temporary = false;
1073             if (m_data) {
1074                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<qint64>*>(old_data)));
1075                 m_data = new QVector<QString>();
1076             }
1077             break;
1078         case AbstractColumn::ColumnMode::DateTime: // TODO: timeUnit
1079             filter = new BigInt2DateTimeFilter();
1080             filter_is_temporary = true;
1081             if (m_data) {
1082                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<qint64>*>(old_data)));
1083                 m_data = new QVector<QDateTime>();
1084             }
1085             break;
1086         case AbstractColumn::ColumnMode::Month:
1087             filter = new BigInt2MonthFilter();
1088             filter_is_temporary = true;
1089             if (m_data) {
1090                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<qint64>*>(old_data)));
1091                 m_data = new QVector<QDateTime>();
1092             }
1093             break;
1094         case AbstractColumn::ColumnMode::Day:
1095             filter = new BigInt2DayOfWeekFilter();
1096             filter_is_temporary = true;
1097             if (m_data) {
1098                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<qint64>*>(old_data)));
1099                 m_data = new QVector<QDateTime>();
1100             }
1101             break;
1102         } // switch(mode)
1103 
1104         break;
1105     }
1106     case AbstractColumn::ColumnMode::Text: {
1107         switch (mode) {
1108         case AbstractColumn::ColumnMode::Text:
1109             break;
1110         case AbstractColumn::ColumnMode::Double:
1111             filter = new String2DoubleFilter();
1112             filter->setNumberLocale(QLocale());
1113             filter_is_temporary = true;
1114             if (m_data) {
1115                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<QString>*>(old_data)));
1116                 m_data = new QVector<double>();
1117             }
1118             break;
1119         case AbstractColumn::ColumnMode::Integer:
1120             filter = new String2IntegerFilter();
1121             filter->setNumberLocale(QLocale());
1122             filter_is_temporary = true;
1123             if (m_data) {
1124                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<QString>*>(old_data)));
1125                 m_data = new QVector<int>();
1126             }
1127             break;
1128         case AbstractColumn::ColumnMode::BigInt:
1129             filter = new String2BigIntFilter();
1130             filter->setNumberLocale(QLocale());
1131             filter_is_temporary = true;
1132             if (m_data) {
1133                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<QString>*>(old_data)));
1134                 m_data = new QVector<qint64>();
1135             }
1136             break;
1137         case AbstractColumn::ColumnMode::DateTime:
1138             filter = new String2DateTimeFilter();
1139             filter_is_temporary = true;
1140             if (m_data) {
1141                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<QString>*>(old_data)));
1142                 m_data = new QVector<QDateTime>();
1143             }
1144             break;
1145         case AbstractColumn::ColumnMode::Month:
1146             filter = new String2MonthFilter();
1147             filter_is_temporary = true;
1148             if (m_data) {
1149                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<QString>*>(old_data)));
1150                 m_data = new QVector<QDateTime>();
1151             }
1152             break;
1153         case AbstractColumn::ColumnMode::Day:
1154             filter = new String2DayOfWeekFilter();
1155             filter_is_temporary = true;
1156             if (m_data) {
1157                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<QString>*>(old_data)));
1158                 m_data = new QVector<QDateTime>();
1159             }
1160             break;
1161         } // switch(mode)
1162 
1163         break;
1164     }
1165     case AbstractColumn::ColumnMode::DateTime:
1166     case AbstractColumn::ColumnMode::Month:
1167     case AbstractColumn::ColumnMode::Day: {
1168         disconnect(static_cast<DateTime2StringFilter*>(m_outputFilter), &DateTime2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1169         switch (mode) {
1170         case AbstractColumn::ColumnMode::DateTime:
1171         case AbstractColumn::ColumnMode::Month:
1172         case AbstractColumn::ColumnMode::Day:
1173             break;
1174         case AbstractColumn::ColumnMode::Text:
1175             filter = outputFilter();
1176             filter_is_temporary = false;
1177             if (m_data) {
1178                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<QDateTime>*>(old_data)), m_columnMode);
1179                 m_data = new QStringList();
1180             }
1181             break;
1182         case AbstractColumn::ColumnMode::Double:
1183             if (m_columnMode == AbstractColumn::ColumnMode::Month)
1184                 filter = new Month2DoubleFilter();
1185             else if (m_columnMode == AbstractColumn::ColumnMode::Day)
1186                 filter = new DayOfWeek2DoubleFilter();
1187             else // TODO: timeUnit
1188                 filter = new DateTime2DoubleFilter();
1189             filter_is_temporary = true;
1190             if (m_data) {
1191                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<QDateTime>*>(old_data)), m_columnMode);
1192                 m_data = new QVector<double>();
1193             }
1194             break;
1195         case AbstractColumn::ColumnMode::Integer:
1196             if (m_columnMode == AbstractColumn::ColumnMode::Month)
1197                 filter = new Month2IntegerFilter();
1198             else if (m_columnMode == AbstractColumn::ColumnMode::Day)
1199                 filter = new DayOfWeek2IntegerFilter();
1200             else // TODO: timeUnit
1201                 filter = new DateTime2IntegerFilter();
1202             filter_is_temporary = true;
1203             if (m_data) {
1204                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<QDateTime>*>(old_data)), m_columnMode);
1205                 m_data = new QVector<int>();
1206             }
1207             break;
1208         case AbstractColumn::ColumnMode::BigInt:
1209             if (m_columnMode == AbstractColumn::ColumnMode::Month)
1210                 filter = new Month2BigIntFilter();
1211             else if (m_columnMode == AbstractColumn::ColumnMode::Day)
1212                 filter = new DayOfWeek2BigIntFilter();
1213             else // TODO: timeUnit
1214                 filter = new DateTime2BigIntFilter();
1215             filter_is_temporary = true;
1216             if (m_data) {
1217                 temp_col = new Column(QStringLiteral("temp_col"), *(static_cast<QVector<QDateTime>*>(old_data)), m_columnMode);
1218                 m_data = new QVector<qint64>();
1219             }
1220             break;
1221         } // switch(mode)
1222 
1223         break;
1224     }
1225     }
1226 
1227     // determine the new input and output filters
1228     switch (mode) { // new mode
1229     case AbstractColumn::ColumnMode::Double:
1230         new_in_filter = new String2DoubleFilter();
1231         new_in_filter->setNumberLocale(QLocale());
1232         new_out_filter = new Double2StringFilter();
1233         new_out_filter->setNumberLocale(QLocale());
1234         connect(static_cast<Double2StringFilter*>(new_out_filter), &Double2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1235         break;
1236     case AbstractColumn::ColumnMode::Integer:
1237         new_in_filter = new String2IntegerFilter();
1238         new_in_filter->setNumberLocale(QLocale());
1239         new_out_filter = new Integer2StringFilter();
1240         new_out_filter->setNumberLocale(QLocale());
1241         connect(static_cast<Integer2StringFilter*>(new_out_filter), &Integer2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1242         break;
1243     case AbstractColumn::ColumnMode::BigInt:
1244         new_in_filter = new String2BigIntFilter();
1245         new_in_filter->setNumberLocale(QLocale());
1246         new_out_filter = new BigInt2StringFilter();
1247         new_out_filter->setNumberLocale(QLocale());
1248         connect(static_cast<BigInt2StringFilter*>(new_out_filter), &BigInt2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1249         break;
1250     case AbstractColumn::ColumnMode::Text:
1251         new_in_filter = new SimpleCopyThroughFilter();
1252         new_out_filter = new SimpleCopyThroughFilter();
1253         break;
1254     case AbstractColumn::ColumnMode::DateTime:
1255         new_in_filter = new String2DateTimeFilter();
1256         new_out_filter = new DateTime2StringFilter();
1257         connect(static_cast<DateTime2StringFilter*>(new_out_filter), &DateTime2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1258         break;
1259     case AbstractColumn::ColumnMode::Month:
1260         new_in_filter = new String2MonthFilter();
1261         new_out_filter = new DateTime2StringFilter();
1262         static_cast<DateTime2StringFilter*>(new_out_filter)->setFormat(QStringLiteral("MMMM"));
1263         // DEBUG("  Month out_filter format: " << STDSTRING(static_cast<DateTime2StringFilter*>(new_out_filter)->format()));
1264         connect(static_cast<DateTime2StringFilter*>(new_out_filter), &DateTime2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1265         break;
1266     case AbstractColumn::ColumnMode::Day:
1267         new_in_filter = new String2DayOfWeekFilter();
1268         new_out_filter = new DateTime2StringFilter();
1269         static_cast<DateTime2StringFilter*>(new_out_filter)->setFormat(QStringLiteral("dddd"));
1270         connect(static_cast<DateTime2StringFilter*>(new_out_filter), &DateTime2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1271         break;
1272     } // switch(mode)
1273 
1274     m_columnMode = mode;
1275 
1276     m_inputFilter = new_in_filter;
1277     m_outputFilter = new_out_filter;
1278     m_inputFilter->input(0, m_owner->m_string_io);
1279     m_outputFilter->input(0, m_owner);
1280     m_inputFilter->setHidden(true);
1281     m_outputFilter->setHidden(true);
1282 
1283     if (temp_col) { // if temp_col == 0, only the input/output filters need to be changed
1284         // copy the filtered, i.e. converted, column (mode is orig mode)
1285         DEBUG(" temp_col column mode = " << ENUM_TO_STRING(AbstractColumn, ColumnMode, temp_col->columnMode()));
1286         filter->input(0, temp_col);
1287         DEBUG(" filter->output size = " << filter->output(0)->rowCount());
1288         copy(filter->output(0));
1289         DEBUG(" DONE")
1290         delete temp_col;
1291     }
1292 
1293     if (filter_is_temporary)
1294         delete filter;
1295 
1296     Q_EMIT m_owner->modeChanged(m_owner);
1297 }
1298 
1299 /**
1300  * \brief Replace all mode related members
1301  *
1302  * Replace column mode, data type, data pointer and filters directly
1303  */
1304 void ColumnPrivate::replaceModeData(AbstractColumn::ColumnMode mode, void* data, AbstractSimpleFilter* in_filter, AbstractSimpleFilter* out_filter) {
1305     Q_EMIT m_owner->modeAboutToChange(m_owner);
1306     // disconnect formatChanged()
1307     switch (m_columnMode) {
1308     case AbstractColumn::ColumnMode::Double:
1309         disconnect(static_cast<Double2StringFilter*>(m_outputFilter), &Double2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1310         break;
1311     case AbstractColumn::ColumnMode::Integer:
1312         disconnect(static_cast<Integer2StringFilter*>(m_outputFilter), &Integer2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1313         break;
1314     case AbstractColumn::ColumnMode::BigInt:
1315         disconnect(static_cast<BigInt2StringFilter*>(m_outputFilter), &BigInt2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1316         break;
1317     case AbstractColumn::ColumnMode::Text:
1318         break;
1319     case AbstractColumn::ColumnMode::DateTime:
1320     case AbstractColumn::ColumnMode::Month:
1321     case AbstractColumn::ColumnMode::Day:
1322         disconnect(static_cast<DateTime2StringFilter*>(m_outputFilter), &DateTime2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1323         break;
1324     }
1325 
1326     m_columnMode = mode;
1327     setLabelsMode(mode);
1328     m_data = data;
1329 
1330     m_inputFilter = in_filter;
1331     m_outputFilter = out_filter;
1332     m_inputFilter->input(0, m_owner->m_string_io);
1333     m_outputFilter->input(0, m_owner);
1334 
1335     // connect formatChanged()
1336     switch (m_columnMode) {
1337     case AbstractColumn::ColumnMode::Double:
1338         connect(static_cast<Double2StringFilter*>(m_outputFilter), &Double2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1339         break;
1340     case AbstractColumn::ColumnMode::Integer:
1341         connect(static_cast<Integer2StringFilter*>(m_outputFilter), &Integer2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1342         break;
1343     case AbstractColumn::ColumnMode::BigInt:
1344         connect(static_cast<BigInt2StringFilter*>(m_outputFilter), &BigInt2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1345         break;
1346     case AbstractColumn::ColumnMode::Text:
1347         break;
1348     case AbstractColumn::ColumnMode::DateTime:
1349     case AbstractColumn::ColumnMode::Month:
1350     case AbstractColumn::ColumnMode::Day:
1351         connect(static_cast<DateTime2StringFilter*>(m_outputFilter), &DateTime2StringFilter::formatChanged, m_owner, &Column::handleFormatChange);
1352         break;
1353     }
1354 
1355     Q_EMIT m_owner->modeChanged(m_owner);
1356 }
1357 
1358 /**
1359  * \brief Replace data pointer
1360  */
1361 void ColumnPrivate::replaceData(void* data) {
1362     Q_EMIT m_owner->dataAboutToChange(m_owner);
1363 
1364     m_data = data;
1365     invalidate();
1366     if (!m_owner->m_suppressDataChangedSignal)
1367         Q_EMIT m_owner->dataChanged(m_owner);
1368 }
1369 
1370 /**
1371  * \brief Copy another column of the same type
1372  *
1373  * This function will return false if the data type
1374  * of 'other' is not the same as the type of 'this'.
1375  * Use a filter to convert a column to another type.
1376  */
1377 bool ColumnPrivate::copy(const AbstractColumn* other) {
1378     DEBUG(Q_FUNC_INFO)
1379     if (other->columnMode() != columnMode())
1380         return false;
1381     //  DEBUG(Q_FUNC_INFO << ", mode = " << ENUM_TO_STRING(AbstractColumn, ColumnMode, columnMode()));
1382     int num_rows = other->rowCount();
1383     //  DEBUG(Q_FUNC_INFO << ", rows " << num_rows);
1384 
1385     Q_EMIT m_owner->dataAboutToChange(m_owner);
1386     resizeTo(num_rows);
1387 
1388     if (!m_data) {
1389         if (!initDataContainer())
1390             return false; // failed to allocate memory
1391     }
1392 
1393     // copy the data
1394     switch (m_columnMode) {
1395     case AbstractColumn::ColumnMode::Double: {
1396         double* ptr = static_cast<QVector<double>*>(m_data)->data();
1397         for (int i = 0; i < num_rows; ++i)
1398             ptr[i] = other->valueAt(i);
1399         break;
1400     }
1401     case AbstractColumn::ColumnMode::Integer: {
1402         int* ptr = static_cast<QVector<int>*>(m_data)->data();
1403         for (int i = 0; i < num_rows; ++i)
1404             ptr[i] = other->integerAt(i);
1405         break;
1406     }
1407     case AbstractColumn::ColumnMode::BigInt: {
1408         qint64* ptr = static_cast<QVector<qint64>*>(m_data)->data();
1409         for (int i = 0; i < num_rows; ++i)
1410             ptr[i] = other->bigIntAt(i);
1411         break;
1412     }
1413     case AbstractColumn::ColumnMode::Text: {
1414         auto* vec = static_cast<QVector<QString>*>(m_data);
1415         for (int i = 0; i < num_rows; ++i)
1416             vec->replace(i, other->textAt(i));
1417         break;
1418     }
1419     case AbstractColumn::ColumnMode::DateTime:
1420     case AbstractColumn::ColumnMode::Month:
1421     case AbstractColumn::ColumnMode::Day: {
1422         auto* vec = static_cast<QVector<QDateTime>*>(m_data);
1423         for (int i = 0; i < num_rows; ++i)
1424             vec->replace(i, other->dateTimeAt(i));
1425         break;
1426     }
1427     }
1428 
1429     invalidate();
1430 
1431     if (!m_owner->m_suppressDataChangedSignal)
1432         Q_EMIT m_owner->dataChanged(m_owner);
1433 
1434     DEBUG(Q_FUNC_INFO << ", done")
1435     return true;
1436 }
1437 
1438 /**
1439  * \brief Copies a part of another column of the same type
1440  *
1441  * This function will return false if the data type
1442  * of 'other' is not the same as the type of 'this'.
1443  * \param source pointer to the column to copy
1444  * \param source_start first row to copy in the column to copy
1445  * \param dest_start first row to copy in
1446  * \param num_rows the number of rows to copy
1447  */
1448 bool ColumnPrivate::copy(const AbstractColumn* source, int source_start, int dest_start, int num_rows) {
1449     if (source->columnMode() != m_columnMode)
1450         return false;
1451     if (num_rows == 0)
1452         return true;
1453 
1454     Q_EMIT m_owner->dataAboutToChange(m_owner);
1455     if (dest_start + num_rows > rowCount())
1456         resizeTo(dest_start + num_rows);
1457 
1458     if (!m_data) {
1459         if (!initDataContainer())
1460             return false; // failed to allocate memory
1461     }
1462 
1463     // copy the data
1464     switch (m_columnMode) {
1465     case AbstractColumn::ColumnMode::Double: {
1466         double* ptr = static_cast<QVector<double>*>(m_data)->data();
1467         for (int i = 0; i < num_rows; i++)
1468             ptr[dest_start + i] = source->valueAt(source_start + i);
1469         break;
1470     }
1471     case AbstractColumn::ColumnMode::Integer: {
1472         int* ptr = static_cast<QVector<int>*>(m_data)->data();
1473         for (int i = 0; i < num_rows; i++)
1474             ptr[dest_start + i] = source->integerAt(source_start + i);
1475         break;
1476     }
1477     case AbstractColumn::ColumnMode::BigInt: {
1478         qint64* ptr = static_cast<QVector<qint64>*>(m_data)->data();
1479         for (int i = 0; i < num_rows; i++)
1480             ptr[dest_start + i] = source->bigIntAt(source_start + i);
1481         break;
1482     }
1483     case AbstractColumn::ColumnMode::Text:
1484         for (int i = 0; i < num_rows; i++)
1485             static_cast<QVector<QString>*>(m_data)->replace(dest_start + i, source->textAt(source_start + i));
1486         break;
1487     case AbstractColumn::ColumnMode::DateTime:
1488     case AbstractColumn::ColumnMode::Month:
1489     case AbstractColumn::ColumnMode::Day:
1490         for (int i = 0; i < num_rows; i++)
1491             static_cast<QVector<QDateTime>*>(m_data)->replace(dest_start + i, source->dateTimeAt(source_start + i));
1492         break;
1493     }
1494 
1495     invalidate();
1496 
1497     if (!m_owner->m_suppressDataChangedSignal)
1498         Q_EMIT m_owner->dataChanged(m_owner);
1499 
1500     return true;
1501 }
1502 
1503 /**
1504  * \brief Copy another column of the same type
1505  *
1506  * This function will return false if the data type
1507  * of 'other' is not the same as the type of 'this'.
1508  * Use a filter to convert a column to another type.
1509  */
1510 bool ColumnPrivate::copy(const ColumnPrivate* other) {
1511     if (other->columnMode() != m_columnMode)
1512         return false;
1513     int num_rows = other->rowCount();
1514 
1515     Q_EMIT m_owner->dataAboutToChange(m_owner);
1516     resizeTo(num_rows);
1517 
1518     if (!m_data) {
1519         if (!initDataContainer())
1520             return false; // failed to allocate memory
1521     }
1522 
1523     // copy the data
1524     switch (m_columnMode) {
1525     case AbstractColumn::ColumnMode::Double: {
1526         double* ptr = static_cast<QVector<double>*>(m_data)->data();
1527         for (int i = 0; i < num_rows; ++i)
1528             ptr[i] = other->valueAt(i);
1529         break;
1530     }
1531     case AbstractColumn::ColumnMode::Integer: {
1532         int* ptr = static_cast<QVector<int>*>(m_data)->data();
1533         for (int i = 0; i < num_rows; ++i)
1534             ptr[i] = other->integerAt(i);
1535         break;
1536     }
1537     case AbstractColumn::ColumnMode::BigInt: {
1538         qint64* ptr = static_cast<QVector<qint64>*>(m_data)->data();
1539         for (int i = 0; i < num_rows; ++i)
1540             ptr[i] = other->bigIntAt(i);
1541         break;
1542     }
1543     case AbstractColumn::ColumnMode::Text:
1544         for (int i = 0; i < num_rows; ++i)
1545             static_cast<QVector<QString>*>(m_data)->replace(i, other->textAt(i));
1546         break;
1547     case AbstractColumn::ColumnMode::DateTime:
1548     case AbstractColumn::ColumnMode::Month:
1549     case AbstractColumn::ColumnMode::Day:
1550         for (int i = 0; i < num_rows; ++i)
1551             static_cast<QVector<QDateTime>*>(m_data)->replace(i, other->dateTimeAt(i));
1552         break;
1553     }
1554 
1555     invalidate();
1556 
1557     if (!m_owner->m_suppressDataChangedSignal)
1558         Q_EMIT m_owner->dataChanged(m_owner);
1559 
1560     return true;
1561 }
1562 
1563 /**
1564  * \brief Copies a part of another column of the same type
1565  *
1566  * This function will return false if the data type
1567  * of 'other' is not the same as the type of 'this'.
1568  * \param source pointer to the column to copy
1569  * \param source_start first row to copy in the column to copy
1570  * \param dest_start first row to copy in
1571  * \param num_rows the number of rows to copy
1572  */
1573 bool ColumnPrivate::copy(const ColumnPrivate* source, int source_start, int dest_start, int num_rows) {
1574     if (source->columnMode() != m_columnMode)
1575         return false;
1576     if (num_rows == 0)
1577         return true;
1578 
1579     Q_EMIT m_owner->dataAboutToChange(m_owner);
1580     if (dest_start + num_rows > rowCount())
1581         resizeTo(dest_start + num_rows);
1582 
1583     if (!m_data) {
1584         if (!initDataContainer())
1585             return false; // failed to allocate memory
1586     }
1587 
1588     // copy the data
1589     switch (m_columnMode) {
1590     case AbstractColumn::ColumnMode::Double: {
1591         double* ptr = static_cast<QVector<double>*>(m_data)->data();
1592         for (int i = 0; i < num_rows; ++i)
1593             ptr[dest_start + i] = source->valueAt(source_start + i);
1594         break;
1595     }
1596     case AbstractColumn::ColumnMode::Integer: {
1597         int* ptr = static_cast<QVector<int>*>(m_data)->data();
1598         for (int i = 0; i < num_rows; ++i)
1599             ptr[dest_start + i] = source->integerAt(source_start + i);
1600         break;
1601     }
1602     case AbstractColumn::ColumnMode::BigInt: {
1603         qint64* ptr = static_cast<QVector<qint64>*>(m_data)->data();
1604         for (int i = 0; i < num_rows; ++i)
1605             ptr[dest_start + i] = source->bigIntAt(source_start + i);
1606         break;
1607     }
1608     case AbstractColumn::ColumnMode::Text:
1609         for (int i = 0; i < num_rows; ++i)
1610             static_cast<QVector<QString>*>(m_data)->replace(dest_start + i, source->textAt(source_start + i));
1611         break;
1612     case AbstractColumn::ColumnMode::DateTime:
1613     case AbstractColumn::ColumnMode::Month:
1614     case AbstractColumn::ColumnMode::Day:
1615         for (int i = 0; i < num_rows; ++i)
1616             static_cast<QVector<QDateTime>*>(m_data)->replace(dest_start + i, source->dateTimeAt(source_start + i));
1617         break;
1618     }
1619 
1620     invalidate();
1621 
1622     if (!m_owner->m_suppressDataChangedSignal)
1623         Q_EMIT m_owner->dataChanged(m_owner);
1624 
1625     return true;
1626 }
1627 
1628 /**
1629  * \brief Return the data vector size
1630  *
1631  * This returns the size of the column container
1632  */
1633 int ColumnPrivate::rowCount() const {
1634     if (!m_data)
1635         return m_rowCount;
1636 
1637     switch (m_columnMode) {
1638     case AbstractColumn::ColumnMode::Double:
1639         return static_cast<QVector<double>*>(m_data)->size();
1640     case AbstractColumn::ColumnMode::Integer:
1641         return static_cast<QVector<int>*>(m_data)->size();
1642     case AbstractColumn::ColumnMode::BigInt:
1643         return static_cast<QVector<qint64>*>(m_data)->size();
1644     case AbstractColumn::ColumnMode::DateTime:
1645     case AbstractColumn::ColumnMode::Month:
1646     case AbstractColumn::ColumnMode::Day:
1647         return static_cast<QVector<QDateTime>*>(m_data)->size();
1648     case AbstractColumn::ColumnMode::Text:
1649         return static_cast<QVector<QString>*>(m_data)->size();
1650     }
1651 
1652     return 0;
1653 }
1654 
1655 int ColumnPrivate::rowCount(double min, double max) const {
1656     if (!m_data)
1657         return m_rowCount;
1658 
1659     int counter = 0;
1660     switch (m_columnMode) {
1661     case AbstractColumn::ColumnMode::Double: {
1662         const auto* data = static_cast<QVector<double>*>(m_data);
1663         for (const auto& d : *data) {
1664             if (d >= min && d <= max)
1665                 counter++;
1666         }
1667         break;
1668     }
1669     case AbstractColumn::ColumnMode::Integer: {
1670         const auto* data = static_cast<QVector<int>*>(m_data);
1671         for (const auto& d : *data) {
1672             if (d >= min && d <= max)
1673                 counter++;
1674         }
1675         break;
1676     }
1677     case AbstractColumn::ColumnMode::BigInt: {
1678         const auto* data = static_cast<QVector<qint64>*>(m_data);
1679         for (const auto& d : *data) {
1680             if (d >= min && d <= max)
1681                 counter++;
1682         }
1683         break;
1684     }
1685     case AbstractColumn::ColumnMode::DateTime:
1686     case AbstractColumn::ColumnMode::Month:
1687     case AbstractColumn::ColumnMode::Day: {
1688         const auto* data = static_cast<QVector<QDateTime>*>(m_data);
1689         for (const auto& d : *data) {
1690             const auto value = d.toMSecsSinceEpoch();
1691             if (value >= min && value <= max)
1692                 counter++;
1693         }
1694         break;
1695     }
1696     case AbstractColumn::ColumnMode::Text:
1697         break;
1698     }
1699     return counter;
1700 }
1701 
1702 /**
1703  * \brief Return the number of available rows
1704  *
1705  * This returns the number of rows that actually contain data.
1706  * Rows beyond this can be masked etc. but should be ignored by filters,
1707  * plots etc.
1708  */
1709 int ColumnPrivate::availableRowCount(int max) const {
1710     int count = 0;
1711     for (int row = 0; row < rowCount(); row++) {
1712         if (m_owner->isValid(row) && !m_owner->isMasked(row)) {
1713             count++;
1714             if (count == max)
1715                 return max;
1716         }
1717     }
1718 
1719     return count;
1720 }
1721 
1722 /**
1723  * \brief Resize the vector to the specified number of rows
1724  *
1725  * Since selecting and masking rows higher than the
1726  * real internal number of rows is supported, this
1727  * does not change the interval attributes. Also
1728  * no signal is emitted. If the new rows are filled
1729  * with values AbstractColumn::dataChanged()
1730  * must be emitted.
1731  */
1732 void ColumnPrivate::resizeTo(int new_size) {
1733     int old_size = rowCount();
1734     if (new_size == old_size)
1735         return;
1736 
1737     //  DEBUG("ColumnPrivate::resizeTo() " << old_size << " -> " << new_size);
1738     const int new_rows = new_size - old_size;
1739 
1740     if (!m_data) {
1741         m_rowCount += new_rows;
1742         return;
1743     }
1744 
1745     switch (m_columnMode) {
1746     case AbstractColumn::ColumnMode::Double: {
1747         auto* data = static_cast<QVector<double>*>(m_data);
1748         if (new_rows > 0)
1749             data->insert(data->end(), new_rows, NAN);
1750         else
1751             data->remove(old_size - 1 + new_rows, -new_rows);
1752         break;
1753     }
1754     case AbstractColumn::ColumnMode::Integer: {
1755         auto* data = static_cast<QVector<int>*>(m_data);
1756         if (new_rows > 0)
1757             data->insert(data->end(), new_rows, 0);
1758         else
1759             data->remove(old_size - 1 + new_rows, -new_rows);
1760         break;
1761     }
1762     case AbstractColumn::ColumnMode::BigInt: {
1763         auto* data = static_cast<QVector<qint64>*>(m_data);
1764         if (new_rows > 0)
1765             data->insert(data->end(), new_rows, 0);
1766         else
1767             data->remove(old_size - 1 + new_rows, -new_rows);
1768         break;
1769     }
1770     case AbstractColumn::ColumnMode::Text: {
1771         auto* data = static_cast<QVector<QString>*>(m_data);
1772         if (new_rows > 0)
1773             data->insert(data->end(), new_rows, QString());
1774         else
1775             data->remove(old_size - 1 + new_rows, -new_rows);
1776         break;
1777     }
1778     case AbstractColumn::ColumnMode::DateTime:
1779     case AbstractColumn::ColumnMode::Month:
1780     case AbstractColumn::ColumnMode::Day: {
1781         auto* data = static_cast<QVector<QDateTime>*>(m_data);
1782         if (new_rows > 0)
1783             data->insert(data->end(), new_rows, QDateTime());
1784         else
1785             data->remove(old_size - 1 + new_rows, -new_rows);
1786         break;
1787     }
1788     }
1789 
1790     invalidate();
1791 }
1792 
1793 /**
1794  * \brief Insert some empty (or initialized with zero) rows
1795  */
1796 void ColumnPrivate::insertRows(int before, int count) {
1797     if (count == 0)
1798         return;
1799 
1800     m_formulas.insertRows(before, count);
1801 
1802     if (!m_data) {
1803         m_rowCount += count;
1804         return;
1805     }
1806 
1807     if (before <= rowCount()) {
1808         switch (m_columnMode) {
1809         case AbstractColumn::ColumnMode::Double:
1810             static_cast<QVector<double>*>(m_data)->insert(before, count, NAN);
1811             break;
1812         case AbstractColumn::ColumnMode::Integer:
1813             static_cast<QVector<int>*>(m_data)->insert(before, count, 0);
1814             break;
1815         case AbstractColumn::ColumnMode::BigInt:
1816             static_cast<QVector<qint64>*>(m_data)->insert(before, count, 0);
1817             break;
1818         case AbstractColumn::ColumnMode::DateTime:
1819         case AbstractColumn::ColumnMode::Month:
1820         case AbstractColumn::ColumnMode::Day:
1821             for (int i = 0; i < count; ++i)
1822                 static_cast<QVector<QDateTime>*>(m_data)->insert(before, QDateTime());
1823             break;
1824         case AbstractColumn::ColumnMode::Text:
1825             for (int i = 0; i < count; ++i)
1826                 static_cast<QVector<QString>*>(m_data)->insert(before, QString());
1827             break;
1828         }
1829     }
1830 
1831     invalidate();
1832 }
1833 
1834 /**
1835  * \brief Remove 'count' rows starting from row 'first'
1836  */
1837 void ColumnPrivate::removeRows(int first, int count) {
1838     if (count == 0)
1839         return;
1840 
1841     m_formulas.removeRows(first, count);
1842 
1843     if (first < rowCount()) {
1844         int corrected_count = count;
1845         if (first + count > rowCount())
1846             corrected_count = rowCount() - first;
1847 
1848         if (!m_data) {
1849             m_rowCount -= corrected_count;
1850             return;
1851         }
1852 
1853         switch (m_columnMode) {
1854         case AbstractColumn::ColumnMode::Double:
1855             static_cast<QVector<double>*>(m_data)->remove(first, corrected_count);
1856             break;
1857         case AbstractColumn::ColumnMode::Integer:
1858             static_cast<QVector<int>*>(m_data)->remove(first, corrected_count);
1859             break;
1860         case AbstractColumn::ColumnMode::BigInt:
1861             static_cast<QVector<qint64>*>(m_data)->remove(first, corrected_count);
1862             break;
1863         case AbstractColumn::ColumnMode::DateTime:
1864         case AbstractColumn::ColumnMode::Month:
1865         case AbstractColumn::ColumnMode::Day:
1866             for (int i = 0; i < corrected_count; ++i)
1867                 static_cast<QVector<QDateTime>*>(m_data)->removeAt(first);
1868             break;
1869         case AbstractColumn::ColumnMode::Text:
1870             for (int i = 0; i < corrected_count; ++i)
1871                 static_cast<QVector<QString>*>(m_data)->removeAt(first);
1872             break;
1873         }
1874     }
1875 
1876     invalidate();
1877 }
1878 
1879 int ColumnPrivate::indexForValue(double x) const {
1880     return indexForValueCommon<Column>(m_owner,
1881                                        x,
1882                                        std::mem_fn(&Column::columnMode),
1883                                        std::mem_fn<int() const>(&Column::rowCount),
1884                                        std::mem_fn(&Column::valueAt),
1885                                        std::mem_fn(&Column::dateTimeAt),
1886                                        std::mem_fn(&Column::properties),
1887                                        std::mem_fn<bool(int) const>(&Column::isValid),
1888                                        std::mem_fn<bool(int) const>(&Column::isMasked));
1889 }
1890 
1891 //! Return the column name
1892 QString ColumnPrivate::name() const {
1893     return m_owner->name();
1894 }
1895 
1896 /**
1897  * \brief Return the column plot designation
1898  */
1899 AbstractColumn::PlotDesignation ColumnPrivate::plotDesignation() const {
1900     return m_plotDesignation;
1901 }
1902 
1903 /**
1904  * \brief Set the column plot designation
1905  */
1906 void ColumnPrivate::setPlotDesignation(AbstractColumn::PlotDesignation pd) {
1907     Q_EMIT m_owner->plotDesignationAboutToChange(m_owner);
1908     m_plotDesignation = pd;
1909     Q_EMIT m_owner->plotDesignationChanged(m_owner);
1910 }
1911 
1912 /**
1913  * \brief Get width
1914  */
1915 int ColumnPrivate::width() const {
1916     return m_width;
1917 }
1918 
1919 /**
1920  * \brief Set width
1921  */
1922 void ColumnPrivate::setWidth(int value) {
1923     m_width = value;
1924 }
1925 
1926 /**
1927  * @brief ColumnPrivate::setData
1928  * Set new column data
1929  */
1930 void ColumnPrivate::setData(void* data) {
1931     deleteData();
1932     m_data = data;
1933     invalidate();
1934 }
1935 
1936 /**
1937  * \brief Return the data pointer
1938  */
1939 void* ColumnPrivate::data() const {
1940     if (!m_data)
1941         const_cast<ColumnPrivate*>(this)->initDataContainer();
1942 
1943     return m_data;
1944 }
1945 
1946 /**
1947  * \brief Return the input filter (for string -> data type conversion)
1948  */
1949 AbstractSimpleFilter* ColumnPrivate::inputFilter() const {
1950     return m_inputFilter;
1951 }
1952 
1953 /**
1954  * \brief Return the output filter (for data type -> string  conversion)
1955  */
1956 AbstractSimpleFilter* ColumnPrivate::outputFilter() const {
1957     return m_outputFilter;
1958 }
1959 
1960 //! \name Labels related functions
1961 //@{
1962 void ColumnPrivate::setLabelsMode(Column::ColumnMode mode) {
1963     m_labels.setMode(mode);
1964 }
1965 
1966 void ColumnPrivate::valueLabelsRemoveAll() {
1967     m_labels.removeAll();
1968 }
1969 
1970 bool ColumnPrivate::valueLabelsInitialized() const {
1971     return m_labels.initialized();
1972 }
1973 
1974 void ColumnPrivate::removeValueLabel(const QString& key) {
1975     m_labels.remove(key);
1976 }
1977 
1978 double ColumnPrivate::valueLabelsMinimum() {
1979     return m_labels.minimum();
1980 }
1981 
1982 double ColumnPrivate::valueLabelsMaximum() {
1983     return m_labels.maximum();
1984 }
1985 
1986 const QVector<Column::ValueLabel<QString>>* ColumnPrivate::textValueLabels() const {
1987     return m_labels.textValueLabels();
1988 }
1989 
1990 const QVector<Column::ValueLabel<QDateTime>>* ColumnPrivate::dateTimeValueLabels() const {
1991     return m_labels.dateTimeValueLabels();
1992 }
1993 
1994 int ColumnPrivate::valueLabelsCount() const {
1995     return m_labels.count();
1996 }
1997 
1998 int ColumnPrivate::valueLabelsCount(double min, double max) const {
1999     return m_labels.count(min, max);
2000 }
2001 
2002 int ColumnPrivate::valueLabelsIndexForValue(double value) const {
2003     return m_labels.indexForValue(value);
2004 }
2005 
2006 double ColumnPrivate::valueLabelsValueAt(int index) const {
2007     return m_labels.valueAt(index);
2008 }
2009 
2010 QString ColumnPrivate::valueLabelAt(int index) const {
2011     return m_labels.labelAt(index);
2012 }
2013 
2014 const QVector<Column::ValueLabel<double>>* ColumnPrivate::valueLabels() const {
2015     return m_labels.valueLabels();
2016 }
2017 
2018 const QVector<Column::ValueLabel<int>>* ColumnPrivate::intValueLabels() const {
2019     return m_labels.intValueLabels();
2020 }
2021 
2022 const QVector<Column::ValueLabel<qint64>>* ColumnPrivate::bigIntValueLabels() const {
2023     return m_labels.bigIntValueLabels();
2024 }
2025 //@}
2026 
2027 //! \name Formula related functions
2028 //@{
2029 /**
2030  * \brief Return the formula last used to generate data for the column
2031  */
2032 QString ColumnPrivate::formula() const {
2033     return m_formula;
2034 }
2035 
2036 const QVector<Column::FormulaData>& ColumnPrivate::formulaData() const {
2037     return m_formulaData;
2038 }
2039 
2040 bool ColumnPrivate::formulaAutoUpdate() const {
2041     return m_formulaAutoUpdate;
2042 }
2043 
2044 bool ColumnPrivate::formulaAutoResize() const {
2045     return m_formulaAutoResize;
2046 }
2047 
2048 /**
2049  * \brief Sets the formula used to generate column values
2050  */
2051 void ColumnPrivate::setFormula(const QString& formula, const QVector<Column::FormulaData>& formulaData, bool autoUpdate, bool autoResize) {
2052     m_formula = formula;
2053     m_formulaData = formulaData; // TODO: disconnecting everything?
2054     m_formulaAutoUpdate = autoUpdate;
2055     m_formulaAutoResize = autoResize;
2056 
2057     for (auto& connection : m_connectionsUpdateFormula)
2058         if (static_cast<bool>(connection))
2059             disconnect(connection);
2060 
2061     for (const auto& data : m_formulaData) {
2062         const auto* column = data.column();
2063         assert(column);
2064         if (autoUpdate)
2065             connectFormulaColumn(column);
2066     }
2067 
2068     Q_EMIT m_owner->formulaChanged(m_owner);
2069 }
2070 
2071 /*!
2072  * called after the import of the project was done and all columns were loaded in \sa Project::load()
2073  * to establish the required slot-signal connections for the formula update
2074  */
2075 void ColumnPrivate::finalizeLoad() {
2076     if (m_formulaAutoUpdate) {
2077         for (const auto& formulaData : m_formulaData) {
2078             const auto* column = formulaData.column();
2079             if (column)
2080                 connectFormulaColumn(column);
2081         }
2082     }
2083 }
2084 
2085 /*!
2086  * \brief ColumnPrivate::connectFormulaColumn
2087  * This function is used to connect the columns to the needed slots for updating formulas
2088  * \param column
2089  */
2090 void ColumnPrivate::connectFormulaColumn(const AbstractColumn* column) {
2091     if (!column)
2092         return;
2093 
2094     // avoid circular dependencies - the current column cannot be part of the variable columns.
2095     // this should't actually happen because of the checks done when the formula is defined,
2096     // but in case we have bugs somewhere or somebody manipulated the project xml file we add
2097     // a sanity check to avoid recursive calls here and crash because of the stack overflow.
2098     if (column == m_owner)
2099         return;
2100 
2101     DEBUG(Q_FUNC_INFO)
2102     m_connectionsUpdateFormula << connect(column, &AbstractColumn::dataChanged, m_owner, &Column::updateFormula);
2103     connect(column->parentAspect(),
2104             QOverload<const AbstractAspect*>::of(&AbstractAspect::childAspectAboutToBeRemoved),
2105             this,
2106             &ColumnPrivate::formulaVariableColumnRemoved);
2107     connect(column, &AbstractColumn::aboutToReset, this, &ColumnPrivate::formulaVariableColumnRemoved);
2108     connect(column->parentAspect(), &AbstractAspect::childAspectAdded, this, &ColumnPrivate::formulaVariableColumnAdded);
2109 }
2110 
2111 /*!
2112  * helper function used in \c Column::load() to set parameters read from the xml file.
2113  * \param variableColumnPaths is used to restore the pointers to columns from pathes
2114  * after the project was loaded in Project::load().
2115  */
2116 void ColumnPrivate::setFormula(const QString& formula,
2117                                const QStringList& variableNames,
2118                                const QStringList& variableColumnPaths,
2119                                bool autoUpdate,
2120                                bool autoResize) {
2121     m_formula = formula;
2122     m_formulaData.clear();
2123     for (int i = 0; i < variableNames.count(); i++)
2124         m_formulaData.append(Column::FormulaData(variableNames.at(i), variableColumnPaths.at(i)));
2125 
2126     m_formulaAutoUpdate = autoUpdate;
2127     m_formulaAutoResize = autoResize;
2128 }
2129 
2130 void ColumnPrivate::setFormulVariableColumnsPath(int index, const QString& path) {
2131     if (!m_formulaData[index].setColumnPath(path))
2132         DEBUG(Q_FUNC_INFO << ": For some reason, there was already a column assigned");
2133 }
2134 
2135 void ColumnPrivate::setFormulVariableColumn(int index, Column* column) {
2136     if (m_formulaData.at(index).column()) // if there exists already a valid column, disconnect it first
2137         disconnect(m_formulaData.at(index).column(), nullptr, this, nullptr);
2138     m_formulaData[index].setColumn(column);
2139     connectFormulaColumn(column);
2140 }
2141 
2142 void ColumnPrivate::setFormulVariableColumn(Column* c) {
2143     for (auto& d : m_formulaData) {
2144         if (d.columnName() == c->path()) {
2145             d.setColumn(c);
2146             break;
2147         }
2148     }
2149 }
2150 
2151 struct PayloadColumn : public Payload {
2152     PayloadColumn(const QVector<Column::FormulaData>& data)
2153         : Payload(true)
2154         , formulaData(data) {
2155     }
2156     const QVector<Column::FormulaData>& formulaData;
2157 };
2158 
2159 #define COLUMN_FUNCTION(function_name, evaluation_function)                                                                                                    \
2160     double column##function_name(const char* variable, const std::weak_ptr<Payload> payload) {                                                                 \
2161         const auto p = std::dynamic_pointer_cast<PayloadColumn>(payload.lock());                                                                               \
2162         if (!p) {                                                                                                                                              \
2163             assert(p); /* Debug build */                                                                                                                       \
2164             return NAN;                                                                                                                                        \
2165         }                                                                                                                                                      \
2166         for (const auto& formulaData : p->formulaData) {                                                                                                       \
2167             if (formulaData.variableName().compare(QLatin1String(variable)) == 0)                                                                              \
2168                 return formulaData.column()->evaluation_function;                                                                                              \
2169         }                                                                                                                                                      \
2170         return NAN;                                                                                                                                            \
2171     }
2172 
2173 // Constant functions, which return always the same value independet of the row index
2174 COLUMN_FUNCTION(Size, statistics().size)
2175 COLUMN_FUNCTION(Min, minimum())
2176 COLUMN_FUNCTION(Max, maximum())
2177 COLUMN_FUNCTION(Mean, statistics().arithmeticMean)
2178 COLUMN_FUNCTION(Median, statistics().median)
2179 COLUMN_FUNCTION(Stdev, statistics().standardDeviation)
2180 COLUMN_FUNCTION(Var, statistics().variance)
2181 COLUMN_FUNCTION(Gm, statistics().geometricMean)
2182 COLUMN_FUNCTION(Hm, statistics().harmonicMean)
2183 COLUMN_FUNCTION(Chm, statistics().contraharmonicMean)
2184 COLUMN_FUNCTION(StatisticsMode, statistics().mode)
2185 COLUMN_FUNCTION(Quartile1, statistics().firstQuartile)
2186 COLUMN_FUNCTION(Quartile3, statistics().thirdQuartile)
2187 COLUMN_FUNCTION(Iqr, statistics().iqr)
2188 COLUMN_FUNCTION(Percentile1, statistics().percentile_1)
2189 COLUMN_FUNCTION(Percentile5, statistics().percentile_5)
2190 COLUMN_FUNCTION(Percentile10, statistics().percentile_10)
2191 COLUMN_FUNCTION(Percentile90, statistics().percentile_90)
2192 COLUMN_FUNCTION(Percentile95, statistics().percentile_95)
2193 COLUMN_FUNCTION(Percentile99, statistics().percentile_99)
2194 COLUMN_FUNCTION(Trimean, statistics().trimean)
2195 COLUMN_FUNCTION(Meandev, statistics().meanDeviation)
2196 COLUMN_FUNCTION(Meandevmedian, statistics().meanDeviationAroundMedian)
2197 COLUMN_FUNCTION(Mediandev, statistics().medianDeviation)
2198 COLUMN_FUNCTION(Skew, statistics().skewness)
2199 COLUMN_FUNCTION(Kurt, statistics().kurtosis)
2200 COLUMN_FUNCTION(Entropy, statistics().entropy)
2201 
2202 double columnQuantile(double p, const char* variable, const std::weak_ptr<Payload> payload) {
2203     const auto pd = std::dynamic_pointer_cast<PayloadColumn>(payload.lock());
2204     if (!pd) {
2205         assert(pd); // Debug build
2206         return NAN;
2207     }
2208 
2209     if (p < 0)
2210         return NAN;
2211 
2212     const Column* column = nullptr;
2213     for (const auto& formulaData : pd->formulaData) {
2214         if (formulaData.variableName().compare(QLatin1String(variable)) == 0) {
2215             column = formulaData.column();
2216             break;
2217         }
2218     }
2219     if (!column)
2220         return NAN;
2221 
2222     double value = 0.0;
2223     switch (column->columnMode()) { // all types
2224     case AbstractColumn::ColumnMode::Double: {
2225         auto data = reinterpret_cast<QVector<double>*>(column->data());
2226         value = nsl_stats_quantile(data->data(), 1, column->statistics().size, p, nsl_stats_quantile_type7);
2227         break;
2228     }
2229     case AbstractColumn::ColumnMode::Integer: {
2230         auto* intData = reinterpret_cast<QVector<int>*>(column->data());
2231 
2232         QVector<double> data = QVector<double>(); // copy data to double
2233         data.reserve(column->rowCount());
2234         for (auto v : *intData)
2235             data << static_cast<double>(v);
2236         value = nsl_stats_quantile(data.data(), 1, column->statistics().size, p, nsl_stats_quantile_type7);
2237         break;
2238     }
2239     case AbstractColumn::ColumnMode::BigInt: {
2240         auto* bigIntData = reinterpret_cast<QVector<qint64>*>(column->data());
2241 
2242         QVector<double> data = QVector<double>(); // copy data to double
2243         data.reserve(column->rowCount());
2244         for (auto v : *bigIntData)
2245             data << static_cast<double>(v);
2246         value = nsl_stats_quantile(data.data(), 1, column->statistics().size, p, nsl_stats_quantile_type7);
2247         break;
2248     }
2249     case AbstractColumn::ColumnMode::DateTime: // not supported yet
2250     case AbstractColumn::ColumnMode::Day:
2251     case AbstractColumn::ColumnMode::Month:
2252     case AbstractColumn::ColumnMode::Text:
2253         break;
2254     }
2255     return value;
2256 }
2257 
2258 double columnPercentile(double p, const char* variable, const std::weak_ptr<Payload> payload) {
2259     return columnQuantile(p / 100., variable, payload);
2260 }
2261 
2262 /*!
2263  * \sa FunctionValuesDialog::generate()
2264  */
2265 void ColumnPrivate::updateFormula() {
2266     if (m_formula.isEmpty())
2267         return;
2268     DEBUG(Q_FUNC_INFO)
2269     // determine variable names and the data vectors of the specified columns
2270     QVector<QVector<double>*> xVectors;
2271 
2272     bool valid = true;
2273     QStringList formulaVariableNames;
2274     int maxRowCount = 0;
2275 
2276     auto numberLocale = QLocale();
2277     // need to disable group separator since parser can't handle it
2278     numberLocale.setNumberOptions(QLocale::OmitGroupSeparator);
2279 
2280     for (const auto& formulaData : m_formulaData) {
2281         auto* column = formulaData.column();
2282         if (!column) {
2283             valid = false;
2284             break;
2285         }
2286         auto varName = formulaData.variableName();
2287         formulaVariableNames << varName;
2288 
2289         if (column->columnMode() == AbstractColumn::ColumnMode::Integer || column->columnMode() == AbstractColumn::ColumnMode::BigInt) {
2290             // convert integers to doubles first
2291             auto* xVector = new QVector<double>(column->rowCount());
2292             for (int i = 0; i < column->rowCount(); ++i)
2293                 (*xVector)[i] = column->valueAt(i);
2294 
2295             xVectors << xVector;
2296         } else
2297             xVectors << static_cast<QVector<double>*>(column->data());
2298 
2299         if (column->rowCount() > maxRowCount)
2300             maxRowCount = column->rowCount();
2301     }
2302 
2303     if (valid) {
2304         // resize the spreadsheet if one of the data vectors from
2305         // other spreadsheet(s) has more elements than the parent spreadsheet
2306         // and if the option "auto resize" is activated
2307         if (m_formulaAutoResize && rowCount() < maxRowCount) {
2308             auto* spreadsheet = static_cast<Spreadsheet*>(m_owner->parentAspect());
2309             // In the tests spreadsheet might not exist, because directly the column was created
2310             if (spreadsheet)
2311                 spreadsheet->setRowCount(maxRowCount);
2312         }
2313 
2314         // create new vector for storing the calculated values
2315         // the vectors with the variable data can be smaller then the result vector. So, not all values in the result vector might get initialized.
2316         //->"clean" the result vector first
2317         QVector<double> new_data(rowCount(), NAN);
2318 
2319         const auto payload = std::make_shared<PayloadColumn>(m_formulaData);
2320 
2321         // evaluate the expression for f(x_1, x_2, ...) and write the calculated values into a new vector.
2322         auto* parser = ExpressionParser::getInstance();
2323         parser->setSpecialFunction1(colfun_size, columnSize, payload);
2324         parser->setSpecialFunction1(colfun_min, columnMin, payload);
2325         parser->setSpecialFunction1(colfun_max, columnMax, payload);
2326         parser->setSpecialFunction1(colfun_mean, columnMean, payload);
2327         parser->setSpecialFunction1(colfun_median, columnMedian, payload);
2328         parser->setSpecialFunction1(colfun_stdev, columnStdev, payload);
2329         parser->setSpecialFunction1(colfun_var, columnVar, payload);
2330         parser->setSpecialFunction1(colfun_gm, columnGm, payload);
2331         parser->setSpecialFunction1(colfun_hm, columnHm, payload);
2332         parser->setSpecialFunction1(colfun_chm, columnChm, payload);
2333         parser->setSpecialFunction1(colfun_mode, columnStatisticsMode, payload);
2334         parser->setSpecialFunction1(colfun_quartile1, columnQuartile1, payload);
2335         parser->setSpecialFunction1(colfun_quartile3, columnQuartile3, payload);
2336         parser->setSpecialFunction1(colfun_iqr, columnIqr, payload);
2337         parser->setSpecialFunction1(colfun_percentile1, columnPercentile1, payload);
2338         parser->setSpecialFunction1(colfun_percentile5, columnPercentile5, payload);
2339         parser->setSpecialFunction1(colfun_percentile10, columnPercentile10, payload);
2340         parser->setSpecialFunction1(colfun_percentile90, columnPercentile90, payload);
2341         parser->setSpecialFunction1(colfun_percentile95, columnPercentile95, payload);
2342         parser->setSpecialFunction1(colfun_percentile99, columnPercentile99, payload);
2343         parser->setSpecialFunction1(colfun_trimean, columnTrimean, payload);
2344         parser->setSpecialFunction1(colfun_meandev, columnMeandev, payload);
2345         parser->setSpecialFunction1(colfun_meandevmedian, columnMeandevmedian, payload);
2346         parser->setSpecialFunction1(colfun_mediandev, columnMediandev, payload);
2347         parser->setSpecialFunction1(colfun_skew, columnSkew, payload);
2348         parser->setSpecialFunction1(colfun_kurt, columnKurt, payload);
2349         parser->setSpecialFunction1(colfun_entropy, columnEntropy, payload);
2350         parser->setSpecialFunction2(colfun_percentile, columnPercentile, payload);
2351         parser->setSpecialFunction2(colfun_quantile, columnQuantile, payload);
2352 
2353         QDEBUG(Q_FUNC_INFO << ", Calling evaluateCartesian(). formula: " << m_formula << ", var names: " << formulaVariableNames)
2354         parser->evaluateCartesian(m_formula, formulaVariableNames, xVectors, &new_data);
2355         DEBUG(Q_FUNC_INFO << ", Calling replaceValues()")
2356         replaceValues(-1, new_data);
2357 
2358         // initialize remaining rows with NAN
2359         // This will be done already in evaluateCartesian()
2360         // int remainingRows = rowCount() - maxRowCount;
2361         // if (remainingRows > 0) {
2362         //  QVector<double> emptyRows(remainingRows, NAN);
2363         //  replaceValues(maxRowCount, emptyRows);
2364         //}
2365     } else { // not valid
2366         QVector<double> new_data(rowCount(), NAN);
2367         replaceValues(-1, new_data);
2368     }
2369 
2370     DEBUG(Q_FUNC_INFO << " DONE")
2371 }
2372 
2373 void ColumnPrivate::formulaVariableColumnRemoved(const AbstractAspect* aspect) {
2374     const Column* column = dynamic_cast<const Column*>(aspect);
2375     disconnect(column, nullptr, this, nullptr);
2376     int index = -1;
2377     for (int i = 0; i < formulaData().count(); i++) {
2378         auto& d = formulaData().at(i);
2379         if (d.column() == column) {
2380             index = i;
2381             break;
2382         }
2383     }
2384     if (index != -1) {
2385         m_formulaData[index].setColumn(nullptr);
2386         DEBUG(Q_FUNC_INFO << ", calling updateFormula()")
2387         updateFormula();
2388     }
2389 }
2390 
2391 void ColumnPrivate::formulaVariableColumnAdded(const AbstractAspect* aspect) {
2392     PERFTRACE(QLatin1String(Q_FUNC_INFO));
2393     const auto& path = aspect->path();
2394     int index = -1;
2395     for (int i = 0; i < formulaData().count(); i++) {
2396         if (formulaData().at(i).columnName() == path) {
2397             index = i;
2398             break;
2399         }
2400     }
2401     if (index != -1) {
2402         const Column* column = dynamic_cast<const Column*>(aspect);
2403         m_formulaData[index].setColumn(const_cast<Column*>(column));
2404         DEBUG(Q_FUNC_INFO << ", calling updateFormula()")
2405         updateFormula();
2406     }
2407 }
2408 
2409 /**
2410  * \brief Return the formula associated with row 'row'
2411  */
2412 QString ColumnPrivate::formula(int row) const {
2413     return m_formulas.value(row);
2414 }
2415 
2416 /**
2417  * \brief Return the intervals that have associated formulas
2418  *
2419  * This can be used to make a list of formulas with their intervals.
2420  * Here is some example code:
2421  *
2422  * \code
2423  * QStringList list;
2424  * QVector< Interval<int> > intervals = my_column.formulaIntervals();
2425  * foreach(Interval<int> interval, intervals)
2426  *  list << QString(interval.toString() + ": " + my_column.formula(interval.start()));
2427  * \endcode
2428  */
2429 QVector<Interval<int>> ColumnPrivate::formulaIntervals() const {
2430     return m_formulas.intervals();
2431 }
2432 
2433 /**
2434  * \brief Set a formula string for an interval of rows
2435  */
2436 void ColumnPrivate::setFormula(const Interval<int>& i, const QString& formula) {
2437     m_formulas.setValue(i, formula);
2438 }
2439 
2440 /**
2441  * \brief Overloaded function for convenience
2442  */
2443 void ColumnPrivate::setFormula(int row, const QString& formula) {
2444     setFormula(Interval<int>(row, row), formula);
2445 }
2446 
2447 /**
2448  * \brief Clear all formulas
2449  */
2450 void ColumnPrivate::clearFormulas() {
2451     m_formulas.clear();
2452 }
2453 //@}
2454 
2455 ////////////////////////////////////////////////////////////////////////////////
2456 //! \name type specific functions
2457 //@{
2458 ////////////////////////////////////////////////////////////////////////////////
2459 void ColumnPrivate::setValueAt(int row, int new_value) {
2460     setIntegerAt(row, new_value);
2461 }
2462 
2463 void ColumnPrivate::setValueAt(int row, qint64 new_value) {
2464     setBigIntAt(row, new_value);
2465 }
2466 
2467 void ColumnPrivate::setValueAt(int row, QDateTime new_value) {
2468     setDateTimeAt(row, new_value);
2469 }
2470 
2471 void ColumnPrivate::setValueAt(int row, QString new_value) {
2472     setTextAt(row, new_value);
2473 }
2474 
2475 void ColumnPrivate::replaceValues(int first, const QVector<int>& new_values) {
2476     replaceInteger(first, new_values);
2477 }
2478 
2479 void ColumnPrivate::replaceValues(int first, const QVector<qint64>& new_values) {
2480     replaceBigInt(first, new_values);
2481 }
2482 
2483 void ColumnPrivate::replaceValues(int first, const QVector<QDateTime>& new_values) {
2484     replaceDateTimes(first, new_values);
2485 }
2486 
2487 void ColumnPrivate::replaceValues(int first, const QVector<QString>& new_values) {
2488     replaceTexts(first, new_values);
2489 }
2490 
2491 /**
2492  * \brief Return the content of row 'row'.
2493  *
2494  * Use this only when columnMode() is Text
2495  */
2496 QString ColumnPrivate::textAt(int row) const {
2497     if (!m_data || m_columnMode != AbstractColumn::ColumnMode::Text)
2498         return {};
2499     return static_cast<QVector<QString>*>(m_data)->value(row);
2500 }
2501 
2502 /**
2503  * \brief Return the date part of row 'row'
2504  *
2505  * Use this only when columnMode() is DateTime, Month or Day
2506  */
2507 QDate ColumnPrivate::dateAt(int row) const {
2508     if (!m_data
2509         || (m_columnMode != AbstractColumn::ColumnMode::DateTime && m_columnMode != AbstractColumn::ColumnMode::Month
2510             && m_columnMode != AbstractColumn::ColumnMode::Day))
2511         return QDate{};
2512     return dateTimeAt(row).date();
2513 }
2514 
2515 /**
2516  * \brief Return the time part of row 'row'
2517  *
2518  * Use this only when columnMode() is DateTime, Month or Day
2519  */
2520 QTime ColumnPrivate::timeAt(int row) const {
2521     if (!m_data
2522         || (m_columnMode != AbstractColumn::ColumnMode::DateTime && m_columnMode != AbstractColumn::ColumnMode::Month
2523             && m_columnMode != AbstractColumn::ColumnMode::Day))
2524         return QTime{};
2525     return dateTimeAt(row).time();
2526 }
2527 
2528 /**
2529  * \brief Return the QDateTime in row 'row'
2530  *
2531  * Use this only when columnMode() is DateTime, Month or Day
2532  */
2533 QDateTime ColumnPrivate::dateTimeAt(int row) const {
2534     if (!m_data
2535         || (m_columnMode != AbstractColumn::ColumnMode::DateTime && m_columnMode != AbstractColumn::ColumnMode::Month
2536             && m_columnMode != AbstractColumn::ColumnMode::Day))
2537         return QDateTime();
2538     return static_cast<QVector<QDateTime>*>(m_data)->value(row);
2539 }
2540 
2541 double ColumnPrivate::doubleAt(int index) const {
2542     if (!m_data)
2543         return NAN;
2544 
2545     return static_cast<QVector<double>*>(m_data)->value(index, NAN);
2546 }
2547 
2548 /**
2549  * \brief Return the double value at index 'index' for columns with type Numeric, Integer or BigInt.
2550  * This function has to be used everywhere where the exact type (double, int or qint64) is not relevant for numerical calculations.
2551  * For cases where the integer value is needed without any implicit conversions, \sa integerAt() has to be used.
2552  */
2553 double ColumnPrivate::valueAt(int index) const {
2554     if (!m_data)
2555         return NAN;
2556 
2557     switch (m_columnMode) {
2558     case AbstractColumn::ColumnMode::Double:
2559         return static_cast<QVector<double>*>(m_data)->value(index, NAN);
2560     case AbstractColumn::ColumnMode::Integer:
2561         return static_cast<QVector<int>*>(m_data)->value(index, 0);
2562     case AbstractColumn::ColumnMode::BigInt:
2563         return static_cast<QVector<qint64>*>(m_data)->value(index, 0);
2564     case AbstractColumn::ColumnMode::DateTime:
2565         return static_cast<QVector<QDateTime>*>(m_data)->value(index).toMSecsSinceEpoch();
2566     case AbstractColumn::ColumnMode::Month: // Fall through
2567     case AbstractColumn::ColumnMode::Day: // Fall through
2568     case AbstractColumn::ColumnMode::Text: // Fall through
2569         break;
2570     }
2571     return NAN;
2572 }
2573 
2574 /**
2575  * \brief Return the int value in row 'row'
2576  */
2577 int ColumnPrivate::integerAt(int row) const {
2578     if (!m_data || m_columnMode != AbstractColumn::ColumnMode::Integer)
2579         return 0;
2580     return static_cast<QVector<int>*>(m_data)->value(row, 0);
2581 }
2582 
2583 /**
2584  * \brief Return the bigint value in row 'row'
2585  */
2586 qint64 ColumnPrivate::bigIntAt(int row) const {
2587     if (!m_data || m_columnMode != AbstractColumn::ColumnMode::BigInt)
2588         return 0;
2589     return static_cast<QVector<qint64>*>(m_data)->value(row, 0);
2590 }
2591 
2592 void ColumnPrivate::invalidate() {
2593     available.setUnavailable();
2594 }
2595 
2596 /**
2597  * \brief Set the content of row 'row'
2598  *
2599  * Use this only when columnMode() is Text
2600  */
2601 void ColumnPrivate::setTextAt(int row, const QString& new_value) {
2602     if (m_columnMode != AbstractColumn::ColumnMode::Text)
2603         return;
2604 
2605     setValueAtPrivate<QString>(row, new_value);
2606 }
2607 
2608 /**
2609  * \brief Replace a range of values
2610  *
2611  * Use this only when columnMode() is Text
2612  */
2613 void ColumnPrivate::replaceTexts(int first, const QVector<QString>& new_values) {
2614     if (m_columnMode != AbstractColumn::ColumnMode::Text)
2615         return;
2616 
2617     replaceValuePrivate<QString>(first, new_values);
2618 }
2619 
2620 int ColumnPrivate::dictionaryIndex(int row) const {
2621     if (!available.dictionary)
2622         const_cast<ColumnPrivate*>(this)->initDictionary();
2623 
2624     const auto& value = textAt(row);
2625     int index = 0;
2626     auto it = m_dictionary.constBegin();
2627     while (it != m_dictionary.constEnd()) {
2628         if (*it == value)
2629             break;
2630         ++index;
2631         ++it;
2632     }
2633 
2634     return index;
2635 }
2636 
2637 const QMap<QString, int>& ColumnPrivate::frequencies() const {
2638     if (!available.dictionary)
2639         const_cast<ColumnPrivate*>(this)->initDictionary();
2640 
2641     return m_dictionaryFrequencies;
2642 }
2643 
2644 void ColumnPrivate::initDictionary() {
2645     m_dictionary.clear();
2646     m_dictionaryFrequencies.clear();
2647     if (!m_data || columnMode() != AbstractColumn::ColumnMode::Text)
2648         return;
2649 
2650     auto data = static_cast<QVector<QString>*>(m_data);
2651     for (auto& value : *data) {
2652         if (value.isEmpty())
2653             continue;
2654 
2655         if (!m_dictionary.contains(value))
2656             m_dictionary << value;
2657 
2658         if (m_dictionaryFrequencies.constFind(value) == m_dictionaryFrequencies.constEnd())
2659             m_dictionaryFrequencies[value] = 1;
2660         else
2661             m_dictionaryFrequencies[value]++;
2662     }
2663 
2664     available.dictionary = true;
2665 }
2666 
2667 /**
2668  * \brief Set the content of row 'row'
2669  *
2670  * Use this only when columnMode() is DateTime, Month or Day
2671  */
2672 void ColumnPrivate::setDateAt(int row, QDate new_value) {
2673     if (m_columnMode != AbstractColumn::ColumnMode::DateTime && m_columnMode != AbstractColumn::ColumnMode::Month
2674         && m_columnMode != AbstractColumn::ColumnMode::Day)
2675         return;
2676 
2677     if (!m_data)
2678         initDataContainer();
2679 
2680     if (!m_data) // failed to allocate memory
2681         return;
2682 
2683     setDateTimeAt(row, QDateTime(new_value, timeAt(row)));
2684 }
2685 
2686 /**
2687  * \brief Set the content of row 'row'
2688  *
2689  * Use this only when columnMode() is DateTime, Month or Day
2690  */
2691 void ColumnPrivate::setTimeAt(int row, QTime new_value) {
2692     if (m_columnMode != AbstractColumn::ColumnMode::DateTime && m_columnMode != AbstractColumn::ColumnMode::Month
2693         && m_columnMode != AbstractColumn::ColumnMode::Day)
2694         return;
2695 
2696     if (!m_data)
2697         initDataContainer();
2698 
2699     if (!m_data) // failed to allocate memory
2700         return;
2701 
2702     setDateTimeAt(row, QDateTime(dateAt(row), new_value));
2703 }
2704 
2705 /**
2706  * \brief Set the content of row 'row'
2707  *
2708  * Use this only when columnMode() is DateTime, Month or Day
2709  */
2710 void ColumnPrivate::setDateTimeAt(int row, const QDateTime& new_value) {
2711     if (m_columnMode != AbstractColumn::ColumnMode::DateTime && m_columnMode != AbstractColumn::ColumnMode::Month
2712         && m_columnMode != AbstractColumn::ColumnMode::Day)
2713         return;
2714 
2715     setValueAtPrivate<QDateTime>(row, new_value);
2716 }
2717 
2718 /**
2719  * \brief Replace a range of values
2720  * \param first first index which should be replaced. If first < 0, the complete vector
2721  * will be replaced
2722  * \param new_values
2723  * Use this only when columnMode() is DateTime, Month or Day
2724  */
2725 void ColumnPrivate::replaceDateTimes(int first, const QVector<QDateTime>& new_values) {
2726     if (m_columnMode != AbstractColumn::ColumnMode::DateTime && m_columnMode != AbstractColumn::ColumnMode::Month
2727         && m_columnMode != AbstractColumn::ColumnMode::Day)
2728         return;
2729 
2730     replaceValuePrivate<QDateTime>(first, new_values);
2731 }
2732 
2733 /**
2734  * \brief Set the content of row 'row'
2735  *
2736  * Use this only when columnMode() is Numeric
2737  */
2738 void ColumnPrivate::setValueAt(int row, double new_value) {
2739     // DEBUG(Q_FUNC_INFO);
2740     if (m_columnMode != AbstractColumn::ColumnMode::Double)
2741         return;
2742 
2743     setValueAtPrivate<double>(row, new_value);
2744 }
2745 
2746 /**
2747  * \brief Replace a range of values
2748  *
2749  * Use this only when columnMode() is Numeric
2750  */
2751 void ColumnPrivate::replaceValues(int first, const QVector<double>& new_values) {
2752     // DEBUG(Q_FUNC_INFO);
2753     if (m_columnMode != AbstractColumn::ColumnMode::Double)
2754         return;
2755 
2756     if (!m_data) {
2757         const bool resize = (first >= 0);
2758         if (!initDataContainer(resize))
2759             return; // failed to allocate memory
2760     }
2761 
2762     invalidate();
2763 
2764     Q_EMIT m_owner->dataAboutToChange(m_owner);
2765     if (first < 0)
2766         *static_cast<QVector<double>*>(m_data) = new_values;
2767     else {
2768         const int num_rows = new_values.size();
2769         resizeTo(first + num_rows);
2770 
2771         double* ptr = static_cast<QVector<double>*>(m_data)->data();
2772         for (int i = 0; i < num_rows; ++i)
2773             ptr[first + i] = new_values.at(i);
2774     }
2775 
2776     if (!m_owner->m_suppressDataChangedSignal)
2777         Q_EMIT m_owner->dataChanged(m_owner);
2778 }
2779 
2780 void ColumnPrivate::addValueLabel(const QString& value, const QString& label) {
2781     m_labels.add(value, label);
2782 }
2783 
2784 void ColumnPrivate::addValueLabel(const QDateTime& value, const QString& label) {
2785     m_labels.add(value, label);
2786 }
2787 
2788 void ColumnPrivate::addValueLabel(double value, const QString& label) {
2789     m_labels.add(value, label);
2790 }
2791 
2792 void ColumnPrivate::addValueLabel(int value, const QString& label) {
2793     m_labels.add(value, label);
2794 }
2795 
2796 void ColumnPrivate::addValueLabel(qint64 value, const QString& label) {
2797     m_labels.add(value, label);
2798 }
2799 
2800 /**
2801  * \brief Set the content of row 'row'
2802  *
2803  * Use this only when columnMode() is Integer
2804  */
2805 void ColumnPrivate::setIntegerAt(int row, int new_value) {
2806     // DEBUG(Q_FUNC_INFO);
2807     if (m_columnMode != AbstractColumn::ColumnMode::Integer)
2808         return;
2809 
2810     setValueAtPrivate<int>(row, new_value);
2811 }
2812 
2813 /**
2814  * \brief Replace a range of values
2815  *
2816  * Use this only when columnMode() is Integer
2817  */
2818 void ColumnPrivate::replaceInteger(int first, const QVector<int>& new_values) {
2819     // DEBUG(Q_FUNC_INFO);
2820     if (m_columnMode != AbstractColumn::ColumnMode::Integer)
2821         return;
2822 
2823     replaceValuePrivate<int>(first, new_values);
2824 }
2825 
2826 /**
2827  * \brief Set the content of row 'row'
2828  *
2829  * Use this only when columnMode() is BigInt
2830  */
2831 void ColumnPrivate::setBigIntAt(int row, qint64 new_value) {
2832     // DEBUG(Q_FUNC_INFO);
2833     if (m_columnMode != AbstractColumn::ColumnMode::BigInt)
2834         return;
2835 
2836     setValueAtPrivate<qint64>(row, new_value);
2837 }
2838 
2839 /**
2840  * \brief Replace a range of values
2841  *
2842  * Use this only when columnMode() is BigInt
2843  */
2844 void ColumnPrivate::replaceBigInt(int first, const QVector<qint64>& new_values) {
2845     // DEBUG(Q_FUNC_INFO);
2846     if (m_columnMode != AbstractColumn::ColumnMode::BigInt)
2847         return;
2848 
2849     replaceValuePrivate<qint64>(first, new_values);
2850 }
2851 
2852 /*!
2853  * Updates the properties. Will be called, when data in the column changed.
2854  * The properties will be used to speed up some algorithms.
2855  * See where variable properties will be used.
2856  */
2857 void ColumnPrivate::updateProperties() {
2858     // DEBUG(Q_FUNC_INFO);
2859 
2860     // TODO: for double Properties::Constant will never be used. Use an epsilon (difference smaller than epsilon is zero)
2861     int rows = rowCount();
2862     if (rowCount() == 0) {
2863         properties = AbstractColumn::Properties::No;
2864         available.properties = true;
2865         return;
2866     }
2867 
2868     double prevValue = NAN;
2869     int prevValueInt = 0;
2870     qint64 prevValueBigInt = 0;
2871     qint64 prevValueDatetime = 0;
2872 
2873     if (m_columnMode == AbstractColumn::ColumnMode::Integer)
2874         prevValueInt = integerAt(0);
2875     else if (m_columnMode == AbstractColumn::ColumnMode::BigInt)
2876         prevValueBigInt = bigIntAt(0);
2877     else if (m_columnMode == AbstractColumn::ColumnMode::Double)
2878         prevValue = valueAt(0);
2879     else if (m_columnMode == AbstractColumn::ColumnMode::DateTime || m_columnMode == AbstractColumn::ColumnMode::Month
2880              || m_columnMode == AbstractColumn::ColumnMode::Day)
2881         prevValueDatetime = dateTimeAt(0).toMSecsSinceEpoch();
2882     else {
2883         properties = AbstractColumn::Properties::No;
2884         available.properties = true;
2885         return;
2886     }
2887 
2888     int monotonic_decreasing = -1;
2889     int monotonic_increasing = -1;
2890 
2891     double value;
2892     int valueInt;
2893     qint64 valueBigInt;
2894     qint64 valueDateTime;
2895     for (int row = 1; row < rows; row++) {
2896         if (!m_owner->isValid(row) || m_owner->isMasked(row)) {
2897             // if there is one invalid or masked value, the property is No, because
2898             // otherwise it's difficult to find the correct index in indexForValue().
2899             // You don't know if you should increase the index or decrease it when
2900             // you hit an invalid value
2901             properties = AbstractColumn::Properties::No;
2902             available.properties = true;
2903             return;
2904         }
2905 
2906         if (m_columnMode == AbstractColumn::ColumnMode::Integer) {
2907             valueInt = integerAt(row);
2908 
2909             if (valueInt > prevValueInt) {
2910                 monotonic_decreasing = 0;
2911                 if (monotonic_increasing < 0)
2912                     monotonic_increasing = 1;
2913                 else if (monotonic_increasing == 0)
2914                     break; // when nor increasing, nor decreasing, break
2915 
2916             } else if (valueInt < prevValueInt) {
2917                 monotonic_increasing = 0;
2918                 if (monotonic_decreasing < 0)
2919                     monotonic_decreasing = 1;
2920                 else if (monotonic_decreasing == 0)
2921                     break; // when nor increasing, nor decreasing, break
2922 
2923             } else {
2924                 if (monotonic_increasing < 0 && monotonic_decreasing < 0) {
2925                     monotonic_decreasing = 1;
2926                     monotonic_increasing = 1;
2927                 }
2928             }
2929 
2930             prevValueInt = valueInt;
2931         } else if (m_columnMode == AbstractColumn::ColumnMode::BigInt) {
2932             valueBigInt = bigIntAt(row);
2933 
2934             if (valueBigInt > prevValueBigInt) {
2935                 monotonic_decreasing = 0;
2936                 if (monotonic_increasing < 0)
2937                     monotonic_increasing = 1;
2938                 else if (monotonic_increasing == 0)
2939                     break; // when nor increasing, nor decreasing, break
2940 
2941             } else if (valueBigInt < prevValueBigInt) {
2942                 monotonic_increasing = 0;
2943                 if (monotonic_decreasing < 0)
2944                     monotonic_decreasing = 1;
2945                 else if (monotonic_decreasing == 0)
2946                     break; // when nor increasing, nor decreasing, break
2947 
2948             } else {
2949                 if (monotonic_increasing < 0 && monotonic_decreasing < 0) {
2950                     monotonic_decreasing = 1;
2951                     monotonic_increasing = 1;
2952                 }
2953             }
2954 
2955             prevValueBigInt = valueBigInt;
2956         } else if (m_columnMode == AbstractColumn::ColumnMode::Double) {
2957             value = valueAt(row);
2958 
2959             if (std::isnan(value)) {
2960                 monotonic_increasing = 0;
2961                 monotonic_decreasing = 0;
2962                 break;
2963             }
2964 
2965             if (value > prevValue) {
2966                 monotonic_decreasing = 0;
2967                 if (monotonic_increasing < 0)
2968                     monotonic_increasing = 1;
2969                 else if (monotonic_increasing == 0)
2970                     break; // when nor increasing, nor decreasing, break
2971 
2972             } else if (value < prevValue) {
2973                 monotonic_increasing = 0;
2974                 if (monotonic_decreasing < 0)
2975                     monotonic_decreasing = 1;
2976                 else if (monotonic_decreasing == 0)
2977                     break; // when nor increasing, nor decreasing, break
2978 
2979             } else {
2980                 if (monotonic_increasing < 0 && monotonic_decreasing < 0) {
2981                     monotonic_decreasing = 1;
2982                     monotonic_increasing = 1;
2983                 }
2984             }
2985 
2986             prevValue = value;
2987         } else if (m_columnMode == AbstractColumn::ColumnMode::DateTime || m_columnMode == AbstractColumn::ColumnMode::Month
2988                    || m_columnMode == AbstractColumn::ColumnMode::Day) {
2989             valueDateTime = dateTimeAt(row).toMSecsSinceEpoch();
2990 
2991             if (valueDateTime > prevValueDatetime) {
2992                 monotonic_decreasing = 0;
2993                 if (monotonic_increasing < 0)
2994                     monotonic_increasing = 1;
2995                 else if (monotonic_increasing == 0)
2996                     break; // when nor increasing, nor decreasing, break
2997 
2998             } else if (valueDateTime < prevValueDatetime) {
2999                 monotonic_increasing = 0;
3000                 if (monotonic_decreasing < 0)
3001                     monotonic_decreasing = 1;
3002                 else if (monotonic_decreasing == 0)
3003                     break; // when nor increasing, nor decreasing, break
3004 
3005             } else {
3006                 if (monotonic_increasing < 0 && monotonic_decreasing < 0) {
3007                     monotonic_decreasing = 1;
3008                     monotonic_increasing = 1;
3009                 }
3010             }
3011 
3012             prevValueDatetime = valueDateTime;
3013         }
3014     }
3015 
3016     properties = AbstractColumn::Properties::NonMonotonic;
3017     if (monotonic_increasing > 0 && monotonic_decreasing > 0) {
3018         properties = AbstractColumn::Properties::Constant;
3019         DEBUG(" setting column CONSTANT")
3020     } else if (monotonic_decreasing > 0) {
3021         properties = AbstractColumn::Properties::MonotonicDecreasing;
3022         DEBUG(" setting column MONTONIC DECREASING")
3023     } else if (monotonic_increasing > 0) {
3024         properties = AbstractColumn::Properties::MonotonicIncreasing;
3025         DEBUG(" setting column MONTONIC INCREASING")
3026     }
3027 
3028     available.properties = true;
3029 }
3030 
3031 ////////////////////////////////////////////////////////////////////////////////
3032 //@}
3033 ////////////////////////////////////////////////////////////////////////////////
3034 
3035 /**
3036  * \brief Return the interval attribute representing the formula strings
3037  */
3038 IntervalAttribute<QString> ColumnPrivate::formulaAttribute() const {
3039     return m_formulas;
3040 }
3041 
3042 /**
3043  * \brief Replace the interval attribute for the formula strings
3044  */
3045 void ColumnPrivate::replaceFormulas(const IntervalAttribute<QString>& formulas) {
3046     m_formulas = formulas;
3047 }
3048 
3049 void ColumnPrivate::calculateStatistics() {
3050     PERFTRACE(QStringLiteral("calculate column statistics"));
3051     statistics = AbstractColumn::ColumnStatistics();
3052 
3053     if (m_owner->columnMode() == AbstractColumn::ColumnMode::Text) {
3054         calculateTextStatistics();
3055         return;
3056     }
3057 
3058     if (!m_owner->isNumeric()) {
3059         calculateDateTimeStatistics();
3060         return;
3061     }
3062 
3063     // ######  location measures  #######
3064     int rowValuesSize = rowCount();
3065     double columnSum = 0.0;
3066     double columnProduct = 1.0;
3067     double columnSumNeg = 0.0;
3068     double columnSumSquare = 0.0;
3069     statistics.minimum = INFINITY;
3070     statistics.maximum = -INFINITY;
3071     std::unordered_map<double, int> frequencyOfValues;
3072     QVector<double> rowData;
3073     rowData.reserve(rowValuesSize);
3074 
3075     for (int row = 0; row < rowValuesSize; ++row) {
3076         double val = valueAt(row);
3077         if (std::isnan(val) || m_owner->isMasked(row))
3078             continue;
3079 
3080         if (val < statistics.minimum)
3081             statistics.minimum = val;
3082         if (val > statistics.maximum)
3083             statistics.maximum = val;
3084         columnSum += val;
3085         columnSumNeg += (1.0 / val); // will be Inf when val == 0
3086         columnSumSquare += val * val;
3087         columnProduct *= val;
3088         if (frequencyOfValues.find(val) != frequencyOfValues.end())
3089             frequencyOfValues.operator[](val)++;
3090         else
3091             frequencyOfValues.insert(std::make_pair(val, 1));
3092         rowData.push_back(val);
3093     }
3094 
3095     const size_t notNanCount = rowData.size();
3096 
3097     if (notNanCount == 0) {
3098         available.statistics = true;
3099         available.min = true;
3100         available.max = true;
3101         return;
3102     }
3103 
3104     if (rowData.size() < rowValuesSize)
3105         rowData.squeeze();
3106 
3107     statistics.size = notNanCount;
3108     statistics.arithmeticMean = columnSum / notNanCount;
3109 
3110     // geometric mean
3111     if (statistics.minimum <= -100.) // invalid
3112         statistics.geometricMean = NAN;
3113     else if (statistics.minimum < 0) { // interpret as percentage (/100) and add 1
3114         columnProduct = 1.; // recalculate
3115         for (auto val : rowData)
3116             columnProduct *= val / 100. + 1.;
3117         // n-th root and convert back to percentage changes
3118         statistics.geometricMean = 100. * (std::pow(columnProduct, 1.0 / notNanCount) - 1.);
3119     } else if (statistics.minimum == 0) { // replace zero values with 1
3120         columnProduct = 1.; // recalculate
3121         for (auto val : rowData)
3122             columnProduct *= (val == 0.) ? 1. : val;
3123         statistics.geometricMean = std::pow(columnProduct, 1.0 / notNanCount);
3124     } else
3125         statistics.geometricMean = std::pow(columnProduct, 1.0 / notNanCount);
3126 
3127     statistics.harmonicMean = notNanCount / columnSumNeg;
3128     statistics.contraharmonicMean = columnSumSquare / columnSum;
3129 
3130     // calculate the mode, the most frequent value in the data set
3131     int maxFreq = 0;
3132     double mode = NAN;
3133     for (const auto& it : frequencyOfValues) {
3134         if (it.second > maxFreq) {
3135             maxFreq = it.second;
3136             mode = it.first;
3137         }
3138     }
3139     // check how many times the max frequency occurs in the data set.
3140     // if more than once, we have a multi-modal distribution and don't show any mode
3141     int maxFreqOccurance = 0;
3142     for (const auto& it : frequencyOfValues) {
3143         if (it.second == maxFreq)
3144             ++maxFreqOccurance;
3145 
3146         if (maxFreqOccurance > 1) {
3147             mode = NAN;
3148             break;
3149         }
3150     }
3151     statistics.mode = mode;
3152 
3153     // sort the data to calculate the percentiles
3154     std::sort(rowData.begin(), rowData.end());
3155     statistics.firstQuartile = gsl_stats_quantile_from_sorted_data(rowData.constData(), 1, notNanCount, 0.25);
3156     statistics.median = gsl_stats_quantile_from_sorted_data(rowData.constData(), 1, notNanCount, 0.50);
3157     statistics.thirdQuartile = gsl_stats_quantile_from_sorted_data(rowData.constData(), 1, notNanCount, 0.75);
3158     statistics.percentile_1 = gsl_stats_quantile_from_sorted_data(rowData.constData(), 1, notNanCount, 0.01);
3159     statistics.percentile_5 = gsl_stats_quantile_from_sorted_data(rowData.constData(), 1, notNanCount, 0.05);
3160     statistics.percentile_10 = gsl_stats_quantile_from_sorted_data(rowData.constData(), 1, notNanCount, 0.1);
3161     statistics.percentile_90 = gsl_stats_quantile_from_sorted_data(rowData.constData(), 1, notNanCount, 0.9);
3162     statistics.percentile_95 = gsl_stats_quantile_from_sorted_data(rowData.constData(), 1, notNanCount, 0.95);
3163     statistics.percentile_99 = gsl_stats_quantile_from_sorted_data(rowData.constData(), 1, notNanCount, 0.99);
3164     statistics.iqr = statistics.thirdQuartile - statistics.firstQuartile;
3165     statistics.trimean = (statistics.firstQuartile + 2. * statistics.median + statistics.thirdQuartile) / 4.;
3166 
3167     // ######  dispersion and shape measures  #######
3168     statistics.variance = 0.;
3169     statistics.meanDeviation = 0.;
3170     statistics.meanDeviationAroundMedian = 0.;
3171     double centralMoment_r3 = 0.;
3172     double centralMoment_r4 = 0.;
3173     QVector<double> absoluteMedianList;
3174     absoluteMedianList.reserve(notNanCount);
3175     absoluteMedianList.resize(notNanCount);
3176 
3177     for (size_t row = 0; row < notNanCount; ++row) {
3178         double val = rowData.value(row);
3179         statistics.variance += gsl_pow_2(val - statistics.arithmeticMean);
3180         statistics.meanDeviation += std::abs(val - statistics.arithmeticMean);
3181 
3182         absoluteMedianList[row] = std::abs(val - statistics.median);
3183         statistics.meanDeviationAroundMedian += absoluteMedianList[row];
3184 
3185         centralMoment_r3 += gsl_pow_3(val - statistics.arithmeticMean);
3186         centralMoment_r4 += gsl_pow_4(val - statistics.arithmeticMean);
3187     }
3188 
3189     double centralMoment_r2 = statistics.variance / notNanCount;
3190 
3191     // normalize
3192     statistics.variance = (notNanCount != 1) ? statistics.variance / (notNanCount - 1) : NAN;
3193     statistics.meanDeviationAroundMedian = statistics.meanDeviationAroundMedian / notNanCount;
3194     statistics.meanDeviation = statistics.meanDeviation / notNanCount;
3195 
3196     // standard deviation
3197     statistics.standardDeviation = std::sqrt(statistics.variance);
3198 
3199     //"median absolute deviation" - the median of the absolute deviations from the data's median.
3200     std::sort(absoluteMedianList.begin(), absoluteMedianList.end());
3201     statistics.medianDeviation = gsl_stats_quantile_from_sorted_data(absoluteMedianList.data(), 1, notNanCount, 0.50);
3202 
3203     // skewness and kurtosis
3204     centralMoment_r3 /= notNanCount;
3205     centralMoment_r4 /= notNanCount;
3206     statistics.skewness = centralMoment_r3 / gsl_pow_3(std::sqrt(centralMoment_r2));
3207     statistics.kurtosis = centralMoment_r4 / gsl_pow_2(centralMoment_r2);
3208 
3209     // entropy
3210     double entropy = 0.;
3211     for (const auto& v : frequencyOfValues) {
3212         const double frequencyNorm = static_cast<double>(v.second) / notNanCount;
3213         entropy += (frequencyNorm * std::log2(frequencyNorm));
3214     }
3215 
3216     statistics.entropy = -entropy;
3217 
3218     available.statistics = true;
3219     available.min = true;
3220     available.max = true;
3221 }
3222 
3223 void ColumnPrivate::calculateTextStatistics() {
3224     if (!available.dictionary)
3225         initDictionary();
3226 
3227     int valid = 0;
3228     for (int row = 0; row < rowCount(); ++row) {
3229         if (m_owner->isMasked(row))
3230             continue;
3231 
3232         ++valid;
3233     }
3234 
3235     statistics.size = valid;
3236     statistics.unique = m_dictionary.count();
3237     available.statistics = true;
3238 }
3239 
3240 void ColumnPrivate::calculateDateTimeStatistics() {
3241     statistics.minimum = INFINITY;
3242     statistics.maximum = -INFINITY;
3243 
3244     int valid = 0;
3245     for (int row = 0; row < rowCount(); ++row) {
3246         if (m_owner->isMasked(row))
3247             continue;
3248 
3249         const auto& value = dateTimeAt(row);
3250         if (!value.isValid())
3251             continue;
3252 
3253         quint64 val = value.toMSecsSinceEpoch();
3254         if (val < statistics.minimum)
3255             statistics.minimum = val;
3256         if (val > statistics.maximum)
3257             statistics.maximum = val;
3258 
3259         ++valid;
3260     }
3261 
3262     statistics.size = valid;
3263     available.statistics = true;
3264 }