Coverage for src/robotide/ui/preferences_dialogs.py: 48%

190 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-05-06 10:40 +0100

1# Copyright 2008-2015 Nokia Networks 

2# Copyright 2016- Robot Framework Foundation 

3# 

4# Licensed under the Apache License, Version 2.0 (the "License"); 

5# you may not use this file except in compliance with the License. 

6# You may obtain a copy of the License at 

7# 

8# http://www.apache.org/licenses/LICENSE-2.0 

9# 

10# Unless required by applicable law or agreed to in writing, software 

11# distributed under the License is distributed on an "AS IS" BASIS, 

12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

13# See the License for the specific language governing permissions and 

14# limitations under the License. 

15 

16import builtins 1ab

17import textwrap 1ab

18 

19import wx 1ab

20 

21from ..context import IS_LINUX 1ab

22from ..widgets import HelpLabel, Label, TextField 1ab

23 

24_ = wx.GetTranslation # To keep linter/code analyser happy 1ab

25builtins.__dict__['_'] = wx.GetTranslation 1ab

26 

27 

28class PreferencesPanel(wx.Panel): 1ab

29 """Base class for all preference panels used by PreferencesDialog""" 

30 

31 def __init__(self, parent=None, name_tr=None, *args, **kwargs): 1ab

32 self.tree_item = None 1c

33 self.name_tr = name_tr 1c

34 from ..preferences.settings import RideSettings 1c

35 wx.Panel.__init__(self, parent, *args, **kwargs) 1c

36 self._gsettings = RideSettings() 1c

37 self.settings = self._gsettings['General'] 1c

38 self.background_color = self.settings['background'] 1c

39 self.foreground_color = self.settings['foreground'] 1c

40 self.secondary_background_color = self.settings['secondary background'] 1c

41 self.secondary_foreground_color = self.settings['secondary foreground'] 1c

42 self.SetBackgroundColour(self.background_color) 1c

43 self.SetForegroundColour(self.foreground_color) 1c

44 

45 def GetTitle(self): 1ab

46 return getattr(self, "title", self.location[-1]) 

47 

48 def Separator(self, parent, title): 1ab

49 """Creates a simple horizontal separator with title""" 

50 container = wx.Panel(parent, wx.ID_ANY) 

51 label = wx.StaticText(container, wx.ID_ANY, label=title) 

52 label.SetBackgroundColour(self.background_color) 

53 label.SetForegroundColour(self.foreground_color) 

54 sep = wx.StaticLine(container, wx.ID_ANY) 

55 sep.SetBackgroundColour(self.secondary_background_color) 

56 sep.SetForegroundColour(self.secondary_foreground_color) 

57 sizer = wx.BoxSizer(wx.VERTICAL) 

58 sizer.Add(label, 0, wx.EXPAND|wx.TOP, 8) 

59 sizer.Add(sep, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 2) 

60 container.SetSizerAndFit(sizer) 

61 return container 

62 

63 

64class PreferencesComboBox(wx.ComboBox): 1ab

65 """A combobox tied to a specific setting. Saves value to disk after edit.""" 

66 def __init__(self, parent, elid, settings, key, choices): 1ab

67 self.settings = settings 1c

68 self.key = key 1c

69 from ..preferences.settings import RideSettings 1c

70 super(PreferencesComboBox, self).__init__(parent, elid, self._get_value(), 1c

71 size=self._get_size(choices), 

72 choices=choices, style=wx.CB_READONLY) 

73 self._gsettings = RideSettings() 1c

74 self.gsettings = self._gsettings['General'] 1c

75 background_color = self.gsettings['secondary background'] 1c

76 foreground_color = self.gsettings['secondary foreground'] 1c

77 self.SetBackgroundColour(background_color) 1c

78 self.SetForegroundColour(foreground_color) 1c

79 self.Bind(wx.EVT_COMBOBOX, self.on_select) 1c

80 

81 def _get_value(self): 1ab

82 return self.settings[self.key] 

83 

84 @staticmethod 1ab

85 def _get_size(choices=None): 1ab

86 """ In Linux with GTK3 wxPython 4, there was not enough spacing. 

87 The value 72 is there for 2 digits numeric lists, for 

88 IntegerPreferenceComboBox. 

89 This issue only occurs in Linux, for Mac and Windows using default size. 

90 """ 

91 if IS_LINUX and isinstance(choices, list): 91 ↛ 92line 91 didn't jump to line 92 because the condition on line 91 was never true1c

92 return wx.Size(max(max(len(str(s)) for s in choices) * 9, 144), 30) 

93 return wx.DefaultSize 1c

94 

95 def on_select(self, event): 1ab

96 self._set_value(str(event.GetEventObject().GetValue())) 

97 self.settings.save() 

98 

99 def _set_value(self, value): 1ab

100 self.settings[self.key] = value 

101 

102 

103class IntegerPreferenceComboBox(PreferencesComboBox): 1ab

104 """A combobox tied to a setting that has integer values.""" 

105 

106 def _get_value(self): 1ab

107 return str(self.settings[self.key]) 1c

108 

109 def _set_value(self, value): 1ab

110 self.settings[self.key] = int(value) 

111 

112 

113class PreferencesSpinControl(wx.SpinCtrl): 1ab

114 """A spin control tied to a specific setting. Saves value to disk after edit.""" 

115 

116 def __init__(self, parent, elid, settings, key, choices): 1ab

117 self.settings = settings 

118 self.key = key 

119 from ..preferences.settings import RideSettings 

120 super(PreferencesSpinControl, self).__init__(parent, elid, 

121 size=self._get_size(choices[-1])) 

122 

123 self._gsettings = RideSettings() 

124 self.psettings = self._gsettings['General'] 

125 background_color = self.psettings['background'] 

126 foreground_color = self.psettings['foreground'] 

127 self.SetBackgroundColour(background_color) 

128 self.SetForegroundColour(foreground_color) 

129 self.SetRange(*choices) 

130 self.SetValue(self._get_value()) 

131 self.Bind(wx.EVT_SPINCTRL, self.on_change) 

132 self.Bind(wx.EVT_TEXT, self.on_change) 

133 

134 def _get_value(self): 1ab

135 return self.settings[self.key] 

136 

137 @staticmethod 1ab

138 def _get_size(max_value): 1ab

139 """ In Linux with GTK3 wxPython 4, there was not enough spacing. 

140 The value 72 is there for 2 digits numeric lists, for 

141 IntegerPreferenceComboBox. 

142 This issue only occurs in Linux, for Mac and Windows using default size. 

143 """ 

144 if IS_LINUX and max_value: 

145 return wx.Size(max(len(str(max_value)) * 9, 144), 20) 

146 return wx.DefaultSize 

147 

148 def on_change(self, event): 1ab

149 self._set_value(event.GetEventObject().GetValue()) 

150 self.settings.save() 

151 

152 def _set_value(self, value): 1ab

153 self.settings[self.key] = value 

154 

155 

156class PreferencesColorPicker(wx.ColourPickerCtrl): 1ab

157 """A colored button that opens a color picker dialog""" 

158 def __init__(self, parent, elid, settings, key): 1ab

159 self.settings = settings 

160 self.key = key 

161 # print(f"DEBUG: Preferences ColourPicker value type {type(settings[key])}") 

162 value = wx.Colour(settings[key]) 

163 from ..preferences.settings import RideSettings 

164 super(PreferencesColorPicker, self).__init__(parent, elid, colour=value) 

165 self._gsettings = RideSettings() 

166 self.psettings = self._gsettings['General'] 

167 background_color = self.psettings['background'] 

168 foreground_color = self.psettings['foreground'] 

169 self.SetBackgroundColour(background_color) 

170 self.SetForegroundColour(foreground_color) 

171 self.Bind(wx.EVT_COLOURPICKER_CHANGED, self.on_pick_color) 

172 

173 def on_pick_color(self, event): 1ab

174 """Set the color for the given key to the color of the widget""" 

175 color = event.GetColour() 

176 rgb = color.GetAsString(flags=wx.C2S_HTML_SYNTAX) 

177 self.settings[self.key] = rgb 

178 self.settings.save() 

179 

180 def SetColour(self, colour): 1ab

181 super(PreferencesColorPicker, self).SetColour(colour) 

182 self.settings[self.key] = colour 

183 self.settings.save() 

184 

185 

186class _ChoiceEditor(object): 1ab

187 _editor_class = None 1ab

188 

189 def __init__(self, settings, setting_name, label, choices, elhelp=''): 1ab

190 self._settings = settings 1c

191 self._setting_name = setting_name 1c

192 self._label = label 1c

193 self._choices = choices 1c

194 self._help = elhelp 1c

195 from ..preferences.settings import RideSettings 1c

196 self._gsettings = RideSettings() 1c

197 self.csettings = self._gsettings['General'] 1c

198 self.background_color = self.csettings['background'] 1c

199 self.foreground_color = self.csettings['foreground'] 1c

200 

201 def chooser(self, parent): 1ab

202 element = self._editor_class(parent, wx.NewId(), self._settings, 1c

203 key=self._setting_name, choices=self._choices) 

204 element.SetBackgroundColour(self.background_color) 1c

205 element.SetForegroundColour(self.foreground_color) 1c

206 return element 1c

207 

208 def label(self, parent): 1ab

209 llabel = wx.StaticText(parent, wx.NewId(), self._label) 1c

210 llabel.SetBackgroundColour(self.background_color) 1c

211 llabel.SetForegroundColour(self.foreground_color) 1c

212 return llabel 1c

213 

214 def help(self, parent): 1ab

215 return HelpLabel(parent, '\n'.join(textwrap.wrap(self._help, 60))) 

216 

217 

218class StringChoiceEditor(_ChoiceEditor): 1ab

219 _editor_class = PreferencesComboBox 1ab

220 

221 def SetSelection(self, combo, idx): 1ab

222 self._editor_class.SetSelection(combo, idx) 

223 

224 

225class IntegerChoiceEditor(_ChoiceEditor): 1ab

226 _editor_class = IntegerPreferenceComboBox 1ab

227 

228 

229class SpinChoiceEditor(_ChoiceEditor): 1ab

230 _editor_class = PreferencesSpinControl 1ab

231 

232 

233def boolean_editor(parent, settings, name, label, elhelp=''): 1ab

234 editor = _create_checkbox_editor(parent, settings, name, elhelp) 

235 from ..preferences.settings import RideSettings 

236 _gsettings = RideSettings() 

237 bsettings = _gsettings['General'] 

238 background_color = bsettings['background'] 

239 foreground_color = bsettings['foreground'] 

240 editor.SetBackgroundColour(background_color) 

241 editor.SetForegroundColour(foreground_color) 

242 blabel = Label(parent, label=label) 

243 blabel.SetBackgroundColour(background_color) 

244 blabel.SetForegroundColour(foreground_color) 

245 return blabel, editor 

246 

247 

248def _create_checkbox_editor(parent, settings, name, elhelp): 1ab

249 initial_value = settings.get(name, "") 

250 editor = wx.CheckBox(parent) 

251 editor.SetValue(initial_value) 

252 editor.Bind(wx.EVT_CHECKBOX, lambda evt: settings.set(name, editor.GetValue())) 

253 editor.SetToolTip(elhelp) 

254 return editor 

255 

256 

257def comma_separated_value_editor(parent, settings, name, label, thelp=''): 1ab

258 initial_value = ', '.join(settings.get(name, "")) 

259 editor = TextField(parent, initial_value) 

260 from ..preferences.settings import RideSettings 

261 _gsettings = RideSettings() 

262 esettings = _gsettings['General'] 

263 background_color = esettings['background'] 

264 foreground_color = esettings['foreground'] 

265 editor.SetBackgroundColour(background_color) 

266 editor.SetForegroundColour(foreground_color) 

267 editor.SetToolTip(thelp) 

268 

269 def set_value(evt): 

270 new_value = [token.strip() for token in editor.GetValue().split(',') 

271 if token.strip()] 

272 settings.set(name, new_value) 

273 evt.Skip() 

274 editor.Bind(wx.EVT_KILL_FOCUS, lambda evt: set_value(evt)) 

275 elabel = Label(parent, label=label) 

276 elabel.SetBackgroundColour(background_color) 

277 elabel.SetForegroundColour(foreground_color) 

278 return elabel, editor