File indexing completed on 2024-06-23 03:46:09

0001 /*
0002     File                 : ColumnPrivate.h
0003     Project              : LabPlot
0004     Description          : Private data class of Column
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2007, 2008 Tilman Benkert <thzs@gmx.net>
0007     SPDX-FileCopyrightText: 2013-2022 Alexander Semke <alexander.semke@web.de>
0008     SPDX-FileCopyrightText: 2020 Stefan Gerlach <stefan.gerlach@uni.kn>
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #ifndef COLUMNPRIVATE_H
0013 #define COLUMNPRIVATE_H
0014 
0015 #include "backend/core/AbstractColumn.h"
0016 #include "backend/core/column/Column.h"
0017 #include "backend/lib/IntervalAttribute.h"
0018 
0019 #include <QMap>
0020 
0021 class Column;
0022 class ColumnSetGlobalFormulaCmd;
0023 
0024 class ColumnPrivate : public QObject {
0025     Q_OBJECT
0026 
0027 public:
0028     ColumnPrivate(Column*, AbstractColumn::ColumnMode);
0029     ~ColumnPrivate() override;
0030     ColumnPrivate(Column*, AbstractColumn::ColumnMode, void*);
0031 
0032     bool initDataContainer(bool resize = true);
0033     void initIOFilters();
0034 
0035     AbstractColumn::ColumnMode columnMode() const;
0036     void setColumnMode(AbstractColumn::ColumnMode);
0037 
0038     bool copy(const AbstractColumn*);
0039     bool copy(const AbstractColumn*, int source_start, int dest_start, int num_rows);
0040     bool copy(const ColumnPrivate*);
0041     bool copy(const ColumnPrivate*, int source_start, int dest_start, int num_rows);
0042 
0043     int indexForValue(double x) const;
0044 
0045     int rowCount() const;
0046     int rowCount(double min, double max) const;
0047     int availableRowCount(int max = -1) const; // valid rows (stops when max rows found)
0048     void resizeTo(int);
0049 
0050     void insertRows(int before, int count);
0051     void removeRows(int first, int count);
0052     QString name() const;
0053 
0054     AbstractColumn::PlotDesignation plotDesignation() const;
0055     void setPlotDesignation(AbstractColumn::PlotDesignation);
0056 
0057     int width() const;
0058     void setWidth(int);
0059 
0060     void setData(void*);
0061     void* data() const;
0062     void deleteData();
0063     bool valueLabelsInitialized() const;
0064     void removeValueLabel(const QString&);
0065     void setLabelsMode(Column::ColumnMode mode);
0066     void valueLabelsRemoveAll();
0067     double valueLabelsMinimum();
0068     double valueLabelsMaximum();
0069 
0070     AbstractSimpleFilter* inputFilter() const;
0071     AbstractSimpleFilter* outputFilter() const;
0072 
0073     void replaceModeData(AbstractColumn::ColumnMode, void* data, AbstractSimpleFilter* in, AbstractSimpleFilter* out);
0074     void replaceData(void*);
0075 
0076     IntervalAttribute<QString> formulaAttribute() const;
0077     void replaceFormulas(const IntervalAttribute<QString>& formulas);
0078 
0079     // global formula defined for the whole column
0080     QString formula() const;
0081     const QVector<Column::FormulaData>& formulaData() const;
0082     void setFormulVariableColumnsPath(int index, const QString& path);
0083     void setFormulVariableColumn(int index, Column* column);
0084     void setFormulVariableColumn(Column*);
0085     bool formulaAutoUpdate() const;
0086     bool formulaAutoResize() const;
0087     void setFormula(const QString& formula, const QVector<Column::FormulaData>& formulaData, bool autoUpdate, bool autoResize);
0088     void setFormula(const QString& formula, const QStringList& variableNames, const QStringList& variableColumnPaths, bool autoUpdate, bool autoResize);
0089     void updateFormula();
0090 
0091     // cell formulas
0092     QString formula(int row) const;
0093     QVector<Interval<int>> formulaIntervals() const;
0094     void setFormula(const Interval<int>& i, const QString& formula);
0095     void setFormula(int row, const QString& formula);
0096     void clearFormulas();
0097 
0098     QString textAt(int row) const;
0099     void setValueAt(int row, QString new_value);
0100     void setTextAt(int row, const QString&);
0101     void replaceValues(int first, const QVector<QString>&);
0102     void replaceTexts(int first, const QVector<QString>&);
0103     int dictionaryIndex(int row) const;
0104     const QMap<QString, int>& frequencies() const;
0105 
0106     QDate dateAt(int row) const;
0107     void setDateAt(int row, QDate);
0108     QTime timeAt(int row) const;
0109     void setTimeAt(int row, QTime);
0110     QDateTime dateTimeAt(int row) const;
0111     void setValueAt(int row, QDateTime new_value);
0112     void setDateTimeAt(int row, const QDateTime&);
0113     void replaceValues(int first, const QVector<QDateTime>&);
0114     void replaceDateTimes(int first, const QVector<QDateTime>&);
0115 
0116     double doubleAt(int row) const;
0117     double valueAt(int row) const;
0118     void setValueAt(int row, double new_value);
0119     void replaceValues(int first, const QVector<double>&);
0120 
0121     int integerAt(int row) const;
0122     void setValueAt(int row, int new_value);
0123     void setIntegerAt(int row, int new_value);
0124     void replaceValues(int first, const QVector<int>&);
0125     void replaceInteger(int first, const QVector<int>&);
0126 
0127     qint64 bigIntAt(int row) const;
0128     void setValueAt(int row, qint64 new_value);
0129     void setBigIntAt(int row, qint64 new_value);
0130     void replaceValues(int first, const QVector<qint64>&);
0131     void replaceBigInt(int first, const QVector<qint64>&);
0132 
0133     void updateProperties();
0134     void calculateStatistics();
0135     void invalidate();
0136     void finalizeLoad();
0137 
0138     struct CachedValuesAvailable {
0139         void setUnavailable() {
0140             statistics = false;
0141             min = false;
0142             max = false;
0143             hasValues = false;
0144             dictionary = false;
0145             properties = false;
0146         }
0147         bool statistics{false}; // is 'statistics' already available or needs to be (re-)calculated?
0148         // are minMax already calculated or needs to be (re-)calculated?
0149         // It is separated from statistics, because these are important values
0150         // which are quite often needed, but if the curve is monoton a faster algorithm is
0151         // used to recalculate the values
0152         bool min{false};
0153         bool max{false};
0154         bool hasValues{false}; // is 'hasValues' already available or needs to be (re-)calculated?
0155         bool dictionary{false}; // dictionary of text values, relevant for text columns only, available?
0156         bool properties{false}; // is 'properties' already available (true) or needs to be (re-)calculated (false)?
0157     };
0158 
0159     CachedValuesAvailable available;
0160     AbstractColumn::ColumnStatistics statistics;
0161     bool hasValues{false};
0162     AbstractColumn::Properties properties{
0163         AbstractColumn::Properties::No}; // declares the properties of the curve (monotonic increasing/decreasing ...). Speed up algorithms
0164 
0165     struct ValueLabels {
0166         void setMode(AbstractColumn::ColumnMode);
0167         void migrateLabels(AbstractColumn::ColumnMode newMode);
0168         void migrateDoubleTo(AbstractColumn::ColumnMode newMode);
0169         void migrateIntTo(AbstractColumn::ColumnMode newMode);
0170         void migrateBigIntTo(AbstractColumn::ColumnMode newMode);
0171         void migrateTextTo(AbstractColumn::ColumnMode newMode);
0172         void migrateDateTimeTo(AbstractColumn::ColumnMode newMode);
0173         int count() const;
0174         int count(double min, double max) const;
0175         void add(qint64, const QString&);
0176         void add(int, const QString&);
0177         void add(double, const QString&);
0178         void add(const QDateTime&, const QString&);
0179         void add(const QString&, const QString&);
0180         void removeAll();
0181         AbstractColumn::ColumnMode mode() const;
0182         AbstractColumn::Properties properties() const;
0183         bool initialized() const {
0184             return m_labels != nullptr;
0185         }
0186         void remove(const QString&);
0187         template<typename T>
0188         inline QVector<Column::ValueLabel<T>>* cast_vector() {
0189             return static_cast<QVector<Column::ValueLabel<T>>*>(m_labels);
0190         }
0191         template<typename T>
0192         inline const QVector<Column::ValueLabel<T>>* cast_vector() const {
0193             return static_cast<QVector<Column::ValueLabel<T>>*>(m_labels);
0194         }
0195         double minimum();
0196         double maximum();
0197         const QVector<Column::ValueLabel<QString>>* textValueLabels() const;
0198         const QVector<Column::ValueLabel<QDateTime>>* dateTimeValueLabels() const;
0199         const QVector<Column::ValueLabel<double>>* valueLabels() const;
0200         const QVector<Column::ValueLabel<int>>* intValueLabels() const;
0201         const QVector<Column::ValueLabel<qint64>>* bigIntValueLabels() const;
0202         int indexForValue(double value) const;
0203         double valueAt(int index) const;
0204         QDateTime dateTimeAt(int index) const;
0205         bool isValid(int index) const;
0206         bool isMasked(int index) const;
0207         QString labelAt(int index) const;
0208 
0209     private:
0210         void invalidateStatistics();
0211         void recalculateStatistics();
0212         bool init(AbstractColumn::ColumnMode);
0213         void deinit();
0214 
0215         // Do not call manually, because it is not doing a type checking!
0216         template<typename T>
0217         void remove(const T& value) {
0218             auto* v = cast_vector<T>();
0219             for (int i = 0; i < v->length(); i++) {
0220                 if (v->at(i).value == value)
0221                     v->remove(i);
0222             }
0223         }
0224 
0225     private:
0226         AbstractColumn::ColumnMode m_mode{AbstractColumn::ColumnMode::Integer};
0227         void* m_labels{nullptr}; // pointer to the container for the value labels(QMap<T, QString>)
0228         struct Statistics {
0229             bool available{false};
0230             double minimum;
0231             double maximum;
0232         };
0233         Statistics m_statistics;
0234     };
0235     ValueLabels m_labels;
0236     int valueLabelsCount() const;
0237     int valueLabelsCount(double min, double max) const;
0238     int valueLabelsIndexForValue(double value) const;
0239     double valueLabelsValueAt(int index) const;
0240     QString valueLabelAt(int index) const;
0241     void addValueLabel(qint64, const QString&);
0242     const QVector<Column::ValueLabel<qint64>>* bigIntValueLabels() const;
0243     void addValueLabel(int, const QString&);
0244     const QVector<Column::ValueLabel<int>>* intValueLabels() const;
0245     void addValueLabel(double, const QString&);
0246     const QVector<Column::ValueLabel<double>>* valueLabels() const;
0247     void addValueLabel(const QDateTime&, const QString&);
0248     const QVector<Column::ValueLabel<QDateTime>>* dateTimeValueLabels() const;
0249     void addValueLabel(const QString&, const QString&);
0250     const QVector<Column::ValueLabel<QString>>* textValueLabels() const;
0251 
0252 private:
0253     AbstractColumn::ColumnMode m_columnMode; // type of column data
0254     void* m_data{nullptr}; // pointer to the data container (QVector<T>)
0255     int m_rowCount{0};
0256     QVector<QString> m_dictionary; // dictionary for string columns
0257     QMap<QString, int> m_dictionaryFrequencies; // dictionary for elements frequencies in string columns
0258 
0259     AbstractSimpleFilter* m_inputFilter{nullptr}; // input filter for string -> data type conversion
0260     AbstractSimpleFilter* m_outputFilter{nullptr}; // output filter for data type -> string conversion
0261     QString m_formula;
0262     QVector<Column::FormulaData> m_formulaData;
0263     bool m_formulaAutoUpdate{false};
0264     bool m_formulaAutoResize{true};
0265     IntervalAttribute<QString> m_formulas;
0266     AbstractColumn::PlotDesignation m_plotDesignation{AbstractColumn::PlotDesignation::NoDesignation};
0267     int m_width{0}; // column width in the view
0268     Column* m_owner{nullptr};
0269     QVector<QMetaObject::Connection> m_connectionsUpdateFormula;
0270 
0271     void initDictionary();
0272     void calculateTextStatistics();
0273     void calculateDateTimeStatistics();
0274     void connectFormulaColumn(const AbstractColumn*);
0275 
0276     // Never call this function directly, because it does no
0277     // mode checking.
0278     template<typename T>
0279     void setValueAtPrivate(int row, const T& new_value) {
0280         if (!m_data) {
0281             if (!initDataContainer())
0282                 return; // failed to allocate memory
0283         }
0284 
0285         invalidate();
0286 
0287         Q_EMIT m_owner->dataAboutToChange(m_owner);
0288         if (row >= rowCount())
0289             resizeTo(row + 1);
0290 
0291         static_cast<QVector<T>*>(m_data)->replace(row, new_value);
0292         if (!m_owner->m_suppressDataChangedSignal)
0293             Q_EMIT m_owner->dataChanged(m_owner);
0294     }
0295 
0296     // Never call this function directly, because it does no
0297     // mode checking.
0298     template<typename T>
0299     void replaceValuePrivate(int first, const QVector<T>& new_values) {
0300         if (!m_data) {
0301             const bool resize = (first >= 0);
0302             if (!initDataContainer(resize))
0303                 return; // failed to allocate memory
0304         }
0305 
0306         invalidate();
0307 
0308         Q_EMIT m_owner->dataAboutToChange(m_owner);
0309 
0310         if (first < 0)
0311             *static_cast<QVector<T>*>(m_data) = new_values;
0312         else {
0313             const int num_rows = new_values.size();
0314             resizeTo(first + num_rows);
0315 
0316             T* ptr = static_cast<QVector<T>*>(m_data)->data();
0317             for (int i = 0; i < num_rows; ++i)
0318                 ptr[first + i] = new_values.at(i);
0319         }
0320 
0321         if (!m_owner->m_suppressDataChangedSignal)
0322             Q_EMIT m_owner->dataChanged(m_owner);
0323     }
0324 
0325 private Q_SLOTS:
0326     void formulaVariableColumnRemoved(const AbstractAspect*);
0327     void formulaVariableColumnAdded(const AbstractAspect*);
0328 
0329     friend class ColumnSetGlobalFormulaCmd;
0330     friend class ColumnRemoveRowsCmd;
0331     friend class ColumnInsertRowsCmd;
0332 };
0333 
0334 #endif