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
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));
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
211 myShowToolTipsMenu->setChecked(!myShowToolTipsMenu->amChecked());
212 if (viewNet) {
213 viewNet->getViewParent()->getShowToolTipsMenu()->setChecked(myShowToolTipsMenu->amChecked());
214 viewNet->getViewParent()->getShowToolTipsMenu()->update();
215 }
216 // enable/disable static tooltip
217 myDialog->getApplicationWindow()->getStaticTooltipMenu()->enableStaticToolTip(myShowToolTipsMenu->amChecked());
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(this, myDialog->getApplicationWindow(),
230 TL("options file"),
234 // check file
235 if (optionsFileDialog.getResult() == GNEDialog::Result::ACCEPT) {
236 std::ofstream out(StringUtils::transcodeToLocal(optionsFileDialog.getFilename()));
237 myOptionsContainer.writeConfiguration(out, true, false, false, optionsFileDialog.getFilename(), true);
238 out.close();
239 }
240 return 1;
241}
242
243
244long
245GNEOptionsEditor::onCmdLoadOptions(FXObject*, FXSelector, void*) {
246 // open file dialog
247 const auto optionsFileDialog = GNEFileDialog(this, myDialog->getApplicationWindow(),
248 TL("options file"),
252 // check file
253 if ((optionsFileDialog.getResult() == GNEDialog::Result::ACCEPT) && loadConfiguration(optionsFileDialog.getFilename())) {
254 // update entries
255 for (const auto& entry : myOptionRowEntries) {
256 entry->updateOption();
257 }
258 }
259 return 1;
260}
261
262
263long
264GNEOptionsEditor::onCmdResetDefault(FXObject*, FXSelector, void*) {
265 // restore entries
266 for (const auto& entry : myOptionRowEntries) {
267 entry->restoreOption();
268 }
269 return 1;
270}
271
272
277
278
279bool
281 // iterate over tree elements and get the selected item
282 for (const auto& treeItemTopic : myTreeItemTopics) {
283 if (treeItemTopic.first->isSelected()) {
284 // iterate over entries
285 for (const auto& entry : myOptionRowEntries) {
286 if (entry->getTopic() == treeItemTopic.second) {
287 entry->show();
288 } else {
289 entry->hide();
290 }
291 }
292 myEntriesFrame->recalc();
293 myEntriesFrame->update();
294 return true;
295 }
296 }
297 // no topic selected, then show all
298 for (const auto& entry : myOptionRowEntries) {
299 entry->show();
300 }
301 myEntriesFrame->recalc();
302 myEntriesFrame->update();
303 return true;
304}
305
306
307void
309 // first lower case search text
310 searchText = StringUtils::to_lower_case(searchText);
311 // iterate over entries
312 for (const auto& entry : myOptionRowEntries) {
313 if (searchText.empty()) {
314 // show all entries if searchText is empty
315 entry->show();
316 } else if (entry->getNameLower().find(searchText) != std::string::npos) {
317 entry->show();
318 } else if ((myDescriptionSearchCheckButton->getCheck() == TRUE) &&
319 (entry->getDescriptionLower().find(searchText) != std::string::npos)) {
320 entry->show();
321 } else {
322 entry->hide();
323 }
324 }
325 myEntriesFrame->recalc();
326 myEntriesFrame->update();
327}
328
329
330bool
331GNEOptionsEditor::loadConfiguration(const std::string& file) {
332 // make all options writable
333 myOptionsContainer.resetWritable();
334 // build parser
335 XERCES_CPP_NAMESPACE::SAXParser parser;
336 parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
337 parser.setDisableDefaultEntityResolution(true);
338 // start the parsing
340 try {
341 parser.setDocumentHandler(&handler);
342 parser.setErrorHandler(&handler);
343 parser.parse(StringUtils::transcodeToLocal(file).c_str());
344 if (handler.errorOccurred()) {
345 WRITE_ERROR(TL("Could not load configuration '") + file + "'.");
346 return false;
347 }
348 } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
349 WRITE_ERROR(TL("Could not load tool configuration '") + file + "':\n " + StringUtils::transcode(e.getMessage()));
350 return false;
351 }
352 // write info
353 WRITE_MESSAGE(TL("Loaded configuration."));
354 return true;
355}
356
357/****************************************************************************/
#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
Definition GUIIcons.h:190
@ OPEN
open icons
Definition GUIIcons.h:77
@ SAVE
save icons
Definition GUIIcons.h:90
#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
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
const OptionsCont & myOriginalOptionsContainer
reference to original Option container, used for restoring
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.
const std::set< std::string > myIgnoredEntries
ignores entries
FXTreeItem * myRootItem
root item
GNEOptionsEditor(GNEDialog *dialog, const std::string &titleName, OptionsCont &optionsContainer, const OptionsCont &originalOptionsContainer)
Constructor.
std::map< FXTreeItem *, std::string > myTreeItemTopics
map with topics and their associated FXTreeItem
const std::set< std::string > myIgnoredTopics
ignores topics
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.
FXTreeList * myTopicsTreeList
Topics elements tree.
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
dialog arguments, used for certain modal dialogs that can not be edited using tab
MFXGroupBoxModule (based on FXGroupBox).
FXVerticalFrame * getCollapsableFrame()
get collapsable frame (used by all elements that will be collapsed if button is toggled)
FXTextFieldIcon (based on FXTextFieldIcon).
A storage for options typed value containers).
Definition OptionsCont.h:89
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