summaryrefslogtreecommitdiffstats
path: root/desktop-widgets/command_edit.h
blob: d77c46a27e47b2e497b91fa8f8a90d4642350d34 (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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// 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;
};

// Fields that work with tag-lists (tags, buddies, divemasters) work differently and therefore
// have their own base class. In this case, it's not a template, as all these lists are base
// on strings.
class EditTagsBase : public Base {
	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;
	QStringList newList;	// Temporary until initialized
	struct dive *oldDive;	// Temporary until initialized
public:
	EditTagsBase(const QVector<dive *> &dives, const QStringList &newList, struct dive *d);

protected:
	QStringList tagsToAdd;
	QStringList tagsToRemove;
	void undo() override;
	void redo() override;

	// Getters, setters and parsers to be overriden by sub-classes.
	virtual QStringList data(struct dive *d) const = 0;
	virtual void set(struct dive *d, const QStringList &v) const = 0;
	virtual QString fieldName() const = 0;	// Name of the field, used to create the undo menu-entry
	virtual DiveField fieldId() const = 0;
};

class EditTags : public EditTagsBase {
public:
	using EditTagsBase::EditTagsBase;	// Use constructor of base class.
	QStringList data(struct dive *d) const override;
	void set(struct dive *d, const QStringList &v) const override;
	QString fieldName() const override;
	DiveField fieldId() const override;
};

class EditBuddies : public EditTagsBase {
public:
	using EditTagsBase::EditTagsBase;	// Use constructor of base class.
	QStringList data(struct dive *d) const override;
	void set(struct dive *d, const QStringList &v) const override;
	QString fieldName() const override;
	DiveField fieldId() const override;
};

} // namespace Command

#endif