mirror of
				https://github.com/subsurface/subsurface.git
				synced 2025-02-19 22:16:15 +00:00 
			
		
		
		
	filter: add a filter constraint widget
This add a widget that represents a single filter constraint. Since filter constraints are very general, the widget has to consider a number of cases: - numerical ranges - star-widget ranges - string lists - multiple choice lists Moreover, it supports units, which must be updated when the preferences change. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
		
							parent
							
								
									af9d379a41
								
							
						
					
					
						commit
						c0af74ba88
					
				
					 3 changed files with 544 additions and 0 deletions
				
			
		|  | @ -77,6 +77,8 @@ set(SUBSURFACE_INTERFACE | |||
| 	divesiteimportdialog.h | ||||
| 	downloadfromdivecomputer.cpp | ||||
| 	downloadfromdivecomputer.h | ||||
| 	filterconstraintwidget.cpp | ||||
| 	filterconstraintwidget.h | ||||
| 	filterwidget2.cpp | ||||
| 	filterwidget2.h | ||||
| 	findmovedimagesdialog.cpp | ||||
|  |  | |||
							
								
								
									
										472
									
								
								desktop-widgets/filterconstraintwidget.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										472
									
								
								desktop-widgets/filterconstraintwidget.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,472 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #include "filterconstraintwidget.h" | ||||
| #include "starwidget.h" | ||||
| #include "core/pref.h" | ||||
| #include "desktop-widgets/preferences/preferencesdialog.h" | ||||
| #include "qt-models/cleanertablemodel.h" // for trashIcon()
 | ||||
| #include "qt-models/filterconstraintmodel.h" | ||||
| 
 | ||||
| #include <QComboBox> | ||||
| #include <QDateEdit> | ||||
| #include <QDoubleSpinBox> | ||||
| #include <QHBoxLayout> | ||||
| #include <QLabel> | ||||
| #include <QLineEdit> | ||||
| #include <QListWidget> | ||||
| #include <QPushButton> | ||||
| #include <QTimeEdit> | ||||
| 
 | ||||
| // Helper function to get enums through Qt's variants
 | ||||
| template<typename T> | ||||
| static T getEnum(const QModelIndex &idx, int role) | ||||
| { | ||||
| 	return static_cast<T>(idx.data(role).value<int>()); | ||||
| } | ||||
| 
 | ||||
| // Helper function, which creates a combo box for a given model role
 | ||||
| // or returns null if the model doesn't return a proper list.
 | ||||
| static QComboBox *makeCombo(const QModelIndex &index, int role) | ||||
| { | ||||
| 	QStringList list = index.data(role).value<QStringList>(); | ||||
| 	if (list.isEmpty()) | ||||
| 		return nullptr; | ||||
| 	QComboBox *res = new QComboBox; | ||||
| 	res->addItems(list); | ||||
| 	res->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| // Helper function, which creates a multiple choice list for a given model role
 | ||||
| // or returns null if the model doesn't return a proper list.
 | ||||
| static QListWidget *makeMultipleChoice(const QModelIndex &index, int role) | ||||
| { | ||||
| 	QStringList list = index.data(role).value<QStringList>(); | ||||
| 	if (list.isEmpty()) | ||||
| 		return nullptr; | ||||
| 	QListWidget *res = new QListWidget; | ||||
| 	res->addItems(list); | ||||
| 	res->setSelectionMode(QAbstractItemView::ExtendedSelection); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| // Helper function to create a floating point spin box.
 | ||||
| // Currently, this allows a large range of values.
 | ||||
| // The limits should be adapted to the constraint in question.
 | ||||
| static QDoubleSpinBox *makeSpinBox(int numDecimals) | ||||
| { | ||||
| 	QDoubleSpinBox *res = new QDoubleSpinBox; | ||||
| 	res->setRange(-10000.0, 10000.0); | ||||
| 	res->setDecimals(numDecimals); | ||||
| 	res->setSingleStep(pow(10.0, -numDecimals)); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| // Helper function to create a date edit widget
 | ||||
| static QDateEdit *makeDateEdit() | ||||
| { | ||||
| 	QDateEdit *res = new QDateEdit; | ||||
| 	res->setCalendarPopup(true); | ||||
| 	res->setTimeSpec(Qt::UTC); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| // Helper function to create a date edit widget
 | ||||
| static QTimeEdit *makeTimeEdit() | ||||
| { | ||||
| 	QTimeEdit *res = new QTimeEdit; | ||||
| 	res->setTimeSpec(Qt::UTC); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| // Helper function, which creates a label with a given string
 | ||||
| // or returns null if the string is empty.
 | ||||
| static QLabel *makeLabel(const QString &s) | ||||
| { | ||||
| 	if (s.isEmpty()) | ||||
| 		return nullptr; | ||||
| 	return new QLabel(s); | ||||
| } | ||||
| 
 | ||||
| // Helper function, which sets the index of a combo box for a given
 | ||||
| // model role, if the combo box is not null.
 | ||||
| static void setIndex(QComboBox *w, const QModelIndex &index, int role) | ||||
| { | ||||
| 	if (!w) | ||||
| 		return; | ||||
| 	w->setCurrentIndex(index.data(role).value<int>()); | ||||
| } | ||||
| 
 | ||||
| // Helper function to add a widget to a layout if it is non-null
 | ||||
| static void addWidgetToLayout(QWidget *w, QHBoxLayout *l) | ||||
| { | ||||
| 	if (w) { | ||||
| 		l->addWidget(w); | ||||
| 		l->setAlignment(w, Qt::AlignLeft); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Helper functions that show / hide non-null widgets
 | ||||
| static void showWidget(QWidget *w) | ||||
| { | ||||
| 	if (w) | ||||
| 		w->show(); | ||||
| } | ||||
| 
 | ||||
| // Helper functions that show / hide non-null widgets
 | ||||
| static void hideWidget(QWidget *w) | ||||
| { | ||||
| 	if (w) | ||||
| 		w->hide(); | ||||
| } | ||||
| 
 | ||||
| // Helper function to create datatimes from either a single date widget,
 | ||||
| // or a combination of a date and a time widget.
 | ||||
| static QDateTime makeDateTime(const QDateEdit *d, const QTimeEdit *t) | ||||
| { | ||||
| 	if (!d) | ||||
| 		return QDateTime(); | ||||
| 	if (!t) | ||||
| 		return d->dateTime(); | ||||
| 	QDateTime res = d->dateTime(); | ||||
| 	res.setTime(t->time()); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| FilterConstraintWidget::FilterConstraintWidget(FilterConstraintModel *modelIn, const QModelIndex &index, QGridLayout *layoutIn) : QObject(layoutIn), | ||||
| 	layout(layoutIn), | ||||
| 	model(modelIn), | ||||
| 	row(index.row()), | ||||
| 	type(getEnum<filter_constraint_type>(index, FilterConstraintModel::TYPE_ROLE)) | ||||
| { | ||||
| 	rangeLayout.reset(new QHBoxLayout); | ||||
| 	rangeLayout->setAlignment(Qt::AlignLeft); | ||||
| 
 | ||||
| 	trashButton.reset(new QPushButton(QIcon(trashIcon()), QString())); | ||||
| 	trashButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); | ||||
| 	trashButton->setToolTip(tr("Click to remove this constraint")); | ||||
| 	connect(trashButton.get(), &QPushButton::clicked, this, &FilterConstraintWidget::trash); | ||||
| 
 | ||||
| 	typeLabel.reset(new QLabel(index.data(FilterConstraintModel::TYPE_DISPLAY_ROLE).value<QString>())); | ||||
| 	typeLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); | ||||
| 
 | ||||
| 	QString unitString = index.data(FilterConstraintModel::UNIT_ROLE).value<QString>(); | ||||
| 	negate.reset(makeCombo(index, FilterConstraintModel::NEGATE_COMBO_ROLE)); | ||||
| 	connect(negate.get(), QOverload<int>::of(&QComboBox::currentIndexChanged), this, &FilterConstraintWidget::negateEdited); | ||||
| 	stringMode.reset(makeCombo(index, FilterConstraintModel::STRING_MODE_COMBO_ROLE)); | ||||
| 	rangeMode.reset(makeCombo(index, FilterConstraintModel::RANGE_MODE_COMBO_ROLE)); | ||||
| 	multipleChoice.reset(makeMultipleChoice(index, FilterConstraintModel::MULTIPLE_CHOICE_LIST_ROLE)); | ||||
| 	bool isStarWidget = index.data(FilterConstraintModel::IS_STAR_WIDGET_ROLE).value<bool>(); | ||||
| 	bool hasDateWidget = index.data(FilterConstraintModel::HAS_DATE_WIDGET_ROLE).value<bool>(); | ||||
| 	bool hasTimeWidget = index.data(FilterConstraintModel::HAS_TIME_WIDGET_ROLE).value<bool>(); | ||||
| 	bool hasSpinBox = rangeMode && !stringMode && !hasDateWidget && !hasTimeWidget && !isStarWidget && !multipleChoice; | ||||
| 	unitFrom.reset(makeLabel(unitString)); | ||||
| 	unitTo.reset(makeLabel(unitString)); | ||||
| 	if (stringMode) { | ||||
| 		string.reset(new QLineEdit); | ||||
| 		string->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); | ||||
| 	} | ||||
| 	int numDecimals = hasSpinBox ? index.data(FilterConstraintModel::NUM_DECIMALS_ROLE).value<int>() : 0; | ||||
| 	if (string) | ||||
| 		connect(string.get(), &QLineEdit::textEdited, this, &FilterConstraintWidget::stringEdited); | ||||
| 
 | ||||
| 	if (multipleChoice) | ||||
| 		connect(multipleChoice.get(), &QListWidget::itemSelectionChanged, this, &FilterConstraintWidget::multipleChoiceEdited); | ||||
| 
 | ||||
| 	if (stringMode) | ||||
| 		connect(stringMode.get(), QOverload<int>::of(&QComboBox::currentIndexChanged), this, &FilterConstraintWidget::stringModeEdited); | ||||
| 
 | ||||
| 	if (rangeMode) { | ||||
| 		toLabel.reset(new QLabel(tr("and"))); | ||||
| 		connect(rangeMode.get(), QOverload<int>::of(&QComboBox::currentIndexChanged), this, &FilterConstraintWidget::rangeModeEdited); | ||||
| 	} | ||||
| 
 | ||||
| 	if (hasSpinBox) { | ||||
| 		spinBoxFrom.reset(makeSpinBox(numDecimals)); | ||||
| 		spinBoxTo.reset(makeSpinBox(numDecimals)); | ||||
| 		connect(spinBoxFrom.get(), QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &FilterConstraintWidget::fromEditedFloat); | ||||
| 		connect(spinBoxTo.get(), QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &FilterConstraintWidget::toEditedFloat); | ||||
| 	} | ||||
| 
 | ||||
| 	if (isStarWidget) { | ||||
| 		starFrom.reset(new StarWidget); | ||||
| 		starTo.reset(new StarWidget); | ||||
| 		connect(starFrom.get(), &StarWidget::valueChanged, this, &FilterConstraintWidget::fromEditedInt); | ||||
| 		connect(starTo.get(), &StarWidget::valueChanged, this, &FilterConstraintWidget::toEditedInt); | ||||
| 	} | ||||
| 
 | ||||
| 	if (hasDateWidget) { | ||||
| 		dateFrom.reset(makeDateEdit()); | ||||
| 		dateTo.reset(makeDateEdit()); | ||||
| 		connect(dateFrom.get(), &QDateEdit::dateTimeChanged, this, &FilterConstraintWidget::fromEditedTimestamp); | ||||
| 		connect(dateTo.get(), &QDateEdit::dateTimeChanged, this, &FilterConstraintWidget::toEditedTimestamp); | ||||
| 	} | ||||
| 
 | ||||
| 	if (hasTimeWidget) { | ||||
| 		timeFrom.reset(makeTimeEdit()); | ||||
| 		timeTo.reset(makeTimeEdit()); | ||||
| 		connect(timeFrom.get(), &QTimeEdit::dateTimeChanged, this, &FilterConstraintWidget::fromEditedTimestamp); | ||||
| 		connect(timeTo.get(), &QTimeEdit::dateTimeChanged, this, &FilterConstraintWidget::toEditedTimestamp); | ||||
| 	} | ||||
| 
 | ||||
| 	addWidgetToLayout(string.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(starFrom.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(spinBoxFrom.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(dateFrom.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(timeFrom.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(unitFrom.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(toLabel.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(starTo.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(spinBoxTo.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(dateTo.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(timeTo.get(), rangeLayout.get()); | ||||
| 	addWidgetToLayout(unitTo.get(), rangeLayout.get()); | ||||
| 	rangeLayout->addStretch(); | ||||
| 
 | ||||
| 	// Update the widget if the settings changed to reflect new units.
 | ||||
| 	connect(PreferencesDialog::instance(), &PreferencesDialog::settingsChanged, this, &FilterConstraintWidget::update); | ||||
| 
 | ||||
| 	addToLayout(); | ||||
| 	update(); | ||||
| } | ||||
| 
 | ||||
| FilterConstraintWidget::~FilterConstraintWidget() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::addToLayout() | ||||
| { | ||||
| 	// Careful: this must mirror the code in removeFromLayout() or weird things will happen.
 | ||||
| 
 | ||||
| 	// Note: we add 2 to row, because the first and second row of the filter layout
 | ||||
| 	// are reserved for the title line and the fulltext widget!
 | ||||
| 	int layoutRow = row + 2; | ||||
| 	layout->addWidget(trashButton.get(), layoutRow, 0); | ||||
| 	if (!stringMode && !rangeMode && !multipleChoice) { | ||||
| 		// If there are no string or range modes, we rearrange to "negate / type" to get
 | ||||
| 		// a layout of the type "is not planned" or "is not logged", where the subject is
 | ||||
| 		// implicitly "dive". This presumes SVO grammar, but so does the rest of the layout.
 | ||||
| 		layout->addWidget(negate.get(), layoutRow, 1, Qt::AlignLeft); | ||||
| 		layout->addWidget(typeLabel.get(), layoutRow, 2, Qt::AlignLeft); | ||||
| 	} else { | ||||
| 		layout->addWidget(negate.get(), layoutRow, 2, Qt::AlignLeft); | ||||
| 		layout->addWidget(typeLabel.get(), layoutRow, 1, Qt::AlignLeft); | ||||
| 	} | ||||
| 	if (stringMode) | ||||
| 		layout->addWidget(stringMode.get(), layoutRow, 3, Qt::AlignLeft); | ||||
| 	else if (rangeMode) | ||||
| 		layout->addWidget(rangeMode.get(), layoutRow, 3, Qt::AlignLeft); | ||||
| 	else if (multipleChoice) | ||||
| 		layout->addWidget(multipleChoice.get(), layoutRow, 3, 1, 2, Qt::AlignLeft); // column span 2
 | ||||
| 	if (!multipleChoice) | ||||
| 		layout->addLayout(rangeLayout.get(), layoutRow, 4, Qt::AlignLeft); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::removeFromLayout() | ||||
| { | ||||
| 	// Careful: this must mirror the code in addToLayout() or weird things will happen.
 | ||||
| 	layout->removeWidget(trashButton.get()); | ||||
| 	layout->removeWidget(negate.get()); | ||||
| 	layout->removeWidget(typeLabel.get()); | ||||
| 	if (stringMode) | ||||
| 		layout->removeWidget(stringMode.get()); | ||||
| 	else if (rangeMode) | ||||
| 		layout->removeWidget(rangeMode.get()); | ||||
| 	else if (multipleChoice) | ||||
| 		layout->removeWidget(multipleChoice.get()); | ||||
| 	if (!multipleChoice) | ||||
| 		layout->removeItem(rangeLayout.get()); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::update() | ||||
| { | ||||
| 	// The user might have changed the date and/or time format. Let's update the widgets.
 | ||||
| 	if (dateFrom) | ||||
| 		dateFrom->setDisplayFormat(prefs.date_format); | ||||
| 	if (dateTo) | ||||
| 		dateTo->setDisplayFormat(prefs.date_format); | ||||
| 	if (timeFrom) | ||||
| 		timeFrom->setDisplayFormat(prefs.time_format); | ||||
| 	if (timeTo) | ||||
| 		timeTo->setDisplayFormat(prefs.time_format); | ||||
| 
 | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	setIndex(negate.get(), idx, FilterConstraintModel::NEGATE_INDEX_ROLE); | ||||
| 	setIndex(stringMode.get(), idx, FilterConstraintModel::STRING_MODE_INDEX_ROLE); | ||||
| 	setIndex(rangeMode.get(), idx, FilterConstraintModel::RANGE_MODE_INDEX_ROLE); | ||||
| 	if (string) | ||||
| 		string->setText(idx.data(FilterConstraintModel::STRING_ROLE).value<QString>()); | ||||
| 	if (starFrom) | ||||
| 		starFrom->setCurrentStars(idx.data(FilterConstraintModel::INTEGER_FROM_ROLE).value<int>()); | ||||
| 	if (starTo) | ||||
| 		starTo->setCurrentStars(idx.data(FilterConstraintModel::INTEGER_TO_ROLE).value<int>()); | ||||
| 	if (spinBoxFrom) | ||||
| 		spinBoxFrom->setValue(idx.data(FilterConstraintModel::FLOAT_FROM_ROLE).value<double>()); | ||||
| 	if (spinBoxTo) | ||||
| 		spinBoxTo->setValue(idx.data(FilterConstraintModel::FLOAT_TO_ROLE).value<double>()); | ||||
| 	if (dateFrom) { | ||||
| 		QDateTime dateTime = idx.data(FilterConstraintModel::TIMESTAMP_FROM_ROLE).value<QDateTime>(); | ||||
| 		dateFrom->setDateTime(dateTime); | ||||
| 		if (timeFrom) | ||||
| 			timeFrom->setDateTime(dateTime); | ||||
| 	} else if (timeFrom) { | ||||
| 		timeFrom->setTime(idx.data(FilterConstraintModel::TIME_FROM_ROLE).value<QTime>()); | ||||
| 	} | ||||
| 	if (dateTo) { | ||||
| 		QDateTime dateTime = idx.data(FilterConstraintModel::TIMESTAMP_TO_ROLE).value<QDateTime>(); | ||||
| 		dateTo->setDateTime(dateTime); | ||||
| 		if (timeTo) | ||||
| 			timeTo->setDateTime(dateTime); | ||||
| 	} else if (timeTo) { | ||||
| 		timeTo->setTime(idx.data(FilterConstraintModel::INTEGER_TO_ROLE).value<QTime>()); | ||||
| 	} | ||||
| 	if (multipleChoice) { | ||||
| 		uint64_t bits = idx.data(FilterConstraintModel::MULTIPLE_CHOICE_ROLE).value<uint64_t>(); | ||||
| 		for (int i = 0; i < multipleChoice->count(); ++i) | ||||
| 			multipleChoice->item(i)->setSelected(bits & (1 << i)); | ||||
| 	} | ||||
| 
 | ||||
| 	// Update the unit strings in case the locale was changed
 | ||||
| 	if (unitFrom || unitTo) { | ||||
| 		QString unitString = idx.data(FilterConstraintModel::UNIT_ROLE).value<QString>(); | ||||
| 		unitFrom->setText(unitString); | ||||
| 		unitTo->setText(unitString); | ||||
| 	} | ||||
| 
 | ||||
| 	if (rangeMode) { | ||||
| 		switch(getEnum<filter_constraint_range_mode>(idx, FilterConstraintModel::RANGE_MODE_ROLE)) { | ||||
| 		case FILTER_CONSTRAINT_LESS: | ||||
| 			hideWidget(toLabel.get()); | ||||
| 			hideWidget(starFrom.get()); | ||||
| 			hideWidget(spinBoxFrom.get()); | ||||
| 			hideWidget(dateFrom.get()); | ||||
| 			hideWidget(timeFrom.get()); | ||||
| 			hideWidget(unitFrom.get()); | ||||
| 			showWidget(starTo.get()); | ||||
| 			showWidget(spinBoxTo.get()); | ||||
| 			showWidget(dateTo.get()); | ||||
| 			showWidget(timeTo.get()); | ||||
| 			showWidget(unitTo.get()); | ||||
| 			break; | ||||
| 		case FILTER_CONSTRAINT_EQUAL: | ||||
| 		case FILTER_CONSTRAINT_GREATER: | ||||
| 			hideWidget(toLabel.get()); | ||||
| 			showWidget(starFrom.get()); | ||||
| 			showWidget(spinBoxFrom.get()); | ||||
| 			showWidget(dateFrom.get()); | ||||
| 			showWidget(timeFrom.get()); | ||||
| 			showWidget(unitFrom.get()); | ||||
| 			hideWidget(starTo.get()); | ||||
| 			hideWidget(spinBoxTo.get()); | ||||
| 			hideWidget(dateTo.get()); | ||||
| 			hideWidget(timeTo.get()); | ||||
| 			hideWidget(unitTo.get()); | ||||
| 			break; | ||||
| 		case FILTER_CONSTRAINT_RANGE: | ||||
| 			showWidget(toLabel.get()); | ||||
| 			showWidget(starFrom.get()); | ||||
| 			showWidget(spinBoxFrom.get()); | ||||
| 			showWidget(dateFrom.get()); | ||||
| 			showWidget(timeFrom.get()); | ||||
| 			showWidget(unitFrom.get()); | ||||
| 			showWidget(starTo.get()); | ||||
| 			showWidget(spinBoxTo.get()); | ||||
| 			showWidget(dateTo.get()); | ||||
| 			showWidget(timeTo.get()); | ||||
| 			showWidget(unitTo.get()); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::stringEdited(const QString &s) | ||||
| { | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	model->setData(idx, s, FilterConstraintModel::STRING_ROLE); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::multipleChoiceEdited() | ||||
| { | ||||
| 	// Turn selected items into bit-field
 | ||||
| 	uint64_t bits = 0; | ||||
| 	for (const QModelIndex &idx: multipleChoice->selectionModel()->selectedIndexes()) { | ||||
| 		int row = idx.row(); | ||||
| 		if (row >= 64) | ||||
| 			qWarning("FilterConstraint: multiple-choice with more than 64 entries not supported"); | ||||
| 		bits |= 1 << row; | ||||
| 	} | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	model->setData(idx, qulonglong(bits), FilterConstraintModel::MULTIPLE_CHOICE_ROLE); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::fromEditedInt(int i) | ||||
| { | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	model->setData(idx, i, FilterConstraintModel::INTEGER_FROM_ROLE); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::toEditedInt(int i) | ||||
| { | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	model->setData(idx, i, FilterConstraintModel::INTEGER_TO_ROLE); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::fromEditedFloat(double f) | ||||
| { | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	model->setData(idx, f, FilterConstraintModel::FLOAT_FROM_ROLE); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::toEditedFloat(double f) | ||||
| { | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	model->setData(idx, f, FilterConstraintModel::FLOAT_TO_ROLE); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::fromEditedTimestamp(const QDateTime &datetime) | ||||
| { | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	if (!dateFrom && timeFrom) | ||||
| 		model->setData(idx, timeFrom->time(), FilterConstraintModel::TIME_FROM_ROLE); | ||||
| 	else | ||||
| 		model->setData(idx, makeDateTime(dateFrom.get(), timeFrom.get()), FilterConstraintModel::TIMESTAMP_FROM_ROLE); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::toEditedTimestamp(const QDateTime &datetime) | ||||
| { | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	if (!dateTo && timeTo) | ||||
| 		model->setData(idx, timeTo->time(), FilterConstraintModel::TIME_TO_ROLE); | ||||
| 	else | ||||
| 		model->setData(idx, makeDateTime(dateTo.get(), timeTo.get()), FilterConstraintModel::TIMESTAMP_TO_ROLE); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::negateEdited(int i) | ||||
| { | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	model->setData(idx, i, FilterConstraintModel::NEGATE_INDEX_ROLE); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::rangeModeEdited(int i) | ||||
| { | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	model->setData(idx, i, FilterConstraintModel::RANGE_MODE_INDEX_ROLE); | ||||
| 	update(); // Range mode may change the shown widgets
 | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::stringModeEdited(int i) | ||||
| { | ||||
| 	QModelIndex idx = model->index(row, 0); | ||||
| 	model->setData(idx, i, FilterConstraintModel::STRING_MODE_INDEX_ROLE); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::moveToRow(int rowIn) | ||||
| { | ||||
| 	removeFromLayout(); | ||||
| 	row = rowIn; | ||||
| 	addToLayout(); | ||||
| } | ||||
| 
 | ||||
| void FilterConstraintWidget::trash() | ||||
| { | ||||
| 	model->deleteConstraint(row); | ||||
| } | ||||
							
								
								
									
										70
									
								
								desktop-widgets/filterconstraintwidget.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								desktop-widgets/filterconstraintwidget.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,70 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #ifndef FILTERCONSTRAINTWIDGET_H | ||||
| #define FILTERCONSTRAINTWIDGET_H | ||||
| 
 | ||||
| #include "core/filterconstraint.h" | ||||
| #include <QWidget> | ||||
| #include <memory> | ||||
| 
 | ||||
| class FilterConstraintModel; | ||||
| class QComboBox; | ||||
| class QDateEdit; | ||||
| class QDoubleSpinBox; | ||||
| class QGridLayout; | ||||
| class QHBoxLayout; | ||||
| class QLabel; | ||||
| class QLineEdit; | ||||
| class QListWidget; | ||||
| class QPushButton; | ||||
| class QTimeEdit; | ||||
| class StarWidget; | ||||
| 
 | ||||
| // Technically, this is not a single widget, but numerous widgets,
 | ||||
| // which are added to the row of a QGridLayout
 | ||||
| class FilterConstraintWidget : public QObject { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	FilterConstraintWidget(FilterConstraintModel *model, const QModelIndex &index, QGridLayout *layout); | ||||
| 	~FilterConstraintWidget(); | ||||
| 	void moveToRow(int row); // call if the row of the widget has changed.
 | ||||
| 				 // this will update the index used to access the model as well as the position in the layout
 | ||||
| 	void update(); | ||||
| private | ||||
| slots: | ||||
| 	void trash(); | ||||
| 	void stringEdited(const QString &s); | ||||
| 	void multipleChoiceEdited(); | ||||
| 	void negateEdited(int index); | ||||
| 	void rangeModeEdited(int index); | ||||
| 	void stringModeEdited(int index); | ||||
| 	void fromEditedInt(int i); | ||||
| 	void toEditedInt(int i); | ||||
| 	void fromEditedFloat(double f); | ||||
| 	void toEditedFloat(double f); | ||||
| 	void fromEditedTimestamp(const QDateTime &datetime); | ||||
| 	void toEditedTimestamp(const QDateTime &datetime); | ||||
| private: | ||||
| 	QGridLayout *layout; | ||||
| 	FilterConstraintModel *model; | ||||
| 	int row; | ||||
| 	const filter_constraint_type type; // we don't support changing the type
 | ||||
| 	void addToLayout(); | ||||
| 	void removeFromLayout(); | ||||
| 
 | ||||
| 	std::unique_ptr<QHBoxLayout> rangeLayout; | ||||
| 	std::unique_ptr<QPushButton> trashButton; | ||||
| 	std::unique_ptr<QLabel> typeLabel; | ||||
| 	std::unique_ptr<QComboBox> negate; | ||||
| 	std::unique_ptr<QComboBox> stringMode; | ||||
| 	std::unique_ptr<QComboBox> rangeMode; | ||||
| 	std::unique_ptr<QListWidget> multipleChoice; | ||||
| 	std::unique_ptr<QLineEdit> string; | ||||
| 	std::unique_ptr<StarWidget> starFrom, starTo; | ||||
| 	std::unique_ptr<QDoubleSpinBox> spinBoxFrom, spinBoxTo; | ||||
| 	std::unique_ptr<QDateEdit> dateFrom, dateTo; | ||||
| 	std::unique_ptr<QTimeEdit> timeFrom, timeTo; | ||||
| 	std::unique_ptr<QLabel> unitFrom, unitTo; | ||||
| 	std::unique_ptr<QLabel> toLabel; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue