1 /*
2    Drawpile - a collaborative drawing program.
3 
4    Copyright (C) 2013-2019 Calle Laakkonen
5 
6    Drawpile is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, either version 3 of the License, or
9    (at your option) any later version.
10 
11    Drawpile is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with Drawpile.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 #ifndef DP_SESSION_LOADER_H
20 #define DP_SESSION_LOADER_H
21 
22 #include <QSize>
23 #include <QColor>
24 #include <QString>
25 #include <QImage>
26 
27 #include "../libshared/net/message.h"
28 
29 namespace paintcore {
30 	class LayerStack;
31 }
32 
33 namespace canvas {
34 
35 class AclFilter;
36 
37 /**
38  * \brief Base class for session initializers.
39  *
40  * Note. The initializers make two assumptions: they are running in
41  * loopback mode and that the session has not already been initialized.
42  *
43  * These assumptions allow the initializers to pick the initial layer/annotation
44  * IDs.
45  */
46 class SessionLoader {
47 public:
48 	virtual ~SessionLoader();
49 
50 	/**
51 	 * @brief Get the commands needed to initialize the session.
52 	 *
53 	 * The commands should be sent to the server in response to a snapshot request,
54 	 * or when initializing the session in local mode.
55 	 *
56 	 * @param client
57 	 * @return empty list if an error occurred
58 	 */
59 	virtual protocol::MessageList loadInitCommands() = 0;
60 
61 	/**
62 	 * @brief Get the error message
63 	 *
64 	 * The error message is available if loadInitCommands() returns false.
65 	 * @return error message
66 	 */
67 	virtual QString errorMessage() const = 0;
68 
69 	/**
70 	 * @brief Get the warning message (if any)
71 	 */
warningMessage()72 	virtual QString warningMessage() const { return QString(); }
73 
74 	/**
75 	 * @brief get the name of the file
76 	 *
77 	 * This if for image loaders. If there is no file (that can be saved again),
78 	 * this function should return an empty string.
79 	 * @return filename or empty string
80 	 */
81 	virtual QString filename() const = 0;
82 
83 	/**
84 	 * @brief Get the canvas resolution
85 	 *
86 	 * Note. This should be called after calling loadInitCommands, to ensure the
87 	 * value has been loaded.
88 	 *
89 	 * This is not currently used internally, except for passing through opening
90 	 * and saving files that record this information. If we do start using it at some
91 	 * point, this function should be removed and a SetDPI command added to the protocol.
92 	 *
93 	 * @return
94 	 */
dotsPerInch()95 	virtual QPair<int,int> dotsPerInch() const { return QPair<int,int>(0, 0); }
96 };
97 
98 class BlankCanvasLoader : public SessionLoader {
99 public:
BlankCanvasLoader(const QSize & size,const QColor & color)100 	BlankCanvasLoader(const QSize &size, const QColor &color) : _size(size), _color(color)
101 	{}
102 
103 	protocol::MessageList loadInitCommands();
filename()104 	QString filename() const { return QString(); }
errorMessage()105 	QString errorMessage() const { return QString(); /* cannot fail */ }
106 
107 private:
108 	QSize _size;
109 	QColor _color;
110 };
111 
112 class ImageCanvasLoader : public SessionLoader {
113 public:
ImageCanvasLoader(const QString & filename)114 	ImageCanvasLoader(const QString &filename) : m_filename(filename) {}
115 
116 	protocol::MessageList loadInitCommands() override;
filename()117 	QString filename() const override { return m_filename; }
errorMessage()118 	QString errorMessage() const override { return m_error; }
warningMessage()119 	QString warningMessage() const override { return m_warning; }
dotsPerInch()120 	QPair<int,int> dotsPerInch() const override { return m_dpi; }
121 
122 	QPixmap loadThumbnail(const QSize &maxSize) const;
123 
124 private:
125 	QString m_filename;
126 	QString m_error;
127 	QString m_warning;
128 	QPair<int,int> m_dpi;
129 };
130 
131 class QImageCanvasLoader : public SessionLoader {
132 public:
QImageCanvasLoader(const QImage & image)133 	QImageCanvasLoader(const QImage &image) : m_image(image) {}
134 
135 	protocol::MessageList loadInitCommands() override;
filename()136 	QString filename() const override { return QString(); }
errorMessage()137 	QString errorMessage() const override { return QString(); }
dotsPerInch()138 	QPair<int,int> dotsPerInch() const override {
139 		return QPair<int,int>(
140 			int(m_image.dotsPerMeterX() * 0.0254),
141 			int(m_image.dotsPerMeterY() * 0.0254)
142 		);
143 	}
144 
145 private:
146 	QImage m_image;
147 };
148 
149 /**
150  * @brief A session loader that takes an existing layer stack and generates a new snapshot from it
151  *
152  * If the optional canvas is given, extra data will be included.
153  */
154 class SnapshotLoader : public SessionLoader {
155 public:
156 	//SnapshotLoader() : m_layers(nullptr), m_aclfilter(nullptr), m_defaultLayer(0), m_contextId(0) { }
157 
158 	/**
159 	 * Construct a snapshot from an existing session.
160 	 *
161 	 * @param context ID resetting user ID
162 	 * @param layers the layer stack (required)
163 	 * @param aclfilter Access controls (optional)
164 	 */
SnapshotLoader(uint8_t contextId,const paintcore::LayerStack * layers,const AclFilter * aclfilter)165 	SnapshotLoader(uint8_t contextId, const paintcore::LayerStack *layers, const AclFilter *aclfilter)
166 		: m_layers(layers), m_aclfilter(aclfilter), m_defaultLayer(0), m_contextId(contextId) {}
167 
168 	//! Include a default layer message
setDefaultLayer(int defaultLayer)169 	void setDefaultLayer(int defaultLayer) { m_defaultLayer = defaultLayer; }
170 
171 	//! Include a pinned chat message
setPinnedMessage(const QString & message)172 	void setPinnedMessage(const QString &message) { m_pinnedMessage = message; }
173 
174 	protocol::MessageList loadInitCommands() override;
filename()175 	QString filename() const override { return QString(); }
errorMessage()176 	QString errorMessage() const override { return QString(); }
177 	QPair<int,int> dotsPerInch() const override;
178 
179 private:
180 	const paintcore::LayerStack *m_layers;
181 	const AclFilter *m_aclfilter;
182 
183 	QString m_pinnedMessage;
184 	int m_defaultLayer;
185 
186 	uint8_t m_contextId;
187 
188 };
189 
190 }
191 
192 #endif
193