Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GNEOptionsEditor.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
21#include <fstream>
22
25#include <netedit/GNEViewNet.h>
33#include <xercesc/parsers/SAXParser.hpp>
34
35#include "GNEOptionsEditor.h"
36
37// ===========================================================================
38// Defines
39// ===========================================================================
40
41#define TREELISTWIDTH 200
42
43// ===========================================================================
44// FOX callback mapping
45// ===========================================================================
46
56
57// Object implementation
58FXIMPLEMENT(GNEOptionsEditor, FXVerticalFrame, GNEOptionsEditorMap, ARRAYNUMBER(GNEOptionsEditorMap))
59
60// ===========================================================================
61// method definitions
62// ===========================================================================
63
64GNEOptionsEditor::GNEOptionsEditor(GNEDialog* dialog, const std::string& titleName, OptionsCont& optionsContainer,
65 const OptionsCont& originalOptionsContainer) :
66 FXVerticalFrame(dialog->getContentFrame(), GUIDesignAuxiliarFrame),
67 myDialog(dialog),
68 myOptionsContainer(optionsContainer),
69 myCopyOfOptionsContainer(optionsContainer.clone()),
70 myOriginalOptionsContainer(originalOptionsContainer) {
71 // get staticTooltipMenu
72 auto staticTooltipMenu = dialog->getApplicationWindow()->getStaticTooltipMenu();
73 // add buttons frame
74 FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(this, GUIDesignHorizontalFrameNoPadding);
75 myShowToolTipsMenu = new MFXCheckableButton(false, buttonsFrame, staticTooltipMenu,
76 (std::string("\t") + TL("Toggle Menu Tooltips") + std::string("\t") + TL("Toggles whether tooltips in the menu shall be shown.")).c_str(),
78 auto saveFile = new MFXButtonTooltip(buttonsFrame, staticTooltipMenu, TL("Save options"),
80 saveFile->setTipText(TL("Save configuration file"));
81 auto loadFile = new MFXButtonTooltip(buttonsFrame, staticTooltipMenu, TL("Load options"),
83 loadFile->setTipText(TL("Load configuration file"));
84 auto resetDefault = new MFXButtonTooltip(buttonsFrame, staticTooltipMenu, TL("Default options"),
86 resetDefault->setTipText(TL("Reset all options to default"));
87 // add separator
88 new FXSeparator(this);
89 // create elements frame
90 FXHorizontalFrame* elementsFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarFrame);
91 FXVerticalFrame* elementsFrameTree = new FXVerticalFrame(elementsFrame, GUIDesignAuxiliarVerticalFrame);
92 FXVerticalFrame* elementsFrameValues = new FXVerticalFrame(elementsFrame, GUIDesignAuxiliarFrame);
93 // Create GroupBox modules
94 MFXGroupBoxModule* groupBoxTree = new MFXGroupBoxModule(elementsFrameTree, TL("Topics"));
95 MFXGroupBoxModule* groupBoxOptions = new MFXGroupBoxModule(elementsFrameValues, TL("Options"));
96 // create FXTreeList
97 myTopicsTreeList = new FXTreeList(groupBoxTree->getCollapsableFrame(), this, MID_GNE_SELECT, GUIDesignTreeListFixedWidth);
98 myTopicsTreeList->setWidth(TREELISTWIDTH);
99 // add root item
100 myRootItem = myTopicsTreeList->appendItem(nullptr, titleName.c_str());
101 myRootItem->setExpanded(TRUE);
102 // create scroll
103 FXScrollWindow* scrollTabEntries = new FXScrollWindow(groupBoxOptions->getCollapsableFrame(), LAYOUT_FILL_X | LAYOUT_FILL_Y);
104 // create vertical frame for entries
105 myEntriesFrame = new FXVerticalFrame(scrollTabEntries, GUIDesignAuxiliarFrame);
106 // iterate over all topics
107 for (const auto& topic : myOptionsContainer.getSubTopics()) {
108 // check if we have to ignore this topic
109 if (myIgnoredTopics.count(topic) == 0) {
110 // add topic into myTreeItemTopics and tree
111 myTreeItemTopics[myTopicsTreeList->appendItem(myRootItem, topic.c_str())] = topic;
112 // iterate over entries
113 const std::vector<std::string> entries = myOptionsContainer.getSubTopicsEntries(topic);
114 for (const auto& entry : entries) {
115 // check if we have to ignore this entry
116 if (myIgnoredEntries.count(entry) == 0) {
117 // get type
118 const std::string type = myOptionsContainer.getTypeName(entry);
119 // get description
120 const std::string description = myOptionsContainer.getDescription(entry);
121 // get default value
122 const std::string defaultValue = myOptionsContainer.getValueString(entry);
123 // continue depending of type
124 if (type == "STR") {
125 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionString(this, myEntriesFrame, topic, entry, description, defaultValue));
126 } else if (type == "TIME") {
127 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionTime(this, myEntriesFrame, topic, entry, description, defaultValue));
128 } else if ((type == "FILE") || (type == "NETWORK") || (type == "ADDITIONAL") || (type == "ROUTE") || (type == "DATA")) {
129 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionFilename(this, myEntriesFrame, topic, entry, description, defaultValue));
130 } else if (type == "BOOL") {
131 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionBool(this, myEntriesFrame, topic, entry, description, defaultValue));
132 } else if (type == "INT") {
133 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionInt(this, myEntriesFrame, topic, entry, description, defaultValue));
134 } else if (type == "FLOAT") {
135 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionFloat(this, myEntriesFrame, topic, entry, description, defaultValue));
136 } else if (type == "INT[]") {
137 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionIntVector(this, myEntriesFrame, topic, entry, description, defaultValue));
138 } else if (type == "STR[]") {
139 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionStringVector(this, myEntriesFrame, topic, entry, description, defaultValue));
140 }
141 }
142 }
143 }
144 }
145 // create search elements
146 FXHorizontalFrame* searchFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
147 new FXLabel(searchFrame, TL("Search"), nullptr, GUIDesignLabelThickedFixed(TREELISTWIDTH - GUIDesignHeight + 14));
148 myDescriptionSearchCheckButton = new MFXCheckButtonTooltip(searchFrame, staticTooltipMenu, "", this, MID_GNE_SEARCH_USEDESCRIPTION, GUIDesignCheckButtonThick);
149 myDescriptionSearchCheckButton->setToolTipText(TL("Include description in search"));
150 mySearchButton = new MFXTextFieldSearch(searchFrame, staticTooltipMenu, this, MID_GNE_SET_ATTRIBUTE, GUIDesignTextField);
151 // after creation, adjust entries name sizes
152 for (const auto& entry : myOptionRowEntries) {
153 entry->adjustNameSize();
154 }
155 // set myShowToolTipsMenu
156 myShowToolTipsMenu->setChecked(getApp()->reg().readIntEntry("gui", "menuToolTips", 0) != 1);
157}
158
159
163
164
165void
167 // not finished yet
168}
169
170
171bool
175
176void
178 for (const auto& entry : myOptionRowEntries) {
179 entry->onCmdResetOption(nullptr, 0, nullptr);
180 }
181 myOptionsModified = false;
182}
183
184
185long
186GNEOptionsEditor::onCmdSelectTopic(FXObject*, FXSelector, void*) {
187 if (mySearchButton->getText().count() == 0) {
189 }
190 return 1;
191}
192
193
194long
195GNEOptionsEditor::onCmdSearch(FXObject*, FXSelector, void*) {
196 if (mySearchButton->getText().count() > 0) {
198 } else {
200 }
201 return 1;
202}
203
204
205long
206GNEOptionsEditor::onCmdShowToolTipsMenu(FXObject*, FXSelector, void*) {
207 // get staticTooltipMenu
208 auto viewNet = myDialog->getApplicationWindow()->getViewNet();
209 // toggle check
211 if (viewNet) {
212 viewNet->getViewParent()->getShowToolTipsMenu()->setChecked(myShowToolTipsMenu->amChecked());
213 viewNet->getViewParent()->getShowToolTipsMenu()->update();
214 }
215 // enable/disable static tooltip
217 // save in registry
218 getApp()->reg().writeIntEntry("gui", "menuToolTips", myShowToolTipsMenu->amChecked() ? 0 : 1);
219 update();
220
221 return 1;
222}
223
224
225long
226GNEOptionsEditor::onCmdSaveOptions(FXObject*, FXSelector, void*) {
227 // open file dialog
228 const auto optionsFileDialog = GNEFileDialog(myDialog->getApplicationWindow(), TL("options file"),
232 // check file
233 if (optionsFileDialog.getResult() == GNEDialog::Result::ACCEPT) {
234 std::ofstream out(StringUtils::transcodeToLocal(optionsFileDialog.getFilename()));
235 myOptionsContainer.writeConfiguration(out, true, false, false, optionsFileDialog.getFilename(), true);
236 out.close();
237 }
238 return 1;
239}
240
241
242long
243GNEOptionsEditor::onCmdLoadOptions(FXObject*, FXSelector, void*) {
244 // open file dialog
245 const auto optionsFileDialog = GNEFileDialog(myDialog->getApplicationWindow(), TL("options file"),
249 // check file
250 if ((optionsFileDialog.getResult() == GNEDialog::Result::ACCEPT) && loadConfiguration(optionsFileDialog.getFilename())) {
251 // update entries
252 for (const auto& entry : myOptionRowEntries) {
253 entry->updateOption();
254 }
255 }
256 return 1;
257}
258
259
260long
261GNEOptionsEditor::onCmdResetDefault(FXObject*, FXSelector, void*) {
262 // restore entries
263 for (const auto& entry : myOptionRowEntries) {
264 entry->restoreOption();
265 }
266 return 1;
267}
268
269
271 myOptionsContainer(OptionsCont::EMPTY_OPTIONS),
272 myOriginalOptionsContainer(OptionsCont::EMPTY_OPTIONS) {
273}
274
275
276bool
278 // iterate over tree elements and get the selected item
279 for (const auto& treeItemTopic : myTreeItemTopics) {
280 if (treeItemTopic.first->isSelected()) {
281 // iterate over entries
282 for (const auto& entry : myOptionRowEntries) {
283 if (entry->getTopic() == treeItemTopic.second) {
284 entry->show();
285 } else {
286 entry->hide();
287 }
288 }
289 myEntriesFrame->recalc();
290 myEntriesFrame->update();
291 return true;
292 }
293 }
294 // no topic selected, then show all
295 for (const auto& entry : myOptionRowEntries) {
296 entry->show();
297 }
298 myEntriesFrame->recalc();
299 myEntriesFrame->update();
300 return true;
301}
302
303
304void
306 // first lower case search text
307 searchText = StringUtils::to_lower_case(searchText);
308 // iterate over entries
309 for (const auto& entry : myOptionRowEntries) {
310 if (searchText.empty()) {
311 // show all entries if searchText is empty
312 entry->show();
313 } else if (entry->getNameLower().find(searchText) != std::string::npos) {
314 entry->show();
315 } else if ((myDescriptionSearchCheckButton->getCheck() == TRUE) &&
316 (entry->getDescriptionLower().find(searchText) != std::string::npos)) {
317 entry->show();
318 } else {
319 entry->hide();
320 }
321 }
322 myEntriesFrame->recalc();
323 myEntriesFrame->update();
324}
325
326
327bool
328GNEOptionsEditor::loadConfiguration(const std::string& file) {
329 // make all options writable
331 // build parser
332 XERCES_CPP_NAMESPACE::SAXParser parser;
333 parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
334 parser.setDisableDefaultEntityResolution(true);
335 // start the parsing
337 try {
338 parser.setDocumentHandler(&handler);
339 parser.setErrorHandler(&handler);
340 parser.parse(StringUtils::transcodeToLocal(file).c_str());
341 if (handler.errorOccurred()) {
342 WRITE_ERROR(TL("Could not load configuration '") + file + "'.");
343 return false;
344 }
345 } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
346 WRITE_ERROR(TL("Could not load tool configuration '") + file + "':\n " + StringUtils::transcode(e.getMessage()));
347 return false;
348 }
349 // write info
350 WRITE_MESSAGE(TL("Loaded configuration."));
351 return true;
352}
353
354/****************************************************************************/
#define TREELISTWIDTH
FXDEFMAP(GNEOptionsEditor) GNEOptionsEditorMap[]
@ MID_GNE_SET_ATTRIBUTE
attribute edited
Definition GUIAppEnum.h:991
@ 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
@ MID_MTEXTFIELDSEARCH_UPDATED
callback for MFXTextFieldSearch
#define GUIDesignCheckButtonThick
checkButton placed in left position
Definition GUIDesigns.h:197
#define GUIDesignTextField
Definition GUIDesigns.h:74
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:430
#define GUIDesignButtonConfiguration
Configuration Button.
Definition GUIDesigns.h:177
#define GUIDesignTreeListFixedWidth
Definition GUIDesigns.h:693
#define GUIDesignAuxiliarVerticalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition GUIDesigns.h:439
#define GUIDesignMFXCheckableButtonSquare
Definition GUIDesigns.h:158
#define GUIDesignAuxiliarFrame
design for auxiliar (Without borders) frame extended in all directions
Definition GUIDesigns.h:409
#define GUIDesignLabelThickedFixed(width)
label thicked, icon before text, text centered and custom width
Definition GUIDesigns.h:254
#define GUIDesignHorizontalFrameNoPadding
Horizontal frame extended over frame parent without padding and spacing.
Definition GUIDesigns.h:350
@ 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 height for GUI elements
Definition StdDefs.cpp:37
GNEViewNet * getViewNet()
get pointer to viewNet
GNEApplicationWindow * getApplicationWindow() const
get pointer to the application window
Definition GNEDialog.cpp:93
long onCmdSaveOptions(FXObject *, FXSelector, void *)
save options
void resetAllOptions()
reset options
bool loadConfiguration(const std::string &file)
load configuration
long onCmdShowToolTipsMenu(FXObject *, FXSelector, void *)
enable/disable show toolTip
FXVerticalFrame * myEntriesFrame
vertical frame for entries
long onCmdSearch(FXObject *, FXSelector, void *)
called when user searches
long onCmdLoadOptions(FXObject *, FXSelector, void *)
load options
MFXTextFieldSearch * mySearchButton
search button
GNEDialog * myDialog
reference to dialog
OptionsCont & myOptionsContainer
reference to edited Option container
bool myOptionsModified
flag for check if options was modified
MFXCheckButtonTooltip * myDescriptionSearchCheckButton
checkbox for enable/disable search by description
void runInternalTest(const InternalTestStep::DialogArgument *dialogArgument)
run internal test
long onCmdResetDefault(FXObject *, FXSelector, void *)
reset default
MFXCheckableButton * myShowToolTipsMenu
checkable button for show toolTips
long onCmdSelectTopic(FXObject *, FXSelector, void *)
called when user select a topic in the list
OptionsCont * myCopyOfOptionsContainer
copy of edited Option container, used for reset
GNEOptionsEditor()
FOX needs this.
std::map< FXTreeItem *, std::string > myTreeItemTopics
map with topics and their associated FXTreeItem
bool updateVisibleEntriesByTopic()
update visible entries by selected topic
void updateVisibleEntriesBySearch(std::string searchText)
update visible entries by search
bool isOptionModified() const
check if option was modified
std::vector< GNEOptionsEditorRow::OptionRow * > myOptionRowEntries
Input option entries.
~GNEOptionsEditor()
Destructor.
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
MFXStaticToolTip * getStaticTooltipMenu() const
get static toolTip for menus
dialog arguments, used for certain modal dialogs that can not be edited using tab
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
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.
void resetWritable()
Resets all options to be writeable.
A SAX-Handler for loading options.
bool errorOccurred() const
Returns the information whether an error occurred.
static StringBijection< XMLFileExtension > XMLFileExtensions
XML file Extensions.
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
Definition json.hpp:4471