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#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 // iterate over entries
114 const std::vector<std::string> entries = myOptionsContainer.getSubTopicsEntries(topic);
115 for (const auto& entry : entries) {
116 // check if we have to ignore this entry
117 if (myIgnoredEntries.count(entry) == 0) {
118 // get type
119 const std::string type = myOptionsContainer.getTypeName(entry);
120 // get description
121 const std::string description = myOptionsContainer.getDescription(entry);
122 // get default value
123 const std::string defaultValue = myOptionsContainer.getValueString(entry);
124 // check if is editable
125 const bool editable = myOptionsContainer.isEditable(entry);
126 // continue depending of type
127 if (type == "STR") {
128 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionString(this, myEntriesFrame, topic, entry, description, defaultValue, editable));
129 } else if (type == "TIME") {
130 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionTime(this, myEntriesFrame, topic, entry, description, defaultValue, editable));
131 } else if ((type == "FILE") || (type == "NETWORK") || (type == "ADDITIONAL") || (type == "ROUTE") || (type == "DATA")) {
132 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionFilename(this, myEntriesFrame, topic, entry, description, defaultValue, editable));
133 } else if (type == "BOOL") {
134 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionBool(this, myEntriesFrame, topic, entry, description, defaultValue, editable));
135 } else if (type == "INT") {
136 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionInt(this, myEntriesFrame, topic, entry, description, defaultValue, editable));
137 } else if (type == "FLOAT") {
138 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionFloat(this, myEntriesFrame, topic, entry, description, defaultValue, editable));
139 } else if (type == "INT[]") {
140 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionIntVector(this, myEntriesFrame, topic, entry, description, defaultValue, editable));
141 } else if (type == "STR[]") {
142 myOptionRowEntries.push_back(new GNEOptionsEditorRow::OptionStringVector(this, myEntriesFrame, topic, entry, description, defaultValue, editable));
143 }
144 }
145 }
146 }
147 }
148 // create search elements
149 FXHorizontalFrame* searchFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarHorizontalFrame);
150 new FXLabel(searchFrame, TL("Search"), nullptr, GUIDesignLabelThickedFixed(TREELISTWIDTH - GUIDesignHeight + 14));
151 myDescriptionSearchCheckButton = new MFXCheckButtonTooltip(searchFrame, staticTooltipMenu, "", this, MID_GNE_SEARCH_USEDESCRIPTION, GUIDesignCheckButtonThick);
152 myDescriptionSearchCheckButton->setToolTipText(TL("Include description in search"));
153 mySearchButton = new MFXTextFieldSearch(searchFrame, staticTooltipMenu, this, MID_GNE_SET_ATTRIBUTE, GUIDesignTextField);
154 // after creation, adjust entries name sizes
155 for (const auto& entry : myOptionRowEntries) {
156 entry->adjustNameSize();
157 }
158 // set myShowToolTipsMenu
159 myShowToolTipsMenu->setChecked(getApp()->reg().readIntEntry("gui", "menuToolTips", 0) != 1);
160}
161
162
166
167
168void
170 // not finished yet
171}
172
173
174bool
178
179void
181 for (const auto& entry : myOptionRowEntries) {
182 entry->onCmdResetOption(nullptr, 0, nullptr);
183 }
184 myOptionsModified = false;
185}
186
187
188long
189GNEOptionsEditor::onCmdSelectTopic(FXObject*, FXSelector, void*) {
190 if (mySearchButton->getText().count() == 0) {
192 }
193 return 1;
194}
195
196
197long
198GNEOptionsEditor::onCmdSearch(FXObject*, FXSelector, void*) {
199 if (mySearchButton->getText().count() > 0) {
201 } else {
203 }
204 return 1;
205}
206
207
208long
209GNEOptionsEditor::onCmdShowToolTipsMenu(FXObject*, FXSelector, void*) {
210 // get staticTooltipMenu
211 auto viewNet = myDialog->getApplicationWindow()->getViewNet();
212 // toggle check
214 if (viewNet) {
215 viewNet->getViewParent()->getShowToolTipsMenu()->setChecked(myShowToolTipsMenu->amChecked());
216 viewNet->getViewParent()->getShowToolTipsMenu()->update();
217 }
218 // enable/disable static tooltip
220 // save in registry
221 getApp()->reg().writeIntEntry("gui", "menuToolTips", myShowToolTipsMenu->amChecked() ? 0 : 1);
222 update();
223
224 return 1;
225}
226
227
228long
229GNEOptionsEditor::onCmdSaveOptions(FXObject*, FXSelector, void*) {
230 // open file dialog
231 const GNEFileDialog optionsFileDialog(myDialog->getApplicationWindow(), myDialog,
232 TL("options file"),
236 // check file
237 if (optionsFileDialog.getResult() == GNEDialog::Result::ACCEPT) {
238 std::ofstream out(StringUtils::transcodeToLocal(optionsFileDialog.getFilename()));
239 myOptionsContainer.writeConfiguration(out, true, false, false, optionsFileDialog.getFilename(), true);
240 out.close();
241 }
242 return 1;
243}
244
245
246long
247GNEOptionsEditor::onCmdLoadOptions(FXObject*, FXSelector, void*) {
248 // open file dialog
249 const GNEFileDialog optionsFileDialog(myDialog->getApplicationWindow(), myDialog,
250 TL("options file"),
254 // check file
255 if ((optionsFileDialog.getResult() == GNEDialog::Result::ACCEPT) && loadConfiguration(optionsFileDialog.getFilename())) {
256 // update entries
257 for (const auto& entry : myOptionRowEntries) {
258 entry->updateOption();
259 }
260 }
261 return 1;
262}
263
264
265long
266GNEOptionsEditor::onCmdResetDefault(FXObject*, FXSelector, void*) {
267 // restore entries
268 for (const auto& entry : myOptionRowEntries) {
269 entry->restoreOption();
270 }
271 return 1;
272}
273
274
276 myOptionsContainer(OptionsCont::EMPTY_OPTIONS),
277 myOriginalOptionsContainer(OptionsCont::EMPTY_OPTIONS) {
278}
279
280
281bool
283 // iterate over tree elements and get the selected item
284 for (const auto& treeItemTopic : myTreeItemTopics) {
285 if (treeItemTopic.first->isSelected()) {
286 // iterate over entries
287 for (const auto& entry : myOptionRowEntries) {
288 if (entry->getTopic() == treeItemTopic.second) {
289 entry->show();
290 } else {
291 entry->hide();
292 }
293 }
294 myEntriesFrame->recalc();
295 myEntriesFrame->update();
296 return true;
297 }
298 }
299 // no topic selected, then show all
300 for (const auto& entry : myOptionRowEntries) {
301 entry->show();
302 }
303 myEntriesFrame->recalc();
304 myEntriesFrame->update();
305 return true;
306}
307
308
309void
311 // first lower case search text
312 searchText = StringUtils::to_lower_case(searchText);
313 // iterate over entries
314 for (const auto& entry : myOptionRowEntries) {
315 if (searchText.empty()) {
316 // show all entries if searchText is empty
317 entry->show();
318 } else if (entry->getNameLower().find(searchText) != std::string::npos) {
319 entry->show();
320 } else if ((myDescriptionSearchCheckButton->getCheck() == TRUE) &&
321 (entry->getDescriptionLower().find(searchText) != std::string::npos)) {
322 entry->show();
323 } else {
324 entry->hide();
325 }
326 }
327 myEntriesFrame->recalc();
328 myEntriesFrame->update();
329}
330
331
332bool
333GNEOptionsEditor::loadConfiguration(const std::string& file) {
334 // make all options writable
336 // build parser
337 XERCES_CPP_NAMESPACE::SAXParser parser;
338 parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
339 parser.setDisableDefaultEntityResolution(true);
340 // start the parsing
342 try {
343 parser.setDocumentHandler(&handler);
344 parser.setErrorHandler(&handler);
345 parser.parse(StringUtils::transcodeToLocal(file).c_str());
346 if (handler.errorOccurred()) {
347 WRITE_ERROR(TL("Could not load configuration '") + file + "'.");
348 return false;
349 }
350 } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
351 WRITE_ERROR(TL("Could not load tool configuration '") + file + "':\n " + StringUtils::transcode(e.getMessage()));
352 return false;
353 }
354 // write info
355 WRITE_MESSAGE(TL("Loaded configuration."));
356 return true;
357}
358
359/****************************************************************************/
#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:40
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
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
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