psychopy 2025.1.1__py3-none-any.whl → 2025.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of psychopy might be problematic. Click here for more details.
- psychopy/VERSION +1 -1
- psychopy/alerts/alertsCatalogue/4810.yaml +19 -0
- psychopy/alerts/alertsCatalogue/alertCategories.yaml +4 -0
- psychopy/alerts/alertsCatalogue/alertmsg.py +15 -1
- psychopy/alerts/alertsCatalogue/generateAlertmsg.py +2 -2
- psychopy/app/Resources/classic/add_many.png +0 -0
- psychopy/app/Resources/classic/add_many@2x.png +0 -0
- psychopy/app/Resources/classic/devices.png +0 -0
- psychopy/app/Resources/classic/devices@2x.png +0 -0
- psychopy/app/Resources/classic/photometer.png +0 -0
- psychopy/app/Resources/classic/photometer@2x.png +0 -0
- psychopy/app/Resources/dark/add_many.png +0 -0
- psychopy/app/Resources/dark/add_many@2x.png +0 -0
- psychopy/app/Resources/dark/devices.png +0 -0
- psychopy/app/Resources/dark/devices@2x.png +0 -0
- psychopy/app/Resources/dark/photometer.png +0 -0
- psychopy/app/Resources/dark/photometer@2x.png +0 -0
- psychopy/app/Resources/light/add_many.png +0 -0
- psychopy/app/Resources/light/add_many@2x.png +0 -0
- psychopy/app/Resources/light/devices.png +0 -0
- psychopy/app/Resources/light/devices@2x.png +0 -0
- psychopy/app/Resources/light/photometer.png +0 -0
- psychopy/app/Resources/light/photometer@2x.png +0 -0
- psychopy/app/_psychopyApp.py +35 -13
- psychopy/app/builder/builder.py +88 -35
- psychopy/app/builder/dialogs/__init__.py +69 -220
- psychopy/app/builder/dialogs/dlgsCode.py +29 -8
- psychopy/app/builder/dialogs/paramCtrls.py +1468 -904
- psychopy/app/builder/validators.py +25 -17
- psychopy/app/coder/coder.py +12 -1
- psychopy/app/coder/repl.py +5 -2
- psychopy/app/colorpicker/__init__.py +1 -1
- psychopy/app/deviceManager/__init__.py +1 -0
- psychopy/app/deviceManager/addDialog.py +218 -0
- psychopy/app/deviceManager/dialog.py +185 -0
- psychopy/app/deviceManager/panel.py +191 -0
- psychopy/app/deviceManager/utils.py +60 -0
- psychopy/app/idle.py +7 -0
- psychopy/app/locale/ar_001/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ar_001/LC_MESSAGE/messages.po +12695 -10592
- psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.po +10199 -24
- psychopy/app/locale/da_DK/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/da_DK/LC_MESSAGE/messages.po +10199 -24
- psychopy/app/locale/de_DE/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/de_DE/LC_MESSAGE/messages.po +11221 -9712
- psychopy/app/locale/el_GR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/el_GR/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/en_NZ/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/en_NZ/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/en_US/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/en_US/LC_MESSAGE/messages.po +10195 -18
- psychopy/app/locale/es_CO/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_CO/LC_MESSAGE/messages.po +11917 -9101
- psychopy/app/locale/es_ES/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_ES/LC_MESSAGE/messages.po +11924 -9103
- psychopy/app/locale/es_US/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_US/LC_MESSAGE/messages.po +11917 -9101
- psychopy/app/locale/et_EE/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/et_EE/LC_MESSAGE/messages.po +11084 -9569
- psychopy/app/locale/fa_IR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/fa_IR/LC_MESSAGE/messages.po +11590 -5806
- psychopy/app/locale/fi_FI/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/fi_FI/LC_MESSAGE/messages.po +10199 -24
- psychopy/app/locale/fr_FR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/fr_FR/LC_MESSAGE/messages.po +11091 -9577
- psychopy/app/locale/he_IL/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/he_IL/LC_MESSAGE/messages.po +11072 -9549
- psychopy/app/locale/hi_IN/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/hi_IN/LC_MESSAGE/messages.po +11071 -9559
- psychopy/app/locale/hu_HU/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/hu_HU/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/it_IT/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/it_IT/LC_MESSAGE/messages.po +11072 -9560
- psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po +1485 -1137
- psychopy/app/locale/ko_KR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ko_KR/LC_MESSAGE/messages.po +10199 -24
- psychopy/app/locale/ms_MY/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ms_MY/LC_MESSAGE/messages.po +11463 -8757
- psychopy/app/locale/nl_NL/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/nl_NL/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/nn_NO/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/nn_NO/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/pl_PL/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/pl_PL/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/pt_PT/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/pt_PT/LC_MESSAGE/messages.po +11288 -9434
- psychopy/app/locale/ro_RO/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ro_RO/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/ru_RU/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ru_RU/LC_MESSAGE/messages.po +10199 -24
- psychopy/app/locale/sv_SE/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/sv_SE/LC_MESSAGE/messages.po +11441 -8747
- psychopy/app/locale/tr_TR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/tr_TR/LC_MESSAGE/messages.po +11069 -9545
- psychopy/app/locale/zh_CN/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/zh_CN/LC_MESSAGE/messages.po +12085 -8268
- psychopy/app/locale/zh_TW/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/zh_TW/LC_MESSAGE/messages.po +11929 -8022
- psychopy/app/plugin_manager/dialog.py +12 -3
- psychopy/app/plugin_manager/packageIndex.py +303 -0
- psychopy/app/plugin_manager/packages.py +203 -63
- psychopy/app/plugin_manager/plugins.py +120 -240
- psychopy/app/preferencesDlg.py +6 -1
- psychopy/app/psychopyApp.py +16 -4
- psychopy/app/runner/runner.py +10 -2
- psychopy/app/runner/scriptProcess.py +8 -3
- psychopy/app/stdout/stdOutRich.py +11 -4
- psychopy/app/themes/icons.py +3 -0
- psychopy/app/utils.py +61 -0
- psychopy/data/experiment.py +133 -23
- psychopy/data/routine.py +12 -0
- psychopy/data/staircase.py +42 -20
- psychopy/data/trial.py +20 -12
- psychopy/data/utils.py +42 -2
- psychopy/demos/builder/Experiments/dragAndDrop/drag_and_drop.psyexp +22 -5
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solutions.xlsx +0 -0
- psychopy/demos/builder/Experiments/stroopVoice/stroopVoice.psyexp +2 -12
- psychopy/demos/builder/Feature Demos/buttonBox/buttonBoxDemo.psyexp +3 -8
- psychopy/demos/builder/Feature Demos/movies/movie.psyexp +220 -0
- psychopy/demos/builder/Feature Demos/movies/readme.md +3 -0
- psychopy/demos/builder/Feature Demos/visualValidator/visualValidator.psyexp +1 -2
- psychopy/demos/builder/Hardware/camera/camera.psyexp +3 -16
- psychopy/demos/builder/Hardware/microphone/microphone.psyexp +3 -16
- psychopy/demos/coder/hardware/hdf5_extract.py +133 -0
- psychopy/event.py +20 -15
- psychopy/experiment/_experiment.py +86 -10
- psychopy/experiment/components/__init__.py +3 -10
- psychopy/experiment/components/_base.py +9 -20
- psychopy/experiment/components/button/__init__.py +1 -1
- psychopy/experiment/components/buttonBox/__init__.py +50 -54
- psychopy/experiment/components/camera/__init__.py +137 -359
- psychopy/experiment/components/keyboard/__init__.py +17 -24
- psychopy/experiment/components/microphone/__init__.py +61 -110
- psychopy/experiment/components/movie/__init__.py +2 -3
- psychopy/experiment/components/serialOut/__init__.py +192 -93
- psychopy/experiment/components/settings/__init__.py +45 -27
- psychopy/experiment/components/sound/__init__.py +82 -73
- psychopy/experiment/components/soundsensor/__init__.py +43 -80
- psychopy/experiment/devices.py +303 -0
- psychopy/experiment/exports.py +20 -18
- psychopy/experiment/flow.py +7 -0
- psychopy/experiment/loops.py +47 -29
- psychopy/experiment/monitor.py +74 -0
- psychopy/experiment/params.py +48 -10
- psychopy/experiment/plugins.py +28 -108
- psychopy/experiment/py2js_transpiler.py +1 -1
- psychopy/experiment/routines/__init__.py +1 -1
- psychopy/experiment/routines/_base.py +59 -24
- psychopy/experiment/routines/audioValidator/__init__.py +19 -155
- psychopy/experiment/routines/visualValidator/__init__.py +25 -25
- psychopy/hardware/__init__.py +20 -57
- psychopy/hardware/button.py +15 -2
- psychopy/hardware/camera/__init__.py +2237 -1394
- psychopy/hardware/joystick/__init__.py +1 -1
- psychopy/hardware/keyboard.py +5 -8
- psychopy/hardware/listener.py +4 -1
- psychopy/hardware/manager.py +75 -35
- psychopy/hardware/microphone.py +52 -6
- psychopy/hardware/monitor.py +144 -0
- psychopy/hardware/photometer/__init__.py +156 -117
- psychopy/hardware/serialdevice.py +16 -2
- psychopy/hardware/soundsensor.py +4 -1
- psychopy/iohub/devices/deviceConfigValidation.py +2 -1
- psychopy/iohub/devices/keyboard/darwin.py +8 -5
- psychopy/iohub/util/__init__.py +7 -8
- psychopy/localization/generateTranslationTemplate.py +208 -116
- psychopy/localization/messages.pot +4305 -3502
- psychopy/monitors/MonitorCenter.py +174 -74
- psychopy/plugins/__init__.py +6 -4
- psychopy/preferences/devices.py +80 -0
- psychopy/preferences/generateHints.py +2 -1
- psychopy/preferences/preferences.py +35 -11
- psychopy/scripts/psychopy-pkgutil.py +969 -0
- psychopy/scripts/psyexpCompile.py +1 -1
- psychopy/session.py +34 -38
- psychopy/sound/__init__.py +6 -260
- psychopy/sound/audioclip.py +164 -0
- psychopy/sound/backend_ptb.py +8 -0
- psychopy/sound/backend_pygame.py +10 -0
- psychopy/sound/backend_pysound.py +9 -0
- psychopy/sound/backends/__init__.py +0 -0
- psychopy/sound/microphone.py +3 -0
- psychopy/sound/sound.py +58 -0
- psychopy/tests/data/correctScript/python/correctNoiseStimComponent.py +1 -1
- psychopy/tests/data/duplicateHeaders.csv +2 -0
- psychopy/tests/test_app/test_builder/test_BuilderFrame.py +22 -7
- psychopy/tests/test_app/test_builder/test_CompileFromBuilder.py +0 -2
- psychopy/tests/test_data/test_utils.py +5 -1
- psychopy/tests/test_experiment/test_components/test_ButtonBoxComponent.py +22 -2
- psychopy/tests/test_hardware/test_ports.py +0 -12
- psychopy/tests/test_tools/test_stringtools.py +1 -1
- psychopy/tools/attributetools.py +12 -5
- psychopy/tools/fontmanager.py +17 -14
- psychopy/tools/movietools.py +43 -2
- psychopy/tools/stringtools.py +33 -8
- psychopy/tools/versionchooser.py +1 -1
- psychopy/validation/audio.py +5 -1
- psychopy/validation/visual.py +5 -1
- psychopy/visual/basevisual.py +8 -7
- psychopy/visual/circle.py +2 -2
- psychopy/visual/image.py +29 -109
- psychopy/visual/movies/__init__.py +1800 -313
- psychopy/visual/polygon.py +4 -0
- psychopy/visual/shape.py +2 -2
- psychopy/visual/window.py +34 -11
- psychopy/voicekey/__init__.py +41 -669
- psychopy/voicekey/labjack_vks.py +7 -48
- psychopy/voicekey/parallel_vks.py +7 -42
- psychopy/voicekey/vk_tools.py +114 -263
- {psychopy-2025.1.1.dist-info → psychopy-2025.2.1.dist-info}/METADATA +17 -11
- {psychopy-2025.1.1.dist-info → psychopy-2025.2.1.dist-info}/RECORD +216 -184
- {psychopy-2025.1.1.dist-info → psychopy-2025.2.1.dist-info}/WHEEL +1 -1
- psychopy/visual/movies/players/__init__.py +0 -62
- psychopy/visual/movies/players/ffpyplayer_player.py +0 -1401
- psychopy/voicekey/demo_vks.py +0 -12
- psychopy/voicekey/signal.py +0 -42
- {psychopy-2025.1.1.dist-info → psychopy-2025.2.1.dist-info}/entry_points.txt +0 -0
- {psychopy-2025.1.1.dist-info → psychopy-2025.2.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
from psychopy.app import utils
|
|
2
|
+
from psychopy.app.builder.dialogs.paramCtrls import EVT_PARAM_CHANGED, ParamCtrl
|
|
3
|
+
from psychopy.app.builder.validators import WarningManager
|
|
4
|
+
from psychopy.app.themes import fonts
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import wx
|
|
8
|
+
from wx.lib.scrolledpanel import ScrolledPanel
|
|
9
|
+
import wx.propgrid
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DevicePanel(ScrolledPanel):
|
|
13
|
+
def __init__(self, parent, dlg, device):
|
|
14
|
+
ScrolledPanel.__init__(self, parent, style=wx.DEFAULT | wx.VSCROLL)
|
|
15
|
+
self.SetMinSize((512, -1))
|
|
16
|
+
# store parentage
|
|
17
|
+
self.parent = parent
|
|
18
|
+
self.dlg = dlg
|
|
19
|
+
# setup warnings
|
|
20
|
+
self.warnings = WarningManager(self)
|
|
21
|
+
# store device
|
|
22
|
+
self.device = device
|
|
23
|
+
# setup sizer
|
|
24
|
+
self.border = wx.BoxSizer(wx.VERTICAL)
|
|
25
|
+
self.SetSizer(self.border)
|
|
26
|
+
self.sizer = wx.BoxSizer(wx.VERTICAL)
|
|
27
|
+
self.border.Add(
|
|
28
|
+
self.sizer, proportion=1, border=0, flag=wx.EXPAND | wx.ALL
|
|
29
|
+
)
|
|
30
|
+
# sort params by categ then order
|
|
31
|
+
sortedParams = {}
|
|
32
|
+
for key in device.order:
|
|
33
|
+
if key in device.params:
|
|
34
|
+
# make sure there's a page for this category
|
|
35
|
+
categ = device.params[key].categ
|
|
36
|
+
if categ not in sortedParams:
|
|
37
|
+
sortedParams[categ] = {}
|
|
38
|
+
# add param to categ
|
|
39
|
+
sortedParams[categ][key] = device.params[key]
|
|
40
|
+
for key in device.params:
|
|
41
|
+
# make sure there's a page for this category
|
|
42
|
+
categ = device.params[key].categ
|
|
43
|
+
if categ not in sortedParams:
|
|
44
|
+
sortedParams[categ] = {}
|
|
45
|
+
# add param to categ
|
|
46
|
+
if key not in sortedParams[categ]:
|
|
47
|
+
sortedParams[categ][key] = device.params[key]
|
|
48
|
+
# param ctrls
|
|
49
|
+
self.paramCtrls = {}
|
|
50
|
+
for categ in sortedParams:
|
|
51
|
+
# if categ if Basic, add to root sizer
|
|
52
|
+
toggle = None
|
|
53
|
+
if categ == "Basic":
|
|
54
|
+
categSizer = self.sizer
|
|
55
|
+
else:
|
|
56
|
+
# otherwise, make a show/hider
|
|
57
|
+
categSizer = wx.BoxSizer(wx.VERTICAL)
|
|
58
|
+
toggle = utils.ShowHideBtn(
|
|
59
|
+
self, target=categSizer, label=categ
|
|
60
|
+
)
|
|
61
|
+
self.sizer.Add(
|
|
62
|
+
toggle, border=6, flag=wx.EXPAND | wx.ALL
|
|
63
|
+
)
|
|
64
|
+
self.sizer.Add(
|
|
65
|
+
categSizer, border=0, flag=wx.EXPAND | wx.ALL
|
|
66
|
+
)
|
|
67
|
+
for name, param in sortedParams[categ].items():
|
|
68
|
+
# make param ctrl
|
|
69
|
+
self.paramCtrls[name] = ctrl = ParamCtrl(
|
|
70
|
+
self,
|
|
71
|
+
field=name,
|
|
72
|
+
param=param,
|
|
73
|
+
element=device,
|
|
74
|
+
warnings=self.warnings
|
|
75
|
+
)
|
|
76
|
+
ctrl.Bind(EVT_PARAM_CHANGED, self.onParamEdit)
|
|
77
|
+
# make label
|
|
78
|
+
lbl = wx.StaticText(
|
|
79
|
+
self, label=param.label
|
|
80
|
+
)
|
|
81
|
+
# make sizer for this ctrl
|
|
82
|
+
if type(ctrl).__name__ in ("BoolCtrl"):
|
|
83
|
+
sizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
84
|
+
# add crl
|
|
85
|
+
sizer.Add(
|
|
86
|
+
ctrl, border=6, flag=wx.EXPAND | wx.RIGHT
|
|
87
|
+
)
|
|
88
|
+
# add label
|
|
89
|
+
sizer.Add(
|
|
90
|
+
lbl, flag=wx.ALIGN_CENTER
|
|
91
|
+
)
|
|
92
|
+
else:
|
|
93
|
+
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
94
|
+
# add label
|
|
95
|
+
sizer.Add(
|
|
96
|
+
lbl, border=3, flag=wx.EXPAND | wx.BOTTOM
|
|
97
|
+
)
|
|
98
|
+
sizer.Add(
|
|
99
|
+
ctrl, flag=wx.EXPAND
|
|
100
|
+
)
|
|
101
|
+
# add ctrl
|
|
102
|
+
# add sizer to panel
|
|
103
|
+
categSizer.Add(
|
|
104
|
+
sizer, border=6, flag=wx.EXPAND | wx.ALL
|
|
105
|
+
)
|
|
106
|
+
# store name param ctrl
|
|
107
|
+
if name == "deviceLabel":
|
|
108
|
+
self.nameCtrl = self.paramCtrls[name]
|
|
109
|
+
# bump up the font size
|
|
110
|
+
self.nameCtrl.ctrl.SetFont(fonts.AppFont(
|
|
111
|
+
pointSize=int(fonts.AppFont.pointSize*1.5),
|
|
112
|
+
bold=True
|
|
113
|
+
).obj)
|
|
114
|
+
# hide label
|
|
115
|
+
lbl.Hide()
|
|
116
|
+
# start other categories off hidden
|
|
117
|
+
if toggle:
|
|
118
|
+
toggle.setValue(False)
|
|
119
|
+
# profile label
|
|
120
|
+
self.profileLbl = wx.StaticText(self, label="Device information")
|
|
121
|
+
self.sizer.Add(
|
|
122
|
+
self.profileLbl, border=6, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP
|
|
123
|
+
)
|
|
124
|
+
# profile ctrl
|
|
125
|
+
self.profileCtrl = wx.propgrid.PropertyGrid(self)
|
|
126
|
+
for key, val in device.profile.items():
|
|
127
|
+
prop = wx.propgrid.StringProperty(key, key, str(val))
|
|
128
|
+
self.profileCtrl.Append(prop)
|
|
129
|
+
prop.ChangeFlag(wx.propgrid.PG_PROP_READONLY, True)
|
|
130
|
+
self.profileCtrl.FitColumns()
|
|
131
|
+
self.profileCtrl.SetMinSize((-1, 128))
|
|
132
|
+
self.sizer.Add(
|
|
133
|
+
self.profileCtrl, border=6, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM
|
|
134
|
+
)
|
|
135
|
+
# delete button
|
|
136
|
+
self.deleteBtn = wx.Button(self, label="Remove device")
|
|
137
|
+
self.deleteBtn.SetMinSize((-1, 24))
|
|
138
|
+
self.deleteBtn.Bind(wx.EVT_BUTTON, self.onDelete)
|
|
139
|
+
self.sizer.Add(
|
|
140
|
+
self.deleteBtn, border=6, flag=wx.ALIGN_RIGHT | wx.ALL
|
|
141
|
+
)
|
|
142
|
+
# warnings panel
|
|
143
|
+
self.sizer.Add(
|
|
144
|
+
self.warnings.output, border=6, flag=wx.EXPAND | wx.ALL
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# populate from device
|
|
148
|
+
self.populate()
|
|
149
|
+
self.SetupScrolling()
|
|
150
|
+
|
|
151
|
+
def onDelete(self, evt=None):
|
|
152
|
+
# remove from devices
|
|
153
|
+
del self.dlg.devices[self.device.name]
|
|
154
|
+
# remove page
|
|
155
|
+
self.dlg.profilesNotebook.DeletePage(
|
|
156
|
+
self.dlg.profilesNotebook.FindPage(self)
|
|
157
|
+
)
|
|
158
|
+
del self.dlg.pages[self.device.name]
|
|
159
|
+
# repopulate without this page
|
|
160
|
+
self.dlg.populate()
|
|
161
|
+
|
|
162
|
+
def onParamEdit(self, evt=None):
|
|
163
|
+
# get calling ctrl and param
|
|
164
|
+
ctrl = evt.GetEventObject()
|
|
165
|
+
param = ctrl.param
|
|
166
|
+
# if renaming, pass it to the dialog so the control updates
|
|
167
|
+
if ctrl is self.nameCtrl:
|
|
168
|
+
self.dlg.renameDevice(
|
|
169
|
+
oldname=self.device.name,
|
|
170
|
+
newname=self.nameCtrl.getValue()
|
|
171
|
+
)
|
|
172
|
+
return
|
|
173
|
+
# set value from ctrl
|
|
174
|
+
param.val = ctrl.getValue()
|
|
175
|
+
# validate dlg
|
|
176
|
+
self.dlg.validate()
|
|
177
|
+
|
|
178
|
+
def onElementOk(self, evt=None):
|
|
179
|
+
for name, ctrl in self.paramCtrls.items():
|
|
180
|
+
# do ctrl's usual ok function
|
|
181
|
+
ctrl.onElementOk(evt)
|
|
182
|
+
# update param
|
|
183
|
+
self.device.params[name] = ctrl.param
|
|
184
|
+
self.device.params[name].val = ctrl.getValue()
|
|
185
|
+
|
|
186
|
+
def populate(self):
|
|
187
|
+
# update params
|
|
188
|
+
for name, ctrl in self.paramCtrls.items():
|
|
189
|
+
ctrl.setValue(self.device.params[name].val)
|
|
190
|
+
|
|
191
|
+
self.Layout()
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import wx
|
|
3
|
+
|
|
4
|
+
from psychopy.app.themes import icons
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DeviceImageList(wx.ImageList):
|
|
8
|
+
"""
|
|
9
|
+
Image list of device icons, allowing indices to be accessed by the device class
|
|
10
|
+
"""
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
width=16,
|
|
14
|
+
height=16,
|
|
15
|
+
mask=True,
|
|
16
|
+
initialCount=1
|
|
17
|
+
):
|
|
18
|
+
# initialise as normal
|
|
19
|
+
wx.ImageList.__init__(
|
|
20
|
+
self,
|
|
21
|
+
width=width,
|
|
22
|
+
height=height,
|
|
23
|
+
mask=mask,
|
|
24
|
+
initialCount=initialCount
|
|
25
|
+
)
|
|
26
|
+
# create index cache
|
|
27
|
+
self.indices = {}
|
|
28
|
+
|
|
29
|
+
def getIcon(self, device):
|
|
30
|
+
"""
|
|
31
|
+
Get the corresponding icon index of the icon for a given device based on its class.
|
|
32
|
+
|
|
33
|
+
Parameters
|
|
34
|
+
----------
|
|
35
|
+
device : psychopy.experiment.devices.DeviceBackend or type
|
|
36
|
+
Device object (or device class) to get the icon for
|
|
37
|
+
"""
|
|
38
|
+
# get device class
|
|
39
|
+
if not isinstance(device, type):
|
|
40
|
+
device = type(device)
|
|
41
|
+
# try to get from indices cache
|
|
42
|
+
if device in self.indices:
|
|
43
|
+
return self.indices[device]
|
|
44
|
+
# get icon file
|
|
45
|
+
file = device.getIconFile()
|
|
46
|
+
# load icon from file (if exists)
|
|
47
|
+
if file and Path(file).is_file():
|
|
48
|
+
bmp = icons.BaseIcon.resizeBitmap(
|
|
49
|
+
wx.Bitmap(str(device.getIconFile())),
|
|
50
|
+
size=self.GetSize()
|
|
51
|
+
)
|
|
52
|
+
i = self.Add(bmp)
|
|
53
|
+
# cache and return
|
|
54
|
+
self.indices[device] = i
|
|
55
|
+
|
|
56
|
+
return i
|
|
57
|
+
|
|
58
|
+
# all else fails, use blank
|
|
59
|
+
return -1
|
|
60
|
+
|
psychopy/app/idle.py
CHANGED
|
@@ -13,6 +13,7 @@ import wx
|
|
|
13
13
|
from psychopy import prefs, logging
|
|
14
14
|
from psychopy.constants import NOT_STARTED, STARTED, SKIP, FINISHED
|
|
15
15
|
from . import connections
|
|
16
|
+
from psychopy.app.plugin_manager.packageIndex import refreshPackageIndexTask
|
|
16
17
|
from psychopy.tools import versionchooser as vc
|
|
17
18
|
from ..app import pavlovia_ui
|
|
18
19
|
_t0 = time.time()
|
|
@@ -78,6 +79,12 @@ tasks['getPavloviaUser'] = {
|
|
|
78
79
|
'tstart': None, 'tEnd': None,
|
|
79
80
|
'thread': False,
|
|
80
81
|
}
|
|
82
|
+
tasks['refreshPackageIndex'] = {
|
|
83
|
+
'status': NOT_STARTED,
|
|
84
|
+
'func': refreshPackageIndexTask,
|
|
85
|
+
'tstart': None, 'tEnd': None,
|
|
86
|
+
'thread': True,
|
|
87
|
+
}
|
|
81
88
|
|
|
82
89
|
currentTask = None
|
|
83
90
|
|
|
Binary file
|