desktop: unglobalize ComboBox-models

The combo-boxes (cylinder type, weightsystem, etc.) were controlled
by global models. Keeping these models up-to-date was very combersome
and buggy.

Create a new model everytime a combobox is opened. Ultimately it
might even be better to create a copy of the strings and switch
to simple QStringListModel. Set data in the core directly and
don't do this via the models.

The result is much simpler and easier to handle.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-03-30 13:40:00 +01:00 committed by Michael Keller
parent de313bd01a
commit 0d011231e6
16 changed files with 130 additions and 215 deletions

View file

@ -1090,11 +1090,6 @@ EditWeight::EditWeight(int index, weightsystem_t wsIn, bool currentDiveOnly) :
dives.clear(); dives.clear();
return; return;
} }
WSInfoModel *wsim = WSInfoModel::instance();
QModelIndexList matches = wsim->match(wsim->index(0, 0), Qt::DisplayRole, gettextFromC::tr(new_ws.description));
if (!matches.isEmpty())
wsim->setData(wsim->index(matches.first().row(), WSInfoModel::GR), new_ws.weight.grams);
} }
EditWeight::~EditWeight() EditWeight::~EditWeight()
@ -1105,6 +1100,7 @@ EditWeight::~EditWeight()
void EditWeight::redo() void EditWeight::redo()
{ {
for (size_t i = 0; i < dives.size(); ++i) { for (size_t i = 0; i < dives.size(); ++i) {
add_weightsystem_description(&new_ws); // This updates the weightsystem info table
set_weightsystem(dives[i], indices[i], new_ws); set_weightsystem(dives[i], indices[i], new_ws);
emit diveListNotifier.weightEdited(dives[i], indices[i]); emit diveListNotifier.weightEdited(dives[i], indices[i]);
invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save() invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save()
@ -1302,16 +1298,6 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn,
} }
} }
// Update the tank info model
TankInfoModel *tim = TankInfoModel::instance();
QModelIndexList matches = tim->match(tim->index(0, 0), Qt::DisplayRole, gettextFromC::tr(cylIn.type.description));
if (!matches.isEmpty()) {
if (cylIn.type.size.mliter != cyl[0].type.size.mliter)
tim->setData(tim->index(matches.first().row(), TankInfoModel::ML), cylIn.type.size.mliter);
if (cylIn.type.workingpressure.mbar != cyl[0].type.workingpressure.mbar)
tim->setData(tim->index(matches.first().row(), TankInfoModel::BAR), cylIn.type.workingpressure.mbar / 1000.0);
}
// The base class copied the cylinders for us, let's edit them // The base class copied the cylinders for us, let's edit them
for (int i = 0; i < (int)indexes.size(); ++i) { for (int i = 0; i < (int)indexes.size(); ++i) {
switch (type) { switch (type) {
@ -1338,6 +1324,8 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn,
void EditCylinder::redo() void EditCylinder::redo()
{ {
for (size_t i = 0; i < dives.size(); ++i) { for (size_t i = 0; i < dives.size(); ++i) {
set_tank_info_size(&tank_info_table, cyl[i].type.description, cyl[i].type.size);
set_tank_info_workingpressure(&tank_info_table, cyl[i].type.description, cyl[i].type.workingpressure);
std::swap(*get_cylinder(dives[i], indexes[i]), cyl[i]); std::swap(*get_cylinder(dives[i], indexes[i]), cyl[i]);
update_cylinder_related_info(dives[i]); update_cylinder_related_info(dives[i]);
emit diveListNotifier.cylinderEdited(dives[i], indexes[i]); emit diveListNotifier.cylinderEdited(dives[i], indexes[i]);
@ -1358,7 +1346,6 @@ EditSensors::EditSensors(int toCylinderIn, int fromCylinderIn, int dcNr)
return; return;
setText(Command::Base::tr("Edit sensors")); setText(Command::Base::tr("Edit sensors"));
} }
void EditSensors::mapSensors(int toCyl, int fromCyl) void EditSensors::mapSensors(int toCyl, int fromCyl)

View file

@ -108,6 +108,45 @@ void add_tank_info_imperial(struct tank_info_table *table, const char *name, int
add_to_tank_info_table(table, table->nr, info); add_to_tank_info_table(table, table->nr, info);
} }
extern struct tank_info *get_tank_info(struct tank_info_table *table, const char *name)
{
for (int i = 0; i < table->nr; ++i) {
if (same_string(table->infos[i].name, name))
return &table->infos[i];
}
return NULL;
}
extern void set_tank_info_size(struct tank_info_table *table, const char *name, volume_t size)
{
struct tank_info *info = get_tank_info(table, name);
if (info) {
// Try to be smart about metric vs. imperial
if (info->cuft == 0 && info->psi == 0)
info->ml = size.mliter;
else
info->cuft = lrint(ml_to_cuft(size.mliter));
} else {
// By default add metric...?
add_tank_info_metric(table, name, size.mliter, 0);
}
}
extern void set_tank_info_workingpressure(struct tank_info_table *table, const char *name, pressure_t working_pressure)
{
struct tank_info *info = get_tank_info(table, name);
if (info) {
// Try to be smart about metric vs. imperial
if (info->cuft == 0 && info->psi == 0)
info->bar = working_pressure.mbar / 1000;
else
info->psi = lrint(mbar_to_PSI(working_pressure.mbar));
} else {
// By default add metric...?
add_tank_info_metric(table, name, 0, working_pressure.mbar / 1000);
}
}
/* placeholders for a few functions that we need to redesign for the Qt UI */ /* placeholders for a few functions that we need to redesign for the Qt UI */
void add_cylinder_description(const cylinder_type_t *type) void add_cylinder_description(const cylinder_type_t *type)
{ {
@ -131,7 +170,7 @@ void add_weightsystem_description(const weightsystem_t *weightsystem)
if (!desc) if (!desc)
return; return;
for (i = 0; i < MAX_WS_INFO && ws_info[i].name != NULL; i++) { for (i = 0; i < MAX_WS_INFO && ws_info[i].name != NULL; i++) {
if (strcmp(ws_info[i].name, desc) == 0) { if (same_string(ws_info[i].name, desc)) {
ws_info[i].grams = weightsystem->weight.grams; ws_info[i].grams = weightsystem->weight.grams;
return; return;
} }
@ -143,6 +182,17 @@ void add_weightsystem_description(const weightsystem_t *weightsystem)
} }
} }
struct ws_info_t *get_weightsystem_description(const char *name)
{
for (int i = 0; i < MAX_WS_INFO && ws_info[i].name != NULL; i++) {
// Also finds translated names (TODO: should only consider non-user items).
if (same_string(ws_info[i].name, name) ||
same_string(translate("gettextFromC", ws_info[i].name), name))
return &ws_info[i];
}
return NULL;
}
weightsystem_t clone_weightsystem(weightsystem_t ws) weightsystem_t clone_weightsystem(weightsystem_t ws)
{ {
weightsystem_t res = { ws.weight, copy_string(ws.description), ws.auto_filled }; weightsystem_t res = { ws.weight, copy_string(ws.description), ws.auto_filled };

View file

@ -125,12 +125,16 @@ extern void reset_tank_info_table(struct tank_info_table *table);
extern void clear_tank_info_table(struct tank_info_table *table); extern void clear_tank_info_table(struct tank_info_table *table);
extern void add_tank_info_metric(struct tank_info_table *table, const char *name, int ml, int bar); extern void add_tank_info_metric(struct tank_info_table *table, const char *name, int ml, int bar);
extern void add_tank_info_imperial(struct tank_info_table *table, const char *name, int cuft, int psi); extern void add_tank_info_imperial(struct tank_info_table *table, const char *name, int cuft, int psi);
extern void set_tank_info_size(struct tank_info_table *table, const char *name, volume_t size);
extern void set_tank_info_workingpressure(struct tank_info_table *table, const char *name, pressure_t working_pressure);
extern struct tank_info *get_tank_info(struct tank_info_table *table, const char *name);
struct ws_info_t { struct ws_info_t {
const char *name; const char *name;
int grams; int grams;
}; };
extern struct ws_info_t ws_info[MAX_WS_INFO]; extern struct ws_info_t ws_info[MAX_WS_INFO];
extern struct ws_info_t *get_weightsystem_description(const char *name);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -32,8 +32,8 @@ DivePlannerWidget::DivePlannerWidget(dive &planned_dive, PlannerWidgets *parent)
ui.tableWidget->setTitle(tr("Dive planner points")); ui.tableWidget->setTitle(tr("Dive planner points"));
ui.tableWidget->setModel(plannerModel); ui.tableWidget->setModel(plannerModel);
connect(ui.tableWidget, &TableView::itemClicked, plannerModel, &DivePlannerPointsModel::remove); connect(ui.tableWidget, &TableView::itemClicked, plannerModel, &DivePlannerPointsModel::remove);
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::GAS, new AirTypesDelegate(parent->gasModel.get(), this)); ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::GAS, new AirTypesDelegate(planned_dive, this));
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::DIVEMODE, new DiveTypesDelegate(parent->diveTypeModel.get(), this)); ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::DIVEMODE, new DiveTypesDelegate(this));
ui.cylinderTableWidget->setTitle(tr("Available gases")); ui.cylinderTableWidget->setTitle(tr("Available gases"));
ui.cylinderTableWidget->setBtnToolTip(tr("Add cylinder")); ui.cylinderTableWidget->setBtnToolTip(tr("Add cylinder"));
ui.cylinderTableWidget->setModel(cylinders); ui.cylinderTableWidget->setModel(cylinders);
@ -56,9 +56,6 @@ DivePlannerWidget::DivePlannerWidget(dive &planned_dive, PlannerWidgets *parent)
view->setItemDelegateForColumn(CylindersModel::USE, tankUseDelegate); view->setItemDelegateForColumn(CylindersModel::USE, tankUseDelegate);
connect(ui.cylinderTableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addCylinder_clicked); connect(ui.cylinderTableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addCylinder_clicked);
connect(ui.tableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addDefaultStop); connect(ui.tableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addDefaultStop);
connect(cylinders, &CylindersModel::dataChanged, parent, &PlannerWidgets::repopulateGasModel);
connect(cylinders, &CylindersModel::rowsInserted, parent, &PlannerWidgets::repopulateGasModel);
connect(cylinders, &CylindersModel::rowsRemoved, parent, &PlannerWidgets::repopulateGasModel);
connect(cylinders, &CylindersModel::dataChanged, plannerModel, &DivePlannerPointsModel::emitDataChanged); connect(cylinders, &CylindersModel::dataChanged, plannerModel, &DivePlannerPointsModel::emitDataChanged);
connect(cylinders, &CylindersModel::dataChanged, plannerModel, &DivePlannerPointsModel::cylinderModelEdited); connect(cylinders, &CylindersModel::dataChanged, plannerModel, &DivePlannerPointsModel::cylinderModelEdited);
connect(cylinders, &CylindersModel::rowsInserted, plannerModel, &DivePlannerPointsModel::cylinderModelEdited); connect(cylinders, &CylindersModel::rowsInserted, plannerModel, &DivePlannerPointsModel::cylinderModelEdited);
@ -542,8 +539,6 @@ void PlannerDetails::setPlanNotes(QString plan)
PlannerWidgets::PlannerWidgets() : PlannerWidgets::PlannerWidgets() :
planned_dive(alloc_dive()), planned_dive(alloc_dive()),
gasModel(std::make_unique<GasSelectionModel>()),
diveTypeModel(std::make_unique<DiveTypeSelectionModel>()),
plannerWidget(*planned_dive, this), plannerWidget(*planned_dive, this),
plannerSettingsWidget(this) plannerSettingsWidget(this)
{ {
@ -587,7 +582,6 @@ void PlannerWidgets::planDive()
{ {
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN); DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN);
repopulateGasModel();
plannerWidget.setReplanButton(false); plannerWidget.setReplanButton(false);
plannerWidget.setupStartTime(timestampToDateTime(planned_dive->when)); // This will reload the profile! plannerWidget.setupStartTime(timestampToDateTime(planned_dive->when)); // This will reload the profile!
} }
@ -612,11 +606,6 @@ void PlannerWidgets::replanDive(int currentDC)
DivePlannerPointsModel::instance()->cylindersModel()->updateDive(planned_dive.get(), currentDC); DivePlannerPointsModel::instance()->cylindersModel()->updateDive(planned_dive.get(), currentDC);
} }
void PlannerWidgets::repopulateGasModel()
{
gasModel->repopulate(planned_dive.get());
}
void PlannerWidgets::printDecoPlan() void PlannerWidgets::printDecoPlan()
{ {
#ifndef NO_PRINTING #ifndef NO_PRINTING

View file

@ -10,8 +10,6 @@
#include <QDateTime> #include <QDateTime>
class DivePlannerPointsModel; class DivePlannerPointsModel;
class GasSelectionModel;
class DiveTypeSelectionModel;
class PlannerWidgets; class PlannerWidgets;
struct dive; struct dive;
@ -92,10 +90,7 @@ public
slots: slots:
void printDecoPlan(); void printDecoPlan();
public: public:
void repopulateGasModel();
OwningDivePtr planned_dive; OwningDivePtr planned_dive;
std::unique_ptr<GasSelectionModel> gasModel;
std::unique_ptr<DiveTypeSelectionModel> diveTypeModel;
DivePlannerWidget plannerWidget; DivePlannerWidget plannerWidget;
PlannerSettingsWidget plannerSettingsWidget; PlannerSettingsWidget plannerSettingsWidget;
PlannerDetails plannerDetails; PlannerDetails plannerDetails;

View file

@ -84,9 +84,11 @@ const QSize &StarWidgetsDelegate::starSize() const
return minStarSize; return minStarSize;
} }
ComboBoxDelegate::ComboBoxDelegate(QAbstractItemModel *model, QObject *parent, bool allowEdit) : QStyledItemDelegate(parent), model(model) ComboBoxDelegate::ComboBoxDelegate(std::function<QAbstractItemModel *(QWidget *)> create_model_func,
QObject *parent, bool allowEdit) : QStyledItemDelegate(parent),
create_model_func(std::move(create_model_func)),
editable(allowEdit)
{ {
editable = allowEdit;
connect(this, &ComboBoxDelegate::closeEditor, this, &ComboBoxDelegate::editorClosed); connect(this, &ComboBoxDelegate::closeEditor, this, &ComboBoxDelegate::editorClosed);
} }
@ -105,7 +107,7 @@ void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index)
QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const
{ {
QComboBox *comboDelegate = new QComboBox(parent); QComboBox *comboDelegate = new QComboBox(parent);
comboDelegate->setModel(model); comboDelegate->setModel(create_model_func(comboDelegate));
comboDelegate->setEditable(true); comboDelegate->setEditable(true);
comboDelegate->completer()->setCaseSensitivity(Qt::CaseInsensitive); comboDelegate->completer()->setCaseSensitivity(Qt::CaseInsensitive);
comboDelegate->completer()->setCompletionMode(QCompleter::PopupCompletion); comboDelegate->completer()->setCompletionMode(QCompleter::PopupCompletion);
@ -207,34 +209,34 @@ void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionV
editor->setGeometry(defaultRect); editor->setGeometry(defaultRect);
} }
void TankInfoDelegate::setModelData(QWidget *, QAbstractItemModel *, const QModelIndex &) const void TankInfoDelegate::setModelData(QWidget *, QAbstractItemModel *model, const QModelIndex &index) const
{ {
QAbstractItemModel *mymodel = currCombo.model; QAbstractItemModel *mymodel = currCombo.model;
TankInfoModel *tanks = TankInfoModel::instance();
QString cylinderName = currCombo.activeText.trimmed(); QString cylinderName = currCombo.activeText.trimmed();
if (cylinderName.isEmpty()) { if (cylinderName.isEmpty()) {
mymodel->setData(IDX(CylindersModel::TYPE), cylinderName, CylindersModel::TEMP_ROLE); mymodel->setData(IDX(CylindersModel::TYPE), cylinderName, CylindersModel::TEMP_ROLE);
return; return;
} }
QModelIndexList matches = tanks->match(tanks->index(0, 0), Qt::DisplayRole, cylinderName, 1, Qt::MatchFixedString | Qt::MatchWrap); int tankSize = 0;
int row; int tankPressure = 0;
if (matches.isEmpty()) { tank_info *info = get_tank_info(&tank_info_table, qPrintable(cylinderName));
tanks->insertRows(tanks->rowCount(), 1); if (info) {
tanks->setData(tanks->index(tanks->rowCount() - 1, 0), currCombo.activeText); // OMG, the units here are a mess.
row = tanks->rowCount() - 1; tankSize = info->ml != 0 ? info->ml : lrint(cuft_to_l(info->cuft) * 1000.0);
} else { tankPressure = info->bar != 0 ? info->bar * 1000 : psi_to_mbar(info->psi);
row = matches.first().row();
cylinderName = matches.first().data().toString();
} }
int tankSize = tanks->data(tanks->index(row, TankInfoModel::ML)).toInt();
int tankPressure = tanks->data(tanks->index(row, TankInfoModel::BAR)).toInt();
mymodel->setData(IDX(CylindersModel::TYPE), cylinderName, CylindersModel::TEMP_ROLE); mymodel->setData(IDX(CylindersModel::TYPE), cylinderName, CylindersModel::TEMP_ROLE);
mymodel->setData(IDX(CylindersModel::WORKINGPRESS), tankPressure, CylindersModel::TEMP_ROLE); mymodel->setData(IDX(CylindersModel::WORKINGPRESS), tankPressure, CylindersModel::TEMP_ROLE);
mymodel->setData(IDX(CylindersModel::SIZE), tankSize, CylindersModel::TEMP_ROLE); mymodel->setData(IDX(CylindersModel::SIZE), tankSize, CylindersModel::TEMP_ROLE);
} }
TankInfoDelegate::TankInfoDelegate(QObject *parent) : ComboBoxDelegate(TankInfoModel::instance(), parent, true) static QAbstractItemModel *createTankInfoModel(QWidget *parent)
{
return new TankInfoModel(parent);
}
TankInfoDelegate::TankInfoDelegate(QObject *parent) : ComboBoxDelegate(&createTankInfoModel, parent, true)
{ {
} }
@ -340,20 +342,19 @@ void WSInfoDelegate::editorClosed(QWidget *, QAbstractItemDelegate::EndEditHint
void WSInfoDelegate::setModelData(QWidget *, QAbstractItemModel *, const QModelIndex &) const void WSInfoDelegate::setModelData(QWidget *, QAbstractItemModel *, const QModelIndex &) const
{ {
WeightModel *mymodel = qobject_cast<WeightModel *>(currCombo.model); WeightModel *mymodel = qobject_cast<WeightModel *>(currCombo.model);
WSInfoModel *wsim = WSInfoModel::instance();
QString weightName = currCombo.activeText; QString weightName = currCombo.activeText;
QModelIndexList matches = wsim->match(wsim->index(0, 0), Qt::DisplayRole, weightName, 1, Qt::MatchFixedString | Qt::MatchWrap); ws_info_t *info = get_weightsystem_description(qPrintable(weightName));
int grams = 0; int grams = info ? info->grams : 0;
if (!matches.isEmpty()) {
int row = matches.first().row();
weightName = matches.first().data().toString();
grams = wsim->data(wsim->index(row, WSInfoModel::GR)).toInt();
}
mymodel->setTempWS(currCombo.currRow, weightsystem_t{ { grams }, copy_qstring(weightName), false }); mymodel->setTempWS(currCombo.currRow, weightsystem_t{ { grams }, copy_qstring(weightName), false });
} }
WSInfoDelegate::WSInfoDelegate(QObject *parent) : ComboBoxDelegate(WSInfoModel::instance(), parent, true) static QAbstractItemModel *createWSInfoModel(QWidget *parent)
{
return new WSInfoModel(parent);
}
WSInfoDelegate::WSInfoDelegate(QObject *parent) : ComboBoxDelegate(&createWSInfoModel, parent, true)
{ {
} }
@ -369,7 +370,9 @@ void AirTypesDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
model->setData(index, QVariant(combo->currentIndex())); model->setData(index, QVariant(combo->currentIndex()));
} }
AirTypesDelegate::AirTypesDelegate(QAbstractItemModel *model, QObject *parent) : ComboBoxDelegate(model, parent, false) AirTypesDelegate::AirTypesDelegate(const dive &d, QObject *parent) :
ComboBoxDelegate([d] (QWidget *parent) { return new GasSelectionModel(d, parent); },
parent, false)
{ {
} }
@ -385,7 +388,12 @@ void DiveTypesDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
model->setData(index, QVariant(combo->currentIndex())); model->setData(index, QVariant(combo->currentIndex()));
} }
DiveTypesDelegate::DiveTypesDelegate(QAbstractItemModel *model, QObject *parent) : ComboBoxDelegate(model, parent, false) static QAbstractItemModel *createDiveTypeSelectionModel(QWidget *parent)
{
return new DiveTypeSelectionModel(parent);
}
DiveTypesDelegate::DiveTypesDelegate(QObject *parent) : ComboBoxDelegate(&createDiveTypeSelectionModel, parent, false)
{ {
} }

View file

@ -6,8 +6,10 @@
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include <QComboBox> #include <QComboBox>
#include <functional>
class QPainter; class QPainter;
struct dive;
struct divecomputer; struct divecomputer;
class DiveListDelegate : public QStyledItemDelegate { class DiveListDelegate : public QStyledItemDelegate {
@ -32,7 +34,8 @@ private:
class ComboBoxDelegate : public QStyledItemDelegate { class ComboBoxDelegate : public QStyledItemDelegate {
Q_OBJECT Q_OBJECT
public: public:
explicit ComboBoxDelegate(QAbstractItemModel *model, QObject *parent = 0, bool allowEdit = true); // First parameter: function that creates a model and makes it a child of the passed-in widget.
explicit ComboBoxDelegate(std::function<QAbstractItemModel *(QWidget *)> create_model_func, QObject *parent = 0, bool allowEdit = true);
private private
slots: slots:
void testActivationString(const QString &currString); void testActivationString(const QString &currString);
@ -43,13 +46,13 @@ protected
slots: slots:
virtual void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) = 0; virtual void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) = 0;
private: private:
std::function<QAbstractItemModel *(QWidget *)> create_model_func;
bool editable; bool editable;
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override; void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
bool eventFilter(QObject *object, QEvent *event) override; bool eventFilter(QObject *object, QEvent *event) override;
protected: protected:
QAbstractItemModel *model;
mutable struct CurrSelected { mutable struct CurrSelected {
QComboBox *comboEditor; QComboBox *comboEditor;
int currRow; int currRow;
@ -103,7 +106,7 @@ private:
class AirTypesDelegate : public ComboBoxDelegate { class AirTypesDelegate : public ComboBoxDelegate {
Q_OBJECT Q_OBJECT
public: public:
explicit AirTypesDelegate(QAbstractItemModel *model, QObject *parent = 0); explicit AirTypesDelegate(const dive &d, QObject *parent = 0);
private: private:
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) override; void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) override;
@ -112,7 +115,7 @@ private:
class DiveTypesDelegate : public ComboBoxDelegate { class DiveTypesDelegate : public ComboBoxDelegate {
Q_OBJECT Q_OBJECT
public: public:
explicit DiveTypesDelegate(QAbstractItemModel *model, QObject *parent = 0); explicit DiveTypesDelegate(QObject *parent = 0);
private: private:
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) override; void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) override;

View file

@ -42,11 +42,8 @@ void PreferencesEquipment::syncSettings()
equipment->set_default_cylinder(ui->default_cylinder->currentText()); equipment->set_default_cylinder(ui->default_cylinder->currentText());
// In case the user changed the tank info settings, // In case the user changed the tank info settings,
// reset the tank_info_table and inform the TankInfoModel of // reset the tank_info_table. It is somewhat questionable
// the changed table. It is somewhat questionable to do this here. // to do this here. Moreover, it is a bit crude, as this
// Moreover, it is a bit crude, as this will be called for *any* // will be called for *any* preferences change.
// preferences change. Perhaps, the model should listen to the
// precise changed signal of the preferences system?
reset_tank_info_table(&tank_info_table); reset_tank_info_table(&tank_info_table);
TankInfoModel::instance()->update();
} }

View file

@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include "cylindermodel.h" #include "cylindermodel.h"
#include "tankinfomodel.h"
#include "models.h" #include "models.h"
#include "commands/command.h" #include "commands/command.h"
#include "core/qthelper.h" #include "core/qthelper.h"
@ -381,23 +380,12 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in
cyl.type.description = newType.c_str(); cyl.type.description = newType.c_str();
type = Command::EditCylinderType::TYPE; type = Command::EditCylinderType::TYPE;
break; break;
case SIZE: { case SIZE:
TankInfoModel *tanks = TankInfoModel::instance(); cyl.type.size = string_to_volume(qPrintable(vString), cyl.type.workingpressure);
QModelIndexList matches = tanks->match(tanks->index(0, 0), Qt::DisplayRole, cyl.type.description);
cyl.type.size = string_to_volume(qPrintable(vString), cyl.type.workingpressure);
if (!matches.isEmpty())
tanks->setData(tanks->index(matches.first().row(), TankInfoModel::ML), cyl.type.size.mliter);
}
type = Command::EditCylinderType::TYPE; type = Command::EditCylinderType::TYPE;
break; break;
case WORKINGPRESS: { case WORKINGPRESS:
TankInfoModel *tanks = TankInfoModel::instance(); cyl.type.workingpressure = string_to_pressure(qPrintable(vString));
QModelIndexList matches = tanks->match(tanks->index(0, 0), Qt::DisplayRole, cyl.type.description);
cyl.type.workingpressure = string_to_pressure(qPrintable(vString));
if (!matches.isEmpty())
tanks->setData(tanks->index(matches.first().row(), TankInfoModel::BAR), cyl.type.workingpressure.mbar / 1000.0);
}
type = Command::EditCylinderType::TYPE; type = Command::EditCylinderType::TYPE;
break; break;
case START: case START:

View file

@ -18,9 +18,10 @@ Qt::ItemFlags GasSelectionModel::flags(const QModelIndex&) const
return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
} }
void GasSelectionModel::repopulate(const dive *d) GasSelectionModel::GasSelectionModel(const dive &d, QObject *parent)
: QStringListModel(parent)
{ {
setStringList(get_dive_gas_list(d)); setStringList(get_dive_gas_list(&d));
} }
QVariant GasSelectionModel::data(const QModelIndex &index, int role) const QVariant GasSelectionModel::data(const QModelIndex &index, int role) const
@ -37,7 +38,7 @@ Qt::ItemFlags DiveTypeSelectionModel::flags(const QModelIndex&) const
return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
} }
DiveTypeSelectionModel::DiveTypeSelectionModel() DiveTypeSelectionModel::DiveTypeSelectionModel(QObject *parent) : QStringListModel(parent)
{ {
QStringList modes; QStringList modes;
for (int i = 0; i < FREEDIVE; i++) for (int i = 0; i < FREEDIVE; i++)

View file

@ -24,15 +24,15 @@ struct dive;
class GasSelectionModel : public QStringListModel { class GasSelectionModel : public QStringListModel {
Q_OBJECT Q_OBJECT
public: public:
GasSelectionModel(const dive &d, QObject *parent);
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
void repopulate(const dive *d);
}; };
class DiveTypeSelectionModel : public QStringListModel { class DiveTypeSelectionModel : public QStringListModel {
Q_OBJECT Q_OBJECT
public: public:
DiveTypeSelectionModel(); DiveTypeSelectionModel(QObject *parent);
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
}; };

View file

@ -5,48 +5,9 @@
#include "core/gettextfromc.h" #include "core/gettextfromc.h"
#include "core/metrics.h" #include "core/metrics.h"
TankInfoModel *TankInfoModel::instance()
{
static TankInfoModel self;
return &self;
}
bool TankInfoModel::insertRows(int, int count, const QModelIndex &parent)
{
beginInsertRows(parent, rowCount(), rowCount() + count - 1);
for (int i = 0; i < count; ++i)
add_tank_info_metric(&tank_info_table, "", 0, 0);
endInsertRows();
return true;
}
bool TankInfoModel::setData(const QModelIndex &index, const QVariant &value, int)
{
//WARN Seems wrong, we need to check for role == Qt::EditRole
if (index.row() < 0 || index.row() >= tank_info_table.nr )
return false;
struct tank_info &info = tank_info_table.infos[index.row()];
switch (index.column()) {
case DESCRIPTION:
free((void *)info.name);
info.name = strdup(value.toByteArray().data());
break;
case ML:
info.ml = value.toInt();
break;
case BAR:
info.bar = value.toInt();
break;
}
emit dataChanged(index, index);
return true;
}
QVariant TankInfoModel::data(const QModelIndex &index, int role) const QVariant TankInfoModel::data(const QModelIndex &index, int role) const
{ {
if (!index.isValid() || index.row() < 0 || index.row() >= tank_info_table.nr) if (index.row() < 0 || index.row() >= tank_info_table.nr)
return QVariant(); return QVariant();
if (role == Qt::FontRole) if (role == Qt::FontRole)
return defaultModelFont(); return defaultModelFont();
@ -75,16 +36,7 @@ int TankInfoModel::rowCount(const QModelIndex&) const
return tank_info_table.nr; return tank_info_table.nr;
} }
TankInfoModel::TankInfoModel() TankInfoModel::TankInfoModel(QObject *parent) : CleanerTableModel(parent)
{ {
setHeaderDataStrings(QStringList() << tr("Description") << tr("ml") << tr("bar")); setHeaderDataStrings(QStringList() << tr("Description") << tr("ml") << tr("bar"));
connect(&diveListNotifier, &DiveListNotifier::dataReset, this, &TankInfoModel::update);
connect(&diveListNotifier, &DiveListNotifier::settingsChanged, this, &TankInfoModel::update);
update();
}
void TankInfoModel::update()
{
beginResetModel();
endResetModel();
} }

View file

@ -9,22 +9,15 @@
class TankInfoModel : public CleanerTableModel { class TankInfoModel : public CleanerTableModel {
Q_OBJECT Q_OBJECT
public: public:
static TankInfoModel *instance();
enum Column { enum Column {
DESCRIPTION, DESCRIPTION,
ML, ML,
BAR BAR
}; };
TankInfoModel(); TankInfoModel(QObject *parent);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
public
slots:
void update();
}; };
#endif #endif

View file

@ -78,8 +78,10 @@ QVariant WeightModel::data(const QModelIndex &index, int role) const
// Ownership of passed in weight system will be taken. Caller must not use it any longer. // Ownership of passed in weight system will be taken. Caller must not use it any longer.
void WeightModel::setTempWS(int row, weightsystem_t ws) void WeightModel::setTempWS(int row, weightsystem_t ws)
{ {
if (!d || row < 0 || row >= d->weightsystems.nr) // Sanity check: row must exist if (!d || row < 0 || row >= d->weightsystems.nr) { // Sanity check: row must exist
free_weightsystem(ws);
return; return;
}
clearTempWS(); // Shouldn't be necessary, just in case: Reset old temporary row. clearTempWS(); // Shouldn't be necessary, just in case: Reset old temporary row.

View file

@ -5,66 +5,27 @@
#include "core/metrics.h" #include "core/metrics.h"
#include "core/gettextfromc.h" #include "core/gettextfromc.h"
WSInfoModel *WSInfoModel::instance()
{
static WSInfoModel self;
return &self;
}
bool WSInfoModel::insertRows(int, int count, const QModelIndex &parent)
{
beginInsertRows(parent, rowCount(), rowCount());
rows += count;
endInsertRows();
return true;
}
bool WSInfoModel::setData(const QModelIndex &index, const QVariant &value, int)
{
//WARN: check for Qt::EditRole
struct ws_info_t *info = &ws_info[index.row()];
switch (index.column()) {
case DESCRIPTION:
info->name = strdup(value.toByteArray().data());
break;
case GR:
info->grams = value.toInt();
break;
}
emit dataChanged(index, index);
return true;
}
void WSInfoModel::clear()
{
}
QVariant WSInfoModel::data(const QModelIndex &index, int role) const QVariant WSInfoModel::data(const QModelIndex &index, int role) const
{ {
QVariant ret; if (!index.isValid() || index.row() >= rows)
if (!index.isValid()) { return QVariant();
return ret;
}
struct ws_info_t *info = &ws_info[index.row()]; struct ws_info_t *info = &ws_info[index.row()];
int gr = info->grams; int gr = info->grams;
switch (role) { switch (role) {
case Qt::FontRole: case Qt::FontRole:
ret = defaultModelFont(); return defaultModelFont();
break;
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::EditRole: case Qt::EditRole:
switch (index.column()) { switch (index.column()) {
case GR: case GR:
ret = gr; return gr;
break;
case DESCRIPTION: case DESCRIPTION:
ret = gettextFromC::tr(info->name); return gettextFromC::tr(info->name);
break;
} }
break; break;
} }
return ret; return QVariant();
} }
int WSInfoModel::rowCount(const QModelIndex&) const int WSInfoModel::rowCount(const QModelIndex&) const
@ -72,18 +33,10 @@ int WSInfoModel::rowCount(const QModelIndex&) const
return rows; return rows;
} }
WSInfoModel::WSInfoModel() WSInfoModel::WSInfoModel(QObject *parent) : CleanerTableModel(parent)
{ {
setHeaderDataStrings(QStringList() << tr("Description") << tr("kg")); setHeaderDataStrings(QStringList() << tr("Description") << tr("kg"));
connect(&diveListNotifier, &DiveListNotifier::dataReset, this, &WSInfoModel::update);
update();
}
void WSInfoModel::update()
{
beginResetModel();
rows = 0; rows = 0;
for (struct ws_info_t *info = ws_info; info->name && info < ws_info + MAX_WS_INFO; info++, rows++) for (struct ws_info_t *info = ws_info; info->name && info < ws_info + MAX_WS_INFO; info++, rows++)
; ;
endResetModel();
} }

View file

@ -8,24 +8,17 @@
class WSInfoModel : public CleanerTableModel { class WSInfoModel : public CleanerTableModel {
Q_OBJECT Q_OBJECT
public: public:
static WSInfoModel *instance();
enum Column { enum Column {
DESCRIPTION, DESCRIPTION,
GR GR
}; };
WSInfoModel(); WSInfoModel(QObject *parent);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
void clear();
void update();
private: private:
int rows; int rows;
QString biggerEntry;
}; };
#endif #endif