Coverage for src/robotide/preferences/general.py: 40%
201 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-06 10:40 +0100
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-06 10:40 +0100
1# Copyright 2020- Robot Framework Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
15from functools import lru_cache 1bc
16from os.path import abspath, dirname, join 1bc
17import builtins 1bc
18import wx 1bc
20from ..ui.preferences_dialogs import (boolean_editor, PreferencesPanel, IntegerChoiceEditor, SpinChoiceEditor, 1bc
21 StringChoiceEditor, PreferencesColorPicker)
22from .managesettingsdialog import SaveLoadSettings 1bc
23try: 1bc
24 from robot.conf import languages 1bc
25except ImportError:
26 languages = None
28_ = wx.GetTranslation # To keep linter/code analyser happy 1bc
29builtins.__dict__['_'] = wx.GetTranslation 1bc
31ID_APPLY_TO_PANEL = wx.NewIdRef() 1bc
32ID_RESET = wx.NewIdRef() 1bc
33ID_SAVELOADSETTINGS = wx.NewIdRef() 1bc
34ID_LOAD = 5551 1bc
35ID_SAVE = 5552 1bc
36ID_CANCEL = -1 1bc
37LIGHT_GRAY = "light gray" 1bc
38FIXED_FONT = 'fixed font' 1bc
41@lru_cache(maxsize=2) 1bc
42def read_fonts(fixed=False): 1bc
43 """Returns list with fixed width fonts"""
44 f = wx.FontEnumerator()
45 f.EnumerateFacenames()
46 names = f.GetFacenames(fixedWidthOnly=fixed)
47 names = [n for n in names if not n.startswith('@')]
48 names.sort()
49 return names
52@lru_cache(maxsize=2) 1bc
53def read_languages(): 1bc
54 """Returns list with translatqble languages"""
55 if languages:
56 from . import Languages
57 names = [n for n in Languages.names]
58 else:
59 names = [('English', 'en'), ('Portuguese', 'pt')]
60 names = [n[0] for n in names if not n[0].startswith('@')]
61 names.sort()
62 return names
65def set_colors(element, bk_color, fg_color): 1bc
66 element.SetBackgroundColour(bk_color) 1a
67 # element.SetOwnBackgroundColour(bk_color)
68 element.SetForegroundColour(fg_color) 1a
69 # element.SetOwnForegroundColour(fg_color)
72class GeneralPreferences(PreferencesPanel): 1bc
74 def __init__(self, settings, *args, **kwargs): 1bc
75 super(GeneralPreferences, self).__init__(*args, **kwargs) 1a
76 self._settings = settings 1a
77 self._color_pickers = [] 1a
78 self.name = 'General' 1a
79 self._apply_to_panels = self._settings.get('apply to panels', False) 1a
80 self.background_color = self.settings['background'] 1a
81 self.foreground_color = self.settings['foreground'] 1a
82 self.sbackground_color = self.settings['secondary background'] 1a
83 self.sforeground_color = self.settings['secondary foreground'] 1a
84 # what would make this UI much more usable is if there were a
85 # preview window in the dialog that showed all the colors. I
86 # don't have the time to do that right now, so this will have
87 # to suffice.
89 # print(f"DEBUG: preferences/general.py GeneralPeferences settings_path={self._settings._default_path}")
90 ui_language = self._select_ui_language() 1a
91 font_editor = self._create_font_editor() 1a
92 colors_sizer = self.create_colors_sizer() 1a
93 main_sizer = wx.FlexGridSizer(rows=6, cols=1, vgap=10, hgap=10) 1a
94 buttons_sizer = wx.BoxSizer(orient=wx.HORIZONTAL) 1a
95 reset = wx.Button(self, ID_RESET, _('Reset colors to default')) 1a
96 saveloadsettings = wx.Button(self, ID_SAVELOADSETTINGS, _('Save or Load settings')) 1a
97 self.cb_apply_to_panels = wx.CheckBox(self, ID_APPLY_TO_PANEL, 1a
98 label=_("Apply to Project and File Explorer panels"))
99 self.cb_apply_to_panels.Enable() 1a
100 self.cb_apply_to_panels.SetValue(self._apply_to_panels) 1a
101 set_colors(self.cb_apply_to_panels, self.background_color, self.foreground_color) 1a
102 set_colors(reset, self.sbackground_color, self.sforeground_color) 1a
103 set_colors(saveloadsettings, self.sbackground_color, self.sforeground_color) 1a
104 # set_colors(ui_language, Colour(self.color_background), Colour(self.color_foreground))
105 main_sizer.Add(font_editor) 1a
106 main_sizer.Add(colors_sizer) 1a
107 main_sizer.Add(self.cb_apply_to_panels) 1a
108 buttons_sizer.Add(reset) 1a
109 buttons_sizer.AddSpacer(10) 1a
110 buttons_sizer.Add(saveloadsettings) 1a
111 main_sizer.Add(buttons_sizer) 1a
112 main_sizer.AddSpacer(10) 1a
113 main_sizer.Add(ui_language) 1a
114 self.SetSizerAndFit(main_sizer) 1a
115 self.Bind(wx.EVT_BUTTON, self.on_reset) 1a
116 self.Bind(wx.EVT_BUTTON, self.on_save_load_settings) 1a
117 self.Bind(wx.EVT_CHECKBOX, self.on_check_box, self.cb_apply_to_panels) 1a
119 def on_check_box(self, event): 1bc
120 self._apply_to_panels = event.IsChecked()
121 self._settings.set('apply to panels', self._apply_to_panels)
122 # print(f"DEBUG: Preferences Checkbox set {str(self._apply_to_panels)}")
124 def on_reset(self, event): 1bc
125 if event.GetId() != ID_RESET:
126 event.Skip()
127 return
128 defaults = self._read_defaults()
129 for picker in self._color_pickers:
130 picker.SetColour(defaults[picker.key])
131 # self.Refresh()
133 def on_save_load_settings(self, event): 1bc
134 if event.GetId() != ID_SAVELOADSETTINGS:
135 event.Skip()
136 return
137 save_settings_dialog = SaveLoadSettings(self, self._settings) # DEBUG self.__class__.__name__
138 save_settings_dialog.CenterOnParent()
139 save_settings_dialog.ShowModal()
140 # Does not look nice but closes Preferences window, so it comes recolored on next call
141 # Only working on first use :(
142 # DEBUG: Only close window when Loading, not when Saving (but return is always 5101)
143 wx.FindWindowByName(_("RIDE - Preferences")).Close(force=True)
145 def _reload_settings(self): 1bc
146 import os
147 from ..context import SETTINGS_DIRECTORY
148 self._default_path = os.path.join(SETTINGS_DIRECTORY, 'settings.cfg')
149 settings = [s.strip() for s in open(self._default_path, 'r').readlines()]
150 name = '[General]'
151 start_index = settings.index(name) + 1
152 defaults = {}
153 for line in settings[start_index:]:
154 if line.startswith('['):
155 break
156 if not line or line.startswith(';') or line.startswith('#'):
157 continue
158 key, value = [s.strip().strip('\'') for s in line.split("=")]
159 # print(f"DEBUG: Preferences General default value type {type(value)} {value}")
160 if len(value) > 0 and value[0] == '(' and value[-1] == ')':
161 from ast import literal_eval as make_tuple
162 value = make_tuple(value)
163 defaults[key] = value
164 self._settings = defaults
166 for picker in self._color_pickers:
167 picker.SetColour(defaults[picker.key])
168 self.Refresh(True)
170 def _read_defaults(self, plugin=False): 1bc
171 settings = [s.strip() for s in open(self._get_path(), 'r').readlines()]
172 name = ('[[%s]]' if plugin else '[%s]') % self.name
173 start_index = settings.index(name) + 1
174 defaults = {}
175 for line in settings[start_index:]:
176 if line.startswith('['):
177 break
178 if not line or line.startswith(';') or line.startswith('#'):
179 continue
180 # print(f"DEBUG: Preferences General RESET default line {line} \nLine Split: {line.split("=")}")
181 key, value = [s.strip().strip('\'') for s in line.split("=")]
182 # print(f"DEBUG: Preferences General default value type {type(value)} {value}")
183 if len(value) > 0 and value[0] == '(' and value[-1] == ')':
184 from ast import literal_eval as make_tuple
185 value = make_tuple(value)
186 defaults[key] = value
187 return defaults
189 @staticmethod 1bc
190 def _get_path(): 1bc
191 return join(dirname(abspath(__file__)), 'settings.cfg')
193 def _create_font_editor(self): 1bc
194 f = IntegerChoiceEditor( 1a
195 self._settings, 'font size', _('Font Size'),
196 [str(i) for i in range(8, 16)])
197 sizer = wx.FlexGridSizer(rows=3, cols=2, vgap=10, hgap=30) 1a
198 l_size = f.label(self) 1a
199 set_colors(l_size, self.background_color, self.foreground_color) 1a
200 sizer.AddMany([l_size, f.chooser(self)]) 1a
201 fixed_font = False 1a
202 if 'zoom factor' in self._settings: 202 ↛ 203line 202 didn't jump to line 203 because the condition on line 202 was never true1a
203 z = SpinChoiceEditor(
204 self._settings, 'zoom factor', _('Zoom Factor'), (-10, 20))
205 l_zoom = z.label(self)
206 set_colors(l_zoom, self.background_color, self.foreground_color)
207 sizer.AddMany([l_zoom, z.chooser(self)])
208 if FIXED_FONT in self._settings: 208 ↛ 209line 208 didn't jump to line 209 because the condition on line 208 was never true1a
209 l_ff, editor = boolean_editor(self, self._settings, FIXED_FONT, _('Use fixed width font'))
210 set_colors(l_ff, self.background_color, self.foreground_color)
211 sizer.AddMany([l_ff, editor])
212 fixed_font = self._settings[FIXED_FONT]
213 if 'font face' in self._settings: 213 ↛ 214line 213 didn't jump to line 214 because the condition on line 213 was never true1a
214 s = StringChoiceEditor(self._settings, 'font face', _('Font Face'), read_fonts(fixed_font))
215 l_font = s.label(self)
216 set_colors(l_font, self.background_color, self.foreground_color)
217 sizer.AddMany([l_font, s.chooser(self)])
218 sizer.Layout() 1a
219 return sizer 1a
221 def _select_ui_language(self): 1bc
222 sizer = wx.FlexGridSizer(rows=3, cols=2, vgap=10, hgap=30) 1a
223 if 'ui language' in self._settings: 223 ↛ 224line 223 didn't jump to line 224 because the condition on line 223 was never true1a
224 ll = StringChoiceEditor(self._settings, 'ui language', _('Language'), read_languages())
225 l_lang = ll.label(self)
226 set_colors(l_lang, self.background_color, self.foreground_color)
227 sizer.AddMany([l_lang, ll.chooser(self)])
228 sizer.Layout() 1a
229 return sizer 1a
231 def create_colors_sizer(self): 1bc
232 raise NotImplementedError('Implement me')
235class DefaultPreferences(GeneralPreferences): 1bc
236 location = (_("General"),) 1bc
238 def __init__(self, settings, *args, **kwargs): 1bc
239 self.location = (_("General"),)
240 self.title = _("General Settings")
241 self.name = "General"
242 super(DefaultPreferences, self).__init__(settings[self.name], name_tr=_("General"), *args, **kwargs)
244 def create_colors_sizer(self): 1bc
245 container = wx.GridBagSizer()
246 column = 0
247 row = 0
248 settings = (
249 ('foreground', _('Foreground')),
250 ('background', _('Background')),
251 ('secondary foreground', _('Secondary Foreground')),
252 ('secondary background', _('Secondary Background')),
253 ('foreground text', _('Text Foreground')),
254 ('background help', _('Help Background'))
255 )
256 for settings_key, label_text in settings:
257 if column == 4:
258 column = 0
259 row += 1
260 label = wx.StaticText(self, wx.ID_ANY, label_text)
261 set_colors(label, self.background_color, self.foreground_color)
262 button = PreferencesColorPicker(
263 self, wx.ID_ANY, self._settings, settings_key)
264 container.Add(button, (row, column), flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=4)
265 self._color_pickers.append(button)
266 column += 1
267 container.Add(label, (row, column), flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=8)
268 column += 1
269 return container
271 def on_reset(self, event): 1bc
272 defaults = self._read_defaults()
273 for picker in self._color_pickers:
274 picker.SetColour(defaults[picker.key])
275 # self.Refresh()
276 wx.FindWindowByName(_("RIDE - Preferences")).Close(force=True)