boris-behav-obs 8.27.10__py2.py3-none-any.whl → 9.0.2__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.
Files changed (105) hide show
  1. boris/about.py +7 -5
  2. boris/add_modifier.py +35 -35
  3. boris/add_modifier_ui.py +229 -129
  4. boris/advanced_event_filtering.py +3 -3
  5. boris/analysis_plugins/__init__.py +0 -0
  6. boris/analysis_plugins/number_of_occurences.py +60 -0
  7. boris/analysis_plugins/number_of_occurences_by_independent_variable.py +72 -0
  8. boris/analysis_plugins/time_budget.py +95 -0
  9. boris/behav_coding_map_creator.py +103 -108
  10. boris/behavior_binary_table.py +1 -1
  11. boris/behaviors_coding_map.py +8 -8
  12. boris/coding_pad.py +6 -6
  13. boris/config.py +6 -0
  14. boris/config_file.py +1 -1
  15. boris/connections.py +4 -2
  16. boris/converters.py +2 -3
  17. boris/converters_ui.py +187 -110
  18. boris/cooccurence.py +2 -2
  19. boris/core.py +341 -94
  20. boris/core_qrc.py +16088 -13246
  21. boris/core_ui.py +922 -812
  22. boris/dialog.py +14 -13
  23. boris/duration_widget.py +5 -5
  24. boris/edit_event.py +1 -1
  25. boris/edit_event_ui.py +162 -88
  26. boris/event_operations.py +4 -25
  27. boris/events_cursor.py +17 -9
  28. boris/events_snapshots.py +5 -5
  29. boris/exclusion_matrix.py +1 -1
  30. boris/export_events.py +38 -28
  31. boris/export_observation.py +1 -1
  32. boris/external_processes.py +3 -5
  33. boris/geometric_measurement.py +49 -26
  34. boris/gui_utilities.py +31 -30
  35. boris/import_observations.py +2 -4
  36. boris/irr.py +1 -1
  37. boris/latency.py +1 -1
  38. boris/map_creator.py +77 -89
  39. boris/measurement_widget.py +4 -4
  40. boris/media_file.py +2 -4
  41. boris/menu_options.py +1 -3
  42. boris/modifiers_coding_map.py +4 -4
  43. boris/mpv2.py +0 -2
  44. boris/observation.py +124 -29
  45. boris/observation_operations.py +18 -40
  46. boris/observation_ui.py +566 -374
  47. boris/observations_list.py +6 -6
  48. boris/param_panel.py +2 -2
  49. boris/param_panel_ui.py +246 -141
  50. boris/player_dock_widget.py +16 -21
  51. boris/plot_data_module.py +6 -6
  52. boris/plot_events_rt.py +7 -8
  53. boris/plot_spectrogram_rt.py +7 -8
  54. boris/plot_waveform_rt.py +6 -7
  55. boris/plugins.py +79 -0
  56. boris/preferences.py +127 -17
  57. boris/preferences_ui.py +464 -240
  58. boris/project.py +69 -72
  59. boris/project_functions.py +233 -31
  60. boris/project_import_export.py +59 -67
  61. boris/project_ui.py +672 -440
  62. boris/qrc_boris.py +6 -3
  63. boris/qrc_boris5.py +6 -3
  64. boris/select_modifiers.py +2 -2
  65. boris/select_observations.py +2 -2
  66. boris/select_subj_behav.py +3 -3
  67. boris/state_events.py +1 -1
  68. boris/subjects_pad.py +5 -5
  69. boris/synthetic_time_budget.py +2 -2
  70. boris/time_budget_functions.py +15 -0
  71. boris/time_budget_widget.py +4 -4
  72. boris/transitions.py +34 -25
  73. boris/utilities.py +96 -3
  74. boris/version.py +2 -2
  75. boris/video_equalizer.py +4 -4
  76. boris/video_equalizer_ui.py +199 -130
  77. boris/video_operations.py +1 -1
  78. boris/view_df.py +106 -0
  79. boris/view_df_ui.py +75 -0
  80. boris/write_event.py +9 -1
  81. {boris_behav_obs-8.27.10.dist-info → boris_behav_obs-9.0.2.dist-info}/METADATA +5 -5
  82. boris_behav_obs-9.0.2.dist-info/RECORD +103 -0
  83. {boris_behav_obs-8.27.10.dist-info → boris_behav_obs-9.0.2.dist-info}/WHEEL +1 -1
  84. boris/qdarkstyle/__init__.py +0 -479
  85. boris/qdarkstyle/__main__.py +0 -66
  86. boris/qdarkstyle/colorsystem.py +0 -38
  87. boris/qdarkstyle/dark/__init__.py +0 -1
  88. boris/qdarkstyle/dark/darkstyle_rc.py +0 -11379
  89. boris/qdarkstyle/dark/palette.py +0 -38
  90. boris/qdarkstyle/example/__init__.py +0 -4
  91. boris/qdarkstyle/example/__main__.py +0 -386
  92. boris/qdarkstyle/example/ui/__init__.py +0 -4
  93. boris/qdarkstyle/light/__init__.py +0 -1
  94. boris/qdarkstyle/light/lightstyle_rc.py +0 -11305
  95. boris/qdarkstyle/light/palette.py +0 -37
  96. boris/qdarkstyle/palette.py +0 -102
  97. boris/qdarkstyle/utils/__init__.py +0 -73
  98. boris/qdarkstyle/utils/__main__.py +0 -96
  99. boris/qdarkstyle/utils/images.py +0 -449
  100. boris/qdarkstyle/utils/scss.py +0 -318
  101. boris/vlc_local.py +0 -83
  102. boris_behav_obs-8.27.10.dist-info/RECORD +0 -114
  103. {boris_behav_obs-8.27.10.dist-info → boris_behav_obs-9.0.2.dist-info}/LICENSE.TXT +0 -0
  104. {boris_behav_obs-8.27.10.dist-info → boris_behav_obs-9.0.2.dist-info}/entry_points.txt +0 -0
  105. {boris_behav_obs-8.27.10.dist-info → boris_behav_obs-9.0.2.dist-info}/top_level.txt +0 -0
@@ -30,7 +30,7 @@ import numpy as np
30
30
 
31
31
  from . import config as cfg
32
32
 
33
- from PyQt5.QtWidgets import (
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 PyQt5.QtCore import pyqtSignal, QEvent
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 = pyqtSignal(QEvent)
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.Qt.NoFocus,
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.Qt.NoFocus,
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.Qt.NoFocus)
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.Qt.NoFocus)
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 PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel
32
- from PyQt5.QtCore import pyqtSignal, QEvent
33
- from PyQt5 import Qt
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 = pyqtSignal(QEvent)
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.Qt.NoFocus,
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.Qt.NoFocus,
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 pathlib
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 PyQt5.QtWidgets import QDialog, QFileDialog
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().getExistingDirectory(
102
+ FFmpegCacheDir = QFileDialog.getExistingDirectory(
78
103
  self,
79
104
  "Select a directory",
80
105
  os.path.expanduser("~"),
81
- options=QFileDialog().ShowDirsOnly,
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[cfg.DISPLAY_SUBTITLES])
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 (pathlib.Path.home() / ".boris").exists():
221
- os.remove(pathlib.Path.home() / ".boris")
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