Eclipse SUMO - Simulation of Urban MObility
GNEFixNetworkElements.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // Dialog used to fix network elements during saving
19 /****************************************************************************/
20 
23 #include <netedit/GNENet.h>
24 #include <netedit/GNEViewNet.h>
25 #include <netedit/GNEUndoList.h>
26 
27 #include "GNEFixNetworkElements.h"
28 
29 
30 // ===========================================================================
31 // FOX callback mapping
32 // ===========================================================================
33 
34 FXDEFMAP(GNEFixNetworkElements) GNEFixNetworkElementsMap[] = {
38 };
39 
40 // Object implementation
41 FXIMPLEMENT(GNEFixNetworkElements, FXDialogBox, GNEFixNetworkElementsMap, ARRAYNUMBER(GNEFixNetworkElementsMap))
42 
43 // ===========================================================================
44 // member method definitions
45 // ===========================================================================
46 
47 // ---------------------------------------------------------------------------
48 // GNEFixNetworkElements - methods
49 // ---------------------------------------------------------------------------
50 
51 GNEFixNetworkElements::GNEFixNetworkElements(GNEViewNet* viewNet, const std::vector<GNENetworkElement*>& invalidNetworkElements) :
52  FXDialogBox(viewNet->getApp(), TL("Fix network elements problems"), GUIDesignDialogBoxExplicitStretchable(600, 620)),
53  myViewNet(viewNet) {
54  // set busStop icon for this dialog
56  // create main frame
57  myMainFrame = new FXVerticalFrame(this, GUIDesignAuxiliarFrame);
58  // create frames for options
59  FXHorizontalFrame* optionsFrame = new FXHorizontalFrame(myMainFrame, GUIDesignAuxiliarFrame);
60  myLeftFrame = new FXVerticalFrame(optionsFrame, GUIDesignAuxiliarFrame);
61  myRightFrame = new FXVerticalFrame(optionsFrame, GUIDesignAuxiliarFrame);
62  // create fix edge options
63  myFixEdgeOptions = new FixEdgeOptions(this, viewNet);
64  // create fix crossing options
65  myFixCrossingOptions = new FixCrossingOptions(this, viewNet);
66  // create buttons
67  myButtons = new Buttons(this);
68  // split invalidNetworkElements in four groups
69  std::vector<GNENetworkElement*> invalidEdges, invalidCrossings;
70  // fill groups
71  for (const auto& invalidNetworkElement : invalidNetworkElements) {
72  if (invalidNetworkElement->getTagProperty().getTag() == SUMO_TAG_EDGE) {
73  invalidEdges.push_back(invalidNetworkElement);
74  } else if (invalidNetworkElement->getTagProperty().getTag() == SUMO_TAG_CROSSING) {
75  invalidCrossings.push_back(invalidNetworkElement);
76  }
77  }
78  // fill options
79  myFixEdgeOptions->setInvalidElements(invalidEdges);
80  myFixCrossingOptions->setInvalidElements(invalidCrossings);
81 }
82 
83 
85 }
86 
87 
88 long
89 GNEFixNetworkElements::onCmdSelectOption(FXObject* obj, FXSelector, void*) {
90  // select options
93  return 1;
94 }
95 
96 
97 long
98 GNEFixNetworkElements::onCmdAccept(FXObject*, FXSelector, void*) {
99  bool abortSaving = false;
100  // fix elements
101  myFixEdgeOptions->fixElements(abortSaving);
102  myFixCrossingOptions->fixElements(abortSaving);
103  // check if abort saving
104  if (abortSaving) {
105  // stop modal with TRUE (abort saving)
106  getApp()->stopModal(this, FALSE);
107  } else {
108  // stop modal with TRUE (continue saving)
109  getApp()->stopModal(this, TRUE);
110  }
111  return 1;
112 }
113 
114 
115 long
116 GNEFixNetworkElements::onCmdCancel(FXObject*, FXSelector, void*) {
117  // Stop Modal (abort saving)
118  getApp()->stopModal(this, FALSE);
119  return 1;
120 }
121 
122 // ---------------------------------------------------------------------------
123 // GNEFixNetworkElements::FixOptions - methods
124 // ---------------------------------------------------------------------------
125 
126 GNEFixNetworkElements::FixOptions::FixOptions(FXVerticalFrame* frameParent, const std::string& title, GNEViewNet* viewNet) :
127  MFXGroupBoxModule(frameParent, title, MFXGroupBoxModule::Options::SAVE),
128  myViewNet(viewNet) {
129  // Create table
130  myTable = new FXTable(this, this, MID_TABLE, GUIDesignTableFixElements);
131  myTable->disable();
132  // create horizontal frame
133  FXHorizontalFrame* horizontalFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
134  // create vertical frames
135  myLeftFrame = new FXVerticalFrame(horizontalFrame, GUIDesignAuxiliarVerticalFrame);
136  myRightFrame = new FXVerticalFrame(horizontalFrame, GUIDesignAuxiliarVerticalFrame);
137 }
138 
139 
140 void
141 GNEFixNetworkElements::FixOptions::setInvalidElements(const std::vector<GNENetworkElement*>& invalidElements) {
142  // update invalid elements
143  myInvalidElements = invalidElements;
144  // configure table
145  myTable->setTableSize((int)(myInvalidElements.size()), 3);
146  myTable->setSelBackColor(FXRGBA(255, 255, 255, 255));
147  myTable->setSelTextColor(FXRGBA(0, 0, 0, 255));
148  myTable->setEditable(false);
149  // configure header
150  myTable->setVisibleColumns(4);
151  myTable->setColumnWidth(0, GUIDesignHeight);
152  myTable->setColumnWidth(1, 150);
153  myTable->setColumnWidth(2, 390);
154  myTable->setColumnText(0, "");
155  myTable->setColumnText(1, toString(SUMO_ATTR_ID).c_str());
156  myTable->setColumnText(2, TL("Conflict"));
157  myTable->getRowHeader()->setWidth(0);
158  // Declare pointer to FXTableItem
159  FXTableItem* item = nullptr;
160  // iterate over invalid edges
161  for (int i = 0; i < (int)myInvalidElements.size(); i++) {
162  // Set icon
163  item = new FXTableItem("", myInvalidElements.at(i)->getACIcon());
164  item->setIconPosition(FXTableItem::CENTER_X);
165  myTable->setItem(i, 0, item);
166  // Set ID
167  item = new FXTableItem(myInvalidElements.at(i)->getID().c_str());
168  item->setJustify(FXTableItem::LEFT | FXTableItem::CENTER_Y);
169  myTable->setItem(i, 1, item);
170  // Set conflict
171  item = new FXTableItem(myInvalidElements.at(i)->getNetworkElementProblem().c_str());
172  item->setJustify(FXTableItem::LEFT | FXTableItem::CENTER_Y);
173  myTable->setItem(i, 2, item);
174  }
175  // check if enable or disable options
176  if (invalidElements.size() > 0) {
177  enableOptions();
178  toggleSaveButton(true);
179  } else {
180  disableOptions();
181  toggleSaveButton(false);
182  }
183 }
184 
185 
186 bool
188  const FXString file = MFXUtils::getFilename2Write(myTable,
189  TL("Save list of conflicted items"), ".txt",
191  if (file == "") {
192  return false;
193  }
194  try {
195  // open output device
196  OutputDevice& dev = OutputDevice::getDevice(file.text());
197  // get invalid element ID and problem
198  for (const auto& invalidElement : myInvalidElements) {
199  dev << invalidElement->getID() << ":" << invalidElement->getNetworkElementProblem() << "\n";
200  }
201  // close output device
202  dev.close();
203  // write warning if netedit is running in testing mode
204  WRITE_DEBUG("Opening FXMessageBox 'Saving list of conflicted items successfully'");
205  // open message box error
206  FXMessageBox::information(myTable, MBOX_OK, TL("Saving successfully"), "%s", "List of conflicted items was successfully saved");
207  // write warning if netedit is running in testing mode
208  WRITE_DEBUG("Closed FXMessageBox 'Saving list of conflicted items successfully' with 'OK'");
209  } catch (IOError& e) {
210  // write warning if netedit is running in testing mode
211  WRITE_DEBUG("Opening FXMessageBox 'error saving list of conflicted items'");
212  // open message box error
213  FXMessageBox::error(myTable, MBOX_OK, TL("Saving list of conflicted items failed"), "%s", e.what());
214  // write warning if netedit is running in testing mode
215  WRITE_DEBUG("Closed FXMessageBox 'error saving list of conflicted items' with 'OK'");
216  }
217  return true;
218 }
219 
220 // ---------------------------------------------------------------------------
221 // GNEFixNetworkElements::FixEdgeOptions - methods
222 // ---------------------------------------------------------------------------
223 
225  FixOptions(fixNetworkElementsParent->myLeftFrame, "Edges", viewNet) {
226  // Remove invalid edges
227  removeInvalidEdges = new FXRadioButton(myLeftFrame, TL("Remove invalid edges"),
228  fixNetworkElementsParent, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);
229  // Save invalid edges
230  saveInvalidEdges = new FXRadioButton(myLeftFrame, TL("Save invalid edges"),
231  fixNetworkElementsParent, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);
232  // Select invalid edges
233  selectInvalidEdgesAndCancel = new FXRadioButton(myRightFrame, TL("Select conflicted edges"),
234  fixNetworkElementsParent, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);
235  // leave option "removeInvalidEdges" as default
236  removeInvalidEdges->setCheck(true);
237 }
238 
239 
240 void
242  if (option == removeInvalidEdges) {
243  removeInvalidEdges->setCheck(true);
244  saveInvalidEdges->setCheck(false);
245  selectInvalidEdgesAndCancel->setCheck(false);
246  } else if (option == saveInvalidEdges) {
247  removeInvalidEdges->setCheck(false);
248  saveInvalidEdges->setCheck(true);
249  selectInvalidEdgesAndCancel->setCheck(false);
250  } else if (option == selectInvalidEdgesAndCancel) {
251  removeInvalidEdges->setCheck(false);
252  saveInvalidEdges->setCheck(false);
253  selectInvalidEdgesAndCancel->setCheck(true);
254  }
255 }
256 
257 
258 void
260  if (myInvalidElements.size() > 0) {
261  if (removeInvalidEdges->getCheck() == TRUE) {
262  // begin undo list
263  myViewNet->getUndoList()->begin(GUIIcon::EDGE, TL("delete invalid edges"));
264  // iterate over invalid edges to delete it
265  for (const auto& invalidEdge : myInvalidElements) {
267  }
268  // end undo list
269  myViewNet->getUndoList()->end();
270  } else if (selectInvalidEdgesAndCancel->getCheck() == TRUE) {
271  // begin undo list
272  myViewNet->getUndoList()->begin(GUIIcon::EDGE, TL("select invalid edges"));
273  // iterate over invalid single lane elements to select all elements
274  for (const auto& invalidEdge : myInvalidElements) {
275  invalidEdge->setAttribute(GNE_ATTR_SELECTED, "true", myViewNet->getUndoList());
276  }
277  // end undo list
278  myViewNet->getUndoList()->end();
279  // abort saving
280  abortSaving = true;
281  }
282  }
283 }
284 
285 
286 void
288  removeInvalidEdges->enable();
289  saveInvalidEdges->enable();
290  selectInvalidEdgesAndCancel->enable();
291 }
292 
293 
294 void
296  removeInvalidEdges->disable();
297  saveInvalidEdges->disable();
298  selectInvalidEdgesAndCancel->disable();
299 }
300 
301 // ---------------------------------------------------------------------------
302 // GNEFixNetworkElements::FixCrossingOptions - methods
303 // ---------------------------------------------------------------------------
304 
306  FixOptions(fixNetworkElementsParent->myLeftFrame, "Crossings", viewNet) {
307  // Remove invalid crossings
308  removeInvalidCrossings = new FXRadioButton(myLeftFrame, TL("Remove invalid crossings"),
309  fixNetworkElementsParent, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);
310  // Save invalid crossings
311  saveInvalidCrossings = new FXRadioButton(myLeftFrame, TL("Save invalid crossings"),
312  fixNetworkElementsParent, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);
313  // Select invalid crossing
314  selectInvalidCrossingsAndCancel = new FXRadioButton(myRightFrame, TL("Select conflicted crossing"),
315  fixNetworkElementsParent, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);
316  // by default remove invalid crossings
317  removeInvalidCrossings->setCheck(TRUE);
318 }
319 
320 
321 void
323  if (option == removeInvalidCrossings) {
324  removeInvalidCrossings->setCheck(true);
325  saveInvalidCrossings->setCheck(false);
326  selectInvalidCrossingsAndCancel->setCheck(false);
327  } else if (option == saveInvalidCrossings) {
328  removeInvalidCrossings->setCheck(false);
329  saveInvalidCrossings->setCheck(true);
330  selectInvalidCrossingsAndCancel->setCheck(false);
331  } else if (option == selectInvalidCrossingsAndCancel) {
332  removeInvalidCrossings->setCheck(false);
333  saveInvalidCrossings->setCheck(false);
334  selectInvalidCrossingsAndCancel->setCheck(true);
335  }
336 }
337 
338 
339 void
341  if (myInvalidElements.size() > 0) {
342  if (removeInvalidCrossings->getCheck() == TRUE) {
343  // begin undo list
344  myViewNet->getUndoList()->begin(GUIIcon::CROSSING, TL("delete invalid crossings"));
345  // iterate over invalid crossings to delete it
346  for (const auto& invalidCrossing : myInvalidElements) {
348  }
349  // end undo list
350  myViewNet->getUndoList()->end();
351  } else if (selectInvalidCrossingsAndCancel->getCheck() == TRUE) {
352  // begin undo list
353  myViewNet->getUndoList()->begin(GUIIcon::CROSSING, TL("select invalid crossings"));
354  // iterate over invalid single lane elements to select all elements
355  for (const auto& invalidCrossing : myInvalidElements) {
356  invalidCrossing->setAttribute(GNE_ATTR_SELECTED, "true", myViewNet->getUndoList());
357  }
358  // end undo list
359  myViewNet->getUndoList()->end();
360  // abort saving
361  abortSaving = true;
362  }
363  }
364 }
365 
366 
367 void
369  removeInvalidCrossings->enable();
370  saveInvalidCrossings->enable();
371  selectInvalidCrossingsAndCancel->enable();
372 }
373 
374 
375 void
377  removeInvalidCrossings->disable();
378  saveInvalidCrossings->disable();
379  selectInvalidCrossingsAndCancel->disable();
380 }
381 
382 // ---------------------------------------------------------------------------
383 // GNEFixNetworkElements::Buttons - methods
384 // ---------------------------------------------------------------------------
385 
387  FXHorizontalFrame(fixNetworkElementsParent->myMainFrame, GUIDesignHorizontalFrame) {
388  new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
391  new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
392  // set focus in accept button
393  myAcceptButton->setFocus();
394 }
395 
396 /****************************************************************************/
FXDEFMAP(GNEFixNetworkElements) GNEFixNetworkElementsMap[]
@ MID_GNE_BUTTON_CANCEL
cancel button
Definition: GUIAppEnum.h:1394
@ MID_TABLE
The Table.
Definition: GUIAppEnum.h:535
@ MID_CHOOSEN_OPERATION
set type of selection
Definition: GUIAppEnum.h:593
@ MID_GNE_BUTTON_ACCEPT
accept button
Definition: GUIAppEnum.h:1392
#define GUIDesignRadioButtonFix
design for radio button with fixed height (used in fix elements dialogs)
Definition: GUIDesigns.h:241
#define GUIDesignButtonAccept
Accept Button.
Definition: GUIDesigns.h:162
#define GUIDesignButtonCancel
Cancel Button.
Definition: GUIDesigns.h:168
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition: GUIDesigns.h:405
#define GUIDesignAuxiliarVerticalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition: GUIDesigns.h:411
#define GUIDesignTableFixElements
design for tables used in GNEFixDemandElements dialogs
Definition: GUIDesigns.h:640
#define GUIDesignAuxiliarFrame
design for auxiliar (Without borders) frame extended in all directions
Definition: GUIDesigns.h:396
#define GUIDesignHorizontalFrame
Horizontal frame extended over frame parent with padding and spacing.
Definition: GUIDesigns.h:334
#define GUIDesignDialogBoxExplicitStretchable(width, height)
design for dialog box with specific width and height that can be stretched (But not shrunk)
Definition: GUIDesigns.h:620
FXString gCurrentFolder
The folder used as last.
@ SUPERMODEDEMAND
@ SAVE
save icons
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:306
#define TL(string)
Definition: MsgHandler.h:315
@ SUMO_TAG_CROSSING
crossing between edges for pedestrians
@ SUMO_TAG_EDGE
begin/end of the description of an edge
@ GNE_ATTR_SELECTED
element is selected
@ SUMO_ATTR_ID
int GUIDesignHeight
the default size for GUI elements
Definition: StdDefs.cpp:34
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
horizontal frame for buttons
FXButton * myCancelButton
cancel button
Buttons(GNEFixNetworkElements *fixNetworkElementsParent)
build Position Options
FXButton * myAcceptButton
accept button
groupbox for all radio buttons related with fix crossing options
FXRadioButton * saveInvalidCrossings
Option "save invalid crossings".
FixCrossingOptions(GNEFixNetworkElements *fixNetworkElementsParent, GNEViewNet *viewNet)
constructor
void fixElements(bool &abortSaving)
fix elements
FXRadioButton * removeInvalidCrossings
Option "remove invalid elements".
void selectOption(FXObject *option)
select option
FXRadioButton * selectInvalidCrossingsAndCancel
Option "Select invalid crossings and cancel".
groupbox for all radio buttons related with fix edges options
void selectOption(FXObject *option)
select option
FXRadioButton * selectInvalidEdgesAndCancel
Option "Select invalid edges and cancel".
void fixElements(bool &abortSaving)
fix elements
FXRadioButton * saveInvalidEdges
Option "Save invalid edges".
FXRadioButton * removeInvalidEdges
Option "Remove invalid edges".
FixEdgeOptions(GNEFixNetworkElements *fixNetworkElementsParent, GNEViewNet *viewNet)
constructor
FixOptions(FXVerticalFrame *frameParent, const std::string &title, GNEViewNet *viewNet)
constructor
FXTable * myTable
Table with the network elements.
FXVerticalFrame * myLeftFrame
vertical left frame
void setInvalidElements(const std::vector< GNENetworkElement * > &invalidElements)
set invalid network elements
FXVerticalFrame * myRightFrame
vertical right frame
Dialog fix network elements.
FXVerticalFrame * myMainFrame
main frame
long onCmdCancel(FXObject *, FXSelector, void *)
event after press cancel button
FixEdgeOptions * myFixEdgeOptions
fix edge options
FixCrossingOptions * myFixCrossingOptions
fix crossing options
GNEViewNet * myViewNet
view net
long onCmdSelectOption(FXObject *obj, FXSelector, void *)
FXVerticalFrame * myLeftFrame
vertical left frame
long onCmdAccept(FXObject *, FXSelector, void *)
event after press accept button
GNECrossing * retrieveCrossing(const GUIGlObject *glObject, bool hardFail=true) const
get Crossing by AC
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
void deleteEdge(GNEEdge *edge, GNEUndoList *undoList, bool recomputeConnections)
removes edge
Definition: GNENet.cpp:413
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:632
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:121
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
void begin(GUIIcon icon, const std::string &description)
Begin undo command sub-group with current supermode. This begins a new group of commands that are tre...
GNENet * getNet() const
get the net object
GNEUndoList * getUndoList() const
get the undoList object
static FXButton * buildFXButton(FXComposite *p, const std::string &text, const std::string &tip, const std::string &help, FXIcon *ic, FXObject *tgt, FXSelector sel, FXuint opts=BUTTON_NORMAL, FXint x=0, FXint y=0, FXint w=0, FXint h=0, FXint pl=DEFAULT_PAD, FXint pr=DEFAULT_PAD, FXint pt=DEFAULT_PAD, FXint pb=DEFAULT_PAD)
build button
Definition: GUIDesigns.cpp:128
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
MFXGroupBoxModule (based on FXGroupBox)
Options
GroupBoxModule options.
static FXString getFilename2Write(FXWindow *parent, const FXString &header, const FXString &extension, FXIcon *icon, FXString &currentFolder)
Returns the file name to write.
Definition: MFXUtils.cpp:82
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
void close()
Closes the device and removes it from the dictionary.
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
Definition: json.hpp:4471