void EditPointTool::updateHoverState(MapCoordF cursor_pos) { HoverState new_hover_state = OverNothing; const Object* new_hover_object = nullptr; MapCoordVector::size_type new_hover_point = no_point; if (text_editor) { handle_offset = MapCoordF(0, 0); } else if (!map()->selectedObjects().empty()) { if (map()->selectedObjects().size() <= max_objects_for_handle_display) { // Try to find object node. auto best_distance_sq = std::numeric_limits<double>::max(); for (const auto object : map()->selectedObjects()) { MapCoordF handle_pos; auto hover_point = findHoverPoint(cur_map_widget->mapToViewport(cursor_pos), cur_map_widget, object, true, &handle_pos); if (hover_point == no_point) continue; auto distance_sq = cursor_pos.distanceSquaredTo(handle_pos); if (distance_sq < best_distance_sq) { new_hover_state |= OverObjectNode; new_hover_object = object; new_hover_point = hover_point; best_distance_sq = distance_sq; handle_offset = handle_pos - cursor_pos; } } if (!new_hover_state.testFlag(OverObjectNode)) { // No object node found. Try to find path object edge. /// \todo De-duplicate: Copied from EditLineTool auto click_tolerance_sq = qPow(0.001 * cur_map_widget->getMapView()->pixelToLength(clickTolerance()), 2); for (auto object : map()->selectedObjects()) { if (object->getType() == Object::Path) { PathObject* path = object->asPath(); float distance_sq; PathCoord path_coord; path->calcClosestPointOnPath(cursor_pos, distance_sq, path_coord); if (distance_sq >= +0.0 && distance_sq < best_distance_sq && distance_sq < qMax(click_tolerance_sq, qPow(path->getSymbol()->calculateLargestLineExtent(map()), 2))) { new_hover_state |= OverPathEdge; new_hover_object = path; new_hover_point = path_coord.index; best_distance_sq = distance_sq; handle_offset = path_coord.pos - cursor_pos; } } } } } if (!new_hover_state.testFlag(OverObjectNode) && selection_extent.isValid()) { QRectF selection_extent_viewport = cur_map_widget->mapToViewport(selection_extent); if (pointOverRectangle(cur_map_widget->mapToViewport(cursor_pos), selection_extent_viewport)) { new_hover_state |= OverFrame; handle_offset = closestPointOnRect(cursor_pos, selection_extent) - cursor_pos; } } } if (new_hover_state != hover_state || new_hover_object != hover_object || new_hover_point != hover_point) { hover_state = new_hover_state; // We have got a Map*, so we may get an non-const Object*. hover_object = const_cast<Object*>(new_hover_object); hover_point = new_hover_point; if (hover_state != OverNothing) start_drag_distance = 0; else start_drag_distance = Settings::getInstance().getStartDragDistancePx(); updateDirtyRect(); } Q_ASSERT((hover_state.testFlag(OverObjectNode) || hover_state.testFlag(OverPathEdge)) == (hover_object != nullptr)); }
void Importer::doImport(bool load_symbols_only, const QString& map_path) { import(load_symbols_only); // Object post processing: // - make sure that there is no object without symbol // - make sure that all area-only path objects are closed // - make sure that there are no special points in wrong places (e.g. curve starts inside curves) for (int p = 0; p < map->getNumParts(); ++p) { MapPart* part = map->getPart(p); for (int o = 0; o < part->getNumObjects(); ++o) { Object* object = part->getObject(o); if (object->getSymbol() == NULL) { addWarning(Importer::tr("Found an object without symbol.")); if (object->getType() == Object::Point) object->setSymbol(map->getUndefinedPoint(), true); else if (object->getType() == Object::Path) object->setSymbol(map->getUndefinedLine(), true); else { // There is no undefined symbol for this type of object, delete the object part->deleteObject(o, false); --o; continue; } } if (object->getType() == Object::Path) { PathObject* path = object->asPath(); Symbol::Type contained_types = path->getSymbol()->getContainedTypes(); if (contained_types & Symbol::Area && !(contained_types & Symbol::Line)) path->closeAllParts(); for (MapCoordVector::size_type i = 0; i < path->getCoordinateCount(); ++i) { if (path->getCoordinate(i).isCurveStart()) { if (i+3 >= path->getCoordinateCount()) { path->getCoordinate(i).setCurveStart(false); continue; } if (path->getCoordinate(i + 1).isClosePoint() || path->getCoordinate(i + 1).isHolePoint() || path->getCoordinate(i + 2).isClosePoint() || path->getCoordinate(i + 2).isHolePoint()) { path->getCoordinate(i).setCurveStart(false); continue; } path->getCoordinate(i + 1).setCurveStart(false); path->getCoordinate(i + 1).setDashPoint(false); path->getCoordinate(i + 2).setCurveStart(false); path->getCoordinate(i + 2).setDashPoint(false); i += 2; } if (i > 0 && path->getCoordinate(i).isHolePoint()) { if (path->getCoordinate(i-1).isHolePoint()) path->deleteCoordinate(i, false); } } } } } // Symbol post processing for (int i = 0; i < map->getNumSymbols(); ++i) { if (!map->getSymbol(i)->loadFinished(map)) throw FileFormatException(Importer::tr("Error during symbol post-processing.")); } // Template loading: try to find all template files bool have_lost_template = false; for (int i = 0; i < map->getNumTemplates(); ++i) { Template* temp = map->getTemplate(i); bool loaded_from_template_dir = false; temp->tryToFindAndReloadTemplateFile(map_path, &loaded_from_template_dir); if (loaded_from_template_dir) addWarning(Importer::tr("Template \"%1\" has been loaded from the map's directory instead of the relative location to the map file where it was previously.").arg(temp->getTemplateFilename())); if (temp->getTemplateState() != Template::Loaded) have_lost_template = true; } if (have_lost_template) { #if defined(Q_OS_ANDROID) addWarning(tr("At least one template file could not be found.")); #else addWarning(tr("At least one template file could not be found.") + " " + tr("Click the red template name(s) in the Templates -> Template setup window to locate the template file name(s).")); #endif } }