Path: blob/main/src/netedit/dialogs/elements/lists/GNETemplateElementList.h
169688 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file GNETemplateElementList.h14/// @author Pablo Alvarez Lopez15/// @date Aug 202516///17// Template used for Element lists18/****************************************************************************/19#pragma once2021#include <netedit/dialogs/elements/GNETemplateElementDialog.h>22#include <netedit/GNEApplicationWindow.h>2324#include "GNEElementTable.h"25#include "GNEElementList.h"2627// ===========================================================================28// class definitions29// ===========================================================================3031template <typename elementDialogType, typename elementType, typename GNEChange_Type>32class GNETemplateElementList : public GNEElementList {3334public:35/// @brief constructor36GNETemplateElementList(GNETemplateElementDialog<elementDialogType>* elementDialogParent,37FXVerticalFrame* contentFrame, SumoXMLTag tag, GNEElementList::Options options) :38GNEElementList(contentFrame, elementDialogParent->getApplicationWindow()->getTagPropertiesDatabase()->getTagProperty(tag, true), options),39myElementDialogParent(elementDialogParent) {40// update table41updateList();42}4344/// @brief get edited elements45const std::vector<elementType*>& getEditedElements() const {46return myEditedElements;47}4849/// @brief insert element50long insertElement(elementType* element) {51// add change command52element->getNet()->getViewNet()->getUndoList()->add(new GNEChange_Type(element, true), true);53// update table54return updateList();55}5657/// @brief update element list58long updateList() {59// reset edited element60myEditedElements.clear();61for (const auto& child : myElementDialogParent->getElement()->getChildren().template get<elementType*>()) {62if (child->getTagProperty()->getTag() == myTagProperty->getTag()) {63myEditedElements.push_back(child);64}65}66// first resize table (used if we removed some elements)67myElementTable->resizeTable(myEditedElements.size());68// now update all rows69for (size_t i = 0; i < myEditedElements.size(); i++) {70myElementTable->updateRow(i, myEditedElements.at(i));71}72return 1;73}7475/// @brief check if the elements are sorted76bool checkSort() const {77// get sort tuples78const auto tuples = getSortTuples(false);79// check if the elements are sorted80for (int i = 0; i < ((int)tuples.size() - 1); i++) {81if (tuples.at(i) > tuples.at(i)) {82return false;83}84}85return true;86}8788/// @brief open dialog89long sortRows() {90// get sort tuples sorted91const auto sortedTuples = getSortTuples(true);92// now update edited elements list using sortTuples93myEditedElements.clear();94for (const auto& element : sortedTuples) {95myEditedElements.push_back(std::get<6>(element));96}97// update table98return updateList();99}100101/// @brief remove element (using index)102long removeElement(const size_t rowIndex) {103// delete element recursively104removeElementRecursively(myEditedElements.at(rowIndex));105// update table106return updateList();107}108109/// @brief remove element110long removeElement(const elementType* element) {111// search index112for (size_t rowIndex = 0; rowIndex < myEditedElements.size(); rowIndex++) {113if (myEditedElements.at(rowIndex) == element) {114return removeElement(rowIndex);115}116}117// if we reach this point, the element was not found118throw ProcessError("Element not found in removeElement");119}120121/// @brief add new element (must be implemented in children)122virtual long addNewElement() = 0;123124/// @brief open element dialog (optional125virtual long openElementDialog(const size_t rowIndex) = 0;126127protected:128/// @brief element dialog parent129GNETemplateElementDialog<elementDialogType>* myElementDialogParent = nullptr;130131/// @brief edited elements132std::vector<elementType*> myEditedElements;133134private:135/// @brief typedef used for sorting elements by attributes136typedef std::tuple<double, double, double, double, double, double, elementType*> SortTuple;137138/// @brief get element sorted139std::vector<SortTuple> getSortTuples(const bool sort) const {140// declare sorted element set141std::vector<SortTuple> elementSortKeyVector;142// add all elements143for (size_t i = 0; i < myEditedElements.size(); i++) {144// create tuple with max 6 sortable attributes145auto tuple = std::make_tuple(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, myEditedElements.at(i));146// update tuple with sortable attributes147const auto& sortableAttributes = myElementTable->getColumnHeader()->getSortableAttributes();148// fill tuple149if (sortableAttributes.size() > 0) {150std::get<0>(tuple) = GNEAttributeCarrier::parse<double>(myEditedElements.at(i)->getAttribute(sortableAttributes.at(0)));151}152if (sortableAttributes.size() > 1) {153std::get<1>(tuple) = GNEAttributeCarrier::parse<double>(myEditedElements.at(i)->getAttribute(sortableAttributes.at(1)));154}155if (sortableAttributes.size() > 2) {156std::get<2>(tuple) = GNEAttributeCarrier::parse<double>(myEditedElements.at(i)->getAttribute(sortableAttributes.at(2)));157}158if (sortableAttributes.size() > 3) {159std::get<3>(tuple) = GNEAttributeCarrier::parse<double>(myEditedElements.at(i)->getAttribute(sortableAttributes.at(3)));160}161if (sortableAttributes.size() > 4) {162std::get<4>(tuple) = GNEAttributeCarrier::parse<double>(myEditedElements.at(i)->getAttribute(sortableAttributes.at(4)));163}164if (sortableAttributes.size() > 5) {165std::get<5>(tuple) = GNEAttributeCarrier::parse<double>(myEditedElements.at(i)->getAttribute(sortableAttributes.at(5)));166}167elementSortKeyVector.push_back(tuple);168}169// check if sort tuples170if (sort) {171std::set<SortTuple> elementSortKeySet;172for (const auto& element : elementSortKeyVector) {173// insert tuple into set174elementSortKeySet.insert(element);175}176// clear vector and copy set into vector177elementSortKeyVector.clear();178for (const auto& element : elementSortKeySet) {179elementSortKeyVector.push_back(element);180}181}182return elementSortKeyVector;183}184185/// @brief Invalidated copy constructor186GNETemplateElementList(const GNETemplateElementList&) = delete;187188/// @brief Invalidated assignment operator189GNETemplateElementList& operator=(const GNETemplateElementList&) = delete;190};191192193