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 ®istration_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