pyqttoolkit 0.9.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.
- pyqttoolkit/__init__.py +20 -0
- pyqttoolkit/_version.py +21 -0
- pyqttoolkit/application/__init__.py +18 -0
- pyqttoolkit/application/application.py +86 -0
- pyqttoolkit/application/garbage_collector.py +65 -0
- pyqttoolkit/colors/__init__.py +84 -0
- pyqttoolkit/config/__init__.py +20 -0
- pyqttoolkit/config/base.py +22 -0
- pyqttoolkit/config/composite.py +31 -0
- pyqttoolkit/config/default.py +27 -0
- pyqttoolkit/config/environment.py +35 -0
- pyqttoolkit/config/multi_json_file.py +93 -0
- pyqttoolkit/config/with_signal.py +30 -0
- pyqttoolkit/config/with_value_changed.py +31 -0
- pyqttoolkit/data/__init__.py +21 -0
- pyqttoolkit/data/bits.py +23 -0
- pyqttoolkit/data/cache.py +64 -0
- pyqttoolkit/data/interval.py +26 -0
- pyqttoolkit/data/message.py +29 -0
- pyqttoolkit/data/names.py +24 -0
- pyqttoolkit/datetime/__init__.py +16 -0
- pyqttoolkit/datetime/datetime.py +51 -0
- pyqttoolkit/datetime/qdatetime.py +53 -0
- pyqttoolkit/dependencies/__init__.py +56 -0
- pyqttoolkit/errors/__init__.py +19 -0
- pyqttoolkit/exceptions/__init__.py +18 -0
- pyqttoolkit/filesystem/__init__.py +24 -0
- pyqttoolkit/logs/__init__.py +140 -0
- pyqttoolkit/metadata/__init__.py +23 -0
- pyqttoolkit/metadata/dataframe_metadata_manager.py +105 -0
- pyqttoolkit/metadata/dict_metadata_manager.py +63 -0
- pyqttoolkit/metadata/id_generator.py +20 -0
- pyqttoolkit/metadata/metadata_manager_base.py +54 -0
- pyqttoolkit/models/__init__.py +26 -0
- pyqttoolkit/models/code_text.py +43 -0
- pyqttoolkit/models/dataframetable.py +135 -0
- pyqttoolkit/models/dictpropertytree.py +155 -0
- pyqttoolkit/models/dicttable.py +140 -0
- pyqttoolkit/models/json_text.py +52 -0
- pyqttoolkit/models/list_model.py +52 -0
- pyqttoolkit/models/module.py +26 -0
- pyqttoolkit/models/roles.py +23 -0
- pyqttoolkit/models/series_data.py +68 -0
- pyqttoolkit/models/span.py +36 -0
- pyqttoolkit/models/validation.py +27 -0
- pyqttoolkit/modules/__init__.py +18 -0
- pyqttoolkit/modules/events/__init__.py +19 -0
- pyqttoolkit/modules/events/add_signal.py +31 -0
- pyqttoolkit/modules/events/module_opening.py +21 -0
- pyqttoolkit/modules/events/rejectable.py +29 -0
- pyqttoolkit/modules/launcher_config.py +55 -0
- pyqttoolkit/modules/module.py +111 -0
- pyqttoolkit/properties/__init__.py +18 -0
- pyqttoolkit/properties/auto.py +221 -0
- pyqttoolkit/properties/throttled.py +77 -0
- pyqttoolkit/scripting/__init__.py +19 -0
- pyqttoolkit/scripting/script_context.py +36 -0
- pyqttoolkit/scripting/script_runner.py +132 -0
- pyqttoolkit/scripting/script_template.py +42 -0
- pyqttoolkit/services/__init__.py +32 -0
- pyqttoolkit/services/autosave.py +41 -0
- pyqttoolkit/services/email.py +25 -0
- pyqttoolkit/services/event_registry.py +52 -0
- pyqttoolkit/services/file_dialog.py +71 -0
- pyqttoolkit/services/hotkey_manager.py +137 -0
- pyqttoolkit/services/link_manager.py +135 -0
- pyqttoolkit/services/message_board.py +90 -0
- pyqttoolkit/services/module_service.py +154 -0
- pyqttoolkit/services/object_converter.py +45 -0
- pyqttoolkit/services/project_updater.py +149 -0
- pyqttoolkit/services/task_runner.py +281 -0
- pyqttoolkit/services/theme_manager.py +46 -0
- pyqttoolkit/services/tool_window_service.py +46 -0
- pyqttoolkit/viewmanagers/__init__.py +17 -0
- pyqttoolkit/viewmanagers/tool.py +23 -0
- pyqttoolkit/views/__init__.py +50 -0
- pyqttoolkit/views/bulk_value_selector.py +112 -0
- pyqttoolkit/views/check_box.py +36 -0
- pyqttoolkit/views/code/__init__.py +18 -0
- pyqttoolkit/views/code/code_edit.py +268 -0
- pyqttoolkit/views/code/python_syntax.py +226 -0
- pyqttoolkit/views/combo_box.py +101 -0
- pyqttoolkit/views/count_selector.py +59 -0
- pyqttoolkit/views/datetime.py +111 -0
- pyqttoolkit/views/datetime_range_selector.py +231 -0
- pyqttoolkit/views/default_text_line_edit.py +50 -0
- pyqttoolkit/views/delegates.py +117 -0
- pyqttoolkit/views/dtype_edit.py +117 -0
- pyqttoolkit/views/editable_combo_box.py +45 -0
- pyqttoolkit/views/file_selector.py +51 -0
- pyqttoolkit/views/icon.py +67 -0
- pyqttoolkit/views/icon_button.py +129 -0
- pyqttoolkit/views/json_edit.py +21 -0
- pyqttoolkit/views/labelled.py +29 -0
- pyqttoolkit/views/layout/__init__.py +21 -0
- pyqttoolkit/views/layout/collabsible.py +59 -0
- pyqttoolkit/views/layout/group_box.py +48 -0
- pyqttoolkit/views/layout/group_panel.py +188 -0
- pyqttoolkit/views/layout/lines.py +30 -0
- pyqttoolkit/views/layout/link.py +38 -0
- pyqttoolkit/views/line_edit.py +61 -0
- pyqttoolkit/views/linkable.py +49 -0
- pyqttoolkit/views/list_view.py +43 -0
- pyqttoolkit/views/main_window.py +91 -0
- pyqttoolkit/views/metadata_selector.py +84 -0
- pyqttoolkit/views/modulewindow.py +81 -0
- pyqttoolkit/views/plot/__init__.py +26 -0
- pyqttoolkit/views/plot/legend_control.py +121 -0
- pyqttoolkit/views/plot/matplotlib/__init__.py +23 -0
- pyqttoolkit/views/plot/matplotlib/base.py +1056 -0
- pyqttoolkit/views/plot/matplotlib/colorbar.py +75 -0
- pyqttoolkit/views/plot/matplotlib/colormap.py +48 -0
- pyqttoolkit/views/plot/matplotlib/font.py +55 -0
- pyqttoolkit/views/plot/plot_options.py +211 -0
- pyqttoolkit/views/plot/plot_toolbar_options.py +133 -0
- pyqttoolkit/views/plot/size.py +41 -0
- pyqttoolkit/views/plot/tool_type.py +26 -0
- pyqttoolkit/views/plot/toolbar.py +100 -0
- pyqttoolkit/views/popout.py +41 -0
- pyqttoolkit/views/popup.py +41 -0
- pyqttoolkit/views/property_tree.py +26 -0
- pyqttoolkit/views/shrunk_push_button.py +34 -0
- pyqttoolkit/views/steppable_combo_box.py +67 -0
- pyqttoolkit/views/styleable.py +37 -0
- pyqttoolkit/views/table.py +146 -0
- pyqttoolkit/views/text_edit.py +31 -0
- pyqttoolkit/views/tool_window.py +35 -0
- pyqttoolkit-0.9.1.dist-info/METADATA +69 -0
- pyqttoolkit-0.9.1.dist-info/RECORD +133 -0
- pyqttoolkit-0.9.1.dist-info/WHEEL +5 -0
- pyqttoolkit-0.9.1.dist-info/licenses/LICENSE.txt +674 -0
- pyqttoolkit-0.9.1.dist-info/licenses/LICENSE_SHORT +16 -0
- pyqttoolkit-0.9.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# pyqttoolkit
|
|
2
|
+
# Copyright (C) 2018-2019, Simmovation Ltd.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
16
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
+
from PyQt5.QtCore import Qt
|
|
18
|
+
from PyQt5.QtWidgets import QBoxLayout, QWidget, QVBoxLayout, QLabel, QSizePolicy
|
|
19
|
+
|
|
20
|
+
from .lines import HLine, VLine
|
|
21
|
+
from .link import LinkWidget
|
|
22
|
+
|
|
23
|
+
class GroupPanelLayout(QBoxLayout):
|
|
24
|
+
def __init__(self, parent, direction):
|
|
25
|
+
super().__init__(direction, parent)
|
|
26
|
+
self._direction = direction
|
|
27
|
+
self._separator = VLine if not self.isVertical() else HLine
|
|
28
|
+
self._grid_layouts = []
|
|
29
|
+
self._containers = []
|
|
30
|
+
self._separators = []
|
|
31
|
+
self._layouts = []
|
|
32
|
+
self._labels = []
|
|
33
|
+
self._minimum_row_height = 0
|
|
34
|
+
self._spacing = 0
|
|
35
|
+
self._label_alignment = Qt.AlignCenter
|
|
36
|
+
self._panel_direction = QBoxLayout.TopToBottom
|
|
37
|
+
self._group_alignment = None
|
|
38
|
+
|
|
39
|
+
def addWidget(self, widget, group_name):
|
|
40
|
+
if self._containers:
|
|
41
|
+
self.addSeparator()
|
|
42
|
+
container = LinkWidget(self.parent(), widget)
|
|
43
|
+
layout = QVBoxLayout(container)
|
|
44
|
+
layout.setDirection(self._panel_direction)
|
|
45
|
+
layout.setContentsMargins(self._spacing, self._spacing, self._spacing, self._spacing)
|
|
46
|
+
self.addLabel(container, layout, group_name)
|
|
47
|
+
layout.addWidget(widget)
|
|
48
|
+
group_alignment = self._group_alignment if self._group_alignment is not None else Qt.Alignment(0)
|
|
49
|
+
self._containers.append(container)
|
|
50
|
+
self._layouts.append(layout)
|
|
51
|
+
super().addWidget(container, alignment=group_alignment)
|
|
52
|
+
|
|
53
|
+
def setLabelAlignment(self, alignment):
|
|
54
|
+
self._label_alignment = alignment
|
|
55
|
+
|
|
56
|
+
def setPanelDirection(self, direction):
|
|
57
|
+
self._panel_direction = direction
|
|
58
|
+
|
|
59
|
+
def setGroupAlignment(self, alignment):
|
|
60
|
+
self._group_alignment = alignment
|
|
61
|
+
|
|
62
|
+
def isVertical(self):
|
|
63
|
+
return self._direction in (QBoxLayout.TopToBottom, QBoxLayout.BottomToTop)
|
|
64
|
+
|
|
65
|
+
def addSeparator(self):
|
|
66
|
+
self._separators.append(self._separator(self.parent()))
|
|
67
|
+
super().addWidget(self._separators[-1])
|
|
68
|
+
|
|
69
|
+
def addLabel(self, parent, layout, name):
|
|
70
|
+
label = QLabel(name, parent)
|
|
71
|
+
label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
72
|
+
layout.addWidget(label, alignment=self._label_alignment)
|
|
73
|
+
self._labels.append(label)
|
|
74
|
+
|
|
75
|
+
def addStretch(self, stretch):
|
|
76
|
+
super().addStretch(stretch)
|
|
77
|
+
|
|
78
|
+
def setContentsMargins(self, left, top, right, bottom):
|
|
79
|
+
super().setContentsMargins(left, top, right, bottom)
|
|
80
|
+
|
|
81
|
+
def setSpacing(self, spacing):
|
|
82
|
+
self._spacing = spacing
|
|
83
|
+
|
|
84
|
+
def count(self):
|
|
85
|
+
return super().count()
|
|
86
|
+
|
|
87
|
+
def sizeHint(self):
|
|
88
|
+
return super().sizeHint()
|
|
89
|
+
|
|
90
|
+
def setGeometry(self, rect):
|
|
91
|
+
super().setGeometry(rect)
|
|
92
|
+
|
|
93
|
+
def itemAt(self, index):
|
|
94
|
+
return super().itemAt(index)
|
|
95
|
+
|
|
96
|
+
def takeAt(self, index):
|
|
97
|
+
return super().takeAt(index)
|
|
98
|
+
|
|
99
|
+
def minimumSize(self):
|
|
100
|
+
return super().minimumSize()
|
|
101
|
+
|
|
102
|
+
def hasHeightForWidth(self):
|
|
103
|
+
return super().hasHeightForWidth()
|
|
104
|
+
|
|
105
|
+
def heightForWidth(self, width):
|
|
106
|
+
return super().heightForWidth(width)
|
|
107
|
+
|
|
108
|
+
def update(self):
|
|
109
|
+
return super().update()
|
|
110
|
+
|
|
111
|
+
class HGroupPanelLayout(GroupPanelLayout):
|
|
112
|
+
def __init__(self, parent):
|
|
113
|
+
super().__init__(parent, QBoxLayout.LeftToRight)
|
|
114
|
+
|
|
115
|
+
class VGroupPanelLayout(GroupPanelLayout):
|
|
116
|
+
def __init__(self, parent):
|
|
117
|
+
super().__init__(parent, QBoxLayout.TopToBottom)
|
|
118
|
+
|
|
119
|
+
class GroupPanelWidget(QWidget):
|
|
120
|
+
def __init__(self, parent, direction):
|
|
121
|
+
super().__init__(parent)
|
|
122
|
+
self._layout = QBoxLayout(direction, self)
|
|
123
|
+
self._layout.setContentsMargins(0, 0, 0, 0)
|
|
124
|
+
self._direction = direction
|
|
125
|
+
self._separator = VLine if direction == QBoxLayout.LeftToRight else HLine
|
|
126
|
+
self._grid_layouts = []
|
|
127
|
+
self._containers = []
|
|
128
|
+
self._separators = []
|
|
129
|
+
self._layouts = []
|
|
130
|
+
self._labels = []
|
|
131
|
+
self._minimum_row_height = 0
|
|
132
|
+
self._spacing = 0
|
|
133
|
+
self._label_alignment = Qt.AlignCenter
|
|
134
|
+
self._panel_direction = QBoxLayout.TopToBottom
|
|
135
|
+
self._group_alignment = None
|
|
136
|
+
|
|
137
|
+
def addWidget(self, widget, group_name):
|
|
138
|
+
if self._containers:
|
|
139
|
+
self.addSeparator()
|
|
140
|
+
container = LinkWidget(self, widget)
|
|
141
|
+
layout = QVBoxLayout(container)
|
|
142
|
+
layout.setDirection(self._panel_direction)
|
|
143
|
+
layout.setContentsMargins(self._spacing, self._spacing, self._spacing, self._spacing)
|
|
144
|
+
self.addLabel(container, layout, group_name)
|
|
145
|
+
layout.addWidget(widget)
|
|
146
|
+
group_alignment = self._group_alignment if self._group_alignment is not None else Qt.Alignment(0)
|
|
147
|
+
self._containers.append(container)
|
|
148
|
+
self._layouts.append(layout)
|
|
149
|
+
self._layout.addWidget(container, alignment=group_alignment)
|
|
150
|
+
|
|
151
|
+
def setLabelAlignment(self, alignment):
|
|
152
|
+
self._label_alignment = alignment
|
|
153
|
+
|
|
154
|
+
def setPanelDirection(self, direction):
|
|
155
|
+
self._panel_direction = direction
|
|
156
|
+
|
|
157
|
+
def setGroupAlignment(self, alignment):
|
|
158
|
+
self._group_alignment = alignment
|
|
159
|
+
|
|
160
|
+
def isVertical(self):
|
|
161
|
+
return self._direction in (QBoxLayout.TopToBottom, QBoxLayout.BottomToTop)
|
|
162
|
+
|
|
163
|
+
def addSeparator(self):
|
|
164
|
+
self._separators.append(self._separator(self))
|
|
165
|
+
self._layout.addWidget(self._separators[-1])
|
|
166
|
+
|
|
167
|
+
def addLabel(self, parent, layout, name):
|
|
168
|
+
label = QLabel(name, parent)
|
|
169
|
+
label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
170
|
+
layout.addWidget(label, alignment=self._label_alignment)
|
|
171
|
+
self._labels.append(label)
|
|
172
|
+
|
|
173
|
+
def addStretch(self, stretch):
|
|
174
|
+
self._layout.addStretch(stretch)
|
|
175
|
+
|
|
176
|
+
def setContentsMargins(self, left, top, right, bottom):
|
|
177
|
+
self._layout.setContentsMargins(left, top, right, bottom)
|
|
178
|
+
|
|
179
|
+
def setSpacing(self, spacing):
|
|
180
|
+
self._spacing = spacing
|
|
181
|
+
|
|
182
|
+
class HGroupPanelWidget(GroupPanelWidget):
|
|
183
|
+
def __init__(self, parent):
|
|
184
|
+
super().__init__(parent, QBoxLayout.LeftToRight)
|
|
185
|
+
|
|
186
|
+
class VGroupPanelWidget(GroupPanelWidget):
|
|
187
|
+
def __init__(self, parent):
|
|
188
|
+
super().__init__(parent, QBoxLayout.TopToBottom)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# pyqttoolkit
|
|
2
|
+
# Copyright (C) 2018-2019, Simmovation Ltd.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
16
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
+
from PyQt5.QtWidgets import QFrame
|
|
18
|
+
|
|
19
|
+
class HLine(QFrame):
|
|
20
|
+
def __init__(self, parent):
|
|
21
|
+
QFrame.__init__(self, parent)
|
|
22
|
+
self.setFrameShape(QFrame.HLine)
|
|
23
|
+
self.setFrameShadow(QFrame.Sunken)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class VLine(QFrame):
|
|
27
|
+
def __init__(self, parent):
|
|
28
|
+
QFrame.__init__(self, parent)
|
|
29
|
+
self.setFrameShape(QFrame.VLine)
|
|
30
|
+
self.setFrameShadow(QFrame.Sunken)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# pyqttoolkit
|
|
2
|
+
# Copyright (C) 2018-2019, Simmovation Ltd.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
16
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
+
from PyQt5.QtWidgets import QWidget
|
|
18
|
+
|
|
19
|
+
class LinkWidget(QWidget):
|
|
20
|
+
def __init__(self, parent, linkable_widget):
|
|
21
|
+
super().__init__(parent)
|
|
22
|
+
self._linkable_widget = linkable_widget
|
|
23
|
+
if hasattr(self._linkable_widget, 'setLinkDisplay'):
|
|
24
|
+
self._linkable_widget.setLinkDisplay(self)
|
|
25
|
+
|
|
26
|
+
def mouseDoubleClickEvent(self, _event):
|
|
27
|
+
self.linkRequested()
|
|
28
|
+
|
|
29
|
+
def contextMenuEvent(self, event):
|
|
30
|
+
return self._linkable_widget.contextMenuEvent(event)
|
|
31
|
+
|
|
32
|
+
def setLinkDisplay(self, widget):
|
|
33
|
+
if hasattr(self._linkable_widget, 'setLinkDisplay'):
|
|
34
|
+
self._linkable_widget.setLinkDisplay(widget)
|
|
35
|
+
|
|
36
|
+
def linkRequested(self):
|
|
37
|
+
if hasattr(self._linkable_widget, 'linkRequested'):
|
|
38
|
+
self._linkable_widget.linkRequested()
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# pyqttoolkit
|
|
2
|
+
# Copyright (C) 2018-2019, Simmovation Ltd.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
16
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
+
from PyQt5.QtCore import pyqtSignal, Qt
|
|
18
|
+
from PyQt5.QtWidgets import QLineEdit
|
|
19
|
+
|
|
20
|
+
from pyqttoolkit.properties import AutoProperty
|
|
21
|
+
from pyqttoolkit.views.styleable import make_styleable
|
|
22
|
+
|
|
23
|
+
class LineEdit(QLineEdit):
|
|
24
|
+
def __init__(self, parent):
|
|
25
|
+
QLineEdit.__init__(self, parent)
|
|
26
|
+
self.focusLost.connect(self._on_edit_complete)
|
|
27
|
+
self.enterPressed.connect(self._on_edit_complete)
|
|
28
|
+
|
|
29
|
+
focusLost = pyqtSignal()
|
|
30
|
+
enterPressed = pyqtSignal()
|
|
31
|
+
editComplete = pyqtSignal(str)
|
|
32
|
+
|
|
33
|
+
def focusOutEvent(self, event):
|
|
34
|
+
self.focusLost.emit()
|
|
35
|
+
QLineEdit.focusOutEvent(self, event)
|
|
36
|
+
|
|
37
|
+
def keyPressEvent(self, event):
|
|
38
|
+
if event.key() in [Qt.Key_Enter, Qt.Key_Return]:
|
|
39
|
+
self.enterPressed.emit()
|
|
40
|
+
QLineEdit.keyPressEvent(self, event)
|
|
41
|
+
|
|
42
|
+
def _on_edit_complete(self):
|
|
43
|
+
self.editComplete.emit(self.text())
|
|
44
|
+
|
|
45
|
+
class BindableLineEdit(LineEdit):
|
|
46
|
+
def __init__(self, parent):
|
|
47
|
+
LineEdit.__init__(self, parent)
|
|
48
|
+
self.editComplete.connect(self._update_value)
|
|
49
|
+
self.valueChanged.connect(self._handle_value_changed)
|
|
50
|
+
|
|
51
|
+
valueChanged = pyqtSignal(str)
|
|
52
|
+
|
|
53
|
+
value = AutoProperty(str)
|
|
54
|
+
|
|
55
|
+
def _update_value(self, value):
|
|
56
|
+
self.value = value
|
|
57
|
+
|
|
58
|
+
def _handle_value_changed(self, value):
|
|
59
|
+
self.setText(value)
|
|
60
|
+
|
|
61
|
+
BindableLineEdit = make_styleable(BindableLineEdit)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# pyqttoolkit
|
|
2
|
+
# Copyright (C) 2018-2019, Simmovation Ltd.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
16
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
+
from PyQt5.QtWidgets import QWidget
|
|
18
|
+
|
|
19
|
+
class LinkableWidget(QWidget):
|
|
20
|
+
def __init__(self, parent, link_manager=None, link_type=None):
|
|
21
|
+
QWidget.__init__(self, parent)
|
|
22
|
+
self._link_display = None
|
|
23
|
+
self._link_manager = link_manager
|
|
24
|
+
self._link_type = link_type
|
|
25
|
+
|
|
26
|
+
def linkDisplay(self):
|
|
27
|
+
return self._link_display or self
|
|
28
|
+
|
|
29
|
+
def setLinkDisplay(self, value):
|
|
30
|
+
self._link_display = value
|
|
31
|
+
|
|
32
|
+
def mouseDoubleClickEvent(self, _event):
|
|
33
|
+
self.linkRequested()
|
|
34
|
+
|
|
35
|
+
def linkRequested(self):
|
|
36
|
+
if self._link_manager is not None:
|
|
37
|
+
self._link_manager.request_link(self)
|
|
38
|
+
|
|
39
|
+
def link(self, other):
|
|
40
|
+
raise NotImplementedError()
|
|
41
|
+
|
|
42
|
+
def unlink(self, other):
|
|
43
|
+
raise NotImplementedError()
|
|
44
|
+
|
|
45
|
+
def linkType(self):
|
|
46
|
+
return self._link_type
|
|
47
|
+
|
|
48
|
+
def setLinkType(self, value):
|
|
49
|
+
self._link_type = value
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# pyqttoolkit
|
|
2
|
+
# Copyright (C) 2018-2019, Simmovation Ltd.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
16
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
+
from PyQt5.QtWidgets import QListView
|
|
18
|
+
from PyQt5.QtCore import pyqtSignal
|
|
19
|
+
|
|
20
|
+
from pyqttoolkit.properties import AutoProperty
|
|
21
|
+
|
|
22
|
+
class ListView(QListView):
|
|
23
|
+
def __init__(self, parent):
|
|
24
|
+
QListView.__init__(self, parent)
|
|
25
|
+
self.selectedIndexChanged.connect(self._handle_selected_index_changed)
|
|
26
|
+
self._updating_selection = False
|
|
27
|
+
|
|
28
|
+
selectedItemsChanged = pyqtSignal()
|
|
29
|
+
selectedIndexChanged = pyqtSignal(int)
|
|
30
|
+
|
|
31
|
+
selectedIndex = AutoProperty(int)
|
|
32
|
+
|
|
33
|
+
def selectionChanged(self, current_selection, previous_selection):
|
|
34
|
+
self._updating_selection = True
|
|
35
|
+
result = QListView.selectionChanged(self, current_selection, previous_selection)
|
|
36
|
+
self.selectedIndex = current_selection.indexes()[0].row() if current_selection.indexes() else -1
|
|
37
|
+
self.selectedItemsChanged.emit()
|
|
38
|
+
self._updating_selection = False
|
|
39
|
+
return result
|
|
40
|
+
|
|
41
|
+
def _handle_selected_index_changed(self, index):
|
|
42
|
+
if self.model() is not None and not self._updating_selection:
|
|
43
|
+
self.setCurrentIndex(self.model().createIndex(index, 0))
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# pyqttoolkit
|
|
2
|
+
# Copyright (C) 2018-2019, Simmovation Ltd.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
16
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
+
|
|
18
|
+
from PyQt5.QtWidgets import QMainWindow, QStyleOption, QStyle
|
|
19
|
+
from PyQt5.QtGui import QPainter
|
|
20
|
+
|
|
21
|
+
from pyqttoolkit.colors import format_color
|
|
22
|
+
|
|
23
|
+
class MainWindow(QMainWindow):
|
|
24
|
+
def __init__(self, parent, theme_manager):
|
|
25
|
+
QMainWindow.__init__(self, parent)
|
|
26
|
+
self._theme_manager = theme_manager
|
|
27
|
+
self.setStyleSheet(self._get_stylesheet())
|
|
28
|
+
self._painter = None
|
|
29
|
+
self._opt = QStyleOption()
|
|
30
|
+
|
|
31
|
+
def paintEvent(self, _event):
|
|
32
|
+
self._opt.initFrom(self)
|
|
33
|
+
self._painter = QPainter(self)
|
|
34
|
+
self.style().drawPrimitive(QStyle.PE_Widget, self._opt, self._painter, self)
|
|
35
|
+
self._painter.end()
|
|
36
|
+
return super().paintEvent(_event)
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def themeManager(self):
|
|
40
|
+
return self._theme_manager
|
|
41
|
+
|
|
42
|
+
def _get_stylesheet(self):
|
|
43
|
+
color = lambda k: format_color(self._theme_manager.get_color(k))
|
|
44
|
+
color_a = lambda k, a: format_color(self._theme_manager.get_color(k), opacity=a)
|
|
45
|
+
return f"""
|
|
46
|
+
QMainWindow, QDialog {{
|
|
47
|
+
background-color: {color('module_background')};
|
|
48
|
+
}}
|
|
49
|
+
|
|
50
|
+
QLabel, QCheckBox, QGroupBox {{
|
|
51
|
+
color: {color('module_text')}
|
|
52
|
+
}}
|
|
53
|
+
QLabel:disabled, QCheckBox:disabled, QGroupBox:disabled, QPushButton:disabled {{
|
|
54
|
+
color: {color_a('module_text', 0.6)};
|
|
55
|
+
}}
|
|
56
|
+
|
|
57
|
+
QPushButton:disabled {{
|
|
58
|
+
background-color:#ccc;
|
|
59
|
+
border: 1px solid {color_a('module_text', 0.6)};
|
|
60
|
+
}}
|
|
61
|
+
|
|
62
|
+
QPushButton {{
|
|
63
|
+
color: #333;
|
|
64
|
+
border: 1px solid #555;
|
|
65
|
+
padding: 3px;
|
|
66
|
+
background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 #fff, stop: 1 #888);
|
|
67
|
+
}}
|
|
68
|
+
|
|
69
|
+
QPushButton[class=highlight] {{
|
|
70
|
+
color: #333;
|
|
71
|
+
border: 1px solid #555;
|
|
72
|
+
padding: 3px;
|
|
73
|
+
background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 #fff, stop: 1 {color('highlight')});
|
|
74
|
+
}}
|
|
75
|
+
|
|
76
|
+
QPushButton:hover {{
|
|
77
|
+
background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 #fff, stop: 1 #bbb);
|
|
78
|
+
}}
|
|
79
|
+
|
|
80
|
+
QPushButton:hover[class=highlight] {{
|
|
81
|
+
background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 #fff, stop: 1 {color('highlight_hover')});
|
|
82
|
+
}}
|
|
83
|
+
|
|
84
|
+
QPushButton:pressed {{
|
|
85
|
+
background: qradialgradient(cx: 0.4, cy: -0.1, fx: 0.4, fy: -0.1, radius: 1.35, stop: 0 #fff, stop: 1 #ddd);
|
|
86
|
+
}}
|
|
87
|
+
|
|
88
|
+
QPushButton:pressed[class=highlight] {{
|
|
89
|
+
background: qradialgradient(cx: 0.4, cy: -0.1, fx: 0.4, fy: -0.1, radius: 1.35, stop: 0 #fff, stop: 1 {color('highlight_pressed')});
|
|
90
|
+
}}
|
|
91
|
+
"""
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# pyqttoolkit
|
|
2
|
+
# Copyright (C) 2018-2019, Simmovation Ltd.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
16
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
+
from PyQt5.QtWidgets import QWidget, QGridLayout, QSizePolicy, QHBoxLayout
|
|
18
|
+
from PyQt5.QtCore import pyqtSignal, QSize
|
|
19
|
+
|
|
20
|
+
from pyqttoolkit.models.roles import DataRole
|
|
21
|
+
from pyqttoolkit.views import ComboBox
|
|
22
|
+
from pyqttoolkit.properties import AutoProperty, bind
|
|
23
|
+
from .icon_button import IconButton
|
|
24
|
+
|
|
25
|
+
class MetadataSelectorDropDown(QWidget):
|
|
26
|
+
def __init__(self, parent):
|
|
27
|
+
QWidget.__init__(self, parent)
|
|
28
|
+
|
|
29
|
+
self._drop_down = ComboBox(self)
|
|
30
|
+
self._drop_down.currentIndexChanged.connect(self._update_current)
|
|
31
|
+
|
|
32
|
+
self._layout = QGridLayout(self)
|
|
33
|
+
self._layout.setContentsMargins(0, 0, 0, 0)
|
|
34
|
+
self._layout.addWidget(self._drop_down)
|
|
35
|
+
|
|
36
|
+
self.selectedIdChanged.connect(self._handle_selected_id_changed)
|
|
37
|
+
self.selectedId = None
|
|
38
|
+
|
|
39
|
+
selectedIdChanged = pyqtSignal(str)
|
|
40
|
+
|
|
41
|
+
selectedId = AutoProperty(str)
|
|
42
|
+
|
|
43
|
+
def setModel(self, model):
|
|
44
|
+
self._drop_down.setModel(model)
|
|
45
|
+
model.dataChanged.connect(self._handle_selected_id_changed)
|
|
46
|
+
|
|
47
|
+
def _update_current(self, index):
|
|
48
|
+
model_index = self._drop_down.model().createIndex(index, 0)
|
|
49
|
+
self.selectedId = self._drop_down.model().data(model_index, DataRole)
|
|
50
|
+
|
|
51
|
+
def _handle_selected_id_changed(self):
|
|
52
|
+
model = self._drop_down.model()
|
|
53
|
+
for i in range(model.rowCount()):
|
|
54
|
+
model_index = model.createIndex(i, 0)
|
|
55
|
+
if model.data(model_index, DataRole) == self.selectedId:
|
|
56
|
+
self._drop_down.setCurrentIndex(i)
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
class MetadataSelector(QWidget):
|
|
60
|
+
def __init__(self, parent):
|
|
61
|
+
QWidget.__init__(self, parent)
|
|
62
|
+
|
|
63
|
+
self._drop_down = MetadataSelectorDropDown(self)
|
|
64
|
+
self._drop_down.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
65
|
+
self._add_item = IconButton('plus.svg', self.tr('Add Item'), self, QSize(20, 20), 2)
|
|
66
|
+
self._add_item.clicked.connect(self.addItemSelected)
|
|
67
|
+
|
|
68
|
+
self._layout = QHBoxLayout(self)
|
|
69
|
+
self._layout.setContentsMargins(0, 0, 0, 0)
|
|
70
|
+
self._layout.addWidget(self._drop_down)
|
|
71
|
+
self._layout.addWidget(self._add_item)
|
|
72
|
+
|
|
73
|
+
bind(self, self._drop_down, 'selectedId')
|
|
74
|
+
|
|
75
|
+
selectedIdChanged = pyqtSignal(str)
|
|
76
|
+
addItemSelected = pyqtSignal()
|
|
77
|
+
|
|
78
|
+
selectedId = AutoProperty(str)
|
|
79
|
+
|
|
80
|
+
def setModel(self, model):
|
|
81
|
+
self._drop_down.setModel(model)
|
|
82
|
+
|
|
83
|
+
def setSelectorEnabled(self, enabled):
|
|
84
|
+
self._drop_down.setEnabled(enabled)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# pyqttoolkit
|
|
2
|
+
# Copyright (C) 2018-2019, Simmovation Ltd.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, write to the Free Software Foundation,
|
|
16
|
+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
+
""":mod:`modulewindow`
|
|
18
|
+
Module window widget
|
|
19
|
+
"""
|
|
20
|
+
from uuid import uuid4
|
|
21
|
+
|
|
22
|
+
from PyQt5.QtCore import pyqtSignal
|
|
23
|
+
|
|
24
|
+
from pyqttoolkit.modules.events import RejectableEvent
|
|
25
|
+
|
|
26
|
+
from .main_window import MainWindow
|
|
27
|
+
|
|
28
|
+
class ModuleWindow(MainWindow):
|
|
29
|
+
"""class::ModuleWindow
|
|
30
|
+
Class for use with QWidget-based modules
|
|
31
|
+
"""
|
|
32
|
+
def __init__(self, theme_manager, title=None, singleton: bool = False):
|
|
33
|
+
MainWindow.__init__(self, None, theme_manager)
|
|
34
|
+
self._id = uuid4()
|
|
35
|
+
self._theme_manager = theme_manager
|
|
36
|
+
self._singleton = singleton
|
|
37
|
+
self._force = not singleton
|
|
38
|
+
if title:
|
|
39
|
+
self.setWindowTitle(title)
|
|
40
|
+
|
|
41
|
+
closing = pyqtSignal(str)
|
|
42
|
+
|
|
43
|
+
def setModuleView(self, module_view):
|
|
44
|
+
"""function::setModuleView(self, module_view)
|
|
45
|
+
Sets the module view (central widget)
|
|
46
|
+
"""
|
|
47
|
+
self.setCentralWidget(module_view)
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def moduleId(self):
|
|
51
|
+
"""function::id(self)
|
|
52
|
+
Returns the id for this module window
|
|
53
|
+
"""
|
|
54
|
+
return str(self._id)
|
|
55
|
+
|
|
56
|
+
def closeEvent(self, event):
|
|
57
|
+
"""function::closeEvent(self, event)
|
|
58
|
+
Decorates the base class with a closing event
|
|
59
|
+
"""
|
|
60
|
+
if self._singleton and not self._force:
|
|
61
|
+
event.ignore()
|
|
62
|
+
self.hide()
|
|
63
|
+
return
|
|
64
|
+
if hasattr(self.centralWidget(), 'prepareClose'):
|
|
65
|
+
close_event = RejectableEvent()
|
|
66
|
+
self.centralWidget().prepareClose(close_event)
|
|
67
|
+
if not close_event.accepted:
|
|
68
|
+
event.ignore()
|
|
69
|
+
return
|
|
70
|
+
MainWindow.closeEvent(self, event)
|
|
71
|
+
if event.isAccepted():
|
|
72
|
+
self.centralWidget().close()
|
|
73
|
+
self.closing.emit(self.moduleId)
|
|
74
|
+
|
|
75
|
+
def forceClose(self):
|
|
76
|
+
self._force = True
|
|
77
|
+
return self.close()
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def themeManager(self):
|
|
81
|
+
return self._theme_manager
|