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