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-2026 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 <fstream>
23
26#include <netedit/GNEViewNet.h>
34#include <xercesc/parsers/SAXParser.hpp>
35
36#include "GNEOptionsEditor.h"
37
38// ===========================================================================
39// Defines
40// ===========================================================================
41
42#define TREELISTWIDTH 200
43
44// ===========================================================================
45// FOX callback mapping
46// ===========================================================================
47
57
58// Object implementation
59FXIMPLEMENT(GNEOptionsEditor, FXVerticalFrame, GNEOptionsEditorMap, ARRAYNUMBER(GNEOptionsEditorMap))
60
61// ===========================================================================
62// method definitions
63// ===========================================================================
64
65GNEOptionsEditor::GNEOptionsEditor(GNEDialog* dialog, const std::string& titleName, OptionsCont& optionsContainer,
66 const OptionsCont& originalOptionsContainer) :
67 FXVerticalFrame(dialog->getContentFrame(), GUIDesignAuxiliarFrame),
68 myDialog(dialog),
69 myOptionsContainer(optionsContainer),
70 myCopyOfOptionsContainer(optionsContainer.clone()),
71 myOriginalOptionsContainer(originalOptionsContainer) {
72 // get staticTooltipMenu
73 auto staticTooltipMenu = dialog->getApplicationWindow()->getStaticTooltipMenu();
74 // add buttons frame
75 FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(this, GUIDesignHorizontalFrameNoPadding);
76 myShowToolTipsMenu = new MFXCheckableButton(false, buttonsFrame, staticTooltipMenu,
77 (std::string("\t") + TL("Toggle Menu Tooltips") + std::string("\t") + TL("Toggles whether tooltips in the menu shall be shown.")).c_str(),
79 auto saveFile = new MFXButtonTooltip(buttonsFrame, staticTooltipMenu, TL("Save options"),
81 saveFile->setTipText(TL("Save configuration file"));
82 auto loadFile = new MFXButtonTooltip(buttonsFrame, staticTooltipMenu, TL("Load options"),
84 loadFile->setTipText(TL("Load configuration file"));
85 auto resetDefault = new MFXButtonTooltip(buttonsFrame, staticTooltipMenu, TL("Default options"),
87 resetDefault->setTipText(TL("Reset all options to default"));
88 // add separator
89 new FXSeparator(this);
90 // create elements frame
91 FXHorizontalFrame* elementsFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarFrame);
92 FXVerticalFrame* elementsFrameTree = new FXVerticalFrame(elementsFrame, GUIDesignAuxiliarVerticalFrame);
93 FXVerticalFrame* elementsFrameValues = new FXVerticalFrame(elementsFrame, GUIDesignAuxiliarFrame);
94 // Create GroupBox modules
95 GNEGroupBoxModule* groupBoxTree = new GNEGroupBoxModule(elementsFrameTree, TL("Topics"));
96 GNEGroupBoxModule* groupBoxOptions = new GNEGroupBoxModule(elementsFrameValues, TL("Options"));
97 // create FXTreeList
98 myTopicsTreeList = new FXTreeList(groupBoxTree->getCollapsableFrame(), this, MID_GNE_SELECT, GUIDesignTreeListFixedWidth);
99 myTopicsTreeList->setWidth(TREELISTWIDTH);
100 // add root item
101 myRootItem = myTopicsTreeList->appendItem(nullptr, titleName.c_str());
102 myRootItem->setExpanded(TRUE);
103 // create scroll
104 FXScrollWindow* scrollTabEntries = new FXScrollWindow(groupBoxOptions->getCollapsableFrame(), LAYOUT_FILL_X | LAYOUT_FILL_Y);
105 // create vertical frame for entries
106 myEntriesFrame = new FXVerticalFrame(scrollTabEntries, GUIDesignAuxiliarFrame);
107 // iterate over all topics
108 for (const auto& topic : myOptionsContainer.getSubTopics()) {
109 // check if we have to ignore this topic
110 if (myIgnoredTopics.count(topic) == 0) {
111 // add topic into myTreeItemTopics and tree
112 myTreeItemTopics[myTopicsTreeList->appendItem(myRootItem, topic.c_str())] = topic;
113 // processing options require save network
114 const bool requireSaveNetwork = (topic == "Processing");
115 // iterate over entries
116 const std::vector<std::string> entries = myOptionsContainer.getSubTopicsEntries(topic);
117 for (const auto& entry : entries) {
118 // check if we have to ignore this entry
119 if (myIgnoredEntries.count(entry) == 0) {
120 // get type
121 const std::string type = myOptionsContainer.getTypeName(entry);
122 // get description
123 const std::string description = myOptionsContainer.getDescription(entry);
124 // get default value
125 const std::string defaultValue = myOptionsContainer.getValueString(entry);
126 // check if is editable
127 const bool editable = myOptionsContainer.isEditable(entry);
128 // continue depending of type
129 if (type == "STR") {
130 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionString(this, myEntriesFrame, topic, entry, description, defaultValue, editable, requireSaveNetwork));
131 } else if (type == "TIME") {
132 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionTime(this, myEntriesFrame, topic, entry, description, defaultValue, editable, requireSaveNetwork));
133 } else if ((type == "FILE") || (type == "NETWORK") || (type == "ADDITIONAL") || (type == "ROUTE") || (type == "DATA")) {
134 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionFilename(this, myEntriesFrame, topic, entry, description, defaultValue, editable, requireSaveNetwork));
135 } else if (type == "BOOL") {
136 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionBool(this, myEntriesFrame, topic, entry, description, defaultValue, editable, requireSaveNetwork));
137 } else if (type == "INT") {
138 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionInt(this, myEntriesFrame, topic, entry, description, defaultValue, editable, requireSaveNetwork));
139 } else if (type == "FLOAT") {
140 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionFloat(this, myEntriesFrame, topic, entry, description, defaultValue, editable, requireSaveNetwork));
141 } else if (type == "INT[]") {
142 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionIntVector(this, myEntriesFrame, topic, entry, description, defaultValue, editable, requireSaveNetwork));
143 } else if (type == "STR[]") {
144 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionStringVector(this, myEntriesFrame, topic, entry, description, defaultValue, editable, requireSaveNetwork));
145 }
146 }
147 }
148 }
149 }
150 // create search elements
151 FXHorizontalFrame* searchFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
152 new FXLabel(searchFrame, TL("Search"), nullptr, GUIDesignLabelThickedFixed(TREELISTWIDTH - GUIDesignHeight + 14));
153 myDescriptionSearchCheckButton = new MFXCheckButtonTooltip(searchFrame, staticTooltipMenu, "", this, MID_GNE_SEARCH_USEDESCRIPTION, GUIDesignCheckButtonThick);
154 myDescriptionSearchCheckButton->setToolTipText(TL("Include description in search"));
155 mySearchButton = new MFXTextFieldSearch(searchFrame, staticTooltipMenu, this, MID_GNE_SET_ATTRIBUTE, GUIDesignTextField);
156 // after creation, adjust entries name sizes
157 for (const auto& entry : myOptionRowEntries) {
158 entry->adjustNameSize();
159 }
160 // set myShowToolTipsMenu
161 myShowToolTipsMenu->setChecked(getApp()->reg().readIntEntry("gui", "menuToolTips", 0) != 1);
162}
163
164
168
169
170void
172 // not finished yet
173}
174
175
176bool
180
181
182bool
186
187
188void
190 for (const auto& entry : myOptionRowEntries) {
191 entry->onCmdResetOption(nullptr, 0, nullptr);
192 }
193 myOptionsModified = false;
194 myRequireSaveNetwork = false;
195}
196
197
198long
199GNEOptionsEditor::onCmdSelectTopic(FXObject*, FXSelector, void*) {
200 if (mySearchButton->getText().count() == 0) {
202 }
203 return 1;
204}
205
206
207long
208GNEOptionsEditor::onCmdSearch(FXObject*, FXSelector, void*) {
209 if (mySearchButton->getText().count() > 0) {
211 } else {
213 }
214 return 1;
215}
216
217
218long
219GNEOptionsEditor::onCmdShowToolTipsMenu(FXObject*, FXSelector, void*) {
220 // get staticTooltipMenu
221 auto viewNet = myDialog->getApplicationWindow()->getViewNet();
222 // toggle check
224 if (viewNet) {
225 viewNet->getViewParent()->getShowToolTipsMenu()->setChecked(myShowToolTipsMenu->amChecked());
226 viewNet->getViewParent()->getShowToolTipsMenu()->update();
227 }
228 // enable/disable static tooltip
230 // save in registry
231 getApp()->reg().writeIntEntry("gui", "menuToolTips", myShowToolTipsMenu->amChecked() ? 0 : 1);
232 update();
233
234 return 1;
235}
236
237
238long
239GNEOptionsEditor::onCmdSaveOptions(FXObject*, FXSelector, void*) {
240 // open file dialog
241 const GNEFileDialog optionsFileDialog(myDialog->getApplicationWindow(), myDialog,
242 TL("options file"),
246 // check file
247 if (optionsFileDialog.getResult() == GNEDialog::Result::ACCEPT) {
248 std::ofstream out(StringUtils::transcodeToLocal(optionsFileDialog.getFilename()));
249 myOptionsContainer.writeConfiguration(out, true, false, false, optionsFileDialog.getFilename(), true);
250 out.close();
251 }
252 return 1;
253}
254
255
256long
257GNEOptionsEditor::onCmdLoadOptions(FXObject*, FXSelector, void*) {
258 // open file dialog
259 const GNEFileDialog optionsFileDialog(myDialog->getApplicationWindow(), myDialog,
260 TL("options file"),
264 // check file
265 if ((optionsFileDialog.getResult() == GNEDialog::Result::ACCEPT) && loadConfiguration(optionsFileDialog.getFilename())) {
266 // update entries
267 for (const auto& entry : myOptionRowEntries) {
268 entry->updateOption();
269 }
270 }
271 return 1;
272}
273
274
275long
276GNEOptionsEditor::onCmdResetDefault(FXObject*, FXSelector, void*) {
277 // restore entries
278 for (const auto& entry : myOptionRowEntries) {
279 if (entry->isEditable()) {
280 entry->restoreOption();
281 }
282 }
283 return 1;
284}
285
286
288 myOptionsContainer(OptionsCont::EMPTY_OPTIONS),
289 myOriginalOptionsContainer(OptionsCont::EMPTY_OPTIONS) {
290}
291
292
293bool
295 // iterate over tree elements and get the selected item
296 for (const auto& treeItemTopic : myTreeItemTopics) {
297 if (treeItemTopic.first->isSelected()) {
298 // iterate over entries
299 for (const auto& entry : myOptionRowEntries) {
300 if (entry->getTopic() == treeItemTopic.second) {
301 entry->show();
302 } else {
303 entry->hide();
304 }
305 }
306 myEntriesFrame->recalc();
307 myEntriesFrame->update();
308 return true;
309 }
310 }
311 // no topic selected, then show all
312 for (const auto& entry : myOptionRowEntries) {
313 entry->show();
314 }
315 myEntriesFrame->recalc();
316 myEntriesFrame->update();
317 return true;
318}
319
320
321void
323 // first lower case search text
324 searchText = StringUtils::to_lower_case(searchText);
325 // iterate over entries
326 for (const auto& entry : myOptionRowEntries) {
327 if (searchText.empty()) {
328 // show all entries if searchText is empty
329 entry->show();
330 } else if (entry->getNameLower().find(searchText) != std::string::npos) {
331 entry->show();
332 } else if ((myDescriptionSearchCheckButton->getCheck() == TRUE) &&
333 (entry->getDescriptionLower().find(searchText) != std::string::npos)) {
334 entry->show();
335 } else {
336 entry->hide();
337 }
338 }
339 myEntriesFrame->recalc();
340 myEntriesFrame->update();
341}
342
343
344bool
345GNEOptionsEditor::loadConfiguration(const std::string& file) {
346 // make all options writable
348 // build parser
349 XERCES_CPP_NAMESPACE::SAXParser parser;
350 parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
351 parser.setDisableDefaultEntityResolution(true);
352 // start the parsing
354 try {
355 parser.setDocumentHandler(&handler);
356 parser.setErrorHandler(&handler);
357 parser.parse(StringUtils::transcodeToLocal(file).c_str());
358 if (handler.errorOccurred()) {
359 WRITE_ERROR(TL("Could not load configuration '") + file + "'.");
360 return false;
361 }
362 } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
363 WRITE_ERROR(TL("Could not load tool configuration '") + file + "':\n " + StringUtils::transcode(e.getMessage()));
364 return false;
365 }
366 // write info
367 WRITE_MESSAGE(TL("Loaded configuration."));
368 return true;
369}
370
371/****************************************************************************/
#define TREELISTWIDTH
FXDEFMAP(GNEOptionsEditor) GNEOptionsEditorMap[]
@ MID_GNE_SET_ATTRIBUTE
attribute edited
@ MID_CHOOSEN_SAVE
Save set.
Definition GUIAppEnum.h:605
@ MID_SHOWTOOLTIPS_MENU
Show tool tips in menus - button.
Definition GUIAppEnum.h:389
@ MID_GNE_SEARCH_USEDESCRIPTION
use search description
@ MID_GNE_BUTTON_DEFAULT
default button
@ MID_CHOOSEN_LOAD
Load set.
Definition GUIAppEnum.h:603
@ 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:288
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:304
int GUIDesignHeight
the default height for GUI elements
Definition StdDefs.cpp:41
GNEViewNet * getViewNet()
get pointer to viewNet
GNEApplicationWindow * getApplicationWindow() const
get pointer to the application window
Result getResult() const
get result to indicate if this dialog was closed accepting or rejecting changes
std::string getFilename() const
Return file name, if any.
GNEGroupBoxModule (based on FXGroupBox)
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toggled)
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
bool requireSaveNetwork() const
check if option require save network
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 myRequireSaveNetwork
flag for check if options require save network
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
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 std::string &indent="") 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