ColumnPrivate.cpp 61.7 KB
Newer Older
1 2
/***************************************************************************
    File                 : ColumnPrivate.cpp
3
    Project              : AbstractColumn
4 5
    Description          : Private data class of Column
    --------------------------------------------------------------------
6
    Copyright            : (C) 2007-2008 Tilman Benkert (thzs@gmx.net)
7
    Copyright            : (C) 2012-2019 Alexander Semke (alexander.semke@web.de)
Stefan Gerlach's avatar
Stefan Gerlach committed
8
    Copyright            : (C) 2017-2020 Stefan Gerlach (stefan.gerlach@uni.kn)
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *  This program is free software; you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation; either version 2 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the Free Software           *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
 *   Boston, MA  02110-1301  USA                                           *
 *                                                                         *
 ***************************************************************************/

#include "ColumnPrivate.h"
31
#include "ColumnStringIO.h"
32
#include "Column.h"
33
#include "backend/spreadsheet/Spreadsheet.h"
34
#include "backend/core/datatypes/filter.h"
35
#include "backend/gsl/ExpressionParser.h"
36

37 38 39
#include <KConfigGroup>
#include <KSharedConfig>

Stefan Gerlach's avatar
Stefan Gerlach committed
40 41
ColumnPrivate::ColumnPrivate(Column* owner, AbstractColumn::ColumnMode mode) :
	m_column_mode(mode), m_owner(owner) {
42
	Q_ASSERT(owner != nullptr);
43

44
	SET_NUMBER_LOCALE
Stefan Gerlach's avatar
Stefan Gerlach committed
45
	switch (mode) {
46
	case AbstractColumn::ColumnMode::Numeric:
47
		m_input_filter = new String2DoubleFilter();
48
		static_cast<String2DoubleFilter*>(m_input_filter)->setNumberLocale(numberLocale);
49
		m_output_filter = new Double2StringFilter('g');
50
		static_cast<Double2StringFilter*>(m_output_filter)->setNumberLocale(numberLocale);
51 52
		m_data = new QVector<double>();
		break;
53
	case AbstractColumn::ColumnMode::Integer:
54
		m_input_filter = new String2IntegerFilter();
55
		static_cast<String2IntegerFilter*>(m_input_filter)->setNumberLocale(numberLocale);
56
		m_output_filter = new Integer2StringFilter();
57
		static_cast<Integer2StringFilter*>(m_output_filter)->setNumberLocale(numberLocale);
58 59
		m_data = new QVector<int>();
		break;
60
	case AbstractColumn::ColumnMode::BigInt:
61
		m_input_filter = new String2BigIntFilter();
62
		static_cast<String2BigIntFilter*>(m_input_filter)->setNumberLocale(numberLocale);
63
		m_output_filter = new BigInt2StringFilter();
64
		static_cast<BigInt2StringFilter*>(m_output_filter)->setNumberLocale(numberLocale);
65 66
		m_data = new QVector<qint64>();
		break;
67
	case AbstractColumn::ColumnMode::Text:
68 69 70 71
		m_input_filter = new SimpleCopyThroughFilter();
		m_output_filter = new SimpleCopyThroughFilter();
		m_data = new QStringList();
		break;
72
	case AbstractColumn::ColumnMode::DateTime:
73 74
		m_input_filter = new String2DateTimeFilter();
		m_output_filter = new DateTime2StringFilter();
75
		m_data = new QVector<QDateTime>();
76
		break;
77
	case AbstractColumn::ColumnMode::Month:
78 79
		m_input_filter = new String2MonthFilter();
		m_output_filter = new DateTime2StringFilter();
80
		static_cast<DateTime2StringFilter*>(m_output_filter)->setFormat("MMMM");
81
		m_data = new QVector<QDateTime>();
82
		break;
83
	case AbstractColumn::ColumnMode::Day:
84 85
		m_input_filter = new String2DayOfWeekFilter();
		m_output_filter = new DateTime2StringFilter();
86
		static_cast<DateTime2StringFilter*>(m_output_filter)->setFormat("dddd");
87
		m_data = new QVector<QDateTime>();
88
		break;
89
	}
90

91
	connect(m_output_filter, &AbstractSimpleFilter::formatChanged, m_owner, &Column::handleFormatChange);
92

93 94
	//m_input_filter->setName("InputFilter");
	//m_output_filter->setName("OutputFilter");
95 96
}

97 98 99
/**
 * \brief Special ctor (to be called from Column only!)
 */
Stefan Gerlach's avatar
Stefan Gerlach committed
100 101 102
ColumnPrivate::ColumnPrivate(Column* owner, AbstractColumn::ColumnMode mode, void* data) :
	m_column_mode(mode), m_data(data), m_owner(owner) {

103
	SET_NUMBER_LOCALE
Stefan Gerlach's avatar
Stefan Gerlach committed
104
	switch (mode) {
105
	case AbstractColumn::ColumnMode::Numeric:
106
		m_input_filter = new String2DoubleFilter();
107
		static_cast<String2DoubleFilter*>(m_input_filter)->setNumberLocale(numberLocale);
108
		m_output_filter = new Double2StringFilter();
109
		static_cast<Double2StringFilter*>(m_output_filter)->setNumberLocale(numberLocale);
110 111
		connect(static_cast<Double2StringFilter *>(m_output_filter), &Double2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
112
		break;
113
	case AbstractColumn::ColumnMode::Integer:
114
		m_input_filter = new String2IntegerFilter();
115
		static_cast<String2IntegerFilter*>(m_input_filter)->setNumberLocale(numberLocale);
116
		m_output_filter = new Integer2StringFilter();
117
		static_cast<Integer2StringFilter*>(m_output_filter)->setNumberLocale(numberLocale);
118 119
		connect(static_cast<Integer2StringFilter *>(m_output_filter), &Integer2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
120
		break;
121
	case AbstractColumn::ColumnMode::BigInt:
122
		m_input_filter = new String2BigIntFilter();
123
		static_cast<String2BigIntFilter*>(m_input_filter)->setNumberLocale(numberLocale);
124
		m_output_filter = new BigInt2StringFilter();
125
		static_cast<BigInt2StringFilter*>(m_output_filter)->setNumberLocale(numberLocale);
126 127
		connect(static_cast<BigInt2StringFilter *>(m_output_filter), &BigInt2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
128
		break;
129
	case AbstractColumn::ColumnMode::Text:
130 131 132
		m_input_filter = new SimpleCopyThroughFilter();
		m_output_filter = new SimpleCopyThroughFilter();
		break;
133
	case AbstractColumn::ColumnMode::DateTime:
134 135
		m_input_filter = new String2DateTimeFilter();
		m_output_filter = new DateTime2StringFilter();
136 137
		connect(static_cast<DateTime2StringFilter *>(m_output_filter), &DateTime2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
138
		break;
139
	case AbstractColumn::ColumnMode::Month:
140 141 142
		m_input_filter = new String2MonthFilter();
		m_output_filter = new DateTime2StringFilter();
		static_cast<DateTime2StringFilter *>(m_output_filter)->setFormat("MMMM");
143 144
		connect(static_cast<DateTime2StringFilter *>(m_output_filter), &DateTime2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
145
		break;
146
	case AbstractColumn::ColumnMode::Day:
147 148 149
		m_input_filter = new String2DayOfWeekFilter();
		m_output_filter = new DateTime2StringFilter();
		static_cast<DateTime2StringFilter *>(m_output_filter)->setFormat("dddd");
150 151
		connect(static_cast<DateTime2StringFilter *>(m_output_filter), &DateTime2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
152
		break;
153
	}
154

155 156
	//m_input_filter->setName("InputFilter");
	//m_output_filter->setName("OutputFilter");
157 158
}

Stefan Gerlach's avatar
Stefan Gerlach committed
159
ColumnPrivate::~ColumnPrivate() {
160 161
	if (!m_data) return;

Stefan Gerlach's avatar
Stefan Gerlach committed
162
	switch (m_column_mode) {
163
	case AbstractColumn::ColumnMode::Numeric:
164
		delete static_cast<QVector<double>*>(m_data);
165
		break;
166
	case AbstractColumn::ColumnMode::Integer:
167 168
		delete static_cast<QVector<int>*>(m_data);
		break;
169
	case AbstractColumn::ColumnMode::BigInt:
170 171
		delete static_cast<QVector<qint64>*>(m_data);
		break;
172
	case AbstractColumn::ColumnMode::Text:
173
		delete static_cast<QVector<QString>*>(m_data);
174
		break;
175 176 177
	case AbstractColumn::ColumnMode::DateTime:
	case AbstractColumn::ColumnMode::Month:
	case AbstractColumn::ColumnMode::Day:
178
		delete static_cast<QVector<QDateTime>*>(m_data);
179
		break;
180
	}
181 182
}

183
AbstractColumn::ColumnMode ColumnPrivate::columnMode() const {
184 185 186 187 188 189 190 191
	return m_column_mode;
}

/**
 * \brief Set the column mode
 *
 * This sets the column mode and, if
 * necessary, converts it to another datatype.
192
 * Remark: setting the mode back to undefined (the
193 194
 * initial value) is not supported.
 */
Stefan Gerlach's avatar
Stefan Gerlach committed
195
void ColumnPrivate::setColumnMode(AbstractColumn::ColumnMode mode) {
196
	DEBUG("ColumnPrivate::setColumnMode() " << ENUM_TO_STRING(AbstractColumn, ColumnMode, m_column_mode)
197
		<< " -> " << ENUM_TO_STRING(AbstractColumn, ColumnMode, mode))
198 199
	if (mode == m_column_mode) return;

200
	void* old_data = m_data;
201 202
	// remark: the deletion of the old data will be done in the dtor of a command

203
	AbstractSimpleFilter* filter{nullptr}, *new_in_filter{nullptr}, *new_out_filter{nullptr};
204
	bool filter_is_temporary = false; // it can also become outputFilter(), which we may not delete here
205
	Column* temp_col = nullptr;
206 207 208 209

	emit m_owner->modeAboutToChange(m_owner);

	// determine the conversion filter and allocate the new data vector
210
	SET_NUMBER_LOCALE
Stefan Gerlach's avatar
Stefan Gerlach committed
211
	switch (m_column_mode) {	// old mode
212
	case AbstractColumn::ColumnMode::Numeric: {
213 214
		disconnect(static_cast<Double2StringFilter*>(m_output_filter), &Double2StringFilter::formatChanged,
				   m_owner, &Column::handleFormatChange);
Stefan Gerlach's avatar
Stefan Gerlach committed
215
		switch (mode) {
216
		case AbstractColumn::ColumnMode::Numeric:
217
			break;
218
		case AbstractColumn::ColumnMode::Integer:
219 220 221 222 223
			filter = new Double2IntegerFilter();
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast<QVector<double>*>(old_data)));
			m_data = new QVector<int>();
			break;
224
		case AbstractColumn::ColumnMode::BigInt:
225
			filter = new Double2BigIntFilter();
226 227 228 229
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast<QVector<double>*>(old_data)));
			m_data = new QVector<qint64>();
			break;
230
		case AbstractColumn::ColumnMode::Text:
231 232 233
			filter = outputFilter();
			filter_is_temporary = false;
			temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)));
234
			m_data = new QVector<QString>();
235
			break;
236
		case AbstractColumn::ColumnMode::DateTime:
237 238 239
			filter = new Double2DateTimeFilter();
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)));
240
			m_data = new QVector<QDateTime>();
241
			break;
242
		case AbstractColumn::ColumnMode::Month:
243 244 245
			filter = new Double2MonthFilter();
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)));
246
			m_data = new QVector<QDateTime>();
247
			break;
248
		case AbstractColumn::ColumnMode::Day:
249 250 251
			filter = new Double2DayOfWeekFilter();
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast< QVector<double>* >(old_data)));
252
			m_data = new QVector<QDateTime>();
253
			break;
254
		} // switch(mode)
Stefan Gerlach's avatar
Stefan Gerlach committed
255

256
		break;
Stefan Gerlach's avatar
Stefan Gerlach committed
257
	}
258
	case AbstractColumn::ColumnMode::Integer: {
259 260
		disconnect(static_cast<Integer2StringFilter*>(m_output_filter), &Integer2StringFilter::formatChanged,
				   m_owner, &Column::handleFormatChange);
Stefan Gerlach's avatar
Stefan Gerlach committed
261
		switch (mode) {
262
		case AbstractColumn::ColumnMode::Integer:
263
			break;
264
		case AbstractColumn::ColumnMode::BigInt:
265
			filter = new Integer2BigIntFilter();
266 267 268 269
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast<QVector<int>*>(old_data)), m_column_mode);
			m_data = new QVector<qint64>();
			break;
270
		case AbstractColumn::ColumnMode::Numeric:
271 272 273 274 275
			filter = new Integer2DoubleFilter();
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast<QVector<int>*>(old_data)), m_column_mode);
			m_data = new QVector<double>();
			break;
276
		case AbstractColumn::ColumnMode::Text:
277 278 279 280 281
			filter = outputFilter();
			filter_is_temporary = false;
			temp_col = new Column("temp_col", *(static_cast< QVector<int>* >(old_data)), m_column_mode);
			m_data = new QVector<QString>();
			break;
282
		case AbstractColumn::ColumnMode::DateTime:
283 284 285 286 287
			filter = new Integer2DateTimeFilter();
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast< QVector<int>* >(old_data)), m_column_mode);
			m_data = new QVector<QDateTime>();
			break;
288
		case AbstractColumn::ColumnMode::Month:
289 290 291 292 293
			filter = new Integer2MonthFilter();
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast< QVector<int>* >(old_data)), m_column_mode);
			m_data = new QVector<QDateTime>();
			break;
294
		case AbstractColumn::ColumnMode::Day:
295 296 297 298 299 300 301 302 303
			filter = new Integer2DayOfWeekFilter();
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast< QVector<int>* >(old_data)), m_column_mode);
			m_data = new QVector<QDateTime>();
			break;
		} // switch(mode)

		break;
	}
304
	case AbstractColumn::ColumnMode::BigInt: {
305 306
		disconnect(static_cast<BigInt2StringFilter*>(m_output_filter), &BigInt2StringFilter::formatChanged,
				   m_owner, &Column::handleFormatChange);
307
		switch (mode) {
308
		case AbstractColumn::ColumnMode::BigInt:
309
			break;
310
		case AbstractColumn::ColumnMode::Integer:
311
			filter = new BigInt2IntegerFilter();
312 313 314 315
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast<QVector<qint64>*>(old_data)), m_column_mode);
			m_data = new QVector<int>();
			break;
316
		case AbstractColumn::ColumnMode::Numeric:
317
			filter = new BigInt2DoubleFilter();
318
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
319
			temp_col = new Column("temp_col", *(static_cast<QVector<qint64>*>(old_data)), m_column_mode);
320 321
			m_data = new QVector<double>();
			break;
322
		case AbstractColumn::ColumnMode::Text:
323 324
			filter = outputFilter();
			filter_is_temporary = false;
Stefan Gerlach's avatar
Stefan Gerlach committed
325
			temp_col = new Column("temp_col", *(static_cast< QVector<qint64>* >(old_data)), m_column_mode);
326 327
			m_data = new QVector<QString>();
			break;
328
		case AbstractColumn::ColumnMode::DateTime:
329
			filter = new BigInt2DateTimeFilter();
330
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
331
			temp_col = new Column("temp_col", *(static_cast< QVector<qint64>* >(old_data)), m_column_mode);
332 333
			m_data = new QVector<QDateTime>();
			break;
334
		case AbstractColumn::ColumnMode::Month:
335
			filter = new BigInt2MonthFilter();
336
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
337
			temp_col = new Column("temp_col", *(static_cast< QVector<qint64>* >(old_data)), m_column_mode);
338 339
			m_data = new QVector<QDateTime>();
			break;
340
		case AbstractColumn::ColumnMode::Day:
341
			filter = new BigInt2DayOfWeekFilter();
342
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
343
			temp_col = new Column("temp_col", *(static_cast< QVector<qint64>* >(old_data)), m_column_mode);
344 345 346
			m_data = new QVector<QDateTime>();
			break;
		} // switch(mode)
Stefan Gerlach's avatar
Stefan Gerlach committed
347

348
		break;
Stefan Gerlach's avatar
Stefan Gerlach committed
349
	}
350
	case AbstractColumn::ColumnMode::Text: {
Stefan Gerlach's avatar
Stefan Gerlach committed
351
		switch (mode) {
352
		case AbstractColumn::ColumnMode::Text:
353
			break;
354
		case AbstractColumn::ColumnMode::Numeric:
355
			filter = new String2DoubleFilter();
356
			static_cast<String2DoubleFilter*>(filter)->setNumberLocale(numberLocale);
357
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
358
			temp_col = new Column("temp_col", *(static_cast<QVector<QString>*>(old_data)), m_column_mode);
359
			m_data = new QVector<double>();
360
			break;
361
		case AbstractColumn::ColumnMode::Integer:
362
			filter = new String2IntegerFilter();
363
			static_cast<String2IntegerFilter*>(filter)->setNumberLocale(numberLocale);
364
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
365
			temp_col = new Column("temp_col", *(static_cast<QVector<QString>*>(old_data)), m_column_mode);
366 367
			m_data = new QVector<int>();
			break;
368
		case AbstractColumn::ColumnMode::BigInt:
369
			filter = new String2BigIntFilter();
370
			static_cast<String2BigIntFilter*>(filter)->setNumberLocale(numberLocale);
Stefan Gerlach's avatar
Stefan Gerlach committed
371 372 373 374
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast<QVector<QString>*>(old_data)), m_column_mode);
			m_data = new QVector<qint64>();
			break;
375
		case AbstractColumn::ColumnMode::DateTime:
376 377
			filter = new String2DateTimeFilter();
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
378
			temp_col = new Column("temp_col", *(static_cast<QVector<QString>*>(old_data)), m_column_mode);
379
			m_data = new QVector<QDateTime>();
380
			break;
381
		case AbstractColumn::ColumnMode::Month:
382 383
			filter = new String2MonthFilter();
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
384
			temp_col = new Column("temp_col", *(static_cast<QVector<QString>*>(old_data)), m_column_mode);
385
			m_data = new QVector<QDateTime>();
386
			break;
387
		case AbstractColumn::ColumnMode::Day:
388 389
			filter = new String2DayOfWeekFilter();
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
390
			temp_col = new Column("temp_col", *(static_cast<QVector<QString>*>(old_data)), m_column_mode);
391
			m_data = new QVector<QDateTime>();
392 393
			break;
		} // switch(mode)
Stefan Gerlach's avatar
Stefan Gerlach committed
394

395
		break;
Stefan Gerlach's avatar
Stefan Gerlach committed
396
	}
397 398 399
	case AbstractColumn::ColumnMode::DateTime:
	case AbstractColumn::ColumnMode::Month:
	case AbstractColumn::ColumnMode::Day: {
400 401
		disconnect(static_cast<DateTime2StringFilter*>(m_output_filter), &DateTime2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
Stefan Gerlach's avatar
Stefan Gerlach committed
402
		switch (mode) {
403 404 405
		case AbstractColumn::ColumnMode::DateTime:
		case AbstractColumn::ColumnMode::Month:
		case AbstractColumn::ColumnMode::Day:
406
			break;
407
		case AbstractColumn::ColumnMode::Text:
408 409
			filter = outputFilter();
			filter_is_temporary = false;
Stefan Gerlach's avatar
Stefan Gerlach committed
410
			temp_col = new Column("temp_col", *(static_cast< QVector<QDateTime>* >(old_data)), m_column_mode);
411
			m_data = new QStringList();
412
			break;
413 414
		case AbstractColumn::ColumnMode::Numeric:
			if (m_column_mode == AbstractColumn::ColumnMode::Month)
415
				filter = new Month2DoubleFilter();
416
			else if (m_column_mode == AbstractColumn::ColumnMode::Day)
417 418 419 420
				filter = new DayOfWeek2DoubleFilter();
			else
				filter = new DateTime2DoubleFilter();
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
421
			temp_col = new Column("temp_col", *(static_cast< QVector<QDateTime>* >(old_data)), m_column_mode);
422 423
			m_data = new QVector<double>();
			break;
424 425
		case AbstractColumn::ColumnMode::Integer:
			if (m_column_mode == AbstractColumn::ColumnMode::Month)
426
				filter = new Month2IntegerFilter();
427
			else if (m_column_mode == AbstractColumn::ColumnMode::Day)
428 429 430 431
				filter = new DayOfWeek2IntegerFilter();
			else
				filter = new DateTime2IntegerFilter();
			filter_is_temporary = true;
Stefan Gerlach's avatar
Stefan Gerlach committed
432
			temp_col = new Column("temp_col", *(static_cast< QVector<QDateTime>* >(old_data)), m_column_mode);
433
			m_data = new QVector<int>();
434
			break;
435 436
		case AbstractColumn::ColumnMode::BigInt:
			if (m_column_mode == AbstractColumn::ColumnMode::Month)
Stefan Gerlach's avatar
Stefan Gerlach committed
437
				filter = new Month2BigIntFilter();
438
			else if (m_column_mode == AbstractColumn::ColumnMode::Day)
Stefan Gerlach's avatar
Stefan Gerlach committed
439 440 441 442 443 444 445
				filter = new DayOfWeek2BigIntFilter();
			else
				filter = new DateTime2BigIntFilter();
			filter_is_temporary = true;
			temp_col = new Column("temp_col", *(static_cast< QVector<QDateTime>* >(old_data)), m_column_mode);
			m_data = new QVector<qint64>();
			break;
446
		} // switch(mode)
Stefan Gerlach's avatar
Stefan Gerlach committed
447

448 449
		break;
	}
Stefan Gerlach's avatar
Stefan Gerlach committed
450
	}
451 452

	// determine the new input and output filters
Stefan Gerlach's avatar
Stefan Gerlach committed
453
	switch (mode) {	// new mode
454
	case AbstractColumn::ColumnMode::Numeric:
455
		new_in_filter = new String2DoubleFilter();
456
		static_cast<String2DoubleFilter*>(new_in_filter)->setNumberLocale(numberLocale);
457
		new_out_filter = new Double2StringFilter();
458
		static_cast<Double2StringFilter*>(new_out_filter)->setNumberLocale(numberLocale);
459 460
		connect(static_cast<Double2StringFilter*>(new_out_filter), &Double2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
461
		break;
462
	case AbstractColumn::ColumnMode::Integer:
463
		new_in_filter = new String2IntegerFilter();
464
		static_cast<String2IntegerFilter*>(new_in_filter)->setNumberLocale(numberLocale);
465
		new_out_filter = new Integer2StringFilter();
466
		static_cast<Integer2StringFilter*>(new_out_filter)->setNumberLocale(numberLocale);
467 468
		connect(static_cast<Integer2StringFilter*>(new_out_filter), &Integer2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
469
		break;
470
	case AbstractColumn::ColumnMode::BigInt:
471
		new_in_filter = new String2BigIntFilter();
472
		static_cast<String2BigIntFilter*>(new_in_filter)->setNumberLocale(numberLocale);
473
		new_out_filter = new BigInt2StringFilter();
474
		static_cast<BigInt2StringFilter*>(new_out_filter)->setNumberLocale(numberLocale);
475 476
		connect(static_cast<BigInt2StringFilter*>(new_out_filter), &BigInt2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
Stefan Gerlach's avatar
Stefan Gerlach committed
477
		break;
478
	case AbstractColumn::ColumnMode::Text:
479 480 481
		new_in_filter = new SimpleCopyThroughFilter();
		new_out_filter = new SimpleCopyThroughFilter();
		break;
482
	case AbstractColumn::ColumnMode::DateTime:
483 484
		new_in_filter = new String2DateTimeFilter();
		new_out_filter = new DateTime2StringFilter();
485 486
		connect(static_cast<DateTime2StringFilter*>(new_out_filter), &DateTime2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
487
		break;
488
	case AbstractColumn::ColumnMode::Month:
489 490
		new_in_filter = new String2MonthFilter();
		new_out_filter = new DateTime2StringFilter();
491
		static_cast<DateTime2StringFilter*>(new_out_filter)->setFormat("MMMM");
492
		DEBUG("	Month out_filter format: " << STDSTRING(static_cast<DateTime2StringFilter*>(new_out_filter)->format()));
493 494
		connect(static_cast<DateTime2StringFilter*>(new_out_filter), &DateTime2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
495
		break;
496
	case AbstractColumn::ColumnMode::Day:
497 498
		new_in_filter = new String2DayOfWeekFilter();
		new_out_filter = new DateTime2StringFilter();
499
		static_cast<DateTime2StringFilter*>(new_out_filter)->setFormat("dddd");
500 501
		connect(static_cast<DateTime2StringFilter*>(new_out_filter), &DateTime2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
502
		break;
503 504 505 506
	} // switch(mode)

	m_column_mode = mode;

507 508
	//new_in_filter->setName("InputFilter");
	//new_out_filter->setName("OutputFilter");
509 510
	m_input_filter = new_in_filter;
	m_output_filter = new_out_filter;
511 512
	m_input_filter->input(0, m_owner->m_string_io);
	m_output_filter->input(0, m_owner);
513 514
	m_input_filter->setHidden(true);
	m_output_filter->setHidden(true);
515

516
	if (temp_col) { // if temp_col == 0, only the input/output filters need to be changed
517 518
		// copy the filtered, i.e. converted, column (mode is orig mode)
		DEBUG("	temp_col column mode = " << ENUM_TO_STRING(AbstractColumn, ColumnMode, temp_col->columnMode()));
519
		filter->input(0, temp_col);
520
		DEBUG("	filter->output size = " << filter->output(0)->rowCount());
521 522 523 524 525 526 527
		copy(filter->output(0));
		delete temp_col;
	}

	if (filter_is_temporary) delete filter;

	emit m_owner->modeChanged(m_owner);
528
	DEBUG("ColumnPrivate::setColumnMode() DONE");
529 530
}

531 532 533
/**
 * \brief Replace all mode related members
 *
534
 * Replace column mode, data type, data pointer and filters directly
535
 */
536 537 538
void ColumnPrivate::replaceModeData(AbstractColumn::ColumnMode mode, void* data,
				AbstractSimpleFilter* in_filter, AbstractSimpleFilter* out_filter) {
	DEBUG("ColumnPrivate::replaceModeData()");
539 540
	emit m_owner->modeAboutToChange(m_owner);
	// disconnect formatChanged()
Stefan Gerlach's avatar
Stefan Gerlach committed
541
	switch (m_column_mode) {
542
	case AbstractColumn::ColumnMode::Numeric:
543 544
		disconnect(static_cast<Double2StringFilter*>(m_output_filter), &Double2StringFilter::formatChanged,
				   m_owner, &Column::handleFormatChange);
545
		break;
546
	case AbstractColumn::ColumnMode::Integer:
547 548
		disconnect(static_cast<Integer2StringFilter*>(m_output_filter), &Integer2StringFilter::formatChanged,
				   m_owner, &Column::handleFormatChange);
549
		break;
550
	case AbstractColumn::ColumnMode::BigInt:
551 552
		disconnect(static_cast<BigInt2StringFilter*>(m_output_filter), &BigInt2StringFilter::formatChanged,
				   m_owner, &Column::handleFormatChange);
Stefan Gerlach's avatar
Stefan Gerlach committed
553
		break;
554
	case AbstractColumn::ColumnMode::Text:
555
		break;
556 557 558
	case AbstractColumn::ColumnMode::DateTime:
	case AbstractColumn::ColumnMode::Month:
	case AbstractColumn::ColumnMode::Day:
559 560
		disconnect(static_cast<DateTime2StringFilter*>(m_output_filter), &DateTime2StringFilter::formatChanged,
				   m_owner, &Column::handleFormatChange);
561
		break;
562 563 564 565 566
	}

	m_column_mode = mode;
	m_data = data;

567 568
	//in_filter->setName("InputFilter");
	//out_filter->setName("OutputFilter");
569 570
	m_input_filter = in_filter;
	m_output_filter = out_filter;
571 572
	m_input_filter->input(0, m_owner->m_string_io);
	m_output_filter->input(0, m_owner);
573 574

	// connect formatChanged()
Stefan Gerlach's avatar
Stefan Gerlach committed
575
	switch (m_column_mode) {
576
	case AbstractColumn::ColumnMode::Numeric:
577 578
		connect(static_cast<Double2StringFilter*>(m_output_filter), &Double2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
579
		break;
580
	case AbstractColumn::ColumnMode::Integer:
581 582
		connect(static_cast<Integer2StringFilter*>(m_output_filter), &Integer2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
583
		break;
584
	case AbstractColumn::ColumnMode::BigInt:
585 586
		connect(static_cast<BigInt2StringFilter*>(m_output_filter), &BigInt2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
Stefan Gerlach's avatar
Stefan Gerlach committed
587
		break;
588
	case AbstractColumn::ColumnMode::Text:
589
		break;
590 591 592
	case AbstractColumn::ColumnMode::DateTime:
	case AbstractColumn::ColumnMode::Month:
	case AbstractColumn::ColumnMode::Day:
593 594
		connect(static_cast<DateTime2StringFilter*>(m_output_filter), &DateTime2StringFilter::formatChanged,
				m_owner, &Column::handleFormatChange);
595
		break;
596
	}
597 598 599 600

	emit m_owner->modeChanged(m_owner);
}

601
/**
602
 * \brief Replace data pointer
603
 */
604
void ColumnPrivate::replaceData(void* data) {
Stefan Gerlach's avatar
Stefan Gerlach committed
605
	DEBUG("ColumnPrivate::replaceData()")
606 607
	emit m_owner->dataAboutToChange(m_owner);
	m_data = data;
608
	invalidate();
609 610
	if (!m_owner->m_suppressDataChangedSignal)
		emit m_owner->dataChanged(m_owner);
611 612
}

613 614 615 616 617 618 619
/**
 * \brief Copy another column of the same type
 *
 * This function will return false if the data type
 * of 'other' is not the same as the type of 'this'.
 * Use a filter to convert a column to another type.
 */
620
bool ColumnPrivate::copy(const AbstractColumn* other) {
621
// 	DEBUG("ColumnPrivate::copy(other)");
622
	if (other->columnMode() != columnMode()) return false;
623
// 	DEBUG("	mode = " << ENUM_TO_STRING(AbstractColumn, ColumnMode, columnMode()));
624
	int num_rows = other->rowCount();
625
// 	DEBUG("	rows " << num_rows);
626 627

	emit m_owner->dataAboutToChange(m_owner);
628
	resizeTo(num_rows);
629 630

	// copy the data
Stefan Gerlach's avatar
Stefan Gerlach committed
631
	switch (m_column_mode) {
632
	case AbstractColumn::ColumnMode::Numeric: {
633
		double* ptr = static_cast<QVector<double>*>(m_data)->data();
634
		for (int i = 0; i < num_rows; ++i)
635 636 637
			ptr[i] = other->valueAt(i);
		break;
	}
638
	case AbstractColumn::ColumnMode::Integer: {
639
		int* ptr = static_cast<QVector<int>*>(m_data)->data();
640
		for (int i = 0; i < num_rows; ++i)
641 642 643
			ptr[i] = other->integerAt(i);
		break;
	}
644
	case AbstractColumn::ColumnMode::BigInt: {
Stefan Gerlach's avatar
Stefan Gerlach committed
645
		qint64* ptr = static_cast<QVector<qint64>*>(m_data)->data();
646 647
		for (int i = 0; i < num_rows; ++i)
			ptr[i] = other->bigIntAt(i);
Stefan Gerlach's avatar
Stefan Gerlach committed
648 649
		break;
	}
650
	case AbstractColumn::ColumnMode::Text: {
651
		auto* vec = static_cast<QVector<QString>*>(m_data);
652
		for (int i = 0; i < num_rows; ++i)
653
			vec->replace(i, other->textAt(i));
654 655
		break;
	}
656 657 658
	case AbstractColumn::ColumnMode::DateTime:
	case AbstractColumn::ColumnMode::Month:
	case AbstractColumn::ColumnMode::Day: {
659
		auto* vec = static_cast<QVector<QDateTime>*>(m_data);
660
		for (int i = 0; i < num_rows; ++i)
661
			vec->replace(i, other->dateTimeAt(i));
662 663
		break;
	}
664 665
	}

666 667
	if (!m_owner->m_suppressDataChangedSignal)
		emit m_owner->dataChanged(m_owner);
668 669 670 671

	return true;
}

672 673 674 675 676
/**
 * \brief Copies a part of another column of the same type
 *
 * This function will return false if the data type
 * of 'other' is not the same as the type of 'this'.
677 678
 * \param source pointer to the column to copy
 * \param source_start first row to copy in the column to copy
679 680
 * \param dest_start first row to copy in
 * \param num_rows the number of rows to copy
681
 */