File indexing completed on 2024-05-19 15:01:18
0001 /*************************************************************************** 0002 File : AbstractColumn.cpp 0003 Project : LabPlot 0004 Description : Interface definition for data with column logic 0005 -------------------------------------------------------------------- 0006 Copyright : (C) 2007,2008 Tilman Benkert (thzs@gmx.net) 0007 Copyright : (C) 2017-2020 Stefan Gerlach (stefan.gerlach@uni.kn) 0008 0009 ***************************************************************************/ 0010 0011 /*************************************************************************** 0012 * * 0013 * This program is free software; you can redistribute it and/or modify * 0014 * it under the terms of the GNU General Public License as published by * 0015 * the Free Software Foundation; either version 2 of the License, or * 0016 * (at your option) any later version. * 0017 * * 0018 * This program is distributed in the hope that it will be useful, * 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0021 * GNU General Public License for more details. * 0022 * * 0023 * You should have received a copy of the GNU General Public License * 0024 * along with this program; if not, write to the Free Software * 0025 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0026 * Boston, MA 02110-1301 USA * 0027 * * 0028 ***************************************************************************/ 0029 0030 #include "backend/core/AbstractColumn.h" 0031 #include "backend/core/AbstractColumnPrivate.h" 0032 #include "backend/core/abstractcolumncommands.h" 0033 #include "backend/lib/XmlStreamReader.h" 0034 #include "backend/lib/SignallingUndoCommand.h" 0035 0036 #include <QDateTime> 0037 #include <QIcon> 0038 #include <KLocalizedString> 0039 0040 /** 0041 * \class AbstractColumn 0042 * \brief Interface definition for data with column logic 0043 * 0044 * This is an abstract base class for column-based data, 0045 * i.e. mathematically a vector or technically a 1D array or list. 0046 * It only defines the interface but has no data members itself. 0047 * 0048 * Classes derived from this are typically table columns or outputs 0049 * of filters which can be chained between table columns and plots. 0050 * From the point of view of the plot functions there will be no difference 0051 * between a table column and a filter output since both use this interface. 0052 * 0053 * Classes derived from this will either store a 0054 * vector with entries of one certain data type, e.g. double, QString, 0055 * QDateTime, or generate such values on demand. To determine the data 0056 * type of a class derived from this, use the columnMode() function. 0057 * AbstractColumn defines all access functions for all supported data 0058 * types but only those corresponding to the return value of columnMode() 0059 * will return a meaningful value. Calling functions not belonging to 0060 * the data type of the column is safe, but will do nothing (writing 0061 * function) or return some default value (reading functions). 0062 * 0063 * This class also defines all signals which indicate a data change. 0064 * Any class whose output values are subject to change over time must emit 0065 * the according signals. These signals notify any object working with the 0066 * column before and after a change of the column. 0067 * In some cases it will be necessary for a class using 0068 * the column to connect aboutToBeDestroyed(), to react 0069 * to a column's deletion, e.g. a filter's reaction to a 0070 * table deletion. 0071 * 0072 * All writing functions have a "do nothing" standard implementation to 0073 * make deriving a read-only class very easy without bothering about the 0074 * writing interface. 0075 */ 0076 0077 /** 0078 * \brief Ctor 0079 * 0080 * \param name the column name (= aspect name) 0081 */ 0082 AbstractColumn::AbstractColumn(const QString &name, AspectType type) 0083 : AbstractAspect(name, type), d( new AbstractColumnPrivate(this) ) { 0084 } 0085 0086 AbstractColumn::~AbstractColumn() { 0087 emit aboutToBeDestroyed(this); 0088 delete d; 0089 } 0090 0091 QStringList AbstractColumn::dateFormats() { 0092 static const QStringList dates{"yyyy-MM-dd", "yyyy/MM/dd", "dd/MM/yyyy", 0093 "dd/MM/yy", "dd.MM.yyyy", "dd.MM.yy", "MM/yyyy", "dd.MM.", "yyyyMMdd"}; 0094 0095 return dates; 0096 } 0097 0098 QStringList AbstractColumn::timeFormats() { 0099 static const QStringList times{"hh", "hh ap", "hh:mm", "hh:mm ap", 0100 "hh:mm:ss", "hh:mm:ss.zzz", "hh:mm:ss:zzz", "mm:ss.zzz", "hhmmss"}; 0101 0102 return times; 0103 } 0104 0105 QStringList AbstractColumn::dateTimeFormats() { 0106 // any combination of date and times 0107 QStringList dateTimes = dateFormats(); 0108 for (const auto& t : timeFormats()) 0109 dateTimes << t; 0110 for (const auto& d : dateFormats()) 0111 for (const auto& t : timeFormats()) 0112 dateTimes << d + ' ' + t; 0113 0114 return dateTimes; 0115 } 0116 0117 /** 0118 * \brief Convenience method for mode-dependent icon 0119 */ 0120 QIcon AbstractColumn::iconForMode(ColumnMode mode) { 0121 switch (mode) { 0122 case ColumnMode::Numeric: 0123 case ColumnMode::Integer: 0124 case ColumnMode::BigInt: 0125 break; 0126 case ColumnMode::Text: 0127 return QIcon::fromTheme("draw-text"); 0128 case ColumnMode::DateTime: 0129 case ColumnMode::Month: 0130 case ColumnMode::Day: 0131 return QIcon::fromTheme("chronometer"); 0132 } 0133 0134 return QIcon::fromTheme("x-shape-text"); 0135 } 0136 0137 /** 0138 * \fn bool AbstractColumn::isReadOnly() const 0139 * \brief Return whether the object is read-only 0140 */ 0141 0142 /** 0143 * \fn AbstractColumn::ColumnMode AbstractColumn::columnMode() const 0144 * \brief Return the column mode 0145 * 0146 * This function is most used by tables but can also be used 0147 * by plots. The column mode specifies how to interpret 0148 * the values in the column additional to the data type. 0149 */ 0150 0151 /** 0152 * \brief Set the column mode 0153 * 0154 * This sets the column mode and, if 0155 * necessary, converts it to another datatype. 0156 */ 0157 void AbstractColumn::setColumnMode(AbstractColumn::ColumnMode) {} 0158 0159 /** 0160 * \brief Copy another column of the same type 0161 * 0162 * This function will return false if the data type 0163 * of 'other' is not the same as the type of 'this'. 0164 * Use a filter to convert a column to another type. 0165 */ 0166 bool AbstractColumn::copy(const AbstractColumn *other) { 0167 Q_UNUSED(other) 0168 return false; 0169 } 0170 0171 /** 0172 * \brief Copies part of another column of the same type 0173 * 0174 * This function will return false if the data type 0175 * of 'other' is not the same as the type of 'this'. 0176 * \param source pointer to the column to copy 0177 * \param source_start first row to copy in the column to copy 0178 * \param destination_start first row to copy in 0179 * \param num_rows the number of rows to copy 0180 */ 0181 bool AbstractColumn::copy(const AbstractColumn *source, int source_start, int destination_start, int num_rows) { 0182 Q_UNUSED(source) 0183 Q_UNUSED(source_start) 0184 Q_UNUSED(destination_start) 0185 Q_UNUSED(num_rows) 0186 return false; 0187 } 0188 0189 /** 0190 * \fn int AbstractColumn::rowCount() const 0191 * \brief Return the data vector size 0192 */ 0193 0194 /** 0195 * \fn int AbstractColumn::availableRowCount() const 0196 * \brief Return the number of available data rows 0197 */ 0198 0199 /** 0200 * \brief Insert some empty (or initialized with invalid values) rows 0201 */ 0202 void AbstractColumn::insertRows(int before, int count) { 0203 beginMacro( i18np("%1: insert 1 row", "%1: insert %2 rows", name(), count) ); 0204 exec(new SignallingUndoCommand("pre-signal", this, "rowsAboutToBeInserted", "rowsRemoved", 0205 Q_ARG(const AbstractColumn*,this), Q_ARG(int,before), Q_ARG(int,count))); 0206 0207 handleRowInsertion(before, count); 0208 0209 exec(new SignallingUndoCommand("post-signal", this, "rowsInserted", "rowsAboutToBeRemoved", 0210 Q_ARG(const AbstractColumn*,this), Q_ARG(int,before), Q_ARG(int,count))); 0211 endMacro(); 0212 } 0213 0214 void AbstractColumn::handleRowInsertion(int before, int count) { 0215 exec(new AbstractColumnInsertRowsCmd(this, before, count)); 0216 } 0217 0218 /** 0219 * \brief Remove 'count' rows starting from row 'first' 0220 */ 0221 void AbstractColumn::removeRows(int first, int count) { 0222 beginMacro( i18np("%1: remove 1 row", "%1: remove %2 rows", name(), count) ); 0223 exec(new SignallingUndoCommand("change signal", this, "rowsAboutToBeRemoved", "rowsInserted", 0224 Q_ARG(const AbstractColumn*,this), Q_ARG(int,first), Q_ARG(int,count))); 0225 0226 handleRowRemoval(first, count); 0227 0228 exec(new SignallingUndoCommand("change signal", this, "rowsRemoved", "rowsAboutToBeInserted", 0229 Q_ARG(const AbstractColumn*,this), Q_ARG(int,first), Q_ARG(int,count))); 0230 endMacro(); 0231 } 0232 0233 void AbstractColumn::handleRowRemoval(int first, int count) { 0234 exec(new AbstractColumnRemoveRowsCmd(this, first, count)); 0235 } 0236 0237 /** 0238 * \fn AbstractColumn::PlotDesignation AbstractColumn::plotDesignation() const 0239 * \brief Return the column plot designation 0240 */ 0241 0242 /** 0243 * \brief Set the column plot designation 0244 */ 0245 void AbstractColumn::setPlotDesignation(AbstractColumn::PlotDesignation pd) { 0246 Q_UNUSED(pd) 0247 } 0248 0249 bool AbstractColumn::isNumeric() const { 0250 const auto mode = columnMode(); 0251 return (mode == ColumnMode::Numeric || mode == ColumnMode::Integer || mode == ColumnMode::BigInt); 0252 } 0253 0254 bool AbstractColumn::isPlottable() const { 0255 const auto mode = columnMode(); 0256 return (mode == ColumnMode::Numeric || mode == ColumnMode::Integer || mode == ColumnMode::BigInt || mode == ColumnMode::DateTime); 0257 } 0258 0259 /** 0260 * \brief Clear the whole column 0261 */ 0262 void AbstractColumn::clear() {} 0263 0264 /** 0265 * \brief Convenience method for mode-independent testing of validity 0266 */ 0267 bool AbstractColumn::isValid(int row) const { 0268 switch (columnMode()) { 0269 case ColumnMode::Numeric: 0270 return !(std::isnan(valueAt(row)) || std::isinf(valueAt(row))); 0271 case ColumnMode::Integer: // there is no invalid integer 0272 case ColumnMode::BigInt: 0273 return true; 0274 case ColumnMode::Text: 0275 return !textAt(row).isNull(); 0276 case ColumnMode::DateTime: 0277 case ColumnMode::Month: 0278 case ColumnMode::Day: 0279 return dateTimeAt(row).isValid(); 0280 } 0281 0282 return false; 0283 } 0284 0285 //////////////////////////////////////////////////////////////////////////////////////////////////// 0286 //! \name IntervalAttribute related functions 0287 //@{ 0288 //////////////////////////////////////////////////////////////////////////////////////////////////// 0289 0290 /** 0291 * \brief Return whether a certain row is masked 0292 */ 0293 bool AbstractColumn::isMasked(int row) const { 0294 return d->m_masking.isSet(row); 0295 } 0296 0297 /** 0298 * \brief Return whether a certain interval of rows is fully masked 0299 */ 0300 bool AbstractColumn::isMasked(const Interval<int>& i) const { 0301 return d->m_masking.isSet(i); 0302 } 0303 0304 /** 0305 * \brief Return all intervals of masked rows 0306 */ 0307 QVector< Interval<int> > AbstractColumn::maskedIntervals() const { 0308 return d->m_masking.intervals(); 0309 } 0310 0311 /** 0312 * \brief Clear all masking information 0313 */ 0314 void AbstractColumn::clearMasks() { 0315 exec(new AbstractColumnClearMasksCmd(d), 0316 "maskingAboutToChange", "maskingChanged", Q_ARG(const AbstractColumn*,this)); 0317 } 0318 0319 /** 0320 * \brief Set an interval masked 0321 * 0322 * \param i the interval 0323 * \param mask true: mask, false: unmask 0324 */ 0325 void AbstractColumn::setMasked(const Interval<int>& i, bool mask) { 0326 exec(new AbstractColumnSetMaskedCmd(d, i, mask), 0327 "maskingAboutToChange", "maskingChanged", Q_ARG(const AbstractColumn*,this)); 0328 } 0329 0330 /** 0331 * \brief Overloaded function for convenience 0332 */ 0333 void AbstractColumn::setMasked(int row, bool mask) { 0334 setMasked(Interval<int>(row,row), mask); 0335 } 0336 0337 //////////////////////////////////////////////////////////////////////////////////////////////////// 0338 //@} 0339 //////////////////////////////////////////////////////////////////////////////////////////////////// 0340 0341 //////////////////////////////////////////////////////////////////////////////////////////////////// 0342 //! \name Formula related functions 0343 //@{ 0344 //////////////////////////////////////////////////////////////////////////////////////////////////// 0345 0346 /** 0347 * \brief Return the formula associated with row 'row' 0348 */ 0349 QString AbstractColumn::formula(int row) const { 0350 Q_UNUSED(row); 0351 return QString(); 0352 } 0353 0354 /** 0355 * \brief Return the intervals that have associated formulas 0356 * 0357 * This can be used to make a list of formulas with their intervals. 0358 * Here is some example code: 0359 * 0360 * \code 0361 * QStringList list; 0362 * QVector< Interval<int> > intervals = my_column.formulaIntervals(); 0363 * foreach(Interval<int> interval, intervals) 0364 * list << QString(interval.toString() + ": " + my_column.formula(interval.start())); 0365 * \endcode 0366 */ 0367 QVector< Interval<int> > AbstractColumn::formulaIntervals() const { 0368 return QVector< Interval<int> >(); 0369 } 0370 0371 /** 0372 * \brief Set a formula string for an interval of rows 0373 */ 0374 void AbstractColumn::setFormula(const Interval<int>& i, const QString& formula) { 0375 Q_UNUSED(i) Q_UNUSED(formula) 0376 } 0377 0378 /** 0379 * \brief Overloaded function for convenience 0380 */ 0381 void AbstractColumn::setFormula(int row, const QString& formula) { 0382 Q_UNUSED(row) Q_UNUSED(formula) 0383 } 0384 0385 /** 0386 * \brief Clear all formulas 0387 */ 0388 void AbstractColumn::clearFormulas() {}; 0389 0390 //////////////////////////////////////////////////////////////////////////////////////////////////// 0391 //@} 0392 //////////////////////////////////////////////////////////////////////////////////////////////////// 0393 0394 //////////////////////////////////////////////////////////////////////////////////////////////////// 0395 //! \name type specific functions 0396 //@{ 0397 //////////////////////////////////////////////////////////////////////////////////////////////////// 0398 0399 /** 0400 * \brief Return the content of row 'row'. 0401 * 0402 * Use this only when columnMode() is Text 0403 */ 0404 QString AbstractColumn::textAt(int row) const { 0405 Q_UNUSED(row); 0406 return QString(); 0407 } 0408 0409 /** 0410 * \brief Set the content of row 'row' 0411 * 0412 * Use this only when columnMode() is Text 0413 */ 0414 void AbstractColumn::setTextAt(int row, const QString& new_value) { 0415 Q_UNUSED(row) Q_UNUSED(new_value) 0416 } 0417 0418 /** 0419 * \brief Replace a range of values 0420 * 0421 * Use this only when columnMode() is Text 0422 */ 0423 void AbstractColumn::replaceTexts(int first, const QVector<QString>& new_values) { 0424 Q_UNUSED(first) Q_UNUSED(new_values) 0425 }; 0426 0427 /** 0428 * \brief Return the date part of row 'row' 0429 * 0430 * Use this only when columnMode() is DateTime, Month or Day 0431 */ 0432 QDate AbstractColumn::dateAt(int row) const { 0433 Q_UNUSED(row); 0434 return QDate{}; 0435 } 0436 0437 /** 0438 * \brief Set the content of row 'row' 0439 * 0440 * Use this only when columnMode() is DateTime, Month or Day 0441 */ 0442 void AbstractColumn::setDateAt(int row, QDate new_value) { 0443 Q_UNUSED(row) Q_UNUSED(new_value) 0444 }; 0445 0446 /** 0447 * \brief Return the time part of row 'row' 0448 * 0449 * Use this only when columnMode() is DateTime, Month or Day 0450 */ 0451 QTime AbstractColumn::timeAt(int row) const { 0452 Q_UNUSED(row); 0453 return QTime{}; 0454 } 0455 0456 /** 0457 * \brief Set the content of row 'row' 0458 * 0459 * Use this only when columnMode() is DateTime, Month or Day 0460 */ 0461 void AbstractColumn::setTimeAt(int row, QTime new_value) { 0462 Q_UNUSED(row) Q_UNUSED(new_value) 0463 } 0464 0465 /** 0466 * \brief Return the QDateTime in row 'row' 0467 * 0468 * Use this only when columnMode() is DateTime, Month or Day 0469 */ 0470 QDateTime AbstractColumn::dateTimeAt(int row) const { 0471 Q_UNUSED(row); 0472 return QDateTime(); 0473 } 0474 0475 /** 0476 * \brief Set the content of row 'row' 0477 * 0478 * Use this only when columnMode() is DateTime, Month or Day 0479 */ 0480 void AbstractColumn::setDateTimeAt(int row, const QDateTime& new_value) { 0481 Q_UNUSED(row) Q_UNUSED(new_value) 0482 }; 0483 0484 /** 0485 * \brief Replace a range of values 0486 * 0487 * Use this only when columnMode() is DateTime, Month or Day 0488 */ 0489 void AbstractColumn::replaceDateTimes(int first, const QVector<QDateTime>& new_values) { 0490 Q_UNUSED(first) Q_UNUSED(new_values) 0491 }; 0492 0493 /** 0494 * \brief Return the double value in row 'row' 0495 * 0496 * Use this only when columnMode() is Numeric 0497 */ 0498 double AbstractColumn::valueAt(int row) const { 0499 Q_UNUSED(row); 0500 return NAN; 0501 } 0502 0503 /** 0504 * \brief Set the content of row 'row' 0505 * 0506 * Use this only when columnMode() is Numeric 0507 */ 0508 void AbstractColumn::setValueAt(int row, const double new_value) { 0509 Q_UNUSED(row) Q_UNUSED(new_value) 0510 }; 0511 0512 /** 0513 * \brief Replace a range of values 0514 * 0515 * Use this only when columnMode() is Numeric 0516 */ 0517 void AbstractColumn::replaceValues(int first, const QVector<double>& new_values) { 0518 Q_UNUSED(first) Q_UNUSED(new_values) 0519 } 0520 0521 /** 0522 * \brief Return the integer value in row 'row' 0523 * 0524 * Use this only when columnMode() is Integer 0525 */ 0526 int AbstractColumn::integerAt(int row) const { 0527 Q_UNUSED(row); 0528 return 42; 0529 } 0530 0531 /** 0532 * \brief Set the content of row 'row' 0533 * 0534 * Use this only when columnMode() is Integer 0535 */ 0536 void AbstractColumn::setIntegerAt(int row, const int new_value) { 0537 Q_UNUSED(row) Q_UNUSED(new_value) 0538 }; 0539 0540 /** 0541 * \brief Replace a range of values 0542 * 0543 * Use this only when columnMode() is Integer 0544 */ 0545 void AbstractColumn::replaceInteger(int first, const QVector<int>& new_values) { 0546 Q_UNUSED(first) Q_UNUSED(new_values) 0547 } 0548 0549 /** 0550 * \brief Return the bigint value in row 'row' 0551 * 0552 * Use this only when columnMode() is BigInt 0553 */ 0554 qint64 AbstractColumn::bigIntAt(int row) const { 0555 Q_UNUSED(row); 0556 return 42; 0557 } 0558 0559 /** 0560 * \brief Set the content of row 'row' 0561 * 0562 * Use this only when columnMode() is BigInt 0563 */ 0564 void AbstractColumn::setBigIntAt(int row, const qint64 new_value) { 0565 Q_UNUSED(row) Q_UNUSED(new_value) 0566 }; 0567 0568 /** 0569 * \brief Replace a range of values 0570 * 0571 * Use this only when columnMode() is BigInt 0572 */ 0573 void AbstractColumn::replaceBigInt(int first, const QVector<qint64>& new_values) { 0574 Q_UNUSED(first) Q_UNUSED(new_values) 0575 } 0576 0577 /** 0578 * Returns the properties hold by this column (no, constant, monotonic increasing, monotonic decreasing,...) 0579 * Is used in XYCurve to improve the search velocity for the y value for a specific x value 0580 */ 0581 AbstractColumn::Properties AbstractColumn::properties() const { 0582 return AbstractColumn::Properties::No; 0583 } 0584 0585 /**********************************************************************/ 0586 double AbstractColumn::minimum(int count) const { 0587 Q_UNUSED(count); 0588 return -INFINITY; 0589 } 0590 0591 double AbstractColumn::minimum(int startIndex, int endIndex) const { 0592 Q_UNUSED(startIndex); 0593 Q_UNUSED(endIndex); 0594 return -INFINITY; 0595 } 0596 0597 double AbstractColumn::maximum(int count) const { 0598 Q_UNUSED(count); 0599 return INFINITY; 0600 } 0601 0602 double AbstractColumn::maximum(int startIndex, int endIndex) const { 0603 Q_UNUSED(startIndex); 0604 Q_UNUSED(endIndex); 0605 return INFINITY; 0606 } 0607 0608 bool AbstractColumn::indicesMinMax(double v1, double v2, int& start, int& end) const { 0609 Q_UNUSED(v1) 0610 Q_UNUSED(v2) 0611 Q_UNUSED(start) 0612 Q_UNUSED(end) 0613 return false; 0614 } 0615 0616 int AbstractColumn::indexForValue(double x) const { 0617 Q_UNUSED(x) 0618 return 0; 0619 } 0620 0621 //////////////////////////////////////////////////////////////////////////////////////////////////// 0622 //@} 0623 //////////////////////////////////////////////////////////////////////////////////////////////////// 0624 0625 /** 0626 * \fn void AbstractColumn::plotDesignationAboutToChange(const AbstractColumn *source) 0627 * \brief Column plot designation will be changed 0628 * 0629 * 'source' is always the this pointer of the column that 0630 * emitted this signal. This way it's easier to use 0631 * one handler for lots of columns. 0632 */ 0633 0634 /** 0635 * \fn void AbstractColumn::plotDesignationChanged(const AbstractColumn *source) 0636 * \brief Column plot designation changed 0637 * 0638 * 'source' is always the this pointer of the column that 0639 * emitted this signal. This way it's easier to use 0640 * one handler for lots of columns. 0641 */ 0642 0643 /** 0644 * \fn void AbstractColumn::modeAboutToChange(const AbstractColumn *source) 0645 * \brief Column mode (possibly also the data type) will be changed 0646 * 0647 * 'source' is always the this pointer of the column that 0648 * emitted this signal. This way it's easier to use 0649 * one handler for lots of columns. 0650 */ 0651 0652 /** 0653 * \fn void AbstractColumn::modeChanged(const AbstractColumn *source) 0654 * \brief Column mode (possibly also the data type) changed 0655 * 0656 * 'source' is always the this pointer of the column that 0657 * emitted this signal. This way it's easier to use 0658 * one handler for lots of columns. 0659 */ 0660 0661 /** 0662 * \fn void AbstractColumn::dataAboutToChange(const AbstractColumn *source) 0663 * \brief Data of the column will be changed 0664 * 0665 * 'source' is always the this pointer of the column that 0666 * emitted this signal. This way it's easier to use 0667 * one handler for lots of columns. 0668 */ 0669 0670 /** 0671 * \fn void AbstractColumn::dataChanged(const AbstractColumn *source) 0672 * \brief Data of the column has changed 0673 * 0674 * Important: When data has changed also the number 0675 * of rows in the column may have changed without 0676 * any other signal emission. 0677 * 'source' is always the this pointer of the column that 0678 * emitted this signal. This way it's easier to use 0679 * one handler for lots of columns. 0680 */ 0681 0682 /** 0683 * \fn void AbstractColumn::rowsAboutToBeInserted(const AbstractColumn *source, int before, int count) 0684 * \brief Rows will be inserted 0685 * 0686 * \param source the column that emitted the signal 0687 * \param before the row to insert before 0688 * \param count the number of rows to be inserted 0689 */ 0690 0691 /** 0692 * \fn void AbstractColumn::rowsInserted(const AbstractColumn *source, int before, int count) 0693 * \brief Rows have been inserted 0694 * 0695 * \param source the column that emitted the signal 0696 * \param before the row to insert before 0697 * \param count the number of rows to be inserted 0698 */ 0699 0700 /** 0701 * \fn void AbstractColumn::rowsAboutToBeRemoved(const AbstractColumn *source, int first, int count) 0702 * \brief Rows will be deleted 0703 * 0704 * \param source the column that emitted the signal 0705 * \param first the first row to be deleted 0706 * \param count the number of rows to be deleted 0707 */ 0708 0709 /** 0710 * \fn void AbstractColumn::rowsRemoved(const AbstractColumn *source, int first, int count) 0711 * \brief Rows have been deleted 0712 * 0713 * \param source the column that emitted the signal 0714 * \param first the first row that was deleted 0715 * \param count the number of deleted rows 0716 */ 0717 0718 /** 0719 * \fn void AbstractColumn::maskingAboutToChange(const AbstractColumn *source) 0720 * \brief Rows are about to be masked or unmasked 0721 */ 0722 0723 /** 0724 * \fn void AbstractColumn::maskingChanged(const AbstractColumn *source) 0725 * \brief Rows have been masked or unmasked 0726 */ 0727 0728 /** 0729 * \fn void AbstractColumn::aboutToBeDestroyed(const AbstractColumn *source) 0730 * \brief Emitted shortl before this column is deleted 0731 * 0732 * \param source the object emitting this signal 0733 * 0734 * This is needed by AbstractFilter. 0735 */ 0736 0737 /** 0738 * \brief Read XML mask element 0739 */ 0740 bool AbstractColumn::XmlReadMask(XmlStreamReader *reader) { 0741 Q_ASSERT(reader->isStartElement() && reader->name() == "mask"); 0742 0743 bool ok1, ok2; 0744 int start, end; 0745 start = reader->readAttributeInt("start_row", &ok1); 0746 end = reader->readAttributeInt("end_row", &ok2); 0747 if (!ok1 || !ok2) { 0748 reader->raiseError(i18n("invalid or missing start or end row")); 0749 return false; 0750 } 0751 setMasked(Interval<int>(start,end)); 0752 if (!reader->skipToEndElement()) return false; 0753 0754 return true; 0755 } 0756 0757 /** 0758 * \brief Write XML mask element 0759 */ 0760 void AbstractColumn::XmlWriteMask(QXmlStreamWriter *writer) const { 0761 for (const auto& interval : maskedIntervals()) { 0762 writer->writeStartElement("mask"); 0763 writer->writeAttribute("start_row", QString::number(interval.start())); 0764 writer->writeAttribute("end_row", QString::number(interval.end())); 0765 writer->writeEndElement(); 0766 } 0767 }