UI restructure: use a global variable to hold the dive we show / edit

There is massive confusion about what we display when and where and which
dive structure (or pointer to a dive structure) contains which information
at which stage. This is the first step towards restructuring all of this.

This creates a global variable displayed_dive which at any point in time
should be what is displayed on screen (both in the profile and in the
maintab). It removes the editedDive concept from MainTab.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2014-07-02 11:50:28 -07:00
parent d568f96d05
commit a221a6e9f5
4 changed files with 86 additions and 81 deletions

5
dive.c
View file

@ -8,6 +8,11 @@
#include "dive.h" #include "dive.h"
#include "libdivecomputer.h" #include "libdivecomputer.h"
/* one could argue about the best place to have this variable -
* it's used in the UI, but it seems to make the most sense to have it
* here */
struct dive displayed_dive;
struct tag_entry *g_tag_list = NULL; struct tag_entry *g_tag_list = NULL;
static const char *default_tags[] = { static const char *default_tags[] = {

2
dive.h
View file

@ -414,7 +414,7 @@ struct dive_table {
}; };
extern struct dive_table dive_table; extern struct dive_table dive_table;
extern struct dive displayed_dive;
extern int selected_dive; extern int selected_dive;
extern unsigned int dc_number; extern unsigned int dc_number;
#define current_dive (get_dive(selected_dive)) #define current_dive (get_dive(selected_dive))

View file

@ -37,7 +37,7 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
{ {
ui.setupUi(this); ui.setupUi(this);
memset(&editedDive, 0, sizeof(editedDive)); memset(&displayed_dive, 0, sizeof(displayed_dive));
ui.cylinders->setModel(cylindersModel); ui.cylinders->setModel(cylindersModel);
ui.weights->setModel(weightModel); ui.weights->setModel(weightModel);
@ -265,8 +265,8 @@ void MainTab::enableEdition(EditMode newEditMode)
if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) { if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) {
// we are editing trip location and notes // we are editing trip location and notes
displayMessage(tr("This trip is being edited.")); displayMessage(tr("This trip is being edited."));
editedDive.location = current_dive->divetrip->location; displayed_dive.location = current_dive->divetrip->location;
editedDive.notes = current_dive->divetrip->notes; displayed_dive.notes = current_dive->divetrip->notes;
ui.dateEdit->setEnabled(false); ui.dateEdit->setEnabled(false);
editMode = TRIP; editMode = TRIP;
} else { } else {
@ -453,12 +453,13 @@ void MainTab::updateDiveInfo(int dive)
ui.LocationLabel->setText(tr("Location")); ui.LocationLabel->setText(tr("Location"));
ui.NotesLabel->setText(tr("Notes")); ui.NotesLabel->setText(tr("Notes"));
ui.equipmentTab->setEnabled(true); ui.equipmentTab->setEnabled(true);
// now copy the current dive over to editedDive and use THAT to show the // now copy the current dive over to dieplayed_dive and use THAT to show the
// cylinder and weight model (this way edits on the equipment tab happen in the // cylinder and weight model (this way edits on the equipment tab happen in the
// editedDive and not on the real data (until the user hits save) // displayed_dive and not on the real data (until the user hits save)
editedDive = *d; // all this will of course be redone in the next commit... one step at a time :-)
cylindersModel->setDive(&editedDive); displayed_dive = *d;
weightModel->setDive(&editedDive); cylindersModel->setDive(&displayed_dive);
weightModel->setDive(&displayed_dive);
taglist_get_tagstring(d->tag_list, buf, 1024); taglist_get_tagstring(d->tag_list, buf, 1024);
ui.tagWidget->setText(QString(buf)); ui.tagWidget->setText(QString(buf));
} }
@ -594,7 +595,7 @@ void MainTab::reload()
// loop over all dives, for each selected dive do WHAT, but do it // loop over all dives, for each selected dive do WHAT, but do it
// last for the current dive; this is required in case the invocation // last for the current dive; this is required in case the invocation
// wants to compare things to the original value in current_dive like it should // wants to compare things to the original value in current_dive like it should
#define EDIT_SELECTED_DIVES(WHAT) \ #define MODIFY_SELECTED_DIVES(WHAT) \
do { \ do { \
struct dive *mydive = NULL; \ struct dive *mydive = NULL; \
int _i; \ int _i; \
@ -612,12 +613,12 @@ void MainTab::reload()
#define EDIT_TEXT(what) \ #define EDIT_TEXT(what) \
if (same_string(mydive->what, cd->what)) { \ if (same_string(mydive->what, cd->what)) { \
free(mydive->what); \ free(mydive->what); \
mydive->what = strdup(editedDive.what); \ mydive->what = strdup(displayed_dive.what); \
} }
#define EDIT_VALUE(what) \ #define EDIT_VALUE(what) \
if (mydive->what == cd->what) { \ if (mydive->what == cd->what) { \
mydive->what = editedDive.what; \ mydive->what = displayed_dive.what; \
} }
void MainTab::acceptChanges() void MainTab::acceptChanges()
@ -630,43 +631,43 @@ void MainTab::acceptChanges()
ui.equipmentTab->setEnabled(true); ui.equipmentTab->setEnabled(true);
/* now figure out if things have changed */ /* now figure out if things have changed */
if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) { if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) {
if (!same_string(editedDive.notes, current_dive->divetrip->notes)) { if (!same_string(displayed_dive.notes, current_dive->divetrip->notes)) {
current_dive->divetrip->notes = strdup(editedDive.notes); current_dive->divetrip->notes = strdup(displayed_dive.notes);
mark_divelist_changed(true); mark_divelist_changed(true);
} }
if (!same_string(editedDive.location, current_dive->divetrip->location)) { if (!same_string(displayed_dive.location, current_dive->divetrip->location)) {
current_dive->divetrip->location = strdup(editedDive.location); current_dive->divetrip->location = strdup(displayed_dive.location);
mark_divelist_changed(true); mark_divelist_changed(true);
} }
ui.dateEdit->setEnabled(true); ui.dateEdit->setEnabled(true);
} else { } else {
struct dive *cd = current_dive; struct dive *cd = current_dive;
//Reset coordinates field, in case it contains garbage. //Reset coordinates field, in case it contains garbage.
updateGpsCoordinates(&editedDive); updateGpsCoordinates(&displayed_dive);
// now check if something has changed and if yes, edit the selected dives that // now check if something has changed and if yes, edit the selected dives that
// were identical with the master dive shown (and mark the divelist as changed) // were identical with the master dive shown (and mark the divelist as changed)
if (!same_string(editedDive.buddy, cd->buddy)) if (!same_string(displayed_dive.buddy, cd->buddy))
EDIT_SELECTED_DIVES(EDIT_TEXT(buddy)); MODIFY_SELECTED_DIVES(EDIT_TEXT(buddy));
if (!same_string(editedDive.suit, cd->suit)) if (!same_string(displayed_dive.suit, cd->suit))
EDIT_SELECTED_DIVES(EDIT_TEXT(suit)); MODIFY_SELECTED_DIVES(EDIT_TEXT(suit));
if (!same_string(editedDive.notes, cd->notes)) if (!same_string(displayed_dive.notes, cd->notes))
EDIT_SELECTED_DIVES(EDIT_TEXT(notes)); MODIFY_SELECTED_DIVES(EDIT_TEXT(notes));
if (!same_string(editedDive.divemaster, cd->divemaster)) if (!same_string(displayed_dive.divemaster, cd->divemaster))
EDIT_SELECTED_DIVES(EDIT_TEXT(divemaster)); MODIFY_SELECTED_DIVES(EDIT_TEXT(divemaster));
if (editedDive.rating != cd->rating) if (displayed_dive.rating != cd->rating)
EDIT_SELECTED_DIVES(EDIT_VALUE(rating)); MODIFY_SELECTED_DIVES(EDIT_VALUE(rating));
if (editedDive.visibility != cd->visibility) if (displayed_dive.visibility != cd->visibility)
EDIT_SELECTED_DIVES(EDIT_VALUE(visibility)); MODIFY_SELECTED_DIVES(EDIT_VALUE(visibility));
if (editedDive.airtemp.mkelvin != cd->airtemp.mkelvin) if (displayed_dive.airtemp.mkelvin != cd->airtemp.mkelvin)
EDIT_SELECTED_DIVES(EDIT_VALUE(airtemp.mkelvin)); MODIFY_SELECTED_DIVES(EDIT_VALUE(airtemp.mkelvin));
if (editedDive.watertemp.mkelvin != cd->watertemp.mkelvin) if (displayed_dive.watertemp.mkelvin != cd->watertemp.mkelvin)
EDIT_SELECTED_DIVES(EDIT_VALUE(watertemp.mkelvin)); MODIFY_SELECTED_DIVES(EDIT_VALUE(watertemp.mkelvin));
if (editedDive.when != cd->when) { if (displayed_dive.when != cd->when) {
time_t offset = current_dive->when - editedDive.when; time_t offset = current_dive->when - displayed_dive.when;
EDIT_SELECTED_DIVES(mydive->when -= offset;); MODIFY_SELECTED_DIVES(mydive->when -= offset;);
} }
if (!same_string(editedDive.location, cd->location)) { if (!same_string(displayed_dive.location, cd->location)) {
EDIT_SELECTED_DIVES(EDIT_TEXT(location)); MODIFY_SELECTED_DIVES(EDIT_TEXT(location));
// if we have a location text and haven't edited the coordinates, try to fill the coordinates // if we have a location text and haven't edited the coordinates, try to fill the coordinates
// from the existing dives // from the existing dives
if (!same_string(cd->location, "") && if (!same_string(cd->location, "") &&
@ -678,7 +679,7 @@ void MainTab::acceptChanges()
QString location(dive->location); QString location(dive->location);
if (location == ui.location->text() && if (location == ui.location->text() &&
(dive->latitude.udeg || dive->longitude.udeg)) { (dive->latitude.udeg || dive->longitude.udeg)) {
EDIT_SELECTED_DIVES(if (same_string(mydive->location, dive->location)) { MODIFY_SELECTED_DIVES(if (same_string(mydive->location, dive->location)) {
mydive->latitude = dive->latitude; mydive->latitude = dive->latitude;
mydive->longitude = dive->longitude; mydive->longitude = dive->longitude;
}); });
@ -688,24 +689,24 @@ void MainTab::acceptChanges()
} }
} }
} }
if (editedDive.latitude.udeg != current_dive->latitude.udeg || if (displayed_dive.latitude.udeg != current_dive->latitude.udeg ||
editedDive.longitude.udeg != current_dive->longitude.udeg) { displayed_dive.longitude.udeg != current_dive->longitude.udeg) {
EDIT_SELECTED_DIVES(gpsHasChanged(mydive, cd, ui.coordinates->text(), 0)); MODIFY_SELECTED_DIVES(gpsHasChanged(mydive, cd, ui.coordinates->text(), 0));
} }
if (tagsChanged(&editedDive, cd)) if (tagsChanged(&displayed_dive, cd))
saveTags(); saveTags();
if (editMode == MANUALLY_ADDED_DIVE) { if (editMode == MANUALLY_ADDED_DIVE) {
DivePlannerPointsModel::instance()->copyCylinders(cd); DivePlannerPointsModel::instance()->copyCylinders(cd);
} else if (editMode != ADD && cylindersModel->changed) { } else if (editMode != ADD && cylindersModel->changed) {
mark_divelist_changed(true); mark_divelist_changed(true);
EDIT_SELECTED_DIVES( MODIFY_SELECTED_DIVES(
for (int i = 0; i < MAX_CYLINDERS; i++) { for (int i = 0; i < MAX_CYLINDERS; i++) {
if (mydive != cd) { if (mydive != cd) {
if (same_string(mydive->cylinder[i].type.description, cd->cylinder[i].type.description)) if (same_string(mydive->cylinder[i].type.description, cd->cylinder[i].type.description))
// only copy the cylinder type, none of the other values // only copy the cylinder type, none of the other values
mydive->cylinder[i].type = editedDive.cylinder[i].type; mydive->cylinder[i].type = displayed_dive.cylinder[i].type;
} else { } else {
mydive->cylinder[i] = editedDive.cylinder[i]; mydive->cylinder[i] = displayed_dive.cylinder[i];
} }
} }
); );
@ -714,10 +715,10 @@ void MainTab::acceptChanges()
if (weightModel->changed) { if (weightModel->changed) {
mark_divelist_changed(true); mark_divelist_changed(true);
EDIT_SELECTED_DIVES( MODIFY_SELECTED_DIVES(
for (int i = 0; i < MAX_WEIGHTSYSTEMS; i++) { for (int i = 0; i < MAX_WEIGHTSYSTEMS; i++) {
if (same_string(mydive->weightsystem[i].description, cd->weightsystem[i].description)) if (same_string(mydive->weightsystem[i].description, cd->weightsystem[i].description))
mydive->weightsystem[i] = editedDive.weightsystem[i]; mydive->weightsystem[i] = displayed_dive.weightsystem[i];
} }
); );
} }
@ -817,13 +818,13 @@ void MainTab::resetPallete()
what = strdup(textByteArray.data()); what = strdup(textByteArray.data());
#define FREE_IF_DIFFERENT(what) \ #define FREE_IF_DIFFERENT(what) \
if (editedDive.what != cd->what) \ if (displayed_dive.what != cd->what) \
free(editedDive.what) free(displayed_dive.what)
void MainTab::rejectChanges() void MainTab::rejectChanges()
{ {
EditMode lastMode = editMode; EditMode lastMode = editMode;
if (lastMode != NONE && current_dive && memcmp(&editedDive, current_dive, sizeof(struct dive))) { if (lastMode != NONE && current_dive && memcmp(&displayed_dive, current_dive, sizeof(struct dive))) {
if (QMessageBox::warning(MainWindow::instance(), TITLE_OR_TEXT(tr("Discard the Changes?"), if (QMessageBox::warning(MainWindow::instance(), TITLE_OR_TEXT(tr("Discard the Changes?"),
tr("You are about to discard your changes.")), tr("You are about to discard your changes.")),
QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard) != QMessageBox::Discard) { QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard) != QMessageBox::Discard) {
@ -847,9 +848,9 @@ void MainTab::rejectChanges()
DivePlannerPointsModel::instance()->restoreBackupDive(); DivePlannerPointsModel::instance()->restoreBackupDive();
} }
if (selected_dive >= 0) { if (selected_dive >= 0) {
editedDive = *get_dive(selected_dive); displayed_dive = *get_dive(selected_dive);
cylindersModel->setDive(&editedDive); cylindersModel->setDive(&displayed_dive);
weightModel->setDive(&editedDive); weightModel->setDive(&displayed_dive);
} else { } else {
cylindersModel->clear(); cylindersModel->clear();
weightModel->clear(); weightModel->clear();
@ -858,10 +859,10 @@ void MainTab::rejectChanges()
} }
// now let's avoid memory leaks // now let's avoid memory leaks
if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) { if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) {
if (editedDive.location != current_dive->divetrip->location) if (displayed_dive.location != current_dive->divetrip->location)
free(editedDive.location); free(displayed_dive.location);
if (editedDive.notes != current_dive->divetrip->notes) if (displayed_dive.notes != current_dive->divetrip->notes)
free(editedDive.notes); free(displayed_dive.notes);
} else { } else {
struct dive *cd = current_dive; struct dive *cd = current_dive;
FREE_IF_DIFFERENT(tag_list); FREE_IF_DIFFERENT(tag_list);
@ -909,7 +910,7 @@ void MainTab::on_buddy_textChanged()
for (int i = 0; i < text_list.size(); i++) for (int i = 0; i < text_list.size(); i++)
text_list[i] = text_list[i].trimmed(); text_list[i] = text_list[i].trimmed();
QString text = text_list.join(", "); QString text = text_list.join(", ");
editedDive.buddy = strdup(text.toUtf8().data()); displayed_dive.buddy = strdup(text.toUtf8().data());
markChangedWidget(ui.buddy); markChangedWidget(ui.buddy);
} }
@ -921,7 +922,7 @@ void MainTab::on_divemaster_textChanged()
for (int i = 0; i < text_list.size(); i++) for (int i = 0; i < text_list.size(); i++)
text_list[i] = text_list[i].trimmed(); text_list[i] = text_list[i].trimmed();
QString text = text_list.join(", "); QString text = text_list.join(", ");
editedDive.divemaster = strdup(text.toUtf8().data()); displayed_dive.divemaster = strdup(text.toUtf8().data());
markChangedWidget(ui.divemaster); markChangedWidget(ui.divemaster);
} }
@ -929,7 +930,7 @@ void MainTab::on_airtemp_textChanged(const QString &text)
{ {
if (editMode == NONE) if (editMode == NONE)
return; return;
editedDive.airtemp.mkelvin = parseTemperatureToMkelvin(text); displayed_dive.airtemp.mkelvin = parseTemperatureToMkelvin(text);
markChangedWidget(ui.airtemp); markChangedWidget(ui.airtemp);
validate_temp_field(ui.airtemp, text); validate_temp_field(ui.airtemp, text);
} }
@ -938,7 +939,7 @@ void MainTab::on_watertemp_textChanged(const QString &text)
{ {
if (editMode == NONE) if (editMode == NONE)
return; return;
editedDive.watertemp.mkelvin = parseTemperatureToMkelvin(text); displayed_dive.watertemp.mkelvin = parseTemperatureToMkelvin(text);
markChangedWidget(ui.watertemp); markChangedWidget(ui.watertemp);
validate_temp_field(ui.watertemp, text); validate_temp_field(ui.watertemp, text);
} }
@ -975,10 +976,10 @@ void MainTab::on_dateEdit_dateChanged(const QDate &date)
{ {
if (editMode == NONE) if (editMode == NONE)
return; return;
QDateTime dateTime = QDateTime::fromTime_t(editedDive.when); QDateTime dateTime = QDateTime::fromTime_t(displayed_dive.when);
dateTime.setTimeSpec(Qt::UTC); dateTime.setTimeSpec(Qt::UTC);
dateTime.setDate(date); dateTime.setDate(date);
editedDive.when = dateTime.toTime_t(); displayed_dive.when = dateTime.toTime_t();
markChangedWidget(ui.dateEdit); markChangedWidget(ui.dateEdit);
} }
@ -986,10 +987,10 @@ void MainTab::on_timeEdit_timeChanged(const QTime &time)
{ {
if (editMode == NONE) if (editMode == NONE)
return; return;
QDateTime dateTime = QDateTime::fromTime_t(editedDive.when); QDateTime dateTime = QDateTime::fromTime_t(displayed_dive.when);
dateTime.setTimeSpec(Qt::UTC); dateTime.setTimeSpec(Qt::UTC);
dateTime.setTime(time); dateTime.setTime(time);
editedDive.when = dateTime.toTime_t(); displayed_dive.when = dateTime.toTime_t();
markChangedWidget(ui.timeEdit); markChangedWidget(ui.timeEdit);
} }
@ -1015,7 +1016,7 @@ bool MainTab::tagsChanged(dive *a, dive *b)
void MainTab::saveTags() void MainTab::saveTags()
{ {
struct dive *cd = current_dive; struct dive *cd = current_dive;
EDIT_SELECTED_DIVES( MODIFY_SELECTED_DIVES(
QString tag; QString tag;
taglist_free(mydive->tag_list); taglist_free(mydive->tag_list);
mydive->tag_list = NULL; mydive->tag_list = NULL;
@ -1028,12 +1029,12 @@ void MainTab::on_tagWidget_textChanged()
if (editMode == NONE) if (editMode == NONE)
return; return;
QString tag; QString tag;
if (editedDive.tag_list != current_dive->tag_list) if (displayed_dive.tag_list != current_dive->tag_list)
taglist_free(editedDive.tag_list); taglist_free(displayed_dive.tag_list);
editedDive.tag_list = NULL; displayed_dive.tag_list = NULL;
Q_FOREACH (tag, ui.tagWidget->getBlockStringList()) Q_FOREACH (tag, ui.tagWidget->getBlockStringList())
taglist_add_tag(&editedDive.tag_list, tag.toUtf8().data()); taglist_add_tag(&displayed_dive.tag_list, tag.toUtf8().data());
if (tagsChanged(&editedDive, current_dive)) if (tagsChanged(&displayed_dive, current_dive))
markChangedWidget(ui.tagWidget); markChangedWidget(ui.tagWidget);
} }
@ -1041,7 +1042,7 @@ void MainTab::on_location_textChanged(const QString &text)
{ {
if (editMode == NONE) if (editMode == NONE)
return; return;
editedDive.location = strdup(ui.location->text().toUtf8().data()); displayed_dive.location = strdup(ui.location->text().toUtf8().data());
markChangedWidget(ui.location); markChangedWidget(ui.location);
} }
@ -1049,7 +1050,7 @@ void MainTab::on_suit_textChanged(const QString &text)
{ {
if (editMode == NONE) if (editMode == NONE)
return; return;
editedDive.suit = strdup(text.toUtf8().data()); displayed_dive.suit = strdup(text.toUtf8().data());
markChangedWidget(ui.suit); markChangedWidget(ui.suit);
} }
@ -1057,7 +1058,7 @@ void MainTab::on_notes_textChanged()
{ {
if (editMode == NONE) if (editMode == NONE)
return; return;
editedDive.notes = strdup(ui.notes->toPlainText().toUtf8().data()); displayed_dive.notes = strdup(ui.notes->toPlainText().toUtf8().data());
markChangedWidget(ui.notes); markChangedWidget(ui.notes);
} }
@ -1069,7 +1070,7 @@ void MainTab::on_coordinates_textChanged(const QString &text)
bool parsed = false; bool parsed = false;
QPalette p; QPalette p;
ui.coordinates->setPalette(p); // reset palette ui.coordinates->setPalette(p); // reset palette
gpsChanged = gpsHasChanged(&editedDive, current_dive, text, &parsed); gpsChanged = gpsHasChanged(&displayed_dive, current_dive, text, &parsed);
if (gpsChanged) if (gpsChanged)
markChangedWidget(ui.coordinates); // marks things yellow markChangedWidget(ui.coordinates); // marks things yellow
if (!parsed) { if (!parsed) {
@ -1080,15 +1081,15 @@ void MainTab::on_coordinates_textChanged(const QString &text)
void MainTab::on_rating_valueChanged(int value) void MainTab::on_rating_valueChanged(int value)
{ {
editedDive.rating = value; displayed_dive.rating = value;
} }
void MainTab::on_visibility_valueChanged(int value) void MainTab::on_visibility_valueChanged(int value)
{ {
editedDive.visibility = value; displayed_dive.visibility = value;
} }
#undef EDIT_SELECTED_DIVES #undef MODIFY_SELECTED_DIVESVES
#undef EDIT_TEXT #undef EDIT_TEXT
#undef EDIT_VALUE #undef EDIT_VALUE

View file

@ -98,7 +98,6 @@ private:
SuitCompletionModel suitModel; SuitCompletionModel suitModel;
TagCompletionModel tagModel; TagCompletionModel tagModel;
DivePictureModel *divePictureModel; DivePictureModel *divePictureModel;
struct dive editedDive; // when editing we do all changes on a copy of the real data and only apply when saved
Completers completers; Completers completers;
void resetPallete(); void resetPallete();
void saveTags(); void saveTags();