mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 05:00:20 +00:00
68b63534a3
This was just ugly: the column with the "trash" symbol and the name had the same size. On creation of the object, make the last column expand and adapt the size of the "trash" column according to its content. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
268 lines
9.2 KiB
C++
268 lines
9.2 KiB
C++
#include "desktop-widgets/filterwidget.h"
|
|
#include "desktop-widgets/filterconstraintwidget.h"
|
|
#include "desktop-widgets/simplewidgets.h"
|
|
#include "desktop-widgets/mainwindow.h"
|
|
#include "commands/command.h"
|
|
#include "core/qthelper.h"
|
|
#include "core/divelist.h"
|
|
#include "core/settings/qPrefUnit.h"
|
|
#include "qt-models/filterpresetmodel.h"
|
|
|
|
FilterWidget::FilterWidget(QWidget* parent) :
|
|
QWidget(parent),
|
|
ignoreSignal(false),
|
|
presetModified(false)
|
|
{
|
|
ui.setupUi(this);
|
|
|
|
QMenu *newConstraintMenu = new QMenu(this);
|
|
QStringList constraintTypes = filter_constraint_type_list_translated();
|
|
for (int i = 0; i < constraintTypes.size(); ++i) {
|
|
filter_constraint_type type = filter_constraint_type_from_index(i);
|
|
newConstraintMenu->addAction(constraintTypes[i], [this, type]() { addConstraint(type); });
|
|
}
|
|
ui.addConstraintButton->setMenu(newConstraintMenu);
|
|
ui.addConstraintButton->setPopupMode(QToolButton::InstantPopup);
|
|
ui.constraintTable->setColumnStretch(4, 1); // The fifth column is were the actual constraint resides - stretch that.
|
|
|
|
ui.loadSetButton->setPopupMode(QToolButton::InstantPopup);
|
|
|
|
ui.presetTable->setModel(FilterPresetModel::instance());
|
|
ui.presetTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
ui.presetTable->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
ui.presetTable->horizontalHeader()->setStretchLastSection(true);
|
|
ui.presetTable->resizeColumnsToContents();
|
|
|
|
connect(ui.clear, &QToolButton::clicked, this, &FilterWidget::clearFilter);
|
|
connect(ui.close, &QToolButton::clicked, this, &FilterWidget::closeFilter);
|
|
connect(ui.fullText, &QLineEdit::textChanged, this, &FilterWidget::filterChanged);
|
|
connect(ui.fulltextStringMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &FilterWidget::filterChanged);
|
|
connect(ui.presetTable, &QTableView::clicked, this, &FilterWidget::presetClicked);
|
|
connect(ui.presetTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &FilterWidget::presetSelected);
|
|
|
|
connect(&constraintModel, &FilterConstraintModel::rowsInserted, this, &FilterWidget::constraintAdded);
|
|
connect(&constraintModel, &FilterConstraintModel::rowsRemoved, this, &FilterWidget::constraintRemoved);
|
|
connect(&constraintModel, &FilterConstraintModel::dataChanged, this, &FilterWidget::constraintChanged);
|
|
connect(&constraintModel, &FilterConstraintModel::modelReset, this, &FilterWidget::constraintsReset);
|
|
|
|
// QDataWidgetMapper might be the more civilized way to keep the menus up to data.
|
|
// For now, let's be blunt and fully reload the context menu if the presets list changes.
|
|
// This gives us more flexibility in populating the menus.
|
|
QAbstractItemModel *presetModel = FilterPresetModel::instance();
|
|
connect(presetModel, &QAbstractItemModel::rowsInserted, this, &FilterWidget::updatePresetMenu);
|
|
connect(presetModel, &QAbstractItemModel::rowsRemoved, this, &FilterWidget::updatePresetMenu);
|
|
connect(presetModel, &QAbstractItemModel::dataChanged, this, &FilterWidget::updatePresetMenu);
|
|
connect(presetModel, &QAbstractItemModel::modelReset, this, &FilterWidget::updatePresetMenu);
|
|
|
|
clearFilter();
|
|
updatePresetMenu();
|
|
}
|
|
|
|
FilterWidget::~FilterWidget()
|
|
{
|
|
}
|
|
|
|
void FilterWidget::updatePresetMenu()
|
|
{
|
|
loadFilterPresetMenu.reset(new QMenu);
|
|
QAbstractItemModel *model = FilterPresetModel::instance();
|
|
int count = model->rowCount(QModelIndex());
|
|
if (count == 0) {
|
|
ui.loadSetButton->setEnabled(false);
|
|
return;
|
|
}
|
|
ui.loadSetButton->setEnabled(true);
|
|
for (int i = 0; i < count; ++i) {
|
|
QModelIndex idx = model->index(i, FilterPresetModel::NAME);
|
|
QString name = model->data(idx, Qt::DisplayRole).value<QString>();
|
|
loadFilterPresetMenu->addAction(name, [this,i]() { selectPreset(i); });
|
|
}
|
|
ui.loadSetButton->setMenu(loadFilterPresetMenu.get());
|
|
}
|
|
|
|
void FilterWidget::selectPreset(int i)
|
|
{
|
|
QAbstractItemModel *model = FilterPresetModel::instance();
|
|
QItemSelectionModel *selectionModel = ui.presetTable->selectionModel();
|
|
QModelIndex idx = model->index(i, 0);
|
|
selectionModel->reset();
|
|
selectionModel->select(idx, QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
|
}
|
|
|
|
void FilterWidget::loadPreset(int index)
|
|
{
|
|
ignoreSignal = true; // When reloading the filter UI, we get numerous constraintChanged signals. Ignore them.
|
|
FilterData filter = filter_preset_get(index);
|
|
setFilterData(filter);
|
|
ignoreSignal = false;
|
|
presetModified = false;
|
|
updateFilter();
|
|
}
|
|
|
|
void FilterWidget::constraintAdded(const QModelIndex &parent, int first, int last)
|
|
{
|
|
if (parent.isValid() || last < first)
|
|
return; // We only support one level
|
|
constraintWidgets.reserve(constraintWidgets.size() + 1 + last - first);
|
|
for (int i = last + 1; i < (int)constraintWidgets.size(); ++i)
|
|
constraintWidgets[i]->moveToRow(i);
|
|
for (int i = first; i <= last; ++i) {
|
|
QModelIndex idx = constraintModel.index(i, 0);
|
|
constraintWidgets.emplace(constraintWidgets.begin() + i, new FilterConstraintWidget(&constraintModel, idx, ui.constraintTable));
|
|
}
|
|
filterChanged();
|
|
}
|
|
|
|
void FilterWidget::constraintRemoved(const QModelIndex &parent, int first, int last)
|
|
{
|
|
if (parent.isValid() || last < first)
|
|
return; // We only support one level
|
|
constraintWidgets.erase(constraintWidgets.begin() + first, constraintWidgets.begin() + last + 1);
|
|
for (int i = first; i < (int)constraintWidgets.size(); ++i)
|
|
constraintWidgets[i]->moveToRow(i);
|
|
filterChanged();
|
|
}
|
|
|
|
void FilterWidget::presetClicked(const QModelIndex &index)
|
|
{
|
|
if (!index.isValid())
|
|
return;
|
|
|
|
if (index.column() == FilterPresetModel::REMOVE)
|
|
Command::removeFilterPreset(index.row());
|
|
}
|
|
|
|
void FilterWidget::presetSelected(const QItemSelection &selected, const QItemSelection &)
|
|
{
|
|
if (selected.indexes().isEmpty())
|
|
return clearFilter();
|
|
const QModelIndex index = selected.indexes()[0];
|
|
if (!index.isValid())
|
|
return clearFilter();
|
|
loadPreset(index.row());
|
|
}
|
|
|
|
void FilterWidget::constraintChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
|
|
{
|
|
// Note: this may appear strange, but we don't update the widget if we get
|
|
// a constraint-changed signal from the model. The reason being that the user
|
|
// is currently editing the constraint and we don't want to bother them by
|
|
// overwriting strings with canonicalized data.
|
|
filterChanged();
|
|
}
|
|
|
|
void FilterWidget::constraintsReset()
|
|
{
|
|
constraintWidgets.clear();
|
|
int count = constraintModel.rowCount(QModelIndex());
|
|
for (int i = 0; i < count; ++i) {
|
|
QModelIndex idx = constraintModel.index(i, 0);
|
|
constraintWidgets.emplace_back(new FilterConstraintWidget(&constraintModel, idx, ui.constraintTable));
|
|
}
|
|
updateFilter();
|
|
}
|
|
|
|
void FilterWidget::clearFilter()
|
|
{
|
|
ignoreSignal = true; // Prevent signals to force filter recalculation (TODO: check if necessary)
|
|
presetModified = false;
|
|
ui.presetTable->selectionModel()->reset(); // Note: we use reset(), because that doesn't emit signals.
|
|
ui.fulltextStringMode->setCurrentIndex((int)StringFilterMode::STARTSWITH);
|
|
ui.fullText->clear();
|
|
ui.presetTable->clearSelection();
|
|
ignoreSignal = false;
|
|
constraintModel.reload({}); // Causes a filter reload
|
|
}
|
|
|
|
void FilterWidget::closeFilter()
|
|
{
|
|
MainWindow::instance()->setApplicationState(ApplicationState::Default);
|
|
}
|
|
|
|
FilterData FilterWidget::createFilterData() const
|
|
{
|
|
FilterData filterData;
|
|
filterData.fulltextStringMode = (StringFilterMode)ui.fulltextStringMode->currentIndex();
|
|
filterData.fullText = ui.fullText->text();
|
|
filterData.constraints = constraintModel.getConstraints();
|
|
return filterData;
|
|
}
|
|
|
|
void FilterWidget::setFilterData(const FilterData &filterData)
|
|
{
|
|
ui.fulltextStringMode->setCurrentIndex((int)filterData.fulltextStringMode);
|
|
ui.fullText->setText(filterData.fullText.originalQuery);
|
|
constraintModel.reload(filterData.constraints);
|
|
}
|
|
|
|
void FilterWidget::filterChanged()
|
|
{
|
|
presetModified = true;
|
|
updateFilter();
|
|
}
|
|
|
|
void FilterWidget::updateFilter()
|
|
{
|
|
if (ignoreSignal)
|
|
return;
|
|
|
|
FilterData filterData = createFilterData();
|
|
DiveFilter::instance()->setFilter(filterData);
|
|
updatePresetLabel();
|
|
}
|
|
|
|
int FilterWidget::selectedPreset() const
|
|
{
|
|
QModelIndexList selection = ui.presetTable->selectionModel()->selectedRows();
|
|
return selection.size() >= 1 ? selection[0].row() : -1;
|
|
}
|
|
|
|
void FilterWidget::updatePresetLabel()
|
|
{
|
|
int presetId = selectedPreset();
|
|
QString text;
|
|
if (presetId >= 0) {
|
|
text = filter_preset_name_qstring(presetId);
|
|
if (presetModified)
|
|
text += " (" + tr("modified") + ")";
|
|
}
|
|
ui.currentSet->setText(text);
|
|
}
|
|
|
|
void FilterWidget::on_addSetButton_clicked()
|
|
{
|
|
// If there is a selected item, suggest that to the user.
|
|
// Thus, if the user selects an item and modify the filter,
|
|
// they can simply overwrite the preset.
|
|
int presetId = selectedPreset();
|
|
QString selectedPreset = presetId >= 0 ? filter_preset_name_qstring(presetId) : QString();
|
|
|
|
AddFilterPresetDialog dialog(selectedPreset, this);
|
|
QString name = dialog.doit();
|
|
if (name.isEmpty())
|
|
return;
|
|
int idx = filter_preset_id(name);
|
|
if (idx >= 0)
|
|
Command::editFilterPreset(idx, createFilterData());
|
|
else
|
|
Command::createFilterPreset(name, createFilterData());
|
|
presetModified = false;
|
|
updatePresetLabel();
|
|
}
|
|
|
|
void FilterWidget::showEvent(QShowEvent *event)
|
|
{
|
|
QWidget::showEvent(event);
|
|
ui.fullText->setFocus();
|
|
updateFilter();
|
|
}
|
|
|
|
void FilterWidget::hideEvent(QHideEvent *event)
|
|
{
|
|
QWidget::hideEvent(event);
|
|
}
|
|
|
|
void FilterWidget::addConstraint(filter_constraint_type type)
|
|
{
|
|
constraintModel.addConstraint(type);
|
|
}
|