summaryrefslogtreecommitdiffstats
path: root/desktop-widgets/command_edit.h
blob: 4eb1da848525f813878a5a0de606b7d0bbb04b2e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// SPDX-License-Identifier: GPL-2.0
// Note: this header file is used by the undo-machinery and should not be included elsewhere.

#ifndef COMMAND_EDIT_H
#define COMMAND_EDIT_H

#include "command_base.h"
#include "core/subsurface-qt/DiveListNotifier.h"

#include <QVector>

// These are commands that edit individual fields of a set of dives.
// The implementation is very OO-style. Out-of-fashion and certainly
// not elegant, but in line with Qt's OO-based design.
// The actual code is in a common base class "Command::EditBase". To
// read and set the fields, the base class calls virtual functions of
// the derived classes.
//
// To deal with different data types, the base class is implemented
// as a template. The template parameter is the type to be read or
// set. Thus, switch-cascades and union trickery can be avoided.

// We put everything in a namespace, so that we can shorten names without polluting the global namespace
namespace Command {

template <typename T>
class EditBase : public Base {
protected:
	T value; // Value to be set
	T old; // Previous value

	void undo() override;
	void redo() override;
	bool workToBeDone() override;

	// Dives to be edited. For historical reasons, the *last* entry was
	// the active dive when the user initialized the action. This dive
	// will be made the current dive on redo / undo.
	std::vector<dive *> dives;
public:
	EditBase(const QVector<dive *> &dives, T newValue, T oldValue);

protected:
	// Get and set functions to be overriden by sub-classes.
	virtual void set(struct dive *d, T) const = 0;
	virtual T data(struct dive *d) const = 0;
	virtual QString fieldName() const = 0;	// Name of the field, used to create the undo menu-entry
	virtual DiveField fieldId() const = 0;
};

class EditNotes : public EditBase<QString> {
public:
	using EditBase<QString>::EditBase;	// Use constructor of base class.
	void set(struct dive *d, QString s) const override;
	QString data(struct dive *d) const override;
	QString fieldName() const override;
	DiveField fieldId() const override;
};

class EditSuit : public EditBase<QString> {
public:
	using EditBase<QString>::EditBase;	// Use constructor of base class.
	void set(struct dive *d, QString s) const override;
	QString data(struct dive *d) const override;
	QString fieldName() const override;
	DiveField fieldId() const override;
};

class EditRating : public EditBase<int> {
public:
	using EditBase<int>::EditBase;	// Use constructor of base class.
	void set(struct dive *d, int value) const override;
	int data(struct dive *d) const override;
	QString fieldName() const override;
	DiveField fieldId() const override;
};

class EditVisibility : public EditBase<int> {
public:
	using EditBase<int>::EditBase;	// Use constructor of base class.
	void set(struct dive *d, int value) const override;
	int data(struct dive *d) const override;
	QString fieldName() const override;
	DiveField fieldId() const override;
};

class EditAirTemp : public EditBase<int> {
public:
	using EditBase<int>::EditBase;	// Use constructor of base class.
	void set(struct dive *d, int value) const override;
	int data(struct dive *d) const override;
	QString fieldName() const override;
	DiveField fieldId() const override;
};

class EditWaterTemp : public EditBase<int> {
public:
	using EditBase<int>::EditBase;	// Use constructor of base class.
	void set(struct dive *d, int value) const override;
	int data(struct dive *d) const override;
	QString fieldName() const override;
	DiveField fieldId() const override;
};

class EditDiveSite : public EditBase<struct dive_site *> {
public:
	using EditBase<struct dive_site *>::EditBase;	// Use constructor of base class.
	void set(struct dive *d, struct dive_site *value) const override;
	struct dive_site *data(struct dive *d) const override;
	QString fieldName() const override;
	DiveField fieldId() const override;

	// We specialize these so that we can send dive-site changed signals.
	void undo() override;
	void redo() override;
};

// Edit dive site, but add a new dive site first. Reuses the code of EditDiveSite by
// deriving from it and hooks into undo() and redo() to add / remove the dive site.
class EditDiveSiteNew : public EditDiveSite {
public:
	OwningDiveSitePtr diveSiteToAdd;
	struct dive_site *diveSiteToRemove;
	EditDiveSiteNew(const QVector<dive *> &dives, const QString &newName, struct dive_site *oldValue);
	void undo() override;
	void redo() override;
};

class EditMode : public EditBase<int> {
	int index;
public:
	EditMode(const QVector<dive *> &dives, int indexIn, int newValue, int oldValue);
	void set(struct dive *d, int i) const override;
	int data(struct dive *d) const override;
	QString fieldName() const override;
	DiveField fieldId() const override;
};

} // namespace Command

#endif