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

@ -118,4 +118,9 @@ void addDiveSite(const QString &name)
execute(new AddDiveSite(name));
}
void mergeDiveSites(dive_site *ds, const QVector<dive_site *> &sites)
{
execute(new MergeDiveSites(ds, sites));
}
} // 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 editDiveSiteTaxonomy(dive_site *ds, taxonomy_data &value); // value is consumed (i.e. will be erased after call)!
void addDiveSite(const QString &name);
void mergeDiveSites(dive_site *ds, const QVector<dive_site *> &sites);
} // namespace Command

View file

@ -266,4 +266,45 @@ void EditDiveSiteTaxonomy::undo()
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

View file

@ -117,6 +117,23 @@ private:
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
#endif // COMMAND_DIVESITE_H

View file

@ -62,24 +62,16 @@ void LocationInformationWidget::mergeSelectedDiveSites()
{
if (!diveSite)
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();
// std::vector guarantees contiguous storage and can therefore be passed to C-code
std::vector<struct dive_site *> selected_dive_sites;
QVector<dive_site *> selected_dive_sites;
selected_dive_sites.reserve(selection.count());
for (const QModelIndex &idx: selection) {
dive_site *ds = idx.data(LocationInformationModel::DIVESITE_ROLE).value<dive_site *>();
if (ds)
selected_dive_sites.push_back(ds);
}
merge_dive_sites(diveSite, selected_dive_sites.data(), (int)selected_dive_sites.size());
LocationInformationModel::instance()->update();
QSortFilterProxyModel *m = (QSortFilterProxyModel *)ui.diveSiteListView->model();
m->invalidate();
Command::mergeDiveSites(diveSite, selected_dive_sites);
}
void LocationInformationWidget::updateLabels()