1 /* 2 * Copyright 2012, 2013 Thomas Schöps 3 * Copyright 2012-2015 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_GEOREFERENCING_DIALOG_H 23 #define OPENORIENTEERING_GEOREFERENCING_DIALOG_H 24 25 #include <vector> 26 27 #include <QDialog> 28 #include <QObject> 29 #include <QScopedPointer> 30 #include <QString> 31 32 #include "core/map_coord.h" 33 #include "tools/tool.h" 34 35 class QAction; 36 class QCursor; 37 class QCheckBox; 38 class QDialogButtonBox; 39 class QDoubleSpinBox; 40 class QLabel; 41 class QMouseEvent; 42 class QPushButton; 43 class QRadioButton; 44 class QNetworkReply; 45 class QWidget; 46 47 namespace OpenOrienteering { 48 49 class CRSSelector; 50 class Georeferencing; 51 class Map; 52 class MapEditorController; 53 class MapWidget; 54 55 56 /** 57 * A GeoreferencingDialog allows the user to adjust the georeferencing properties 58 * of a map. 59 */ 60 class GeoreferencingDialog : public QDialog 61 { 62 Q_OBJECT 63 public: 64 /** 65 * Constructs a new georeferencing dialog for the map handled by the given 66 * controller. The optional parameter initial allows to override the current 67 * properties of the map's georeferencing. The parameter 68 * allow_no_georeferencing determines if the okay button can 69 * be clicked while "- none -" is selected. 70 */ 71 GeoreferencingDialog(MapEditorController* controller, const Georeferencing* initial = nullptr, bool allow_no_georeferencing = true); 72 73 /** 74 * Constructs a new georeferencing dialog for the given map. The optional 75 * parameter initial allows to override the current properties of the map's 76 * georeferencing. Since the dialog will not know a MapEditorController, 77 * it will not allow to select a new reference point from the map. 78 * The parameter allow_no_georeferencing determines if the okay button can 79 * be clicked while "- none -" is selected. 80 */ 81 GeoreferencingDialog(QWidget* parent, Map* map, const Georeferencing* initial = nullptr, bool allow_no_georeferencing = true); 82 83 protected: 84 /** 85 * Constructs a new georeferencing dialog. 86 * 87 * The map parameter must not be nullptr, and it must not be a different 88 * map than the one handled by controller. 89 * 90 * @param parent A parent widget. 91 * @param controller A controller which operates on the map. 92 * @param map The map. 93 * @param initial An override of the map's georeferencing 94 * @param allow_no_georeferencing Determines if the okay button can be 95 * be clicked while "- none -" is selected. 96 */ 97 GeoreferencingDialog( 98 QWidget* parent, 99 MapEditorController* controller, 100 Map* map, 101 const Georeferencing* initial, 102 bool allow_no_georeferencing 103 ); 104 105 public: 106 /** 107 * Releases resources. 108 */ 109 ~GeoreferencingDialog() override; 110 111 112 /** 113 * Updates the dialog from georeferencing state changes. 114 */ 115 void georefStateChanged(); 116 117 /** 118 * Moves transformation properties from the georeferencing to the widgets. 119 */ 120 void transformationChanged(); 121 122 /** 123 * Moves projection properties from the georeferencing to the widgets. 124 */ 125 void projectionChanged(); 126 127 /** 128 * Updates the declination widget from the georeferencing. 129 */ 130 void declinationChanged(); 131 132 /** 133 * Updates the scale factor widget from the georeferencing. 134 */ 135 void auxiliaryFactorChanged(); 136 137 /** 138 * Sets visibility of scale compensation widgets. 139 */ 140 void showScaleChanged(bool checked); 141 142 /** 143 * Triggers an online request for the magnetic declination. 144 * 145 * @param no_confirm If true, the user will not be asked for confirmation. 146 */ 147 void requestDeclination(bool no_confirm = false); 148 149 /** 150 * Sets the map coordinates of the reference point 151 */ 152 void setMapRefPoint(const MapCoord& coords); 153 154 /** 155 * Activates the "keep projected reference point coordinates on CRS changes" radio button. 156 */ 157 void setKeepProjectedRefCoords(); 158 159 /** 160 * Activates the "keep geographic reference point coordinates on CRS changes" radio button. 161 */ 162 void setKeepGeographicRefCoords(); 163 164 /** 165 * Notifies the dialog that the active GeoreferencingTool was deleted. 166 */ 167 void toolDeleted(); 168 169 /** 170 * Opens this dialog's help page. 171 */ 172 void showHelp(); 173 174 /** 175 * Resets all input fields to the values in the map's Georeferencing. 176 * 177 * This will also reset initial values passed to the constructor. 178 */ 179 void reset(); 180 181 /** 182 * Pushes the changes from the dialog to the map's Georeferencing 183 * and closes the dialog. The dialog's result is set to QDialog::Accepted, 184 * and the active exec() function will return. 185 */ 186 void accept() override; 187 188 protected: 189 /** 190 * Updates enabled / disabled states of all widgets. 191 */ 192 void updateWidgets(); 193 194 /** 195 * Updates enabled / disabled state and text of the declination query button. 196 */ 197 void updateDeclinationButton(); 198 199 200 /** 201 * Notifies the dialog of a change in the CRS configuration. 202 */ 203 void crsEdited(); 204 205 /** 206 * Notifies the dialog of a change in the auxiliary scale factor. 207 */ 208 void auxiliaryFactorEdited(double value); 209 210 /** 211 * Updates the combined scale factor field from the underlying Georeferencing. 212 */ 213 void updateCombinedFactor(); 214 215 /** 216 * Hides the dialog and activates a GeoreferencingTool for selecting 217 * the reference point on the map. 218 */ 219 void selectMapRefPoint(); 220 221 /** 222 * Notifies the dialog of a change in the map reference point fields. 223 */ 224 void mapRefChanged(); 225 226 /** 227 * Notifies the dialog of a change in the easting / northing fields. 228 */ 229 void eastingNorthingEdited(); 230 231 /** 232 * Notifies the dialog of change of the keep-coords buttons. 233 */ 234 void keepCoordsChanged(); 235 236 /** 237 * Notifies the dialog of a change in the latitude / longitude fields. 238 */ 239 void latLonEdited(); 240 241 /** 242 * Notifies the dialog of a change in the declination field. 243 */ 244 void declinationEdited(double value); 245 246 /** 247 * Handles replies from the online declination service. 248 */ 249 void declinationReplyFinished(QNetworkReply* reply); 250 251 /** 252 * Updates the grivation field from the underlying Georeferencing. 253 */ 254 void updateGrivation(); 255 256 private: 257 /* Internal state */ 258 MapEditorController* const controller; 259 Map* const map; 260 const Georeferencing* initial_georef; 261 QScopedPointer<Georeferencing> georef; // A working copy of the current or given initial Georeferencing 262 bool allow_no_georeferencing; 263 bool tool_active; 264 bool declination_query_in_progress; 265 bool grivation_locked; 266 bool scale_factor_locked; 267 268 /* GUI elements */ 269 CRSSelector* crs_selector; 270 QLabel* status_label; 271 QLabel* status_field; 272 273 QDoubleSpinBox* map_x_edit; 274 QDoubleSpinBox* map_y_edit; 275 QPushButton* ref_point_button; 276 277 QLabel* projected_ref_label; 278 QDoubleSpinBox* easting_edit; 279 QDoubleSpinBox* northing_edit; 280 281 QDoubleSpinBox* lat_edit; 282 QDoubleSpinBox* lon_edit; 283 QLabel* show_refpoint_label; 284 QLabel* link_label; 285 286 QRadioButton* keep_projected_radio; 287 QRadioButton* keep_geographic_radio; 288 289 QDoubleSpinBox* declination_edit; 290 QPushButton* declination_button; 291 QLabel* grivation_label; 292 293 QCheckBox* show_scale_check; 294 std::vector<QWidget*> scale_widget_list; 295 QDoubleSpinBox* scale_factor_edit; 296 QLabel* combined_factor_display; 297 298 QDialogButtonBox* buttons_box; 299 QPushButton* reset_button; 300 }; 301 302 303 304 /** 305 * GeoreferencingTool is a helper to the GeoreferencingDialog which allows 306 * the user to select the position of the reference point on the map 307 * The GeoreferencingDialog hides when it activates this tool. The tool 308 * takes care of reactivating the dialog. 309 */ 310 class GeoreferencingTool : public MapEditorTool 311 { 312 Q_OBJECT 313 public: 314 /** 315 * Constructs a new tool for the given dialog and controller. 316 */ 317 GeoreferencingTool( 318 GeoreferencingDialog* dialog, 319 MapEditorController* controller, 320 QAction* action = nullptr 321 ); 322 323 /** 324 * Notifies the dialog that the tool is deleted. 325 */ 326 ~GeoreferencingTool() override; 327 328 /** 329 * Activates the tool. 330 */ 331 void init() override; 332 333 /** 334 * Consumes left and right clicks. They are handled in mouseReleaseEvent. 335 */ 336 bool mousePressEvent(QMouseEvent* event, const MapCoordF& map_coord, MapWidget* widget) override; 337 338 /** 339 * Reacts to the user activity by sending the reference point coordinates 340 * to the dialog (on left click) and reactivating the dialog. 341 */ 342 bool mouseReleaseEvent(QMouseEvent* event, const MapCoordF& map_coord, MapWidget* widget) override; 343 344 /** 345 * Returns the mouse cursor that will be shown when the tool is active. 346 */ 347 const QCursor& getCursor() const override; 348 349 private: 350 GeoreferencingDialog* const dialog; 351 }; 352 353 354 } // namespace OpenOrienteering 355 356 #endif 357