Undo: make dive site merging undoable

This one was rather trivial, as there is no actual merging
done. Quite simply, a number of dive sites are removed and
their dive added to a different dive site.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2019-03-15 17:41:31 +01:00 committed by Dirk Hohndel
parent 7c63956ee4
commit 59239cec02
7 changed files with 66 additions and 36 deletions

View file

@ -310,31 +310,6 @@ void merge_dive_site(struct dive_site *a, struct dive_site *b)
} }
} }
void merge_dive_sites(struct dive_site *ref, struct dive_site *dive_sites[], int count)
{
int curr_dive, i;
struct dive *d;
for(i = 0; i < count; i++){
if (dive_sites[i] == ref)
continue;
for_each_dive(curr_dive, d) {
if (d->dive_site != dive_sites[i] )
continue;
unregister_dive_from_dive_site(d);
add_dive_to_dive_site(d, ref);
invalidate_dive_cache(d);
}
}
for(i = 0; i < count; i++) {
if (dive_sites[i] == ref)
continue;
delete_dive_site(dive_sites[i], &dive_site_table);
}
mark_divelist_changed(true);
}
struct dive_site *find_or_create_dive_site_with_name(const char *name, struct dive_site_table *ds_table) struct dive_site *find_or_create_dive_site_with_name(const char *name, struct dive_site_table *ds_table)
{ {
int i; int i;

View file

@ -69,7 +69,6 @@ void copy_dive_site(struct dive_site *orig, struct dive_site *copy);
void merge_dive_site(struct dive_site *a, struct dive_site *b); void merge_dive_site(struct dive_site *a, struct dive_site *b);
unsigned int get_distance(const location_t *loc1, const location_t *loc2); unsigned int get_distance(const location_t *loc1, const location_t *loc2);
struct dive_site *find_or_create_dive_site_with_name(const char *name, struct dive_site_table *ds_table); struct dive_site *find_or_create_dive_site_with_name(const char *name, struct dive_site_table *ds_table);
void merge_dive_sites(struct dive_site *ref, struct dive_site *dive_sites[], int count);
void purge_empty_dive_sites(struct dive_site_table *ds_table); void purge_empty_dive_sites(struct dive_site_table *ds_table);
void clear_dive_site_table(struct dive_site_table *ds_table); void clear_dive_site_table(struct dive_site_table *ds_table);
void add_dive_to_dive_site(struct dive *d, struct dive_site *ds); void add_dive_to_dive_site(struct dive *d, struct dive_site *ds);

View file

@ -118,4 +118,9 @@ void addDiveSite(const QString &name)
execute(new AddDiveSite(name)); execute(new AddDiveSite(name));
} }
void mergeDiveSites(dive_site *ds, const QVector<dive_site *> &sites)
{
execute(new MergeDiveSites(ds, sites));
}
} // namespace Command } // namespace Command

View file

@ -48,6 +48,7 @@ void editDiveSiteCountry(dive_site *ds, const QString &value);
void editDiveSiteLocation(dive_site *ds, location_t value); void editDiveSiteLocation(dive_site *ds, location_t value);
void editDiveSiteTaxonomy(dive_site *ds, taxonomy_data &value); // value is consumed (i.e. will be erased after call)! void editDiveSiteTaxonomy(dive_site *ds, taxonomy_data &value); // value is consumed (i.e. will be erased after call)!
void addDiveSite(const QString &name); void addDiveSite(const QString &name);
void mergeDiveSites(dive_site *ds, const QVector<dive_site *> &sites);
} // namespace Command } // namespace Command

View file

@ -266,4 +266,45 @@ void EditDiveSiteTaxonomy::undo()
redo(); redo();
} }
MergeDiveSites::MergeDiveSites(dive_site *dsIn, const QVector<dive_site *> &sites) : ds(dsIn)
{
setText(tr("merge dive sites"));
sitesToRemove.reserve(sites.size());
for (dive_site *site: sites) {
if (site != ds)
sitesToRemove.push_back(site);
}
}
bool MergeDiveSites::workToBeDone()
{
return !sitesToRemove.empty();
}
void MergeDiveSites::redo()
{
// First, remove all dive sites
sitesToAdd = std::move(removeDiveSites(sitesToRemove));
// The dives of the above dive sites were reset to no dive sites.
// Add them to the merged-into dive site. Thankfully, we remember
// the dives in the sitesToAdd vector.
for (const OwningDiveSitePtr &site: sitesToAdd) {
for (int i = 0; i < site->dives.nr; ++i)
add_dive_to_dive_site(site->dives.dives[i], ds); // TODO: send dive changed signal
}
}
void MergeDiveSites::undo()
{
// Before readding the dive sites, unregister the corresponding dives so that they can be
// readded to their old dive sites.
for (const OwningDiveSitePtr &site: sitesToAdd) {
for (int i = 0; i < site->dives.nr; ++i)
unregister_dive_from_dive_site(site->dives.dives[i]);
}
sitesToRemove = std::move(addDiveSites(sitesToAdd));
}
} // namespace Command } // namespace Command

View file

@ -117,6 +117,23 @@ private:
taxonomy_data value; // Value to be set taxonomy_data value; // Value to be set
}; };
class MergeDiveSites : public Base {
public:
MergeDiveSites(dive_site *ds, const QVector<dive_site *> &sites);
private:
bool workToBeDone() override;
void undo() override;
void redo() override;
dive_site *ds;
// For redo
std::vector<dive_site *> sitesToRemove;
// For undo
std::vector<OwningDiveSitePtr> sitesToAdd;
};
} // namespace Command } // namespace Command
#endif // COMMAND_DIVESITE_H #endif // COMMAND_DIVESITE_H

View file

@ -62,24 +62,16 @@ void LocationInformationWidget::mergeSelectedDiveSites()
{ {
if (!diveSite) if (!diveSite)
return; return;
if (QMessageBox::warning(MainWindow::instance(), tr("Merging dive sites"),
tr("You are about to merge dive sites, you can't undo that action \n Are you sure you want to continue?"),
QMessageBox::Ok, QMessageBox::Cancel) != QMessageBox::Ok)
return;
const QModelIndexList selection = ui.diveSiteListView->selectionModel()->selectedIndexes(); const QModelIndexList selection = ui.diveSiteListView->selectionModel()->selectedIndexes();
// std::vector guarantees contiguous storage and can therefore be passed to C-code QVector<dive_site *> selected_dive_sites;
std::vector<struct dive_site *> selected_dive_sites;
selected_dive_sites.reserve(selection.count()); selected_dive_sites.reserve(selection.count());
for (const QModelIndex &idx: selection) { for (const QModelIndex &idx: selection) {
dive_site *ds = idx.data(LocationInformationModel::DIVESITE_ROLE).value<dive_site *>(); dive_site *ds = idx.data(LocationInformationModel::DIVESITE_ROLE).value<dive_site *>();
if (ds) if (ds)
selected_dive_sites.push_back(ds); selected_dive_sites.push_back(ds);
} }
merge_dive_sites(diveSite, selected_dive_sites.data(), (int)selected_dive_sites.size()); Command::mergeDiveSites(diveSite, selected_dive_sites);
LocationInformationModel::instance()->update();
QSortFilterProxyModel *m = (QSortFilterProxyModel *)ui.diveSiteListView->model();
m->invalidate();
} }
void LocationInformationWidget::updateLabels() void LocationInformationWidget::updateLabels()