File indexing completed on 2024-05-12 03:47:25
0001 /* 0002 File : AbstractColumn.cpp 0003 Project : LabPlot 0004 Description : Interface definition for data with column logic 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2007, 2008 Tilman Benkert <thzs@gmx.net> 0007 SPDX-FileCopyrightText: 2017-2022 Stefan Gerlach <stefan.gerlach@uni.kn> 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "backend/core/AbstractColumn.h" 0012 #include "backend/core/AbstractColumnPrivate.h" 0013 #include "backend/core/Settings.h" 0014 #include "backend/core/abstractcolumncommands.h" 0015 #include "backend/lib/SignallingUndoCommand.h" 0016 #include "backend/lib/XmlStreamReader.h" 0017 0018 #include <KConfigGroup> 0019 #include <KLocalizedString> 0020 0021 #include <QDateTime> 0022 #include <QIcon> 0023 0024 #include <cmath> 0025 0026 /** 0027 * \class AbstractColumn 0028 * \brief Interface definition for data with column logic 0029 * 0030 * This is an abstract base class for column-based data, 0031 * i.e. mathematically a vector or technically a 1D array or list. 0032 * It only defines the interface but has no data members itself. 0033 * 0034 * Classes derived from this are typically table columns or outputs 0035 * of filters which can be chained between table columns and plots. 0036 * From the point of view of the plot functions there will be no difference 0037 * between a table column and a filter output since both use this interface. 0038 * 0039 * Classes derived from this will either store a 0040 * vector with entries of one certain data type, e.g. double, QString, 0041 * QDateTime, or generate such values on demand. To determine the data 0042 * type of a class derived from this, use the columnMode() function. 0043 * AbstractColumn defines all access functions for all supported data 0044 * types but only those corresponding to the return value of columnMode() 0045 * will return a meaningful value. Calling functions not belonging to 0046 * the data type of the column is safe, but will do nothing (writing 0047 * function) or return some default value (reading functions). 0048 * 0049 * This class also defines all signals which indicate a data change. 0050 * Any class whose output values are subject to change over time must emit 0051 * the according signals. These signals notify any object working with the 0052 * column before and after a change of the column. 0053 * In some cases it will be necessary for a class using 0054 * the column to connect aboutToBeDestroyed(), to react 0055 * to a column's deletion, e.g. a filter's reaction to a 0056 * table deletion. 0057 * 0058 * All writing functions have a "do nothing" standard implementation to 0059 * make deriving a read-only class very easy without bothering about the 0060 * writing interface. 0061 */ 0062 0063 /** 0064 * \brief Ctor 0065 * 0066 * \param name the column name (= aspect name) 0067 */ 0068 AbstractColumn::AbstractColumn(const QString& name, AspectType type) 0069 : AbstractAspect(name, type) 0070 , d(new AbstractColumnPrivate(this)) { 0071 } 0072 0073 AbstractColumn::~AbstractColumn() { 0074 Q_EMIT aboutToBeDestroyed(this); 0075 delete d; 0076 } 0077 0078 QStringList AbstractColumn::dateFormats() { 0079 static const QStringList dates{QStringLiteral("yyyy-MM-dd"), 0080 QStringLiteral("yyyy.MM.dd"), 0081 QStringLiteral("yyyy/MM/dd"), 0082 QStringLiteral("yyyyMMdd"), 0083 QStringLiteral("dd-MM-yyyy"), 0084 QStringLiteral("dd.MM.yyyy"), 0085 QStringLiteral("dd/MM/yyyy"), 0086 QStringLiteral("ddMMyyyy"), 0087 QStringLiteral("dd-MM-yy"), 0088 QStringLiteral("dd.MM.yy"), 0089 QStringLiteral("dd/MM/yy"), 0090 QStringLiteral("ddMMyy"), 0091 QStringLiteral("MM-yyyy"), 0092 QStringLiteral("MM.yyyy"), 0093 QStringLiteral("MM/yyyy"), 0094 QStringLiteral("dd-MM"), 0095 QStringLiteral("dd.MM"), 0096 QStringLiteral("dd/MM"), 0097 QStringLiteral("ddMM")}; 0098 0099 return dates; 0100 } 0101 0102 QStringList AbstractColumn::timeFormats() { 0103 static const QStringList times{QStringLiteral("hh"), 0104 QStringLiteral("hh ap"), 0105 QStringLiteral("hh:mm"), 0106 QStringLiteral("hh:mm ap"), 0107 QStringLiteral("hh:mm:ss"), 0108 QStringLiteral("hh:mm:ss.zzz"), 0109 QStringLiteral("hh:mm:ss:zzz"), 0110 QStringLiteral("mm:ss.zzz"), 0111 QStringLiteral("hhmmss")}; 0112 0113 return times; 0114 } 0115 0116 QStringList AbstractColumn::dateTimeFormats() { 0117 QStringList dateTimes = dateFormats(); 0118 dateTimes << timeFormats(); 0119 // any combination of date and times 0120 for (const auto& d : dateFormats()) 0121 for (const auto& t : timeFormats()) 0122 dateTimes << d + QLatin1Char(' ') + t; 0123 0124 return dateTimes; 0125 } 0126 0127 /** 0128 * \brief Convenience method for getting time unit string 0129 * translated since used in UI 0130 */ 0131 QString AbstractColumn::timeUnitString(TimeUnit unit) { 0132 switch (unit) { 0133 case TimeUnit::Milliseconds: 0134 return i18n("Milliseconds"); 0135 case TimeUnit::Seconds: 0136 return i18n("Seconds"); 0137 case TimeUnit::Minutes: 0138 return i18n("Minutes"); 0139 case TimeUnit::Hours: 0140 return i18n("Hours"); 0141 case TimeUnit::Days: 0142 return i18n("Days"); 0143 } 0144 0145 return {}; 0146 } 0147 0148 /** 0149 * \brief Convenience method for getting plot designation string 0150 * translated since used in UI 0151 */ 0152 QString AbstractColumn::plotDesignationString(PlotDesignation d, bool withBrackets) { 0153 QString s; 0154 0155 const KConfigGroup group = Settings::group(QStringLiteral("Settings_General")); 0156 switch (d) { 0157 case PlotDesignation::NoDesignation: 0158 s = i18n("None"); 0159 break; 0160 case PlotDesignation::X: 0161 s = QStringLiteral("X"); 0162 break; 0163 case PlotDesignation::Y: 0164 s = QStringLiteral("Y"); 0165 break; 0166 case PlotDesignation::Z: 0167 s = QStringLiteral("Z"); 0168 break; 0169 case PlotDesignation::XError: 0170 if (group.readEntry("GUMTerms", false)) 0171 s = i18n("X-Uncertainty"); 0172 else 0173 s = i18n("X-Error"); 0174 break; 0175 case PlotDesignation::XErrorPlus: 0176 if (group.readEntry("GUMTerms", false)) 0177 s = i18n("X-Uncertainty +"); 0178 else 0179 s = i18n("X-Error +"); 0180 break; 0181 case PlotDesignation::XErrorMinus: 0182 if (group.readEntry("GUMTerms", false)) 0183 s = i18n("X-Uncertainty -"); 0184 else 0185 s = i18n("X-Error -"); 0186 break; 0187 case PlotDesignation::YError: 0188 if (group.readEntry("GUMTerms", false)) 0189 s = i18n("Y-Uncertainty"); 0190 else 0191 s = i18n("Y-Error"); 0192 break; 0193 case PlotDesignation::YErrorPlus: 0194 if (group.readEntry("GUMTerms", false)) 0195 s = i18n("Y-Uncertainty +"); 0196 else 0197 s = i18n("Y-Error +"); 0198 break; 0199 case PlotDesignation::YErrorMinus: 0200 if (group.readEntry("GUMTerms", false)) 0201 s = i18n("Y-Uncertainty -"); 0202 else 0203 s = i18n("Y-Error -"); 0204 break; 0205 default: 0206 return {}; 0207 } 0208 0209 if (withBrackets) 0210 s = QStringLiteral("[") + s + QLatin1Char(']'); 0211 0212 return s; 0213 } 0214 0215 /** 0216 * \brief Convenience method for getting mode string 0217 * translated since used in UI 0218 */ 0219 QString AbstractColumn::columnModeString(ColumnMode mode) { 0220 switch (mode) { 0221 case ColumnMode::Double: 0222 return i18n("Double"); 0223 case ColumnMode::Integer: 0224 return i18n("Integer"); 0225 case ColumnMode::BigInt: 0226 return i18n("Big Integer"); 0227 case ColumnMode::Text: 0228 return i18n("Text"); 0229 case ColumnMode::DateTime: 0230 return i18n("Date & Time"); 0231 case ColumnMode::Month: 0232 return i18n("Month Names"); 0233 case ColumnMode::Day: 0234 return i18n("Day Names"); 0235 } 0236 0237 return i18n("UNDEFINED"); 0238 } 0239 0240 /** 0241 * \brief Convenience method for mode-dependent icon 0242 */ 0243 QIcon AbstractColumn::modeIcon(ColumnMode mode) { 0244 switch (mode) { 0245 case ColumnMode::Double: 0246 case ColumnMode::Integer: 0247 case ColumnMode::BigInt: 0248 break; 0249 case ColumnMode::Text: 0250 return QIcon::fromTheme(QStringLiteral("draw-text")); 0251 case ColumnMode::DateTime: 0252 case ColumnMode::Month: 0253 case ColumnMode::Day: 0254 return QIcon::fromTheme(QStringLiteral("chronometer")); 0255 } 0256 0257 return QIcon::fromTheme(QStringLiteral("x-shape-text")); 0258 } 0259 0260 /** 0261 * \fn bool AbstractColumn::isReadOnly() const 0262 * \brief Return whether the object is read-only 0263 */ 0264 0265 /** 0266 * \fn AbstractColumn::ColumnMode AbstractColumn::columnMode() const 0267 * \brief Return the column mode 0268 * 0269 * This function is most used by tables but can also be used 0270 * by plots. The column mode specifies how to interpret 0271 * the values in the column additional to the data type. 0272 */ 0273 0274 /** 0275 * \brief Set the column mode 0276 * 0277 * This sets the column mode and, if 0278 * necessary, converts it to another datatype. 0279 */ 0280 void AbstractColumn::setColumnMode(AbstractColumn::ColumnMode) { 0281 } 0282 0283 /** 0284 * \brief Copy another column of the same type 0285 * 0286 * This function will return false if the data type 0287 * of 'other' is not the same as the type of 'this'. 0288 * Use a filter to convert a column to another type. 0289 */ 0290 bool AbstractColumn::copy(const AbstractColumn* /*other*/) { 0291 return false; 0292 } 0293 0294 /** 0295 * \brief Copies part of another column of the same type 0296 * 0297 * This function will return false if the data type 0298 * of 'other' is not the same as the type of 'this'. 0299 * \param source pointer to the column to copy 0300 * \param source_start first row to copy in the column to copy 0301 * \param destination_start first row to copy in 0302 * \param num_rows the number of rows to copy 0303 */ 0304 bool AbstractColumn::copy(const AbstractColumn* /*source*/, int /*source_start*/, int /*destination_start*/, int /*num_rows*/) { 0305 return false; 0306 } 0307 0308 /** 0309 * \fn int AbstractColumn::rowCount() const 0310 * \brief Return the data vector size 0311 */ 0312 0313 /** 0314 * \fn int AbstractColumn::availableRowCount() const 0315 * \brief Return the number of available data rows 0316 */ 0317 0318 class ColumnSetRowsCountCmd : public QUndoCommand { 0319 public: 0320 ColumnSetRowsCountCmd(AbstractColumn* column, bool insert, int first, int count, QUndoCommand* parent) 0321 : QUndoCommand(parent) 0322 , m_column(column) 0323 , m_insert(insert) 0324 , m_first(first) 0325 , m_count(count) { 0326 if (insert) 0327 setText(i18np("%1: insert 1 row", "%1: insert %2 rows", m_column->name(), count)); 0328 else 0329 setText(i18np("%1: remove 1 row", "%1: remove %2 rows", m_column->name(), count)); 0330 } 0331 0332 virtual void redo() override { 0333 if (m_insert) 0334 Q_EMIT m_column->rowsAboutToBeInserted(m_column, m_first, m_count); 0335 else 0336 Q_EMIT m_column->rowsAboutToBeRemoved(m_column, m_first, m_count); 0337 0338 QUndoCommand::redo(); 0339 0340 if (m_insert) 0341 Q_EMIT m_column->rowsInserted(m_column, m_first, m_count); 0342 else 0343 Q_EMIT m_column->rowsRemoved(m_column, m_first, m_count); 0344 } 0345 0346 virtual void undo() override { 0347 if (m_insert) 0348 Q_EMIT m_column->rowsAboutToBeRemoved(m_column, m_first, m_count); 0349 else 0350 Q_EMIT m_column->rowsAboutToBeInserted(m_column, m_first, m_count); 0351 QUndoCommand::undo(); 0352 0353 if (m_insert) 0354 Q_EMIT m_column->rowsRemoved(m_column, m_first, m_count); 0355 else 0356 Q_EMIT m_column->rowsInserted(m_column, m_first, m_count); 0357 } 0358 0359 private: 0360 AbstractColumn* m_column; 0361 bool m_insert; 0362 int m_first; 0363 int m_count; 0364 }; 0365 0366 /** 0367 * \brief Insert some empty (or initialized with invalid values) rows 0368 */ 0369 void AbstractColumn::insertRows(int before, int count, QUndoCommand* parent) { 0370 auto* command = new ColumnSetRowsCountCmd(this, true, before, count, parent); 0371 0372 handleRowInsertion(before, count, command); 0373 0374 if (!parent) 0375 exec(command); 0376 } 0377 0378 void AbstractColumn::handleRowInsertion(int before, int count, QUndoCommand* parent) { 0379 new AbstractColumnInsertRowsCmd(this, before, count, parent); 0380 } 0381 0382 /** 0383 * \brief Remove 'count' rows starting from row 'first' 0384 */ 0385 void AbstractColumn::removeRows(int first, int count, QUndoCommand* parent) { 0386 auto* command = new ColumnSetRowsCountCmd(this, false, first, count, parent); 0387 0388 handleRowRemoval(first, count, command); 0389 0390 if (!parent) 0391 exec(command); 0392 } 0393 0394 void AbstractColumn::handleRowRemoval(int first, int count, QUndoCommand* parent) { 0395 new AbstractColumnRemoveRowsCmd(this, first, count, parent); 0396 } 0397 0398 /** 0399 * \fn AbstractColumn::PlotDesignation AbstractColumn::plotDesignation() const 0400 * \brief Return the column plot designation 0401 */ 0402 0403 /** 0404 * \brief Set the column plot designation 0405 */ 0406 void AbstractColumn::setPlotDesignation(AbstractColumn::PlotDesignation) { 0407 } 0408 0409 bool AbstractColumn::isNumeric() const { 0410 const auto mode = columnMode(); 0411 return (mode == ColumnMode::Double || mode == ColumnMode::Integer || mode == ColumnMode::BigInt); 0412 } 0413 0414 bool AbstractColumn::isPlottable() const { 0415 const auto mode = columnMode(); 0416 return (isNumeric() || mode == ColumnMode::DateTime); 0417 } 0418 0419 /** 0420 * \brief Clear the whole column 0421 */ 0422 void AbstractColumn::clear(QUndoCommand*) { 0423 } 0424 0425 /** 0426 * \brief Convenience method for mode-independent testing of validity 0427 */ 0428 bool AbstractColumn::isValid(int row) const { 0429 switch (columnMode()) { 0430 case ColumnMode::Double: { 0431 double value = valueAt(row); 0432 return std::isfinite(value); 0433 } 0434 case ColumnMode::Integer: // there is no invalid integer 0435 case ColumnMode::BigInt: 0436 return true; 0437 case ColumnMode::Text: 0438 return !textAt(row).isNull(); 0439 case ColumnMode::DateTime: 0440 case ColumnMode::Month: 0441 case ColumnMode::Day: 0442 return dateTimeAt(row).isValid(); 0443 } 0444 0445 return false; 0446 } 0447 0448 //////////////////////////////////////////////////////////////////////////////////////////////////// 0449 //! \name IntervalAttribute related functions 0450 //@{ 0451 //////////////////////////////////////////////////////////////////////////////////////////////////// 0452 0453 /** 0454 * \brief Return whether a certain row is masked 0455 */ 0456 bool AbstractColumn::isMasked(int row) const { 0457 return d->m_masking.isSet(row); 0458 } 0459 0460 /** 0461 * \brief Return whether a certain interval of rows is fully masked 0462 */ 0463 bool AbstractColumn::isMasked(const Interval<int>& i) const { 0464 return d->m_masking.isSet(i); 0465 } 0466 0467 /** 0468 * \brief Return all intervals of masked rows 0469 */ 0470 QVector<Interval<int>> AbstractColumn::maskedIntervals() const { 0471 return d->m_masking.intervals(); 0472 } 0473 0474 /** 0475 * \brief Clear all masking information 0476 */ 0477 void AbstractColumn::clearMasks() { 0478 exec(new AbstractColumnClearMasksCmd(d), "maskingAboutToChange", "maskingChanged", QArgument<const AbstractColumn*>("const AbstractColumn*", this)); 0479 } 0480 0481 /** 0482 * \brief Set an interval masked 0483 * 0484 * \param i the interval 0485 * \param mask true: mask, false: unmask 0486 */ 0487 void AbstractColumn::setMasked(const Interval<int>& i, bool mask) { 0488 exec(new AbstractColumnSetMaskedCmd(d, i, mask), "maskingAboutToChange", "maskingChanged", QArgument<const AbstractColumn*>("const AbstractColumn*", this)); 0489 } 0490 0491 /** 0492 * \brief Overloaded function for convenience 0493 */ 0494 void AbstractColumn::setMasked(int row, bool mask) { 0495 setMasked(Interval<int>(row, row), mask); 0496 } 0497 0498 //////////////////////////////////////////////////////////////////////////////////////////////////// 0499 //@} 0500 //////////////////////////////////////////////////////////////////////////////////////////////////// 0501 0502 //////////////////////////////////////////////////////////////////////////////////////////////////// 0503 //! \name Formula related functions 0504 //@{ 0505 //////////////////////////////////////////////////////////////////////////////////////////////////// 0506 0507 /** 0508 * \brief Return the formula associated with row 'row' 0509 */ 0510 QString AbstractColumn::formula(int /*row*/) const { 0511 return {}; 0512 } 0513 0514 /** 0515 * \brief Return the intervals that have associated formulas 0516 * 0517 * This can be used to make a list of formulas with their intervals. 0518 * Here is some example code: 0519 * 0520 * \code 0521 * QStringList list; 0522 * QVector< Interval<int> > intervals = my_column.formulaIntervals(); 0523 * foreach(Interval<int> interval, intervals) 0524 * list << QString(interval.toString() + ": " + my_column.formula(interval.start())); 0525 * \endcode 0526 */ 0527 QVector<Interval<int>> AbstractColumn::formulaIntervals() const { 0528 return {}; 0529 } 0530 0531 /** 0532 * \brief Set a formula string for an interval of rows 0533 */ 0534 void AbstractColumn::setFormula(const Interval<int>&, const QString& /*formula*/) { 0535 } 0536 0537 /** 0538 * \brief Overloaded function for convenience 0539 */ 0540 void AbstractColumn::setFormula(int /*row*/, const QString& /*formula*/) { 0541 } 0542 0543 /** 0544 * \brief Clear all formulas 0545 */ 0546 void AbstractColumn::clearFormulas() { 0547 } 0548 0549 // conditional formatting 0550 bool AbstractColumn::hasHeatmapFormat() const { 0551 return (d->m_heatmapFormat != nullptr); 0552 } 0553 0554 AbstractColumn::HeatmapFormat& AbstractColumn::heatmapFormat() const { 0555 if (!d->m_heatmapFormat) 0556 d->m_heatmapFormat = new HeatmapFormat(); 0557 0558 return *(d->m_heatmapFormat); 0559 } 0560 0561 void AbstractColumn::setHeatmapFormat(const AbstractColumn::HeatmapFormat& format) { 0562 exec(new AbstractColumnSetHeatmapFormatCmd(d, format)); 0563 } 0564 0565 void AbstractColumn::removeFormat() { 0566 exec(new AbstractColumnRemoveHeatmapFormatCmd(d)); 0567 } 0568 0569 /*! 0570 * resets the connections for the dependent objects like plots and formulas in other columns 0571 * to the dataChanged signal in the current column. 0572 */ 0573 void AbstractColumn::reset() { 0574 // don't disconnect from all signals since we'd loose all connections done in AbstractAspect::connectChild(). 0575 // disconnect from the dataChanged signal only, the reconnect is triggered in Project::descriptionChanged(). 0576 Q_EMIT aboutToReset(this); 0577 disconnect(this, &AbstractColumn::dataChanged, nullptr, nullptr); 0578 } 0579 0580 //////////////////////////////////////////////////////////////////////////////////////////////////// 0581 //@} 0582 //////////////////////////////////////////////////////////////////////////////////////////////////// 0583 0584 //////////////////////////////////////////////////////////////////////////////////////////////////// 0585 //! \name type specific functions 0586 //@{ 0587 //////////////////////////////////////////////////////////////////////////////////////////////////// 0588 0589 /** 0590 * \brief Return the content of row 'row'. 0591 * 0592 * Use this only when columnMode() is Text 0593 */ 0594 QString AbstractColumn::textAt(int /*row*/) const { 0595 return {}; 0596 } 0597 0598 /** 0599 * \brief Set the content of row 'row' 0600 * 0601 * Use this only when columnMode() is Text 0602 */ 0603 void AbstractColumn::setTextAt(int /*row*/, const QString& /*new_text*/) { 0604 } 0605 0606 /** 0607 * \brief Replace a range of values 0608 * 0609 * Use this only when columnMode() is Text 0610 */ 0611 void AbstractColumn::replaceTexts(int /*first*/, const QVector<QString>& /*new_text*/) { 0612 } 0613 0614 /** 0615 * \brief Return the position/index in the dictionary for the text value at \param row 0616 * 0617 * Use this only when columnMode() is Text 0618 */ 0619 int AbstractColumn::dictionaryIndex(int /* row */) const { 0620 return 0; 0621 } 0622 /** 0623 * \brief Return the date part of row 'row' 0624 * 0625 * Use this only when columnMode() is DateTime, Month or Day 0626 */ 0627 QDate AbstractColumn::dateAt(int /*row*/) const { 0628 return QDate{}; 0629 } 0630 0631 /** 0632 * \brief Set the content of row 'row' 0633 * 0634 * Use this only when columnMode() is DateTime, Month or Day 0635 */ 0636 void AbstractColumn::setDateAt(int /*row*/, QDate) { 0637 } 0638 0639 /** 0640 * \brief Return the time part of row 'row' 0641 * 0642 * Use this only when columnMode() is DateTime, Month or Day 0643 */ 0644 QTime AbstractColumn::timeAt(int /*row*/) const { 0645 return {}; 0646 } 0647 0648 /** 0649 * \brief Set the content of row 'row' 0650 * 0651 * Use this only when columnMode() is DateTime, Month or Day 0652 */ 0653 void AbstractColumn::setTimeAt(int /*row*/, QTime) { 0654 } 0655 0656 /** 0657 * \brief Return the QDateTime in row 'row' 0658 * 0659 * Use this only when columnMode() is DateTime, Month or Day 0660 */ 0661 QDateTime AbstractColumn::dateTimeAt(int /*row*/) const { 0662 return {}; 0663 } 0664 0665 /** 0666 * \brief Set the content of row 'row' 0667 * 0668 * Use this only when columnMode() is DateTime, Month or Day 0669 */ 0670 void AbstractColumn::setDateTimeAt(int /*row*/, const QDateTime&) { 0671 } 0672 0673 /** 0674 * \brief Replace a range of values 0675 * 0676 * Use this only when columnMode() is DateTime, Month or Day 0677 */ 0678 void AbstractColumn::replaceDateTimes(int /*first*/, const QVector<QDateTime>&) { 0679 } 0680 0681 /** 0682 * \brief Return the double value in row 'row' 0683 * 0684 * Use this only when columnMode() is Numeric 0685 */ 0686 double AbstractColumn::doubleAt(int /*row*/) const { 0687 return NAN; 0688 } 0689 0690 /** 0691 * \brief Return the double value in row 'row' independent of the column mode. 0692 * 0693 * Integer and big integer values are converted to double, NAN is returned for other modes. 0694 */ 0695 double AbstractColumn::valueAt(int /*row*/) const { 0696 return NAN; 0697 } 0698 0699 /** 0700 * \brief Set the content of row 'row' 0701 * 0702 * Use this only when columnMode() is Numeric 0703 */ 0704 void AbstractColumn::setValueAt(int /*row*/, const double) { 0705 } 0706 0707 /** 0708 * \brief Replace a range of values 0709 * 0710 * Use this only when columnMode() is Numeric 0711 */ 0712 void AbstractColumn::replaceValues(int /*first*/, const QVector<double>&) { 0713 } 0714 0715 /** 0716 * \brief Return the integer value in row 'row' 0717 * 0718 * Use this only when columnMode() is Integer 0719 */ 0720 int AbstractColumn::integerAt(int /*row*/) const { 0721 return 42; 0722 } 0723 0724 /** 0725 * \brief Set the content of row 'row' 0726 * 0727 * Use this only when columnMode() is Integer 0728 */ 0729 void AbstractColumn::setIntegerAt(int /*row*/, const int) { 0730 } 0731 0732 /** 0733 * \brief Replace a range of values 0734 * 0735 * Use this only when columnMode() is Integer 0736 */ 0737 void AbstractColumn::replaceInteger(int /*first*/, const QVector<int>&) { 0738 } 0739 0740 /** 0741 * \brief Return the bigint value in row 'row' 0742 * 0743 * Use this only when columnMode() is BigInt 0744 */ 0745 qint64 AbstractColumn::bigIntAt(int /*row*/) const { 0746 return 42; 0747 } 0748 0749 /** 0750 * \brief Set the content of row 'row' 0751 * 0752 * Use this only when columnMode() is BigInt 0753 */ 0754 void AbstractColumn::setBigIntAt(int /*row*/, const qint64) { 0755 } 0756 0757 /** 0758 * \brief Replace a range of values 0759 * 0760 * Use this only when columnMode() is BigInt 0761 */ 0762 void AbstractColumn::replaceBigInt(int /*first*/, const QVector<qint64>&) { 0763 } 0764 0765 /** 0766 * Returns the properties hold by this column (no, constant, monotonic increasing, monotonic decreasing,...) 0767 * Is used in XYCurve to improve the search velocity for the y value for a specific x value 0768 */ 0769 AbstractColumn::Properties AbstractColumn::properties() const { 0770 return AbstractColumn::Properties::No; 0771 } 0772 0773 /**********************************************************************/ 0774 double AbstractColumn::minimum(int /*count*/) const { 0775 return INFINITY; 0776 } 0777 0778 double AbstractColumn::minimum(int /*startIndex*/, int /*endIndex*/) const { 0779 return INFINITY; 0780 } 0781 0782 double AbstractColumn::maximum(int /*count*/) const { 0783 return -INFINITY; 0784 } 0785 0786 double AbstractColumn::maximum(int /*startIndex*/, int /*endIndex*/) const { 0787 return -INFINITY; 0788 } 0789 0790 bool AbstractColumn::indicesMinMax(double /*v1*/, double /*v2*/, int& /*start*/, int& /*end*/) const { 0791 return false; 0792 } 0793 0794 int AbstractColumn::indexForValue(double /*x*/) const { 0795 return 0; 0796 } 0797 0798 //////////////////////////////////////////////////////////////////////////////////////////////////// 0799 //@} 0800 //////////////////////////////////////////////////////////////////////////////////////////////////// 0801 0802 /** 0803 * \fn void AbstractColumn::plotDesignationAboutToChange(const AbstractColumn *source) 0804 * \brief Column plot designation will be changed 0805 * 0806 * 'source' is always the this pointer of the column that 0807 * emitted this signal. This way it's easier to use 0808 * one handler for lots of columns. 0809 */ 0810 0811 /** 0812 * \fn void AbstractColumn::plotDesignationChanged(const AbstractColumn *source) 0813 * \brief Column plot designation changed 0814 * 0815 * 'source' is always the this pointer of the column that 0816 * emitted this signal. This way it's easier to use 0817 * one handler for lots of columns. 0818 */ 0819 0820 /** 0821 * \fn void AbstractColumn::modeAboutToChange(const AbstractColumn *source) 0822 * \brief Column mode (possibly also the data type) will be changed 0823 * 0824 * 'source' is always the this pointer of the column that 0825 * emitted this signal. This way it's easier to use 0826 * one handler for lots of columns. 0827 */ 0828 0829 /** 0830 * \fn void AbstractColumn::modeChanged(const AbstractColumn *source) 0831 * \brief Column mode (possibly also the data type) changed 0832 * 0833 * 'source' is always the this pointer of the column that 0834 * emitted this signal. This way it's easier to use 0835 * one handler for lots of columns. 0836 */ 0837 0838 /** 0839 * \fn void AbstractColumn::dataAboutToChange(const AbstractColumn *source) 0840 * \brief Data of the column will be changed 0841 * 0842 * 'source' is always the this pointer of the column that 0843 * emitted this signal. This way it's easier to use 0844 * one handler for lots of columns. 0845 */ 0846 0847 /** 0848 * \fn void AbstractColumn::dataChanged(const AbstractColumn *source) 0849 * \brief Data of the column has changed 0850 * 0851 * Important: When data has changed also the number 0852 * of rows in the column may have changed without 0853 * any other signal emission. 0854 * 'source' is always the this pointer of the column that 0855 * emitted this signal. This way it's easier to use 0856 * one handler for lots of columns. 0857 */ 0858 0859 /** 0860 * \fn void AbstractColumn::rowsAboutToBeInserted(const AbstractColumn *source, int before, int count) 0861 * \brief Rows will be inserted 0862 * 0863 * \param source the column that emitted the signal 0864 * \param before the row to insert before 0865 * \param count the number of rows to be inserted 0866 */ 0867 0868 /** 0869 * \fn void AbstractColumn::rowsInserted(const AbstractColumn *source, int before, int count) 0870 * \brief Rows have been inserted 0871 * 0872 * \param source the column that emitted the signal 0873 * \param before the row to insert before 0874 * \param count the number of rows to be inserted 0875 */ 0876 0877 /** 0878 * \fn void AbstractColumn::rowsAboutToBeRemoved(const AbstractColumn *source, int first, int count) 0879 * \brief Rows will be deleted 0880 * 0881 * \param source the column that emitted the signal 0882 * \param first the first row to be deleted 0883 * \param count the number of rows to be deleted 0884 */ 0885 0886 /** 0887 * \fn void AbstractColumn::rowsRemoved(const AbstractColumn *source, int first, int count) 0888 * \brief Rows have been deleted 0889 * 0890 * \param source the column that emitted the signal 0891 * \param first the first row that was deleted 0892 * \param count the number of deleted rows 0893 */ 0894 0895 /** 0896 * \fn void AbstractColumn::maskingAboutToChange(const AbstractColumn *source) 0897 * \brief Rows are about to be masked or unmasked 0898 */ 0899 0900 /** 0901 * \fn void AbstractColumn::maskingChanged(const AbstractColumn *source) 0902 * \brief Rows have been masked or unmasked 0903 */ 0904 0905 /** 0906 * \fn void AbstractColumn::aboutToBeDestroyed(const AbstractColumn *source) 0907 * \brief Emitted shortl before this column is deleted 0908 * 0909 * \param source the object emitting this signal 0910 * 0911 * This is needed by AbstractFilter. 0912 */ 0913 0914 /** 0915 * \brief Read XML mask element 0916 */ 0917 bool AbstractColumn::XmlReadMask(XmlStreamReader* reader) { 0918 Q_ASSERT(reader->isStartElement() && reader->name() == QLatin1String("mask")); 0919 0920 bool ok1, ok2; 0921 int start, end; 0922 start = reader->readAttributeInt(QStringLiteral("start_row"), &ok1); 0923 end = reader->readAttributeInt(QStringLiteral("end_row"), &ok2); 0924 if (!ok1 || !ok2) { 0925 reader->raiseError(i18n("invalid or missing start or end row")); 0926 return false; 0927 } 0928 setMasked(Interval<int>(start, end)); 0929 if (!reader->skipToEndElement()) 0930 return false; 0931 0932 return true; 0933 } 0934 0935 /** 0936 * \brief Write XML mask element 0937 */ 0938 void AbstractColumn::XmlWriteMask(QXmlStreamWriter* writer) const { 0939 for (const auto& interval : maskedIntervals()) { 0940 writer->writeStartElement(QStringLiteral("mask")); 0941 writer->writeAttribute(QStringLiteral("start_row"), QString::number(interval.start())); 0942 writer->writeAttribute(QStringLiteral("end_row"), QString::number(interval.end())); 0943 writer->writeEndElement(); 0944 } 0945 }