Coverage for aipyapp/gui/config.py: 0%

120 statements  

« prev     ^ index     » next       coverage.py v7.10.3, created at 2025-08-11 12:02 +0200

1#!/usr/bin/env python 

2#coding: utf-8 

3 

4import os 

5 

6import wx 

7import wx.adv 

8from wx import DirDialog, FD_SAVE, FD_OVERWRITE_PROMPT 

9from wx.lib.agw.floatspin import FloatSpin, EVT_FLOATSPIN, FS_LEFT, FS_RIGHT, FS_CENTRE, FS_READONLY 

10 

11from .. import T, set_lang 

12 

13class ConfigDialog(wx.Dialog): 

14 def __init__(self, parent, settings): 

15 super().__init__(parent, title=T('Configuration')) 

16 

17 self.settings = settings 

18 

19 vbox = wx.BoxSizer(wx.VERTICAL) 

20 

21 # Main panel with content 

22 main_panel = wx.Panel(self) 

23 main_vbox = wx.BoxSizer(wx.VERTICAL) 

24 

25 # Work directory group 

26 work_dir_box = wx.StaticBox(main_panel, -1, T('Work Directory')) 

27 work_dir_sizer = wx.StaticBoxSizer(work_dir_box, wx.VERTICAL) 

28 

29 work_dir_panel = wx.Panel(main_panel) 

30 work_dir_inner_sizer = wx.BoxSizer(wx.HORIZONTAL) 

31 

32 self.work_dir_text = wx.TextCtrl(work_dir_panel, -1, settings.workdir, style=wx.TE_READONLY) 

33 work_dir_inner_sizer.Add(self.work_dir_text, 1, wx.ALL | wx.EXPAND, 5) 

34 

35 browse_button = wx.Button(work_dir_panel, -1, T('Browse...')) 

36 browse_button.Bind(wx.EVT_BUTTON, self.on_browse_work_dir) 

37 work_dir_inner_sizer.Add(browse_button, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) 

38 

39 work_dir_panel.SetSizer(work_dir_inner_sizer) 

40 work_dir_sizer.Add(work_dir_panel, 0, wx.ALL | wx.EXPAND, 5) 

41 

42 # Add hint about creating new directory 

43 hint_text = wx.StaticText(main_panel, -1, T('You can create a new directory in the file dialog')) 

44 work_dir_sizer.Add(hint_text, 0, wx.LEFT | wx.BOTTOM, 5) 

45 

46 main_vbox.Add(work_dir_sizer, 0, wx.ALL | wx.EXPAND, 10) 

47 

48 # Settings group 

49 settings_box = wx.StaticBox(main_panel, -1, T('Settings')) 

50 settings_sizer = wx.StaticBoxSizer(settings_box, wx.VERTICAL) 

51 

52 # Max tokens slider 

53 tokens_panel = wx.Panel(main_panel) 

54 tokens_sizer = wx.BoxSizer(wx.HORIZONTAL) 

55 

56 tokens_label = wx.StaticText(tokens_panel, -1, T('Max Tokens') + ":") 

57 tokens_sizer.Add(tokens_label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) 

58 

59 self.tokens_slider = wx.Slider(tokens_panel, -1, 

60 settings.get('max_tokens', 8192), 

61 minValue=64, 

62 maxValue=128*1024, 

63 style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS) 

64 self.tokens_slider.SetTickFreq(100) 

65 tokens_sizer.Add(self.tokens_slider, 1, wx.ALL | wx.EXPAND, 5) 

66 

67 self.tokens_text = wx.StaticText(tokens_panel, -1, str(self.tokens_slider.GetValue())) 

68 self.tokens_text.SetMinSize((50, -1)) 

69 tokens_sizer.Add(self.tokens_text, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) 

70 

71 tokens_panel.SetSizer(tokens_sizer) 

72 settings_sizer.Add(tokens_panel, 0, wx.ALL | wx.EXPAND, 5) 

73 

74 # Timeout slider 

75 timeout_panel = wx.Panel(main_panel) 

76 timeout_sizer = wx.BoxSizer(wx.HORIZONTAL) 

77 

78 timeout_label = wx.StaticText(timeout_panel, -1, T('Timeout (seconds)') + ":") 

79 timeout_sizer.Add(timeout_label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) 

80 

81 self.timeout_slider = wx.Slider(timeout_panel, -1, 

82 int(settings.get('timeout', 0)), 

83 minValue=0, 

84 maxValue=120, 

85 style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS) 

86 self.timeout_slider.SetTickFreq(30) 

87 timeout_sizer.Add(self.timeout_slider, 1, wx.ALL | wx.EXPAND, 5) 

88 

89 self.timeout_text = wx.StaticText(timeout_panel, -1, str(self.timeout_slider.GetValue())) 

90 self.timeout_text.SetMinSize((50, -1)) 

91 timeout_sizer.Add(self.timeout_text, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) 

92 

93 timeout_panel.SetSizer(timeout_sizer) 

94 settings_sizer.Add(timeout_panel, 0, wx.ALL | wx.EXPAND, 5) 

95 

96 # Max rounds slider 

97 rounds_panel = wx.Panel(main_panel) 

98 rounds_sizer = wx.BoxSizer(wx.HORIZONTAL) 

99 

100 rounds_label = wx.StaticText(rounds_panel, -1, T('Max Rounds') + ":") 

101 rounds_sizer.Add(rounds_label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) 

102 

103 self.rounds_slider = wx.Slider(rounds_panel, -1, 

104 settings.get('max_rounds', 16), 

105 minValue=1, 

106 maxValue=64, 

107 style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS) 

108 self.rounds_slider.SetTickFreq(8) 

109 rounds_sizer.Add(self.rounds_slider, 1, wx.ALL | wx.EXPAND, 5) 

110 

111 self.rounds_text = wx.StaticText(rounds_panel, -1, str(self.rounds_slider.GetValue())) 

112 rounds_sizer.Add(self.rounds_text, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) 

113 

114 rounds_panel.SetSizer(rounds_sizer) 

115 settings_sizer.Add(rounds_panel, 0, wx.ALL | wx.EXPAND, 5) 

116 

117 main_vbox.Add(settings_sizer, 0, wx.ALL | wx.EXPAND, 10) 

118 

119 self.url_ctrl = wx.adv.HyperlinkCtrl(main_panel, label=T('Click here for more information'), url="https://d.aipyaipy.com/d/162", style=wx.adv.HL_ALIGN_LEFT | wx.adv.HL_CONTEXTMENU) 

120 main_vbox.Add(self.url_ctrl, 0, wx.ALL, 10) 

121 

122 main_panel.SetSizer(main_vbox) 

123 vbox.Add(main_panel, 1, wx.EXPAND) 

124 

125 # Buttons panel at bottom 

126 button_panel = wx.Panel(self) 

127 button_sizer = wx.BoxSizer(wx.HORIZONTAL) 

128 

129 ok_button = wx.Button(button_panel, wx.ID_OK, T('OK')) 

130 ok_button.SetMinSize((100, 30)) 

131 cancel_button = wx.Button(button_panel, wx.ID_CANCEL, T('Cancel')) 

132 cancel_button.SetMinSize((100, 30)) 

133 

134 button_sizer.Add(ok_button, 0, wx.ALL, 5) 

135 button_sizer.Add(cancel_button, 0, wx.ALL, 5) 

136 

137 button_panel.SetSizer(button_sizer) 

138 vbox.Add(button_panel, 0, wx.ALL | wx.ALIGN_CENTER | wx.BOTTOM, 20) 

139 

140 # Bind events 

141 self.tokens_slider.Bind(wx.EVT_SLIDER, self.on_tokens_slider) 

142 self.timeout_slider.Bind(wx.EVT_SLIDER, self.on_timeout_slider) 

143 self.rounds_slider.Bind(wx.EVT_SLIDER, self.on_rounds_slider) 

144 

145 self.SetSizer(vbox) 

146 self.SetMinSize((500, 450)) 

147 self.Fit() 

148 self.Centre() 

149 

150 def on_browse_work_dir(self, event): 

151 with DirDialog(self, T('Select work directory'), 

152 defaultPath=self.work_dir_text.GetValue(), 

153 style=wx.DD_DEFAULT_STYLE) as dlg: 

154 if dlg.ShowModal() == wx.ID_OK: 

155 self.work_dir_text.SetValue(dlg.GetPath()) 

156 

157 def on_tokens_slider(self, event): 

158 value = self.tokens_slider.GetValue() 

159 self.tokens_text.SetLabel(str(value)) 

160 

161 def on_timeout_slider(self, event): 

162 value = self.timeout_slider.GetValue() 

163 self.timeout_text.SetLabel(str(value)) 

164 

165 def on_rounds_slider(self, event): 

166 value = self.rounds_slider.GetValue() 

167 self.rounds_text.SetLabel(str(value)) 

168 

169 def get_values(self): 

170 return { 

171 'workdir': self.work_dir_text.GetValue(), 

172 'max_tokens': int(self.tokens_slider.GetValue()), 

173 'timeout': float(self.timeout_slider.GetValue()), 

174 'max_rounds': int(self.rounds_slider.GetValue()) 

175 } 

176 

177if __name__ == '__main__': 

178 class TestSettings: 

179 def __init__(self): 

180 self.workdir = os.getcwd() 

181 self._settings = { 

182 'max-tokens': 2000, 

183 'timeout': 30.0, 

184 'max-rounds': 10 

185 } 

186 

187 def get(self, key, default=None): 

188 return self._settings.get(key, default) 

189 

190 def __setitem__(self, key, value): 

191 self._settings[key] = value 

192 

193 def save(self): 

194 print("Settings saved:", self._settings) 

195 

196 app = wx.App(False) 

197 settings = TestSettings() 

198 dialog = ConfigDialog(None, settings) 

199 if dialog.ShowModal() == wx.ID_OK: 

200 values = dialog.get_values() 

201 print("New settings:", values) 

202 dialog.Destroy() 

203 app.MainLoop()