dcscope 2.22.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.
- dcscope/__init__.py +17 -0
- dcscope/__main__.py +44 -0
- dcscope/_version.py +21 -0
- dcscope/extensions.py +250 -0
- dcscope/gui/__init__.py +2 -0
- dcscope/gui/analysis/__init__.py +10 -0
- dcscope/gui/analysis/ana_basins.py +110 -0
- dcscope/gui/analysis/ana_basins.ui +143 -0
- dcscope/gui/analysis/ana_filter.py +341 -0
- dcscope/gui/analysis/ana_filter.ui +364 -0
- dcscope/gui/analysis/ana_log.py +122 -0
- dcscope/gui/analysis/ana_log.ui +100 -0
- dcscope/gui/analysis/ana_meta.py +207 -0
- dcscope/gui/analysis/ana_meta.ui +141 -0
- dcscope/gui/analysis/ana_plot.py +638 -0
- dcscope/gui/analysis/ana_plot.ui +1060 -0
- dcscope/gui/analysis/ana_slot.py +504 -0
- dcscope/gui/analysis/ana_slot.ui +684 -0
- dcscope/gui/analysis/ana_tables.py +227 -0
- dcscope/gui/analysis/ana_tables.ui +195 -0
- dcscope/gui/analysis/ana_view.py +69 -0
- dcscope/gui/analysis/ana_view.ui +269 -0
- dcscope/gui/analysis/dlg_slot_reorder.py +55 -0
- dcscope/gui/analysis/dlg_slot_reorder.ui +138 -0
- dcscope/gui/bulk/__init__.py +2 -0
- dcscope/gui/bulk/bulk_emodulus.py +200 -0
- dcscope/gui/bulk/bulk_emodulus.ui +245 -0
- dcscope/gui/compute/__init__.py +3 -0
- dcscope/gui/compute/comp_lme4.py +115 -0
- dcscope/gui/compute/comp_lme4.ui +194 -0
- dcscope/gui/compute/comp_lme4_dataset.py +51 -0
- dcscope/gui/compute/comp_lme4_dataset.ui +92 -0
- dcscope/gui/compute/comp_lme4_results.py +120 -0
- dcscope/gui/compute/comp_lme4_results.ui +268 -0
- dcscope/gui/compute/comp_stats.py +223 -0
- dcscope/gui/compute/comp_stats.ui +187 -0
- dcscope/gui/dcor/__init__.py +304 -0
- dcscope/gui/dcor/dcor.ui +118 -0
- dcscope/gui/export/__init__.py +3 -0
- dcscope/gui/export/e2data.py +394 -0
- dcscope/gui/export/e2data.ui +367 -0
- dcscope/gui/export/e2filter.py +76 -0
- dcscope/gui/export/e2filter.ui +111 -0
- dcscope/gui/export/e2plot.py +94 -0
- dcscope/gui/export/e2plot.ui +175 -0
- dcscope/gui/main.py +1089 -0
- dcscope/gui/main.ui +579 -0
- dcscope/gui/matrix/__init__.py +4 -0
- dcscope/gui/matrix/block_matrix.py +141 -0
- dcscope/gui/matrix/block_matrix.ui +207 -0
- dcscope/gui/matrix/data_matrix.py +574 -0
- dcscope/gui/matrix/dm_dataset.py +116 -0
- dcscope/gui/matrix/dm_dataset.ui +348 -0
- dcscope/gui/matrix/dm_element.py +111 -0
- dcscope/gui/matrix/dm_element.ui +169 -0
- dcscope/gui/matrix/dm_filter.py +115 -0
- dcscope/gui/matrix/dm_filter.ui +287 -0
- dcscope/gui/matrix/plot_matrix.py +316 -0
- dcscope/gui/matrix/pm_element.py +39 -0
- dcscope/gui/matrix/pm_plot.py +86 -0
- dcscope/gui/matrix/pm_plot.ui +249 -0
- dcscope/gui/pipeline_plot.py +797 -0
- dcscope/gui/pipeline_plot.ui +66 -0
- dcscope/gui/preferences.py +380 -0
- dcscope/gui/preferences.ui +554 -0
- dcscope/gui/quick_view/__init__.py +1 -0
- dcscope/gui/quick_view/qv_main.py +1072 -0
- dcscope/gui/quick_view/qv_main.ui +1297 -0
- dcscope/gui/quick_view/qv_scatter.py +284 -0
- dcscope/gui/quick_view/qv_style.css +10 -0
- dcscope/gui/update.py +90 -0
- dcscope/gui/widgets/__init__.py +15 -0
- dcscope/gui/widgets/bg_thread.py +29 -0
- dcscope/gui/widgets/bulk_list.py +79 -0
- dcscope/gui/widgets/bulk_list.ui +95 -0
- dcscope/gui/widgets/double_spin_box_nan.py +75 -0
- dcscope/gui/widgets/feature_combobox.py +140 -0
- dcscope/gui/widgets/get_path.py +42 -0
- dcscope/gui/widgets/key_value_table_widget.css +12 -0
- dcscope/gui/widgets/key_value_table_widget.py +75 -0
- dcscope/gui/widgets/mdi_subwindow_wo_close.py +12 -0
- dcscope/gui/widgets/qrangeslider.py +262 -0
- dcscope/gui/widgets/rangecontrol.py +308 -0
- dcscope/gui/widgets/rangecontrol.ui +136 -0
- dcscope/gui/widgets/simple_image_view.py +55 -0
- dcscope/gui/widgets/simple_plot_widget.py +113 -0
- dcscope/gui/widgets/so_colorbaritem.py +29 -0
- dcscope/gui/widgets/wait_cursor.py +33 -0
- dcscope/idiom.py +26 -0
- dcscope/img/__init__.py +2 -0
- dcscope/img/icon-theme/breeze/COPYING-ICONS +209 -0
- dcscope/img/icon-theme/breeze/COPYING.LIB +510 -0
- dcscope/img/icon-theme/breeze/README +5 -0
- dcscope/img/icon-theme/breeze/actions/16/application-exit.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/16/code-context.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/dialog-cancel.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/dialog-close.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/16/dialog-messages.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/dialog-ok-apply.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/dialog-ok.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/document-open-folder.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/document-open.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/document-save.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/documentinfo.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/16/draw-watercolor.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/edit-clear-all.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/edit-clear.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/edit-paste.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/globe.svg +16 -0
- dcscope/img/icon-theme/breeze/actions/16/gtk-preferences.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/list-add.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/messagebox_warning.svg +20 -0
- dcscope/img/icon-theme/breeze/actions/16/object-columns.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/object-order-lower.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/object-rows.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/office-chart-line-stacked.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/office-chart-ring.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/office-chart-scatter.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/path-mode-polyline.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/preferences-activities.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/remove.svg +10 -0
- dcscope/img/icon-theme/breeze/actions/16/search.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/show-grid.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/special_paste.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/tools-wizard.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/view-calendar-list.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/view-filter.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/view-list-tree.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/view-statistics.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/16/visibility.svg +21 -0
- dcscope/img/icon-theme/breeze/actions/22/application-exit.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/22/code-context.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/dialog-cancel.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/dialog-close.svg +10 -0
- dcscope/img/icon-theme/breeze/actions/22/dialog-messages.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/dialog-ok-apply.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/dialog-ok.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/document-open-folder.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/document-open.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/document-save.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/documentinfo.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/draw-watercolor.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/edit-clear-all.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/edit-clear.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/edit-paste.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/globe.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/22/gtk-preferences.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/22/list-add.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/messagebox_warning.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/object-columns.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/object-order-lower.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/object-rows.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/office-chart-line-stacked.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/office-chart-ring.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/office-chart-scatter.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/path-mode-polyline.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/22/preferences-activities.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/remove.svg +10 -0
- dcscope/img/icon-theme/breeze/actions/22/special_paste.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/tools-wizard.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/view-calendar-list.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/view-filter.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/view-list-tree.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/view-statistics.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/22/visibility.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/24/application-exit.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/code-context.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/dialog-cancel.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/dialog-close.svg +10 -0
- dcscope/img/icon-theme/breeze/actions/24/dialog-messages.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/dialog-ok-apply.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/dialog-ok.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/24/document-open-folder.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/document-open.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/document-save.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/documentinfo.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/24/draw-watercolor.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/edit-clear-all.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/24/edit-clear.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/edit-paste.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/globe.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/24/gtk-preferences.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/24/list-add.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/messagebox_warning.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/24/object-columns.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/object-order-lower.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/object-rows.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/office-chart-line-stacked.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/office-chart-ring.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/office-chart-scatter.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/path-mode-polyline.svg +15 -0
- dcscope/img/icon-theme/breeze/actions/24/preferences-activities.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/24/remove.svg +10 -0
- dcscope/img/icon-theme/breeze/actions/24/special_paste.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/tools-wizard.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/view-calendar-list.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/view-filter.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/view-list-tree.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/view-statistics.svg +12 -0
- dcscope/img/icon-theme/breeze/actions/24/visibility.svg +14 -0
- dcscope/img/icon-theme/breeze/actions/32/application-exit.svg +8 -0
- dcscope/img/icon-theme/breeze/actions/32/dialog-cancel.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/32/dialog-messages.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/32/dialog-ok-apply.svg +1 -0
- dcscope/img/icon-theme/breeze/actions/32/dialog-ok.svg +1 -0
- dcscope/img/icon-theme/breeze/actions/32/document-open-folder.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/32/document-open.svg +13 -0
- dcscope/img/icon-theme/breeze/actions/32/document-save.svg +18 -0
- dcscope/img/icon-theme/breeze/actions/32/gtk-preferences.svg +17 -0
- dcscope/img/icon-theme/breeze/actions/32/object-order-lower.svg +18 -0
- dcscope/img/icon-theme/breeze/actions/32/view-filter.svg +18 -0
- dcscope/img/icon-theme/breeze/actions/32/view-list-tree.svg +18 -0
- dcscope/img/icon-theme/breeze/places/16/folder-cloud.svg +13 -0
- dcscope/img/icon-theme/breeze/places/16/folder.svg +13 -0
- dcscope/img/icon-theme/breeze/places/22/folder-cloud.svg +13 -0
- dcscope/img/icon-theme/breeze/places/22/folder.svg +13 -0
- dcscope/img/icon-theme/breeze/places/24/folder-cloud.svg +12 -0
- dcscope/img/icon-theme/breeze/places/24/folder.svg +12 -0
- dcscope/img/icon-theme/breeze/places/32/folder-cloud.svg +35 -0
- dcscope/img/icon-theme/breeze/places/32/folder.svg +30 -0
- dcscope/img/icon-theme/breeze/places/64/folder-cloud.svg +35 -0
- dcscope/img/icon-theme/breeze/places/64/folder.svg +30 -0
- dcscope/img/icon-theme/breeze/status/16/dialog-error.svg +9 -0
- dcscope/img/icon-theme/breeze/status/16/dialog-information.svg +9 -0
- dcscope/img/icon-theme/breeze/status/16/dialog-question.svg +7 -0
- dcscope/img/icon-theme/breeze/status/16/dialog-warning.svg +9 -0
- dcscope/img/icon-theme/breeze/status/22/dialog-error.svg +9 -0
- dcscope/img/icon-theme/breeze/status/22/dialog-information.svg +9 -0
- dcscope/img/icon-theme/breeze/status/22/dialog-question.svg +7 -0
- dcscope/img/icon-theme/breeze/status/22/dialog-warning.svg +9 -0
- dcscope/img/icon-theme/breeze/status/24/dialog-error.svg +13 -0
- dcscope/img/icon-theme/breeze/status/24/dialog-information.svg +13 -0
- dcscope/img/icon-theme/breeze/status/24/dialog-question.svg +9 -0
- dcscope/img/icon-theme/breeze/status/24/dialog-warning.svg +1 -0
- dcscope/img/icon-theme/breeze/status/64/dialog-error.svg +25 -0
- dcscope/img/icon-theme/breeze/status/64/dialog-information.svg +25 -0
- dcscope/img/icon-theme/breeze/status/64/dialog-question.svg +25 -0
- dcscope/img/icon-theme/breeze/status/64/dialog-warning.svg +25 -0
- dcscope/img/icon-theme/collect_icons.py +124 -0
- dcscope/img/icon-theme/dcscope/dcor.png +0 -0
- dcscope/img/icon-theme/dcscope/edit-copy-anew.svg +13 -0
- dcscope/img/icon-theme/dcscope/emodulus.svg +69 -0
- dcscope/img/icon-theme/dcscope/filter_ray.svg +54 -0
- dcscope/img/icon-theme/dcscope/region_channel.svg +86 -0
- dcscope/img/icon-theme/dcscope/region_reservoir.svg +89 -0
- dcscope/img/icon-theme/dcscope/rlang.svg +108 -0
- dcscope/img/icon-theme/dcscope/statistical_significance.svg +106 -0
- dcscope/img/icon-theme/index.theme +81 -0
- dcscope/img/icon.png +0 -0
- dcscope/img/icon.svg +73 -0
- dcscope/img/splash.png +0 -0
- dcscope/meta_tool.py +143 -0
- dcscope/pipeline/__init__.py +5 -0
- dcscope/pipeline/core.py +632 -0
- dcscope/pipeline/dataslot.py +270 -0
- dcscope/pipeline/filter.py +161 -0
- dcscope/pipeline/filter_ray.py +170 -0
- dcscope/pipeline/plot.py +187 -0
- dcscope/plot_cache.py +79 -0
- dcscope/session.py +379 -0
- dcscope/util.py +34 -0
- dcscope-2.22.1.dist-info/METADATA +95 -0
- dcscope-2.22.1.dist-info/RECORD +267 -0
- dcscope-2.22.1.dist-info/WHEEL +5 -0
- dcscope-2.22.1.dist-info/entry_points.txt +2 -0
- dcscope-2.22.1.dist-info/licenses/LICENSE +621 -0
- dcscope-2.22.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import dclab
|
|
2
|
+
from PyQt6 import QtCore, QtGui, QtWidgets
|
|
3
|
+
|
|
4
|
+
#: These are features only visible in developer mode
|
|
5
|
+
HIDDEN_FEATURES = []
|
|
6
|
+
for ii in range(10):
|
|
7
|
+
HIDDEN_FEATURES.append(f"basinmap{ii}")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FeatureComboBox(QtWidgets.QComboBox):
|
|
11
|
+
def __init__(self, *args, **kwargs):
|
|
12
|
+
"""A DC data aware combobox for displaying DC features
|
|
13
|
+
|
|
14
|
+
The combobox uses different colors do indicate the
|
|
15
|
+
availability of features. Features can be ancillary,
|
|
16
|
+
innate, basin-based, etc.
|
|
17
|
+
|
|
18
|
+
This class serves as a drop-in replacement for QComboBox
|
|
19
|
+
with a few special properties:
|
|
20
|
+
|
|
21
|
+
- Call `set_dataset` with an instance of RTDCBase and the
|
|
22
|
+
list of options is automatically populated with the values
|
|
23
|
+
for this dataset, including coloring based on feature origin.
|
|
24
|
+
- Features defined in :const:`HIDDEN_FEATURES` are not shown in
|
|
25
|
+
the combobox if "advanced/developer mode" is not set in the
|
|
26
|
+
settings.
|
|
27
|
+
- Make sure to use `findData` and don't rely on any external
|
|
28
|
+
lists when using `addItem`, because some of the items may
|
|
29
|
+
not be added as explained in the previous point.
|
|
30
|
+
"""
|
|
31
|
+
super(FeatureComboBox, self).__init__(*args, **kwargs)
|
|
32
|
+
self.rtdc_ds = None
|
|
33
|
+
self.default_choices = []
|
|
34
|
+
|
|
35
|
+
# determine whether we should hide certain features
|
|
36
|
+
settings = QtCore.QSettings()
|
|
37
|
+
devmode = bool(int(settings.value("advanced/developer mode", 0)))
|
|
38
|
+
self.hidden_feats = HIDDEN_FEATURES if not devmode else []
|
|
39
|
+
|
|
40
|
+
# where the data at
|
|
41
|
+
self.data_role = QtCore.Qt.ItemDataRole.UserRole
|
|
42
|
+
|
|
43
|
+
# Set background color to white
|
|
44
|
+
pal = self.palette()
|
|
45
|
+
pal.setColor(self.backgroundRole(), QtGui.QColor(255, 255, 255))
|
|
46
|
+
|
|
47
|
+
def addItem(self, text, userData=None):
|
|
48
|
+
if userData not in self.hidden_feats:
|
|
49
|
+
super(FeatureComboBox, self).addItem(text, userData)
|
|
50
|
+
|
|
51
|
+
def currentData(self, role=None):
|
|
52
|
+
if role is None:
|
|
53
|
+
role = self.data_role
|
|
54
|
+
return super(FeatureComboBox, self).currentData(role)
|
|
55
|
+
|
|
56
|
+
def findData(self, data, role=None, *args, **kwargs):
|
|
57
|
+
if role is None:
|
|
58
|
+
role = self.data_role
|
|
59
|
+
return super(FeatureComboBox, self).findData(data, role=role,
|
|
60
|
+
*args, **kwargs)
|
|
61
|
+
|
|
62
|
+
def set_dataset(self, rtdc_ds):
|
|
63
|
+
self.rtdc_ds = rtdc_ds
|
|
64
|
+
self.update_feature_list()
|
|
65
|
+
|
|
66
|
+
@QtCore.pyqtSlot()
|
|
67
|
+
def update_feature_list(self):
|
|
68
|
+
"""Update the colors of all features in the combobox"""
|
|
69
|
+
if self.rtdc_ds is None:
|
|
70
|
+
raise ValueError("Please call `set_dataset` first!")
|
|
71
|
+
# axes combobox choices
|
|
72
|
+
ds_feats = self.rtdc_ds.features_scalar
|
|
73
|
+
# remove hidden features
|
|
74
|
+
[ds_feats.remove(f) for f in self.hidden_feats if f in ds_feats]
|
|
75
|
+
ds_labels = [dclab.dfn.get_feature_label(f) for f in ds_feats]
|
|
76
|
+
ds_colors = []
|
|
77
|
+
ds_tips = []
|
|
78
|
+
feats_loaded = self.rtdc_ds.features_loaded
|
|
79
|
+
feats_ancillary = self.rtdc_ds.features_ancillary
|
|
80
|
+
feats_basin = self.rtdc_ds.features_basin
|
|
81
|
+
for feat in ds_feats:
|
|
82
|
+
if feat in feats_loaded:
|
|
83
|
+
ds_colors.append("#D2FFC8")
|
|
84
|
+
ds_tips.append("feature data loaded")
|
|
85
|
+
elif feat in feats_basin:
|
|
86
|
+
ds_colors.append("#C0E8FF")
|
|
87
|
+
ds_tips.append("feature data located in basin")
|
|
88
|
+
elif feat in feats_ancillary:
|
|
89
|
+
ds_colors.append("#FFD9C1")
|
|
90
|
+
ds_tips.append("feature data needs to be computed")
|
|
91
|
+
else:
|
|
92
|
+
# fall-back
|
|
93
|
+
ds_colors.append("#A9A9A9")
|
|
94
|
+
ds_tips.append("unknown location of feature data")
|
|
95
|
+
|
|
96
|
+
ds_fl = sorted(zip(ds_labels, ds_feats, ds_colors, ds_tips))
|
|
97
|
+
|
|
98
|
+
# Remember current index. If it is -1, we can select a best feature
|
|
99
|
+
# based on self.default_choices in the end.
|
|
100
|
+
idx_cur = self.currentIndex()
|
|
101
|
+
|
|
102
|
+
# Remember user selection. If it exists in ds_feats, the selection
|
|
103
|
+
# will persist even if the user switches the dataset.
|
|
104
|
+
feat_cur = self.currentData(self.data_role)
|
|
105
|
+
|
|
106
|
+
blocked = self.signalsBlocked() # remember block state
|
|
107
|
+
self.blockSignals(True)
|
|
108
|
+
|
|
109
|
+
# set features
|
|
110
|
+
self.clear()
|
|
111
|
+
model = self.model()
|
|
112
|
+
for (label, feat, color, tip) in ds_fl:
|
|
113
|
+
item = QtGui.QStandardItem(label)
|
|
114
|
+
item.setData(feat, self.data_role)
|
|
115
|
+
item.setBackground(QtGui.QColor(color))
|
|
116
|
+
item.setForeground(QtGui.QColor("black"))
|
|
117
|
+
item.setToolTip(tip)
|
|
118
|
+
model.appendRow(item)
|
|
119
|
+
|
|
120
|
+
if feat_cur and feat_cur in ds_feats:
|
|
121
|
+
# If the previous selection exists in the new feature list, set it.
|
|
122
|
+
idx_cur = self.findData(feat_cur)
|
|
123
|
+
else:
|
|
124
|
+
# If the previous selection does not exist in the new feature list,
|
|
125
|
+
# select the first available feature in `default_choices`
|
|
126
|
+
idx_cur = -1
|
|
127
|
+
|
|
128
|
+
if idx_cur < 0:
|
|
129
|
+
# If no selection made by user, select the first available feature
|
|
130
|
+
# in `default_choices`
|
|
131
|
+
for choice in self.default_choices:
|
|
132
|
+
idx_choice = self.findData(choice)
|
|
133
|
+
if idx_choice >= 0:
|
|
134
|
+
idx_cur = idx_choice
|
|
135
|
+
break
|
|
136
|
+
|
|
137
|
+
self.setCurrentIndex(idx_cur)
|
|
138
|
+
|
|
139
|
+
# set previous selection
|
|
140
|
+
self.blockSignals(blocked)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import pathlib
|
|
2
|
+
|
|
3
|
+
from PyQt6 import QtCore, QtWidgets
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_directory(
|
|
7
|
+
parent: QtWidgets.QWidget,
|
|
8
|
+
identifier: str,
|
|
9
|
+
caption: str = "Select directory",
|
|
10
|
+
force_dialog: bool = True,
|
|
11
|
+
):
|
|
12
|
+
"""Retrieve the path for a given identifier
|
|
13
|
+
|
|
14
|
+
When called for the first time, a directory dialog is opened and
|
|
15
|
+
the user can select the target directory. The directory is then stored
|
|
16
|
+
in the settings.
|
|
17
|
+
When called for the second time, a dialog will only pop up when
|
|
18
|
+
`show_dialog` is set to `True`, otherwise the value from the settings
|
|
19
|
+
is returned.
|
|
20
|
+
"""
|
|
21
|
+
path = "" # default value
|
|
22
|
+
settings = QtCore.QSettings()
|
|
23
|
+
if not force_dialog:
|
|
24
|
+
# attempt to get the directory from the settings
|
|
25
|
+
dir_settings = settings.value(f"paths/{identifier}", path)
|
|
26
|
+
if dir_settings and pathlib.Path(dir_settings).exists():
|
|
27
|
+
path = dir_settings
|
|
28
|
+
else:
|
|
29
|
+
# we *have* to ask the user for the directory
|
|
30
|
+
force_dialog = True
|
|
31
|
+
|
|
32
|
+
if force_dialog:
|
|
33
|
+
dir_user = QtWidgets.QFileDialog.getExistingDirectory(
|
|
34
|
+
parent=parent,
|
|
35
|
+
caption=caption,
|
|
36
|
+
directory=settings.value(f"paths/{identifier}", path)
|
|
37
|
+
)
|
|
38
|
+
if dir_user:
|
|
39
|
+
path = dir_user
|
|
40
|
+
settings.setValue(f"paths/{identifier}", path)
|
|
41
|
+
|
|
42
|
+
return path
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import pathlib
|
|
2
|
+
import importlib.resources
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
from PyQt6 import QtCore, QtWidgets
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class KeyValueTableWidget(QtWidgets.QTableWidget):
|
|
9
|
+
def __init__(self, *args, **kwargs):
|
|
10
|
+
"""A table widgets with two columns for key-value visualization"""
|
|
11
|
+
super(KeyValueTableWidget, self).__init__(*args, **kwargs)
|
|
12
|
+
ref = importlib.resources.files(
|
|
13
|
+
"dcscope.gui.widgets") / "key_value_table_widget.css"
|
|
14
|
+
with importlib.resources.as_file(ref) as path_css:
|
|
15
|
+
stylesheet = pathlib.Path(path_css).read_text()
|
|
16
|
+
self.setStyleSheet(stylesheet)
|
|
17
|
+
self.horizontalHeader().hide()
|
|
18
|
+
self.verticalHeader().hide()
|
|
19
|
+
self.setAlternatingRowColors(True)
|
|
20
|
+
self.setSelectionMode(
|
|
21
|
+
QtWidgets.QAbstractItemView.SelectionMode.NoSelection)
|
|
22
|
+
# For some reason this does not work here.
|
|
23
|
+
# self.setColumnCount(2)
|
|
24
|
+
# header = self.horizontalHeader()
|
|
25
|
+
# header.setSectionResizeMode(0,
|
|
26
|
+
# QtWidgets.QHeaderView.ResizeToContents)
|
|
27
|
+
# header.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
|
|
28
|
+
|
|
29
|
+
def set_key_vals(self, keys, vals, max_key_len=23):
|
|
30
|
+
"""Convenience function for setting key-value pairs in this table"""
|
|
31
|
+
# disable updates
|
|
32
|
+
self.setUpdatesEnabled(False)
|
|
33
|
+
# rows'n'cols
|
|
34
|
+
self.setRowCount(len(keys))
|
|
35
|
+
self.setColumnCount(2)
|
|
36
|
+
# populate
|
|
37
|
+
for ii, (hi, vi) in enumerate(zip(keys, vals)):
|
|
38
|
+
# name
|
|
39
|
+
if len(hi) < max_key_len:
|
|
40
|
+
name_vis = hi
|
|
41
|
+
else:
|
|
42
|
+
name_vis = hi[:max_key_len-3] + "..."
|
|
43
|
+
# pad with spaces (b/c css padding caused overlap)
|
|
44
|
+
name_vis = " " + name_vis + " "
|
|
45
|
+
label_name = self.item(ii, 0)
|
|
46
|
+
if label_name is None:
|
|
47
|
+
label_name = QtWidgets.QTableWidgetItem(name_vis)
|
|
48
|
+
label_name.setFlags(QtCore.Qt.ItemFlag.ItemIsEnabled)
|
|
49
|
+
self.setItem(ii, 0, label_name)
|
|
50
|
+
else:
|
|
51
|
+
if label_name.text() != name_vis:
|
|
52
|
+
label_name.setText(name_vis)
|
|
53
|
+
label_name.setToolTip(hi)
|
|
54
|
+
# value
|
|
55
|
+
if np.isnan(vi) or np.isinf(vi):
|
|
56
|
+
fmt = "{}"
|
|
57
|
+
else:
|
|
58
|
+
fmt = "{:.7g}"
|
|
59
|
+
value_vis = fmt.format(vi)
|
|
60
|
+
label_value = self.item(ii, 1)
|
|
61
|
+
if label_value is None:
|
|
62
|
+
label_value = QtWidgets.QTableWidgetItem(value_vis)
|
|
63
|
+
label_value.setFlags(QtCore.Qt.ItemFlag.ItemIsEnabled)
|
|
64
|
+
self.setItem(ii, 1, label_value)
|
|
65
|
+
else:
|
|
66
|
+
label_value.setText(value_vis)
|
|
67
|
+
label_value.setToolTip(hi)
|
|
68
|
+
# spacing (did not work in __init__)
|
|
69
|
+
header = self.horizontalHeader()
|
|
70
|
+
header.setSectionResizeMode(
|
|
71
|
+
0, QtWidgets.QHeaderView.ResizeMode.ResizeToContents)
|
|
72
|
+
header.setSectionResizeMode(1,
|
|
73
|
+
QtWidgets.QHeaderView.ResizeMode.Stretch)
|
|
74
|
+
# enable updates again
|
|
75
|
+
self.setUpdatesEnabled(True)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from PyQt6 import QtCore, QtWidgets
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class MDISubWindowWOButtons(QtWidgets.QMdiSubWindow):
|
|
5
|
+
def __init__(self, *args, **kwargs):
|
|
6
|
+
super(MDISubWindowWOButtons, self).__init__(*args, **kwargs)
|
|
7
|
+
self.setSystemMenu(None)
|
|
8
|
+
self.setWindowFlags(QtCore.Qt.WindowType.CustomizeWindowHint
|
|
9
|
+
| QtCore.Qt.WindowType.WindowTitleHint)
|
|
10
|
+
|
|
11
|
+
def closeEvent(self, event):
|
|
12
|
+
event.ignore()
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
from PyQt6 import QtCore, QtGui, QtWidgets
|
|
2
|
+
|
|
3
|
+
DEFAULT_CSS = """
|
|
4
|
+
QRangeSlider * {
|
|
5
|
+
border: 0px;
|
|
6
|
+
padding: 0px;
|
|
7
|
+
}
|
|
8
|
+
QRangeSlider #Head {
|
|
9
|
+
background: #cef;
|
|
10
|
+
}
|
|
11
|
+
QRangeSlider #Span {
|
|
12
|
+
background: #16f;
|
|
13
|
+
}
|
|
14
|
+
QRangeSlider #Span:active {
|
|
15
|
+
background: #05f;
|
|
16
|
+
}
|
|
17
|
+
QRangeSlider #Tail {
|
|
18
|
+
background: #cef;
|
|
19
|
+
}
|
|
20
|
+
QRangeSlider > QSplitter::handle {
|
|
21
|
+
background: #08f;
|
|
22
|
+
}
|
|
23
|
+
QRangeSlider > QSplitter::handle:vertical {
|
|
24
|
+
height: 3px;
|
|
25
|
+
}
|
|
26
|
+
QRangeSlider > QSplitter::handle:pressed {
|
|
27
|
+
background: #0cf;
|
|
28
|
+
}
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def scale(val, src, dst):
|
|
33
|
+
ret = ((val - src[0]) / float(src[1]-src[0])) * (dst[1]-dst[0]) + dst[0]
|
|
34
|
+
return int(ret)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Ui_Form(object):
|
|
38
|
+
def setupUi(self, Form):
|
|
39
|
+
Form.setObjectName("QRangeSlider")
|
|
40
|
+
Form.setStyleSheet(DEFAULT_CSS)
|
|
41
|
+
self.gridLayout = QtWidgets.QGridLayout(Form)
|
|
42
|
+
self.gridLayout.setContentsMargins(0, 0, 0, 0)
|
|
43
|
+
self.gridLayout.setSpacing(0)
|
|
44
|
+
self.gridLayout.setObjectName("gridLayout")
|
|
45
|
+
self._splitter = QtWidgets.QSplitter(Form)
|
|
46
|
+
self._splitter.setMinimumSize(QtCore.QSize(0, 0))
|
|
47
|
+
self._splitter.setMaximumSize(QtCore.QSize(16777215, 16777215))
|
|
48
|
+
self._splitter.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
|
49
|
+
self._splitter.setObjectName("splitter")
|
|
50
|
+
self._head = QtWidgets.QGroupBox(self._splitter)
|
|
51
|
+
self._head.setTitle("")
|
|
52
|
+
self._head.setObjectName("Head")
|
|
53
|
+
self._handle = QtWidgets.QGroupBox(self._splitter)
|
|
54
|
+
self._handle.setTitle("")
|
|
55
|
+
self._handle.setObjectName("Span")
|
|
56
|
+
self._tail = QtWidgets.QGroupBox(self._splitter)
|
|
57
|
+
self._tail.setTitle("")
|
|
58
|
+
self._tail.setObjectName("Tail")
|
|
59
|
+
self.gridLayout.addWidget(self._splitter, 0, 0, 1, 1)
|
|
60
|
+
self.retranslateUi(Form)
|
|
61
|
+
QtCore.QMetaObject.connectSlotsByName(Form)
|
|
62
|
+
|
|
63
|
+
def retranslateUi(self, Form):
|
|
64
|
+
_translate = QtCore.QCoreApplication.translate
|
|
65
|
+
Form.setWindowTitle(_translate("QRangeSlider", "QRangeSlider"))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Element(QtWidgets.QGroupBox):
|
|
69
|
+
def __init__(self, parent, main, *args, **kwargs):
|
|
70
|
+
super(Element, self).__init__(parent, *args, **kwargs)
|
|
71
|
+
self.main = main
|
|
72
|
+
|
|
73
|
+
def setStyleSheet(self, style):
|
|
74
|
+
self.parent().setStyleSheet(style)
|
|
75
|
+
|
|
76
|
+
def textColor(self):
|
|
77
|
+
return getattr(self, '__textColor', QtGui.QColor(125, 125, 125))
|
|
78
|
+
|
|
79
|
+
def setTextColor(self, color):
|
|
80
|
+
if type(color) is tuple and len(color) == 3:
|
|
81
|
+
color = QtGui.QColor(color[0], color[1], color[2])
|
|
82
|
+
elif type(color) is int:
|
|
83
|
+
color = QtGui.QColor(color, color, color)
|
|
84
|
+
setattr(self, '__textColor', color)
|
|
85
|
+
|
|
86
|
+
def paintEvent(self, event):
|
|
87
|
+
qp = QtGui.QPainter()
|
|
88
|
+
qp.begin(self)
|
|
89
|
+
if self.main.drawValues():
|
|
90
|
+
self.drawText(event, qp)
|
|
91
|
+
qp.end()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class Head(Element):
|
|
95
|
+
def __init__(self, parent, main, *args, **kwargs):
|
|
96
|
+
super(Head, self).__init__(parent, main, *args, **kwargs)
|
|
97
|
+
|
|
98
|
+
def drawText(self, event, qp):
|
|
99
|
+
qp.setPen(self.textColor())
|
|
100
|
+
qp.setFont(QtGui.QFont('Arial', 10))
|
|
101
|
+
qp.drawText(event.rect(), QtCore.Qt.AlignmentFlag.AlignLeft,
|
|
102
|
+
str(self.main.min()))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class Tail(Element):
|
|
106
|
+
def __init__(self, parent, main, *args, **kwargs):
|
|
107
|
+
super(Tail, self).__init__(parent, main, *args, **kwargs)
|
|
108
|
+
|
|
109
|
+
def drawText(self, event, qp):
|
|
110
|
+
qp.setPen(self.textColor())
|
|
111
|
+
qp.setFont(QtGui.QFont('Arial', 10))
|
|
112
|
+
qp.drawText(event.rect(), QtCore.Qt.AlignmentFlag.AlignRight,
|
|
113
|
+
str(self.main.max()))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class Handle(Element):
|
|
117
|
+
def __init__(self, parent, main, *args, **kwargs):
|
|
118
|
+
super(Handle, self).__init__(parent, main, *args, **kwargs)
|
|
119
|
+
|
|
120
|
+
def drawText(self, event, qp):
|
|
121
|
+
qp.setPen(self.textColor())
|
|
122
|
+
qp.setFont(QtGui.QFont('Arial', 10))
|
|
123
|
+
qp.drawText(event.rect(), QtCore.Qt.AlignmentFlag.AlignLeft,
|
|
124
|
+
str(self.main.start()))
|
|
125
|
+
qp.drawText(event.rect(), QtCore.Qt.AlignmentFlag.AlignRight,
|
|
126
|
+
str(self.main.end()))
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class QRangeSlider(QtWidgets.QWidget, Ui_Form):
|
|
130
|
+
minValueChanged = QtCore.pyqtSignal(int)
|
|
131
|
+
maxValueChanged = QtCore.pyqtSignal(int)
|
|
132
|
+
startValueChanged = QtCore.pyqtSignal(int)
|
|
133
|
+
endValueChanged = QtCore.pyqtSignal(int)
|
|
134
|
+
rangeChanged = QtCore.pyqtSignal(int, int)
|
|
135
|
+
|
|
136
|
+
_INT_NUM = 2000
|
|
137
|
+
_SPLIT_START = 1
|
|
138
|
+
_SPLIT_END = 2
|
|
139
|
+
|
|
140
|
+
def __init__(self, parent=None, *args, **kwargs):
|
|
141
|
+
super(QRangeSlider, self).__init__(parent, *args, **kwargs)
|
|
142
|
+
self.setupUi(self)
|
|
143
|
+
self.setFixedHeight(21)
|
|
144
|
+
self.setMouseTracking(False)
|
|
145
|
+
self._splitter.splitterMoved.connect(self._handleMoveSplitter)
|
|
146
|
+
self._head_layout = QtWidgets.QHBoxLayout()
|
|
147
|
+
self._head_layout.setSpacing(0)
|
|
148
|
+
self._head_layout.setContentsMargins(0, 0, 0, 0)
|
|
149
|
+
self._head.setLayout(self._head_layout)
|
|
150
|
+
self.head = Head(self._head, main=self)
|
|
151
|
+
self._head_layout.addWidget(self.head)
|
|
152
|
+
self._handle_layout = QtWidgets.QHBoxLayout()
|
|
153
|
+
self._handle_layout.setSpacing(0)
|
|
154
|
+
self._handle_layout.setContentsMargins(0, 0, 0, 0)
|
|
155
|
+
self._handle.setLayout(self._handle_layout)
|
|
156
|
+
self.handle = Handle(self._handle, main=self)
|
|
157
|
+
self._handle_layout.addWidget(self.handle)
|
|
158
|
+
self._tail_layout = QtWidgets.QHBoxLayout()
|
|
159
|
+
self._tail_layout.setSpacing(0)
|
|
160
|
+
self._tail_layout.setContentsMargins(0, 0, 0, 0)
|
|
161
|
+
self._tail.setLayout(self._tail_layout)
|
|
162
|
+
self.tail = Tail(self._tail, main=self)
|
|
163
|
+
self._tail_layout.addWidget(self.tail)
|
|
164
|
+
# set limits
|
|
165
|
+
self.setMin(0)
|
|
166
|
+
self.setMax(self._INT_NUM)
|
|
167
|
+
self.setStart(0)
|
|
168
|
+
self.setEnd(self._INT_NUM)
|
|
169
|
+
self.setDrawValues(False)
|
|
170
|
+
|
|
171
|
+
@QtCore.pyqtSlot(object)
|
|
172
|
+
def resizeEvent(self, event):
|
|
173
|
+
# The geometry changed and `self.width` is different now. Adjust
|
|
174
|
+
# the entire range slider to reflect the new values.
|
|
175
|
+
self.setStart(self.start())
|
|
176
|
+
self.setEnd(self.end())
|
|
177
|
+
super(QRangeSlider, self).resizeEvent(event)
|
|
178
|
+
|
|
179
|
+
def min(self):
|
|
180
|
+
return getattr(self, '__min', None)
|
|
181
|
+
|
|
182
|
+
def max(self):
|
|
183
|
+
return getattr(self, '__max', None)
|
|
184
|
+
|
|
185
|
+
def setMin(self, value):
|
|
186
|
+
setattr(self, '__min', value)
|
|
187
|
+
self.minValueChanged.emit(value)
|
|
188
|
+
|
|
189
|
+
def setMax(self, value):
|
|
190
|
+
setattr(self, '__max', value)
|
|
191
|
+
self.maxValueChanged.emit(value)
|
|
192
|
+
|
|
193
|
+
def start(self):
|
|
194
|
+
return getattr(self, '__start', None)
|
|
195
|
+
|
|
196
|
+
def end(self):
|
|
197
|
+
return getattr(self, '__end', None)
|
|
198
|
+
|
|
199
|
+
def _setStart(self, value):
|
|
200
|
+
setattr(self, '__start', value)
|
|
201
|
+
self.startValueChanged.emit(value)
|
|
202
|
+
self.rangeChanged.emit(value, self.end())
|
|
203
|
+
|
|
204
|
+
def setStart(self, value):
|
|
205
|
+
v = self._valueToPos(value)
|
|
206
|
+
self._splitter.splitterMoved.disconnect()
|
|
207
|
+
self._splitter.moveSplitter(v, self._SPLIT_START)
|
|
208
|
+
self._splitter.refresh()
|
|
209
|
+
self._splitter.splitterMoved.connect(self._handleMoveSplitter)
|
|
210
|
+
self._setStart(value)
|
|
211
|
+
|
|
212
|
+
def _setEnd(self, value):
|
|
213
|
+
setattr(self, '__end', value)
|
|
214
|
+
self.endValueChanged.emit(value)
|
|
215
|
+
self.rangeChanged.emit(self.start(), value)
|
|
216
|
+
|
|
217
|
+
def setEnd(self, value):
|
|
218
|
+
v = self._valueToPos(value)
|
|
219
|
+
self._splitter.splitterMoved.disconnect()
|
|
220
|
+
self._splitter.moveSplitter(v, self._SPLIT_END)
|
|
221
|
+
self._splitter.refresh()
|
|
222
|
+
self._splitter.splitterMoved.connect(self._handleMoveSplitter)
|
|
223
|
+
self._setEnd(value)
|
|
224
|
+
|
|
225
|
+
def drawValues(self):
|
|
226
|
+
return getattr(self, '__drawValues', None)
|
|
227
|
+
|
|
228
|
+
def setDrawValues(self, draw):
|
|
229
|
+
setattr(self, '__drawValues', draw)
|
|
230
|
+
|
|
231
|
+
def getRange(self):
|
|
232
|
+
return self.start(), self.end()
|
|
233
|
+
|
|
234
|
+
def setRange(self, start, end):
|
|
235
|
+
self.setStart(start)
|
|
236
|
+
self.setEnd(end)
|
|
237
|
+
|
|
238
|
+
def setBackgroundStyle(self, style):
|
|
239
|
+
self._tail.setStyleSheet(style)
|
|
240
|
+
self._head.setStyleSheet(style)
|
|
241
|
+
|
|
242
|
+
def setSpanStyle(self, style):
|
|
243
|
+
self._handle.setStyleSheet(style)
|
|
244
|
+
|
|
245
|
+
def _valueToPos(self, value):
|
|
246
|
+
return scale(value, (self.min(), self.max()), (0, self.width()))
|
|
247
|
+
|
|
248
|
+
def _posToValue(self, xpos):
|
|
249
|
+
return scale(xpos, (0, self.width()), (self.min(), self.max()))
|
|
250
|
+
|
|
251
|
+
def _handleMoveSplitter(self, xpos, index):
|
|
252
|
+
hw = self._splitter.handleWidth()
|
|
253
|
+
if index == self._SPLIT_START:
|
|
254
|
+
v = self._posToValue(xpos)
|
|
255
|
+
if v >= self.end():
|
|
256
|
+
self.setEnd(self._INT_NUM)
|
|
257
|
+
self._setStart(v)
|
|
258
|
+
elif index == self._SPLIT_END:
|
|
259
|
+
v = self._posToValue(xpos + hw)
|
|
260
|
+
if v <= self.start():
|
|
261
|
+
self.setStart(0)
|
|
262
|
+
self._setEnd(v)
|