boris-behav-obs 8.25.4__tar.gz → 8.26.1__tar.gz
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.
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/PKG-INFO +3 -3
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/add_modifier.py +48 -18
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/add_modifier_ui.py +9 -5
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/advanced_event_filtering.py +2 -2
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/behav_coding_map_creator.py +1 -1
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/behaviors_coding_map.py +1 -1
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/config.py +7 -23
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/config_file.py +0 -2
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/core.py +7 -6
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/dialog.py +2 -2
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/geometric_measurement.py +1 -1
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/measurement_widget.py +1 -1
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/observation.py +1 -1
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/otx_parser.py +1 -1
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/preferences.py +0 -2
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/project.py +29 -14
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/select_modifiers.py +32 -8
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/time_budget_widget.py +1 -1
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/utilities.py +14 -3
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/version.py +2 -2
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/write_event.py +178 -75
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris_behav_obs.egg-info/PKG-INFO +3 -3
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris_behav_obs.egg-info/SOURCES.txt +0 -12
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris_behav_obs.egg-info/requires.txt +2 -2
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/pyproject.toml +4 -4
- boris_behav_obs-8.25.4/boris/LICENSE.TXT +0 -674
- boris_behav_obs-8.25.4/boris/README.TXT +0 -22
- boris_behav_obs-8.25.4/boris/add_modifier.ui +0 -323
- boris_behav_obs-8.25.4/boris/converters.ui +0 -289
- boris_behav_obs-8.25.4/boris/core.qrc +0 -67
- boris_behav_obs-8.25.4/boris/core.ui +0 -1585
- boris_behav_obs-8.25.4/boris/edit_event.ui +0 -240
- boris_behav_obs-8.25.4/boris/icons/logo_eye.ico +0 -0
- boris_behav_obs-8.25.4/boris/observation.ui +0 -848
- boris_behav_obs-8.25.4/boris/param_panel.ui +0 -379
- boris_behav_obs-8.25.4/boris/preferences.ui +0 -588
- boris_behav_obs-8.25.4/boris/project.ui +0 -1074
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/LICENSE.TXT +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/MANIFEST.in +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/README.TXT +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/README.rst +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/__init__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/__main__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/about.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/behavior_binary_table.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/boris_cli.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/cmd_arguments.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/coding_pad.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/connections.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/converters.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/converters_ui.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/cooccurence.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/core_qrc.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/core_ui.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/db_functions.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/dev.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/duration_widget.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/edit_event.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/edit_event_ui.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/event_operations.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/events_cursor.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/events_snapshots.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/exclusion_matrix.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/export_events.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/export_observation.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/external_processes.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/gui_utilities.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/image_overlay.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/import_observations.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/irr.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/latency.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/map_creator.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/media_file.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/menu_options.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/modifiers_coding_map.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/mpv.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/mpv2.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/observation_operations.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/observation_ui.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/observations_list.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/param_panel.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/param_panel_ui.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/player_dock_widget.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/plot_data_module.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/plot_events.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/plot_events_rt.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/plot_spectrogram_rt.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/plot_waveform_rt.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/portion/__init__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/portion/const.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/portion/dict.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/portion/func.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/portion/interval.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/portion/io.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/preferences_ui.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/project_functions.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/project_import_export.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/project_ui.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/__init__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/__main__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/colorsystem.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/dark/__init__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/dark/darkstyle_rc.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/dark/palette.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/example/__init__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/example/__main__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/example/ui/__init__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/light/__init__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/light/lightstyle_rc.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/light/palette.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/palette.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/utils/__init__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/utils/__main__.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/utils/images.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qdarkstyle/utils/scss.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qrc_boris.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/qrc_boris5.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/select_observations.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/select_subj_behav.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/state_events.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/subjects_pad.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/synthetic_time_budget.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/time_budget_functions.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/transitions.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/video_equalizer.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/video_equalizer_ui.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/video_operations.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris/vlc_local.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris_behav_obs.egg-info/dependency_links.txt +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris_behav_obs.egg-info/entry_points.txt +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/boris_behav_obs.egg-info/top_level.txt +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/setup.cfg +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/tests/test_db_functions.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/tests/test_export_observation.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/tests/test_irr.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/tests/test_observation_gui.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/tests/test_otx_parser.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/tests/test_preferences_gui.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/tests/test_project_functions.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/tests/test_time_budget.py +0 -0
- {boris_behav_obs-8.25.4 → boris_behav_obs-8.26.1}/tests/test_utilities.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: boris-behav-obs
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.26.1
|
|
4
4
|
Summary: BORIS - Behavioral Observation Research Interactive Software
|
|
5
5
|
Author-email: Olivier Friard <olivier.friard@unito.it>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -697,9 +697,9 @@ Requires-Python: >=3.8
|
|
|
697
697
|
Description-Content-Type: text/x-rst
|
|
698
698
|
License-File: LICENSE.TXT
|
|
699
699
|
Requires-Dist: exifread>=3.0.0
|
|
700
|
-
Requires-Dist: numpy>=1.
|
|
700
|
+
Requires-Dist: numpy>=1.26.4
|
|
701
701
|
Requires-Dist: matplotlib>=3.3.3
|
|
702
|
-
Requires-Dist: pandas>=
|
|
702
|
+
Requires-Dist: pandas>=2.2.2
|
|
703
703
|
Requires-Dist: tablib[cli,html,ods,pandas,xls,xlsx]>=3
|
|
704
704
|
Requires-Dist: pyqt5>=5.15
|
|
705
705
|
Requires-Dist: pyreadr
|
|
@@ -36,7 +36,7 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
36
36
|
tabMem = -1
|
|
37
37
|
itemPositionMem = -1
|
|
38
38
|
|
|
39
|
-
def __init__(self, modifiers_str, subjects=[], parent=None):
|
|
39
|
+
def __init__(self, modifiers_str: str, subjects: list = [], ask_at_stop_enabled: bool = False, parent=None):
|
|
40
40
|
super().__init__()
|
|
41
41
|
self.setupUi(self)
|
|
42
42
|
|
|
@@ -44,10 +44,12 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
44
44
|
if not self.subjects:
|
|
45
45
|
self.pb_add_subjects.setEnabled(False)
|
|
46
46
|
|
|
47
|
+
self.ask_at_stop_enabled = ask_at_stop_enabled
|
|
48
|
+
|
|
47
49
|
self.pbAddModifier.clicked.connect(self.addModifier)
|
|
48
50
|
self.pbAddModifier.setIcon(QIcon(":/frame_forward"))
|
|
49
|
-
self.pbAddSet.clicked.connect(self.
|
|
50
|
-
self.pbRemoveSet.clicked.connect(self.
|
|
51
|
+
self.pbAddSet.clicked.connect(self.add_set_of_modifiers)
|
|
52
|
+
self.pbRemoveSet.clicked.connect(self.remove_set_of_modifiers)
|
|
51
53
|
self.pbModifyModifier.clicked.connect(self.modifyModifier)
|
|
52
54
|
self.pbModifyModifier.setIcon(QIcon(":/frame_backward"))
|
|
53
55
|
|
|
@@ -60,22 +62,27 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
60
62
|
self.pb_add_subjects.clicked.connect(self.add_subjects)
|
|
61
63
|
self.pb_load_file.clicked.connect(self.add_modifiers_from_file)
|
|
62
64
|
|
|
63
|
-
self.pbOK.clicked.connect(lambda: self.pb_pushed(
|
|
64
|
-
self.pbCancel.clicked.connect(lambda: self.pb_pushed(
|
|
65
|
+
self.pbOK.clicked.connect(lambda: self.pb_pushed(cfg.OK))
|
|
66
|
+
self.pbCancel.clicked.connect(lambda: self.pb_pushed(cfg.CANCEL))
|
|
65
67
|
|
|
66
68
|
self.le_name.textChanged.connect(self.set_name_changed)
|
|
67
69
|
self.le_description.textChanged.connect(self.set_description_changed)
|
|
68
70
|
|
|
69
71
|
self.cbType.currentIndexChanged.connect(self.type_changed)
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
# self.cb_ask_at_stop.clicked.connect(self.ask_at_stop_changed)
|
|
74
|
+
|
|
75
|
+
dummy_dict: dict = json.loads(modifiers_str) if modifiers_str else {}
|
|
76
|
+
modif_values: list = []
|
|
73
77
|
for idx in sorted_keys(dummy_dict):
|
|
74
78
|
modif_values.append(dummy_dict[idx])
|
|
75
79
|
|
|
76
|
-
self.modifiers_sets_dict = {}
|
|
80
|
+
self.modifiers_sets_dict: dict = {}
|
|
77
81
|
for modif in modif_values:
|
|
78
82
|
self.modifiers_sets_dict[str(len(self.modifiers_sets_dict))] = dict(modif)
|
|
83
|
+
if self.ask_at_stop_enabled:
|
|
84
|
+
if dict(modif).get("ask at stop", False):
|
|
85
|
+
self.cb_ask_at_stop.setChecked(True)
|
|
79
86
|
|
|
80
87
|
self.tabWidgetModifiersSets.currentChanged.connect(self.tabWidgetModifiersSets_changed)
|
|
81
88
|
|
|
@@ -102,6 +109,7 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
102
109
|
self.pb_add_subjects,
|
|
103
110
|
self.pb_load_file,
|
|
104
111
|
self.pb_sort_modifiers,
|
|
112
|
+
self.cb_ask_at_stop,
|
|
105
113
|
):
|
|
106
114
|
w.setVisible(False)
|
|
107
115
|
for w in (self.leModifier, self.leCode, self.pbAddModifier, self.pbModifyModifier):
|
|
@@ -120,14 +128,14 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
120
128
|
"If you close the window it will be lost.<br>"
|
|
121
129
|
"Do you want to change modifiers set"
|
|
122
130
|
),
|
|
123
|
-
[
|
|
131
|
+
[cfg.CLOSE, cfg.CANCEL],
|
|
124
132
|
)
|
|
125
133
|
== cfg.CANCEL
|
|
126
134
|
):
|
|
127
135
|
return
|
|
128
|
-
if button ==
|
|
136
|
+
if button == cfg.OK:
|
|
129
137
|
self.accept()
|
|
130
|
-
if button ==
|
|
138
|
+
if button == cfg.CANCEL:
|
|
131
139
|
self.reject()
|
|
132
140
|
|
|
133
141
|
def add_subjects(self):
|
|
@@ -247,6 +255,12 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
247
255
|
else:
|
|
248
256
|
self.lb_name.setText("Set name")
|
|
249
257
|
|
|
258
|
+
# def ask_at_stop_changed(self):
|
|
259
|
+
# """
|
|
260
|
+
# value changed
|
|
261
|
+
# """
|
|
262
|
+
# self.modifiers_sets_dict[str(self.tabWidgetModifiersSets.currentIndex())]["ask at stop"] = self.cb_ask_at_stop.isChecked()
|
|
263
|
+
|
|
250
264
|
def moveSetLeft(self):
|
|
251
265
|
"""
|
|
252
266
|
move selected modifiers set left
|
|
@@ -304,7 +318,7 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
304
318
|
self.lwModifiers.item(x).text() for x in range(self.lwModifiers.count())
|
|
305
319
|
]
|
|
306
320
|
|
|
307
|
-
def
|
|
321
|
+
def add_set_of_modifiers(self):
|
|
308
322
|
"""
|
|
309
323
|
Add a set of modifiers
|
|
310
324
|
"""
|
|
@@ -315,6 +329,7 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
315
329
|
"name": "",
|
|
316
330
|
"description": "",
|
|
317
331
|
"type": cfg.SINGLE_SELECTION,
|
|
332
|
+
"ask at stop": False,
|
|
318
333
|
"values": [],
|
|
319
334
|
}
|
|
320
335
|
self.tabWidgetModifiersSets.addTab(QWidget(), f"Set #{len(self.modifiers_sets_dict)}")
|
|
@@ -342,6 +357,8 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
342
357
|
self.pb_sort_modifiers,
|
|
343
358
|
):
|
|
344
359
|
w.setVisible(True)
|
|
360
|
+
self.cb_ask_at_stop.setVisible(self.ask_at_stop_enabled)
|
|
361
|
+
|
|
345
362
|
for w in (self.leModifier, self.leCode, self.pbAddModifier, self.pbModifyModifier):
|
|
346
363
|
w.setEnabled(True)
|
|
347
364
|
return
|
|
@@ -351,6 +368,7 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
351
368
|
"name": "",
|
|
352
369
|
"description": "",
|
|
353
370
|
"type": cfg.SINGLE_SELECTION,
|
|
371
|
+
"ask at stop": False,
|
|
354
372
|
"values": [],
|
|
355
373
|
}
|
|
356
374
|
self.tabWidgetModifiersSets.addTab(QWidget(), f"Set #{len(self.modifiers_sets_dict)}")
|
|
@@ -364,7 +382,7 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
364
382
|
"It is not possible to add a modifiers' set while the current modifiers' set is empty.",
|
|
365
383
|
)
|
|
366
384
|
|
|
367
|
-
def
|
|
385
|
+
def remove_set_of_modifiers(self):
|
|
368
386
|
"""
|
|
369
387
|
remove set of modifiers
|
|
370
388
|
"""
|
|
@@ -403,14 +421,15 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
403
421
|
self.pbRemoveSet,
|
|
404
422
|
self.pbMoveSetLeft,
|
|
405
423
|
self.pbMoveSetRight,
|
|
424
|
+
self.cb_ask_at_stop,
|
|
406
425
|
):
|
|
407
426
|
w.setVisible(False)
|
|
408
|
-
for w in
|
|
427
|
+
for w in (self.leModifier, self.leCode, self.pbAddModifier, self.pbModifyModifier):
|
|
409
428
|
w.setEnabled(False)
|
|
410
429
|
|
|
411
430
|
if not len(self.modifiers_sets_dict):
|
|
412
431
|
# set invisible and unavailable buttons and others elements
|
|
413
|
-
for w in
|
|
432
|
+
for w in (
|
|
414
433
|
self.lb_name,
|
|
415
434
|
self.le_name,
|
|
416
435
|
self.lbType,
|
|
@@ -428,7 +447,7 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
428
447
|
self.pb_add_subjects,
|
|
429
448
|
self.pb_load_file,
|
|
430
449
|
self.pb_sort_modifiers,
|
|
431
|
-
|
|
450
|
+
):
|
|
432
451
|
w.setVisible(False)
|
|
433
452
|
for w in [self.leModifier, self.leCode, self.pbAddModifier, self.pbModifyModifier]:
|
|
434
453
|
w.setEnabled(False)
|
|
@@ -500,6 +519,7 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
500
519
|
"name": "",
|
|
501
520
|
"description": "",
|
|
502
521
|
"type": cfg.SINGLE_SELECTION,
|
|
522
|
+
"ask at stop": False,
|
|
503
523
|
"values": [],
|
|
504
524
|
}
|
|
505
525
|
|
|
@@ -530,6 +550,7 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
530
550
|
"name": "",
|
|
531
551
|
"description": "",
|
|
532
552
|
"type": cfg.SINGLE_SELECTION,
|
|
553
|
+
"ask at stop": False,
|
|
533
554
|
"values": [],
|
|
534
555
|
}
|
|
535
556
|
|
|
@@ -582,6 +603,8 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
582
603
|
self.lwModifiers.clear()
|
|
583
604
|
self.leCode.clear()
|
|
584
605
|
self.leModifier.clear()
|
|
606
|
+
# if self.ask_at_stop_enabled:
|
|
607
|
+
# self.cb_ask_at_stop.setChecked(False)
|
|
585
608
|
|
|
586
609
|
self.tabMem = tabIndex
|
|
587
610
|
|
|
@@ -589,14 +612,21 @@ class addModifierDialog(QDialog, Ui_Dialog):
|
|
|
589
612
|
self.le_name.setText(self.modifiers_sets_dict[str(tabIndex)]["name"])
|
|
590
613
|
self.le_description.setText(self.modifiers_sets_dict[str(tabIndex)].get("description", ""))
|
|
591
614
|
self.cbType.setCurrentIndex(self.modifiers_sets_dict[str(tabIndex)]["type"])
|
|
615
|
+
# if self.ask_at_stop_enabled:
|
|
616
|
+
# self.cb_ask_at_stop.setChecked(self.modifiers_sets_dict[str(tabIndex)].get("ask at stop", False))
|
|
617
|
+
|
|
592
618
|
self.lwModifiers.addItems(self.modifiers_sets_dict[str(tabIndex)]["values"])
|
|
593
619
|
|
|
594
|
-
def
|
|
620
|
+
def get_modifiers(self) -> str:
|
|
595
621
|
"""
|
|
596
622
|
returns modifiers as string
|
|
597
623
|
"""
|
|
598
|
-
keys_to_delete = []
|
|
624
|
+
keys_to_delete: list = []
|
|
599
625
|
for idx in self.modifiers_sets_dict:
|
|
626
|
+
# add ask_at_stop value (boolean) to each set of modifiers
|
|
627
|
+
if self.ask_at_stop_enabled:
|
|
628
|
+
self.modifiers_sets_dict[idx]["ask at stop"] = self.cb_ask_at_stop.isChecked()
|
|
629
|
+
# delete modifiers without values for selection
|
|
600
630
|
if (
|
|
601
631
|
self.modifiers_sets_dict[idx]["type"] in (cfg.SINGLE_SELECTION, cfg.MULTI_SELECTION)
|
|
602
632
|
and not self.modifiers_sets_dict[idx]["values"]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
|
|
3
|
-
# Form implementation generated from reading ui file 'add_modifier.ui'
|
|
3
|
+
# Form implementation generated from reading ui file 'boris/add_modifier.ui'
|
|
4
4
|
#
|
|
5
|
-
# Created by: PyQt5 UI code generator 5.15.
|
|
5
|
+
# Created by: PyQt5 UI code generator 5.15.6
|
|
6
6
|
#
|
|
7
7
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
|
8
8
|
# run again. Do not edit this file unless you know what you are doing.
|
|
@@ -14,9 +14,12 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|
|
14
14
|
class Ui_Dialog(object):
|
|
15
15
|
def setupUi(self, Dialog):
|
|
16
16
|
Dialog.setObjectName("Dialog")
|
|
17
|
-
Dialog.resize(
|
|
17
|
+
Dialog.resize(1088, 654)
|
|
18
18
|
self.verticalLayout_5 = QtWidgets.QVBoxLayout(Dialog)
|
|
19
19
|
self.verticalLayout_5.setObjectName("verticalLayout_5")
|
|
20
|
+
self.cb_ask_at_stop = QtWidgets.QCheckBox(Dialog)
|
|
21
|
+
self.cb_ask_at_stop.setObjectName("cb_ask_at_stop")
|
|
22
|
+
self.verticalLayout_5.addWidget(self.cb_ask_at_stop)
|
|
20
23
|
self.verticalLayout_4 = QtWidgets.QVBoxLayout()
|
|
21
24
|
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
|
22
25
|
self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
|
|
@@ -101,10 +104,10 @@ class Ui_Dialog(object):
|
|
|
101
104
|
self.pbMoveDown = QtWidgets.QPushButton(Dialog)
|
|
102
105
|
self.pbMoveDown.setObjectName("pbMoveDown")
|
|
103
106
|
self.horizontalLayout.addWidget(self.pbMoveDown)
|
|
104
|
-
self.verticalLayout.addLayout(self.horizontalLayout)
|
|
105
107
|
self.pbRemoveModifier = QtWidgets.QPushButton(Dialog)
|
|
106
108
|
self.pbRemoveModifier.setObjectName("pbRemoveModifier")
|
|
107
|
-
self.
|
|
109
|
+
self.horizontalLayout.addWidget(self.pbRemoveModifier)
|
|
110
|
+
self.verticalLayout.addLayout(self.horizontalLayout)
|
|
108
111
|
self.pb_sort_modifiers = QtWidgets.QPushButton(Dialog)
|
|
109
112
|
self.pb_sort_modifiers.setObjectName("pb_sort_modifiers")
|
|
110
113
|
self.verticalLayout.addWidget(self.pb_sort_modifiers)
|
|
@@ -156,6 +159,7 @@ class Ui_Dialog(object):
|
|
|
156
159
|
def retranslateUi(self, Dialog):
|
|
157
160
|
_translate = QtCore.QCoreApplication.translate
|
|
158
161
|
Dialog.setWindowTitle(_translate("Dialog", "Set modifiers"))
|
|
162
|
+
self.cb_ask_at_stop.setText(_translate("Dialog", "Ask for modifier(s) when behavior stops"))
|
|
159
163
|
self.lbModifier.setText(_translate("Dialog", "Modifier"))
|
|
160
164
|
self.lbCode.setText(_translate("Dialog", "Key code"))
|
|
161
165
|
self.lbCodeHelp.setText(_translate("Dialog", "Key code is case sensitive. Type one character or a function key (F1, F2... F12)"))
|
|
@@ -155,7 +155,7 @@ class Advanced_event_filtering_dialog(QDialog):
|
|
|
155
155
|
hbox.addItem(QSpacerItem(241, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
|
|
156
156
|
self.pb_save = QPushButton("Save results", clicked=self.save_results)
|
|
157
157
|
hbox.addWidget(self.pb_save)
|
|
158
|
-
self.pb_close = QPushButton(
|
|
158
|
+
self.pb_close = QPushButton(cfg.CLOSE, clicked=self.close)
|
|
159
159
|
hbox.addWidget(self.pb_close)
|
|
160
160
|
vbox.addLayout(hbox)
|
|
161
161
|
|
|
@@ -429,7 +429,7 @@ def event_filtering(self):
|
|
|
429
429
|
for row in cursor.fetchall():
|
|
430
430
|
obs, subj, behav, start, stop = row
|
|
431
431
|
if obs not in events:
|
|
432
|
-
events[obs]
|
|
432
|
+
events[obs] = {}
|
|
433
433
|
|
|
434
434
|
# use function in base at event (state or point)
|
|
435
435
|
interval_func = icc if start == stop else ico
|
|
@@ -138,7 +138,7 @@ class BehaviorsMapCreatorWindow(QMainWindow):
|
|
|
138
138
|
self.addToProject.triggered.connect(self.add_to_project)
|
|
139
139
|
|
|
140
140
|
self.exitAction = QAction(QIcon(), "&Close", self)
|
|
141
|
-
self.exitAction.setStatusTip(
|
|
141
|
+
self.exitAction.setStatusTip(cfg.CLOSE)
|
|
142
142
|
self.exitAction.triggered.connect(self.close)
|
|
143
143
|
|
|
144
144
|
menubar = self.menuBar()
|
|
@@ -102,7 +102,7 @@ class BehaviorsCodingMapWindowClass(QWidget):
|
|
|
102
102
|
self.leareaCode = QLineEdit(self)
|
|
103
103
|
hBoxLayout1.addWidget(self.leareaCode)
|
|
104
104
|
|
|
105
|
-
self.btClose = QPushButton(
|
|
105
|
+
self.btClose = QPushButton(cfg.CLOSE)
|
|
106
106
|
self.btClose.clicked.connect(self.close)
|
|
107
107
|
hBoxLayout1.addWidget(self.btClose)
|
|
108
108
|
|
|
@@ -82,6 +82,7 @@ EVENTS = "events"
|
|
|
82
82
|
TIME_OFFSET = "time offset"
|
|
83
83
|
|
|
84
84
|
CODING_MAP = "coding_map"
|
|
85
|
+
CODING_MAP_sp = "coding map" # space between words (no underscore)
|
|
85
86
|
BEHAVIORS_CODING_MAP = "behaviors_coding_map"
|
|
86
87
|
SUBJECTS = "subjects_conf"
|
|
87
88
|
ETHOGRAM = "behaviors_conf"
|
|
@@ -139,6 +140,7 @@ YES = "Yes"
|
|
|
139
140
|
NO = "No"
|
|
140
141
|
CANCEL = "Cancel"
|
|
141
142
|
APPEND = "Append"
|
|
143
|
+
CLOSE = "Close"
|
|
142
144
|
REPLACE = "Replace"
|
|
143
145
|
REMOVE = "Remove"
|
|
144
146
|
SAVE = "Save"
|
|
@@ -210,17 +212,6 @@ TIME_LAPSE = "time_lapse_delay"
|
|
|
210
212
|
|
|
211
213
|
|
|
212
214
|
# fields for event configuration
|
|
213
|
-
"""
|
|
214
|
-
fields = {
|
|
215
|
-
"type": 0,
|
|
216
|
-
"key": 1,
|
|
217
|
-
"code": 2,
|
|
218
|
-
"description": 3,
|
|
219
|
-
"modifiers": 4,
|
|
220
|
-
"excluded": 5,
|
|
221
|
-
"coding map": 6,
|
|
222
|
-
}
|
|
223
|
-
"""
|
|
224
215
|
|
|
225
216
|
ETHOGRAM_TABLE_COLUMNS: dict = {
|
|
226
217
|
0: "key",
|
|
@@ -245,18 +236,6 @@ behavioursFields: dict = {
|
|
|
245
236
|
"excluded": 7,
|
|
246
237
|
"coding map": 8,
|
|
247
238
|
}
|
|
248
|
-
"""
|
|
249
|
-
ETHOGRAM_FIELDS = [
|
|
250
|
-
"type",
|
|
251
|
-
"key",
|
|
252
|
-
"code",
|
|
253
|
-
"description",
|
|
254
|
-
"category",
|
|
255
|
-
"modifiers",
|
|
256
|
-
"excluded",
|
|
257
|
-
"coding map",
|
|
258
|
-
]
|
|
259
|
-
"""
|
|
260
239
|
ETHOGRAM_EDITABLE_FIELDS: tuple = ("key", "code", "description")
|
|
261
240
|
|
|
262
241
|
PROJECT_BEHAVIORS_KEY_FIELD_IDX = 1
|
|
@@ -471,6 +450,9 @@ WAVEFORM_PLOT = "waveform"
|
|
|
471
450
|
SPECTROGRAM_PLOT = "spectrogram"
|
|
472
451
|
EVENTS_PLOT = "plot_events"
|
|
473
452
|
|
|
453
|
+
PLAYING = "playing"
|
|
454
|
+
PAUSED = "paused"
|
|
455
|
+
STOPPED = "stopped"
|
|
474
456
|
|
|
475
457
|
POINT_EVENT_ST_DURATION = 0.5
|
|
476
458
|
|
|
@@ -481,6 +463,8 @@ SLIDER_MAXIMUM = 1000
|
|
|
481
463
|
|
|
482
464
|
FRAME_DEFAULT_CACHE_SIZE = 1
|
|
483
465
|
|
|
466
|
+
EXCLUDED = "excluded"
|
|
467
|
+
|
|
484
468
|
# modifiers
|
|
485
469
|
MODIFIERS = "modifiers"
|
|
486
470
|
SINGLE_SELECTION = 0
|
|
@@ -316,8 +316,6 @@ def save(self, lastCheckForNewVersion=0):
|
|
|
316
316
|
|
|
317
317
|
settings = QSettings(str(file_path), QSettings.IniFormat)
|
|
318
318
|
|
|
319
|
-
print(f"{self.config_param=}")
|
|
320
|
-
|
|
321
319
|
settings.setValue("config", self.config_param)
|
|
322
320
|
|
|
323
321
|
settings.setValue("geometry", self.saveGeometry())
|
|
@@ -20,7 +20,6 @@ This file is part of BORIS.
|
|
|
20
20
|
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
|
|
24
23
|
import os
|
|
25
24
|
import sys
|
|
26
25
|
|
|
@@ -1365,13 +1364,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
1365
1364
|
|
|
1366
1365
|
try:
|
|
1367
1366
|
versionURL = "https://www.boris.unito.it/static/ver4.dat"
|
|
1368
|
-
|
|
1369
|
-
if util.versiontuple(
|
|
1367
|
+
last_version = urllib.request.urlopen(versionURL).read().strip().decode("utf-8")
|
|
1368
|
+
if util.versiontuple(last_version) > util.versiontuple(__version__):
|
|
1370
1369
|
msg = (
|
|
1371
|
-
f"A new version is available: v. <b>{
|
|
1370
|
+
f"A new version is available: v. <b>{last_version}</b><br>"
|
|
1372
1371
|
'Go to <a href="https://www.boris.unito.it">'
|
|
1373
1372
|
"https://www.boris.unito.it</a> to install it."
|
|
1374
1373
|
)
|
|
1374
|
+
# https://github.com/olivierfriard/BORIS/archive/refs/tags/v{last_version}.zip
|
|
1375
1375
|
else:
|
|
1376
1376
|
msg = f"The version you are using is the last one: <b>{__version__}</b>"
|
|
1377
1377
|
newsURL = "https://www.boris.unito.it/static/news.dat"
|
|
@@ -3611,6 +3611,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3611
3611
|
if dialog.MessageDialog(cfg.programName, "Delete the current events?", (cfg.YES, cfg.NO)) == cfg.YES:
|
|
3612
3612
|
self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS] = []
|
|
3613
3613
|
self.project_changed()
|
|
3614
|
+
self.load_tw_events(self.observationId)
|
|
3614
3615
|
|
|
3615
3616
|
self.pb_live_obs.setText("Stop live observation")
|
|
3616
3617
|
|
|
@@ -4651,9 +4652,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
4651
4652
|
|
|
4652
4653
|
event = dict(self.pj[cfg.ETHOGRAM][behavior_idx])
|
|
4653
4654
|
# check if coding map for modifiers
|
|
4654
|
-
if
|
|
4655
|
+
if util.has_coding_map(self.pj[cfg.ETHOGRAM], behavior_idx):
|
|
4655
4656
|
# pause if media and media playing
|
|
4656
|
-
if self.pj[cfg.OBSERVATIONS][self.observationId][cfg.TYPE]
|
|
4657
|
+
if self.pj[cfg.OBSERVATIONS][self.observationId][cfg.TYPE] == cfg.MEDIA:
|
|
4657
4658
|
if self.playerType == cfg.MEDIA:
|
|
4658
4659
|
if self.is_playing():
|
|
4659
4660
|
flag_player_playing = True
|
|
@@ -1027,8 +1027,8 @@ class FindInEvents(QWidget):
|
|
|
1027
1027
|
hbox2 = QHBoxLayout()
|
|
1028
1028
|
self.pbOK = QPushButton("Find")
|
|
1029
1029
|
self.pbOK.clicked.connect(lambda: self.click("FIND"))
|
|
1030
|
-
self.pbCancel = QPushButton(
|
|
1031
|
-
self.pbCancel.clicked.connect(lambda: self.click(
|
|
1030
|
+
self.pbCancel = QPushButton(cfg.CLOSE)
|
|
1031
|
+
self.pbCancel.clicked.connect(lambda: self.click(cfg.CLOSE))
|
|
1032
1032
|
hbox2.addWidget(self.pbCancel)
|
|
1033
1033
|
hbox2.addWidget(self.pbOK)
|
|
1034
1034
|
hbox.addLayout(hbox2)
|
|
@@ -182,7 +182,7 @@ class wgMeasurement(QDialog):
|
|
|
182
182
|
|
|
183
183
|
self.pb_save = QPushButton("Save results", clicked=self.pb_save_clicked)
|
|
184
184
|
hbox3.addWidget(self.pb_save)
|
|
185
|
-
self.pb_close = QPushButton(
|
|
185
|
+
self.pb_close = QPushButton(cfg.CLOSE, clicked=self.pbClose_clicked)
|
|
186
186
|
hbox3.addWidget(self.pb_close)
|
|
187
187
|
vbox.addLayout(hbox3)
|
|
188
188
|
|
|
@@ -111,7 +111,7 @@ class wgMeasurement(QWidget):
|
|
|
111
111
|
self.pbSave = QPushButton("Save results", clicked=self.pbSave_clicked)
|
|
112
112
|
hbox3.addWidget(self.pbSave)
|
|
113
113
|
|
|
114
|
-
self.pbClose = QPushButton(
|
|
114
|
+
self.pbClose = QPushButton(cfg.CLOSE, clicked=self.pbClose_clicked)
|
|
115
115
|
hbox3.addWidget(self.pbClose)
|
|
116
116
|
|
|
117
117
|
vbox.addLayout(hbox3)
|
|
@@ -706,7 +706,7 @@ class Observation(QDialog, Ui_Form):
|
|
|
706
706
|
w = dialog.View_data()
|
|
707
707
|
w.setWindowTitle("View data")
|
|
708
708
|
w.lb.setText(f"View first and last rows of <b>{pl.Path(data_file_path).name}</b> file")
|
|
709
|
-
w.pbOK.setText(
|
|
709
|
+
w.pbOK.setText(cfg.CLOSE)
|
|
710
710
|
w.label.setText("Index of columns to plot")
|
|
711
711
|
w.le.setEnabled(False)
|
|
712
712
|
w.le.setText(columns_to_plot)
|
|
@@ -204,8 +204,6 @@ def preferences(self):
|
|
|
204
204
|
preferencesWindow.sb_toolbar_icon_size.setValue(self.config_param.get(cfg.TOOLBAR_ICON_SIZE, cfg.DEFAULT_TOOLBAR_ICON_SIZE_VALUE))
|
|
205
205
|
preferencesWindow.cb_darkmode.setChecked(self.config_param.get(cfg.DARK_MODE, cfg.DARK_MODE_DEFAULT_VALUE))
|
|
206
206
|
|
|
207
|
-
self.config_param[cfg.DARK_MODE] = preferencesWindow.cb_darkmode.isChecked()
|
|
208
|
-
|
|
209
207
|
gui_utilities.restore_geometry(preferencesWindow, "preferences", (700, 500))
|
|
210
208
|
|
|
211
209
|
if preferencesWindow.exec_():
|
|
@@ -760,7 +760,7 @@ class projectDialog(QDialog, Ui_dlgProject):
|
|
|
760
760
|
# check if double click on 'coding map' column
|
|
761
761
|
if column == cfg.behavioursFields["coding map"]:
|
|
762
762
|
if "with coding map" in self.twBehaviors.item(row, cfg.behavioursFields[cfg.TYPE]).text():
|
|
763
|
-
self.
|
|
763
|
+
self.behavior_type_changed(row)
|
|
764
764
|
else:
|
|
765
765
|
QMessageBox.information(self, cfg.programName, "Change the behavior type on first column to select a coding map")
|
|
766
766
|
|
|
@@ -790,10 +790,15 @@ class projectDialog(QDialog, Ui_dlgProject):
|
|
|
790
790
|
subjectName = self.twSubjects.item(subject_row, 1).text().strip() if self.twSubjects.item(subject_row, 1) else ""
|
|
791
791
|
subjects_list.append((subjectName, key))
|
|
792
792
|
|
|
793
|
-
addModifierWindow = add_modifier.addModifierDialog(
|
|
793
|
+
addModifierWindow = add_modifier.addModifierDialog(
|
|
794
|
+
self.twBehaviors.item(row, column).text(),
|
|
795
|
+
subjects=subjects_list,
|
|
796
|
+
ask_at_stop_enabled=self.twBehaviors.item(row, cfg.behavioursFields["type"]).text() == cfg.STATE_EVENT,
|
|
797
|
+
)
|
|
794
798
|
addModifierWindow.setWindowTitle(f'Set modifiers for "{self.twBehaviors.item(row, 2).text()}" behavior')
|
|
799
|
+
|
|
795
800
|
if addModifierWindow.exec_():
|
|
796
|
-
self.twBehaviors.item(row, column).setText(addModifierWindow.
|
|
801
|
+
self.twBehaviors.item(row, column).setText(addModifierWindow.get_modifiers())
|
|
797
802
|
|
|
798
803
|
def behavior_type_doubleclicked(self, row):
|
|
799
804
|
"""
|
|
@@ -810,7 +815,7 @@ class projectDialog(QDialog, Ui_dlgProject):
|
|
|
810
815
|
if ok and new_type:
|
|
811
816
|
self.twBehaviors.item(row, cfg.behavioursFields["type"]).setText(new_type)
|
|
812
817
|
|
|
813
|
-
self.
|
|
818
|
+
self.behavior_type_changed(row)
|
|
814
819
|
|
|
815
820
|
def color_doubleclicked(self, row: int) -> None:
|
|
816
821
|
"""
|
|
@@ -1325,16 +1330,16 @@ class projectDialog(QDialog, Ui_dlgProject):
|
|
|
1325
1330
|
self.twBehaviors.setItem(self.twBehaviors.rowCount() - 1, cfg.behavioursFields[field_type], item)
|
|
1326
1331
|
self.twBehaviors.scrollToBottom()
|
|
1327
1332
|
|
|
1328
|
-
def
|
|
1333
|
+
def behavior_type_changed(self, row: int) -> None:
|
|
1329
1334
|
"""
|
|
1330
1335
|
event type combobox changed
|
|
1331
1336
|
"""
|
|
1332
1337
|
|
|
1333
|
-
if
|
|
1338
|
+
if cfg.CODING_MAP_sp in self.twBehaviors.item(row, cfg.behavioursFields[cfg.TYPE]).text():
|
|
1334
1339
|
# let user select a coding maop
|
|
1335
1340
|
fn = QFileDialog().getOpenFileName(
|
|
1336
1341
|
self,
|
|
1337
|
-
"Select a coding map for " f"{self.twBehaviors.item(row, cfg.behavioursFields['code']).text()} behavior",
|
|
1342
|
+
"Select a modifier coding map for " f"{self.twBehaviors.item(row, cfg.behavioursFields['code']).text()} behavior",
|
|
1338
1343
|
"",
|
|
1339
1344
|
"BORIS map files (*.boris_map);;All files (*)",
|
|
1340
1345
|
)
|
|
@@ -1344,12 +1349,12 @@ class projectDialog(QDialog, Ui_dlgProject):
|
|
|
1344
1349
|
try:
|
|
1345
1350
|
new_map = json.loads(open(fileName, "r").read())
|
|
1346
1351
|
except Exception:
|
|
1347
|
-
QMessageBox.critical(self, cfg.programName, "Error reding the
|
|
1352
|
+
QMessageBox.critical(self, cfg.programName, "Error reding the coding map")
|
|
1348
1353
|
return
|
|
1349
1354
|
self.pj[cfg.CODING_MAP][new_map["name"]] = new_map
|
|
1350
1355
|
|
|
1351
1356
|
# add modifiers from coding map areas
|
|
1352
|
-
modifstr =
|
|
1357
|
+
modifstr = json.dumps(
|
|
1353
1358
|
{
|
|
1354
1359
|
"0": {
|
|
1355
1360
|
"name": new_map["name"],
|
|
@@ -1581,7 +1586,7 @@ class projectDialog(QDialog, Ui_dlgProject):
|
|
|
1581
1586
|
def check_ethogram(self) -> dict:
|
|
1582
1587
|
"""
|
|
1583
1588
|
check ethogram for various parameter
|
|
1584
|
-
returns ethogram dict or {cfg.CANCEL: True
|
|
1589
|
+
returns ethogram dict or {cfg.CANCEL: True} in case of error
|
|
1585
1590
|
|
|
1586
1591
|
"""
|
|
1587
1592
|
# store behaviors
|
|
@@ -1602,7 +1607,11 @@ class projectDialog(QDialog, Ui_dlgProject):
|
|
|
1602
1607
|
|
|
1603
1608
|
if self.twBehaviors.item(r, cfg.behavioursFields["modifiers"]).text():
|
|
1604
1609
|
try:
|
|
1605
|
-
modifiers_dict =
|
|
1610
|
+
modifiers_dict = (
|
|
1611
|
+
json.loads(self.twBehaviors.item(r, cfg.behavioursFields["modifiers"]).text())
|
|
1612
|
+
if self.twBehaviors.item(r, cfg.behavioursFields["modifiers"]).text()
|
|
1613
|
+
else {}
|
|
1614
|
+
)
|
|
1606
1615
|
for k in modifiers_dict:
|
|
1607
1616
|
for value in modifiers_dict[k]["values"]:
|
|
1608
1617
|
modif_code = value.split(" (")[0]
|
|
@@ -1672,7 +1681,7 @@ class projectDialog(QDialog, Ui_dlgProject):
|
|
|
1672
1681
|
if field == "modifiers" and row["modifiers"]:
|
|
1673
1682
|
if remove_leading_trailing_spaces_in_modifiers == cfg.YES:
|
|
1674
1683
|
try:
|
|
1675
|
-
modifiers_dict =
|
|
1684
|
+
modifiers_dict = json.loads(row["modifiers"]) if row["modifiers"] else {}
|
|
1676
1685
|
for k in modifiers_dict:
|
|
1677
1686
|
for idx, value in enumerate(modifiers_dict[k]["values"]):
|
|
1678
1687
|
modif_code = value.split(" (")[0]
|
|
@@ -1688,7 +1697,13 @@ class projectDialog(QDialog, Ui_dlgProject):
|
|
|
1688
1697
|
QMessageBox.critical(self, cfg.programName, "Error removing leading/trailing spaces in modifiers")
|
|
1689
1698
|
|
|
1690
1699
|
else:
|
|
1691
|
-
|
|
1700
|
+
"""
|
|
1701
|
+
if row["modifiers"]:
|
|
1702
|
+
row["modifiers"] = eval(row["modifiers"])
|
|
1703
|
+
else:
|
|
1704
|
+
row["modifiers"] = {}
|
|
1705
|
+
"""
|
|
1706
|
+
row["modifiers"] = json.loads(row["modifiers"]) if row["modifiers"] else {}
|
|
1692
1707
|
else:
|
|
1693
1708
|
row[field] = ""
|
|
1694
1709
|
|
|
@@ -1714,7 +1729,7 @@ class projectDialog(QDialog, Ui_dlgProject):
|
|
|
1714
1729
|
return {cfg.CANCEL: True}
|
|
1715
1730
|
|
|
1716
1731
|
# check if behavior belong to category that is not in categories list
|
|
1717
|
-
behavior_category = []
|
|
1732
|
+
behavior_category: list = []
|
|
1718
1733
|
for idx in checked_ethogram:
|
|
1719
1734
|
if cfg.BEHAVIOR_CATEGORY in checked_ethogram[idx]:
|
|
1720
1735
|
if checked_ethogram[idx][cfg.BEHAVIOR_CATEGORY]:
|