Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
GNEOptionsDialog.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-2025 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// A Dialog for setting options (see OptionsCont)
19/****************************************************************************/
20#include <config.h>
21
22#include <algorithm>
23#include <fstream>
25#include <netedit/GNEViewNet.h>
35#include <xercesc/parsers/SAXParser.hpp>
36
37#include "GNEOptionsDialog.h"
38
39// ===========================================================================
40// Defines
41// ===========================================================================
42
43#define TREELISTWIDTH 200
44
45// ===========================================================================
46// FOX callback mapping
47// ===========================================================================
48
61
62// Object implementation
63FXIMPLEMENT(GNEOptionsDialog, FXDialogBox, GUIDialogOptionsMap, ARRAYNUMBER(GUIDialogOptionsMap))
64
65// ===========================================================================
66// method definitions
67// ===========================================================================
68
69std::pair<int, bool>
70GNEOptionsDialog::Options(GNEApplicationWindow* GNEApp, GUIIcon icon, OptionsCont& optionsContainer, const OptionsCont& originalOptionsContainer, const char* titleName) {
71 GNEOptionsDialog* optionsDialog = new GNEOptionsDialog(GNEApp, icon, optionsContainer, originalOptionsContainer, titleName, false);
72 auto result = std::make_pair(optionsDialog->execute(), optionsDialog->myOptionsModified);
73 delete optionsDialog;
74 return result;
75}
76
77
78std::pair<int, bool>
79GNEOptionsDialog::Run(GNEApplicationWindow* GNEApp, GUIIcon icon, OptionsCont& optionsContainer, const OptionsCont& originalOptionsContainer, const char* titleName) {
80 GNEOptionsDialog* optionsDialog = new GNEOptionsDialog(GNEApp, icon, optionsContainer, originalOptionsContainer, titleName, true);
81 auto result = std::make_pair(optionsDialog->execute(), optionsDialog->myOptionsModified);
82 delete optionsDialog;
83 return result;
84}
85
86
88
89
90long
91GNEOptionsDialog::onCmdCancel(FXObject*, FXSelector, void*) {
92 // reset entries
93 for (const auto& entry : myInputOptionEntries) {
94 entry->onCmdResetOption(nullptr, 0, nullptr);
95 }
96 // close dialog canceling changes
97 return handle(this, FXSEL(SEL_COMMAND, ID_CANCEL), nullptr);
98}
99
100
101long
102GNEOptionsDialog::onCmdReset(FXObject*, FXSelector, void*) {
103 // reset entries
104 for (const auto& entry : myInputOptionEntries) {
105 entry->onCmdResetOption(nullptr, 0, nullptr);
106 }
107 return 1;
108}
109
110
111long
112GNEOptionsDialog::onCmdRunNetgenerate(FXObject*, FXSelector, void*) {
113 // close dialog accepting changes
114 handle(this, FXSEL(SEL_COMMAND, ID_ACCEPT), nullptr);
115 // run tool in mainWindow
116 return myGNEApp->handle(this, FXSEL(SEL_COMMAND, MID_GNE_RUNNETGENERATE), nullptr);
117}
118
119
120long
121GNEOptionsDialog::onCmdSelectTopic(FXObject*, FXSelector, void*) {
122 if (mySearchButton->getText().count() == 0) {
124 }
125 return 1;
126}
127
128
129long
130GNEOptionsDialog::onCmdSearch(FXObject*, FXSelector, void*) {
131 if (mySearchButton->getText().count() > 0) {
133 } else {
135 }
136 return 1;
137}
138
139
140long
141GNEOptionsDialog::onCmdShowToolTipsMenu(FXObject*, FXSelector, void*) {
142 // toggle check
144 if (myGNEApp->getViewNet()) {
147 }
148 // enable/disable static tooltip
150 // save in registry
151 getApp()->reg().writeIntEntry("gui", "menuToolTips", myShowToolTipsMenu->amChecked() ? 0 : 1);
152 update();
153
154 return 1;
155}
156
157
158long
159GNEOptionsDialog::onCmdSaveOptions(FXObject*, FXSelector, void*) {
160 // open save dialog
161 const std::string file = GNEApplicationWindowHelper::openOptionFileDialog(this, true);
162 // check file
163 if (file.size() > 0) {
164 std::ofstream out(StringUtils::transcodeToLocal(file));
165 myOptionsContainer.writeConfiguration(out, true, false, false, file, true);
166 out.close();
167 }
168 return 1;
169}
170
171
172long
173GNEOptionsDialog::onCmdLoadOptions(FXObject*, FXSelector, void*) {
174 // open file dialog
175 const std::string file = GNEApplicationWindowHelper::openOptionFileDialog(this, false);
176 // check file
177 if ((file.size() > 0) && loadConfiguration(file)) {
178 // update entries
179 for (const auto& entry : myInputOptionEntries) {
180 entry->updateOption();
181 }
182 }
183 return 1;
184}
185
186
187long
188GNEOptionsDialog::onCmdResetDefault(FXObject*, FXSelector, void*) {
189 // restore entries
190 for (const auto& entry : myInputOptionEntries) {
191 entry->restoreOption();
192 }
193 return 1;
194}
195
196
198 myGNEApp(nullptr),
199 myOptionsContainer(OptionsCont::EMPTY_OPTIONS),
200 myOriginalOptionsContainer(OptionsCont::EMPTY_OPTIONS) {
201}
202
203
204bool
206 // iterate over tree elements and get the selected item
207 for (const auto& treeItemTopic : myTreeItemTopics) {
208 if (treeItemTopic.first->isSelected()) {
209 // iterate over entries
210 for (const auto& entry : myInputOptionEntries) {
211 if (entry->getTopic() == treeItemTopic.second) {
212 entry->show();
213 } else {
214 entry->hide();
215 }
216 }
217 myEntriesFrame->recalc();
218 myEntriesFrame->update();
219 return true;
220 }
221 }
222 // no topic selected, then show all
223 for (const auto& entry : myInputOptionEntries) {
224 entry->show();
225 }
226 myEntriesFrame->recalc();
227 myEntriesFrame->update();
228 return true;
229}
230
231
232void
234 // first lower case search text
235 searchText = StringUtils::to_lower_case(searchText);
236 // iterate over entries
237 for (const auto& entry : myInputOptionEntries) {
238 if (searchText.empty()) {
239 // show all entries if searchText is empty
240 entry->show();
241 } else if (entry->getNameLower().find(searchText) != std::string::npos) {
242 entry->show();
243 } else if ((myDescriptionSearchCheckButton->getCheck() == TRUE) &&
244 (entry->getDescriptionLower().find(searchText) != std::string::npos)) {
245 entry->show();
246 } else {
247 entry->hide();
248 }
249 }
250 myEntriesFrame->recalc();
251 myEntriesFrame->update();
252}
253
254
255bool
256GNEOptionsDialog::loadConfiguration(const std::string& file) {
257 // make all options writable
259 // build parser
260 XERCES_CPP_NAMESPACE::SAXParser parser;
261 parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
262 parser.setDisableDefaultEntityResolution(true);
263 // start the parsing
265 try {
266 parser.setDocumentHandler(&handler);
267 parser.setErrorHandler(&handler);
268 parser.parse(StringUtils::transcodeToLocal(file).c_str());
269 if (handler.errorOccurred()) {
270 WRITE_ERROR(TL("Could not load configuration '") + file + "'.");
271 return false;
272 }
273 } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
274 WRITE_ERROR(TL("Could not load tool configuration '") + file + "':\n " + StringUtils::transcode(e.getMessage()));
275 return false;
276 }
277 // write info
278 WRITE_MESSAGE(TL("Loaded configuration."));
279 return true;
280}
281
282
284 const OptionsCont& originalOptionsContainer, const char* titleName, const bool runDialog) :
285 FXDialogBox(GNEApp, titleName, GUIDesignDialogBoxExplicitStretchable(800, 600)),
286 myGNEApp(GNEApp),
287 myOptionsContainer(optionsContainer),
288 myOriginalOptionsContainer(originalOptionsContainer) {
289 // set icon
290 setIcon(GUIIconSubSys::getIcon(icon));
291 // create content frame
292 FXVerticalFrame* contentFrame = new FXVerticalFrame(this, GUIDesignContentsFrame);
293 // add buttons frame
294 FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(contentFrame, GUIDesignHorizontalFrameNoPadding);
295 myShowToolTipsMenu = new MFXCheckableButton(false, buttonsFrame,
296 myGNEApp->getStaticTooltipMenu(), (std::string("\t") + TL("Toggle Menu Tooltips") + std::string("\t") + TL("Toggles whether tooltips in the menu shall be shown.")).c_str(),
298 auto saveFile = new MFXButtonTooltip(buttonsFrame, myGNEApp->getStaticTooltipMenu(), TL("Save options"),
300 saveFile->setTipText(TL("Save configuration file"));
301 auto loadFile = new MFXButtonTooltip(buttonsFrame, myGNEApp->getStaticTooltipMenu(), TL("Load options"),
303 loadFile->setTipText(TL("Load configuration file"));
304 auto resetDefault = new MFXButtonTooltip(buttonsFrame, myGNEApp->getStaticTooltipMenu(), TL("Default options"),
306 resetDefault->setTipText(TL("Reset all options to default"));
307 // add separator
308 new FXSeparator(contentFrame);
309 // create elements frame
310 FXHorizontalFrame* elementsFrame = new FXHorizontalFrame(contentFrame, GUIDesignAuxiliarFrame);
311 FXVerticalFrame* elementsFrameTree = new FXVerticalFrame(elementsFrame, GUIDesignAuxiliarVerticalFrame);
312 FXVerticalFrame* elementsFrameValues = new FXVerticalFrame(elementsFrame, GUIDesignAuxiliarFrame);
313 // Create GroupBox modules
314 MFXGroupBoxModule* groupBoxTree = new MFXGroupBoxModule(elementsFrameTree, TL("Topics"));
315 MFXGroupBoxModule* groupBoxOptions = new MFXGroupBoxModule(elementsFrameValues, TL("Options"));
316 // create FXTreeList
317 myTopicsTreeList = new FXTreeList(groupBoxTree->getCollapsableFrame(), this, MID_GNE_SELECT, GUIDesignTreeListFixedWidth);
319 // add root item
320 myRootItem = myTopicsTreeList->appendItem(nullptr, titleName);
321 myRootItem->setExpanded(TRUE);
322 // create scroll
323 FXScrollWindow* scrollTabEntries = new FXScrollWindow(groupBoxOptions->getCollapsableFrame(), LAYOUT_FILL_X | LAYOUT_FILL_Y);
324 // create vertical frame for entries
325 myEntriesFrame = new FXVerticalFrame(scrollTabEntries, GUIDesignAuxiliarFrame);
326 // iterate over all topics
327 for (const auto& topic : myOptionsContainer.getSubTopics()) {
328 // check if we have to ignore this topic
329 if (myIgnoredTopics.count(topic) == 0) {
330 // add topic into myTreeItemTopics and tree
331 myTreeItemTopics[myTopicsTreeList->appendItem(myRootItem, topic.c_str())] = topic;
332 // iterate over entries
333 const std::vector<std::string> entries = myOptionsContainer.getSubTopicsEntries(topic);
334 for (const auto& entry : entries) {
335 // check if we have to ignore this entry
336 if (myIgnoredEntries.count(entry) == 0) {
337 // get type
338 const std::string type = myOptionsContainer.getTypeName(entry);
339 // get description
340 const std::string description = myOptionsContainer.getDescription(entry);
341 // get default value
342 const std::string defaultValue = myOptionsContainer.getValueString(entry);
343 // continue depending of type
344 if (type == "STR") {
345 myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputString(this, myEntriesFrame, topic, entry, description, defaultValue));
346 } else if (type == "TIME") {
347 myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputTime(this, myEntriesFrame, topic, entry, description, defaultValue));
348 } else if ((type == "FILE") || (type == "NETWORK") || (type == "ADDITIONAL") || (type == "ROUTE") || (type == "DATA")) {
349 myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputFilename(this, myEntriesFrame, topic, entry, description, defaultValue));
350 } else if (type == "BOOL") {
351 myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputBool(this, myEntriesFrame, topic, entry, description, defaultValue));
352 } else if (type == "INT") {
353 myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputInt(this, myEntriesFrame, topic, entry, description, defaultValue));
354 } else if (type == "FLOAT") {
355 myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputFloat(this, myEntriesFrame, topic, entry, description, defaultValue));
356 } else if (type == "INT[]") {
357 myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputIntVector(this, myEntriesFrame, topic, entry, description, defaultValue));
358 } else if (type == "STR[]") {
359 myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputStringVector(this, myEntriesFrame, topic, entry, description, defaultValue));
360 }
361 }
362 }
363 }
364 }
365 // create search elements
366 FXHorizontalFrame* searchFrame = new FXHorizontalFrame(contentFrame, GUIDesignAuxiliarHorizontalFrame);
367 new FXLabel(searchFrame, TL("Search"), nullptr, GUIDesignLabelThickedFixed(TREELISTWIDTH - GUIDesignHeight + 14));
369 myDescriptionSearchCheckButton->setToolTipText(TL("Include description in search"));
371 // add separator
372 new FXSeparator(contentFrame);
373 // create buttons frame
374 buttonsFrame = new FXHorizontalFrame(contentFrame, GUIDesignHorizontalFrame);
375 new FXHorizontalFrame(buttonsFrame, GUIDesignAuxiliarHorizontalFrame);
376 // continue depending of dialog type
377 if (runDialog) {
379 } else {
380 GUIDesigns::buildFXButton(buttonsFrame, TL("OK"), "", "", GUIIconSubSys::getIcon(GUIIcon::ACCEPT), this, ID_ACCEPT, GUIDesignButtonOK);
381 }
384 new FXHorizontalFrame(buttonsFrame, GUIDesignAuxiliarHorizontalFrame);
385 // create dialog
386 create();
387 // after creation, adjust entries name sizes
388 for (const auto& entry : myInputOptionEntries) {
389 entry->adjustNameSize();
390 }
391 // set myShowToolTipsMenu
392 myShowToolTipsMenu->setChecked(getApp()->reg().readIntEntry("gui", "menuToolTips", 0) != 1);
393}
394
395/****************************************************************************/
#define TREELISTWIDTH
FXDEFMAP(GNEOptionsDialog) GUIDialogOptionsMap[]
@ MID_GNE_RUNNETGENERATE
run netgenerate tool
Definition GUIAppEnum.h:773
@ MID_GNE_SET_ATTRIBUTE
attribute edited
Definition GUIAppEnum.h:939
@ MID_CANCEL
Cancel-button pressed.
Definition GUIAppEnum.h:308
@ MID_CHOOSEN_SAVE
Save set.
Definition GUIAppEnum.h:603
@ MID_SHOWTOOLTIPS_MENU
Show tool tips in menus - button.
Definition GUIAppEnum.h:387
@ MID_GNE_SEARCH_USEDESCRIPTION
use search description
@ MID_GNE_BUTTON_DEFAULT
default button
@ MID_CHOOSEN_LOAD
Load set.
Definition GUIAppEnum.h:601
@ MID_GNE_SELECT
select element
Definition GUIAppEnum.h:957
@ MID_GNE_RESET
reset element
Definition GUIAppEnum.h:947
@ MID_MTEXTFIELDSEARCH_UPDATED
callback for MFXTextFieldSearch
#define GUIDesignCheckButtonThick
checkButton placed in left position
Definition GUIDesigns.h:195
#define GUIDesignContentsFrame
design for the main content frame of every frame/dialog with padding and spacing
Definition GUIDesigns.h:387
#define GUIDesignTextField
Definition GUIDesigns.h:59
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:399
#define GUIDesignButtonConfiguration
Configuration Button.
Definition GUIDesigns.h:159
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition GUIDesigns.h:74
#define GUIDesignTreeListFixedWidth
Definition GUIDesigns.h:677
#define GUIDesignButtonOK
Definition GUIDesigns.h:153
#define GUIDesignAuxiliarVerticalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:408
#define GUIDesignMFXCheckableButtonSquare
Definition GUIDesigns.h:137
#define GUIDesignAuxiliarFrame
design for auxiliar (Without borders) frame extended in all directions
Definition GUIDesigns.h:390
#define GUIDesignLabelThickedFixed(width)
label thicked, icon before text, text centered and custom width
Definition GUIDesigns.h:252
#define GUIDesignHorizontalFrameNoPadding
Horizontal frame extended over frame parent without padding and spacing.
Definition GUIDesigns.h:331
#define GUIDesignHorizontalFrame
Horizontal frame extended over frame parent with padding and spacing.
Definition GUIDesigns.h:328
#define GUIDesignDialogBoxExplicitStretchable(width, height)
design for dialog box with specific width and height that can be stretched (But not shrunk)
Definition GUIDesigns.h:617
GUIIcon
An enumeration of icons used by the gui applications.
Definition GUIIcons.h:33
@ SHOWTOOLTIPS_MENU
@ OPEN
open icons
@ SAVE
save icons
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:289
#define WRITE_ERROR(msg)
Definition MsgHandler.h:296
#define TL(string)
Definition MsgHandler.h:305
int GUIDesignHeight
the default size for GUI elements
Definition StdDefs.cpp:35
The main window of Netedit.
GNEViewNet * getViewNet()
get pointer to viewNet
long onCmdSaveOptions(FXObject *, FXSelector, void *)
save options
FXTreeItem * myRootItem
root item
FXTreeList * myTopicsTreeList
Topics elements tree.
void updateVisibleEntriesBySearch(std::string searchText)
update visible entries by search
MFXCheckableButton * myShowToolTipsMenu
checkable button for show toolTips
long onCmdCancel(FXObject *, FXSelector, void *)
called when user press cancel button
const std::set< std::string > myIgnoredEntries
ignores entries
long onCmdSelectTopic(FXObject *, FXSelector, void *)
called when user select a topic in the list
std::vector< GNEOptionsDialogElements::InputOption * > myInputOptionEntries
Input option entries.
const std::set< std::string > myIgnoredTopics
ignores topics
long onCmdReset(FXObject *, FXSelector, void *)
called when user press reset button
std::map< FXTreeItem *, std::string > myTreeItemTopics
map with topics and their associated FXTreeItem
GNEApplicationWindow * myGNEApp
pointer to main window parent
~GNEOptionsDialog()
Destructor.
MFXTextFieldSearch * mySearchButton
search button
static std::pair< int, bool > Run(GNEApplicationWindow *GNEApp, GUIIcon icon, OptionsCont &optionsContainer, const OptionsCont &originalOptionsContainer, const char *titleName)
Constructor for run dialogs.
bool loadConfiguration(const std::string &file)
load configuration
static std::pair< int, bool > Options(GNEApplicationWindow *GNEApp, GUIIcon icon, OptionsCont &optionsContainer, const OptionsCont &originalOptionsContainer, const char *titleName)
Constructor for options dialogs.
OptionsCont & myOptionsContainer
reference to edited Option container
FXVerticalFrame * myEntriesFrame
vertical frame for entries
MFXCheckButtonTooltip * myDescriptionSearchCheckButton
checkbox for enable/disable search by description
long onCmdShowToolTipsMenu(FXObject *, FXSelector, void *)
enable/disable show toolTip
long onCmdResetDefault(FXObject *, FXSelector, void *)
reset default
long onCmdSearch(FXObject *, FXSelector, void *)
called when user searches
long onCmdLoadOptions(FXObject *, FXSelector, void *)
load options
bool myOptionsModified
flag for check if options was modified
bool updateVisibleEntriesByTopic()
update visible entries by selected topic
GNEOptionsDialog()
FOX needs this.
long onCmdRunNetgenerate(FXObject *, FXSelector, void *)
called when user press reset button
GNEViewParent * getViewParent() const
get the net 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
MFXCheckableButton * getShowToolTipsMenu() const
get menu for tooltips menu
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
MFXStaticToolTip * getStaticTooltipMenu() const
get static toolTip for menus
void setToolTipText(const FXString &toolTip)
set toolTip
bool amChecked() const
check if this MFXCheckableButton is checked
void setChecked(bool val, const bool inform=false)
check or uncheck this MFXCheckableButton
MFXGroupBoxModule (based on FXGroupBox)
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toggled)
void enableStaticToolTip(const bool value)
enable/disable static tooltip
FXString getText() const
Get the text for this label.
FXTextFieldIcon (based on FXTextFieldIcon)
A storage for options typed value containers)
Definition OptionsCont.h:89
const std::vector< std::string > & getSubTopics() const
return the list of subtopics
std::string getTypeName(const std::string name)
return the type name for the given option
void writeConfiguration(std::ostream &os, const bool filled, const bool complete, const bool addComments, const std::string &relativeTo="", const bool forceRelative=false, const bool inComment=false) const
Writes the configuration.
std::string getValueString(const std::string &name) const
Returns the string-value of the named option (all options)
const std::string & getDescription(const std::string &name) const
Returns the option description.
void resetWritable()
Resets all options to be writeable.
std::vector< std::string > getSubTopicsEntries(const std::string &subtopic) const
return the list of entries for the given subtopic
A SAX-Handler for loading options.
bool errorOccurred() const
Returns the information whether an error occurred.
static std::string to_lower_case(const std::string &str)
Transfers the content to lower case.
static std::string transcode(const XMLCh *const data)
converts a 0-terminated XMLCh* array (usually UTF-16, stemming from Xerces) into std::string in UTF-8
static std::string transcodeToLocal(const std::string &utf8String)
convert a string from UTF-8 to the local codepage
static std::string openOptionFileDialog(FXWindow *window, bool save)
open option dialog