boris-behav-obs 8.27.9__py2.py3-none-any.whl → 9.0.1__py2.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.
- boris/about.py +7 -5
- boris/add_modifier.py +35 -35
- boris/add_modifier_ui.py +229 -129
- boris/advanced_event_filtering.py +3 -3
- boris/analysis_plugins/__init__.py +0 -0
- boris/analysis_plugins/number_of_occurences.py +60 -0
- boris/analysis_plugins/number_of_occurences_by_independent_variable.py +72 -0
- boris/analysis_plugins/time_budget.py +95 -0
- boris/behav_coding_map_creator.py +103 -108
- boris/behavior_binary_table.py +1 -1
- boris/behaviors_coding_map.py +8 -8
- boris/coding_pad.py +6 -6
- boris/config.py +6 -0
- boris/config_file.py +1 -1
- boris/connections.py +4 -2
- boris/converters.py +2 -3
- boris/converters_ui.py +187 -110
- boris/cooccurence.py +2 -2
- boris/core.py +340 -94
- boris/core_qrc.py +16088 -13246
- boris/core_ui.py +922 -812
- boris/db_functions.py +3 -1
- boris/dialog.py +14 -13
- boris/duration_widget.py +5 -5
- boris/edit_event.py +1 -1
- boris/edit_event_ui.py +162 -88
- boris/event_operations.py +4 -25
- boris/events_cursor.py +17 -9
- boris/events_snapshots.py +5 -5
- boris/exclusion_matrix.py +1 -1
- boris/export_events.py +38 -28
- boris/export_observation.py +1 -1
- boris/external_processes.py +3 -5
- boris/geometric_measurement.py +49 -26
- boris/gui_utilities.py +31 -30
- boris/import_observations.py +2 -4
- boris/irr.py +1 -1
- boris/latency.py +1 -1
- boris/map_creator.py +77 -89
- boris/measurement_widget.py +4 -4
- boris/media_file.py +2 -4
- boris/menu_options.py +1 -3
- boris/modifiers_coding_map.py +4 -4
- boris/mpv2.py +0 -2
- boris/observation.py +124 -29
- boris/observation_operations.py +18 -40
- boris/observation_ui.py +566 -374
- boris/observations_list.py +6 -6
- boris/param_panel.py +2 -2
- boris/param_panel_ui.py +246 -141
- boris/player_dock_widget.py +16 -21
- boris/plot_data_module.py +6 -6
- boris/plot_events_rt.py +7 -8
- boris/plot_spectrogram_rt.py +7 -8
- boris/plot_waveform_rt.py +6 -7
- boris/plugins.py +79 -0
- boris/preferences.py +127 -17
- boris/preferences_ui.py +464 -240
- boris/project.py +69 -72
- boris/project_functions.py +233 -31
- boris/project_import_export.py +59 -67
- boris/project_ui.py +672 -440
- boris/qrc_boris.py +6 -3
- boris/qrc_boris5.py +6 -3
- boris/select_modifiers.py +2 -2
- boris/select_observations.py +2 -2
- boris/select_subj_behav.py +3 -3
- boris/state_events.py +1 -1
- boris/subjects_pad.py +5 -5
- boris/synthetic_time_budget.py +2 -2
- boris/time_budget_functions.py +15 -0
- boris/time_budget_widget.py +4 -4
- boris/transitions.py +34 -25
- boris/utilities.py +95 -2
- boris/version.py +2 -2
- boris/video_equalizer.py +4 -4
- boris/video_equalizer_ui.py +199 -130
- boris/video_operations.py +1 -1
- boris/view_df.py +106 -0
- boris/view_df_ui.py +75 -0
- boris/write_event.py +9 -1
- {boris_behav_obs-8.27.9.dist-info → boris_behav_obs-9.0.1.dist-info}/METADATA +5 -5
- boris_behav_obs-9.0.1.dist-info/RECORD +103 -0
- {boris_behav_obs-8.27.9.dist-info → boris_behav_obs-9.0.1.dist-info}/WHEEL +1 -1
- boris/qdarkstyle/__init__.py +0 -479
- boris/qdarkstyle/__main__.py +0 -66
- boris/qdarkstyle/colorsystem.py +0 -38
- boris/qdarkstyle/dark/__init__.py +0 -1
- boris/qdarkstyle/dark/darkstyle_rc.py +0 -11379
- boris/qdarkstyle/dark/palette.py +0 -38
- boris/qdarkstyle/example/__init__.py +0 -4
- boris/qdarkstyle/example/__main__.py +0 -386
- boris/qdarkstyle/example/ui/__init__.py +0 -4
- boris/qdarkstyle/light/__init__.py +0 -1
- boris/qdarkstyle/light/lightstyle_rc.py +0 -11305
- boris/qdarkstyle/light/palette.py +0 -37
- boris/qdarkstyle/palette.py +0 -102
- boris/qdarkstyle/utils/__init__.py +0 -73
- boris/qdarkstyle/utils/__main__.py +0 -96
- boris/qdarkstyle/utils/images.py +0 -449
- boris/qdarkstyle/utils/scss.py +0 -318
- boris/vlc_local.py +0 -83
- boris_behav_obs-8.27.9.dist-info/RECORD +0 -114
- {boris_behav_obs-8.27.9.dist-info → boris_behav_obs-9.0.1.dist-info}/LICENSE.TXT +0 -0
- {boris_behav_obs-8.27.9.dist-info → boris_behav_obs-9.0.1.dist-info}/entry_points.txt +0 -0
- {boris_behav_obs-8.27.9.dist-info → boris_behav_obs-9.0.1.dist-info}/top_level.txt +0 -0
boris/plot_spectrogram_rt.py
CHANGED
|
@@ -30,7 +30,7 @@ import numpy as np
|
|
|
30
30
|
|
|
31
31
|
from . import config as cfg
|
|
32
32
|
|
|
33
|
-
from
|
|
33
|
+
from PySide6.QtWidgets import (
|
|
34
34
|
QWidget,
|
|
35
35
|
QVBoxLayout,
|
|
36
36
|
QHBoxLayout,
|
|
@@ -38,8 +38,7 @@ from PyQt5.QtWidgets import (
|
|
|
38
38
|
QLabel,
|
|
39
39
|
QSpinBox,
|
|
40
40
|
)
|
|
41
|
-
from
|
|
42
|
-
from PyQt5 import Qt
|
|
41
|
+
from PySide6.QtCore import Signal, QEvent, Qt
|
|
43
42
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
|
44
43
|
from matplotlib.figure import Figure
|
|
45
44
|
import matplotlib.ticker as mticker
|
|
@@ -49,7 +48,7 @@ import matplotlib.ticker as mticker
|
|
|
49
48
|
|
|
50
49
|
class Plot_spectrogram_RT(QWidget):
|
|
51
50
|
# send keypress event to mainwindow
|
|
52
|
-
sendEvent =
|
|
51
|
+
sendEvent = Signal(QEvent)
|
|
53
52
|
|
|
54
53
|
def __init__(self):
|
|
55
54
|
super().__init__()
|
|
@@ -77,7 +76,7 @@ class Plot_spectrogram_RT(QWidget):
|
|
|
77
76
|
"+",
|
|
78
77
|
self,
|
|
79
78
|
clicked=lambda: self.time_interval_changed(1),
|
|
80
|
-
focusPolicy=Qt.
|
|
79
|
+
focusPolicy=Qt.NoFocus,
|
|
81
80
|
)
|
|
82
81
|
)
|
|
83
82
|
hlayout1.addWidget(
|
|
@@ -85,17 +84,17 @@ class Plot_spectrogram_RT(QWidget):
|
|
|
85
84
|
"-",
|
|
86
85
|
self,
|
|
87
86
|
clicked=lambda: self.time_interval_changed(-1),
|
|
88
|
-
focusPolicy=Qt.
|
|
87
|
+
focusPolicy=Qt.NoFocus,
|
|
89
88
|
)
|
|
90
89
|
)
|
|
91
90
|
layout.addLayout(hlayout1)
|
|
92
91
|
|
|
93
92
|
hlayout2 = QHBoxLayout()
|
|
94
93
|
hlayout2.addWidget(QLabel("Frequency interval"))
|
|
95
|
-
self.sb_freq_min = QSpinBox(valueChanged=self.frequency_interval_changed, focusPolicy=Qt.
|
|
94
|
+
self.sb_freq_min = QSpinBox(valueChanged=self.frequency_interval_changed, focusPolicy=Qt.NoFocus)
|
|
96
95
|
self.sb_freq_min.setRange(0, 200000)
|
|
97
96
|
self.sb_freq_min.setSingleStep(100)
|
|
98
|
-
self.sb_freq_max = QSpinBox(valueChanged=self.frequency_interval_changed, focusPolicy=Qt.
|
|
97
|
+
self.sb_freq_max = QSpinBox(valueChanged=self.frequency_interval_changed, focusPolicy=Qt.NoFocus)
|
|
99
98
|
self.sb_freq_max.setRange(0, 200000)
|
|
100
99
|
self.sb_freq_max.setSingleStep(100)
|
|
101
100
|
hlayout2.addWidget(self.sb_freq_min)
|
boris/plot_waveform_rt.py
CHANGED
|
@@ -28,10 +28,9 @@ import matplotlib
|
|
|
28
28
|
matplotlib.use("Qt5Agg")
|
|
29
29
|
|
|
30
30
|
import numpy as np
|
|
31
|
-
from
|
|
32
|
-
from
|
|
33
|
-
from
|
|
34
|
-
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
|
31
|
+
from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel
|
|
32
|
+
from PySide6.QtCore import Signal, QEvent, Qt
|
|
33
|
+
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
|
|
35
34
|
from matplotlib.figure import Figure
|
|
36
35
|
import matplotlib.ticker as mticker
|
|
37
36
|
|
|
@@ -40,7 +39,7 @@ import matplotlib.ticker as mticker
|
|
|
40
39
|
|
|
41
40
|
class Plot_waveform_RT(QWidget):
|
|
42
41
|
# send keypress event to mainwindow
|
|
43
|
-
sendEvent =
|
|
42
|
+
sendEvent = Signal(QEvent)
|
|
44
43
|
|
|
45
44
|
def __init__(self):
|
|
46
45
|
super().__init__()
|
|
@@ -68,7 +67,7 @@ class Plot_waveform_RT(QWidget):
|
|
|
68
67
|
"+",
|
|
69
68
|
self,
|
|
70
69
|
clicked=lambda: self.time_interval_changed(1),
|
|
71
|
-
focusPolicy=Qt.
|
|
70
|
+
focusPolicy=Qt.NoFocus,
|
|
72
71
|
)
|
|
73
72
|
)
|
|
74
73
|
hlayout1.addWidget(
|
|
@@ -76,7 +75,7 @@ class Plot_waveform_RT(QWidget):
|
|
|
76
75
|
"-",
|
|
77
76
|
self,
|
|
78
77
|
clicked=lambda: self.time_interval_changed(-1),
|
|
79
|
-
focusPolicy=Qt.
|
|
78
|
+
focusPolicy=Qt.NoFocus,
|
|
80
79
|
)
|
|
81
80
|
)
|
|
82
81
|
layout.addLayout(hlayout1)
|
boris/plugins.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""
|
|
2
|
+
BORIS
|
|
3
|
+
Behavioral Observation Research Interactive Software
|
|
4
|
+
Copyright 2012-2024 Olivier Friard
|
|
5
|
+
|
|
6
|
+
This program is free software; you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU General Public License as published by
|
|
8
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License
|
|
17
|
+
along with this program; if not, write to the Free Software
|
|
18
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
19
|
+
MA 02110-1301, USA.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import logging
|
|
23
|
+
from PySide6.QtGui import QAction
|
|
24
|
+
from . import config as cfg
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def add_plugins_to_menu(self):
|
|
29
|
+
"""
|
|
30
|
+
add plugins to the plugins menu
|
|
31
|
+
"""
|
|
32
|
+
for plugin_name in self.config_param.get(cfg.ANALYSIS_PLUGINS, {}):
|
|
33
|
+
logging.debug(f"adding plugin '{plugin_name}' to menu")
|
|
34
|
+
# Create an action for each submenu option
|
|
35
|
+
action = QAction(self, triggered=self.run_plugin)
|
|
36
|
+
action.setText(plugin_name)
|
|
37
|
+
|
|
38
|
+
self.menu_plugins.addAction(action)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_plugin_name(plugin_path: str):
|
|
42
|
+
"""
|
|
43
|
+
get name of plugin
|
|
44
|
+
"""
|
|
45
|
+
# search plugin name
|
|
46
|
+
plugin_name = None
|
|
47
|
+
with open(plugin_path, "r") as f_in:
|
|
48
|
+
for line in f_in:
|
|
49
|
+
if line.startswith("__plugin_name__"):
|
|
50
|
+
plugin_name = line.split("=")[1].strip().replace('"', "")
|
|
51
|
+
break
|
|
52
|
+
return plugin_name
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def load_plugins(self):
|
|
56
|
+
"""
|
|
57
|
+
load selected plugins in analysis menu
|
|
58
|
+
"""
|
|
59
|
+
self.menu_plugins.clear()
|
|
60
|
+
self.config_param[cfg.ANALYSIS_PLUGINS] = {}
|
|
61
|
+
|
|
62
|
+
# load BORIS plugins
|
|
63
|
+
for file_ in (Path(__file__).parent / "analysis_plugins").glob("*.py"):
|
|
64
|
+
if file_.name == "__init__.py":
|
|
65
|
+
continue
|
|
66
|
+
plugin_name = get_plugin_name(file_)
|
|
67
|
+
if plugin_name is not None and plugin_name not in self.config_param.get(cfg.EXCLUDED_PLUGINS, set()):
|
|
68
|
+
self.config_param[cfg.ANALYSIS_PLUGINS][plugin_name] = str(file_)
|
|
69
|
+
|
|
70
|
+
# load personal plugins
|
|
71
|
+
if self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, ""):
|
|
72
|
+
for file_ in Path(self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, "")).glob("*.py"):
|
|
73
|
+
if file_.name == "__init__.py":
|
|
74
|
+
continue
|
|
75
|
+
plugin_name = get_plugin_name(file_)
|
|
76
|
+
if plugin_name is not None and plugin_name not in self.config_param.get(cfg.EXCLUDED_PLUGINS, set()):
|
|
77
|
+
self.config_param[cfg.ANALYSIS_PLUGINS][plugin_name] = str(file_)
|
|
78
|
+
|
|
79
|
+
print(f"{self.config_param.get(cfg.ANALYSIS_PLUGINS, {})=}")
|
boris/preferences.py
CHANGED
|
@@ -22,21 +22,19 @@ This file is part of BORIS.
|
|
|
22
22
|
|
|
23
23
|
import logging
|
|
24
24
|
import os
|
|
25
|
-
import
|
|
25
|
+
from pathlib import Path
|
|
26
26
|
import sys
|
|
27
|
-
|
|
28
|
-
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".")))
|
|
29
|
-
import qdarkstyle
|
|
30
|
-
|
|
31
27
|
from . import dialog
|
|
32
28
|
from . import gui_utilities
|
|
33
29
|
from . import menu_options
|
|
34
30
|
from . import config as cfg
|
|
35
31
|
from . import config_file
|
|
32
|
+
from . import plugins
|
|
36
33
|
|
|
37
34
|
from .preferences_ui import Ui_prefDialog
|
|
38
35
|
|
|
39
|
-
from
|
|
36
|
+
from PySide6.QtWidgets import QDialog, QFileDialog, QListWidgetItem, QMessageBox
|
|
37
|
+
from PySide6.QtCore import Qt
|
|
40
38
|
|
|
41
39
|
|
|
42
40
|
class Preferences(QDialog, Ui_prefDialog):
|
|
@@ -44,6 +42,11 @@ class Preferences(QDialog, Ui_prefDialog):
|
|
|
44
42
|
super().__init__()
|
|
45
43
|
self.setupUi(self)
|
|
46
44
|
|
|
45
|
+
# plugins
|
|
46
|
+
"""self.pb_add_plugin.clicked.connect(self.add_plugin)
|
|
47
|
+
self.pb_remove_plugin.clicked.connect(self.remove_plugin)"""
|
|
48
|
+
self.pb_browse_plugins_dir.clicked.connect(self.browse_plugins_dir)
|
|
49
|
+
|
|
47
50
|
self.pbBrowseFFmpegCacheDir.clicked.connect(self.browseFFmpegCacheDir)
|
|
48
51
|
|
|
49
52
|
self.pb_reset_behav_colors.clicked.connect(self.reset_behav_colors)
|
|
@@ -55,6 +58,28 @@ class Preferences(QDialog, Ui_prefDialog):
|
|
|
55
58
|
|
|
56
59
|
self.flag_refresh = False
|
|
57
60
|
|
|
61
|
+
def browse_plugins_dir(self):
|
|
62
|
+
"""
|
|
63
|
+
get the personal plugins directory
|
|
64
|
+
"""
|
|
65
|
+
directory = QFileDialog.getExistingDirectory(None, "Select the plugins directory", self.le_personal_plugins_dir.text())
|
|
66
|
+
if not directory:
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
self.le_personal_plugins_dir.setText(directory)
|
|
70
|
+
self.lw_personal_plugins.clear()
|
|
71
|
+
for file_ in Path(directory).glob("*.py"):
|
|
72
|
+
item = QListWidgetItem(file_.stem)
|
|
73
|
+
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
|
|
74
|
+
# if plugin_name in self.config_param.get(cfg.EXCLUDED_PLUGINS, set()):
|
|
75
|
+
# item.setCheckState(Qt.Unchecked)
|
|
76
|
+
# else:
|
|
77
|
+
item.setCheckState(Qt.Checked)
|
|
78
|
+
item.setData(100, file_.stem)
|
|
79
|
+
self.lw_personal_plugins.addItem(item)
|
|
80
|
+
if self.lw_personal_plugins.count() == 0:
|
|
81
|
+
QMessageBox.warning(self, cfg.programName, f"No plugin found in {directory}")
|
|
82
|
+
|
|
58
83
|
def refresh_preferences(self):
|
|
59
84
|
"""
|
|
60
85
|
allow user to delete the config file (.boris)
|
|
@@ -74,11 +99,11 @@ class Preferences(QDialog, Ui_prefDialog):
|
|
|
74
99
|
"""
|
|
75
100
|
allow user select a cache dir for ffmpeg images
|
|
76
101
|
"""
|
|
77
|
-
FFmpegCacheDir = QFileDialog
|
|
102
|
+
FFmpegCacheDir = QFileDialog.getExistingDirectory(
|
|
78
103
|
self,
|
|
79
104
|
"Select a directory",
|
|
80
105
|
os.path.expanduser("~"),
|
|
81
|
-
options=QFileDialog
|
|
106
|
+
options=QFileDialog.ShowDirsOnly,
|
|
82
107
|
)
|
|
83
108
|
if FFmpegCacheDir:
|
|
84
109
|
self.leFFmpegCacheDir.setText(FFmpegCacheDir)
|
|
@@ -105,6 +130,30 @@ def preferences(self):
|
|
|
105
130
|
show preferences window
|
|
106
131
|
"""
|
|
107
132
|
|
|
133
|
+
def show_plugin_info(item):
|
|
134
|
+
"""
|
|
135
|
+
display information about the clicked plugin
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
if item.text() not in self.config_param[cfg.ANALYSIS_PLUGINS]:
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
import importlib
|
|
142
|
+
|
|
143
|
+
plugin_path = item.data(100)
|
|
144
|
+
|
|
145
|
+
module_name = Path(plugin_path).stem
|
|
146
|
+
spec = importlib.util.spec_from_file_location(module_name, plugin_path)
|
|
147
|
+
plugin_module = importlib.util.module_from_spec(spec)
|
|
148
|
+
spec.loader.exec_module(plugin_module)
|
|
149
|
+
out: list = []
|
|
150
|
+
out.append(plugin_module.__plugin_name__ + "\n")
|
|
151
|
+
out.append(plugin_module.__author__)
|
|
152
|
+
out.append(f"{plugin_module.__version__} ({plugin_module.__version_date__})\n")
|
|
153
|
+
out.append(plugin_module.run.__doc__.strip())
|
|
154
|
+
|
|
155
|
+
preferencesWindow.pte_plugin_description.setPlainText("\n".join(out))
|
|
156
|
+
|
|
108
157
|
preferencesWindow = Preferences()
|
|
109
158
|
preferencesWindow.tabWidget.setCurrentIndex(0)
|
|
110
159
|
|
|
@@ -135,7 +184,7 @@ def preferences(self):
|
|
|
135
184
|
# check for new version
|
|
136
185
|
preferencesWindow.cbCheckForNewVersion.setChecked(self.checkForNewVersion)
|
|
137
186
|
# display subtitles
|
|
138
|
-
preferencesWindow.cb_display_subtitles.setChecked(self.config_param
|
|
187
|
+
preferencesWindow.cb_display_subtitles.setChecked(self.config_param.get(cfg.DISPLAY_SUBTITLES, False))
|
|
139
188
|
# pause before add event
|
|
140
189
|
preferencesWindow.cb_pause_before_addevent.setChecked(self.pause_before_addevent)
|
|
141
190
|
# MPV hwdec
|
|
@@ -148,6 +197,49 @@ def preferences(self):
|
|
|
148
197
|
except Exception:
|
|
149
198
|
preferencesWindow.cb_hwdec.setCurrentIndex(cfg.MPV_HWDEC_OPTIONS.index(cfg.MPV_HWDEC_DEFAULT_VALUE))
|
|
150
199
|
|
|
200
|
+
# BORIS plugins
|
|
201
|
+
preferencesWindow.lv_all_plugins.itemClicked.connect(show_plugin_info)
|
|
202
|
+
|
|
203
|
+
preferencesWindow.lv_all_plugins.clear()
|
|
204
|
+
|
|
205
|
+
for file_ in (Path(__file__).parent / "analysis_plugins").glob("*.py"):
|
|
206
|
+
if file_.name == "__init__.py":
|
|
207
|
+
continue
|
|
208
|
+
plugin_name = plugins.get_plugin_name(file_)
|
|
209
|
+
if plugin_name is not None:
|
|
210
|
+
item = QListWidgetItem(plugin_name)
|
|
211
|
+
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
|
|
212
|
+
if plugin_name in self.config_param.get(cfg.EXCLUDED_PLUGINS, set()):
|
|
213
|
+
item.setCheckState(Qt.Unchecked)
|
|
214
|
+
else:
|
|
215
|
+
item.setCheckState(Qt.Checked)
|
|
216
|
+
item.setData(100, str(file_))
|
|
217
|
+
preferencesWindow.lv_all_plugins.addItem(item)
|
|
218
|
+
|
|
219
|
+
# personal plugins
|
|
220
|
+
preferencesWindow.le_personal_plugins_dir.setText(self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, ""))
|
|
221
|
+
preferencesWindow.lw_personal_plugins.itemClicked.connect(show_plugin_info)
|
|
222
|
+
|
|
223
|
+
preferencesWindow.lw_personal_plugins.clear()
|
|
224
|
+
if self.config_param.get(cfg.PERSONAL_PLUGINS_DIR, ""):
|
|
225
|
+
for file_ in Path(self.config_param[cfg.PERSONAL_PLUGINS_DIR]).glob("*.py"):
|
|
226
|
+
if file_.name == "__init__.py":
|
|
227
|
+
continue
|
|
228
|
+
plugin_name = plugins.get_plugin_name(file_)
|
|
229
|
+
if plugin_name is None:
|
|
230
|
+
continue
|
|
231
|
+
# check if personal plugin name is in BORIS plugins (case sensitive)
|
|
232
|
+
if plugin_name in [preferencesWindow.lv_all_plugins.item(i).text() for i in range(preferencesWindow.lv_all_plugins.count())]:
|
|
233
|
+
continue
|
|
234
|
+
item = QListWidgetItem(plugin_name)
|
|
235
|
+
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
|
|
236
|
+
if plugin_name in self.config_param.get(cfg.EXCLUDED_PLUGINS, set()):
|
|
237
|
+
item.setCheckState(Qt.Unchecked)
|
|
238
|
+
else:
|
|
239
|
+
item.setCheckState(Qt.Checked)
|
|
240
|
+
item.setData(100, str(file_))
|
|
241
|
+
preferencesWindow.lw_personal_plugins.addItem(item)
|
|
242
|
+
|
|
151
243
|
# PROJET FILE INDENTATION
|
|
152
244
|
preferencesWindow.combo_project_file_indentation.clear()
|
|
153
245
|
preferencesWindow.combo_project_file_indentation.addItems(cfg.PROJECT_FILE_INDENTATION_COMBO_OPTIONS)
|
|
@@ -201,7 +293,6 @@ def preferences(self):
|
|
|
201
293
|
|
|
202
294
|
# interface
|
|
203
295
|
preferencesWindow.sb_toolbar_icon_size.setValue(self.config_param.get(cfg.TOOLBAR_ICON_SIZE, cfg.DEFAULT_TOOLBAR_ICON_SIZE_VALUE))
|
|
204
|
-
preferencesWindow.cb_darkmode.setChecked(self.config_param.get(cfg.DARK_MODE, cfg.DARK_MODE_DEFAULT_VALUE))
|
|
205
296
|
|
|
206
297
|
gui_utilities.restore_geometry(preferencesWindow, "preferences", (700, 500))
|
|
207
298
|
|
|
@@ -217,8 +308,8 @@ def preferences(self):
|
|
|
217
308
|
self.close()
|
|
218
309
|
# check if refresh canceled for not saved project
|
|
219
310
|
if "refresh_preferences" in self.config_param:
|
|
220
|
-
if (
|
|
221
|
-
os.remove(
|
|
311
|
+
if (Path.home() / ".boris").exists():
|
|
312
|
+
os.remove(Path.home() / ".boris")
|
|
222
313
|
sys.exit()
|
|
223
314
|
|
|
224
315
|
if preferencesWindow.cbTimeFormat.currentIndex() == 0:
|
|
@@ -262,6 +353,30 @@ def preferences(self):
|
|
|
262
353
|
# MPV hwdec
|
|
263
354
|
self.config_param[cfg.MPV_HWDEC] = cfg.MPV_HWDEC_OPTIONS[preferencesWindow.cb_hwdec.currentIndex()]
|
|
264
355
|
|
|
356
|
+
# update BORIS analysis plugins
|
|
357
|
+
self.config_param[cfg.ANALYSIS_PLUGINS] = {}
|
|
358
|
+
self.config_param[cfg.EXCLUDED_PLUGINS] = set()
|
|
359
|
+
for i in range(preferencesWindow.lv_all_plugins.count()):
|
|
360
|
+
if preferencesWindow.lv_all_plugins.item(i).checkState() == Qt.Checked:
|
|
361
|
+
self.config_param[cfg.ANALYSIS_PLUGINS][preferencesWindow.lv_all_plugins.item(i).text()] = (
|
|
362
|
+
preferencesWindow.lv_all_plugins.item(i).data(100)
|
|
363
|
+
)
|
|
364
|
+
else:
|
|
365
|
+
self.config_param[cfg.EXCLUDED_PLUGINS].add(preferencesWindow.lv_all_plugins.item(i).text())
|
|
366
|
+
|
|
367
|
+
# update personal plugins
|
|
368
|
+
self.config_param[cfg.PERSONAL_PLUGINS_DIR] = preferencesWindow.le_personal_plugins_dir.text()
|
|
369
|
+
for i in range(preferencesWindow.lw_personal_plugins.count()):
|
|
370
|
+
if preferencesWindow.lw_personal_plugins.item(i).checkState() == Qt.Checked:
|
|
371
|
+
self.config_param[cfg.ANALYSIS_PLUGINS][preferencesWindow.lw_personal_plugins.item(i).text()] = (
|
|
372
|
+
preferencesWindow.lw_personal_plugins.item(i).data(100)
|
|
373
|
+
)
|
|
374
|
+
else:
|
|
375
|
+
self.config_param[cfg.EXCLUDED_PLUGINS].add(preferencesWindow.lw_personal_plugins.item(i).text())
|
|
376
|
+
|
|
377
|
+
plugins.load_plugins(self)
|
|
378
|
+
plugins.add_plugins_to_menu(self)
|
|
379
|
+
|
|
265
380
|
# project file indentation
|
|
266
381
|
self.config_param[cfg.PROJECT_FILE_INDENTATION] = cfg.PROJECT_FILE_INDENTATION_OPTIONS[
|
|
267
382
|
preferencesWindow.combo_project_file_indentation.currentIndex()
|
|
@@ -285,11 +400,6 @@ def preferences(self):
|
|
|
285
400
|
|
|
286
401
|
# interface
|
|
287
402
|
self.config_param[cfg.TOOLBAR_ICON_SIZE] = preferencesWindow.sb_toolbar_icon_size.value()
|
|
288
|
-
self.config_param[cfg.DARK_MODE] = preferencesWindow.cb_darkmode.isChecked()
|
|
289
|
-
if self.config_param.get(cfg.DARK_MODE, cfg.DEFAULT_FRAME_MODE):
|
|
290
|
-
self.setStyleSheet(qdarkstyle.load_stylesheet(qt_api="pyqt5"))
|
|
291
|
-
else:
|
|
292
|
-
self.setStyleSheet("")
|
|
293
403
|
|
|
294
404
|
menu_options.update_menu(self)
|
|
295
405
|
|