Eclipse SUMO - Simulation of Urban MObility
GNEOptionsDialog.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-2024 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 <algorithm>
23 #include <fstream>
32 #include <xercesc/parsers/SAXParser.hpp>
34 #include <netedit/GNEViewNet.h>
35 #include <netedit/GNEViewParent.h>
36 
37 #include "GNEOptionsDialog.h"
38 
39 #define TREELISTWIDTH 200
40 
41 // ===========================================================================
42 // FOX callback mapping
43 // ===========================================================================
44 
45 FXDEFMAP(GNEOptionsDialog) GUIDialogOptionsMap[] = {
46  FXMAPFUNC(SEL_COMMAND, MID_CANCEL, GNEOptionsDialog::onCmdCancel),
47  FXMAPFUNC(SEL_COMMAND, MID_GNE_RESET, GNEOptionsDialog::onCmdReset),
49  FXMAPFUNC(SEL_COMMAND, MID_GNE_SELECT, GNEOptionsDialog::onCmdSelectTopic),
56 };
57 
58 // Object implementation
59 FXIMPLEMENT(GNEOptionsDialog, FXDialogBox, GUIDialogOptionsMap, ARRAYNUMBER(GUIDialogOptionsMap))
60 
61 // ===========================================================================
62 // method definitions
63 // ===========================================================================
64 
65 std::pair<int, bool>
66 GNEOptionsDialog::Options(GNEApplicationWindow* GNEApp, GUIIcon icon, OptionsCont& optionsContainer, const OptionsCont& originalOptionsContainer, const char* titleName) {
67  GNEOptionsDialog* optionsDialog = new GNEOptionsDialog(GNEApp, icon, optionsContainer, originalOptionsContainer, titleName, false);
68  auto result = std::make_pair(optionsDialog->execute(), optionsDialog->myOptionsModified);
69  delete optionsDialog;
70  return result;
71 }
72 
73 
74 std::pair<int, bool>
75 GNEOptionsDialog::Run(GNEApplicationWindow* GNEApp, GUIIcon icon, OptionsCont& optionsContainer, const OptionsCont& originalOptionsContainer, const char* titleName) {
76  GNEOptionsDialog* optionsDialog = new GNEOptionsDialog(GNEApp, icon, optionsContainer, originalOptionsContainer, titleName, true);
77  auto result = std::make_pair(optionsDialog->execute(), optionsDialog->myOptionsModified);
78  delete optionsDialog;
79  return result;
80 }
81 
82 
84 
85 
86 long
87 GNEOptionsDialog::onCmdCancel(FXObject*, FXSelector, void*) {
88  // reset entries
89  for (const auto& entry : myInputOptionEntries) {
90  entry->onCmdResetOption(nullptr, 0, nullptr);
91  }
92  // close dialog canceling changes
93  return handle(this, FXSEL(SEL_COMMAND, ID_CANCEL), nullptr);
94 }
95 
96 
97 long
98 GNEOptionsDialog::onCmdReset(FXObject*, FXSelector, void*) {
99  // reset entries
100  for (const auto& entry : myInputOptionEntries) {
101  entry->onCmdResetOption(nullptr, 0, nullptr);
102  }
103  return 1;
104 }
105 
106 
107 long
108 GNEOptionsDialog::onCmdRunNetgenerate(FXObject*, FXSelector, void*) {
109  // close dialog accepting changes
110  handle(this, FXSEL(SEL_COMMAND, ID_ACCEPT), nullptr);
111  // run tool in mainWindow
112  return myGNEApp->handle(this, FXSEL(SEL_COMMAND, MID_GNE_RUNNETGENERATE), nullptr);
113 }
114 
115 
116 long
117 GNEOptionsDialog::onCmdSelectTopic(FXObject*, FXSelector, void*) {
118  if (mySearchButton->getText().count() == 0) {
120  }
121  return 1;
122 }
123 
124 
125 long
126 GNEOptionsDialog::onCmdSearch(FXObject*, FXSelector, void*) {
127  if (mySearchButton->getText().count() > 0) {
129  } else {
131  }
132  return 1;
133 }
134 
135 
136 long
137 GNEOptionsDialog::onCmdShowToolTipsMenu(FXObject*, FXSelector, void*) {
138  // toggle check
140  if (myGNEApp->getViewNet()) {
143  }
144  // enable/disable static tooltip
146  // save in registry
147  getApp()->reg().writeIntEntry("gui", "menuToolTips", myShowToolTipsMenu->amChecked() ? 0 : 1);
148  update();
149 
150  return 1;
151 }
152 
153 
154 long
155 GNEOptionsDialog::onCmdSaveOptions(FXObject*, FXSelector, void*) {
156  // open save dialog
157  const std::string file = GNEApplicationWindowHelper::openOptionFileDialog(this, true);
158  // check file
159  if (file.size() > 0) {
160  std::ofstream out(StringUtils::transcodeToLocal(file));
161  myOptionsContainer.writeConfiguration(out, true, false, false, file, true);
162  out.close();
163  }
164  return 1;
165 }
166 
167 
168 long
169 GNEOptionsDialog::onCmdLoadOptions(FXObject*, FXSelector, void*) {
170  // open file dialog
171  const std::string file = GNEApplicationWindowHelper::openOptionFileDialog(this, false);
172  // check file
173  if ((file.size() > 0) && loadConfiguration(file)) {
174  // update entries
175  for (const auto& entry : myInputOptionEntries) {
176  entry->updateOption();
177  }
178  }
179  return 1;
180 }
181 
182 
183 long
184 GNEOptionsDialog::onCmdResetDefault(FXObject*, FXSelector, void*) {
185  // restore entries
186  for (const auto& entry : myInputOptionEntries) {
187  entry->restoreOption();
188  }
189  return 1;
190 }
191 
192 
194  myGNEApp(nullptr),
195  myOptionsContainer(OptionsCont::EMPTY_OPTIONS),
196  myOriginalOptionsContainer(OptionsCont::EMPTY_OPTIONS) {
197 }
198 
199 
200 bool
202  // iterate over tree elements and get the selected item
203  for (const auto& treeItemTopic : myTreeItemTopics) {
204  if (treeItemTopic.first->isSelected()) {
205  // iterate over entries
206  for (const auto& entry : myInputOptionEntries) {
207  if (entry->getTopic() == treeItemTopic.second) {
208  entry->show();
209  } else {
210  entry->hide();
211  }
212  }
213  myEntriesFrame->recalc();
214  myEntriesFrame->update();
215  return true;
216  }
217  }
218  // no topic selected, then show all
219  for (const auto& entry : myInputOptionEntries) {
220  entry->show();
221  }
222  myEntriesFrame->recalc();
223  myEntriesFrame->update();
224  return true;
225 }
226 
227 
228 void
230  // first lower case search text
231  searchText = StringUtils::to_lower_case(searchText);
232  // iterate over entries
233  for (const auto& entry : myInputOptionEntries) {
234  if (searchText.empty()) {
235  // show all entries if searchText is empty
236  entry->show();
237  } else if (entry->getNameLower().find(searchText) != std::string::npos) {
238  entry->show();
239  } else if ((myDescriptionSearchCheckButton->getCheck() == TRUE) &&
240  (entry->getDescriptionLower().find(searchText) != std::string::npos)) {
241  entry->show();
242  } else {
243  entry->hide();
244  }
245  }
246  myEntriesFrame->recalc();
247  myEntriesFrame->update();
248 }
249 
250 
251 bool
252 GNEOptionsDialog::loadConfiguration(const std::string& file) {
253  // make all options writable
255  // build parser
256  XERCES_CPP_NAMESPACE::SAXParser parser;
257  parser.setValidationScheme(XERCES_CPP_NAMESPACE::SAXParser::Val_Never);
258  parser.setDisableDefaultEntityResolution(true);
259  // start the parsing
261  try {
262  parser.setDocumentHandler(&handler);
263  parser.setErrorHandler(&handler);
264  parser.parse(StringUtils::transcodeToLocal(file).c_str());
265  if (handler.errorOccurred()) {
266  WRITE_ERROR(TL("Could not load configuration '") + file + "'.");
267  return false;
268  }
269  } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
270  WRITE_ERROR(TL("Could not load tool configuration '") + file + "':\n " + StringUtils::transcode(e.getMessage()));
271  return false;
272  }
273  // write info
274  WRITE_MESSAGE(TL("Loaded configuration."));
275  return true;
276 }
277 
278 
280  const OptionsCont& originalOptionsContainer, const char* titleName, const bool runDialog) :
281  FXDialogBox(GNEApp, titleName, GUIDesignDialogBoxExplicitStretchable(800, 600)),
282  myGNEApp(GNEApp),
283  myOptionsContainer(optionsContainer),
284  myOriginalOptionsContainer(originalOptionsContainer) {
285  // set icon
286  setIcon(GUIIconSubSys::getIcon(icon));
287  // create content frame
288  FXVerticalFrame* contentFrame = new FXVerticalFrame(this, GUIDesignContentsFrame);
289  // add buttons frame
290  FXHorizontalFrame* buttonsFrame = new FXHorizontalFrame(contentFrame, GUIDesignHorizontalFrameNoPadding);
291  myShowToolTipsMenu = new MFXCheckableButton(false, buttonsFrame,
292  myGNEApp->getStaticTooltipMenu(), (std::string("\t") + TL("Toggle Menu Tooltips") + std::string("\t") + TL("Toggles whether tooltips in the menu shall be shown.")).c_str(),
294  auto saveFile = new MFXButtonTooltip(buttonsFrame, myGNEApp->getStaticTooltipMenu(), TL("Save options"),
296  saveFile->setTipText(TL("Save configuration file"));
297  auto loadFile = new MFXButtonTooltip(buttonsFrame, myGNEApp->getStaticTooltipMenu(), TL("Load options"),
299  loadFile->setTipText(TL("Load configuration file"));
300  auto resetDefault = new MFXButtonTooltip(buttonsFrame, myGNEApp->getStaticTooltipMenu(), TL("Default options"),
302  resetDefault->setTipText(TL("Reset all options to default"));
303  // add separator
304  new FXSeparator(contentFrame);
305  // create elements frame
306  FXHorizontalFrame* elementsFrame = new FXHorizontalFrame(contentFrame, GUIDesignAuxiliarFrame);
307  FXVerticalFrame* elementsFrameTree = new FXVerticalFrame(elementsFrame, GUIDesignAuxiliarVerticalFrame);
308  FXVerticalFrame* elementsFrameValues = new FXVerticalFrame(elementsFrame, GUIDesignAuxiliarFrame);
309  // Create GroupBox modules
310  MFXGroupBoxModule* groupBoxTree = new MFXGroupBoxModule(elementsFrameTree, TL("Topics"));
311  MFXGroupBoxModule* groupBoxOptions = new MFXGroupBoxModule(elementsFrameValues, TL("Options"));
312  // create FXTreeList
313  myTopicsTreeList = new FXTreeList(groupBoxTree->getCollapsableFrame(), this, MID_GNE_SELECT, GUIDesignTreeListFixedWidth);
314  myTopicsTreeList->setWidth(TREELISTWIDTH);
315  // add root item
316  myRootItem = myTopicsTreeList->appendItem(nullptr, titleName);
317  myRootItem->setExpanded(TRUE);
318  // create scroll
319  FXScrollWindow* scrollTabEntries = new FXScrollWindow(groupBoxOptions->getCollapsableFrame(), LAYOUT_FILL_X | LAYOUT_FILL_Y);
320  // create vertical frame for entries
321  myEntriesFrame = new FXVerticalFrame(scrollTabEntries, GUIDesignAuxiliarFrame);
322  // iterate over all topics
323  for (const auto& topic : myOptionsContainer.getSubTopics()) {
324  // check if we have to ignore this topic
325  if (myIgnoredTopics.count(topic) == 0) {
326  // add topic into myTreeItemTopics and tree
327  myTreeItemTopics[myTopicsTreeList->appendItem(myRootItem, topic.c_str())] = topic;
328  // iterate over entries
329  const std::vector<std::string> entries = myOptionsContainer.getSubTopicsEntries(topic);
330  for (const auto& entry : entries) {
331  // check if we have to ignore this entry
332  if (myIgnoredEntries.count(entry) == 0) {
333  // get type
334  const std::string type = myOptionsContainer.getTypeName(entry);
335  // get description
336  const std::string description = myOptionsContainer.getDescription(entry);
337  // get default value
338  const std::string defaultValue = myOptionsContainer.getValueString(entry);
339  // continue depending of type
340  if (type == "STR") {
341  myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputString(this, myEntriesFrame, topic, entry, description, defaultValue));
342  } else if ((type == "FILE") || (type == "NETWORK") || (type == "ADDITIONAL") || (type == "ROUTE") || (type == "DATA")) {
343  myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputFilename(this, myEntriesFrame, topic, entry, description, defaultValue));
344  } else if (type == "BOOL") {
345  myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputBool(this, myEntriesFrame, topic, entry, description, defaultValue));
346  } else if (type == "INT") {
347  myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputInt(this, myEntriesFrame, topic, entry, description, defaultValue));
348  } else if (type == "FLOAT") {
349  myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputFloat(this, myEntriesFrame, topic, entry, description, defaultValue));
350  } else if (type == "INT[]") {
351  myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputIntVector(this, myEntriesFrame, topic, entry, description, defaultValue));
352  } else if (type == "STR[]") {
353  myInputOptionEntries.push_back(new GNEOptionsDialogElements::InputStringVector(this, myEntriesFrame, topic, entry, description, defaultValue));
354  }
355  }
356  }
357  }
358  }
359  // create search elements
360  FXHorizontalFrame* searchFrame = new FXHorizontalFrame(contentFrame, GUIDesignAuxiliarHorizontalFrame);
361  new FXLabel(searchFrame, TL("Search"), nullptr, GUIDesignLabelThickedFixed(TREELISTWIDTH - GUIDesignHeight + 14));
363  myDescriptionSearchCheckButton->setToolTipText(TL("Include description in search"));
365  // add separator
366  new FXSeparator(contentFrame);
367  // create buttons frame
368  buttonsFrame = new FXHorizontalFrame(contentFrame, GUIDesignHorizontalFrame);
369  new FXHorizontalFrame(buttonsFrame, GUIDesignAuxiliarHorizontalFrame);
370  // continue depending of dialog type
371  if (runDialog) {
373  } else {
374  GUIDesigns::buildFXButton(buttonsFrame, TL("OK"), "", "", GUIIconSubSys::getIcon(GUIIcon::ACCEPT), this, ID_ACCEPT, GUIDesignButtonOK);
375  }
378  new FXHorizontalFrame(buttonsFrame, GUIDesignAuxiliarHorizontalFrame);
379  // create dialog
380  create();
381  // after creation, adjust entries name sizes
382  for (const auto& entry : myInputOptionEntries) {
383  entry->adjustNameSize();
384  }
385  // set myShowToolTipsMenu
386  myShowToolTipsMenu->setChecked(getApp()->reg().readIntEntry("gui", "menuToolTips", 0) != 1);
387 }
388 
389 /****************************************************************************/
#define TREELISTWIDTH
FXDEFMAP(GNEOptionsDialog) GUIDialogOptionsMap[]
@ MID_GNE_RUNNETGENERATE
run netgenerate tool
Definition: GUIAppEnum.h:768
@ MID_GNE_SET_ATTRIBUTE
attribute edited
Definition: GUIAppEnum.h:930
@ MID_CANCEL
Cancel-button pressed.
Definition: GUIAppEnum.h:306
@ MID_CHOOSEN_SAVE
Save set.
Definition: GUIAppEnum.h:599
@ MID_SHOWTOOLTIPS_MENU
Show tool tips in menus - button.
Definition: GUIAppEnum.h:385
@ MID_GNE_SEARCH_USEDESCRIPTION
use search description
Definition: GUIAppEnum.h:1543
@ MID_GNE_BUTTON_DEFAULT
default button
Definition: GUIAppEnum.h:1418
@ MID_CHOOSEN_LOAD
Load set.
Definition: GUIAppEnum.h:597
@ MID_GNE_SELECT
select element
Definition: GUIAppEnum.h:948
@ MID_GNE_RESET
reset element
Definition: GUIAppEnum.h:938
@ MID_MTEXTFIELDSEARCH_UPDATED
callback for MFXTextFieldSearch
Definition: GUIAppEnum.h:1584
#define GUIDesignCheckButtonThick
checkButton placed in left position
Definition: GUIDesigns.h:201
#define GUIDesignContentsFrame
design for the main content frame of every frame/dialog with padding and spacing
Definition: GUIDesigns.h:393
#define GUIDesignTextField
Definition: GUIDesigns.h:65
#define GUIDesignAuxiliarHorizontalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition: GUIDesigns.h:405
#define GUIDesignButtonConfiguration
Configuration Button.
Definition: GUIDesigns.h:165
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:80
#define GUIDesignTreeListFixedWidth
Definition: GUIDesigns.h:680
#define GUIDesignButtonOK
Definition: GUIDesigns.h:159
#define GUIDesignAuxiliarVerticalFrame
design for auxiliar (Without borders) horizontal frame used to pack another frames
Definition: GUIDesigns.h:411
#define GUIDesignMFXCheckableButtonSquare
Definition: GUIDesigns.h:143
#define GUIDesignAuxiliarFrame
design for auxiliar (Without borders) frame extended in all directions
Definition: GUIDesigns.h:396
#define GUIDesignLabelThickedFixed(width)
label thicked, icon before text, text centered and custom width
Definition: GUIDesigns.h:258
#define GUIDesignHorizontalFrameNoPadding
Horizontal frame extended over frame parent without padding and spacing.
Definition: GUIDesigns.h:337
#define GUIDesignHorizontalFrame
Horizontal frame extended over frame parent with padding and spacing.
Definition: GUIDesigns.h:334
#define GUIDesignDialogBoxExplicitStretchable(width, height)
design for dialog box with specific width and height that can be stretched (But not shrunk)
Definition: GUIDesigns.h:620
GUIIcon
An enumeration of icons used by the gui applications.
Definition: GUIIcons.h:33
@ SHOWTOOLTIPS_MENU
@ OPEN
open icons
@ SAVE
save icons
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:297
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define TL(string)
Definition: MsgHandler.h:315
int GUIDesignHeight
the default size for GUI elements
Definition: StdDefs.cpp:34
The main window of Netedit.
GNEViewNet * getViewNet()
get pointer to viewNet
long onCmdSaveOptions(FXObject *, FXSelector, void *)
save options
FXTreeItem * myRootItem
root item
FXTreeList * myTopicsTreeList
Topics elements tree.
void updateVisibleEntriesBySearch(std::string searchText)
update visible entries by search
MFXCheckableButton * myShowToolTipsMenu
checkable button for show toolTips
long onCmdCancel(FXObject *, FXSelector, void *)
called when user press cancel button
const std::set< std::string > myIgnoredEntries
ignores entries
long onCmdSelectTopic(FXObject *, FXSelector, void *)
called when user select a topic in the list
std::vector< GNEOptionsDialogElements::InputOption * > myInputOptionEntries
Input option entries.
const std::set< std::string > myIgnoredTopics
ignores topics
long onCmdReset(FXObject *, FXSelector, void *)
called when user press reset button
std::map< FXTreeItem *, std::string > myTreeItemTopics
map with topics and their associated FXTreeItem
GNEApplicationWindow * myGNEApp
pointer to main window parent
~GNEOptionsDialog()
Destructor.
MFXTextFieldSearch * mySearchButton
search button
static std::pair< int, bool > Run(GNEApplicationWindow *GNEApp, GUIIcon icon, OptionsCont &optionsContainer, const OptionsCont &originalOptionsContainer, const char *titleName)
Constructor for run dialogs.
bool loadConfiguration(const std::string &file)
load configuration
static std::pair< int, bool > Options(GNEApplicationWindow *GNEApp, GUIIcon icon, OptionsCont &optionsContainer, const OptionsCont &originalOptionsContainer, const char *titleName)
Constructor for options dialogs.
OptionsCont & myOptionsContainer
reference to edited Option container
FXVerticalFrame * myEntriesFrame
vertical frame for entries
MFXCheckButtonTooltip * myDescriptionSearchCheckButton
checkbox for enable/disable search by description
long onCmdShowToolTipsMenu(FXObject *, FXSelector, void *)
enable/disable show toolTip
long onCmdResetDefault(FXObject *, FXSelector, void *)
reset default
long onCmdSearch(FXObject *, FXSelector, void *)
called when user searches
long onCmdLoadOptions(FXObject *, FXSelector, void *)
load options
bool myOptionsModified
flag for check if options was modified
bool updateVisibleEntriesByTopic()
update visible entries by selected topic
GNEOptionsDialog()
FOX needs this.
long onCmdRunNetgenerate(FXObject *, FXSelector, void *)
called when user press reset button
GNEViewParent * getViewParent() const
get the net object
static FXButton * buildFXButton(FXComposite *p, const std::string &text, const std::string &tip, const std::string &help, FXIcon *ic, FXObject *tgt, FXSelector sel, FXuint opts=BUTTON_NORMAL, FXint x=0, FXint y=0, FXint w=0, FXint h=0, FXint pl=DEFAULT_PAD, FXint pr=DEFAULT_PAD, FXint pt=DEFAULT_PAD, FXint pb=DEFAULT_PAD)
build button
Definition: GUIDesigns.cpp:128
MFXCheckableButton * getShowToolTipsMenu() const
get menu for tooltips menu
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
MFXStaticToolTip * getStaticTooltipMenu() const
get static toolTip for menus
void setToolTipText(const FXString &toolTip)
set toolTip
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
const std::vector< std::string > & getSubTopics() const
return the list of subtopics
std::string getTypeName(const std::string name)
return the type name for the given option
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
Writes the configuration.
std::string getValueString(const std::string &name) const
Returns the string-value of the named option (all options)
const std::string & getDescription(const std::string &name) const
Returns the option description.
void resetWritable()
Resets all options to be writeable.
std::vector< std::string > getSubTopicsEntries(const std::string &subtopic) const
return the list of entries for the given subtopic
A SAX-Handler for loading options.
Definition: OptionsLoader.h:44
bool errorOccurred() const
Returns the information whether an error occurred.
static std::string to_lower_case(const std::string &str)
Transfers the content to lower case.
Definition: StringUtils.cpp:77
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
Definition: StringUtils.h:146
static std::string transcodeToLocal(const std::string &utf8String)
convert a string from UTF-8 to the local codepage
static std::string openOptionFileDialog(FXWindow *window, bool save)
open option dialog