1 /*
2  *    Copyright 2012-2014 Thomas Schöps
3  *    Copyright 2013-2018 Kai Pastor
4  *
5  *    This file is part of OpenOrienteering.
6  *
7  *    OpenOrienteering is free software: you can redistribute it and/or modify
8  *    it under the terms of the GNU General Public License as published by
9  *    the Free Software Foundation, either version 3 of the License, or
10  *    (at your option) any later version.
11  *
12  *    OpenOrienteering is distributed in the hope that it will be useful,
13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *    GNU General Public License for more details.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with OpenOrienteering.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 
22 #ifndef OPENORIENTEERING_MAP_H
23 #define OPENORIENTEERING_MAP_H
24 
25 #include <algorithm>
26 #include <cstddef>
27 #include <functional>
28 #include <set>
29 #include <vector>
30 
31 #include <QtGlobal>
32 #include <QExplicitlySharedDataPointer>
33 #include <QFlags>
34 #include <QHash>
35 #include <QMetaType>
36 #include <QObject>
37 #include <QPointer>
38 #include <QRectF>
39 #include <QScopedPointer>
40 #include <QSharedData>
41 #include <QString>
42 #include <QTransform>
43 
44 #include "core/map_coord.h"
45 #include "core/map_grid.h"
46 #include "core/map_part.h"
47 
48 class QIODevice;
49 class QPainter;
50 class QTranslator;
51 class QWidget;
52 // IWYU pragma: no_forward_declare QRectF
53 
54 namespace OpenOrienteering {
55 
56 class CombinedSymbol;
57 class Georeferencing;
58 class LineSymbol;
59 class MapColor;
60 class MapColorMap;
61 class MapPrinterConfig;
62 class MapRenderables;
63 class MapView;
64 class MapWidget;
65 class Object;
66 class PointSymbol;
67 class RenderConfig;
68 class Symbol;
69 class Template;
70 class TextSymbol;
71 class UndoManager;
72 class UndoStep;
73 
74 
75 /**
76  * The translator for color and symbol texts.
77  *
78  * This translator is used by class Map but kept outside of the
79  * class' namespace in order to allow for forward declaration
80  * instead of including "map.h".
81  */
82 extern QPointer<QTranslator> map_symbol_translator;
83 
84 
85 
86 /** Central class for an OpenOrienteering map */
87 class Map : public QObject
88 {
89 Q_OBJECT
90 friend class MapTest;
91 friend class MapRenderables;
92 friend class OCAD8FileImport;
93 friend class XMLFileImporter;
94 friend class XMLFileExporter;
95 public:
96 	/** A set of selected objects represented by a std::set of object pointers. */
97 	typedef std::set<Object*> ObjectSelection;
98 
99 	/**
100 	 * Different strategies for importing elements from another map.
101 	 */
102 	enum ImportModeFlag
103 	{
104 		ObjectImport   = 0x00,       ///< Import objects, symbols and colors.
105 		SymbolImport   = 0x01,       ///< Import symbols and colors.
106 		ColorImport    = 0x02,       ///< Import colors.
107 		GeorefImport   = 0x10,       ///< Use the georeferencing for object import.
108 		MinimalImport  = 0x20,       ///< Imports with minimal symbol and color dependencies.
109 
110 		MinimalSymbolImport = SymbolImport | MinimalImport,
111 		MinimalObjectImport = ObjectImport | MinimalImport,
112 		CompleteImport      = ObjectImport | GeorefImport
113 	};
114 
115 	Q_DECLARE_FLAGS(ImportMode, ImportModeFlag)
116 
117 
118 	/** Options for zooming to visibility of selection. */
119 	enum SelectionVisibility
120 	{
121 		FullVisibility,
122 		PartialVisibility,
123 		IgnoreVisibilty
124 	};
125 
126 
127 	/** Creates a new, empty map. */
128 	Map();
129 
130 	/** Destroys the map. */
131 	~Map() override;
132 
133 
134 	/**
135 	 * Deletes all map data.
136 	 *
137 	 * The resulting map must not be modified before another init().
138 	 */
139 	void clear();
140 
141 	/**
142 	 * Initializes an empty map.
143 	 *
144 	 * A map is empty when it is newly constructed or after clear().
145 	 */
146 	void init();
147 
148 	/**
149 	 * Deletes all map data, and reinitializes the empty map.
150 	 *
151 	 * This method combines a call to clear() followed by init().
152 	 */
153 	void reset();
154 
155 
156 	/**
157 	 * Attempts to load the map from the specified path. Returns true on success.
158 	 *
159 	 * This is a convenience function used by tests. Normally, a importer should be
160 	 * used explicitly.
161 	 *
162 	 * @param path The file path to load the map from.
163 	 * @param view If not nullptr, restores this map view.
164 	 */
165 	bool loadFrom(const QString& path, MapView* view = nullptr);
166 
167 
168 	/**
169 	 * Imports another map into this map.
170 	 *
171 	 * If the Map::GeorefImport mode flag is set, this overload will attempt to
172 	 * calculate a transformation based on the maps' georeferencing.
173 	 * All further processing is delegated to the other overload.
174 	 *
175 	 */
176 	QHash<const Symbol*, Symbol*> importMap(
177 	        const Map& imported_map,
178 	        ImportMode mode,
179 	        std::vector<bool>* filter = nullptr,
180 	        int symbol_insert_pos = -1,
181 	        bool merge_duplicate_symbols = true
182 	);
183 
184 	/**
185 	 * Imports another map into this map.
186 	 *
187 	 * The amount of imported elements is controlled by the mode argument which
188 	 * is a combination of an enumeration of basic modes (ColorImport,
189 	 * SymbolImport, ObjectImport) and the flags (MinimalImport).
190 	 * - ObjectImport: Import objects, symbols and colors.
191 	 *   If the MinimalImport flag is set, symbols and colors not used
192 	 *   by the imported objects are ignored.
193 	 *   The filter argument is not used.
194 	 * - SymbolImport: Import symbols and colors.
195 	 *   If the MinimalImport flag is set, the filter argument may be used to
196 	 *   select a subset of the symbols, and colors not used by the imported
197 	 *   symbols are ignored.
198 	 * - ColorImport: Import colors.
199 	 *   If the MinimalImport flag is set, the filter argument may be used to
200 	 *   select a subset of the colors.
201 	 *
202 	 * This overload ignores the Map::GeorefImport mode flag. It only uses the
203 	 * given transformation. It is applied to all imported objects.
204 	 * No other adjustment of object positions and no scaling of symbol sizes
205 	 * (with respect to possible different map scales) is performed.
206 	 */
207 	QHash<const Symbol*, Symbol*> importMap(
208 	        const Map& imported_map,
209 	        ImportMode mode,
210 	        const QTransform& transform,
211 	        std::vector<bool>* filter = nullptr,
212 	        int symbol_insert_pos = -1,
213 	        bool merge_duplicate_symbols = true
214 	);
215 
216 
217 	/**
218 	 * Serializes the map directly to the given IO device, in a fixed format.
219 	 *
220 	 * This can be imported again using importFromIODevice().
221 	 * Returns true if successful.
222 	 */
223 	bool exportToIODevice(QIODevice& device) const;
224 
225 	/**
226 	 * Loads the map directly from the given IO device.
227 	 *
228 	 * The data must have been written by exportToIODevice() (or at least use
229 	 * the same format.)
230 	 * Returns true if successful.
231 	 */
232 	bool importFromIODevice(QIODevice& device);
233 
234 
235 	/**
236 	 * Draws the part of the map which is visible in the bounding box.
237 	 *
238 	 * @param painter The QPainter used for drawing.
239 	 * @param config  The rendering configuration
240 	 */
241 	void draw(QPainter* painter, const RenderConfig& config);
242 
243 	/**
244 	 * Draws a spot color overprinting simulation for the part of the map
245 	 * which is visible in the given bounding box.
246 	 *
247 	 * @param painter Must be a QPainter on a QImage of Format_ARGB32_Premultiplied.
248 	 * @param config  The rendering configuration
249 	 */
250 	void drawOverprintingSimulation(QPainter* painter, const RenderConfig& config);
251 
252 	/**
253 	 * Draws the separation for a particular spot color for the part of the
254 	 * map which is visible in the given bounding box.
255 	 *
256 	 * Separations are normally drawn in levels of gray where black means
257 	 * full tone of the spot color. The parameter use_color can be used to
258 	 * draw in the actual spot color instead.
259 	 *
260 	 * @param painter The QPainter used for drawing.
261 	 * @param config  The rendering configuration
262 	 * @param spot_color The spot color to draw the separation for.
263 	 * @param use_color  If true, forces the separation to be drawn in its actual color.
264 	 */
265 	void drawColorSeparation(QPainter* painter, const RenderConfig& config,
266 		const MapColor* spot_color, bool use_color = false);
267 
268 	/**
269 	 * Draws the map grid.
270 	 *
271 	 * @param painter The QPainter used for drawing.
272 	 * @param bounding_box Bounding box of area to draw, given in map coordinates.
273 	 */
274 	void drawGrid(QPainter* painter, const QRectF& bounding_box);
275 
276 	/**
277 	 * Draws the templates with indices first_template until last_template which
278 	 * are visible in the given bounding box.
279 	 *
280 	 * view determines template visibility and can be nullptr to show all templates.
281 	 * The initial transform of the given QPainter must be the map-to-paintdevice transformation.
282      * If on_screen is set to true, some optimizations will be applied, leading to a possibly lower display quality.
283 	 *
284 	 * @param painter The QPainter used for drawing.
285 	 * @param bounding_box Bounding box of area to draw, given in map coordinates.
286 	 * @param first_template Lowest index of the template range to draw.
287 	 * @param last_template Highest index of the template range to draw.
288 	 * @param view Optional pointer to MapView object which is used to query
289 	 *     template visibilities.
290 	 * @param on_screen Potentially enables some drawing optimizations which
291 	 *     decrease drawing quality. Should be enabled when drawing on-screen.
292 	 */
293 	void drawTemplates(QPainter* painter, const QRectF& bounding_box, int first_template,
294 					   int last_template, const MapView* view, bool on_screen) const;
295 
296 
297 	/**
298 	 * Updates the renderables and extent of all objects which have changed.
299 	 * This is automatically called by draw(), you normally do not need to call it directly.
300 	 */
301 	void updateObjects();
302 
303 	/**
304 	 * Calculates the extent of all map elements.
305 	 *
306 	 * If templates shall be included, view may either be nullptr to include all
307 	 * templates, or specify a MapView to take the template visibilities from.
308 	 */
309 	QRectF calculateExtent(bool include_helper_symbols = false, bool include_templates = false, const MapView* view = nullptr) const;
310 
311 
312 	/**
313 	 * Must be called to notify the map of new widgets displaying it.
314 	 * Useful to notify the widgets about which parts of the map have changed
315 	 * and need to be redrawn.
316 	 */
317 	void addMapWidget(MapWidget* widget);
318 
319 	/**
320 	 * Removes the map widget, see addMapWidget().
321 	 */
322 	void removeMapWidget(MapWidget* widget);
323 
324 	/**
325 	 * Redraws all map widgets completely - this can be slow!
326 	 * Try to avoid this and do partial redraws instead, if possible.
327 	 */
328 	void updateAllMapWidgets();
329 
330 	/**
331 	 * Makes sure that the selected object(s) are visible in all map widgets
332 	 * by moving the views in the widgets to the selected objects.
333 	 */
334 	void ensureVisibilityOfSelectedObjects(SelectionVisibility visibility);
335 
336 
337 	// Current drawing
338 
339 	/**
340 	 * Sets the rect (given in map coordinates) as "dirty rect" for every
341 	 * map widget showing this map, enlarged by the given pixel border.
342 	 * This means that the area covered by the rect will be redrawn by
343 	 * the active tool. Use this if the current tool's display has changed.
344 	 *
345 	 * @param map_coords_rect Area covered by the current tool's drawing in map coords.
346 	 * @param pixel_border Border around the map coords rect which is also covered,
347 	 *     given in pixels. Allows to enlarge the area given by the map coords
348 	 *     by some pixels which are independent from the zoom level.
349 	 *     For example if a tool displays markers with a radius of 3 pixels,
350 	 *     it would set the bounding box of all markers as map_coords_rect and
351 	 *     3 for pixel_border.
352 	 * @param do_update Whether a repaint of the covered area should be triggered.
353 	 */
354 	void setDrawingBoundingBox(const QRectF& map_coords_rect, int pixel_border, bool do_update = true);
355 
356 	/**
357 	 * Removes the drawing bounding box and triggers a repaint. Use this if
358 	 * the current drawing is hidden or erased.
359 	 */
360 	void clearDrawingBoundingBox();
361 
362 
363 	/**
364 	 * This is the analogon to setDrawingBoundingBox() for activities.
365 	 * See setDrawingBoundingBox().
366 	 */
367 	void setActivityBoundingBox(const QRectF& map_coords_rect, int pixel_border, bool do_update = true);
368 
369 	/**
370 	 * This is the analogon to clearDrawingBoundingBox() for activities.
371 	 * See clearDrawingBoundingBox().
372 	 */
373 	void clearActivityBoundingBox();
374 
375 
376 	/**
377 	 * Updates all dynamic drawings at the given positions,
378 	 * i.e. tool & activity drawings.
379 	 *
380 	 * See setDrawingBoundingBox() and setActivityBoundingBox().
381 	 */
382 	void updateDrawing(const QRectF& map_coords_rect, int pixel_border);
383 
384 
385 
386 	// Element translations
387 
388 	/**
389 	 * Returns a translated symbol text (name or description), or the original text.
390 	 */
391 	QString translate(const QString& symbol_text) const;
392 
393 	/**
394 	 * Returns a translated symbol text (name or description), or an empty string.
395 	 */
396 	QString raw_translation(const QString& symbol_text) const;
397 
398 
399 
400 	// Colors
401 
402 	/** Returns the number of map colors defined in this map.*/
403 	int getNumColors() const;
404 
405 	/** Returns a pointer to the MapColor identified by the non-negative priority i.
406 	 *
407 	 *  Returns nullptr if the color is not defined, or if it is a special color (i.e i<0),
408 	 *  i.e. only actual map colors are returned.
409 	 */
410 	const MapColor* getMapColor(int i) const;
411 
412 	/** Returns a pointer to the MapColor identified by the non-negative priority i.
413 	 *
414 	 *  Returns nullptr if the color is not defined, or if it is a special color (i.e i<0),
415 	 *  i.e. only actual map colors are returned.
416 	 */
417 	MapColor* getMapColor(int i);
418 
419 	/** Returns a pointer to the const MapColor identified by the priority i.
420 	 *
421 	 *  Parameter i may also be negative for specifying special reserved colors.
422 	 *  This is different from getMapColor();
423 	 *
424 	 *  Returns nullptr if the color is not defined.
425 	 */
426 	const MapColor* getColor(int i) const;
427 
428 	/**
429 	 * Replaces the color at index pos with the given color, updates dependent
430 	 * colors and symbol icons.
431 	 *
432 	 * Emits colorChanged(). Does not delete the replaced color.
433 	 */
434 	void setColor(MapColor* color, int pos);
435 
436 	/**
437 	 * Adds the given color as a new color at the given index.
438 	 * Emits colorAdded().
439 	 */
440 	void addColor(MapColor* color, int pos);
441 
442 	/**
443 	 * Deletes the color at the given index.
444 	 * Emits colorDeleted().
445 	 */
446 	void deleteColor(int pos);
447 
448 	/**
449 	 * Loops through the color list, looking for the given color pointer.
450 	 * Returns the index of the color, or -1 if it is not found.
451 	 */
452 	int findColorIndex(const MapColor* color) const;
453 
454 	/**
455 	 * Marks the colors as "dirty", i.e. as having unsaved changes.
456 	 * Emits hasUnsavedChanged(true) if the map did not have unsaved changed before.
457 	 */
458 	void setColorsDirty();
459 
460 	/**
461 	 * Makes this map use the color set from the given map.
462 	 * Used to create the maps containing preview objects in the symbol editor.
463 	 */
464 	void useColorsFrom(Map* map);
465 
466 	/**
467 	 * Checks and returns if the given color is used by at least one symbol.
468 	 */
469 	bool isColorUsedByASymbol(const MapColor* color) const;
470 
471 	/**
472 	 * Checks which colors are in use by the symbols in this map.
473 	 *
474 	 * WARNING (FIXME): returns an empty list if the map does not contain symbols!
475 	 *
476 	 * @param by_which_symbols Must be of the same size as the symbol set.
477 	 *     If set to false for a symbol, it will be disregarded.
478 	 * @param out Output parameter: a vector of the same size as the color list,
479 	 *     where each element is set to true if the color is used by at least one symbol.
480 	 */
481 	void determineColorsInUse(const std::vector< bool >& by_which_symbols, std::vector< bool >& out) const;
482 
483 	/** Returns true if the map contains spot colors. */
484 	bool hasSpotColors() const;
485 
486 	/**
487 	 * Returns true if any visible object uses a non-opaque color.
488 	 */
489 	bool hasAlpha() const;
490 
491 
492 	// Symbols
493 
494 	/** Returns the symbol set ID. */
495 	QString symbolSetId() const;
496 
497 	/** Sets the symbol set ID. */
498 	void setSymbolSetId(const QString& id);
499 
500 
501 	/** Returns the number of symbols in this map. */
502 	int getNumSymbols() const;
503 
504 	/** Returns a pointer to the i-th symbol. */
505 	const Symbol* getSymbol(int i) const;
506 
507 	/** Returns a pointer to the i-th symbol. */
508 	Symbol* getSymbol(int i);
509 
510 	/**
511 	 * Replaces the symbol at the given index with another symbol.
512 	 * Emits symbolChanged() and possibly selectedObjectEdited().
513 	 */
514 	void setSymbol(Symbol* symbol, int pos);
515 
516 	/**
517 	 * Adds the given symbol at the specified index.
518 	 * Emits symbolAdded().
519 	 */
520 	void addSymbol(Symbol* symbol, int pos);
521 
522 	/**
523 	 * Moves a symbol from one index to another in the symbol list.
524 	 */
525 	void moveSymbol(int from, int to);
526 
527 	/**
528 	 * Sorts the symbol list using the given comparator.
529 	 */
530 	template<typename T> void sortSymbols(T compare);
531 
532 	/**
533 	 * Deletes the symbol at the given index.
534 	 * Emits symbolDeleted().
535 	 */
536 	void deleteSymbol(int pos);
537 
538 	/**
539 	 * Loops over all symbols, looking for the given symbol pointer.
540 	 * Returns the index of the symbol, or -1 if the symbol is not found.
541 	 * For the "undefined" symbols, returns special indices smaller than -1.
542 	 */
543 	int findSymbolIndex(const Symbol* symbol) const;
544 
545 	/**
546 	 * Marks the symbols as "dirty", i.e. as having unsaved changes.
547 	 * Emits hasUnsavedChanged(true) if the map did not have unsaved changed before.
548 	 */
549 	void setSymbolsDirty();
550 
551 	/**
552 	 * Updates the icons of all symbols with the given color.
553 	 */
554 	void updateSymbolIcons(const MapColor* color);
555 
556 	/**
557 	 * Scales all symbols by the given factor.
558 	 */
559 	void scaleAllSymbols(double factor);
560 
561 	/**
562 	 * Checks which symbols are in use in this map.
563 	 *
564 	 * Returns a vector of the same size as the symbol list, where each element
565 	 * is set to true if there is at least one object which uses this symbol or
566 	 * a derived (combined) symbol.
567 	 */
568 	void determineSymbolsInUse(std::vector<bool>& out) const;
569 
570 	/**
571 	 * Adds to the given symbol bitfield all other symbols which are needed to
572 	 * display the symbols indicated by the bitfield because of symbol dependencies.
573 	 */
574 	void determineSymbolUseClosure(std::vector< bool >& symbol_bitfield) const;
575 
576 	/**
577 	 * Returns the scale factor to be used for default symbol icons.
578 	 *
579 	 * The full icon size (width, height) is represented by 1.0.
580 	 */
581 	qreal symbolIconZoom() const;
582 
583 public slots:
584 	/**
585 	 * Updates the symbol icon zoom from the current set of symbols.
586 	 *
587 	 * The symbol icon zoom is chosen so that most symbols fit into the full
588 	 * icon space, and the number of symbol below 10% size is kept low.
589 	 * For a map without symbols, this returns 1.0.
590 	 */
591 	void updateSymbolIconZoom();
592 
593 
594 public:
595 	// Templates
596 
597 	/** Returns the number of templates in this map. */
598 	int getNumTemplates() const;
599 
600 	/** Returns the i-th template. */
601 	const Template* getTemplate(int i) const;
602 
603 	/** Returns the i-th template. */
604 	Template* getTemplate(int i);
605 
606 	/** Sets the template index which is the first (lowest) to be drawn in front of the map. */
607 	void setFirstFrontTemplate(int pos);
608 
609 	/** Returns the template index which is the first (lowest) to be drawn in front of the map. */
610 	int getFirstFrontTemplate() const;
611 
612 	/**
613 	 * Replaces the template at the given index with another.
614 	 * Emits templateChanged().
615 	 */
616 	void setTemplate(Template* temp, int pos);
617 
618 	/**
619 	 * Adds a new template at the given index.
620 	 *
621 	 * To place a template immediately below the map, adjust first_front_template
622 	 * manually with setFirstFrontTemplate()!
623 	 */
624 	void addTemplate(Template* temp, int pos);
625 
626 	/**
627 	 * Removes the template with the given index from the template list,
628 	 * but does not delete it.
629 	 * NOTE: if required, adjust first_front_template manually with setFirstFrontTemplate()!
630 	 */
631 	void removeTemplate(int pos);
632 
633 	/**
634 	 * Removes the template with the given position from the template list and deletes it.
635 	 * NOTE: if required, adjust first_front_template manually with setFirstFrontTemplate()!
636 	 */
637 	void deleteTemplate(int pos);
638 
639 	/**
640 	 * Marks the area defined by the given QRectF (in map coordinates) and
641 	 * pixel border as "dirty", i.e. as needing a repaint, for the given template
642 	 * in all map widgets.
643 	 *
644 	 * For an explanation of the area and pixel border, see setDrawingBoundingBox().
645 	 *
646 	 * Warning: does nothing if the template is not visible in a widget!
647 	 * So make sure to call this and showing/hiding a template in the correct order!
648 	 */
649 	void setTemplateAreaDirty(Template* temp, const QRectF& area, int pixel_border);
650 
651 	/**
652 	 * Marks the whole area of the i-th template as "to be repainted".
653 	 * See setTemplateAreaDirty().
654 	 * Does nothing for i == -1.
655 	 */
656 	void setTemplateAreaDirty(int i);
657 
658 	/**
659 	 * Loops over all templates in the map and looks for the given template pointer.
660 	 * Returns the index of the template. The template must be contained in the map,
661 	 * otherwise an assert will be triggered!
662 	 */
663 	int findTemplateIndex(const Template* temp) const;
664 
665 	/**
666 	 * Marks the template settings as "dirty", i.e. as having unsaved changes.
667 	 * Emits hasUnsavedChanged(true) if the map did not have unsaved changed before.
668 	 */
669 	void setTemplatesDirty();
670 
671 	/** Emits templateChanged() for the given template. */
672 	void emitTemplateChanged(Template* temp);
673 
674 
675 	/**
676 	 * Returns the number of manually closed templates
677 	 * for which the settings are still stored.
678 	 */
679 	int getNumClosedTemplates() const;
680 
681 	/** Returns the i-th closed template. */
682 	const Template* getClosedTemplate(int i) const;
683 
684 	/** Returns the i-th closed template. */
685 	Template* getClosedTemplate(int i);
686 
687 	/** Empties the list of closed templates. */
688 	void clearClosedTemplates();
689 
690 	/**
691 	 * Removes the template with the given index from the normal template list,
692 	 * unloads the template file and adds the template to the closed template list
693 	 *
694 	 * NOTE: if required, adjust first_front_template manually with setFirstFrontTemplate()!
695 	 */
696 	void closeTemplate(int i);
697 
698 	/**
699 	 * Removes the template with the given index from the closed template list,
700 	 * load the template file and adds the template to the normal template list again.
701 	 * The template is made visible in the given view.
702 	 *
703 	 * NOTE: if required, adjust first_front_template manually with
704 	 * setFirstFrontTemplate() before calling this method!
705 	 *
706 	 * @param i The index of the closed template to reload.
707 	 * @param target_pos The desired index in the normal template list after loading.
708 	 * @param dialog_parent Widget as parent for possible dialogs.
709 	 * @param map_path Path where the map is saved currently. Used as possible
710 	 *     search location to locate missing templates.
711 	 */
712 	bool reloadClosedTemplate(int i, int target_pos, QWidget* dialog_parent, const QString& map_path = QString());
713 
714 
715 	// Undo & Redo
716 
717 	/**
718 	 * Returns the UndoManager instance for this map.
719 	 */
720 	UndoManager& undoManager();
721 
722 	/**
723 	 * Returns the UndoManager instance for this map.
724 	 */
725 	const UndoManager& undoManager() const;
726 
727 	/**
728 	 * Pushes a new undo step to the map's undoManager.
729 	 */
730 	void push(UndoStep* step);
731 
732 
733 	// Map parts
734 
735 	/**
736 	 * Returns the number of map parts in this map.
737 	 */
738 	int getNumParts() const;
739 
740 	/**
741 	 * Returns the i-th map part.
742 	 */
743 	MapPart* getPart(std::size_t i) const;
744 
745 	/**
746 	 * Adds the new part at the given index.
747 	 */
748 	void addPart(MapPart* part, std::size_t index);
749 
750 	/**
751 	 * Removes the map part at position.
752 	 */
753 	void removePart(std::size_t index);
754 
755 	/**
756 	 * Loops over all map parts, looking for the given part pointer.
757 	 * Returns the part's index in the list. The part must be contained in the
758 	 * map, otherwise an assert will be triggered!
759 	 */
760 	int findPartIndex(const MapPart* part) const;
761 
762 	/**
763 	 * Returns the current map part, i.e. the part where edit operations happen.
764 	 */
765 	MapPart* getCurrentPart() const;
766 
767 	/**
768 	 * Changes the current map part.
769 	 *
770 	 * This is a convenience method which looks up the part's index and then
771 	 * calls setCurrentPartIndex.
772 	 */
773 	void setCurrentPart(MapPart* part);
774 
775 	/**
776 	 * Returns the index of the current map part.
777 	 *
778 	 * @see getCurrentPart().
779 	 */
780 	std::size_t getCurrentPartIndex() const;
781 
782 	/**
783 	 * Changes the current map part.
784 	 */
785 	void setCurrentPartIndex(std::size_t index);
786 
787 	/**
788 	 * Moves all specified objects from the source to the target map part.
789 	 *
790 	 * Objects are processed one by one. This means that processing one object
791 	 * changes the index of following objects. Thus the given indices must
792 	 * normally be in descending order.
793 	 *
794 	 * The objects will be continuously located at the end to the objects in the target part.
795 	 * Source object which were selected will be removed from the object selection.
796 	 *
797 	 * @return The index of the first object which has been reassigned.
798 	 */
799 	int reassignObjectsToMapPart(std::vector<int>::const_iterator first, std::vector<int>::const_iterator last, std::size_t source, std::size_t destination);
800 
801 	/**
802 	 * Merges the source part with the destination part.
803 	 *
804 	 * Removes the source part unless it is identical with the destination part.
805 	 *
806 	 * The objects will be continuously located at the end to the objects in the target part.
807 	 * Does not change the object selection.
808 	 *
809 	 * Makes the destination part the current part when the source part is the current part.
810 	 *
811 	 * @return The index of the first object which has been reassigned.
812 	 */
813 	int mergeParts(std::size_t source, std::size_t destination);
814 
815 
816 	// Objects
817 
818 	/** Returns the total number of objects in this map (sum of all parts) */
819 	int getNumObjects() const;
820 
821 	/**
822 	 * Adds the object as new object in the part with the given index,
823 	 * or in the current part if the default -1 is passed.
824 	 * Returns the index of the added object in the part.
825 	 */
826 	int addObject(Object* object, int part_index = -1);
827 
828 	/**
829 	 * Deletes the given object from the map.
830 	 *
831 	 * Be sure to call removeObjectFromSelection() if necessary.
832 	 */
833 	void deleteObject(Object* object);
834 
835 	/**
836 	 * Relinquish object ownership.
837 	 *
838 	 * Searches map parts and returns pointer if the object was found.
839 	 * Otherwise nullptr is returned.
840 	 */
841 	Object* releaseObject(Object* object);
842 
843 	/**
844 	 * Marks the objects as "dirty", i.e. as having unsaved changes.
845 	 * Emits hasUnsavedChanged(true) if the map did not have unsaved changed before.
846 	 */
847 	void setObjectsDirty();
848 
849 	/**
850 	 * Marks the area given by map_coords_rect as "dirty" in all map widgets,
851 	 * i.e. as needing to be redrawn because some object(s) changed there.
852 	 */
853 	void setObjectAreaDirty(const QRectF& map_coords_rect);
854 
855 	/**
856 	 * Finds and returns all objects at the given position in the current part.
857 	 *
858 	 * @param coord Coordinate where to query objects.
859 	 * @param tolerance Allowed distance from the query coordinate to the objects.
860 	 * @param treat_areas_as_paths If set to true, areas will be treated as paths,
861 	 *     i.e. they will be returned only if the query coordinate is close to
862 	 *     their border, not in all cases where the query coordinate is inside the area.
863 	 * @param extended_selection If set to true, more object than defined by the
864 	 *     default behavior will be selected. For example, by default point objects
865 	 *     will only be returned if the query coord is close to the point object
866 	 *     coord. With extended_selection, they are also returned if the query
867 	 *     coord is just inside the graphical extent of the point object.
868 	 *     This can be used for a two-pass algorithm to find the most relevant
869 	 *     objects first, and then query for all objects if no objects are found
870 	 *     in the first pass.
871 	 * @param include_hidden_objects Set to true if you want to find hidden objects.
872 	 * @param include_protected_objects Set to true if you want to find protected objects.
873 	 * @param out Output parameter. Will be filled with pairs of symbol types
874 	 *     and corresponding objects. The symbol type describes the way in which
875 	 *     an object has been found and is taken from Symbol::Type. This is e.g.
876 	 *     important for combined symbols, which can be found from a line or
877 	 *     an area.
878 	 */
879 	void findObjectsAt(const MapCoordF& coord, qreal tolerance, bool treat_areas_as_paths,
880 		bool extended_selection, bool include_hidden_objects,
881 		bool include_protected_objects, SelectionInfoVector& out) const;
882 
883 	/**
884 	 * Finds and returns all objects at the given position in all parts.
885 	 *
886 	 * @see Map::findObjectsAt
887 	 */
888 	void findAllObjectsAt(const MapCoordF& coord, qreal tolerance, bool treat_areas_as_paths,
889 		bool extended_selection, bool include_hidden_objects,
890 		bool include_protected_objects, SelectionInfoVector& out) const;
891 
892 	/**
893 	 * Finds and returns all objects intersecting the given box in the current part.
894 	 *
895 	 * @param corner1 First corner of the query box.
896 	 * @param corner2 Second corner of the query box.
897 	 * @param include_hidden_objects Set to true if you want to find hidden objects.
898 	 * @param include_protected_objects Set to true if you want to find protected objects.
899 	 * @param out Output parameter. Will be filled with an object list.
900 	 */
901 	void findObjectsAtBox(const MapCoordF& corner1, const MapCoordF& corner2,
902 		bool include_hidden_objects, bool include_protected_objects,
903 		std::vector<Object*>& out) const;
904 
905 	/**
906 	 * Counts the objects whose bounding boxes intersect the given rect.
907 	 *
908 	 * This may be inaccurate because the true object shapes usually differ
909 	 * from the bounding boxes.
910 	 *
911 	 * @param map_coord_rect The query rect.
912 	 * @param include_hidden_objects Set to true if you want to find hidden objects.
913 	 */
914 	int countObjectsInRect(const QRectF& map_coord_rect, bool include_hidden_objects);
915 
916 
917 	/**
918 	 * Applies a condition on all objects until the first match is found.
919 	 *
920 	 * @return True if there is an object matching the condition, false otherwise.
921 	 */
922 	bool existsObject(const std::function<bool (const Object*)>& condition) const;
923 
924 	/**
925 	 * Applies an operation on all objects which match a particular condition.
926 	 */
927 	void applyOnMatchingObjects(const std::function<void (Object*)>& operation, const std::function<bool (const Object*)>& condition);
928 
929 	/**
930 	 * Applies a function on all objects which match a particular condition.
931 	 */
932 	void applyOnMatchingObjects(const std::function<void (const Object*)>& operation, const std::function<bool (const Object*)>& condition) const;
933 
934 	/**
935 	 * Applies an operation on all objects which match a particular condition.
936 	 */
937 	void applyOnMatchingObjects(const std::function<void (Object*, MapPart*, int)>& operation, const std::function<bool (const Object*)>& condition);
938 
939 	/**
940 	 * Applies an operation on all objects.
941 	 */
942 	void applyOnAllObjects(const std::function<void (Object*)>& operation);
943 
944 	/**
945 	 * Applies an operation on all objects.
946 	 */
947 	void applyOnAllObjects(const std::function<void (const Object*)>& operation) const;
948 
949 	/**
950 	 * Applies an operation on all objects.
951 	 */
952 	void applyOnAllObjects(const std::function<void (Object*, MapPart*, int)>& operation);
953 
954 
955 	/** Scales all objects by the given factor. */
956 	void scaleAllObjects(double factor, const MapCoord& scaling_center);
957 
958 	/** Rotates all objects by the given rotation angle (in radians). */
959 	void rotateAllObjects(double rotation, const MapCoord& center);
960 
961 	/** Forces an update of all objects, i.e. calls update(true) on each map object. */
962 	void updateAllObjects();
963 
964 	/** Forces an update of all objects with the given symbol. */
965 	void updateAllObjectsWithSymbol(const Symbol* symbol);
966 
967 	/** For all symbols with old_symbol, replaces the symbol by new_symbol. */
968 	void changeSymbolForAllObjects(const Symbol* old_symbol, const Symbol* new_symbol);
969 
970 	/**
971 	 * Deletes all objects with the given symbol.
972 	 *
973 	 * @return True if at least one object was deleted, false otherwise
974 	 */
975 	bool deleteAllObjectsWithSymbol(const Symbol* symbol);
976 
977 	/**
978 	 * Returns if at least one object with the given symbol exists in the map.
979 	 * WARNING: Even if no objects exist directly, the symbol could still be
980 	 *          required by another (combined) symbol used by an object!
981 	 */
982 	bool existsObjectWithSymbol(const Symbol* symbol) const;
983 
984 
985 	/**
986 	 * Removes the renderables of the given object from display (does not
987 	 * delete them!).
988 	 */
989 	void removeRenderablesOfObject(const Object* object, bool mark_area_as_dirty);
990 
991 	/**
992 	 * Inserts the renderables of the given object, so they will be displayed.
993 	 */
994 	void insertRenderablesOfObject(const Object* object);
995 
996 
997 	/**
998 	 * Marks an object as irregular.
999 	 */
1000 	void markAsIrregular(Object* object);
1001 
1002 	/**
1003 	 * Returns the list of objects marked as irregular.
1004 	 */
1005 	const std::set<Object*> irregularObjects() const;
1006 
1007 	/**
1008 	 * Deletes the irregular objects.
1009 	 *
1010 	 * This function deletes the objects which were previously marked as irregular.
1011 	 * Only objects which are actually member of map parts are deleted. Objects in
1012 	 * undo steps or similar are ignored.
1013 	 *
1014 	 * \return The number of deleted objects.
1015 	 */
1016 	std::size_t deleteIrregularObjects();
1017 
1018 
1019 	// Object selection
1020 
1021 	const ObjectSelection& selectedObjects() const;
1022 
1023 	/** Returns the number of selected objects. */
1024 	int getNumSelectedObjects() const;
1025 
1026 	/** Returns an iterator allowing to iterate over the selected objects. */
1027 	ObjectSelection::const_iterator selectedObjectsBegin() const;
1028 
1029 	/** Returns an end iterator allowing to iterate over the selected objects. */
1030 	ObjectSelection::const_iterator selectedObjectsEnd() const;
1031 
1032 	/**
1033 	 * Returns the object in the selection which was selected first by the user.
1034 	 *
1035 	 * If she later deselects it while other objects are still selected or if
1036 	 * the selection is done as box selection, this "first" selected object is
1037 	 * just a more or less random object from the selection.
1038 	 */
1039 	const Object* getFirstSelectedObject() const;
1040 
1041 	/**
1042 	 * Returns the object in the selection which was selected first by the user.
1043 	 */
1044 	Object* getFirstSelectedObject();
1045 
1046  	/**
1047 	 * Checks the selected objects for compatibility with the given symbol.
1048 	 * @param symbol the symbol to check compatibility for
1049 	 * @param out_compatible returns if all selected objects are compatible
1050 	 *     to the given symbol
1051 	 * @param out_different returns if at least one of the selected objects'
1052 	 *     symbols is different to the given symbol
1053 	 */
1054 	void getSelectionToSymbolCompatibility(const Symbol* symbol, bool& out_compatible, bool& out_different) const;
1055 
1056 	/**
1057 	 * Deletes the selected objects and creates an undo step for this action.
1058 	 */
1059 	void deleteSelectedObjects();
1060 
1061 	/**
1062 	 * Enlarges the given rect to cover all selected objects.
1063 	 */
1064 	void includeSelectionRect(QRectF& rect) const;
1065 
1066 	/**
1067 	 * Draws the selected objects.
1068 	 *
1069 	 * @param painter The QPainter used for drawing.
1070 	 * @param force_min_size See draw().
1071 	 * @param widget The widget in which the drawing happens.
1072 	 *     Used to get view and viewport information.
1073 	 * @param replacement_renderables If given, draws these renderables instead
1074 	 *     Of the selection renderables. TODO: HACK
1075 	 * @param draw_normal If set to true, draws the objects like normal objects,
1076 	 *     otherwise draws transparent highlights.
1077 	 */
1078 	void drawSelection(QPainter* painter, bool force_min_size, MapWidget* widget,
1079 		MapRenderables* replacement_renderables = nullptr, bool draw_normal = false);
1080 
1081 	/**
1082 	 * Adds the given object to the selection.
1083 	 * @param object The object to add.
1084 	 * @param emit_selection_changed Set to true if objectSelectionChanged()
1085 	 *     should be emitted. Do this only for the last in a
1086 	 *     sequence of selection change oparations to prevent bad performance!
1087 	 */
1088 	void addObjectToSelection(Object* object, bool emit_selection_changed);
1089 
1090 	/**
1091 	 * Removes the given object from the selection.
1092 	 * @param object The object to remove.
1093 	 * @param emit_selection_changed See addObjectToSelection().
1094 	 */
1095 	void removeObjectFromSelection(Object* object, bool emit_selection_changed);
1096 
1097 	/**
1098 	 * Removes from the selection all objects with the given symbol.
1099 	 * Returns true if at least one object has been removed.
1100 	 * @param symbol The symbol of the objects to remove.
1101 	 * @param emit_selection_changed See addObjectToSelection().
1102 	 */
1103 	bool removeSymbolFromSelection(const Symbol* symbol, bool emit_selection_changed);
1104 
1105 	/** Returns true if the given object is selected. */
1106 	bool isObjectSelected(const Object* object) const;
1107 
1108 	/**
1109 	 * Toggles the selection of the given object.
1110 	 * Returns true if the object was selected, false if deselected.
1111 	 * @param object The object to select or deselect.
1112 	 * @param emit_selection_changed See addObjectToSelection().
1113 	 */
1114 	bool toggleObjectSelection(Object* object, bool emit_selection_changed);
1115 
1116 	/**
1117 	 * Empties the object selection.
1118 	 * @param emit_selection_changed See addObjectToSelection().
1119 	 */
1120 	void clearObjectSelection(bool emit_selection_changed);
1121 
1122 	/**
1123 	 * Emits objectSelectionChanged(). Use this if setting emit_selection_changed
1124 	 * in a selection change method is unfeasible.
1125 	 */
1126 	void emitSelectionChanged();
1127 
1128 	/**
1129 	 * Emits selectedObjectEdited(). Use this after making changes
1130 	 * to a selected object.
1131 	 */
1132 	void emitSelectionEdited();
1133 
1134 
1135 	// Other settings
1136 
1137 	/** Sets the map's scale denominator. */
1138 	void setScaleDenominator(unsigned int value);
1139 
1140 	/** Returns the map's scale denominator. */
1141 	unsigned int getScaleDenominator() const;
1142 
1143 	/**
1144 	 * Changes the map's scale.
1145 	 *
1146 	 * @param new_scale_denominator The new scale denominator.
1147 	 * @param additional_stretch Additional stretch/shrink applied to the map.
1148 	 * @param scaling_center The coordinate to use as scaling center.
1149 	 * @param scale_symbols Whether to scale the map symbols.
1150 	 * @param scale_objects Whether to scale the map object coordinates.
1151 	 * @param scale_georeferencing Whether to adjust the map's georeferencing reference point.
1152 	 * @param scale_templates Whether to scale non-georeferenced templates.
1153 	 */
1154 	void changeScale(unsigned int new_scale_denominator, double additional_stretch,
1155 		const MapCoord& scaling_center, bool scale_symbols, bool scale_objects,
1156 		bool scale_georeferencing, bool scale_templates);
1157 
1158 
1159 	/**
1160 	 * Rotate the map around a point.
1161 	 *
1162 	 * @param rotation The rotation angle (in radians).
1163 	 * @param center The rotation center point.
1164 	 * @param adjust_georeferencing Whether to adjust the georeferencing reference point.
1165 	 * @param adjust_declination Whether to adjust the georeferencing declination.
1166 	 * @param adjust_templates Whether to adjust non-georeferenced templates.
1167 	 */
1168 	void rotateMap(double rotation, const MapCoord& center,
1169 		bool adjust_georeferencing, bool adjust_declination,
1170 		bool adjust_templates);
1171 
1172 
1173 	/** Returns the map notes string. */
1174 	const QString& getMapNotes() const;
1175 
1176 	/**
1177 	 * Sets the map notes string.
1178 	 * NOTE: Set the map to dirty manually!
1179 	 */
1180 	void setMapNotes(const QString& text);
1181 
1182 
1183 	/** Returns the map's georeferencing object. */
1184 	const Georeferencing& getGeoreferencing() const;
1185 
1186 	/**
1187 	 * Assigns georeferencing settings for the map from the given object and
1188 	 * sets the map to have unsaved changes.
1189 	 */
1190 	void setGeoreferencing(const Georeferencing& georeferencing);
1191 
1192 
1193 	/**
1194 	 * Returns the map's grid settings.
1195 	 */
1196 	const MapGrid& getGrid() const;
1197 
1198 	/**
1199 	 * Sets the map's grid settings from the given object and
1200 	 * may set the map to have unsaved changes.
1201 	 */
1202 	void setGrid(const MapGrid& grid);
1203 
1204 
1205 	/**
1206 	 * TODO: These two options should really be view options, but are not due
1207 	 * to a limitation:
1208 	 * the current architecture makes it impossible to have different
1209 	 * renderables of the same objects in different views!
1210 	 */
1211 
1212 	/** Returns if area hatching is enabled. */
1213 	bool isAreaHatchingEnabled() const;
1214 
1215 	/** Sets if area hatching is enabled. */
1216 	void setAreaHatchingEnabled(bool enabled);
1217 
1218 
1219 	/** Returns if the baseline view is enabled. */
1220 	bool isBaselineViewEnabled() const;
1221 
1222 	/** Sets if the baseline view is enabled. */
1223 	void setBaselineViewEnabled(bool enabled);
1224 
1225 
1226 	/** Returns the rendering options as an int representing Symbol::RenderableOptions. */
1227 	int renderableOptions() const;
1228 
1229 
1230 	/** Returns true if the map has a print configuration. */
1231 	bool hasPrinterConfig() const noexcept;
1232 
1233 	/** Returns a const reference to the current print configuration.
1234 	 *
1235 	 * If the map does not have a print configuration, a default configuration
1236 	 * is created first.
1237 	 */
1238 	const MapPrinterConfig& printerConfig();
1239 
1240 	/** Returns a copy of the current print configuration.
1241 	 *
1242 	 * If the map does not have a print configuration, the function will return
1243 	 * a default configuration for this map.
1244 	 */
1245 	MapPrinterConfig printerConfig() const;
1246 
1247 	/** Sets the print configuration. */
1248 	void setPrinterConfig(const MapPrinterConfig& config);
1249 
1250 	/** Clears the print configuration.
1251 	 *
1252 	 * After calling this method, hasPrinterConfig() returns false.
1253 	 */
1254 	void resetPrinterConfig();
1255 
1256 
1257 	/** Returns the default parameters for loading of image templates. */
1258 	void getImageTemplateDefaults(bool& use_meters_per_pixel, double& meters_per_pixel,
1259 		double& dpi, double& scale);
1260 
1261 	/**
1262 	 * Sets default parameters for loading of image templates.
1263 	 * TODO: put these into a struct.
1264 	 */
1265 	void setImageTemplateDefaults(bool use_meters_per_pixel, double meters_per_pixel,
1266 		double dpi, double scale);
1267 
1268 
1269 	/**
1270 	 * Returns whether there are unsaved changes in the map.
1271 	 *
1272 	 * To toggle this state, never use setHasUnsavedChanges() directly unless
1273 	 * you know what you are doing, instead use setOtherDirty() or set one of
1274 	 * the more specific 'dirty' flags. This is because a call to
1275 	 * setHasUnsavedChanges() alone followed by a map change and an undo would
1276 	 * result in no changed flag.
1277 	 */
1278 	bool hasUnsavedChanges() const;
1279 
1280 	/** Do not use this in usual cases, see hasUnsavedChanged(). */
1281 	void setHasUnsavedChanges(bool has_unsaved_changes);
1282 
1283 	/** Returns if there are unsaved changes to the colors. */
1284 	bool areColorsDirty() const;
1285 
1286 	/** Returns if there are unsaved changes to the symbols. */
1287 	bool areSymbolsDirty() const;
1288 
1289 	/** Returns if there are unsaved changes to the templates. */
1290 	bool areTemplatesDirty() const;
1291 
1292 	/** Returns if there are unsaved changes to the objects. */
1293 	bool areObjectsDirty() const;
1294 
1295 	/** Returns if there are unsaved changes to anything else than the above. */
1296 	bool isOtherDirty() const;
1297 
1298 	/**
1299 	 * Marks something unspecific in the map as "dirty", i.e. as having unsaved changes.
1300 	 * Emits hasUnsavedChanged(true) if the map did not have unsaved changed before.
1301 	 *
1302 	 * Use setColorsDirty(), setSymbolsDirty(), setTemplatesDirty() or
1303 	 * setObjectsDirty() if you know more specifically what has changed.
1304 	 */
1305 	void setOtherDirty();
1306 
1307 
1308 	// Static
1309 
1310 	/** Returns the special covering red color. */
1311 	static const MapColor* getCoveringRed();
1312 
1313 	/** Returns the special covering white color. */
1314 	static const MapColor* getCoveringWhite();
1315 
1316 	/** Returns the special covering gray color for "undefined" objects. */
1317 	static const MapColor* getUndefinedColor();
1318 
1319 	/** Returns the special registration color. */
1320 	static const MapColor* getRegistrationColor();
1321 
1322 	/** Returns the special covering white line symbol. */
1323 	static LineSymbol* getCoveringWhiteLine();
1324 
1325 	/** Returns the special covering red line symbol. */
1326 	static LineSymbol* getCoveringRedLine();
1327 
1328 	/** Returns the special covering combined symbol (white + red). */
1329 	static CombinedSymbol* getCoveringCombinedLine();
1330 
1331 	/** Returns the special gray "undefined" line symbol. */
1332 	static LineSymbol* getUndefinedLine();
1333 
1334 	/** Returns the special gray "undefined" point symbol. */
1335 	static PointSymbol* getUndefinedPoint();
1336 
1337 	/** Returns the special gray "undefined" text symbol. */
1338 	static TextSymbol* getUndefinedText();
1339 
1340 
1341 signals:
1342 	/**
1343 	 * Emitted when a the map enters or leaves the state which is saved on map.
1344 	 */
1345 	void hasUnsavedChanged(bool is_clean);
1346 
1347 
1348 	/** Emitted when a color is added to the map, gives the color's index and pointer. */
1349 	void colorAdded(int pos, const OpenOrienteering::MapColor* color);
1350 
1351 	/** Emitted when a map color is changed, gives the color's index and pointer. */
1352 	void colorChanged(int pos, const OpenOrienteering::MapColor* color);
1353 
1354 	/** Emitted when a map color is deleted, gives the color's index and pointer. */
1355 	void colorDeleted(int pos, const OpenOrienteering::MapColor* old_color);
1356 
1357 	/** Emitted when the presence of spot colors in the map changes. */
1358 	void spotColorPresenceChanged(bool has_spot_colors) const;  // clazy:exclude=const-signal-or-slot
1359 
1360 
1361 	/** Emitted when a symbol is added to the map, gives the symbol's index and pointer. */
1362 	void symbolAdded(int pos, const OpenOrienteering::Symbol* symbol);
1363 
1364 	/** Emitted when a symbol in the map is changed. */
1365 	void symbolChanged(int pos, const OpenOrienteering::Symbol* new_symbol, const OpenOrienteering::Symbol* old_symbol);
1366 
1367 	/** Emitted when the icon of the symbol with the given index changes. */
1368 	void symbolIconChanged(int pos);
1369 
1370 	/** Emitted when a symbol in the map is deleted. */
1371 	void symbolDeleted(int pos, const OpenOrienteering::Symbol* old_symbol);
1372 
1373 	/** Emitted when the symbol icon zoom changes. */
1374 	void symbolIconZoomChanged();
1375 
1376 
1377 	/** Emitted when a template is added to the map, gives the template's index and pointer. */
1378 	void templateAdded(int pos, OpenOrienteering::Template* temp);
1379 
1380 	/** Emitted when a template in the map is changed, gives the template's index and pointer. */
1381 	void templateChanged(int pos, OpenOrienteering::Template* temp);
1382 
1383 	/** Emitted when a template in the map is deleted, gives the template's index and pointer. */
1384 	void templateDeleted(int pos, const OpenOrienteering::Template* old_temp);
1385 
1386 	/** Emitted when the number of closed templates changes between zero and one. */
1387 	void closedTemplateAvailabilityChanged();
1388 
1389 
1390 	/** Emitted when the set of selected objects changes. Also emitted when the
1391 	 *  symbol of a selected object changes (which is similar to selecting another
1392 	 *  object). */
1393 	void objectSelectionChanged();
1394 
1395 	/**
1396 	 * Emitted when at least one of the selected objects is edited in any way.
1397 	 * For example, this includes the case where a symbol of one of the
1398 	 * selected objects is edited, too.
1399 	 */
1400 	void selectedObjectEdited();
1401 
1402 
1403 	/**
1404 	 * Emitted when the map part currently used for drawing changes.
1405 	 *
1406 	 * @see currentMapPartIndexChanged()
1407 	 */
1408 	void currentMapPartChanged(const OpenOrienteering::MapPart* part);
1409 
1410 	/**
1411 	 * Emitted when the index of map part currently used for drawing changes.
1412 	 *
1413 	 * This signal may be emitted even when the current MapPart object does not
1414 	 * change. This happens when the index changes due to addition or removal
1415 	 * of map parts.
1416 	 */
1417 	void currentMapPartIndexChanged(std::size_t index);
1418 
1419 	/**
1420 	 * Emitted when a part is added to the map.
1421 	 */
1422 	void mapPartAdded(std::size_t index, const OpenOrienteering::MapPart* part);
1423 
1424 	/**
1425 	 * Emitted when a part's properties are changed.
1426 	 */
1427 	void mapPartChanged(std::size_t index, const OpenOrienteering::MapPart* part);
1428 
1429 	/**
1430 	 * Emitted when a part is removed from the map.
1431 	 */
1432 	void mapPartDeleted(std::size_t index, const OpenOrienteering::MapPart* part);
1433 
1434 protected slots:
1435 	void checkSpotColorPresence();
1436 
1437 	void undoCleanChanged(bool is_clean);
1438 
1439 private:
1440 	typedef std::vector<MapColor*> ColorVector;
1441 	typedef std::vector<Symbol*> SymbolVector;
1442 	typedef std::vector<Template*> TemplateVector;
1443 	typedef std::vector<MapPart*> PartVector;
1444 	typedef std::vector<MapWidget*> WidgetVector;
1445 
1446 	class MapColorSet : public QSharedData
1447 	{
1448 	public:
1449 		ColorVector colors;
1450 
1451 		MapColorSet();
1452 
1453 		MapColorSet(const MapColorSet& ) = delete;
1454 
1455 		~MapColorSet();
1456 
1457 		void insert(int pos, MapColor* color);
1458 
1459 		void erase(int pos);
1460 
1461 		/** Merges another MapColorSet into this set, trying to maintain
1462 		 *  the relative order of colors.
1463 		 *  If a filter is given, imports only the colors for  which
1464 		 *  filter[color_index] is true, or which are spot colors referenced
1465 		 *  by the selected colors.
1466 		 *  If a map is given, this color set is modified through the map's
1467 		 *  color accessor methods so that other object become aware of the
1468 		 *  changes.
1469 		 *  @return a mapping from the imported color pointer in the other set
1470 		 *          to color pointers in this set.
1471 		 */
1472 		MapColorMap importSet(const MapColorSet& other,
1473 		                      std::vector<bool>* filter = nullptr,
1474 		                      Map* map = nullptr);
1475 
1476 	private:
1477 		/**
1478 		 * Adjust the priorities of the colors in the range [first,last).
1479 		 */
1480 		void adjustColorPriorities(int first, int last);
1481 	};
1482 
1483 
1484 	/**
1485 	 * Imports the other symbol set into this map's symbols.
1486 	 *
1487 	 * If a filter is given, imports only the symbols for which filter[color_index] == true.
1488 	 * Imported symbols are placed at insert_pos (if positive), or after the existing symbols.
1489 	 * Returns a mapping from original symbols (in other) to imported symbols.
1490 	 */
1491 	QHash<const Symbol*, Symbol*> importSymbols(
1492 	        const Map& other,
1493 	        const MapColorMap& color_map,
1494 	        int insert_pos = -1,
1495 	        bool merge_duplicates = true,
1496 	        const std::vector<bool>& filter = {}
1497 	);
1498 
1499 
1500 	void addSelectionRenderables(const Object* object);
1501 	void updateSelectionRenderables(const Object* object);
1502 	void removeSelectionRenderables(const Object* object);
1503 
1504 	static void initStatic();
1505 
1506 	QExplicitlySharedDataPointer<MapColorSet> color_set;
1507 	bool has_spot_colors;
1508 	QString symbol_set_id;
1509 	SymbolVector symbols;
1510 	mutable qreal symbol_icon_scale = 0;
1511 	TemplateVector templates;
1512 	TemplateVector closed_templates;
1513 	int first_front_template = 0;		// index of the first template in templates which should be drawn in front of the map
1514 	PartVector parts;
1515 	ObjectSelection object_selection;
1516 	Object* first_selected_object = nullptr;
1517 	QScopedPointer<UndoManager> undo_manager;
1518 	std::size_t current_part_index = 0;
1519 	WidgetVector widgets;
1520 	QScopedPointer<MapRenderables> renderables;
1521 	QScopedPointer<MapRenderables> selection_renderables;
1522 
1523 	QString map_notes;
1524 
1525 	QScopedPointer<Georeferencing> georeferencing;
1526 
1527 	MapGrid grid;
1528 
1529 	int renderable_options;
1530 
1531 	QScopedPointer<MapPrinterConfig> printer_config;
1532 
1533 	bool image_template_use_meters_per_pixel;
1534 	double image_template_meters_per_pixel;
1535 	double image_template_dpi;
1536 	double image_template_scale;
1537 
1538 	bool colors_dirty;				// are there unsaved changes for the colors?
1539 	bool symbols_dirty;				//    ... for the symbols?
1540 	bool templates_dirty;			//    ... for the templates?
1541 	bool objects_dirty;				//    ... for the objects?
1542 	bool other_dirty;				//    ... for any other settings?
1543 	bool unsaved_changes;			// are there unsaved changes for any component?
1544 
1545 	std::set<Object*> irregular_objects;
1546 
1547 	// Static
1548 
1549 	static bool static_initialized;
1550 	static MapColor covering_white;
1551 	static MapColor covering_red;
1552 	static MapColor undefined_symbol_color;
1553 	static MapColor registration_color;
1554 	static LineSymbol* covering_white_line;
1555 	static LineSymbol* covering_red_line;
1556 	static LineSymbol* undefined_line;
1557 	static PointSymbol* undefined_point;
1558 	static TextSymbol* undefined_text;
1559 	static CombinedSymbol* covering_combined_line;
1560 };
1561 
1562 
1563 
1564 // ### Map inline code ###
1565 
1566 inline
getNumColors()1567 int Map::getNumColors() const
1568 {
1569 	return (int)color_set->colors.size();
1570 }
1571 
1572 inline
getMapColor(int i)1573 MapColor* Map::getMapColor(int i)
1574 {
1575 	return const_cast<MapColor*>(static_cast<const Map*>(this)->getMapColor(i));
1576 }
1577 
1578 inline
getMapColor(int i)1579 const MapColor* Map::getMapColor(int i) const
1580 {
1581 	if (0 <= i && i < (int)color_set->colors.size())
1582 	{
1583 		return color_set->colors[i];
1584 	}
1585 	return nullptr;
1586 }
1587 
1588 inline
getColor(int i)1589 const MapColor* Map::getColor(int i) const
1590 {
1591 	if (0 <= i && i < (int)color_set->colors.size())
1592 	{
1593 		return color_set->colors[i];
1594 	}
1595 	else switch (i)
1596 	{
1597 		case -1005:
1598 			return getCoveringRed();
1599 		case -1000:
1600 			return getCoveringWhite();
1601 		case -900:
1602 			return getRegistrationColor();
1603 		case -500:
1604 			return getUndefinedColor();
1605 		default:
1606 			return nullptr;
1607 	}
1608 }
1609 
1610 
1611 
1612 inline
symbolSetId()1613 QString Map::symbolSetId() const
1614 {
1615 	return symbol_set_id;
1616 }
1617 
1618 
1619 inline
getNumSymbols()1620 int Map::getNumSymbols() const
1621 {
1622 	return (int)symbols.size();
1623 }
1624 
1625 template<typename T>
sortSymbols(T compare)1626 void Map::sortSymbols(T compare)
1627 {
1628 	std::stable_sort(symbols.begin(), symbols.end(), compare);
1629 	// TODO: emit symbolChanged(pos, symbol); ? s/b same choice as for moveSymbol()
1630 	setSymbolsDirty();
1631 }
1632 
1633 inline
getNumTemplates()1634 int Map::getNumTemplates() const
1635 {
1636 	return templates.size();
1637 }
1638 
1639 inline
getTemplate(int i)1640 const Template*Map::getTemplate(int i) const
1641 {
1642 	return templates[i];
1643 }
1644 
1645 inline
getTemplate(int i)1646 Template*Map::getTemplate(int i)
1647 {
1648 	return templates[i];
1649 }
1650 
1651 inline
setFirstFrontTemplate(int pos)1652 void Map::setFirstFrontTemplate(int pos)
1653 {
1654 	first_front_template = pos;
1655 }
1656 
1657 inline
getFirstFrontTemplate()1658 int Map::getFirstFrontTemplate() const
1659 {
1660 	return first_front_template;
1661 }
1662 
1663 inline
getNumClosedTemplates()1664 int Map::getNumClosedTemplates() const
1665 {
1666 	return (int)closed_templates.size();
1667 }
1668 
1669 inline
getClosedTemplate(int i)1670 const Template* Map::getClosedTemplate(int i) const
1671 {
1672 	return closed_templates[i];
1673 }
1674 
1675 inline
getClosedTemplate(int i)1676 Template* Map::getClosedTemplate(int i)
1677 {
1678 	return closed_templates[i];
1679 }
1680 
1681 inline
undoManager()1682 UndoManager& Map::undoManager()
1683 {
1684 	return const_cast<UndoManager&>(static_cast<const Map*>(this)->undoManager());
1685 }
1686 
1687 inline
undoManager()1688 const UndoManager& Map::undoManager() const
1689 {
1690 	return *(undo_manager.data());
1691 }
1692 
1693 inline
getNumParts()1694 int Map::getNumParts() const
1695 {
1696 	return parts.size();
1697 }
1698 
1699 inline
getPart(std::size_t i)1700 MapPart* Map::getPart(std::size_t i) const
1701 {
1702 	return parts[i];
1703 }
1704 
1705 inline
getCurrentPart()1706 MapPart* Map::getCurrentPart() const
1707 {
1708 	return parts[current_part_index];
1709 }
1710 
1711 inline
setCurrentPart(MapPart * part)1712 void Map::setCurrentPart(MapPart* part)
1713 {
1714 	setCurrentPartIndex(findPartIndex(part));
1715 }
1716 
1717 inline
getCurrentPartIndex()1718 std::size_t Map::getCurrentPartIndex() const
1719 {
1720 	return current_part_index;
1721 }
1722 
1723 inline
selectedObjects()1724 const Map::ObjectSelection& Map::selectedObjects() const
1725 {
1726 	return object_selection;
1727 }
1728 
1729 inline
getNumSelectedObjects()1730 int Map::getNumSelectedObjects() const
1731 {
1732 	return (int)object_selection.size();
1733 }
1734 
1735 inline
selectedObjectsBegin()1736 Map::ObjectSelection::const_iterator Map::selectedObjectsBegin() const
1737 {
1738 	return object_selection.cbegin();
1739 }
1740 
1741 inline
selectedObjectsEnd()1742 Map::ObjectSelection::const_iterator Map::selectedObjectsEnd() const
1743 {
1744 	return object_selection.cend();
1745 }
1746 
1747 inline
getFirstSelectedObject()1748 const Object* Map::getFirstSelectedObject() const
1749 {
1750 	return first_selected_object;
1751 }
1752 
1753 inline
getFirstSelectedObject()1754 Object* Map::getFirstSelectedObject()
1755 {
1756 	return first_selected_object;
1757 }
1758 
1759 inline
getMapNotes()1760 const QString& Map::getMapNotes() const
1761 {
1762 	return map_notes;
1763 }
1764 
1765 inline
getGeoreferencing()1766 const Georeferencing& Map::getGeoreferencing() const
1767 {
1768 	return *georeferencing;
1769 }
1770 
1771 inline
getGrid()1772 const MapGrid& Map::getGrid() const
1773 {
1774 	return grid;
1775 }
1776 
1777 inline
renderableOptions()1778 int Map::renderableOptions() const
1779 {
1780 	return renderable_options;
1781 }
1782 
1783 inline
hasPrinterConfig()1784 bool Map::hasPrinterConfig() const noexcept
1785 {
1786 	return !printer_config.isNull();
1787 }
1788 
1789 inline
hasUnsavedChanges()1790 bool Map::hasUnsavedChanges() const
1791 {
1792 	return unsaved_changes;
1793 }
1794 
1795 inline
areColorsDirty()1796 bool Map::areColorsDirty() const
1797 {
1798 	return colors_dirty;
1799 }
1800 
1801 inline
areSymbolsDirty()1802 bool Map::areSymbolsDirty() const
1803 {
1804 	return symbols_dirty;
1805 }
1806 
1807 inline
areTemplatesDirty()1808 bool Map::areTemplatesDirty() const
1809 {
1810 	return templates_dirty;
1811 }
1812 
1813 inline
areObjectsDirty()1814 bool Map::areObjectsDirty() const
1815 {
1816 	return objects_dirty;
1817 }
1818 
1819 inline
isOtherDirty()1820 bool Map::isOtherDirty() const
1821 {
1822 	return other_dirty;
1823 }
1824 
1825 inline
getCoveringRed()1826 const MapColor* Map::getCoveringRed()
1827 {
1828 	return &covering_red;
1829 }
1830 
1831 inline
getCoveringWhite()1832 const MapColor* Map::getCoveringWhite()
1833 {
1834 	return &covering_white;
1835 }
1836 
1837 inline
getUndefinedColor()1838 const MapColor* Map::getUndefinedColor()
1839 {
1840 	return &undefined_symbol_color;
1841 }
1842 
1843 inline
getRegistrationColor()1844 const MapColor* Map::getRegistrationColor()
1845 {
1846 	return &registration_color;
1847 }
1848 
1849 inline
getCoveringWhiteLine()1850 LineSymbol* Map::getCoveringWhiteLine()
1851 {
1852 	return covering_white_line;
1853 }
1854 
1855 inline
getCoveringRedLine()1856 LineSymbol* Map::getCoveringRedLine()
1857 {
1858 	return covering_red_line;
1859 }
1860 
1861 inline
getCoveringCombinedLine()1862 CombinedSymbol* Map::getCoveringCombinedLine()
1863 {
1864 	return covering_combined_line;
1865 }
1866 
1867 inline
getUndefinedLine()1868 LineSymbol* Map::getUndefinedLine()
1869 {
1870 	return undefined_line;
1871 }
1872 
1873 inline
getUndefinedPoint()1874 PointSymbol* Map::getUndefinedPoint()
1875 {
1876 	return undefined_point;
1877 }
1878 
1879 inline
getUndefinedText()1880 TextSymbol* Map::getUndefinedText()
1881 {
1882 	return undefined_text;
1883 }
1884 
1885 
1886 }  // namespace OpenOrienteering
1887 
1888 
1889 Q_DECLARE_METATYPE(const OpenOrienteering::Map*)
1890 
1891 Q_DECLARE_OPERATORS_FOR_FLAGS(OpenOrienteering::Map::ImportMode)
1892 
1893 
1894 #endif
1895