1 /*
2  *    Copyright 2012, 2013, 2014 Thomas Schöps
3  *    Copyright 2013-2017 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_EDITOR_H
23 #define OPENORIENTEERING_MAP_EDITOR_H
24 
25 #include <memory>
26 #include <vector>
27 
28 #include <QClipboard>
29 #include <QHash>
30 #include <QObject>
31 #include <QPointer>
32 #include <QScopedPointer>
33 #include <QString>
34 #include <QTimer>
35 
36 #include "core/map.h"
37 #include "gui/main_window_controller.h"
38 
39 class QAction;
40 class QByteArray;
41 class QComboBox;
42 class QDockWidget;
43 class QFrame;
44 class QKeyEvent;
45 class QLabel;
46 class QMenu;
47 class QSignalMapper;
48 // IWYU pragma: no_forward_declare QString
49 class QToolBar;
50 class QToolButton;
51 class QWidget;
52 
53 namespace OpenOrienteering {
54 
55 class ActionGridBar;
56 class CompassDisplay;
57 class EditorDockWidget;
58 class FileFormat;
59 class GPSDisplay;
60 class GPSTemporaryMarkers;
61 class GPSTrackRecorder;
62 class GeoreferencingDialog;
63 class MainWindow;
64 class MapEditorActivity;
65 class MapEditorTool;
66 class MapFindFeature;
67 class MapView;
68 class MapWidget;
69 class PrintWidget;
70 class ReopenTemplateDialog;
71 class Symbol;
72 class SymbolWidget;
73 class Template;
74 class TemplateListWidget;
75 class TemplatePositionDockWidget;
76 
77 
78 /**
79  * MainWindowController for editing a map.
80  *
81  * Creates menus and toolbars, manages editing tools,
82  * dock widgets, and much more.
83  */
84 class MapEditorController : public MainWindowController
85 {
86 friend class Map;
87 Q_OBJECT
88 public:
89 	/** See MapEditorController constructor. */
90 	enum OperatingMode
91 	{
92 		MapEditor = 0,
93 		SymbolEditor = 1
94 	};
95 
96 	/**
97 	 * Constructs a new MapEditorController for a map.
98 	 *
99 	 * @param mode Normally, MapEditor should be used. However, as a HACK the
100 	 *     MapEditorController is also used in the symbol editor for the preview.
101 	 *     In this case, SymbolEditor is passed to disable showing the menus,
102 	 *     toolbars, etc.
103 	 * @param map       A Map which is to be edited by the controller.
104 	 * @param map_view  A MapView for the given map.
105 	 *
106 	 * \todo Review/remove mode hack.
107 	 * \todo Document and fix ownership of map and map_view. Double deletes waiting...
108 	 */
109 	MapEditorController(OperatingMode mode, Map* map = nullptr, MapView* map_view = nullptr);
110 
111 	/** Destroys the MapEditorController. */
112 	~MapEditorController() override;
113 
114 	/**
115 	 * In SymbolEditor mode, this controller doesn't want a menu bar.
116 	 */
117 	bool menuBarVisible() override;
118 
119 	/** Returns if the editor is in mobile mode. */
120 	bool isInMobileMode() const;
121 
122 	/**
123 	 * Changes to new_tool as the new active tool.
124 	 * If there is a current tool before, calls deleteLater() on it.
125 	 * new_tool may be nullptr, but it is unusual to have no active tool, so
126 	 * consider setEditTool() instead.
127 	 */
128 	void setTool(MapEditorTool* new_tool);
129 
130 	/**
131 	 * Shortcut to change to the point edit tool as new active tool.
132 	 * See setTool().
133 	 */
134 	void setEditTool();
135 
136 	/**
137 	 * Sets new_override_tool as the new active override tool.
138 	 * This takes precedence over all tools set via setTool().
139 	 * new_override_tool may be nullptr, which disables using an override tool
140 	 * and re-enables the normal tool set via setTool().
141 	 */
142 	void setOverrideTool(MapEditorTool* new_override_tool);
143 
144 	/** Returns the current tool. */
getTool()145 	inline MapEditorTool* getTool() const {return current_tool;}
146 
147 	/** Returns the default drawing tool for a given symbol. */
148 	MapEditorTool* getDefaultDrawToolForSymbol(const Symbol* symbol);
149 
150 
151 	/**
152 	 * @brief Returns the active symbol, or nullptr.
153 	 *
154 	 * The active symbol is the single symbol which is to be used by drawing
155 	 * tools and actions.
156 	 *
157 	 * It there is no active symbol, this function returns nullptr.
158 	 */
159 	Symbol* activeSymbol() const;
160 
161 
162 	/**
163 	 * If this is set to true (usually by the current tool),
164 	 * undo/redo and saving the map is deactivated.
165 	 *
166 	 * This is important if the map is in an "unstable" state temporarily.
167 	 */
168 	void setEditingInProgress(bool value);
169 
170 	/**
171 	 * Returns true when editing is in progress.
172 	 * @see setEditingInProgress
173 	 */
174 	bool isEditingInProgress() const override;
175 
176 	/**
177 	 * Adds a a floating dock widget to the main window.
178 	 * Adjusts some geometric properties.
179 	 */
180 	void addFloatingDockWidget(QDockWidget* dock_widget);
181 
182 	/**
183 	 * Sets the current editor activity.
184 	 * new_activity may be nullptr to disable the current editor activity.
185 	 */
186 	void setEditorActivity(MapEditorActivity* new_activity);
187 
188 	/** Returns the current editor activity. */
getEditorActivity()189 	inline MapEditorActivity* getEditorActivity() const {return editor_activity;}
190 
191 	/** Returns the map on which this controller operates. */
getMap()192 	inline Map* getMap() const {return map;}
193 	/** Returns the main map widget (which is currently the only map widget). */
getMainWidget()194 	inline MapWidget* getMainWidget() const {return map_widget;}
195 	/** Returns this controller's symbol widget, where the symbol selection happens. */
getSymbolWidget()196 	inline SymbolWidget* getSymbolWidget() const {return symbol_widget;}
197 
198 	/** Returns if a template position dock widget exists for a template. */
existsTemplatePositionDockWidget(Template * temp)199 	inline bool existsTemplatePositionDockWidget(Template* temp) const {return template_position_widgets.contains(temp);}
200 	/** Returns the template position dock widget for a template. */
getTemplatePositionDockWidget(Template * temp)201 	inline TemplatePositionDockWidget* getTemplatePositionDockWidget(Template* temp) const {return template_position_widgets.value(temp);}
202 	/** Adds a template position dock widget for the given template. */
203 	void addTemplatePositionDockWidget(Template* temp);
204 	/**
205 	 * Removes the template position dock widget for the template.
206 	 *
207 	 * Should be called by the dock widget if it is closed or the
208 	 * template deleted; deletes the dock widget.
209 	 */
210 	void removeTemplatePositionDockWidget(Template* temp);
211 
212 
213 	/**
214 	 * Shows the given widget in a popup window with specified title.
215 	 *
216 	 * In the desktop version, the widget is shown inside a dock widget.
217 	 * In the mobile version, the widget is shown as a popup over the map,
218 	 * ignoring the title.
219 	 *
220 	 * Make sure that the child widget has a reasonable size hint.
221 	 */
222 	void showPopupWidget(QWidget* child_widget, const QString& title);
223 
224 	/**
225 	 * Deletes the given popup widget, which was previously shown with
226 	 * showPopupWidget().
227 	 */
228 	void deletePopupWidget(QWidget* child_widget);
229 
230 
231 	/**
232 	 * Returns the action identified by id if it exists, or nullptr.
233 	 * This allows the reuse of the controller's actions in dock widgets etc.
234 	 */
235 	QAction* getAction(const char* id);
236 
237 	/** Override from MainWindowController */
238 	bool saveTo(const QString& path, const FileFormat& format) override;
239 	/** Override from MainWindowController */
240 	bool exportTo(const QString& path, const FileFormat& format) override;
241 	/** Override from MainWindowController */
242 	bool loadFrom(const QString& path, const FileFormat& format, QWidget* dialog_parent = nullptr) override;
243 
244 	/** Override from MainWindowController */
245 	void attach(MainWindow* window) override;
246 	/** Override from MainWindowController */
247 	void detach() override;
248 
249 	/**
250 	 * @copybrief MainWindowController::keyPressEventFilter
251 	 * This implementation passes the event to MapWidget::keyPressEventFilter.
252 	 */
253 	bool keyPressEventFilter(QKeyEvent* event) override;
254 
255 	/**
256 	 * @copybrief MainWindowController::keyReleaseEventFilter
257 	 * This implementation passes the event to MapWidget::keyReleaseEventFilter.
258 	 */
259 	bool keyReleaseEventFilter(QKeyEvent* event) override;
260 
261 public slots:
262 	/**
263 	 * Lets the user export the map as geospatial vector data.
264 	 */
265 	void exportVector();
266 
267 	/**
268 	 * Makes the print/export dock widget visible, and configures it for
269 	 * the given task (which is of type PrintWidget::TaskFlags).
270 	 */
271 	void printClicked(int task);
272 
273 	/** Undoes the last object edit step. */
274 	void undo();
275 	/** Redoes the last object edit step */
276 	void redo();
277 	/** Cuts the selected object(s). */
278 	void cut();
279 	/** Copies the selected object(s). */
280 	void copy();
281 	/** Pastes the object(s) from the clipboard. */
282 	void paste();
283 	/** Empties the undo / redo history to save space. */
284 	void clearUndoRedoHistory();
285 
286 	/** Toggles visivbility of the map grid. */
287 	void showGrid();
288 	/** Shows the map grid configuration dialog. */
289 	void configureGrid();
290 
291 	/** Activates the pan tool. */
292 	void pan();
293 	/** Moves view to GPS position. */
294 	void moveToGpsPos();
295 	/** Zooms in in the current map widget. */
296 	void zoomIn();
297 	/** Zooms out in the current map widget. */
298 	void zoomOut();
299 	/** Shows the dialog to set a custom zoom factor in the current map widget. */
300 	void setCustomZoomFactorClicked();
301 
302 	/** Sets the hatch areas view option. */
303 	void hatchAreas(bool checked);
304 	/** Sets the baseline view option. */
305 	void baselineView(bool checked);
306 	/** Sets the "hide all templates" view option. */
307 	void hideAllTemplates(bool checked);
308 	/** Sets the overprinting simulation view option. */
309 	void overprintingSimulation(bool checked);
310 
311 	/** Adjusts the coordinates display of the map widget to the selected option. */
312 	void coordsDisplayChanged();
313 	/** Copies the displayed coordinates to the clipboard. */
314 	void copyDisplayedCoords();
315 
316 	/** Shows or hides the symbol pane. */
317 	void showSymbolWindow(bool show);
318 	/** Shows or hides the color dock widget. */
319 	void showColorWindow(bool show);
320 	/** Shows a dialog for changing the symbol set ID. */
321 	void symbolSetIdClicked();
322 	/** Shows the "load symbols from" dialog. */
323 	void loadSymbolsFromClicked();
324 	/** Loads a CRT file and shows the symbol replacement dialog. */
325 	void loadCrtClicked();
326 	/** TODO: not implemented yet. */
327 	void loadColorsFromClicked();
328 	/** Shows the "scale all symbols" dialog. */
329 	void scaleAllSymbolsClicked();
330 
331 	/** Shows the ScaleMapDialog. */
332 	void scaleMapClicked();
333 	/** Shows the RotateMapDialog. */
334 	void rotateMapClicked();
335 	/** Shows the dialog to enter map notes. */
336 	void mapNotesClicked();
337 
338 	/** Shows or hides the template setup dock widget. */
339 	void showTemplateWindow(bool show);
340 	/** Shows a file selector to open a template. */
341 	void openTemplateClicked();
342 	/** Shows the ReopenTemplateDialog. */
343 	void reopenTemplateClicked();
344 	/** Adjusts action availability based on the presence of templates */
345 	void templateAvailabilityChanged();
346 	/** Adjusts action availability based on the presence of closed templates */
347 	void closedTemplateAvailabilityChanged();
348 
349 	/** Shows or hides the tags editor dock widget. */
350 	void showTagsWindow(bool show);
351 
352 	/** Shows the GeoreferencingDialog. */
353 	void editGeoreferencing();
354 
355 	/**
356 	 * Makes the editor aware of a change of the selected symbols.
357 	 */
358 	void selectedSymbolsChanged();
359 
360 	/**
361 	 * Makes the editor aware of a change of the selected object.
362 	 */
363 	void objectSelectionChanged();
364 
365 	/** Adjusts the enabled state of the undo / redo actions. */
366 	void undoStepAvailabilityChanged();
367 	/** Adjusts the enabled state of the paste action (specific signature required). */
368 	void clipboardChanged(QClipboard::Mode mode);
369 	/** Adjusts the enabled state of the paste action. */
370 	void updatePasteAvailability();
371 
372 	/**
373 	 * Checks the presence of spot colors,
374 	 * and to disables overprinting simulation if there are no spot colors.
375 	 */
376 	void spotColorPresenceChanged(bool has_spot_colors);
377 
378 	/** Adjusts the view in the current map widget to show the whole map. */
379 	void showWholeMap();
380 
381 	/** Activates the point edit tool. */
382 	void editToolClicked();
383 	/** Activates the line edit tool. */
384 	void editLineToolClicked();
385 	/** Activates the draw point tool. */
386 	void drawPointClicked();
387 	/** Activates the draw path tool. */
388 	void drawPathClicked();
389 	/** Activates the draw circle tool. */
390 	void drawCircleClicked();
391 	/** Activates the draw rectangle tool. */
392 	void drawRectangleClicked();
393 	/** Activates the draw freehand tool. */
394 	void drawFreehandClicked();
395 	/** Activates the draw fill tool. */
396 	void drawFillClicked();
397 	/** Activates the draw text tool. */
398 	void drawTextClicked();
399 
400 	/** Deletes the selected object(s) */
401 	void deleteClicked();
402 	/** Duplicates the selected object(s) */
403 	void duplicateClicked();
404 	/** Switches the symbol of the selected object(s) to the selected symbol. */
405 	void switchSymbolClicked();
406 	/** Creates duplicates of the selected object(s) and assigns them the selected symbol. */
407 	void fillBorderClicked();
408 	/** Selects all objects with the selected symbol(s) */
409 	void selectObjectsClicked(bool select_exclusively);
410 	/** Deselects all objects with the selected symbol(s) */
411 	void deselectObjectsClicked();
412 
413 	/** Selects all objects in the current map part. */
414 	void selectAll();
415 	/** Clears the object selection. */
416 	void selectNothing();
417 	/** Inverts in the object selection in the current map part. */
418 	void invertSelection();
419 	/** Selects all objects having the current selected symbols. */
420 	void selectByCurrentSymbols();
421 
422 	/**
423 	 * Reverses the selected object(s) direcction(s),
424 	 * thus switching dash directions for lines.
425 	 */
426 	void switchDashesClicked();
427 	/** Connects close endpoints of selected lines */
428 	void connectPathsClicked();
429 	/** Activates the cut tool */
430 	void cutClicked();
431 	/** Activates the cut hole tool */
432 	void cutHoleClicked();
433 	/** Activates the cut circular hole tool */
434 	void cutHoleCircleClicked();
435 	/** Activates the cut rectangular hole tool */
436 	void cutHoleRectangleClicked();
437 	/** Activates the rotate tool */
438 	void rotateClicked();
439 	/** Activates the rotate pattern tool */
440 	void rotatePatternClicked();
441 	/** Activates the scale tool */
442 	void scaleClicked();
443 	/** Shows or hides the MeasureWidget */
444 	void measureClicked(bool checked);
445 	/** Calculates the union of selected same-symbol area objects */
446 	void booleanUnionClicked();
447 	/** Calculates the intersection of selected same-symbol area objects */
448 	void booleanIntersectionClicked();
449 	/** Calculates the difference of selected area objects from the first selected area object */
450 	void booleanDifferenceClicked();
451 	/** Calculates the boolean XOr of selected same-symbol area objects */
452 	void booleanXOrClicked();
453 	/** Merges holes of the (single) selected area object */
454 	void booleanMergeHolesClicked();
455 	/** Converts selected polygonal paths to curves */
456 	void convertToCurvesClicked();
457 	/** Tries to remove points of selected paths while retaining their shape */
458 	void simplifyPathClicked();
459 	/** Activates the physical cutout tool */
460 	void cutoutPhysicalClicked();
461 	/** Activates the physical cutout tool (inversed) */
462 	void cutawayPhysicalClicked();
463 	/** Executes the "distribute points along path" action.
464 	 *  The prerequisites for using the tool must be given. */
465 	void distributePointsClicked();
466 
467 	/** Shows or hides the paint-on-template widget */
468 	void paintOnTemplateClicked(bool checked);
469 	/** Shows the template selection dialog for for the paint-on-template functionality */
470 	void paintOnTemplateSelectClicked();
471 
472 	/** Enables or disables GPS display. */
473 	void enableGPSDisplay(bool enable);
474 	/** Enables or disables showing distance rings when GPS display is active. */
475 	void enableGPSDistanceRings(bool enable);
476 	/** Updates availability of the GPS point drawing tool. */
477 	void updateDrawPointGPSAvailability();
478 	/** Switches to the GPS point drawing tool. */
479 	void drawPointGPSClicked();
480 	/** Sets a temporary marker at the GPS position. */
481 	void gpsTemporaryPointClicked();
482 	/** Draws a temporary path at the GPS position. */
483 	void gpsTemporaryPathClicked(bool enable);
484 	/** Clears temporary GPS markers. */
485 	void gpsTemporaryClearClicked();
486 
487 	/** Enables or disables digital compass display. */
488 	void enableCompassDisplay(bool enable);
489 	/** Enables or disables map auto-rotation according to compass. */
490 	void alignMapWithNorth(bool enable);
491 	/** Called regularly after enabled with alignMapWithNorth() to update the map rotation. */
492 	void alignMapWithNorthUpdate();
493 
494 	/** For mobile UI: hides the top action bar. */
495 	void hideTopActionBar();
496 	/** For mobile UI: shows the top action bar again after hiding it. */
497 	void showTopActionBar();
498 	/** For mobile UI: shows the symbol selection screen. */
499 	void mobileSymbolSelectorClicked();
500 	/** Counterpart to mobileSymbolSelectorClicked(). */
501 	void mobileSymbolSelectorFinished();
502 
503 	/** Creates and adds a new map part */
504 	void addMapPart();
505 	/** Removes the current map part */
506 	void removeMapPart();
507 	/** Renames the current map part */
508 	void renameMapPart();
509 	/** Moves all selected objects to a different map part */
510 	void reassignObjectsToMapPart(int target);
511 	/** Merges the current map part with another one */
512 	void mergeCurrentMapPartTo(int target);
513 	/** Merges all map parts into the current one. */
514 	void mergeAllMapParts();
515 
516 	/** Updates action enabled states after a template has been added */
517 	void templateAdded(int pos, const OpenOrienteering::Template* temp);
518 	/** Updates action enabled states after a template has been deleted */
519 	void templateDeleted(int pos, const OpenOrienteering::Template* temp);
520 
521 	/** Shows the import file selector and imports the selected file, if any. */
522 	void importClicked();
523 
524 public:
525 	/**
526 	 * Imports another map into this map, after successful symbol replacement.
527 	 *
528 	 * The filepath given in crt_file_hint is used in addition (and preferred)
529 	 * to the symbol set IDs to locate a CRT file for initializing the
530 	 * replacement table.
531 	 *
532 	 * Returns true on success.
533 	 */
534 	bool importMapWithReplacement(
535 	        Map& imported_map,
536 	        Map::ImportMode mode,
537 	        const QString& crt_file_hint
538 	);
539 
540 	/**
541 	 * Imports another map into this map.
542 	 *
543 	 * This method changes the given 'other' map if the	maps' scales differ.
544 	 * This is an optimization for the use cases where temporary maps are
545 	 * created just for this kind of import.
546 	 *
547 	 * \see Map::importMap
548 	 */
549 	QHash<const Symbol*, Symbol*> importMap(
550 	        Map& other,
551 	        Map::ImportMode mode,
552 	        QWidget* dialog_parent,
553 	        std::vector<bool>* filter = nullptr,
554 	        int symbol_insert_pos = -1,
555 	        bool merge_duplicate_symbols = true
556 	);
557 
558 	/** Imports a track file (GPX) into the map */
559 	bool importGpxFile(const QString& filename);
560 	/** Imports a map file into the loaded map */
561 	bool importMapFile(const QString& filename, bool show_errors);
562 	/** Imports a data file supported by OGR into the map */
563 	bool importOgrFile(const QString& filename);
564 
565 public slots:
566 	/** Sets the enabled state of actions which change how the map is rendered,
567 	 *  such as with grid, with templates, with overprinting simulation. */
568 	void setViewOptionsEnabled(bool enabled = true);
569 
570 	/**
571 	 * Indicates a change of the current toolbar and dock widget positions,
572 	 * and schedules saving.
573 	 */
574 	void setWindowStateChanged();
575 
576 private:
577 	/**
578 	 * Immediately saves the window state if needed.
579 	 *
580 	 * This will save the current toolbar and dock widget positions if the
581 	 * window state is marked as changed.
582 	 * After saving, it marks the state as clean.
583 	 */
584 	void saveWindowState();
585 
586 	/**
587 	 * Restores previously saved toolbar and dock widget positions.
588 	 */
589 	void restoreWindowState();
590 
591 signals:
592 	/**
593 	 * @brief Indicates a change of the active symbol.
594 	 * @param symbol The new active symbol, or nullptr.
595 	 */
596 	void activeSymbolChanged(const OpenOrienteering::Symbol* symbol);
597 
598 	void templatePositionDockWidgetClosed(OpenOrienteering::Template* temp);
599 
600 protected:
601 	/**
602 	 * Adjusts the enabled state of various actions
603 	 * after the selected symbol(s) have changed.
604 	 *
605 	 * In addition, it disables actions as long as some editing is in progress.
606 	 *
607 	 * The caller shall also call updateSymbolAndObjectDependentActions().
608 	 */
609 	void updateSymbolDependentActions();
610 
611 	/**
612 	 * Adjusts the enabled state of various actions
613 	 * after the selected object(s) have changed.
614 	 *
615 	 * In addition, it disables actions as long as some editing is in progress.
616 	 *
617 	 * The caller shall also call updateSymbolAndObjectDependentActions().
618 	 */
619 	void updateObjectDependentActions();
620 
621 	/**
622 	 * Adjusts the enabled state of various actions
623 	 * after the selected symbol(s) or object(s) have changed.
624 	 *
625 	 * In addition, it disables actions as long as some editing is in progress.
626 	 */
627 	void updateSymbolAndObjectDependentActions();
628 
629 protected slots:
630 	void projectionChanged();
631 	void georeferencingDialogFinished();
632 
633 	/**
634 	 * Sets the map's current part.
635 	 */
636 	void changeMapPart(int index);
637 
638 	/**
639 	 * Updates all UI components related to map parts.
640 	 */
641 	void updateMapPartsUI();
642 
643 private:
644 	void setMapAndView(Map* map, MapView* map_view);
645 
646 	/// Updates enabled state of all widgets
647 	void updateWidgets();
648 
649 	void createSymbolWidget(QWidget* parent = nullptr);
650 
651 	void createColorWindow();
652 
653 	void createTemplateWindow();
654 
655 	void createTagEditor();
656 
657 	QAction* newAction(const char* id, const QString& tr_text, QObject* receiver, const char* slot, const char* icon = nullptr, const QString& tr_tip = QString{}, const char* whats_this_link = nullptr);
658 	QAction* newCheckAction(const char* id, const QString& tr_text, QObject* receiver, const char* slot, const char* icon = nullptr, const QString& tr_tip = QString{}, const char* whats_this_link = nullptr);
659 	QAction* newToolAction(const char* id, const QString& tr_text, QObject* receiver, const char* slot, const char* icon = nullptr, const QString& tr_tip = QString{}, const char* whats_this_link = nullptr);
660 	QAction* findAction(const char* id);
661 	void assignKeyboardShortcuts();
662 	void createActions();
663 	void createMenuAndToolbars();
664 	void createMobileGUI();
665 
666 	void paintOnTemplate(Template* temp);
667 	void finishPaintOnTemplate();
668 
669 	void doUndo(bool redo);
670 
671 	Map* map;
672 	MapView* main_view;
673 	MapWidget* map_widget;
674 
675 	OperatingMode mode;
676 	bool mobile_mode;
677 	bool window_state_changed = false;
678 
679 	MapEditorTool* current_tool;
680 	MapEditorTool* override_tool;
681 	MapEditorActivity* editor_activity;
682 
683 	Symbol* active_symbol;
684 
685 	bool editing_in_progress;
686 
687 	// Action handling
688 	QHash<QByteArray, QAction*> actionsById;
689 
690 	EditorDockWidget* print_dock_widget;
691 	PrintWidget* print_widget;
692 
693 	QAction* print_act;
694 	QAction* export_image_act;
695 	QAction* export_pdf_act;
696 	QAction* export_vector_act;
697 
698 	QAction* undo_act;
699 	QAction* redo_act;
700 	QAction* cut_act;
701 	QAction* copy_act;
702 	QAction* paste_act;
703 	QAction* delete_act;
704 	QAction* select_all_act;
705 	QAction* select_nothing_act;
706 	QAction* invert_selection_act;
707 	QAction* select_by_current_symbol_act;
708 	std::unique_ptr<MapFindFeature> find_feature;
709 	QAction* clear_undo_redo_history_act;
710 
711 	QAction* pan_act;
712 	QAction* move_to_gps_pos_act;
713 	QAction* zoom_in_act;
714 	QAction* zoom_out_act;
715 	QAction* show_all_act;
716 	QAction* fullscreen_act;
717 	QAction* custom_zoom_act;
718 	QAction* show_grid_act;
719 	QAction* configure_grid_act;
720 	QAction* hatch_areas_view_act;
721 	QAction* baseline_view_act;
722 	QAction* hide_all_templates_act;
723 	QAction* overprinting_simulation_act;
724 
725 	QAction* map_coordinates_act;
726 	QAction* projected_coordinates_act;
727 	QAction* geographic_coordinates_act;
728 	QAction* geographic_coordinates_dms_act;
729 
730 	QMenu* toolbars_menu = nullptr;
731 
732 	QAction* scale_all_symbols_act;
733 	QAction* georeferencing_act;
734 	QAction* scale_map_act;
735 	QAction* rotate_map_act;
736 	QAction* map_notes_act;
737 	QAction* symbol_set_id_act;
738 
739 	QAction* color_window_act;
740 	QPointer<EditorDockWidget> color_dock_widget;
741 	QAction* load_symbols_from_act;
742 	QAction* load_crt_act;
743 
744 	QAction* symbol_window_act;
745 	EditorDockWidget* symbol_dock_widget;
746 	SymbolWidget* symbol_widget;
747 
748 	QAction* template_window_act;
749 	QPointer<QWidget> template_dock_widget;
750 	TemplateListWidget* template_list_widget;
751 	QAction* open_template_act;
752 	QAction* reopen_template_act;
753 
754 	QAction* tags_window_act;
755 	QPointer<EditorDockWidget> tags_dock_widget;
756 
757 	QAction* edit_tool_act;
758 	QAction* edit_line_tool_act;
759 	QAction* draw_point_act;
760 	QAction* draw_path_act;
761 	QAction* draw_circle_act;
762 	QAction* draw_rectangle_act;
763 	QAction* draw_freehand_act;
764 	QAction* draw_fill_act;
765 	QAction* draw_text_act;
766 
767 	QAction* duplicate_act;
768 	QAction* switch_symbol_act;
769 	QAction* fill_border_act;
770 	QAction* switch_dashes_act;
771 	QAction* connect_paths_act;
772 	QAction* cut_tool_act;
773 	QMenu* cut_hole_menu;
774 	QAction* cut_hole_act;
775 	QAction* cut_hole_circle_act;
776 	QAction* cut_hole_rectangle_act;
777 	QAction* rotate_act;
778 	QAction* rotate_pattern_act;
779 	QAction* scale_act;
780 	QAction* measure_act;
781 	EditorDockWidget* measure_dock_widget;
782 	QAction* boolean_union_act;
783 	QAction* boolean_intersection_act;
784 	QAction* boolean_difference_act;
785 	QAction* boolean_xor_act;
786 	QAction* boolean_merge_holes_act;
787 	QAction* convert_to_curves_act;
788 	QAction* simplify_path_act;
789 	QAction* cutout_physical_act;
790 	QAction* cutaway_physical_act;
791 	QAction* distribute_points_act;
792 
793 	QAction* paint_on_template_act;
794 	QAction* paint_on_template_settings_act;
795 	Template* last_painted_on_template;
796 
797 	QAction* touch_cursor_action;
798 	QAction* gps_display_action;
799 	QAction* gps_distance_rings_action;
800 	QAction* draw_point_gps_act;
801 	QAction* gps_temporary_point_act;
802 	QAction* gps_temporary_path_act;
803 	QAction* gps_temporary_clear_act;
804 	GPSTemporaryMarkers* gps_marker_display;
805 	GPSDisplay* gps_display;
806 	GPSTrackRecorder* gps_track_recorder;
807 	QAction* compass_action;
808 	CompassDisplay* compass_display;
809 	QAction* align_map_with_north_act;
810 	QTimer align_map_with_north_timer;
811 
812 	QAction* mappart_add_act;
813 	QAction* mappart_rename_act;
814 	QAction* mappart_remove_act;
815 	QAction* mappart_merge_act;
816 	QMenu* mappart_merge_menu;
817 	QMenu* mappart_move_menu;
818 
819 	QAction* import_act;
820 
821 	QFrame* statusbar_zoom_frame;
822 	QLabel* statusbar_cursorpos_label;
823 	QAction* copy_coords_act;
824 
825 	QToolBar* toolbar_view;
826 	QToolBar* toolbar_drawing;
827 	QToolBar* toolbar_editing;
828 	QToolBar* toolbar_advanced_editing;
829 	QToolBar* toolbar_mapparts = nullptr;
830 
831 	// For mobile UI
832 	ActionGridBar* bottom_action_bar;
833 	ActionGridBar* top_action_bar;
834 	QToolButton* show_top_bar_button;
835 	QAction* mobile_symbol_selector_action;
836 	QMenu* mobile_symbol_button_menu;
837 
838 	QPointer<QComboBox> mappart_selector_box;
839 
840 	QScopedPointer<GeoreferencingDialog> georeferencing_dialog;
841 	QScopedPointer<ReopenTemplateDialog> reopen_template_dialog;
842 
843 	QHash<Template*, TemplatePositionDockWidget*> template_position_widgets;
844 
845 	QSignalMapper* mappart_merge_mapper;
846 	QSignalMapper* mappart_move_mapper;
847 };
848 
849 
850 
851 //### MapEditorController inline code ###
852 
853 inline
activeSymbol()854 Symbol* MapEditorController::activeSymbol() const
855 {
856 	return active_symbol;
857 }
858 
859 
860 }  // namespace OpenOrienteering
861 
862 #endif
863