myokit 1.33.9__py3-none-any.whl → 1.35.0__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 (229) hide show
  1. myokit/__init__.py +9 -36
  2. myokit/__main__.py +76 -142
  3. myokit/_aux.py +62 -16
  4. myokit/_bin/example.mmt +1 -2
  5. myokit/_bin/install-win/menu.json +7 -7
  6. myokit/_config.py +22 -31
  7. myokit/_datablock.py +30 -74
  8. myokit/_datalog.py +49 -72
  9. myokit/_err.py +25 -24
  10. myokit/_expressions.py +50 -68
  11. myokit/_io.py +15 -27
  12. myokit/_model_api.py +453 -249
  13. myokit/_myokit_version.py +1 -5
  14. myokit/_parsing.py +38 -44
  15. myokit/_progress.py +5 -8
  16. myokit/_protocol.py +99 -9
  17. myokit/_sim/__init__.py +7 -24
  18. myokit/_sim/cable.c +6 -8
  19. myokit/_sim/cable.py +6 -8
  20. myokit/_sim/cmodel.h +125 -70
  21. myokit/_sim/cmodel.py +12 -14
  22. myokit/_sim/compiler.py +1 -4
  23. myokit/_sim/cvodessim.c +196 -118
  24. myokit/_sim/cvodessim.py +130 -103
  25. myokit/_sim/differential.hpp +4 -4
  26. myokit/_sim/fiber_tissue.c +4 -8
  27. myokit/_sim/fiber_tissue.py +11 -13
  28. myokit/_sim/jacobian.cpp +2 -2
  29. myokit/_sim/jacobian.py +11 -8
  30. myokit/_sim/mcl.h +53 -55
  31. myokit/_sim/opencl.py +21 -27
  32. myokit/_sim/openclsim.c +3 -7
  33. myokit/_sim/openclsim.cl +3 -3
  34. myokit/_sim/openclsim.py +49 -40
  35. myokit/_sim/pacing.h +36 -16
  36. myokit/_sim/rhs.c +6 -13
  37. myokit/_sim/rhs.py +5 -14
  38. myokit/_sim/sundials.py +1 -4
  39. myokit/_system.py +10 -16
  40. myokit/_unit.py +4 -13
  41. myokit/float.py +0 -3
  42. myokit/formats/__init__.py +8 -10
  43. myokit/formats/ansic/__init__.py +0 -3
  44. myokit/formats/ansic/_ewriter.py +2 -4
  45. myokit/formats/ansic/_exporter.py +1 -4
  46. myokit/formats/ansic/template/cable.c +4 -4
  47. myokit/formats/ansic/template/euler.c +5 -5
  48. myokit/formats/ansic/template/sim.c +6 -6
  49. myokit/formats/axon/__init__.py +1 -3
  50. myokit/formats/axon/_abf.py +12 -17
  51. myokit/formats/axon/_atf.py +5 -6
  52. myokit/formats/axon/_importer.py +0 -3
  53. myokit/formats/cellml/__init__.py +0 -3
  54. myokit/formats/cellml/_ewriter.py +3 -6
  55. myokit/formats/cellml/_exporter.py +3 -6
  56. myokit/formats/cellml/_importer.py +1 -4
  57. myokit/formats/cellml/v1/__init__.py +0 -4
  58. myokit/formats/cellml/v1/_api.py +8 -11
  59. myokit/formats/cellml/v1/_parser.py +2 -5
  60. myokit/formats/cellml/v1/_writer.py +2 -11
  61. myokit/formats/cellml/v2/__init__.py +0 -3
  62. myokit/formats/cellml/v2/_api.py +8 -17
  63. myokit/formats/cellml/v2/_parser.py +2 -5
  64. myokit/formats/cellml/v2/_writer.py +1 -4
  65. myokit/formats/channelml/__init__.py +0 -3
  66. myokit/formats/channelml/_importer.py +11 -21
  67. myokit/formats/cpp/__init__.py +1 -3
  68. myokit/formats/cpp/_ewriter.py +0 -3
  69. myokit/formats/cuda/__init__.py +0 -3
  70. myokit/formats/cuda/_ewriter.py +2 -4
  71. myokit/formats/cuda/_exporter.py +0 -3
  72. myokit/formats/cuda/template/kernel.cu +8 -5
  73. myokit/formats/easyml/__init__.py +0 -3
  74. myokit/formats/easyml/_ewriter.py +9 -11
  75. myokit/formats/easyml/_exporter.py +2 -5
  76. myokit/formats/html/__init__.py +0 -3
  77. myokit/formats/html/_exporter.py +0 -3
  78. myokit/formats/html/_flatten.py +5 -21
  79. myokit/formats/latex/__init__.py +0 -3
  80. myokit/formats/latex/_ewriter.py +1 -4
  81. myokit/formats/latex/_exporter.py +4 -6
  82. myokit/formats/mathml/__init__.py +0 -3
  83. myokit/formats/mathml/_ewriter.py +2 -11
  84. myokit/formats/mathml/_parser.py +4 -6
  85. myokit/formats/matlab/__init__.py +0 -3
  86. myokit/formats/matlab/_ewriter.py +1 -4
  87. myokit/formats/matlab/_exporter.py +2 -5
  88. myokit/formats/matlab/template/main.m +3 -2
  89. myokit/formats/opencl/__init__.py +0 -3
  90. myokit/formats/opencl/_ewriter.py +2 -4
  91. myokit/formats/opencl/_exporter.py +2 -5
  92. myokit/formats/opencl/template/cable.c +10 -10
  93. myokit/formats/opencl/template/kernel.cl +1 -1
  94. myokit/formats/opencl/template/minilog.py +1 -1
  95. myokit/formats/python/__init__.py +0 -3
  96. myokit/formats/python/_ewriter.py +2 -5
  97. myokit/formats/python/_exporter.py +0 -3
  98. myokit/formats/python/template/sim.py +14 -14
  99. myokit/formats/sbml/__init__.py +0 -3
  100. myokit/formats/sbml/_api.py +50 -44
  101. myokit/formats/sbml/_importer.py +1 -4
  102. myokit/formats/sbml/_parser.py +2 -5
  103. myokit/formats/stan/__init__.py +0 -3
  104. myokit/formats/stan/_ewriter.py +2 -4
  105. myokit/formats/stan/_exporter.py +2 -5
  106. myokit/formats/stan/template/cell.stan +3 -3
  107. myokit/formats/sympy/__init__.py +0 -3
  108. myokit/formats/sympy/_ereader.py +1 -4
  109. myokit/formats/sympy/_ewriter.py +2 -5
  110. myokit/formats/wcp/__init__.py +0 -3
  111. myokit/formats/wcp/_wcp.py +2 -8
  112. myokit/formats/xml/__init__.py +0 -3
  113. myokit/formats/xml/_exporter.py +0 -3
  114. myokit/formats/xml/_split.py +0 -3
  115. myokit/gui/__init__.py +80 -246
  116. myokit/gui/datablock_viewer.py +103 -86
  117. myokit/gui/datalog_viewer.py +214 -66
  118. myokit/gui/explorer.py +15 -21
  119. myokit/gui/ide.py +171 -144
  120. myokit/gui/progress.py +9 -9
  121. myokit/gui/source.py +406 -375
  122. myokit/gui/vargrapher.py +2 -12
  123. myokit/lib/deps.py +12 -13
  124. myokit/lib/guess.py +3 -4
  125. myokit/lib/hh.py +20 -18
  126. myokit/lib/markov.py +21 -20
  127. myokit/lib/multi.py +1 -3
  128. myokit/lib/plots.py +20 -9
  129. myokit/pacing.py +0 -3
  130. myokit/pype.py +7 -18
  131. myokit/tests/__init__.py +3 -6
  132. myokit/tests/ansic_event_based_pacing.py +1 -4
  133. myokit/tests/ansic_fixed_form_pacing.py +3 -6
  134. myokit/tests/data/beeler-1977-model-compare-b.mmt +2 -2
  135. myokit/tests/data/clancy-1999-fitting.mmt +1 -0
  136. myokit/tests/test_aux.py +13 -28
  137. myokit/tests/test_cellml_v1_api.py +4 -19
  138. myokit/tests/test_cellml_v1_parser.py +0 -15
  139. myokit/tests/test_cellml_v1_writer.py +0 -9
  140. myokit/tests/test_cellml_v2_api.py +4 -19
  141. myokit/tests/test_cellml_v2_parser.py +0 -15
  142. myokit/tests/test_cellml_v2_writer.py +0 -9
  143. myokit/tests/test_cmodel.py +16 -22
  144. myokit/tests/test_compiler_detection.py +1 -11
  145. myokit/tests/test_component.py +108 -56
  146. myokit/tests/test_config.py +34 -67
  147. myokit/tests/test_datablock.py +1 -9
  148. myokit/tests/test_datalog.py +19 -24
  149. myokit/tests/test_dependency_checking.py +8 -23
  150. myokit/tests/test_expressions.py +0 -9
  151. myokit/tests/test_float.py +1 -5
  152. myokit/tests/test_formats.py +0 -9
  153. myokit/tests/test_formats_axon.py +1 -9
  154. myokit/tests/test_formats_cellml.py +0 -15
  155. myokit/tests/test_formats_channelml.py +0 -15
  156. myokit/tests/test_formats_easyml.py +0 -14
  157. myokit/tests/test_formats_exporters.py +1 -16
  158. myokit/tests/test_formats_expression_writers.py +1 -17
  159. myokit/tests/test_formats_html.py +0 -3
  160. myokit/tests/test_formats_importers.py +1 -16
  161. myokit/tests/test_formats_mathml_content.py +0 -9
  162. myokit/tests/test_formats_mathml_presentation.py +0 -9
  163. myokit/tests/test_formats_opencl.py +0 -10
  164. myokit/tests/test_formats_sbml.py +0 -15
  165. myokit/tests/test_formats_sympy.py +0 -9
  166. myokit/tests/test_formats_wcp.py +1 -3
  167. myokit/tests/test_io.py +27 -27
  168. myokit/tests/test_jacobian_calculator.py +6 -14
  169. myokit/tests/test_jacobian_tracer.py +0 -9
  170. myokit/tests/test_lib_deps.py +0 -9
  171. myokit/tests/test_lib_guess.py +0 -9
  172. myokit/tests/test_lib_hh.py +18 -12
  173. myokit/tests/test_lib_markov.py +21 -13
  174. myokit/tests/test_lib_multi.py +0 -9
  175. myokit/tests/test_lib_plots.py +13 -8
  176. myokit/tests/test_meta.py +0 -3
  177. myokit/tests/test_model.py +390 -96
  178. myokit/tests/test_model_building.py +44 -96
  179. myokit/tests/test_opencl_info.py +5 -14
  180. myokit/tests/test_pacing_factory.py +0 -3
  181. myokit/tests/test_pacing_system_c.py +1 -23
  182. myokit/tests/test_pacing_system_py.py +0 -9
  183. myokit/tests/test_parsing.py +139 -56
  184. myokit/tests/test_progress_reporters.py +0 -3
  185. myokit/tests/test_protocol.py +0 -9
  186. myokit/tests/test_protocol_floating_point.py +1 -10
  187. myokit/tests/test_protocol_time_series.py +82 -0
  188. myokit/tests/test_pype.py +0 -9
  189. myokit/tests/test_quantity.py +0 -9
  190. myokit/tests/test_rhs_benchmarker.py +1 -9
  191. myokit/tests/test_sbml_api.py +27 -42
  192. myokit/tests/test_sbml_parser.py +4 -19
  193. myokit/tests/test_simulation_1d.py +45 -25
  194. myokit/tests/test_simulation_cvodes.py +321 -55
  195. myokit/tests/test_simulation_cvodes_from_disk.py +0 -3
  196. myokit/tests/test_simulation_fiber_tissue.py +39 -12
  197. myokit/tests/test_simulation_log_interval.py +1 -431
  198. myokit/tests/test_simulation_opencl.py +69 -48
  199. myokit/tests/test_simulation_opencl_log_interval.py +1 -3
  200. myokit/tests/test_simulation_opencl_vs_cvode.py +1 -10
  201. myokit/tests/test_simulation_opencl_vs_sim1d.py +1 -10
  202. myokit/tests/test_system_info.py +1 -11
  203. myokit/tests/test_tools.py +0 -9
  204. myokit/tests/test_unit.py +1 -10
  205. myokit/tests/test_user_functions.py +0 -10
  206. myokit/tests/test_variable.py +231 -27
  207. myokit/tools.py +5 -21
  208. myokit/units.py +5 -3
  209. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/METADATA +12 -15
  210. myokit-1.35.0.dist-info/RECORD +391 -0
  211. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/WHEEL +1 -1
  212. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/entry_points.txt +0 -1
  213. myokit/_exec_new.py +0 -15
  214. myokit/_exec_old.py +0 -15
  215. myokit/_sim/cvodesim.c +0 -1551
  216. myokit/_sim/cvodesim.py +0 -674
  217. myokit/_sim/icsim.cpp +0 -563
  218. myokit/_sim/icsim.py +0 -363
  219. myokit/_sim/psim.cpp +0 -656
  220. myokit/_sim/psim.py +0 -493
  221. myokit/lib/common.py +0 -1094
  222. myokit/tests/test_lib_common.py +0 -130
  223. myokit/tests/test_simulation_cvode.py +0 -612
  224. myokit/tests/test_simulation_ic.py +0 -108
  225. myokit/tests/test_simulation_p.py +0 -223
  226. myokit-1.33.9.dist-info/RECORD +0 -403
  227. /myokit/formats/opencl/template/{test → test.sh} +0 -0
  228. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/LICENSE.txt +0 -0
  229. {myokit-1.33.9.dist-info → myokit-1.35.0.dist-info}/top_level.txt +0 -0
@@ -4,9 +4,6 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
9
-
10
7
  import os
11
8
  import struct
12
9
  import numpy as np
@@ -17,7 +14,7 @@ import myokit
17
14
  _ENC = 'ascii'
18
15
 
19
16
 
20
- class WcpFile(object):
17
+ class WcpFile:
21
18
  """
22
19
  Represents a read-only WinWCP file (``.wcp``), stored at the location
23
20
  pointed to by ``filepath``.
@@ -35,7 +32,6 @@ class WcpFile(object):
35
32
  """
36
33
  def __init__(self, filepath):
37
34
  # The path to the file and its basename
38
- # Ensure it's a `str` for Python2/3 compatibility
39
35
  filepath = str(filepath)
40
36
  self._filepath = os.path.abspath(filepath)
41
37
  self._filename = os.path.basename(filepath)
@@ -160,8 +156,6 @@ class WcpFile(object):
160
156
  rtype = f.read(4)
161
157
 
162
158
  # Group number (float set by the user)
163
- # Note: First argument to struct.unpack must be a str (so bytes on
164
- # Python 2).
165
159
  group_number = struct.unpack(str('<f'), f.read(4))[0]
166
160
 
167
161
  # Time of recording, as float, not sure how to interpret
@@ -231,7 +225,7 @@ class WcpFile(object):
231
225
  Creates and returns a:class:`myokit.DataLog` containing all the
232
226
  data from this file.
233
227
 
234
- Each channel is stored under its own name, with an indice indicating
228
+ Each channel is stored under its own name, with an index indicating
235
229
  the record it was from. Time is stored under ``time``.
236
230
  """
237
231
  log = myokit.DataLog()
@@ -4,9 +4,6 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
9
-
10
7
  from ._exporter import XMLExporter
11
8
  from ._split import split # noqa
12
9
 
@@ -4,9 +4,6 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
9
-
10
7
  import os
11
8
 
12
9
  from lxml import etree
@@ -4,9 +4,6 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
9
-
10
7
 
11
8
  def split(tag):
12
9
  """
myokit/gui/__init__.py CHANGED
@@ -4,303 +4,136 @@
4
4
  # This file is part of Myokit.
5
5
  # See http://myokit.org for copyright, sharing, and licensing details.
6
6
  #
7
- from __future__ import absolute_import, division
8
- from __future__ import print_function, unicode_literals
9
-
10
- # Library imports
11
- import logging
12
7
  import os
13
8
  import platform
14
9
  import signal
15
10
  import sys
16
11
 
17
- # Myokit imports
18
12
  import myokit
19
13
 
20
14
  # Detect platform
21
15
  platform = platform.system()
22
16
 
23
17
  # Select Qt library to use
24
- pyqt4 = False
25
18
  pyqt5 = False
26
- pyside = False
19
+ pyqt6 = False
27
20
  pyside2 = False
21
+ pyside6 = False
28
22
 
29
23
  # Allow overriding automatic selection
24
+ if myokit.FORCE_PYQT6:
25
+ pyqt6 = True
30
26
  if myokit.FORCE_PYQT5:
31
27
  pyqt5 = True
32
- elif myokit.FORCE_PYQT4:
33
- pyqt4 = True
34
- elif myokit.FORCE_PYSIDE:
35
- pyside = True
28
+ elif myokit.FORCE_PYSIDE6:
29
+ pyside6 = True
36
30
  elif myokit.FORCE_PYSIDE2:
37
31
  pyside2 = True
38
32
  else:
39
33
  # Automatic selection
40
34
  try:
41
- import PyQt5 # noqa
42
- pyqt5 = True
35
+ import PyQt6 # noqa
36
+ pyqt6 = True
43
37
  except ImportError:
44
38
  try:
45
- import PySide2 # noqa
46
- pyside2 = True
39
+ import PySide6 # noqa
40
+ pyside6 = True
47
41
  except ImportError:
48
42
  try:
49
- import PyQt4 # noqa
50
- pyqt4 = True
43
+ import PyQt5 # noqa
44
+ pyqt5 = True
51
45
  except ImportError:
52
46
  try:
53
- import PySide # noqa
54
- pyside = True
47
+ import PySide2 # noqa
48
+ pyside2 = True
55
49
  except ImportError:
56
50
  raise ImportError(
57
- 'Unable to find PyQt5, PyQt4, PySide2 or PySide')
51
+ 'Unable to find PyQt6, PyQt5, PySide6, or PySide2.')
52
+
58
53
 
59
54
  # Import and configure Qt
60
- if pyqt5:
55
+ if pyqt6:
56
+ from PyQt6 import QtGui, QtWidgets, QtCore
57
+ from PyQt6.QtCore import Qt
58
+
59
+ # Use PySide signal names
60
+ QtCore.Signal = QtCore.pyqtSignal
61
+ QtCore.Slot = QtCore.pyqtSlot
62
+ QtCore.Property = QtCore.pyqtProperty
63
+
64
+ # Set backend variables
65
+ backend = 'PyQt6'
66
+ qtversion = 6
61
67
 
62
- # Load PyQt5
68
+ elif pyqt5:
63
69
  from PyQt5 import QtGui, QtWidgets, QtCore
64
70
  from PyQt5.QtCore import Qt
65
71
 
66
- # Fix PyQt naming issues
72
+ # Mimic PyQt6 API changes
73
+ # https://doc.qt.io/qt-6/widgets-changes-qt6.html
74
+ QtGui.QAction = QtWidgets.QAction
75
+ QtWidgets.QApplication.exec = QtWidgets.QApplication.exec_
76
+
77
+ # Use PySide signal names
67
78
  QtCore.Signal = QtCore.pyqtSignal
68
79
  QtCore.Slot = QtCore.pyqtSlot
69
80
  QtCore.Property = QtCore.pyqtProperty
70
81
 
71
- # Configure Matplotlib for use with PyQt5
72
- import matplotlib
73
- try:
74
- matplotlib.use('Qt5Agg')
75
- except ImportError:
76
- # In matplotlib 3.7.0 this raises ImportErrors if a previous backend
77
- # was already set.
78
- pass
79
- else: # pragma: no cover
80
- # The method below was deprecated by matplotlib version 2.2, released
81
- # in 2018. So probably fine to remove this (and similar) after 2023
82
- v = [int(x) for x in matplotlib.__version__.split('.')]
83
- if v[0] < 3 and v[1] < 3:
84
- matplotlib.rcParams['backend.qt5'] = 'PyQt5'
85
- import matplotlib.backends.backend_qt5agg as matplotlib_backend
86
-
87
82
  # Set backend variables
88
83
  backend = 'PyQt5'
89
84
  qtversion = 5
90
85
 
91
- elif pyside2:
86
+ elif pyside6:
87
+ from PySide6 import QtGui, QtWidgets, QtCore
88
+ from PySide6.QtCore import Qt
92
89
 
93
- # Load PySide2
94
- # Load main classes
90
+ # Mimic PyQt6 API changes
91
+ QtWidgets.QApplication.exec = QtWidgets.QApplication.exec_
92
+
93
+ # Set backend variables
94
+ backend = 'PySide6'
95
+ qtversion = 6
96
+
97
+ elif pyside2:
95
98
  from PySide2 import QtGui, QtWidgets, QtCore
96
99
  from PySide2.QtCore import Qt
97
100
 
98
- # Configure Matplotlib for use with PySide2
99
- import matplotlib
100
- try:
101
- matplotlib.use('Qt5Agg')
102
- except ImportError:
103
- # In matplotlib 3.3.0 this raises ImportErrors if a previous backend
104
- # was already set.
105
- pass
106
- else: # pragma: no cover
107
- v = [int(x) for x in matplotlib.__version__.split('.')]
108
- if v[0] < 3 and v[1] < 3:
109
- matplotlib.rcParams['backend.qt5'] = 'PySide2'
110
- import matplotlib.backends.backend_qt5agg as matplotlib_backend # noqa
101
+ # Mimic PyQt6 API changes
102
+ QtGui.QAction = QtWidgets.QAction
103
+ QtWidgets.QApplication.exec = QtWidgets.QApplication.exec_
111
104
 
112
105
  # Set backend variables
113
106
  backend = 'PySide2'
114
107
  qtversion = 5
115
108
 
116
- elif pyqt4:
117
-
118
- # Load PyQt4
119
-
120
- # Deprecated since 2019-09-11
121
- logger = logging.getLogger('myokit')
122
- logger.warning(
123
- 'PyQt4 support has been deprecated. Please upgrade to PyQt5 or'
124
- ' Pyside2.'
125
- )
126
-
127
- # Set PyQt to "API 2"
128
- import sip
129
- sip.setapi('QString', 2)
130
- sip.setapi('QVariant', 2)
131
- sip.setapi('QDate', 2)
132
- sip.setapi('QDateTime', 2)
133
- sip.setapi('QTextStream', 2)
134
- sip.setapi('QTime', 2)
135
- sip.setapi('QUrl', 2)
136
-
137
- # Load main classes
138
- from PyQt4 import QtGui, QtCore
139
- from PyQt4.QtCore import Qt
140
-
141
- # Qt5 compatibility
142
- QtWidgets = QtGui
143
- QtCore.QItemSelection = QtGui.QItemSelection
144
- QtCore.QItemSelectionModel = QtGui.QItemSelectionModel
145
- QtCore.QItemSelectionRange = QtGui.QItemSelectionRange
146
- QtCore.QSortFilterProxyModel = QtGui.QSortFilterProxyModel
147
- QtWidgets.QStyleOptionViewItem = QtWidgets.QStyleOptionViewItemV4
148
-
149
- # Fix Qt4 location issue
150
- import PyQt4.Qt
151
- QtGui.QKeySequence = PyQt4.Qt.QKeySequence
152
- QtGui.QTextCursor = PyQt4.Qt.QTextCursor
153
- del PyQt4.Qt
154
-
155
- # Fix PyQt4 naming issues
156
- QtCore.Signal = QtCore.pyqtSignal
157
- QtCore.Slot = QtCore.pyqtSlot
158
- QtCore.Property = QtCore.pyqtProperty
159
-
160
- # Fix QFileDialog.getOpenFileName return type issues:
161
- # Return type in PyQt4 is not a tuple (call ...AndFilter methods instead)
162
- # Fix getOpenFileName
163
- def gofn(parent=None, caption='', directory='', filter='',
164
- initialFilter='', options=0):
165
- if options == 0:
166
- options = QtWidgets.QFileDialog.Options()
167
- return QtWidgets.QFileDialog.getOpenFileNameAndFilter(
168
- parent, caption, directory, filter, initialFilter, options)
169
- QtWidgets.QFileDialog.getOpenFileName = staticmethod(gofn)
170
- del gofn
171
-
172
- # Fix getOpenFileNames
173
- def gofns(parent=None, caption='', directory='', filter='',
174
- initialFilter='', options=0):
175
- if options == 0:
176
- options = QtWidgets.QFileDialog.Options()
177
- return QtWidgets.QFileDialog.getOpenFileNamesAndFilter(
178
- parent, caption, directory, filter, initialFilter, options)
179
- QtWidgets.QFileDialog.getOpenFileNames = staticmethod(gofns)
180
- del gofns
181
-
182
- # Fix getSaveFileName
183
- def gsfn(parent=None, caption='', directory='', filter='',
184
- initialFilter='', options=0):
185
- if options == 0:
186
- options = QtWidgets.QFileDialog.Options()
187
- return QtWidgets.QFileDialog.getSaveFileNameAndFilter(
188
- parent, caption, directory, filter, initialFilter, options)
189
- QtWidgets.QFileDialog.getSaveFileName = staticmethod(gsfn)
190
- del gsfn
191
-
192
- # Configure Matplotlib for use with PyQt4
193
- import matplotlib
194
- try:
195
- matplotlib.use('Qt4Agg')
196
- except ImportError:
197
- # In matplotlib 3.3.0 this raises ImportErrors if a previous backend
198
- # was already set.
199
- pass
200
- else: # pragma: no cover
201
- v = [int(x) for x in matplotlib.__version__.split('.')]
202
- if v[0] < 3 and v[1] < 3:
203
- matplotlib.rcParams['backend.qt4'] = 'PyQt4'
204
- import matplotlib.backends.backend_qt4agg as matplotlib_backend
109
+ else:
110
+ raise Exception('Selection of qt version failed.')
205
111
 
206
- # Set backend variables
207
- backend = 'PyQt4'
208
- qtversion = 4
209
-
210
- elif pyside:
211
-
212
- # Load PySide
213
-
214
- # Deprecated since 2019-09-11
215
- logger = logging.getLogger('myokit')
216
- logger.warning(
217
- 'PySide support has been deprecated. Please upgrade to PyQt5 or'
218
- ' Pyside2.'
219
- )
220
-
221
- # Load main classes
222
- from PySide import QtGui, QtCore
223
- from PySide.QtCore import Qt
224
-
225
- # Qt5 compatibility
226
- QtWidgets = QtGui
227
- QtCore.QItemSelection = QtGui.QItemSelection
228
- QtCore.QItemSelectionModel = QtGui.QItemSelectionModel
229
- QtCore.QItemSelectionRange = QtGui.QItemSelectionRange
230
- QtCore.QSortFilterProxyModel = QtGui.QSortFilterProxyModel
231
- QtWidgets.QStyleOptionViewItem = QtWidgets.QStyleOptionViewItemV4
232
-
233
- # Fix QFileDialog.getOpenFileName signature issues (is different in PySide,
234
- # which causes issues when using keyword arguments. This is fixed simply
235
- # by simply wrapping the methods.)
236
- # Signature in PySide
237
- # parent
238
- # caption
239
- # dir --> directory PyQt4/5
240
- # filter
241
- # selectedFilter --> initialFilter in PyQt4/5
242
- # options
243
-
244
- # Fix getOpenFileName
245
- gofn_org = QtWidgets.QFileDialog.getOpenFileName
246
-
247
- def gofn(parent=None, caption='', directory='', filter='',
248
- initialFilter='', options=0):
249
- if options == 0:
250
- options = QtWidgets.QFileDialog.Options()
251
- return gofn_org(
252
- parent, caption, directory, filter, initialFilter, options)
253
- QtWidgets.QFileDialog.getOpenFileName = staticmethod(gofn)
254
- del gofn
255
-
256
- # Fix getOpenFileNames
257
- gofns_org = QtWidgets.QFileDialog.getOpenFileNames
258
-
259
- def gofns(parent=None, caption='', directory='', filter='',
260
- initialFilter='', options=0):
261
- if options == 0:
262
- options = QtWidgets.QFileDialog.Options()
263
- return gofns_org(
264
- parent, caption, directory, filter, initialFilter, options)
265
- QtWidgets.QFileDialog.getOpenFileNames = staticmethod(gofns)
266
- del gofns
267
-
268
- # Fix getSaveFileName
269
- gsfn_org = QtWidgets.QFileDialog.getSaveFileName
270
-
271
- def gsfn(parent=None, caption='', directory='', filter='',
272
- initialFilter='', options=0):
273
- if options == 0:
274
- options = QtWidgets.QFileDialog.Options()
275
- return gsfn_org(
276
- parent, caption, directory, filter, initialFilter, options)
277
- QtWidgets.QFileDialog.getSaveFileName = staticmethod(gsfn)
278
- del gsfn
279
-
280
- # Configure Matplotlib for use with PySide
281
- import matplotlib
282
- try:
283
- matplotlib.use('Qt4Agg')
284
- except ImportError:
285
- # In matplotlib 3.3.0 this raises ImportErrors if a previous backend
286
- # was already set.
287
- pass
288
- else: # pragma: no cover
289
- v = [int(x) for x in matplotlib.__version__.split('.')]
290
- if v[0] < 3 and v[1] < 3:
291
- matplotlib.rcParams['backend.qt4'] = 'PySide'
292
- import matplotlib.backends.backend_qt4agg as matplotlib_backend # noqa
293
112
 
294
- # Set backend variables
295
- backend = 'PySide'
296
- qtversion = 4
113
+ # Configure Matplotlib for use with Qt
114
+ import matplotlib # noqa
115
+ try:
116
+ matplotlib.use('QtAgg')
117
+ except ImportError:
118
+ # In matplotlib 3.7.0 this raises ImportErrors if a previous backend
119
+ # was already set.
120
+ pass
121
+ try:
122
+ # New Matplotlib no longer has qt4agg/qt5agg, but now uses qtagg for all
123
+ import matplotlib.backends.back_qtagg as matplotlib_backend # noqa
124
+ except ImportError:
125
+ # https://matplotlib.org/stable/api/backend_qt_api.html
126
+ import matplotlib.backends.backend_qt5agg as matplotlib_backend # noqa
297
127
 
298
- else:
128
+ # Delete temporary variables
129
+ del pyqt5, pyqt6, pyside2, pyside6
299
130
 
300
- raise Exception('Selection of qt version failed.')
301
131
 
302
- # Delete temporary variables
303
- del pyqt4, pyqt5, pyside
132
+ # Load Gnome theme on Wayland (for icons)
133
+ if platform == 'Linux':
134
+ icon = QtGui.QIcon.fromTheme('document-new')
135
+ if icon.isNull():
136
+ QtGui.QIcon.setThemeName('gnome')
304
137
 
305
138
  # Icons with fallback for apple and windows
306
139
  ICON_PATH = os.path.join(myokit.DIR_DATA, 'gui')
@@ -317,11 +150,11 @@ for k, v in ICONS.items():
317
150
  ICONS[k] = os.path.join(ICON_PATH, v)
318
151
 
319
152
  # Toolbar style suitable for platform
320
- TOOL_BUTTON_STYLE = Qt.ToolButtonTextUnderIcon
153
+ TOOL_BUTTON_STYLE = Qt.ToolButtonStyle.ToolButtonTextUnderIcon
321
154
  if platform == 'Windows': # pragma: no linux cover
322
- TOOL_BUTTON_STYLE = Qt.ToolButtonIconOnly
155
+ TOOL_BUTTON_STYLE = Qt.ToolButtonStyle.ToolButtonIconOnly
323
156
  elif platform == 'Darwin': # pragma: no linux cover
324
- TOOL_BUTTON_STYLE = Qt.ToolButtonTextOnly
157
+ TOOL_BUTTON_STYLE = Qt.ToolButtonStyle.ToolButtonTextOnly
325
158
 
326
159
 
327
160
  # Stand alone applications
@@ -349,10 +182,11 @@ def qtMonospaceFont():
349
182
  """
350
183
  font = QtGui.QFont('monospace')
351
184
  if platform == 'Windows': # pragma: no linux cover
352
- font.setStyleHint(QtGui.QFont.TypeWriter)
185
+ font.setStyleHint(QtGui.QFont.StyleHint.TypeWriter)
353
186
  else:
354
- font.setStyleHint(QtGui.QFont.Monospace)
355
- font.setHintingPreference(QtGui.QFont.PreferVerticalHinting) # Qt5
187
+ font.setStyleHint(QtGui.QFont.StyleHint.Monospace)
188
+ font.setHintingPreference(
189
+ QtGui.QFont.HintingPreference.PreferVerticalHinting)
356
190
  return font
357
191
 
358
192
 
@@ -402,5 +236,5 @@ def run(app, *args):
402
236
  timer.timeout.connect(lambda: None)
403
237
 
404
238
  # Wait for app to exit
405
- sys.exit(a.exec_())
239
+ sys.exit(a.exec())
406
240