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 }