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