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(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
274 myOptionsContainer(OptionsCont::EMPTY_OPTIONS),
275 myOriginalOptionsContainer(OptionsCont::EMPTY_OPTIONS) {
276}
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
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
@ 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