/* * Copyright 2014 Thomas Schöps * Copyright 2014, 2015 Kai Pastor * * This file is part of OpenOrienteering. * * OpenOrienteering is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenOrienteering is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenOrienteering. If not, see . */ #include "draw_point_gps_tool.h" #include #include #include #include #include #include #include #include #include #include "core/map.h" #include "core/map_coord.h" #include "core/map_view.h" #include "core/objects/object.h" #include "core/renderables/renderable.h" #include "core/symbols/point_symbol.h" #include "core/symbols/symbol.h" #include "gui/map/map_editor.h" #include "gui/map/map_widget.h" #include "sensors/gps_display.h" #include "tools/tool.h" #include "undo/object_undo.h" #include "util/util.h" namespace OpenOrienteering { DrawPointGPSTool::DrawPointGPSTool(GPSDisplay* gps_display, MapEditorController* editor, QAction* tool_action) : MapEditorToolBase(QCursor(QPixmap(QString::fromLatin1(":/images/cursor-draw-point.png")), 11, 11), DrawPoint, editor, tool_action) , renderables(new MapRenderables(map())) { useTouchCursor(false); preview_object = nullptr; if (gps_display->hasValidPosition()) newGPSPosition(gps_display->getLatestGPSCoord(), gps_display->getLatestGPSCoordAccuracy()); connect(gps_display, &GPSDisplay::mapPositionUpdated, this, &DrawPointGPSTool::newGPSPosition); connect(editor, &MapEditorController::activeSymbolChanged, this, &DrawPointGPSTool::activeSymbolChanged); connect(map(), &Map::symbolDeleted, this, &DrawPointGPSTool::symbolDeleted); } DrawPointGPSTool::~DrawPointGPSTool() { if (preview_object) { renderables->removeRenderablesOfObject(preview_object, false); delete preview_object; } if (help_label) editor->deletePopupWidget(help_label); } void DrawPointGPSTool::initImpl() { if (editor->isInMobileMode()) { help_label = new QLabel(tr("Touch the map to finish averaging")); editor->showPopupWidget(help_label, QString{}); } } void DrawPointGPSTool::newGPSPosition(const MapCoordF& coord, float accuracy) { auto point = reinterpret_cast(editor->activeSymbol()); // Calculate weight from accuracy. This is arbitrarily chosen. float weight; if (accuracy < 0) weight = 1; // accuracy unknown else weight = 1.0f / qMax(0.5f, accuracy); if (! preview_object) { // This is the first received position. preview_object = new PointObject(point); x_sum = weight * coord.x(); y_sum = weight * coord.y(); weights_sum = weight; } else { renderables->removeRenderablesOfObject(preview_object, false); if (preview_object->getSymbol() != point) { bool success = preview_object->setSymbol(point, true); Q_ASSERT(success); Q_UNUSED(success); } x_sum += weight * coord.x(); y_sum += weight * coord.y(); weights_sum += weight; } MapCoordF avg_position(x_sum / weights_sum, y_sum / weights_sum); preview_object->setPosition(avg_position); preview_object->setRotation(0); preview_object->update(); renderables->insertRenderablesOfObject(preview_object); updateDirtyRect(); } void DrawPointGPSTool::clickRelease() { if (! preview_object) return; auto point = preview_object->duplicate()->asPoint(); int index = map()->addObject(point); map()->clearObjectSelection(false); map()->addObjectToSelection(point, true); map()->setObjectsDirty(); map()->clearDrawingBoundingBox(); renderables->removeRenderablesOfObject(preview_object, false); auto undo_step = new DeleteObjectsUndoStep(map()); undo_step->addObject(index); map()->push(undo_step); setEditingInProgress(false); deactivate(); } bool DrawPointGPSTool::keyPress(QKeyEvent* event) { switch (event->key()) { case Qt::Key_Tab: deactivate(); return true; } return false; } void DrawPointGPSTool::drawImpl(QPainter* painter, MapWidget* widget) { if (preview_object) { const MapView* map_view = widget->getMapView(); painter->save(); painter->translate(widget->width() / 2.0 + map_view->panOffset().x(), widget->height() / 2.0 + map_view->panOffset().y()); painter->setWorldTransform(map_view->worldTransform(), true); RenderConfig config = { *map(), map_view->calculateViewedRect(widget->viewportToView(widget->rect())), map_view->calculateFinalZoomFactor(), RenderConfig::Tool, 0.5 }; renderables->draw(painter, config); painter->restore(); } } int DrawPointGPSTool::updateDirtyRectImpl(QRectF& rect) { if (preview_object) { rectIncludeSafe(rect, preview_object->getExtent()); return 0; } else return -1; } void DrawPointGPSTool::updateStatusText() { setStatusBarText( tr("Click: Finish setting the object. ")); } void DrawPointGPSTool::objectSelectionChangedImpl() { // NOP } void DrawPointGPSTool::activeSymbolChanged(const Symbol* symbol) { if (!symbol || symbol->getType() != Symbol::Point || symbol->isHidden()) { if (symbol && symbol->isHidden()) deactivate(); else switchToDefaultDrawTool(symbol); } else last_used_symbol = symbol; } void DrawPointGPSTool::symbolDeleted(int pos, const Symbol* old_symbol) { Q_UNUSED(pos); if (last_used_symbol == old_symbol) deactivate(); } } // namespace OpenOrienteering