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.
Files changed (133) hide show
  1. pyqttoolkit/__init__.py +20 -0
  2. pyqttoolkit/_version.py +21 -0
  3. pyqttoolkit/application/__init__.py +18 -0
  4. pyqttoolkit/application/application.py +86 -0
  5. pyqttoolkit/application/garbage_collector.py +65 -0
  6. pyqttoolkit/colors/__init__.py +84 -0
  7. pyqttoolkit/config/__init__.py +20 -0
  8. pyqttoolkit/config/base.py +22 -0
  9. pyqttoolkit/config/composite.py +31 -0
  10. pyqttoolkit/config/default.py +27 -0
  11. pyqttoolkit/config/environment.py +35 -0
  12. pyqttoolkit/config/multi_json_file.py +93 -0
  13. pyqttoolkit/config/with_signal.py +30 -0
  14. pyqttoolkit/config/with_value_changed.py +31 -0
  15. pyqttoolkit/data/__init__.py +21 -0
  16. pyqttoolkit/data/bits.py +23 -0
  17. pyqttoolkit/data/cache.py +64 -0
  18. pyqttoolkit/data/interval.py +26 -0
  19. pyqttoolkit/data/message.py +29 -0
  20. pyqttoolkit/data/names.py +24 -0
  21. pyqttoolkit/datetime/__init__.py +16 -0
  22. pyqttoolkit/datetime/datetime.py +51 -0
  23. pyqttoolkit/datetime/qdatetime.py +53 -0
  24. pyqttoolkit/dependencies/__init__.py +56 -0
  25. pyqttoolkit/errors/__init__.py +19 -0
  26. pyqttoolkit/exceptions/__init__.py +18 -0
  27. pyqttoolkit/filesystem/__init__.py +24 -0
  28. pyqttoolkit/logs/__init__.py +140 -0
  29. pyqttoolkit/metadata/__init__.py +23 -0
  30. pyqttoolkit/metadata/dataframe_metadata_manager.py +105 -0
  31. pyqttoolkit/metadata/dict_metadata_manager.py +63 -0
  32. pyqttoolkit/metadata/id_generator.py +20 -0
  33. pyqttoolkit/metadata/metadata_manager_base.py +54 -0
  34. pyqttoolkit/models/__init__.py +26 -0
  35. pyqttoolkit/models/code_text.py +43 -0
  36. pyqttoolkit/models/dataframetable.py +135 -0
  37. pyqttoolkit/models/dictpropertytree.py +155 -0
  38. pyqttoolkit/models/dicttable.py +140 -0
  39. pyqttoolkit/models/json_text.py +52 -0
  40. pyqttoolkit/models/list_model.py +52 -0
  41. pyqttoolkit/models/module.py +26 -0
  42. pyqttoolkit/models/roles.py +23 -0
  43. pyqttoolkit/models/series_data.py +68 -0
  44. pyqttoolkit/models/span.py +36 -0
  45. pyqttoolkit/models/validation.py +27 -0
  46. pyqttoolkit/modules/__init__.py +18 -0
  47. pyqttoolkit/modules/events/__init__.py +19 -0
  48. pyqttoolkit/modules/events/add_signal.py +31 -0
  49. pyqttoolkit/modules/events/module_opening.py +21 -0
  50. pyqttoolkit/modules/events/rejectable.py +29 -0
  51. pyqttoolkit/modules/launcher_config.py +55 -0
  52. pyqttoolkit/modules/module.py +111 -0
  53. pyqttoolkit/properties/__init__.py +18 -0
  54. pyqttoolkit/properties/auto.py +221 -0
  55. pyqttoolkit/properties/throttled.py +77 -0
  56. pyqttoolkit/scripting/__init__.py +19 -0
  57. pyqttoolkit/scripting/script_context.py +36 -0
  58. pyqttoolkit/scripting/script_runner.py +132 -0
  59. pyqttoolkit/scripting/script_template.py +42 -0
  60. pyqttoolkit/services/__init__.py +32 -0
  61. pyqttoolkit/services/autosave.py +41 -0
  62. pyqttoolkit/services/email.py +25 -0
  63. pyqttoolkit/services/event_registry.py +52 -0
  64. pyqttoolkit/services/file_dialog.py +71 -0
  65. pyqttoolkit/services/hotkey_manager.py +137 -0
  66. pyqttoolkit/services/link_manager.py +135 -0
  67. pyqttoolkit/services/message_board.py +90 -0
  68. pyqttoolkit/services/module_service.py +154 -0
  69. pyqttoolkit/services/object_converter.py +45 -0
  70. pyqttoolkit/services/project_updater.py +149 -0
  71. pyqttoolkit/services/task_runner.py +281 -0
  72. pyqttoolkit/services/theme_manager.py +46 -0
  73. pyqttoolkit/services/tool_window_service.py +46 -0
  74. pyqttoolkit/viewmanagers/__init__.py +17 -0
  75. pyqttoolkit/viewmanagers/tool.py +23 -0
  76. pyqttoolkit/views/__init__.py +50 -0
  77. pyqttoolkit/views/bulk_value_selector.py +112 -0
  78. pyqttoolkit/views/check_box.py +36 -0
  79. pyqttoolkit/views/code/__init__.py +18 -0
  80. pyqttoolkit/views/code/code_edit.py +268 -0
  81. pyqttoolkit/views/code/python_syntax.py +226 -0
  82. pyqttoolkit/views/combo_box.py +101 -0
  83. pyqttoolkit/views/count_selector.py +59 -0
  84. pyqttoolkit/views/datetime.py +111 -0
  85. pyqttoolkit/views/datetime_range_selector.py +231 -0
  86. pyqttoolkit/views/default_text_line_edit.py +50 -0
  87. pyqttoolkit/views/delegates.py +117 -0
  88. pyqttoolkit/views/dtype_edit.py +117 -0
  89. pyqttoolkit/views/editable_combo_box.py +45 -0
  90. pyqttoolkit/views/file_selector.py +51 -0
  91. pyqttoolkit/views/icon.py +67 -0
  92. pyqttoolkit/views/icon_button.py +129 -0
  93. pyqttoolkit/views/json_edit.py +21 -0
  94. pyqttoolkit/views/labelled.py +29 -0
  95. pyqttoolkit/views/layout/__init__.py +21 -0
  96. pyqttoolkit/views/layout/collabsible.py +59 -0
  97. pyqttoolkit/views/layout/group_box.py +48 -0
  98. pyqttoolkit/views/layout/group_panel.py +188 -0
  99. pyqttoolkit/views/layout/lines.py +30 -0
  100. pyqttoolkit/views/layout/link.py +38 -0
  101. pyqttoolkit/views/line_edit.py +61 -0
  102. pyqttoolkit/views/linkable.py +49 -0
  103. pyqttoolkit/views/list_view.py +43 -0
  104. pyqttoolkit/views/main_window.py +91 -0
  105. pyqttoolkit/views/metadata_selector.py +84 -0
  106. pyqttoolkit/views/modulewindow.py +81 -0
  107. pyqttoolkit/views/plot/__init__.py +26 -0
  108. pyqttoolkit/views/plot/legend_control.py +121 -0
  109. pyqttoolkit/views/plot/matplotlib/__init__.py +23 -0
  110. pyqttoolkit/views/plot/matplotlib/base.py +1056 -0
  111. pyqttoolkit/views/plot/matplotlib/colorbar.py +75 -0
  112. pyqttoolkit/views/plot/matplotlib/colormap.py +48 -0
  113. pyqttoolkit/views/plot/matplotlib/font.py +55 -0
  114. pyqttoolkit/views/plot/plot_options.py +211 -0
  115. pyqttoolkit/views/plot/plot_toolbar_options.py +133 -0
  116. pyqttoolkit/views/plot/size.py +41 -0
  117. pyqttoolkit/views/plot/tool_type.py +26 -0
  118. pyqttoolkit/views/plot/toolbar.py +100 -0
  119. pyqttoolkit/views/popout.py +41 -0
  120. pyqttoolkit/views/popup.py +41 -0
  121. pyqttoolkit/views/property_tree.py +26 -0
  122. pyqttoolkit/views/shrunk_push_button.py +34 -0
  123. pyqttoolkit/views/steppable_combo_box.py +67 -0
  124. pyqttoolkit/views/styleable.py +37 -0
  125. pyqttoolkit/views/table.py +146 -0
  126. pyqttoolkit/views/text_edit.py +31 -0
  127. pyqttoolkit/views/tool_window.py +35 -0
  128. pyqttoolkit-0.9.1.dist-info/METADATA +69 -0
  129. pyqttoolkit-0.9.1.dist-info/RECORD +133 -0
  130. pyqttoolkit-0.9.1.dist-info/WHEEL +5 -0
  131. pyqttoolkit-0.9.1.dist-info/licenses/LICENSE.txt +674 -0
  132. pyqttoolkit-0.9.1.dist-info/licenses/LICENSE_SHORT +16 -0
  133. pyqttoolkit-0.9.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,117 @@
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 math import isnan, isfinite
18
+
19
+ from PyQt5.QtCore import pyqtSignal, Qt
20
+ from PyQt5.QtGui import QDoubleValidator
21
+
22
+ from pyqttoolkit.properties import AutoProperty
23
+ from pyqttoolkit.views import LineEdit
24
+
25
+ def _type_editor(dtype, default_value):
26
+ class _TypeEdit(LineEdit):
27
+ def __init__(self, parent):
28
+ LineEdit.__init__(self, parent)
29
+ self.setValidator(QDoubleValidator(self))
30
+ self.editComplete.connect(self._set_value)
31
+ self.valueChanged.connect(self._set_text)
32
+
33
+ valueChanged = pyqtSignal(dtype)
34
+
35
+ value = AutoProperty(dtype)
36
+
37
+ def _set_value(self, text):
38
+ try:
39
+ self.value = dtype(text)
40
+ except (TypeError, ValueError):
41
+ self.value = default_value
42
+ self._set_text(self.value)
43
+
44
+ def _set_text(self, value):
45
+ self.setText(str(value))
46
+
47
+ return _TypeEdit
48
+
49
+ FloatEdit = _type_editor(float, 0.0)
50
+ IntEdit = _type_editor(int, 0)
51
+
52
+ class InfFloatLineEdit(LineEdit):
53
+ def __init__(self, parent, formatter=None, update_on_enter_pressed=True):
54
+ LineEdit.__init__(self, parent)
55
+ self.editComplete.connect(self._handle_edit_complete)
56
+ self.valueChanged.connect(self._handle_value_changed)
57
+ self._formatter = formatter
58
+ self._update_on_enter_pressed = update_on_enter_pressed
59
+
60
+ valueChanged = pyqtSignal(float)
61
+ value = AutoProperty(float)
62
+
63
+ def _handle_edit_complete(self):
64
+ try:
65
+ self.value = float(self.text())
66
+ except ValueError:
67
+ self.setText(self._get_text(self.value))
68
+
69
+ def _handle_value_changed(self, value):
70
+ self.setText(self._get_text(value))
71
+
72
+ def _get_text(self, value):
73
+ if self._formatter is not None:
74
+ return self._formatter(value)
75
+ else:
76
+ return str(value)
77
+
78
+ def keyPressEvent(self, event):
79
+ super().keyPressEvent(event)
80
+ if event.key() in [Qt.Key_Enter, Qt.Key_Return] and self._update_on_enter_pressed:
81
+ self.valueChanged.emit(self.value)
82
+
83
+
84
+ class AutoFloatLineEdit(InfFloatLineEdit):
85
+ def __init__(self, parent, allow_inf=True, default_text=None, formatter=None, update_on_enter_pressed=True):
86
+ InfFloatLineEdit.__init__(self, parent, formatter, update_on_enter_pressed)
87
+ self._allow_inf = allow_inf
88
+ self._default_text_ = default_text or self.tr('Auto')
89
+
90
+ @property
91
+ def _default_text(self):
92
+ return self._default_text_
93
+
94
+ def _handle_edit_complete(self):
95
+ if self.text().lower() == self._default_text.lower() or not self.text():
96
+ self._reset()
97
+ else:
98
+ if not self._allow_inf:
99
+ try:
100
+ if not isfinite(float(self.text())):
101
+ self._reset()
102
+ except ValueError:
103
+ pass
104
+ InfFloatLineEdit._handle_edit_complete(self)
105
+
106
+ def _reset(self):
107
+ self.value = float('nan')
108
+ self.setText(self._default_text)
109
+
110
+ def _handle_value_changed(self, value):
111
+ if isnan(value):
112
+ self.setText(self._default_text)
113
+ else:
114
+ InfFloatLineEdit._handle_value_changed(self, value)
115
+
116
+ def setText(self, value):
117
+ InfFloatLineEdit.setText(self, self._default_text if value == 'nan' else value)
@@ -0,0 +1,45 @@
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:`editable_combo_box`
18
+ Defines the EditableComboBox class
19
+ """
20
+ #pylint: disable=no-name-in-module
21
+ from PyQt5.QtCore import QEvent
22
+ from PyQt5.QtWidgets import QComboBox
23
+ #pylint: enable=no-name-in-module
24
+
25
+ class EditableComboBox(QComboBox):
26
+ """class::EditableComboBox
27
+ A combo box that is editable by default, and adds the current item if focus is lost
28
+ """
29
+ def __init__(self, parent):
30
+ QComboBox.__init__(self, parent)
31
+ self.setEditable(True)
32
+ self.installEventFilter(self)
33
+
34
+ def eventFilter(self, _obj, event):
35
+ """function::eventFilter(self, _obj, evet)
36
+ Override the QComboBox.eventFilter method to provide lost focus functionality
37
+ """
38
+ if event.type() == QEvent.FocusOut and self.currentText():
39
+ index = self.findText(self.currentText())
40
+ if index == -1:
41
+ self.addItem(self.currentText())
42
+ index = self.findText(self.currentText())
43
+ self.setCurrentIndex(index)
44
+ self.activated.emit(index)
45
+ return QComboBox.eventFilter(self, _obj, event)
@@ -0,0 +1,51 @@
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, QLineEdit, QHBoxLayout
18
+ from PyQt5.QtCore import pyqtSignal
19
+
20
+ from pyqttoolkit.properties import auto_property
21
+
22
+ from . import ShrunkPushButton
23
+
24
+ class FileSelector(QWidget):
25
+ def __init__(self, parent, filter_, file_dialog_service):
26
+ QWidget.__init__(self, parent)
27
+ self._file_dialog_service = file_dialog_service
28
+ self._filter = filter_
29
+ self._line_edit = QLineEdit(self)
30
+ self._open_dialog = ShrunkPushButton('...', self)
31
+ self._layout = QHBoxLayout(self)
32
+ self._layout.setContentsMargins(0, 0, 0, 0)
33
+ self._layout.addWidget(self._line_edit)
34
+ self._layout.addWidget(self._open_dialog)
35
+ self._line_edit.textChanged.connect(self.textChanged)
36
+ self._open_dialog.clicked.connect(self._open_file_dialog)
37
+
38
+ textChanged = pyqtSignal(str)
39
+
40
+ @auto_property(str)
41
+ def text(self):
42
+ return self._line_edit.text()
43
+
44
+ @text.setter
45
+ def text(self, value):
46
+ self._line_edit.setText(value)
47
+
48
+ def _open_file_dialog(self):
49
+ file_name = self._file_dialog_service.get_open_filename(self, self._filter)
50
+ if file_name:
51
+ self.text = file_name
@@ -0,0 +1,67 @@
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 QHBoxLayout, QWidget
18
+ from PyQt5.QtCore import QFile, QSize, Qt
19
+ from PyQt5.QtSvg import QSvgWidget
20
+ from PyQt5.QtXml import QDomDocument
21
+
22
+ from pyqttoolkit.colors import format_color, ColorFormat
23
+ from pyqttoolkit.services.theme_manager import ThemeManager
24
+ from .styleable import make_styleable
25
+
26
+ class Icon(QWidget):
27
+ def __init__(self, parent, icon, size=None, padding=None, color=None):
28
+ QWidget.__init__(self, parent)
29
+ padding = padding or 0
30
+ self._theme_manager = ThemeManager.get(self)
31
+
32
+ self._color = format_color(color or self._theme_manager.get_color('button_foreground'), ColorFormat.rgb_string_256)
33
+
34
+ self._svgdoc = QDomDocument()
35
+ self._icon_widget = QSvgWidget(self)
36
+ self.loadIcon(icon)
37
+
38
+ if size:
39
+ self._icon_widget.setFixedSize(QSize(size.width() - 2 * padding, size.height() - 2 * padding))
40
+
41
+ self._layout = QHBoxLayout(self)
42
+ self._layout.setContentsMargins(padding, padding, padding, padding)
43
+ self._layout.addWidget(self._icon_widget, Qt.AlignCenter)
44
+
45
+ def loadIcon(self, icon):
46
+ file = QFile(f'icons:{icon}', self)
47
+ try:
48
+ file.open(QFile.ReadOnly)
49
+ self._svgdoc.setContent(file.readAll())
50
+ self._svgdoc.documentElement().setAttribute('fill', self._color)
51
+ self._icon_widget.load(self._svgdoc.toByteArray())
52
+ finally:
53
+ file.close()
54
+
55
+ def setEnabled(self, enabled):
56
+ QWidget.setEnabled(self, enabled)
57
+ self._svgdoc.documentElement().setAttribute('fill', self._color)
58
+ self._svgdoc.documentElement().setAttribute('fill-opacity', '1' if self.isEnabled() else '0.4')
59
+ self._icon_widget.load(self._svgdoc.toByteArray())
60
+
61
+ def setColor(self, color=None):
62
+ self._color = format_color(color or self._theme_manager.get_color('button_foreground'), ColorFormat.rgb_string_256) or self._color
63
+ self._svgdoc.documentElement().setAttribute('fill', self._color)
64
+ self._svgdoc.documentElement().setAttribute('fill-opacity', '1' if self.isEnabled() else '0.4')
65
+ self._icon_widget.load(self._svgdoc.toByteArray())
66
+
67
+ Icon = make_styleable(Icon)
@@ -0,0 +1,129 @@
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 QPropertyAnimation, QEasingCurve, pyqtSignal, pyqtProperty
18
+ from PyQt5.QtWidgets import QPushButton, QHBoxLayout, QSizePolicy
19
+
20
+ from pyqttoolkit.properties import AutoProperty
21
+ from pyqttoolkit.colors import format_color, ColorFormat
22
+ from pyqttoolkit.services.theme_manager import ThemeManager
23
+ from .icon import Icon
24
+
25
+ class IconButton(QPushButton):
26
+ def __init__(self, icon, title, parent, size=None, padding=None, color=None, hover_color=None):
27
+ QPushButton.__init__(self, parent)
28
+ self._theme_manager = ThemeManager.get(self)
29
+ self._background_color = hover_color or self._theme_manager.get_color('button_background_hover')
30
+ self.setToolTip(title)
31
+ self._icon = Icon(self, icon, size, padding, color)
32
+ self._iconname = icon
33
+
34
+ self._layout = QHBoxLayout(self)
35
+ self._layout.addWidget(self._icon)
36
+ self._layout.setContentsMargins(0, 0, 0, 0)
37
+ self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
38
+ self._size = size
39
+ self.setFlat(True)
40
+ self._background_opacity = 0.0
41
+ self._background_opacity_stop = 0.0
42
+ self._update_style_sheet()
43
+ self._animation = QPropertyAnimation(self, b'backgroundOpacity', self)
44
+ self.clicked.connect(self._update_background_opacity_stop)
45
+
46
+ def setColor(self, color=None):
47
+ self._icon.setColor(color)
48
+
49
+ def setIcon(self, icon):
50
+ self._icon.loadIcon(icon)
51
+
52
+ @pyqtProperty(float)
53
+ def backgroundOpacity(self):
54
+ return self._background_opacity
55
+
56
+ @backgroundOpacity.setter
57
+ def backgroundOpacity(self, value):
58
+ self._background_opacity = value
59
+ self._update_style_sheet()
60
+
61
+ def sizeHint(self):
62
+ return self._size or self._icon.sizeHint()
63
+
64
+ def enterEvent(self, event):
65
+ if self.isEnabled():
66
+ self._start_opacity_animation(350, 0, 1)
67
+ return QPushButton.enterEvent(self, event)
68
+
69
+ def leaveEvent(self, event):
70
+ if self.isEnabled():
71
+ self._start_opacity_animation(350, 1, 0)
72
+ return QPushButton.leaveEvent(self, event)
73
+
74
+ def mousePressEvent(self, event):
75
+ if self.isEnabled():
76
+ self._start_opacity_animation(50, 1, 0.6)
77
+ return QPushButton.mousePressEvent(self, event)
78
+
79
+ def mouseReleaseEvent(self, event):
80
+ if self.isEnabled():
81
+ self._start_opacity_animation(50, self._background_opacity, 1)
82
+ return QPushButton.mouseReleaseEvent(self, event)
83
+
84
+ def _start_opacity_animation(self, duration, start, end):
85
+ self._animation.stop()
86
+ self._animation.setDuration(duration)
87
+ self._animation.setStartValue(start)
88
+ self._animation.setEndValue(end)
89
+ self._animation.setEasingCurve(QEasingCurve.BezierSpline)
90
+ self._animation.start()
91
+
92
+ def setEnabled(self, value):
93
+ QPushButton.setEnabled(self, value)
94
+ self._icon.setEnabled(value)
95
+
96
+ def _update_background_opacity_stop(self):
97
+ self._background_opacity_stop = 0.0 if not self.isChecked() else 0.8
98
+ self._update_style_sheet()
99
+
100
+ def setChecked(self, value):
101
+ QPushButton.setChecked(self, value)
102
+ self._update_background_opacity_stop()
103
+
104
+ def _update_style_sheet(self):
105
+ stylesheet = """
106
+ Icon {{
107
+ background-color: {color};
108
+ border-radius: 2px;
109
+ }}
110
+ QPushButton {{
111
+ background-color: transparent;
112
+ border: none;
113
+ }}
114
+ """.format(color=format_color(self._background_color, ColorFormat.rgba_string_256, max(self._background_opacity, self._background_opacity_stop)))
115
+ self.setStyleSheet(stylesheet)
116
+
117
+
118
+ class BindableIconButton(IconButton):
119
+ def __init__(self, icon, title, parent, size=None, padding=None, color=None, hover_color=None):
120
+ IconButton.__init__(self, icon, title, parent, size, padding, color, hover_color)
121
+ self.setCheckable(True)
122
+ self.clicked.connect(self._handle_clicked)
123
+ self.checkedChanged.connect(self.setChecked)
124
+
125
+ checkedChanged = pyqtSignal(bool)
126
+ checked = AutoProperty(bool)
127
+
128
+ def _handle_clicked(self):
129
+ self.checked = self.isChecked()
@@ -0,0 +1,21 @@
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 .code import CodeEdit
18
+
19
+ class JsonEdit(CodeEdit):
20
+ def __init__(self, parent):
21
+ CodeEdit.__init__(self, parent)
@@ -0,0 +1,29 @@
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, QHBoxLayout, QLabel
18
+
19
+
20
+ def make_labelled(parent, label: str, widget: QWidget):
21
+ """Put a widget into a container with a label to the left of it. Like a single row of a `QFormLayout`"""
22
+ container = QWidget(parent)
23
+ label_widget = QLabel(label)
24
+ layout = QHBoxLayout(container)
25
+ layout.setSpacing(0)
26
+ layout.addWidget(label_widget)
27
+ layout.addWidget(widget)
28
+ layout.setContentsMargins(0, 0, 0, 0)
29
+ return container
@@ -0,0 +1,21 @@
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 .lines import HLine, VLine
18
+ from .group_panel import GroupPanelLayout, VGroupPanelLayout, HGroupPanelLayout, GroupPanelWidget, HGroupPanelWidget, VGroupPanelWidget
19
+ from .group_box import wrap_in_group_box, wrap_many_in_group_box
20
+ from .collabsible import HCollapsibleLayout, VCollapsibleLayout
21
+ from .link import LinkWidget
@@ -0,0 +1,59 @@
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 QBoxLayout, QToolButton
18
+ from PyQt5.QtCore import Qt
19
+
20
+ class CollapsibleLayout(QBoxLayout):
21
+ def __init__(self, parent, direction):
22
+ QBoxLayout.__init__(self, direction, parent)
23
+ self._index = 0
24
+ self._widgets = []
25
+
26
+ def addWidget(self, widget, group_name, expanded=True):
27
+ QBoxLayout.addWidget(self, self._create_header(group_name, expanded))
28
+ QBoxLayout.addWidget(self, widget)
29
+ self._widgets.append(widget)
30
+ widget.setVisible(expanded)
31
+ self._index += 1
32
+
33
+ def _create_header(self, name, expanded):
34
+ button = QToolButton(self.parent())
35
+ button.setStyleSheet('QToolButton { border: none; }')
36
+ button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
37
+ button.setArrowType(self._get_arrow(expanded))
38
+ button.setText(name)
39
+ button.setCheckable(True)
40
+ button.setChecked(True)
41
+ button.clicked.connect(self._handle_toggle(button, self._index))
42
+ return button
43
+
44
+ def _handle_toggle(self, button, index):
45
+ def _handler(checked):
46
+ button.setArrowType(self._get_arrow(checked))
47
+ self._widgets[index].setVisible(checked)
48
+ return _handler
49
+
50
+ def _get_arrow(self, expanded):
51
+ return Qt.DownArrow if expanded else Qt.RightArrow
52
+
53
+ class VCollapsibleLayout(CollapsibleLayout):
54
+ def __init__(self, parent):
55
+ CollapsibleLayout.__init__(self, parent, QBoxLayout.TopToBottom)
56
+
57
+ class HCollapsibleLayout(CollapsibleLayout):
58
+ def __init__(self, parent):
59
+ CollapsibleLayout.__init__(self, parent, QBoxLayout.LeftToRight)
@@ -0,0 +1,48 @@
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 QGroupBox, QGridLayout, QVBoxLayout
18
+ from PyQt5.QtCore import Qt
19
+
20
+ class LinkGroupBox(QGroupBox):
21
+ def __init__(self, name, parent, linkable_widget):
22
+ QGroupBox.__init__(self, name, parent)
23
+ self._linkable_widget = linkable_widget
24
+ if hasattr(self._linkable_widget, 'setLinkDisplay'):
25
+ self._linkable_widget.setLinkDisplay(self)
26
+
27
+ def mouseDoubleClickEvent(self, _event):
28
+ if hasattr(self._linkable_widget, 'linkRequested'):
29
+ self._linkable_widget.linkRequested()
30
+
31
+ def wrap_in_group_box(widget, parent, name, alignment=Qt.AlignTop):
32
+ group_box = LinkGroupBox(name, parent, widget)
33
+ group_box_layout = QGridLayout(group_box)
34
+ if alignment is not None:
35
+ group_box_layout.addWidget(widget, 0, 0, alignment)
36
+ else:
37
+ group_box_layout.addWidget(widget, 0, 0)
38
+ return group_box
39
+
40
+ def wrap_many_in_group_box(widgets, parent, name, alignment=Qt.AlignTop):
41
+ group_box = QGroupBox(name, parent)
42
+ group_box_layout = QVBoxLayout(group_box)
43
+ for widget in widgets:
44
+ if alignment is not None:
45
+ group_box_layout.addWidget(widget, alignment)
46
+ else:
47
+ group_box_layout.addWidget(widget)
48
+ return group_box