"""
Author: HECE - University of Liege, Pierre Archambeau
Date: 2024
Copyright (c) 2024 University of Liege. All rights reserved.
This script and its content are protected by copyright law. Unauthorized
copying or distribution of this file, via any medium, is strictly prohibited.
"""
import os
import json
from enum import Enum
from pathlib import Path
import logging
import wx
from .PyTranslate import _
[docs]
class ConfigurationKeys(Enum):
""" Using enumerated keys make sure we
can check value names at code write time
(i.e. we don't use string which are brittle)
"""
[docs]
PLAY_WELCOME_SOUND = "PlayWelcomeSound"
[docs]
TICKS_SIZE = "TicksSize"
[docs]
TICKS_BOUNDS = "TicksBounds"
[docs]
TICKS_XROTATION = "TicksXRotation"
[docs]
TICKS_FONTSIZE = "TicksFontSize"
[docs]
OVERLAY_XY_FONT_NAME = "OverlayXYFontName"
[docs]
OVERLAY_XY_FONT_SIZE = "OverlayXYFontSize"
[docs]
COLOR_BACKGROUND = "ColorBackground"
[docs]
ACTIVE_ARRAY_PALETTE_FOR_IMAGE = "Use active array palette for image"
[docs]
ACTIVE_RES2D_PALETTE_FOR_IMAGE = "Use active result palette for image"
[docs]
ASSEMBLY_IMAGES = "AssemblyImages"
[docs]
DIRECTORY_DEM = "Default DEM directory"
[docs]
DIRECTORY_DTM = "Default DTM directory"
[docs]
DIRECTORY_LAZ = "Default LAZ directory"
[docs]
ACTIVE_VECTOR_COLOR = "Active vector color"
[docs]
ACTIVE_VECTOR_SIZE_SQUARE = "Active vector square size"
[docs]
XLSX_HECE_DATABASE = "Hece Database XLSX file"
[docs]
EPSG_CODE = "Default EPSG code"
[docs]
SNAP_GRID_UNIT = "Snap grid base unit"
[docs]
SNAP_GRID_ROUND_BASE = "Snap grid origin round base"
[docs]
class WolfConfiguration:
""" Holds the PyWolf configuration """
def __init__(self, path=None):
# We make sure we use a standard location
# to store the configuration
if path is None:
if os.name == "nt":
# On Windows NT, LOCALAPPDATA is expected to be defined.
# (might not be true in the future, who knows)
self._options_file_path = Path(os.getenv("LOCALAPPDATA")) / "wolf.conf"
else:
self._options_file_path = Path("wolf.conf")
else:
self._options_file_path = path
#Set default -- useful if new options are inserted
# --> ensuring that default values are created even if not stored in the options file
self.set_default_config()
if self._options_file_path.exists():
self.load()
else:
# self.set_default_config()
# This save is not 100% necessary but it helps
# to make sure a config file exists.
self.save()
@property
[docs]
def path(self) -> Path:
""" Where the configuration is read/saved."""
return self._options_file_path
[docs]
def set_default_config(self):
self._config = {
ConfigurationKeys.VERSION.value: 1,
ConfigurationKeys.PLAY_WELCOME_SOUND.value: True,
ConfigurationKeys.TICKS_SIZE.value: 500.,
ConfigurationKeys.ACTIVE_ARRAY_PALETTE_FOR_IMAGE.value: True,
ConfigurationKeys.ACTIVE_RES2D_PALETTE_FOR_IMAGE.value: False,
ConfigurationKeys.TICKS_BOUNDS.value: True,
ConfigurationKeys.COLOR_BACKGROUND.value: [255, 255, 255, 255],
ConfigurationKeys.ASSEMBLY_IMAGES.value: 0,
ConfigurationKeys.TICKS_XROTATION.value: 30.,
ConfigurationKeys.TICKS_FONTSIZE.value: 12,
ConfigurationKeys.OVERLAY_XY_FONT_NAME.value: "Arial",
ConfigurationKeys.OVERLAY_XY_FONT_SIZE.value: 13,
ConfigurationKeys.DIRECTORY_DEM.value: "",
ConfigurationKeys.DIRECTORY_DTM.value: "",
ConfigurationKeys.DIRECTORY_LAZ.value: "",
ConfigurationKeys.ACTIVE_VECTOR_COLOR.value: [0, 0, 0, 255],
ConfigurationKeys.ACTIVE_VECTOR_SIZE_SQUARE.value: 5,
ConfigurationKeys.XLSX_HECE_DATABASE.value: "",
ConfigurationKeys.EPSG_CODE.value: "EPSG:31370",
ConfigurationKeys.SNAP_GRID_UNIT.value: 0.01,
ConfigurationKeys.SNAP_GRID_ROUND_BASE.value: 1000.0,
}
self._types = {
ConfigurationKeys.VERSION.value: int,
ConfigurationKeys.PLAY_WELCOME_SOUND.value: bool,
ConfigurationKeys.TICKS_SIZE.value: float,
ConfigurationKeys.ACTIVE_ARRAY_PALETTE_FOR_IMAGE.value: bool,
ConfigurationKeys.ACTIVE_RES2D_PALETTE_FOR_IMAGE.value: bool,
ConfigurationKeys.TICKS_BOUNDS.value: bool,
ConfigurationKeys.COLOR_BACKGROUND.value: list,
ConfigurationKeys.ASSEMBLY_IMAGES.value: int,
ConfigurationKeys.TICKS_XROTATION.value: float,
ConfigurationKeys.TICKS_FONTSIZE.value: int,
ConfigurationKeys.OVERLAY_XY_FONT_NAME.value: str,
ConfigurationKeys.OVERLAY_XY_FONT_SIZE.value: int,
ConfigurationKeys.DIRECTORY_DEM.value: str,
ConfigurationKeys.DIRECTORY_DTM.value: str,
ConfigurationKeys.DIRECTORY_LAZ.value: str,
ConfigurationKeys.ACTIVE_VECTOR_COLOR.value: list,
ConfigurationKeys.ACTIVE_VECTOR_SIZE_SQUARE.value: int,
ConfigurationKeys.XLSX_HECE_DATABASE.value: str,
ConfigurationKeys.EPSG_CODE.value: str,
ConfigurationKeys.SNAP_GRID_UNIT.value: float,
ConfigurationKeys.SNAP_GRID_ROUND_BASE.value: float,
}
self._check_config()
[docs]
def _check_config(self):
assert self._config.keys() == self._types.keys()
for idx, (key,val) in enumerate(self._config.items()):
assert isinstance(val, self._types[key])
[docs]
def load(self):
with open(self._options_file_path, "r", encoding="utf-8") as configfile:
filecfg = json.loads(configfile.read())
for curkey in filecfg.keys():
if curkey in self._config.keys():
self._config[curkey] = filecfg[curkey]
self._check_config()
[docs]
def save(self):
# Make sure to write the config file only if it can
# be dumped by JSON.
txt = json.dumps(self._config, indent=1)
with open(self._options_file_path, "w", encoding="utf-8") as configfile:
configfile.write(txt)
def __getitem__(self, key: ConfigurationKeys):
assert isinstance(key, ConfigurationKeys), "Please only use enum's for configuration keys."
return self._config[key.value]
def __setitem__(self, key: ConfigurationKeys, value):
# A half-measure to ensure the config structure
# can be somehow validated before run time.
assert isinstance(key, ConfigurationKeys), "Please only use enum's for configuration keys."
self._config[key.value] = value
self._check_config()
[docs]
class GlobalOptionsDialog(wx.Dialog):
""" A dialog to set global options for a WolfMapViewer. """
def __init__(self, *args, **kw):
super(GlobalOptionsDialog, self).__init__(*args, **kw)
self.InitUI()
self.SetSize((600, 600))
self.SetTitle(_("Global options"))
[docs]
def push_configuration(self, configuration):
self.cfg_welcome_voice.SetValue(configuration[ConfigurationKeys.PLAY_WELCOME_SOUND])
self.cfg_ticks_size.SetValue(str(configuration[ConfigurationKeys.TICKS_SIZE]))
self.cfg_ticks_bounds.SetValue(configuration[ConfigurationKeys.TICKS_BOUNDS])
self.cfg_bkg_color.SetColour(configuration[ConfigurationKeys.COLOR_BACKGROUND])
self.cfg_active_array_pal.SetValue(configuration[ConfigurationKeys.ACTIVE_ARRAY_PALETTE_FOR_IMAGE])
self.cfg_active_res_pal.SetValue(configuration[ConfigurationKeys.ACTIVE_RES2D_PALETTE_FOR_IMAGE])
self.cfg_assembly_images.SetSelection(configuration[ConfigurationKeys.ASSEMBLY_IMAGES])
self.cfg_ticks_xrotation.SetValue(str(configuration[ConfigurationKeys.TICKS_XROTATION]))
self.cfg_ticks_fontsize.SetValue(str(configuration[ConfigurationKeys.TICKS_FONTSIZE]))
self.cfg_overlay_xy_font_name.SetValue(str(configuration[ConfigurationKeys.OVERLAY_XY_FONT_NAME]))
self.cfg_overlay_xy_font_size.SetValue(str(configuration[ConfigurationKeys.OVERLAY_XY_FONT_SIZE]))
self.cfg_directory_dem.SetValue(str(configuration[ConfigurationKeys.DIRECTORY_DEM]))
self.cfg_directory_dtm.SetValue(str(configuration[ConfigurationKeys.DIRECTORY_DTM]))
self.cfg_directory_laz.SetValue(str(configuration[ConfigurationKeys.DIRECTORY_LAZ]))
self.cfg_vector_color.SetColour(configuration[ConfigurationKeys.ACTIVE_VECTOR_COLOR])
self.cfg_square_size.SetValue(str(configuration[ConfigurationKeys.ACTIVE_VECTOR_SIZE_SQUARE]))
self.cfg_xlsx_hece_database.SetValue(str(configuration[ConfigurationKeys.XLSX_HECE_DATABASE]))
self.cfg_epsg_code.SetValue(str(configuration[ConfigurationKeys.EPSG_CODE]))
self.cfg_snap_grid_unit.SetValue(str(configuration[ConfigurationKeys.SNAP_GRID_UNIT]))
self.cfg_snap_grid_round_base.SetValue(str(configuration[ConfigurationKeys.SNAP_GRID_ROUND_BASE]))
[docs]
def pull_configuration(self, configuration):
configuration[ConfigurationKeys.PLAY_WELCOME_SOUND] = self.cfg_welcome_voice.IsChecked()
configuration[ConfigurationKeys.TICKS_SIZE] = float(self.cfg_ticks_size.Value)
configuration[ConfigurationKeys.TICKS_BOUNDS] = self.cfg_ticks_bounds.IsChecked()
configuration[ConfigurationKeys.COLOR_BACKGROUND] = list(self.cfg_bkg_color.GetColour())
configuration[ConfigurationKeys.ACTIVE_ARRAY_PALETTE_FOR_IMAGE] = self.cfg_active_array_pal.IsChecked()
configuration[ConfigurationKeys.ACTIVE_RES2D_PALETTE_FOR_IMAGE] = self.cfg_active_res_pal.IsChecked()
configuration[ConfigurationKeys.ASSEMBLY_IMAGES] = self.cfg_assembly_images.GetSelection()
configuration[ConfigurationKeys.TICKS_XROTATION] = float(self.cfg_ticks_xrotation.Value)
configuration[ConfigurationKeys.TICKS_FONTSIZE] = int(self.cfg_ticks_fontsize.Value)
configuration[ConfigurationKeys.OVERLAY_XY_FONT_NAME] = str(self.cfg_overlay_xy_font_name.Value).strip()
configuration[ConfigurationKeys.OVERLAY_XY_FONT_SIZE] = max(6, int(self.cfg_overlay_xy_font_size.Value))
configuration[ConfigurationKeys.DIRECTORY_DEM] = str(self.cfg_directory_dem.Value)
configuration[ConfigurationKeys.DIRECTORY_DTM] = str(self.cfg_directory_dtm.Value)
configuration[ConfigurationKeys.DIRECTORY_LAZ] = str(self.cfg_directory_laz.Value)
configuration[ConfigurationKeys.ACTIVE_VECTOR_COLOR] = list(self.cfg_vector_color.GetColour())
configuration[ConfigurationKeys.ACTIVE_VECTOR_SIZE_SQUARE] = int(self.cfg_square_size.Value)
configuration[ConfigurationKeys.XLSX_HECE_DATABASE] = str(self.cfg_xlsx_hece_database.Value)
configuration[ConfigurationKeys.SNAP_GRID_UNIT] = max(1e-12, float(self.cfg_snap_grid_unit.Value))
configuration[ConfigurationKeys.SNAP_GRID_ROUND_BASE] = max(1e-12, float(self.cfg_snap_grid_round_base.Value))
epsg = str(self.cfg_epsg_code.Value)
if not epsg.upper().startswith("EPSG:"):
epsg = epsg.strip().lower()
if 'belgium 2008' in epsg or 'belgique 2008' in epsg:
epsg = "EPSG:3812"
elif 'belgium 1972' in epsg or 'belgium' in epsg or 'belgique 1972' in epsg or 'belgique' in epsg:
epsg = "EPSG:31370"
elif 'rgf93' in epsg or 'france' in epsg:
epsg = "EPSG:2154"
elif 'wgs 84' in epsg:
epsg = "EPSG:4326"
elif 'germany' in epsg or 'allemagne' in epsg:
epsg = "EPSG:25832"
else:
try:
code = int(epsg)
epsg = f"EPSG:{code}"
except:
logging.warning(_('Could not interpret EPSG code: {} -- keeping original value').format(epsg))
return
configuration[ConfigurationKeys.EPSG_CODE] = epsg
[docs]
def InitUI(self):
vbox = wx.BoxSizer(wx.VERTICAL)
self.notebook = wx.Notebook(self)
self._init_tab_general(self.notebook)
self._init_tab_display(self.notebook)
self._init_tab_directories(self.notebook)
self._init_tab_vectors(self.notebook)
vbox.Add(self.notebook, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
# Buttons
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
okButton = wx.Button(self, wx.ID_OK, label=_('Ok'))
okButton.SetDefault()
closeButton = wx.Button(self, label=_('Close'))
hbox2.Add(okButton)
hbox2.Add(closeButton, flag=wx.LEFT, border=5)
vbox.Add(hbox2, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10)
self.SetSizer(vbox)
self.Layout()
okButton.Bind(wx.EVT_BUTTON, self.OnOk)
closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
[docs]
def _init_tab_general(self, notebook):
pnl = wx.Panel(notebook)
sizer = wx.BoxSizer(wx.VERTICAL)
# Welcome voice
self.cfg_welcome_voice = wx.CheckBox(pnl, label=_('Welcome voice'))
self.cfg_welcome_voice.SetToolTip(_('Play a welcome message when opening the application'))
sizer.Add(self.cfg_welcome_voice, 0, wx.ALL, 5)
# Background color
hsizer = wx.BoxSizer(wx.HORIZONTAL)
self.label_background_color = wx.StaticText(pnl, label=_('Background color'))
self.cfg_bkg_color = wx.ColourPickerCtrl(pnl, colour=(255, 255, 255, 255))
self.cfg_bkg_color.SetToolTip(_('Background color for the viewer'))
hsizer.Add(self.label_background_color, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
hsizer.Add(self.cfg_bkg_color, 1, wx.EXPAND)
sizer.Add(hsizer, 0, wx.ALL | wx.EXPAND, 5)
# EPSG code
epsg_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.label_epsg_code = wx.StaticText(pnl, label=_('Default EPSG code'))
self.cfg_epsg_code = wx.TextCtrl(pnl, value='EPSG:31370', style=wx.TE_CENTRE)
self.cfg_epsg_code.SetToolTip(_('Default EPSG code for new arrays added to the viewer\nExamples: EPSG:31370, EPSG:2154, EPSG:4326\nor simply the code number: 31370, 2154, 4326\nor a descriptive name: Belgium 1972, Belgium 2008, France RGF93, WGS 84'))
epsg_sizer.Add(self.label_epsg_code, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
epsg_sizer.Add(self.cfg_epsg_code, 1, wx.EXPAND)
sizer.Add(epsg_sizer, 0, wx.ALL | wx.EXPAND, 5)
pnl.SetSizer(sizer)
notebook.AddPage(pnl, _("General"))
[docs]
def _init_tab_display(self, notebook):
pnl = wx.Panel(notebook)
sizer = wx.BoxSizer(wx.VERTICAL)
# -- Ticks section --
sb_ticks = wx.StaticBox(pnl, label=_('Ticks'))
sbs_ticks = wx.StaticBoxSizer(sb_ticks, orient=wx.VERTICAL)
hboxticks = wx.BoxSizer(wx.HORIZONTAL)
self.label_ticks_size = wx.StaticText(pnl, label=_('Default ticks size [m]'))
self.cfg_ticks_size = wx.TextCtrl(pnl, value='500.', style=wx.TE_CENTRE)
hboxticks.Add(self.label_ticks_size, 1, wx.ALIGN_CENTER_VERTICAL)
hboxticks.Add(self.cfg_ticks_size, 1, wx.EXPAND)
sbs_ticks.Add(hboxticks, 0, wx.ALL | wx.EXPAND, 3)
hboxrot = wx.BoxSizer(wx.HORIZONTAL)
self.label_ticks_xrotation = wx.StaticText(pnl, label=_('X rotation of ticks [°]'))
self.cfg_ticks_xrotation = wx.TextCtrl(pnl, value='30.', style=wx.TE_CENTRE)
hboxrot.Add(self.label_ticks_xrotation, 1, wx.ALIGN_CENTER_VERTICAL)
hboxrot.Add(self.cfg_ticks_xrotation, 1, wx.EXPAND)
sbs_ticks.Add(hboxrot, 0, wx.ALL | wx.EXPAND, 3)
hboxfs = wx.BoxSizer(wx.HORIZONTAL)
self.label_ticks_fontsize = wx.StaticText(pnl, label=_('Font size of ticks'))
self.cfg_ticks_fontsize = wx.TextCtrl(pnl, value='12', style=wx.TE_CENTRE)
hboxfs.Add(self.label_ticks_fontsize, 1, wx.ALIGN_CENTER_VERTICAL)
hboxfs.Add(self.cfg_ticks_fontsize, 1, wx.EXPAND)
sbs_ticks.Add(hboxfs, 0, wx.ALL | wx.EXPAND, 3)
self.cfg_ticks_bounds = wx.CheckBox(pnl, label=_('Add bounds to ticks'))
self.cfg_ticks_bounds.SetToolTip(_('If not checked, the extreme values of the ticks will not be displayed'))
sbs_ticks.Add(self.cfg_ticks_bounds, 0, wx.ALL, 3)
sizer.Add(sbs_ticks, 0, wx.ALL | wx.EXPAND, 5)
# -- Overlay XY section --
sb_overlay = wx.StaticBox(pnl, label=_('Overlay XY'))
sbs_overlay = wx.StaticBoxSizer(sb_overlay, orient=wx.VERTICAL)
hboxfn = wx.BoxSizer(wx.HORIZONTAL)
self.label_overlay_xy_font_name = wx.StaticText(pnl, label=_('Overlay XY font name'))
self.cfg_overlay_xy_font_name = wx.TextCtrl(pnl, value='Arial', style=wx.TE_CENTRE)
self.cfg_overlay_xy_font_name.SetToolTip(_('Font file name used by OpenGL XY overlay, e.g. arial.ttf'))
hboxfn.Add(self.label_overlay_xy_font_name, 1, wx.ALIGN_CENTER_VERTICAL)
hboxfn.Add(self.cfg_overlay_xy_font_name, 1, wx.EXPAND)
sbs_overlay.Add(hboxfn, 0, wx.ALL | wx.EXPAND, 3)
hboxfsize = wx.BoxSizer(wx.HORIZONTAL)
self.label_overlay_xy_font_size = wx.StaticText(pnl, label=_('Overlay XY font size [px]'))
self.cfg_overlay_xy_font_size = wx.TextCtrl(pnl, value='13', style=wx.TE_CENTRE)
self.cfg_overlay_xy_font_size.SetToolTip(_('Font pixel size used by OpenGL XY overlay'))
hboxfsize.Add(self.label_overlay_xy_font_size, 1, wx.ALIGN_CENTER_VERTICAL)
hboxfsize.Add(self.cfg_overlay_xy_font_size, 1, wx.EXPAND)
sbs_overlay.Add(hboxfsize, 0, wx.ALL | wx.EXPAND, 3)
sizer.Add(sbs_overlay, 0, wx.ALL | wx.EXPAND, 5)
# -- Snap grid section --
sb_snap = wx.StaticBox(pnl, label=_('Snap grid'))
sbs_snap = wx.StaticBoxSizer(sb_snap, orient=wx.VERTICAL)
hbox_snap_unit = wx.BoxSizer(wx.HORIZONTAL)
self.label_snap_grid_unit = wx.StaticText(pnl, label=_('Base unit [m]'))
self.cfg_snap_grid_unit = wx.TextCtrl(pnl, value='0.01', style=wx.TE_CENTRE)
self.cfg_snap_grid_unit.SetToolTip(_('Base spacing used by snap (adaptive levels are powers of two of this value)'))
hbox_snap_unit.Add(self.label_snap_grid_unit, 1, wx.ALIGN_CENTER_VERTICAL)
hbox_snap_unit.Add(self.cfg_snap_grid_unit, 1, wx.EXPAND)
sbs_snap.Add(hbox_snap_unit, 0, wx.ALL | wx.EXPAND, 3)
hbox_snap_round = wx.BoxSizer(wx.HORIZONTAL)
self.label_snap_grid_round_base = wx.StaticText(pnl, label=_('Origin rounding base [m]'))
self.cfg_snap_grid_round_base = wx.TextCtrl(pnl, value='1000.0', style=wx.TE_CENTRE)
self.cfg_snap_grid_round_base.SetToolTip(_('Snap origin is aligned on a multiple of this value to keep a stable global grid'))
hbox_snap_round.Add(self.label_snap_grid_round_base, 1, wx.ALIGN_CENTER_VERTICAL)
hbox_snap_round.Add(self.cfg_snap_grid_round_base, 1, wx.EXPAND)
sbs_snap.Add(hbox_snap_round, 0, wx.ALL | wx.EXPAND, 3)
sizer.Add(sbs_snap, 0, wx.ALL | wx.EXPAND, 5)
# -- Palettes & Images section --
sb_pal = wx.StaticBox(pnl, label=_('Palettes & Images'))
sbs_pal = wx.StaticBoxSizer(sb_pal, orient=wx.VERTICAL)
self.cfg_active_array_pal = wx.CheckBox(pnl, label=_('Use active array palette for image'))
self.cfg_active_array_pal.SetToolTip(_('If checked, the active array palette will be used for the image'))
sbs_pal.Add(self.cfg_active_array_pal, 0, wx.ALL, 3)
self.cfg_active_res_pal = wx.CheckBox(pnl, label=_('Use active result palette for image'))
self.cfg_active_res_pal.SetToolTip(_('If checked, the active result palette will be used for the image (but priority to active array palette if checked)'))
sbs_pal.Add(self.cfg_active_res_pal, 0, wx.ALL, 3)
locsizer = wx.BoxSizer(wx.HORIZONTAL)
self.label_assembly_images = wx.StaticText(pnl, label=_('Assembly mode for images (if linked viewers)'))
self.cfg_assembly_images = wx.ListBox(pnl, choices=['horizontal', 'vertical', 'square'], style=wx.LB_SINGLE)
self.cfg_assembly_images.SetToolTip(_('Choose the assembly mode for images -- horizontal, vertical or square'))
locsizer.Add(self.label_assembly_images, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
locsizer.Add(self.cfg_assembly_images, 1, wx.EXPAND)
sbs_pal.Add(locsizer, 0, wx.ALL | wx.EXPAND, 3)
sizer.Add(sbs_pal, 0, wx.ALL | wx.EXPAND, 5)
pnl.SetSizer(sizer)
notebook.AddPage(pnl, _("Display / Export"))
[docs]
def _init_tab_directories(self, notebook):
pnl = wx.Panel(notebook)
sizer = wx.BoxSizer(wx.VERTICAL)
# DEM directory
dir_dem = wx.BoxSizer(wx.HORIZONTAL)
self.label_directory_dem = wx.StaticText(pnl, label=_('Default DEM directory'))
self.cfg_directory_dem = wx.TextCtrl(pnl, value='', style=wx.TE_CENTRE)
self.btn_choose_dem = wx.Button(pnl, label=_('Choose'))
self.btn_choose_dem.Bind(wx.EVT_BUTTON, self.OnChooseDem)
dir_dem.Add(self.label_directory_dem, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
dir_dem.Add(self.cfg_directory_dem, 2, wx.EXPAND | wx.RIGHT, 5)
dir_dem.Add(self.btn_choose_dem, 0)
sizer.Add(dir_dem, 0, wx.ALL | wx.EXPAND, 5)
# DTM directory
dir_dtm = wx.BoxSizer(wx.HORIZONTAL)
self.label_directory_dtm = wx.StaticText(pnl, label=_('Default DTM directory'))
self.cfg_directory_dtm = wx.TextCtrl(pnl, value='', style=wx.TE_CENTRE)
self.btn_choose_dtm = wx.Button(pnl, label=_('Choose'))
self.btn_choose_dtm.Bind(wx.EVT_BUTTON, self.OnChooseDtm)
dir_dtm.Add(self.label_directory_dtm, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
dir_dtm.Add(self.cfg_directory_dtm, 2, wx.EXPAND | wx.RIGHT, 5)
dir_dtm.Add(self.btn_choose_dtm, 0)
sizer.Add(dir_dtm, 0, wx.ALL | wx.EXPAND, 5)
# LAZ directory
dir_laz = wx.BoxSizer(wx.HORIZONTAL)
self.label_directory_laz = wx.StaticText(pnl, label=_('Default LAZ directory'))
self.cfg_directory_laz = wx.TextCtrl(pnl, value='', style=wx.TE_CENTRE)
self.btn_choose_laz = wx.Button(pnl, label=_('Choose'))
self.btn_choose_laz.Bind(wx.EVT_BUTTON, self.OnChooseLaz)
dir_laz.Add(self.label_directory_laz, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
dir_laz.Add(self.cfg_directory_laz, 2, wx.EXPAND | wx.RIGHT, 5)
dir_laz.Add(self.btn_choose_laz, 0)
sizer.Add(dir_laz, 0, wx.ALL | wx.EXPAND, 5)
# XLSX HECE database
dir_xlsx = wx.BoxSizer(wx.HORIZONTAL)
self.label_xlsx_hece_database = wx.StaticText(pnl, label=_('HECE Database file'))
self.cfg_xlsx_hece_database = wx.TextCtrl(pnl, value='', style=wx.TE_CENTRE)
self.btn_choose_xlsx = wx.Button(pnl, label=_('Choose'))
self.btn_choose_xlsx.Bind(wx.EVT_BUTTON, self.OnChooseXLSX)
dir_xlsx.Add(self.label_xlsx_hece_database, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
dir_xlsx.Add(self.cfg_xlsx_hece_database, 2, wx.EXPAND | wx.RIGHT, 5)
dir_xlsx.Add(self.btn_choose_xlsx, 0)
sizer.Add(dir_xlsx, 0, wx.ALL | wx.EXPAND, 5)
pnl.SetSizer(sizer)
notebook.AddPage(pnl, _("Directories"))
[docs]
def _init_tab_vectors(self, notebook):
pnl = wx.Panel(notebook)
sizer = wx.BoxSizer(wx.VERTICAL)
# Vector color
color_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.label_vector_color = wx.StaticText(pnl, label=_('Default vector color'))
self.cfg_vector_color = wx.ColourPickerCtrl(pnl, colour=(0, 0, 0, 255))
self.cfg_vector_color.SetToolTip(_('Color for active vector in the viewer'))
color_sizer.Add(self.label_vector_color, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
color_sizer.Add(self.cfg_vector_color, 1, wx.EXPAND)
sizer.Add(color_sizer, 0, wx.ALL | wx.EXPAND, 5)
# Square size
square_sizer = wx.BoxSizer(wx.HORIZONTAL)
label_sq = wx.StaticText(pnl, label=_('Square size [px]'))
self.cfg_square_size = wx.TextCtrl(pnl, value='5', style=wx.TE_CENTRE)
self.cfg_square_size.SetToolTip(_('Size of the square for active vector in the viewer'))
square_sizer.Add(label_sq, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
square_sizer.Add(self.cfg_square_size, 1, wx.EXPAND)
sizer.Add(square_sizer, 0, wx.ALL | wx.EXPAND, 5)
pnl.SetSizer(sizer)
notebook.AddPage(pnl, _("Vectors"))
[docs]
def OnChooseDem(self, e):
""" Choose a directory for DEM files """
dlg = wx.DirDialog(self, _("Choose a directory"), style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
self.cfg_directory_dem.SetValue(str(dlg.GetPath()))
dlg.Destroy()
[docs]
def OnChooseDtm(self, e):
""" Choose a directory for DTM files """
dlg = wx.DirDialog(self, _("Choose a directory"), style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
self.cfg_directory_dtm.SetValue(str(dlg.GetPath()))
dlg.Destroy()
[docs]
def OnChooseLaz(self, e):
""" Choose a directory for LAZ files """
dlg = wx.DirDialog(self, _("Choose a directory"), style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
self.cfg_directory_laz.SetValue(str(dlg.GetPath()))
dlg.Destroy()
[docs]
def OnChooseXLSX(self, e):
""" Choose a XLSX file for HECE database """
dlg = wx.FileDialog(self, _("Choose a HECE database file"), style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
dlg.SetWildcard("Excel files (*.xlsx)|*.xlsx")
if dlg.ShowModal() == wx.ID_OK:
self.cfg_xlsx_hece_database.SetValue(str(dlg.GetPath()))
dlg.Destroy()
[docs]
def OnOk(self, e):
if self.IsModal():
self.EndModal(wx.ID_OK)
else:
self.Close()
[docs]
def OnClose(self, e):
self.Destroy()
[docs]
def handle_configuration_dialog(wxparent, configuration):
dlg = GlobalOptionsDialog(wxparent)
try:
dlg.push_configuration(configuration)
if dlg.ShowModal() == wx.ID_OK:
# do something here
dlg.pull_configuration(configuration)
configuration.save()
logging.info(_('Configuration saved in {}').format(str(configuration.path)))
else:
# handle dialog being cancelled or ended by some other button
pass
finally:
# explicitly cause the dialog to destroy itself
dlg.Destroy()
if __name__ == "__main__":
[docs]
cfg = WolfConfiguration(Path("test.conf"))
cfg[ConfigurationKeys.PLAY_WELCOME_SOUND] = False
print(cfg._config)
cfg.save()
cfg = WolfConfiguration(Path("test.conf"))
cfg.load()
print(cfg[ConfigurationKeys.PLAY_WELCOME_SOUND])