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