Path: blob/main/src/netedit/dialogs/fix/GNEFixElementsDialog.h
169684 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 GNEFixElementsDialog.h14/// @author Pablo Alvarez Lopez15/// @date Jul 202516///17// template used to fix elements during saving18/****************************************************************************/19#pragma once20#include <config.h>2122#include <netedit/dialogs/basic/GNEErrorBasicDialog.h>23#include <netedit/dialogs/basic/GNEInformationBasicDialog.h>24#include <utils/foxtools/MFXGroupBoxModule.h>25#include <utils/gui/div/GUIDesigns.h>26#include <utils/gui/windows/GUIAppEnum.h>2728// ===========================================================================29// class definitions30// ===========================================================================3132template <typename T>33class GNEFixElementsDialog : public GNEDialog {3435public:36/// @brief Conflict37class ConflictElement {3839public:40/// @brief constructor41ConflictElement(T element, const std::string& id, FXIcon* icon, const std::string& description) :42myElement(element),43myID(id),44myIcon(icon),45myDescription(description) {}4647/// @brief destructor48~ConflictElement() {}4950/// @brief conflicted element51T getElement() const {52return myElement;53}5455/// @brief get element ID56const std::string& getID() const {57return myID;58}5960/// @brief get element icon61FXIcon* getIcon() const {62return myIcon;63}6465/// @brief get conflict description66const std::string& getDescription() const {67return myDescription;68}6970private:71/// @brief conflicted element72T myElement;7374/// @brief ID of the element75std::string myID;7677/// @brief icon78FXIcon* myIcon = nullptr;7980/// @brief conflict description81std::string myDescription;8283/// @brief invalidate default constructor84ConflictElement() = delete;85};8687/// @brief GNEFixOptions module88class FixOptions : public MFXGroupBoxModule {8990public:91/// @brief constructor92FixOptions(GNEFixElementsDialog<T>* fixElementDialog, FXVerticalFrame* frameParent, const std::string& title) :93MFXGroupBoxModule(frameParent, title, MFXGroupBoxModule::Options::SAVE),94myFixElementDialogParent(fixElementDialog) {95// register this fix option to list of fix options96fixElementDialog->registerFixOptions(this);97// Create table98myTable = new FXTable(getCollapsableFrame(), this, MID_TABLE, GUIDesignTableFixElements);99// create frames for options100FXHorizontalFrame* optionsFrame = new FXHorizontalFrame(getCollapsableFrame(), GUIDesignAuxiliarHorizontalFrame);101myLeftFrameOptions = new FXVerticalFrame(optionsFrame, GUIDesignAuxiliarFrameFixedWidth(int(myTable->getWidth() * 0.5)));102myRightFrameOptions = new FXVerticalFrame(optionsFrame, GUIDesignAuxiliarFrameFixedWidth(int(myTable->getWidth() * 0.5)));103}104105/// @brief select internal test solution (used in internal tests)106virtual void selectInternalTestSolution(const std::string& solution) = 0;107108/// @brief apply selected fix option109virtual bool applyFixOption() = 0;110111/// @name FOX-callbacks112/// @{113114/// @brief called when user select a option115virtual long onCmdSelectOption(FXObject*, FXSelector, void*) = 0;116117/// @}118119/// @brief set invalid elements to fix120void setInvalidElements(const std::vector<ConflictElement>& conflictedElements) {121// parse invalid elements122myConflictedElements = conflictedElements;123// configure table124myTable->setTableSize((int)(myConflictedElements.size()), 3);125myTable->setSelBackColor(FXRGBA(255, 255, 255, 255));126myTable->setSelTextColor(FXRGBA(0, 0, 0, 255));127myTable->setEditable(false);128// configure header129myTable->setVisibleColumns(4);130myTable->setColumnHeaderHeight(GUIDesignHeight);131myTable->getRowHeader()->setWidth(0);132// icon133myTable->setColumnWidth(0, GUIDesignHeight);134myTable->setColumnText(0, "");135// ID136myTable->setColumnWidth(1, 110);137myTable->setColumnText(1, toString(SUMO_ATTR_ID).c_str());138// description139myTable->setColumnWidth(2, myTable->getWidth() - GUIDesignHeight - 110 - 15);140myTable->setColumnText(2, TL("Conflict"));141// Declare pointer to FXTableItem142FXTableItem* item = nullptr;143// iterate over invalid edges144for (int i = 0; i < (int)myConflictedElements.size(); i++) {145// Set icon146item = new FXTableItem("", myConflictedElements.at(i).getIcon());147item->setIconPosition(FXTableItem::CENTER_X);148myTable->setItem(i, 0, item);149// Set ID150item = new FXTableItem(myConflictedElements.at(i).getID().c_str());151item->setJustify(FXTableItem::LEFT | FXTableItem::CENTER_Y);152myTable->setItem(i, 1, item);153// Set conflict154item = new FXTableItem(myConflictedElements.at(i).getDescription().c_str());155item->setJustify(FXTableItem::LEFT | FXTableItem::CENTER_Y);156myTable->setItem(i, 2, item);157// set row height158myTable->setRowHeight(i, GUIDesignHeight);159}160// check if enable or disable options161if (myConflictedElements.size() > 0) {162enableOptions();163} else {164disableOptions();165}166}167168protected:169/// @brief pointer to the parent dialog170GNEFixElementsDialog* myFixElementDialogParent = nullptr;171172/// @brief Table with the demand elements173FXTable* myTable = nullptr;174175/// @brief vertical left frame for options176FXVerticalFrame* myLeftFrameOptions = nullptr;177178/// @brief vertical right frame for options179FXVerticalFrame* myRightFrameOptions = nullptr;180181/// @brief list of elements to fix182std::vector<ConflictElement> myConflictedElements;183184/// @brief default constructor185FixOptions() :186MFXGroupBoxModule() {187}188189/// @brief add option to options container (used for adjust width and enable/disable)190void registerOption(FXWindow* option) {191myOptions.push_back(option);192// adjust width193option->setWidth(int(myTable->getWidth() * 0.5));194}195196private:197/// @brief list of options198std::vector<FXWindow*> myOptions;199200/// @brief enable options201void enableOptions() {202// enable each option203for (auto option : myOptions) {204option->enable();205}206}207208/// @brief disable options209void disableOptions() {210// disable each option211for (auto option : myOptions) {212option->disable();213}214}215216/// @brief save save list of conflicted items to a file (Reimplemented from MFXGroupBoxModule)217bool saveContents() const {218// open file dialog to save list of conflicted items219const FXString file = MFXUtils::getFilename2Write(myTable,220TL("Save list of conflicted items"),221SUMOXMLDefinitions::TXTFileExtensions.getMultilineString().c_str(),222GUIIconSubSys::getIcon(GUIIcon::SAVE), gCurrentFolder);223// continue if file is not empty224if (file == "") {225return false;226} else {227try {228// open output device229OutputDevice& device = OutputDevice::getDevice(file.text());230// get invalid element ID and problem231for (const auto& conflictedElement : myConflictedElements) {232device << conflictedElement.getID() << ":" << conflictedElement.getDescription() << "\n";233}234// close output device235device.close();236// open information message box237GNEInformationBasicDialog(myFixElementDialogParent->myApplicationWindow,238TL("Saving successfully"),239TL("List of conflicted items was successfully saved"));240return true;241} catch (IOError& e) {242// open message box error243GNEErrorBasicDialog(myFixElementDialogParent->myApplicationWindow,244TL("Saving list of conflicted items failed"), e.what());245return false;246}247}248}249250/// @brief Invalidated copy constructor.251FixOptions(const FixOptions&) = delete;252253/// @brief Invalidated assignment operator.254FixOptions& operator=(const FixOptions&) = delete;255};256257/// @brief Constructor258GNEFixElementsDialog(GNEApplicationWindow* mainWindow, const std::string title,259GUIIcon icon, DialogType type):260GNEDialog(mainWindow, title.c_str(), icon, type, GNEDialog::Buttons::ACCEPT_CANCEL,261GNEDialog::OpenType::MODAL, ResizeMode::STATIC) {262// create left and right frames263FXHorizontalFrame* columnFrame = new FXHorizontalFrame(myContentFrame, GUIDesignAuxiliarHorizontalFrame);264myLeftFrame = new FXVerticalFrame(columnFrame, GUIDesignAuxiliarVerticalFrame);265myRightFrame = new FXVerticalFrame(columnFrame, GUIDesignAuxiliarVerticalFrame);266}267268/// @brief destructor269~GNEFixElementsDialog() {}270271/// @brief pointer to the main window272GNEApplicationWindow* getApplicationWindow() {273return myApplicationWindow;274}275276/// @brief register fix options to the dialog (called automatically during FixOptions constructor)277void registerFixOptions(FixOptions* fixOptions) {278myFixOptions.push_back(fixOptions);279}280281/// @brief run internal test282void runInternalTest(const InternalTestStep::DialogArgument* dialogArgument) {283// run internal test for each fix option284for (auto fixOption : myFixOptions) {285fixOption->selectInternalTestSolution(dialogArgument->getCustomAction());286}287}288289/// @name FOX-callbacks290/// @{291292/// @brief event after press accept button293long onCmdAccept(FXObject*, FXSelector, void*) {294bool abortSaving = false;295// apply each fix option in their correspond fixOption296for (auto fixOption : myFixOptions) {297// if applyFixOption returns false, abort saving (usually for selecting invalid elements)298if (fixOption->applyFixOption() == false) {299abortSaving = true;300}301}302// continue depending of abortSaving303if (abortSaving == false) {304return closeDialogAccepting();305} else {306return closeDialogCanceling();307}308}309310/// @}311312protected:313/// @brief vector with all fix options314std::vector<GNEFixElementsDialog::FixOptions*> myFixOptions;315316/// @brief left frame for fix options317FXVerticalFrame* myLeftFrame = nullptr;318319/// @brief right frame for fix options320FXVerticalFrame* myRightFrame = nullptr;321322private:323/// @brief Invalidated copy constructor.324GNEFixElementsDialog(const GNEFixElementsDialog&) = delete;325326/// @brief Invalidated assignment operator.327GNEFixElementsDialog& operator=(const GNEFixElementsDialog&) = delete;328};329330331