spiceitup 1.2.2__tar.gz → 1.3.3__tar.gz

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 (70) hide show
  1. {spiceitup-1.2.2 → spiceitup-1.3.3}/PKG-INFO +1 -1
  2. {spiceitup-1.2.2 → spiceitup-1.3.3}/setup.py +2 -2
  3. spiceitup-1.3.3/spiceitup/__init__.py +0 -0
  4. {spiceitup-1.2.2 → spiceitup-1.3.3}/spiceitup/__main__.py +3 -4
  5. spiceitup-1.3.3/spiceitup/docs/__init__.py +0 -0
  6. spiceitup-1.3.3/spiceitup/images/__init__.py +0 -0
  7. spiceitup-1.3.3/spiceitup/layout/__init__.py +0 -0
  8. spiceitup-1.3.3/spiceitup/layout/flow_layout.py +91 -0
  9. spiceitup-1.3.3/spiceitup/layout/flow_layout_edited.py +98 -0
  10. spiceitup-1.3.3/spiceitup/layout/flow_layout_old.py +96 -0
  11. spiceitup-1.3.3/spiceitup/logs/__init__.py +0 -0
  12. spiceitup-1.3.3/spiceitup/logs/log.py +41 -0
  13. spiceitup-1.3.3/spiceitup/main/__init__.py +0 -0
  14. spiceitup-1.3.3/spiceitup/main/footer.py +229 -0
  15. spiceitup-1.3.3/spiceitup/main/header.py +153 -0
  16. spiceitup-1.3.3/spiceitup/main/menu.py +624 -0
  17. spiceitup-1.3.3/spiceitup/main/menu_bar.py +183 -0
  18. spiceitup-1.3.3/spiceitup/main/w.py +28 -0
  19. spiceitup-1.3.3/spiceitup/main/winc.py +508 -0
  20. spiceitup-1.3.3/spiceitup/plot/__init__.py +0 -0
  21. spiceitup-1.3.3/spiceitup/plot/plot_line.py +182 -0
  22. spiceitup-1.3.3/spiceitup/plot/plot_map.py +537 -0
  23. spiceitup-1.3.3/spiceitup/processing/__init__.py +0 -0
  24. spiceitup-1.3.3/spiceitup/processing/dh.py +376 -0
  25. spiceitup-1.3.3/spiceitup/processing/fit.py +55 -0
  26. spiceitup-1.3.3/spiceitup/processing/threads/__init__.py +0 -0
  27. spiceitup-1.3.3/spiceitup/processing/threads/run_thread.py +137 -0
  28. spiceitup-1.3.3/spiceitup/processing/threads/thread_worker.py +20 -0
  29. spiceitup-1.3.3/spiceitup/processing/threads/workers/__init__.py +0 -0
  30. spiceitup-1.3.3/spiceitup/processing/threads/workers/compute_average.py +34 -0
  31. spiceitup-1.3.3/spiceitup/processing/threads/workers/generate_fit_maps.py +65 -0
  32. spiceitup-1.3.3/spiceitup/processing/threads/workers/load_plot_map.py +21 -0
  33. spiceitup-1.3.3/spiceitup/processing/threads/workers/make_process_available.py +17 -0
  34. spiceitup-1.3.3/spiceitup/processing/threads/workers/out_of_sync.py +30 -0
  35. spiceitup-1.3.3/spiceitup/processing/threads/workers/update_levels.py +37 -0
  36. spiceitup-1.3.3/spiceitup/processing/threads/workers/update_profile.py +77 -0
  37. {spiceitup-1.2.2 → spiceitup-1.3.3}/spiceitup/run.py +25 -26
  38. spiceitup-1.3.3/spiceitup/settings/__init__.py +0 -0
  39. spiceitup-1.3.3/spiceitup/settings/const.py +134 -0
  40. spiceitup-1.3.3/spiceitup/settings/states/__init__.py +0 -0
  41. spiceitup-1.3.3/spiceitup/style/__init__.py +0 -0
  42. spiceitup-1.3.3/spiceitup/toolbox/__init__.py +0 -0
  43. spiceitup-1.3.3/spiceitup/toolbox/binning.py +60 -0
  44. spiceitup-1.3.3/spiceitup/toolbox/clickable_qlabel.py +9 -0
  45. spiceitup-1.3.3/spiceitup/toolbox/filter2D_tests.py +27 -0
  46. spiceitup-1.3.3/spiceitup/toolbox/images/__init__.py +0 -0
  47. spiceitup-1.3.3/spiceitup/toolbox/level_methods.py +23 -0
  48. spiceitup-1.3.3/spiceitup/toolbox/multithreading.py +22 -0
  49. spiceitup-1.3.3/spiceitup/toolbox/pyqtgraph_examples.py +10 -0
  50. spiceitup-1.3.3/spiceitup/toolbox/pyqtgraph_plot_example.py +104 -0
  51. spiceitup-1.3.3/spiceitup/toolbox/scipy_fit.py +29 -0
  52. spiceitup-1.3.3/spiceitup/toolbox/scipy_fit_gaussian.py +39 -0
  53. spiceitup-1.3.3/spiceitup/toolbox/show_icons.py +29 -0
  54. spiceitup-1.3.3/spiceitup/toolbox/signal_thread_ex.py +16 -0
  55. spiceitup-1.3.3/spiceitup/toolbox/small_pyqtgraph.py +91 -0
  56. spiceitup-1.3.3/spiceitup/toolbox/small_pyqtgraph2.py +94 -0
  57. spiceitup-1.3.3/spiceitup/toolbox/test.py +63 -0
  58. spiceitup-1.3.3/spiceitup/utils/__init__.py +0 -0
  59. spiceitup-1.3.3/spiceitup/utils/internal_utils.py +188 -0
  60. spiceitup-1.3.3/spiceitup/utils/special_chars.py +5 -0
  61. {spiceitup-1.2.2 → spiceitup-1.3.3}/spiceitup.egg-info/PKG-INFO +1 -1
  62. spiceitup-1.3.3/spiceitup.egg-info/SOURCES.txt +67 -0
  63. spiceitup-1.2.2/spiceitup.egg-info/SOURCES.txt +0 -11
  64. {spiceitup-1.2.2 → spiceitup-1.3.3}/README.md +0 -0
  65. {spiceitup-1.2.2 → spiceitup-1.3.3}/pyproject.toml +0 -0
  66. {spiceitup-1.2.2 → spiceitup-1.3.3}/setup.cfg +0 -0
  67. {spiceitup-1.2.2 → spiceitup-1.3.3}/spiceitup.egg-info/dependency_links.txt +0 -0
  68. {spiceitup-1.2.2 → spiceitup-1.3.3}/spiceitup.egg-info/entry_points.txt +0 -0
  69. {spiceitup-1.2.2 → spiceitup-1.3.3}/spiceitup.egg-info/requires.txt +0 -0
  70. {spiceitup-1.2.2 → spiceitup-1.3.3}/spiceitup.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spiceitup
3
- Version: 1.2.2
3
+ Version: 1.3.3
4
4
  Summary: Quicklook tool for level 2 SPICE imaging
5
5
  Home-page: https://git.ias.u-psud.fr/spice/data_quicklook
6
6
  Author: David Picard
@@ -13,14 +13,14 @@ def load_requirements(filename):
13
13
 
14
14
  setup(
15
15
  name='spiceitup',
16
- version='1.2.2',
16
+ version='1.3.3',
17
17
  description='Quicklook tool for level 2 SPICE imaging',
18
18
  long_description=open('README.md').read(),
19
19
  long_description_content_type='text/markdown',
20
20
  author='David Picard',
21
21
  author_email='david.picard@universite-paris-saclay.fr',
22
22
  url='https://git.ias.u-psud.fr/spice/data_quicklook',
23
- packages=['spiceitup'],
23
+ packages=find_packages(),
24
24
  install_requires=[
25
25
  "PyQt5",
26
26
  "sunraster",
File without changes
@@ -1,12 +1,11 @@
1
1
  import sys
2
2
  import warnings
3
-
4
- from run import Main
5
- from settings.const import Const
3
+ import os
4
+ from .settings.const import Const
5
+ from .run import Main
6
6
  from PyQt5.QtGui import *
7
7
  from PyQt5.QtWidgets import *
8
8
 
9
-
10
9
  def main():
11
10
  warnings.filterwarnings("ignore")
12
11
  # Used to prevent to show All-NaN RuntimeWarning
File without changes
File without changes
File without changes
@@ -0,0 +1,91 @@
1
+ from PyQt5.QtCore import QPoint, QRect, QSize, Qt
2
+ from PyQt5.QtWidgets import (QApplication, QLayout, QPushButton, QSizePolicy, QWidget, QGridLayout)
3
+
4
+ class FlowLayout(QLayout):
5
+
6
+ def __init__(self, parent = None, margin = 0, spacing = -1):
7
+ super(FlowLayout, self).__init__(parent)
8
+
9
+ if parent is not None:
10
+ self.setContentsMargins(margin, margin, margin, margin)
11
+
12
+ self.setSpacing(spacing)
13
+
14
+ self.itemList = []
15
+
16
+ def __del__(self):
17
+ item = self.takeAt(0)
18
+ while item:
19
+ item = self.takeAt(0)
20
+
21
+ def addItem(self, item):
22
+ self.itemList.append(item)
23
+
24
+ def count(self):
25
+ return len(self.itemList)
26
+
27
+ def itemAt(self, index):
28
+ if index >= 0 and index < len(self.itemList):
29
+ return self.itemList[index]
30
+
31
+ return None
32
+
33
+ def takeAt(self, index):
34
+ if index >= 0 and index < len(self.itemList):
35
+ return self.itemList.pop(index)
36
+
37
+ return None
38
+
39
+ def expandingDirections(self):
40
+ return Qt.Orientations(Qt.Orientation(0))
41
+
42
+ def hasHeightForWidth(self):
43
+ return True
44
+
45
+ def heightForWidth(self, width):
46
+ height = self.doLayout(QRect(0, 0, width, 0), True)
47
+ return height
48
+
49
+ def setGeometry(self, rect):
50
+ super(FlowLayout, self).setGeometry(rect)
51
+ self.doLayout(rect, False)
52
+
53
+ def sizeHint(self):
54
+ return self.minimumSize()
55
+
56
+ def minimumSize(self):
57
+ size = QSize()
58
+
59
+ for item in self.itemList:
60
+ size = size.expandedTo(item.minimumSize())
61
+
62
+ margin, _, _, _ = self.getContentsMargins()
63
+
64
+ size += QSize(2 * margin, 2 * margin)
65
+ return size
66
+
67
+ def doLayout(self, rect, testOnly):
68
+ x = rect.x()
69
+ y = rect.y()
70
+ lineHeight = 0
71
+
72
+ for item in self.itemList:
73
+ wid = item.widget()
74
+ spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,
75
+ QSizePolicy.PushButton, Qt.Horizontal)
76
+ spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,
77
+ QSizePolicy.PushButton, Qt.Vertical)
78
+ nextX = x + item.sizeHint().width() + spaceX
79
+ if nextX - spaceX > rect.right() and lineHeight > 0:
80
+ x = rect.x()
81
+ y = y + lineHeight + spaceY
82
+ nextX = x + item.sizeHint().width() + spaceX
83
+ lineHeight = 0
84
+
85
+ if not testOnly:
86
+ item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
87
+
88
+ x = nextX
89
+ lineHeight = max(lineHeight, item.sizeHint().height())
90
+
91
+ return y + lineHeight - rect.y()
@@ -0,0 +1,98 @@
1
+ from PyQt5.QtCore import QPoint, QRect, QSize, Qt
2
+ from PyQt5.QtWidgets import (QApplication, QLayout, QPushButton, QSizePolicy, QWidget, QGridLayout)
3
+
4
+ class FlowLayout(QLayout):
5
+ q_plot_size = None
6
+
7
+ def __init__(self, parent = None, margin = 0, spacing = -1, q_plot_size = None):
8
+ # plot_size must be a QSize object
9
+ super(FlowLayout, self).__init__(parent)
10
+
11
+ if q_plot_size is not None:
12
+ self.q_plot_size = q_plot_size
13
+ self.q_plot_size.setHeight(int(self.q_plot_size.width() * 1.3)) # because of win title
14
+ self.q_plot_size.setWidth(self.q_plot_size.width() * 2) # because 2 plots x,y and lambda,y
15
+
16
+ if parent is not None:
17
+ self.setContentsMargins(margin, margin, margin, margin)
18
+
19
+ self.setSpacing(spacing)
20
+
21
+ self.itemList = []
22
+
23
+ def __del__(self):
24
+ item = self.takeAt(0)
25
+ while item:
26
+ item = self.takeAt(0)
27
+
28
+ def addItem(self, item):
29
+ self.itemList.append(item)
30
+
31
+ def count(self):
32
+ return len(self.itemList)
33
+
34
+ def itemAt(self, index):
35
+ if index >= 0 and index < len(self.itemList):
36
+ return self.itemList[index]
37
+
38
+ return None
39
+
40
+ def takeAt(self, index):
41
+ if index >= 0 and index < len(self.itemList):
42
+ return self.itemList.pop(index)
43
+
44
+ return None
45
+
46
+ def expandingDirections(self):
47
+ return Qt.Orientations(Qt.Orientation(0))
48
+
49
+ def hasHeightForWidth(self):
50
+ return True
51
+
52
+ def heightForWidth(self, width):
53
+ height = self.doLayout(QRect(0, 0, width, 0), True)
54
+ return height
55
+
56
+ def setGeometry(self, rect):
57
+ super(FlowLayout, self).setGeometry(rect)
58
+ self.doLayout(rect, False)
59
+
60
+ def sizeHint(self):
61
+ return self.minimumSize()
62
+
63
+ def minimumSize(self):
64
+ size = QSize()
65
+
66
+ for item in self.itemList:
67
+ size = size.expandedTo(item.minimumSize())
68
+
69
+ margin, _, _, _ = self.getContentsMargins()
70
+
71
+ size += QSize(2 * margin, 2 * margin)
72
+ return size
73
+
74
+ def doLayout(self, rect, testOnly):
75
+ x = rect.x()
76
+ y = rect.y()
77
+ lineHeight = 0
78
+
79
+ for item in self.itemList:
80
+ wid = item.widget()
81
+ spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,
82
+ QSizePolicy.PushButton, Qt.Horizontal)
83
+ spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,
84
+ QSizePolicy.PushButton, Qt.Vertical)
85
+ nextX = x + self.q_plot_size.width() + spaceX #nextX = x + item.sizeHint().width() + spaceX
86
+ if nextX - spaceX > rect.right() and lineHeight > 0:
87
+ x = rect.x()
88
+ y = y + lineHeight + spaceY
89
+ nextX = x + self.q_plot_size.width() + spaceX #nextX = x + item.sizeHint().width() + spaceX
90
+ lineHeight = 0
91
+
92
+ if not testOnly:
93
+ item.setGeometry(QRect(QPoint(x, y), self.q_plot_size)) #item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
94
+
95
+ x = nextX
96
+ lineHeight = max(lineHeight, self.q_plot_size.height()) #lineHeight = max(lineHeight, item.sizeHint().height())
97
+
98
+ return y + lineHeight - rect.y()
@@ -0,0 +1,96 @@
1
+ from PyQt5.QtCore import QPoint, QRect, QSize, Qt
2
+ from PyQt5.QtWidgets import (QApplication, QLayout, QPushButton, QSizePolicy, QWidget, QGridLayout)
3
+
4
+ class FlowLayout(QLayout):
5
+ q_plot_size = None
6
+
7
+ def __init__(self, parent = None, margin = 0, spacing = -1, q_plot_size = None):
8
+ # plot_size must be a QSize object
9
+ super(FlowLayout, self).__init__(parent)
10
+
11
+ if q_plot_size is not None:
12
+ self.q_plot_size = q_plot_size
13
+
14
+ if parent is not None:
15
+ self.setContentsMargins(margin, margin, margin, margin)
16
+
17
+ self.setSpacing(spacing)
18
+
19
+ self.itemList = []
20
+
21
+ def __del__(self):
22
+ item = self.takeAt(0)
23
+ while item:
24
+ item = self.takeAt(0)
25
+
26
+ def addItem(self, item):
27
+ self.itemList.append(item)
28
+
29
+ def count(self):
30
+ return len(self.itemList)
31
+
32
+ def itemAt(self, index):
33
+ if index >= 0 and index < len(self.itemList):
34
+ return self.itemList[index]
35
+
36
+ return None
37
+
38
+ def takeAt(self, index):
39
+ if index >= 0 and index < len(self.itemList):
40
+ return self.itemList.pop(index)
41
+
42
+ return None
43
+
44
+ def expandingDirections(self):
45
+ return Qt.Orientations(Qt.Orientation(0))
46
+
47
+ def hasHeightForWidth(self):
48
+ return True
49
+
50
+ def heightForWidth(self, width):
51
+ height = self.doLayout(QRect(0, 0, width, 0), True)
52
+ return height
53
+
54
+ def setGeometry(self, rect):
55
+ super(FlowLayout, self).setGeometry(rect)
56
+ self.doLayout(rect, False)
57
+
58
+ def sizeHint(self):
59
+ return self.minimumSize()
60
+
61
+ def minimumSize(self):
62
+ size = QSize()
63
+
64
+ for item in self.itemList:
65
+ size = size.expandedTo(item.minimumSize())
66
+
67
+ margin, _, _, _ = self.getContentsMargins()
68
+
69
+ size += QSize(2 * margin, 2 * margin)
70
+ return size
71
+
72
+ def doLayout(self, rect, testOnly):
73
+ x = rect.x()
74
+ y = rect.y()
75
+ lineHeight = 0
76
+
77
+ for item in self.itemList:
78
+ wid = item.widget()
79
+ spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,
80
+ QSizePolicy.PushButton, Qt.Horizontal)
81
+ spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,
82
+ QSizePolicy.PushButton, Qt.Vertical)
83
+ nextX = x + item.sizeHint().width() + spaceX
84
+ if nextX - spaceX > rect.right() and lineHeight > 0:
85
+ x = rect.x()
86
+ y = y + lineHeight + spaceY
87
+ nextX = x + item.sizeHint().width() + spaceX
88
+ lineHeight = 0
89
+
90
+ if not testOnly:
91
+ item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
92
+
93
+ x = nextX
94
+ lineHeight = max(lineHeight, item.sizeHint().height())
95
+
96
+ return y + lineHeight - rect.y()
File without changes
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from datetime import datetime
4
+ from ..settings.const import Const
5
+
6
+ from ..utils.internal_utils import get_ms
7
+
8
+
9
+ class Log:
10
+
11
+ @staticmethod
12
+ def p(*msgs, msg_type='info'):
13
+ """Prints in log"""
14
+ prefix = 'INFO'
15
+ if msg_type == 'warn':
16
+ prefix = 'WARNING'
17
+ elif msg_type == 'error':
18
+ prefix = 'ERROR'
19
+
20
+ today_dt = datetime.now()
21
+ today_str = today_dt.strftime(Const.date_format)
22
+
23
+ try:
24
+ with open(Const.log_file, 'a') as f:
25
+ for msg in msgs:
26
+ f.write(today_str + ' ' + prefix + ': ' + str(msg) + '\n')
27
+ except PermissionError:
28
+ print('Permission denined when appening in ' + Const.log_file)
29
+
30
+
31
+ @staticmethod
32
+ def p_ms(msg, first_time_ms=0):
33
+ """Prints current time in milliseconds in log file.
34
+ A first_time_ms can be removed in order to investigate more easily the time
35
+ latency between instructions"""
36
+ Log.p(str(get_ms() - first_time_ms) + ': ' + msg)
37
+
38
+
39
+ @staticmethod
40
+ def p_duration(first_time_ms):
41
+ Log.p('Duration since first time: ' + str(get_ms() - first_time_ms) + ' ms')
File without changes
@@ -0,0 +1,229 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ from datetime import datetime
4
+ from functools import partial
5
+
6
+ from PyQt5.QtCore import Qt
7
+ from PyQt5.QtWidgets import *
8
+
9
+ from ..logs.log import Log
10
+ from ..processing.threads.run_thread import RunThread
11
+ from ..settings.const import Const
12
+
13
+ class Footer(QFrame):
14
+ main = None
15
+ f_container = None
16
+ progress_lines = []
17
+
18
+ def __init__(self, main):
19
+ super(Footer, self).__init__()
20
+ self.main = main
21
+ self.setFrameShape(QFrame.StyledPanel)
22
+
23
+ l_footer = QVBoxLayout(self)
24
+ self.f_container = QFrame()
25
+
26
+ w_scroll = QScrollArea()
27
+ w_scroll.setWidget(self.f_container)
28
+ w_scroll.setWidgetResizable(True)
29
+ l_footer.addWidget(w_scroll)
30
+
31
+ self.l_grid = QGridLayout()
32
+ self.l_grid.setVerticalSpacing(5)
33
+
34
+ self.f_container.setLayout(self.l_grid)
35
+
36
+ def show_progress_line(self, index):
37
+ for key, widget in self.progress_lines[index].items():
38
+ if not isinstance(widget, int) and not isinstance(widget, str): # exclude index/line and title text
39
+ widget.show()
40
+
41
+ def hide_progress_line(self, index):
42
+ for key, widget in self.progress_lines[index].items():
43
+ if not isinstance(widget, int) and not isinstance(widget, str): # exclude index/line and title text
44
+ widget.hide()
45
+
46
+ def get_color(self, val):
47
+ color = Const.progress_bar_color
48
+ if val == 100:
49
+ color = Const.progress_bar_color_done
50
+ return color
51
+
52
+ def get_text_color(self, val):
53
+ color = Const.progress_bar_color
54
+ if val == 100:
55
+ color = Const.green_text
56
+ return color
57
+
58
+ def get_progress_line_index(self, id_):
59
+ for index, pl in enumerate(self.progress_lines):
60
+ if pl['id'] == id_:
61
+ return index
62
+
63
+ def update_progress_line_by_id(self, id_, val):
64
+ index = self.get_progress_line_index(id_)
65
+ self.update_progress_line(index, val)
66
+
67
+ def interrupt_progress_line_by_id(self, id_):
68
+ index = self.get_progress_line_index(id_)
69
+ self.interrupt_progress_line(index)
70
+
71
+ def interrupt_processes(self):
72
+ for index, pl in enumerate(self.progress_lines):
73
+ if pl['val'] < 100:
74
+ self.interrupt_progress_line(index)
75
+
76
+ def interrupt_progress_line(self, index):
77
+ color = Const.progress_bar_interrupt_color
78
+ text_color = Const.red_text
79
+ self.progress_lines[index]['interrupted'] = True
80
+ self.progress_lines[index]['pb'].setStyleSheet('QProgressBar::chunk { background-color: ' +
81
+ color + ';}')
82
+ self.progress_lines[index]['pb2'].setStyleSheet('QProgressBar::chunk { background-color: ' +
83
+ color + ';}')
84
+ self.progress_lines[index]['q_title'].setText('<font color="' + text_color + '">' +
85
+ self.progress_lines[index]['title'] + '</font>')
86
+ val = self.progress_lines[index]['val']
87
+ val_str = '-'
88
+ if val != 1:
89
+ val_str = str(val) + ' %'
90
+ self.progress_lines[index]['q_pc'].setText('<font color="' + text_color + '"><b>' +
91
+ val_str + '</b></font>')
92
+ self.progress_lines[index]['b_cancel'].setText('Cancelled')
93
+
94
+ def update_progress_line(self, index, val, new_line=False): # Use update_progress_line_by_id from outside instead
95
+ # because lines are continuously changing here (adding one moves the other ones)
96
+ if self.progress_lines[index]['interrupted'] and not new_line and val < 100:
97
+ color = Const.progress_bar_interrupt_color
98
+ text_color = Const.red_text
99
+ else:
100
+ color = self.get_color(val)
101
+ text_color = self.get_text_color(val)
102
+ self.progress_lines[index]['pb'].setStyleSheet('QProgressBar::chunk { background-color: ' +
103
+ color + ';}')
104
+ self.progress_lines[index]['pb2'].setStyleSheet('QProgressBar::chunk { background-color: ' +
105
+ color + ';}')
106
+ if val > 100:
107
+ Log.p('Warning: value greater than 100% given (' + str(val) + '), set to 100.')
108
+ val = 100
109
+
110
+ # Setting up both sliders
111
+ val1 = val * 2
112
+ if val1 > 100:
113
+ val1 = 100
114
+ val2 = 2 * (val - 50)
115
+ if val2 < 0:
116
+ val2 = 0
117
+ val_str = '-'
118
+ if val != 1:
119
+ val_str = str(val) + ' %'
120
+ self.progress_lines[index]['pb'].setValue(val1)
121
+ self.progress_lines[index]['pb2'].setValue(val2)
122
+ self.progress_lines[index]['q_title'].setText('<font color="' + text_color + '">' +
123
+ self.progress_lines[index]['title'] + '</font>')
124
+ self.progress_lines[index]['q_pc'].setText('<font color="' + text_color + '"><b>' +
125
+ val_str + '</b></font>')
126
+ self.progress_lines[index]['val'] = val
127
+
128
+ if not new_line:
129
+ pl_from = self.progress_lines[index]
130
+ pl_from['val'] = val
131
+ self.update_cancel_button(pl_from, self.progress_lines[index])
132
+ rt = self.progress_lines[index]['rt']
133
+ b_cancel = self.progress_lines[index]['b_cancel']
134
+ try:
135
+ b_cancel.clicked.disconnect()
136
+ except TypeError: # this one was not connected
137
+ pass
138
+ b_cancel.clicked.connect(partial(Footer.interrupt,
139
+ b_cancel,
140
+ rt))
141
+
142
+ def change_line(self, index, pl):
143
+ val = self.progress_lines[index]['val']
144
+ if pl['interrupted']:
145
+ text_color = Const.red_text
146
+ else:
147
+ text_color = self.get_text_color(val)
148
+ self.progress_lines[index]['title'] = pl['title']
149
+ self.progress_lines[index]['q_title'].setText('<font color="' + text_color + '">' +
150
+ pl['title'] + '</font>')
151
+ self.progress_lines[index]['interrupted'] = pl['interrupted']
152
+ self.progress_lines[index]['with_cancel'] = pl['with_cancel']
153
+ self.update_cancel_button(pl, self.progress_lines[index])
154
+ self.progress_lines[index]['rt'] = pl['rt']
155
+
156
+ def update_cancel_button(self, pl_from, pl_to):
157
+ if pl_to['val'] is not None:
158
+ is_done = pl_to['val'] >= 100
159
+ must_be_enabled = pl_from['with_cancel'] and not pl_from['interrupted'] and not is_done
160
+ pl_to['b_cancel'].setEnabled(must_be_enabled)
161
+ cancel_text = 'Cancel'
162
+ if is_done:
163
+ cancel_text = 'Done'
164
+ elif pl_from['interrupted']:
165
+ cancel_text = 'Cancelled'
166
+ button_css = Const.footer_button + ' '
167
+ button_css += Const.button_enabled if must_be_enabled else Const.button_disabled
168
+ pl_to['b_cancel'].setStyleSheet(button_css)
169
+ pl_to['b_cancel'].setText(cancel_text)
170
+
171
+ @staticmethod
172
+ def interrupt(b_cancel, rt):
173
+ b_cancel.setText('Cancelled')
174
+ b_cancel.setEnabled(False)
175
+ b_cancel.setStyleSheet(Const.footer_button + ' ' + Const.button_disabled)
176
+ rt.interrupt()
177
+
178
+ def create_progress_line(self, rt, title, with_cancel=True):
179
+ now = datetime.now()
180
+ title = 'At ' + now.strftime('%H:%M:%S') + ' - ' + title
181
+ q_title = QLabel()
182
+ q_pc = QLabel('')
183
+ q_pc.setAlignment(Qt.AlignCenter)
184
+ pb = QProgressBar()
185
+ pb.setFixedHeight(Const.progress_bar_height)
186
+ pb.setTextVisible(False)
187
+ pb2 = QProgressBar()
188
+ pb2.setFixedHeight(Const.progress_bar_height)
189
+ pb2.setTextVisible(False)
190
+ b_cancel = QPushButton('Cancel')
191
+ if with_cancel:
192
+ b_cancel.setStyleSheet(Const.footer_button + ' ' + Const.button_enabled)
193
+ else:
194
+ b_cancel.setStyleSheet(Const.footer_button + ' ' + Const.button_disabled)
195
+ b_cancel.setEnabled(False)
196
+
197
+ new_index = len(self.progress_lines)
198
+
199
+ self.l_grid.addWidget(q_title, new_index, 0)
200
+ self.l_grid.addWidget(pb, new_index, 1)
201
+ self.l_grid.addWidget(q_pc, new_index, 2)
202
+ self.l_grid.addWidget(pb2, new_index, 3)
203
+ self.l_grid.addWidget(b_cancel, new_index, 4)
204
+
205
+ # will be erased but create permanent objects (bars, labels, button)
206
+ self.progress_lines.append({'id': '', 'title': '', 'q_title': q_title, 'with_cancel': None,
207
+ 'pb': pb, 'q_pc': q_pc, 'pb2': pb2, 'val': None,
208
+ 'interrupted': None, 'b_cancel': b_cancel, 'rt': None})
209
+
210
+ if new_index > 0:
211
+ # Push other lines to free the first line
212
+ for i in reversed(range(new_index)):
213
+ # Copying i into (i + 1)
214
+ self.progress_lines[i + 1]['id'] = self.progress_lines[i]['id']
215
+ self.change_line(i + 1, self.progress_lines[i])
216
+ self.update_progress_line(i + 1, self.progress_lines[i]['val'])
217
+
218
+ # Now line 0 is available
219
+ self.update_progress_line(0, 0, True)
220
+ self.change_line(0, {'title': title, 'interrupted': False, 'with_cancel': with_cancel,
221
+ 'b_cancel': b_cancel, 'rt': rt})
222
+ self.progress_lines[0]['id'] = new_index
223
+ if with_cancel:
224
+ self.progress_lines[0]['b_cancel'].clicked.connect(partial(Footer.interrupt,
225
+ self.progress_lines[0]['b_cancel'],
226
+ rt))
227
+
228
+ return new_index # created id
229
+