frontengine-dev 0.0.65__py3-none-any.whl → 0.0.71__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 (34) hide show
  1. frontengine/gl_widget/__init__.py +0 -0
  2. frontengine/show/clicker/__init__.py +0 -0
  3. frontengine/show/clicker/clicker_scene.py +7 -0
  4. frontengine/show/clicker/clicker_ui.py +30 -0
  5. frontengine/show/gif/paint_gif.py +1 -0
  6. frontengine/show/image/paint_image.py +1 -0
  7. frontengine/show/particle/__init__.py +0 -0
  8. frontengine/show/particle/particle_scene.py +71 -0
  9. frontengine/show/particle/particle_ui.py +39 -0
  10. frontengine/show/particle/particle_utils.py +61 -0
  11. frontengine/show/video/video_player.py +1 -0
  12. frontengine/show/web/webview.py +9 -5
  13. frontengine/ui/main_ui.py +16 -23
  14. frontengine/ui/page/control_center/control_center_ui.py +5 -1
  15. frontengine/ui/page/gif/gif_setting_ui.py +11 -8
  16. frontengine/ui/page/image/image_setting_ui.py +14 -10
  17. frontengine/ui/page/particle/__init__.py +0 -0
  18. frontengine/ui/page/particle/particle_setting_ui.py +175 -0
  19. frontengine/ui/page/utils.py +21 -1
  20. frontengine/ui/page/video/video_setting_ui.py +11 -9
  21. frontengine/utils/multi_language/english.py +8 -0
  22. frontengine/utils/multi_language/france.py +8 -0
  23. frontengine/utils/multi_language/germany.py +8 -0
  24. frontengine/utils/multi_language/italy.py +8 -0
  25. frontengine/utils/multi_language/russian.py +8 -0
  26. frontengine/utils/multi_language/simplified_chinese.py +8 -0
  27. frontengine/utils/multi_language/traditional_chinese.py +8 -0
  28. frontengine/worker/__init__.py +0 -0
  29. frontengine/worker/qthread_worker.py +34 -0
  30. {frontengine_dev-0.0.65.dist-info → frontengine_dev-0.0.71.dist-info}/METADATA +6 -1
  31. {frontengine_dev-0.0.65.dist-info → frontengine_dev-0.0.71.dist-info}/RECORD +34 -22
  32. {frontengine_dev-0.0.65.dist-info → frontengine_dev-0.0.71.dist-info}/WHEEL +1 -1
  33. {frontengine_dev-0.0.65.dist-info → frontengine_dev-0.0.71.dist-info}/LICENSE +0 -0
  34. {frontengine_dev-0.0.65.dist-info → frontengine_dev-0.0.71.dist-info}/top_level.txt +0 -0
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ from PySide6.QtWidgets import QGraphicsScene
2
+
3
+
4
+ class ClickerGraphicScene(QGraphicsScene):
5
+
6
+ def __init__(self):
7
+ super().__init__()
@@ -0,0 +1,30 @@
1
+ from PySide6.QtCore import Qt
2
+ from PySide6.QtWidgets import QWidget, QGridLayout
3
+
4
+ from frontengine.show.clicker.clicker_scene import ClickerGraphicScene
5
+ from frontengine.show.scene.extend_graphic_view import ExtendGraphicView
6
+
7
+
8
+ class ClickerWidget(QWidget):
9
+
10
+ def __init__(self):
11
+ super().__init__()
12
+ self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
13
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
14
+ self.clicker_view = ExtendGraphicView()
15
+ self.clicker_scene = ClickerGraphicScene()
16
+ self.clicker_view.setScene(self.clicker_scene)
17
+ self.grid_layout = QGridLayout()
18
+ self.grid_layout.addWidget(self.clicker_view, 0, 0, -1, -1)
19
+ self.setLayout(self.grid_layout)
20
+
21
+ def set_ui_window_flag(self, show_on_bottom: bool = False) -> None:
22
+ self.setWindowFlag(
23
+ Qt.WindowType.WindowTransparentForInput |
24
+ Qt.WindowType.FramelessWindowHint |
25
+ Qt.WindowType.Tool
26
+ )
27
+ if not show_on_bottom:
28
+ self.setWindowFlag(Qt.WindowType.WindowStaysOnTopHint)
29
+ else:
30
+ self.setWindowFlag(Qt.WindowType.WindowStaysOnBottomHint)
@@ -28,6 +28,7 @@ class GifWidget(QWidget):
28
28
  self.movie.frameChanged.connect(self.repaint)
29
29
  self.gif_label.setMovie(self.movie)
30
30
  self.movie.start()
31
+ self.resize(self.movie.frameRect().size())
31
32
  else:
32
33
  message_box: QMessageBox = QMessageBox(self)
33
34
  message_box.setText(
@@ -19,6 +19,7 @@ class ImageWidget(QWidget):
19
19
  if self.image_path.exists() and self.image_path.is_file():
20
20
  print(f"Origin file {str(self.image_path)}")
21
21
  self.image = QImage(str(self.image_path))
22
+ self.resize(self.image.size())
22
23
  else:
23
24
  message_box: QMessageBox = QMessageBox(self)
24
25
  message_box.setText(
File without changes
@@ -0,0 +1,71 @@
1
+ import random
2
+ from typing import Callable
3
+
4
+ from PySide6.QtCore import QTimer, QPoint, QRect
5
+ from PySide6.QtGui import QPixmap
6
+ from PySide6.QtWidgets import QGraphicsScene
7
+
8
+ from frontengine.show.particle.particle_utils import particle_down, particle_up, particle_left, particle_right, \
9
+ particle_left_down, particle_left_up, particle_right_down, particle_right_up, particle_random_minus, \
10
+ particle_random_add, particle_random
11
+
12
+
13
+ class ParticleGraphicScene(QGraphicsScene):
14
+
15
+ def __init__(self, particle_pixmap: QPixmap, particle_direction: str,
16
+ particle_count: int = 500,
17
+ screen_height: int = 1920, screen_width: int = 1080, opacity: float = 0.2,
18
+ particle_speed: int = 1):
19
+ super().__init__()
20
+ self.particle_pixmap: QPixmap = particle_pixmap
21
+ self.particle_direction: str = particle_direction
22
+ self.particle_count: int = particle_count
23
+ self.opacity: float = opacity
24
+ self.particle_dict: dict = {}
25
+ self.particle_speed: int = particle_speed
26
+ self.screen_height: int = screen_height
27
+ self.screen_width: int = screen_width
28
+ self.create_particle()
29
+ self.update_function: Callable = {
30
+ "down": particle_down,
31
+ "up": particle_up,
32
+ "left": particle_left,
33
+ "right": particle_right,
34
+ "left_down": particle_left_down,
35
+ "left_up": particle_left_up,
36
+ "right_down": particle_right_down,
37
+ "right_up": particle_right_up,
38
+ "random_minus": particle_random_minus,
39
+ "random_add": particle_random_add,
40
+ "random": particle_random
41
+ }.get(self.particle_direction)
42
+ self.setSceneRect(QRect(0, 0, screen_width, screen_height))
43
+ self.update_timer: QTimer = QTimer()
44
+ self.update_timer.setInterval(100)
45
+ self.update_timer.timeout.connect(self.update_particle_xy)
46
+ self.update_timer.start()
47
+
48
+ def create_particle(self):
49
+ self.particle_dict = {}
50
+ for count in range(self.particle_count):
51
+ item = self.addPixmap(self.particle_pixmap)
52
+ item.setOpacity(self.opacity)
53
+ self.particle_dict.update({
54
+ f"particle_{count}": {
55
+ "x": random.randint(0, self.screen_width),
56
+ "y": random.randint(0, self.screen_height),
57
+ "height": self.screen_height,
58
+ "width": self.screen_width,
59
+ "pixmap_item": item,
60
+ }
61
+ })
62
+
63
+ def update_particle_xy(self):
64
+ self.update_function(self.particle_dict, self.particle_speed)
65
+ for particle_key, particle in self.particle_dict.items():
66
+ pixmap_item = particle.get("pixmap_item")
67
+ pixmap_item.setPos(particle.get("x"), particle.get("y"))
68
+ if not self.sceneRect().contains(QPoint(particle.get("x"), particle.get("y"))):
69
+ self.removeItem(particle.get("pixmap_item"))
70
+ if len(self.items()) == 0:
71
+ self.create_particle()
@@ -0,0 +1,39 @@
1
+ from PySide6.QtCore import QSize
2
+ from PySide6.QtGui import QPixmap, Qt
3
+ from PySide6.QtWidgets import QWidget, QGridLayout
4
+
5
+ from frontengine.show.particle.particle_scene import ParticleGraphicScene
6
+ from frontengine.show.scene.extend_graphic_view import ExtendGraphicView
7
+
8
+
9
+ class ParticleWidget(QWidget):
10
+
11
+ def __init__(self, pixmap: QPixmap, particle_size: int, particle_direction: str, particle_count: int = 50,
12
+ screen_height: int = 1080, screen_width: int = 1920, opacity: float = 0.2,
13
+ particle_speed: int = 1):
14
+ super().__init__()
15
+ self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
16
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
17
+ if particle_size:
18
+ self.pixmap = pixmap.scaled(QSize(particle_size, particle_size), Qt.AspectRatioMode.KeepAspectRatio)
19
+ else:
20
+ self.pixmap = pixmap.scaled(QSize(pixmap.width(), pixmap.height()), Qt.AspectRatioMode.KeepAspectRatio)
21
+ self.particle_view = ExtendGraphicView()
22
+ self.particle_scene = ParticleGraphicScene(
23
+ self.pixmap, particle_direction, particle_count,
24
+ screen_height, screen_width, opacity, particle_speed)
25
+ self.particle_view.setScene(self.particle_scene)
26
+ self.grid_layout = QGridLayout()
27
+ self.grid_layout.addWidget(self.particle_view, 0, 0, -1, -1)
28
+ self.setLayout(self.grid_layout)
29
+
30
+ def set_ui_window_flag(self, show_on_bottom: bool = False) -> None:
31
+ self.setWindowFlag(
32
+ Qt.WindowType.WindowTransparentForInput |
33
+ Qt.WindowType.FramelessWindowHint |
34
+ Qt.WindowType.Tool
35
+ )
36
+ if not show_on_bottom:
37
+ self.setWindowFlag(Qt.WindowType.WindowStaysOnTopHint)
38
+ else:
39
+ self.setWindowFlag(Qt.WindowType.WindowStaysOnBottomHint)
@@ -0,0 +1,61 @@
1
+ import random
2
+ from typing import Dict, Callable
3
+
4
+
5
+ def particle_down(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
6
+ for particle in particle_dict.values():
7
+ particle.update({"y": particle.get("y") + random.randint(0, particle_speed)})
8
+
9
+
10
+ def particle_up(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
11
+ for particle in particle_dict.values():
12
+ particle.update({"y": particle.get("y") - random.randint(0, particle_speed)})
13
+
14
+
15
+ def particle_left(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
16
+ for particle in particle_dict.values():
17
+ particle.update({"x": particle.get("x") - random.randint(0, particle_speed)})
18
+
19
+
20
+ def particle_right(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
21
+ for particle in particle_dict.values():
22
+ particle.update({"x": particle.get("x") + random.randint(0, particle_speed)})
23
+
24
+
25
+ def particle_left_down(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
26
+ particle_left(particle_dict, particle_speed)
27
+ particle_down(particle_dict, particle_speed)
28
+
29
+
30
+ def particle_left_up(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
31
+ particle_left(particle_dict, particle_speed)
32
+ particle_up(particle_dict, particle_speed)
33
+
34
+
35
+ def particle_right_down(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
36
+ particle_right(particle_dict, particle_speed)
37
+ particle_down(particle_dict, particle_speed)
38
+
39
+
40
+ def particle_right_up(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
41
+ particle_right(particle_dict, particle_speed)
42
+ particle_up(particle_dict, particle_speed)
43
+
44
+
45
+ def particle_random_minus(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
46
+ for particle in particle_dict.values():
47
+ particle.update({"y": particle.get("y") + random.randint(0, particle_speed)})
48
+ particle.update({"x": particle.get("x") - random.randint(0, particle_speed)})
49
+
50
+
51
+ def particle_random_add(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
52
+ for particle in particle_dict.values():
53
+ particle.update({"y": particle.get("y") - random.randint(0, particle_speed)})
54
+ particle.update({"x": particle.get("x") + random.randint(0, particle_speed)})
55
+
56
+
57
+ def particle_random(particle_dict: Dict[str, dict], particle_speed: int = 30) -> None:
58
+ function: Callable = random.choice(
59
+ [particle_down, particle_up, particle_left, particle_right, particle_right_up, particle_left_down,
60
+ particle_left_up, particle_right_down, particle_random_add, particle_random_minus])
61
+ function(particle_dict, particle_speed)
@@ -45,6 +45,7 @@ class VideoWidget(QVideoWidget):
45
45
  if self.icon_path.exists() and self.icon_path.is_file():
46
46
  self.setWindowIcon(QIcon(str(self.icon_path)))
47
47
 
48
+
48
49
  def set_ui_window_flag(self, show_on_bottom: bool = False) -> None:
49
50
  self.setWindowFlag(
50
51
  Qt.WindowType.WindowTransparentForInput |
@@ -4,7 +4,7 @@ from pathlib import Path
4
4
  from PySide6.QtCore import Qt, QUrl
5
5
  from PySide6.QtGui import QIcon, QAction
6
6
  from PySide6.QtWebEngineWidgets import QWebEngineView
7
- from PySide6.QtWidgets import QMessageBox
7
+ from PySide6.QtWidgets import QMessageBox, QMenu
8
8
 
9
9
  from frontengine.utils.multi_language.language_wrapper import language_wrapper
10
10
 
@@ -13,6 +13,8 @@ class WebWidget(QWebEngineView):
13
13
 
14
14
  def __init__(self, url: str, is_file: bool = False):
15
15
  super().__init__()
16
+ self.menu = None
17
+ self.close_action = None
16
18
  self.opacity: float = 0.2
17
19
  self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
18
20
  if not is_file:
@@ -36,10 +38,12 @@ class WebWidget(QWebEngineView):
36
38
  self.setWindowIcon(QIcon(str(self.icon_path)))
37
39
 
38
40
  def contextMenuEvent(self, event):
39
- self.menu = self.createStandardContextMenu()
40
- self.close_action = QAction("Close")
41
- self.close_action.triggered.connect(self.close)
42
- self.menu.addAction(self.close_action)
41
+ if self.close_action is None:
42
+ self.close_action = QAction("Close")
43
+ self.close_action.triggered.connect(self.close)
44
+ if self.menu is None:
45
+ self.menu = QMenu(self)
46
+ self.menu.addAction(self.close_action)
43
47
  self.menu.popup(event.globalPos())
44
48
 
45
49
  def set_ui_variable(self, opacity: float = 0.2) -> None:
frontengine/ui/main_ui.py CHANGED
@@ -4,9 +4,9 @@ from pathlib import Path
4
4
  from typing import Dict, Type
5
5
 
6
6
  from PySide6.QtCore import QTimer, QCoreApplication
7
- from PySide6.QtGui import QIcon, QAction, Qt
7
+ from PySide6.QtGui import QIcon, Qt
8
8
  from PySide6.QtWidgets import QMainWindow, QApplication, QGridLayout, QTabWidget, QMenuBar, QWidget
9
- from qt_material import apply_stylesheet, QtStyleTools
9
+ from qt_material import apply_stylesheet
10
10
 
11
11
  from frontengine.system_tray.extend_system_tray import ExtendSystemTray
12
12
  from frontengine.ui.menu.help_menu import build_help_menu
@@ -15,6 +15,7 @@ from frontengine.ui.menu.language_menu import build_language_menu
15
15
  from frontengine.ui.page.control_center.control_center_ui import ControlCenterUI
16
16
  from frontengine.ui.page.gif.gif_setting_ui import GIFSettingUI
17
17
  from frontengine.ui.page.image.image_setting_ui import ImageSettingUI
18
+ from frontengine.ui.page.particle.particle_setting_ui import ParticleSettingUI
18
19
  from frontengine.ui.page.scene_setting.scene_setting_ui import SceneSettingUI
19
20
  from frontengine.ui.page.sound_player.sound_player_setting_ui import SoundPlayerSettingUI
20
21
  from frontengine.ui.page.text.text_setting_ui import TextSettingUI
@@ -28,12 +29,13 @@ from frontengine.utils.multi_language.language_wrapper import language_wrapper
28
29
  FrontEngine_EXTEND_TAB: Dict[str, Type[QWidget]] = {}
29
30
 
30
31
 
31
- class FrontEngineMainUI(QMainWindow, QtStyleTools):
32
+ class FrontEngineMainUI(QMainWindow):
32
33
 
33
- def __init__(self, debug: bool = False, show_system_tray_ray: bool = True):
34
+ def __init__(self, main_app: QApplication = None, debug: bool = False, show_system_tray_ray: bool = True):
34
35
  super().__init__()
35
36
  # User setting
36
37
  self.id = "FrontEngine"
38
+ self.main_app = main_app
37
39
  QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_EnableHighDpiScaling)
38
40
  if sys.platform in ["win32", "cygwin", "msys"]:
39
41
  from ctypes import windll
@@ -55,6 +57,7 @@ class FrontEngineMainUI(QMainWindow, QtStyleTools):
55
57
  self.sound_player_setting_ui = SoundPlayerSettingUI()
56
58
  self.text_setting_ui = TextSettingUI()
57
59
  self.scene_setting_ui = SceneSettingUI()
60
+ self.particle_setting_ui = ParticleSettingUI()
58
61
  self.control_center_ui = ControlCenterUI(
59
62
  self.video_setting_ui,
60
63
  self.image_setting_ui,
@@ -62,11 +65,11 @@ class FrontEngineMainUI(QMainWindow, QtStyleTools):
62
65
  self.gif_setting_ui,
63
66
  self.sound_player_setting_ui,
64
67
  self.text_setting_ui,
65
- self.scene_setting_ui
68
+ self.scene_setting_ui,
69
+ self.particle_setting_ui
66
70
  )
67
71
  # Style menu bar
68
72
  self.menu_bar = QMenuBar()
69
- self.add_style_menu()
70
73
  self.setMenuBar(self.menu_bar)
71
74
  self.tab_widget.addTab(
72
75
  self.video_setting_ui, language_wrapper.language_word_dict.get("tab_video_text"))
@@ -90,6 +93,10 @@ class FrontEngineMainUI(QMainWindow, QtStyleTools):
90
93
  self.scene_setting_ui,
91
94
  language_wrapper.language_word_dict.get("tab_scene_text")
92
95
  )
96
+ self.tab_widget.addTab(
97
+ self.particle_setting_ui,
98
+ language_wrapper.language_word_dict.get("tab_particle_text")
99
+ )
93
100
  self.tab_widget.addTab(
94
101
  self.control_center_ui,
95
102
  language_wrapper.language_word_dict.get("tab_control_center_text")
@@ -124,22 +131,7 @@ class FrontEngineMainUI(QMainWindow, QtStyleTools):
124
131
  apply_stylesheet(self, theme=user_setting_dict.get("theme"))
125
132
  self.showMaximized()
126
133
 
127
- def add_style_menu(self) -> None:
128
- self.menu_bar.style_menu = self.menu_bar.addMenu(
129
- language_wrapper.language_word_dict.get("menu_bar_ui_style")
130
- )
131
- for style in [
132
- 'dark_amber.xml', 'dark_blue.xml', 'dark_cyan.xml', 'dark_lightgreen.xml', 'dark_pink.xml',
133
- 'dark_purple.xml', 'dark_red.xml', 'dark_teal.xml', 'dark_yellow.xml', 'light_amber.xml',
134
- 'light_blue.xml', 'light_cyan.xml', 'light_cyan_500.xml', 'light_lightgreen.xml',
135
- 'light_pink.xml', 'light_purple.xml', 'light_red.xml', 'light_teal.xml', 'light_yellow.xml'
136
- ]:
137
- change_style_action = QAction(style, parent=self)
138
- change_style_action.triggered.connect(self.set_style)
139
- self.menu_bar.style_menu.addAction(change_style_action)
140
-
141
134
  def set_style(self) -> None:
142
- self.apply_stylesheet(self, self.sender().text())
143
135
  user_setting_dict.update({"theme": self.sender().text()})
144
136
 
145
137
  def closeEvent(self, event) -> None:
@@ -159,7 +151,8 @@ class FrontEngineMainUI(QMainWindow, QtStyleTools):
159
151
  self.sound_player_setting_ui.sound_widget_list.clear()
160
152
  self.text_setting_ui.text_widget_list.clear()
161
153
  super().close()
162
- QCoreApplication.exit(0)
154
+ if self.main_app:
155
+ self.main_app.exit(0)
163
156
 
164
157
  @classmethod
165
158
  def debug_close(cls):
@@ -168,7 +161,7 @@ class FrontEngineMainUI(QMainWindow, QtStyleTools):
168
161
 
169
162
  def start_front_engine(debug: bool = False) -> None:
170
163
  main_app = QApplication(sys.argv)
171
- window = FrontEngineMainUI(debug=debug)
164
+ window = FrontEngineMainUI(main_app=main_app, debug=debug)
172
165
  try:
173
166
  window.startup_setting()
174
167
  except Exception as error:
@@ -4,6 +4,7 @@ from PySide6.QtWidgets import QGridLayout, QWidget, QPushButton, QTextEdit, QScr
4
4
  from frontengine.ui.color.global_color import error_color, output_color
5
5
  from frontengine.ui.page.gif.gif_setting_ui import GIFSettingUI
6
6
  from frontengine.ui.page.image.image_setting_ui import ImageSettingUI
7
+ from frontengine.ui.page.particle.particle_setting_ui import ParticleSettingUI
7
8
  from frontengine.ui.page.scene_setting.scene_setting_ui import SceneSettingUI
8
9
  from frontengine.ui.page.sound_player.sound_player_setting_ui import SoundPlayerSettingUI
9
10
  from frontengine.ui.page.text.text_setting_ui import TextSettingUI
@@ -24,7 +25,8 @@ class ControlCenterUI(QWidget):
24
25
  gif_setting_ui: GIFSettingUI,
25
26
  sound_player_setting_ui: SoundPlayerSettingUI,
26
27
  text_setting_ui: TextSettingUI,
27
- scene_setting_ui: SceneSettingUI
28
+ scene_setting_ui: SceneSettingUI,
29
+ particle_setting_ui: ParticleSettingUI
28
30
  ):
29
31
  super().__init__()
30
32
  # Layout
@@ -39,6 +41,7 @@ class ControlCenterUI(QWidget):
39
41
  self.sound_player_setting_ui = sound_player_setting_ui
40
42
  self.text_setting_ui = text_setting_ui
41
43
  self.scene_setting_ui = scene_setting_ui
44
+ self.particle_setting_ui = particle_setting_ui
42
45
  # Close video widget
43
46
  self.clear_video_button = QPushButton(
44
47
  language_wrapper.language_word_dict.get("control_center_close_all_video")
@@ -155,6 +158,7 @@ class ControlCenterUI(QWidget):
155
158
  self.gif_setting_ui.gif_widget_list.clear()
156
159
  self.sound_player_setting_ui.sound_widget_list.clear()
157
160
  self.text_setting_ui.text_widget_list.clear()
161
+ self.particle_setting_ui.particle_list.clear()
158
162
  self.scene_setting_ui.close_scene()
159
163
 
160
164
  def redirect(self) -> None:
@@ -5,7 +5,8 @@ from PySide6.QtWidgets import QWidget, QGridLayout, QLabel, QSlider, QPushButton
5
5
 
6
6
  from frontengine.show.gif.paint_gif import GifWidget
7
7
  from frontengine.ui.dialog.choose_file_dialog import choose_gif
8
- from frontengine.ui.page.utils import monitor_choose_dialog
8
+ from frontengine.ui.page.utils import monitor_choose_dialog, check_show_fullscreen_multi_screen, \
9
+ check_show_fullscreen_one_screen
9
10
  from frontengine.utils.logging.loggin_instance import front_engine_logger
10
11
  from frontengine.utils.multi_language.language_wrapper import language_wrapper
11
12
 
@@ -61,6 +62,11 @@ class GIFSettingUI(QWidget):
61
62
  language_wrapper.language_word_dict.get("gif_setting_ui_play")
62
63
  )
63
64
  self.start_button.clicked.connect(self.start_play_gif)
65
+ # Expand
66
+ self.fullscreen_checkbox = QCheckBox(
67
+ language_wrapper.language_word_dict.get("fullscreen_checkbox_label")
68
+ )
69
+ self.fullscreen_checkbox.setChecked(True)
64
70
  # Show on all screen
65
71
  self.show_on_all_screen_checkbox = QCheckBox(
66
72
  language_wrapper.language_word_dict.get("Show on all screen")
@@ -79,6 +85,7 @@ class GIFSettingUI(QWidget):
79
85
  self.grid_layout.addWidget(self.speed_slider, 1, 2)
80
86
  self.grid_layout.addWidget(self.choose_file_button, 2, 0)
81
87
  self.grid_layout.addWidget(self.ready_label, 2, 1)
88
+ self.grid_layout.addWidget(self.fullscreen_checkbox, 2, 2)
82
89
  self.grid_layout.addWidget(self.start_button, 3, 0)
83
90
  self.grid_layout.addWidget(self.show_on_all_screen_checkbox, 3, 1)
84
91
  self.grid_layout.addWidget(self.show_on_bottom_checkbox, 3, 2)
@@ -107,7 +114,7 @@ class GIFSettingUI(QWidget):
107
114
  monitors = QGuiApplication.screens()
108
115
  if self.show_all_screen is False and len(monitors) <= 1:
109
116
  gif_widget = self._create_gif_widget()
110
- gif_widget.showFullScreen()
117
+ check_show_fullscreen_one_screen(gif_widget, self.fullscreen_checkbox)
111
118
  elif self.show_all_screen is False and len(monitors) >= 2:
112
119
  input_dialog, combobox = monitor_choose_dialog(self, monitors)
113
120
  result = input_dialog.exec_()
@@ -116,15 +123,11 @@ class GIFSettingUI(QWidget):
116
123
  if len(monitors) > select_monitor_index:
117
124
  monitor = monitors[select_monitor_index]
118
125
  gif_widget = self._create_gif_widget()
119
- gif_widget.setScreen(monitor)
120
- gif_widget.move(monitor.availableGeometry().topLeft())
121
- gif_widget.showFullScreen()
126
+ check_show_fullscreen_multi_screen(gif_widget, self.fullscreen_checkbox, monitor)
122
127
  else:
123
128
  for monitor in monitors:
124
129
  gif_widget = self._create_gif_widget()
125
- gif_widget.setScreen(monitor)
126
- gif_widget.move(monitor.availableGeometry().topLeft())
127
- gif_widget.showFullScreen()
130
+ check_show_fullscreen_multi_screen(gif_widget, self.fullscreen_checkbox, monitor)
128
131
 
129
132
  def choose_and_copy_file_to_cwd_gif_dir_then_play(self) -> None:
130
133
  self.ready_label.setText(
@@ -1,11 +1,12 @@
1
1
  from PySide6.QtCore import Qt
2
- from PySide6.QtGui import QScreen, QGuiApplication
2
+ from PySide6.QtGui import QGuiApplication
3
3
  from PySide6.QtWidgets import QWidget, QGridLayout, QSlider, QLabel, QPushButton, QMessageBox, \
4
4
  QCheckBox, QDialog
5
5
 
6
6
  from frontengine.show.image.paint_image import ImageWidget
7
7
  from frontengine.ui.dialog.choose_file_dialog import choose_image
8
- from frontengine.ui.page.utils import monitor_choose_dialog
8
+ from frontengine.ui.page.utils import monitor_choose_dialog, check_show_fullscreen_multi_screen, \
9
+ check_show_fullscreen_one_screen
9
10
  from frontengine.utils.logging.loggin_instance import front_engine_logger
10
11
  from frontengine.utils.multi_language.language_wrapper import language_wrapper
11
12
 
@@ -50,6 +51,11 @@ class ImageSettingUI(QWidget):
50
51
  language_wrapper.language_word_dict.get("image_setting_ui_play")
51
52
  )
52
53
  self.start_button.clicked.connect(self.start_play_image)
54
+ # Expand
55
+ self.fullscreen_checkbox = QCheckBox(
56
+ language_wrapper.language_word_dict.get("fullscreen_checkbox_label")
57
+ )
58
+ self.fullscreen_checkbox.setChecked(True)
53
59
  # Show on all screen
54
60
  self.show_on_all_screen_checkbox = QCheckBox(
55
61
  language_wrapper.language_word_dict.get("Show on all screen")
@@ -65,6 +71,7 @@ class ImageSettingUI(QWidget):
65
71
  self.grid_layout.addWidget(self.opacity_slider, 0, 2)
66
72
  self.grid_layout.addWidget(self.choose_file_button, 1, 0)
67
73
  self.grid_layout.addWidget(self.ready_label, 1, 1)
74
+ self.grid_layout.addWidget(self.fullscreen_checkbox, 1, 2)
68
75
  self.grid_layout.addWidget(self.start_button, 2, 0)
69
76
  self.grid_layout.addWidget(self.show_on_all_screen_checkbox, 2, 1)
70
77
  self.grid_layout.addWidget(self.show_on_bottom_checkbox, 2, 2)
@@ -92,7 +99,7 @@ class ImageSettingUI(QWidget):
92
99
  monitors = QGuiApplication.screens()
93
100
  if self.show_all_screen is False and len(monitors) <= 1:
94
101
  image_widget = self._create_image_widget()
95
- image_widget.showFullScreen()
102
+ check_show_fullscreen_one_screen(image_widget, self.fullscreen_checkbox)
96
103
  elif self.show_all_screen is False and len(monitors) >= 2:
97
104
  input_dialog, combobox = monitor_choose_dialog(self, monitors)
98
105
  result = input_dialog.exec_()
@@ -100,16 +107,13 @@ class ImageSettingUI(QWidget):
100
107
  select_monitor_index = int(combobox.currentText())
101
108
  if len(monitors) > select_monitor_index:
102
109
  monitor = monitors[select_monitor_index]
103
- gif_widget = self._create_image_widget()
104
- gif_widget.setScreen(monitor)
105
- gif_widget.move(monitor.availableGeometry().topLeft())
106
- gif_widget.showFullScreen()
110
+ image_widget = self._create_image_widget()
111
+ check_show_fullscreen_multi_screen(image_widget, self.fullscreen_checkbox, monitor)
112
+
107
113
  else:
108
114
  for monitor in monitors:
109
115
  image_widget = self._create_image_widget()
110
- image_widget.setScreen(monitor)
111
- image_widget.move(monitor.availableGeometry().topLeft())
112
- image_widget.showFullScreen()
116
+ check_show_fullscreen_multi_screen(image_widget, self.fullscreen_checkbox, monitor)
113
117
 
114
118
  def choose_and_copy_file_to_cwd_image_dir_then_play(self) -> None:
115
119
  self.ready_label.setText(
File without changes
@@ -0,0 +1,175 @@
1
+ from PySide6.QtCore import Qt
2
+ from PySide6.QtGui import QGuiApplication, QPixmap
3
+ from PySide6.QtWidgets import QWidget, QGridLayout, QSlider, QLabel, QPushButton, QMessageBox, \
4
+ QCheckBox, QDialog, QComboBox
5
+
6
+ from frontengine.show.particle.particle_ui import ParticleWidget
7
+ from frontengine.ui.dialog.choose_file_dialog import choose_image
8
+ from frontengine.ui.page.utils import monitor_choose_dialog
9
+ from frontengine.utils.logging.loggin_instance import front_engine_logger
10
+ from frontengine.utils.multi_language.language_wrapper import language_wrapper
11
+
12
+
13
+ class ParticleSettingUI(QWidget):
14
+
15
+ def __init__(self):
16
+ super().__init__()
17
+ self.grid_layout = QGridLayout()
18
+ self.grid_layout = QGridLayout(self)
19
+ self.grid_layout.setContentsMargins(0, 0, 0, 0)
20
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
21
+ # Init variable
22
+ self.particle_list = []
23
+ self.show_all_screen = False
24
+ self.ready_to_play = False
25
+ # Opacity setting
26
+ self.opacity_slider = QSlider()
27
+ self.opacity_slider.setOrientation(Qt.Orientation.Horizontal)
28
+ self.opacity_label = QLabel(
29
+ language_wrapper.language_word_dict.get("Opacity")
30
+ )
31
+ self.opacity_slider.setMinimum(1)
32
+ self.opacity_slider.setMaximum(100)
33
+ self.opacity_slider.setValue(20)
34
+ self.opacity_slider.setTickInterval(1)
35
+ self.opacity_slider_value_label = QLabel(str(self.opacity_slider.value()))
36
+ self.opacity_slider.actionTriggered.connect(self.opacity_trick)
37
+ self.setLayout(self.grid_layout)
38
+ # Choose file button
39
+ self.choose_file_button = QPushButton(
40
+ language_wrapper.language_word_dict.get("image_setting_choose_file")
41
+ )
42
+ self.choose_file_button.clicked.connect(self.choose_and_copy_file_to_cwd_image_dir_then_play)
43
+ # Ready label and variable
44
+ self.ready_label = QLabel(
45
+ language_wrapper.language_word_dict.get("Not Ready")
46
+ )
47
+ self.image_path: [str, None] = None
48
+ # Choose direction
49
+ self.choose_direction_label = QLabel(language_wrapper.language_word_dict.get("choose_particle_direction"))
50
+ self.choose_direction_combobox = QComboBox()
51
+ self.choose_direction_combobox.addItems(
52
+ ["down", "up", "left", "right", "left_down", "left_up", "right_down", "right_up",
53
+ "random_minus", "random_add", "random"])
54
+ # Particle size
55
+ self.particle_size_label = QLabel(language_wrapper.language_word_dict.get("particle_size"))
56
+ self.particle_size_combobox = QComboBox()
57
+ for size in range(10, 310, 10):
58
+ self.particle_size_combobox.addItem(str(size))
59
+ self.particle_size_combobox.setCurrentText("50")
60
+ # Particle count
61
+ self.particle_count_label = QLabel(language_wrapper.language_word_dict.get("particle_count"))
62
+ self.particle_count_combobox = QComboBox()
63
+ for count in range(50, 10010, 10):
64
+ self.particle_count_combobox.addItem(str(count))
65
+ self.particle_count_combobox.setCurrentText("100")
66
+ # Particle count
67
+ self.particle_speed_label = QLabel(language_wrapper.language_word_dict.get("particle_speed"))
68
+ self.particle_speed_combobox = QComboBox()
69
+ for speed in range(1, 11, 1):
70
+ self.particle_speed_combobox.addItem(str(speed))
71
+ # Start button
72
+ self.start_button = QPushButton(
73
+ language_wrapper.language_word_dict.get("particle_setting_ui_play")
74
+ )
75
+ self.start_button.clicked.connect(self.start_play_particle)
76
+ # Show on all screen
77
+ self.show_on_all_screen_checkbox = QCheckBox(
78
+ language_wrapper.language_word_dict.get("Show on all screen")
79
+ )
80
+ self.show_on_all_screen_checkbox.clicked.connect(self.set_show_all_screen)
81
+ # Show on bottom
82
+ self.show_on_bottom_checkbox = QCheckBox(
83
+ language_wrapper.language_word_dict.get("Show on bottom")
84
+ )
85
+ # Add to layout
86
+ self.grid_layout.addWidget(self.opacity_label, 0, 0)
87
+ self.grid_layout.addWidget(self.opacity_slider_value_label, 0, 1)
88
+ self.grid_layout.addWidget(self.opacity_slider, 0, 2)
89
+ self.grid_layout.addWidget(self.choose_file_button, 1, 0)
90
+ self.grid_layout.addWidget(self.ready_label, 1, 1)
91
+ self.grid_layout.addWidget(self.choose_direction_label, 2, 0)
92
+ self.grid_layout.addWidget(self.choose_direction_combobox, 2, 1)
93
+ self.grid_layout.addWidget(self.particle_size_label, 3, 0)
94
+ self.grid_layout.addWidget(self.particle_size_combobox, 3, 1)
95
+ self.grid_layout.addWidget(self.particle_count_label, 4, 0)
96
+ self.grid_layout.addWidget(self.particle_count_combobox, 4, 1)
97
+ self.grid_layout.addWidget(self.particle_speed_label, 5, 0)
98
+ self.grid_layout.addWidget(self.particle_speed_combobox, 5, 1)
99
+ self.grid_layout.addWidget(self.start_button, 6, 0)
100
+ self.grid_layout.addWidget(self.show_on_all_screen_checkbox, 6, 1)
101
+ self.grid_layout.addWidget(self.show_on_bottom_checkbox, 6, 2)
102
+ self.setLayout(self.grid_layout)
103
+
104
+ def set_show_all_screen(self) -> None:
105
+ self.show_all_screen = self.show_on_all_screen_checkbox.isChecked()
106
+
107
+ def _create_particle_widget(self, screen_width: int = 1920, screen_height: int = 1080) -> ParticleWidget:
108
+ particle_widget = ParticleWidget(
109
+ pixmap=QPixmap(self.image_path),
110
+ particle_size=int(self.particle_size_combobox.currentText()),
111
+ particle_direction=self.choose_direction_combobox.currentText(),
112
+ particle_count=int(self.particle_count_combobox.currentText()),
113
+ opacity=float(self.opacity_slider.value()) / 100,
114
+ screen_width=screen_width,
115
+ screen_height=screen_height,
116
+ particle_speed=int(self.particle_speed_combobox.currentText())
117
+ )
118
+ particle_widget.set_ui_window_flag(self.show_on_bottom_checkbox.isChecked())
119
+ self.particle_list.append(particle_widget)
120
+ return particle_widget
121
+
122
+ def start_play_particle(self) -> None:
123
+ if self.image_path is None or self.ready_to_play is False:
124
+ message_box = QMessageBox(self)
125
+ message_box.setText(
126
+ language_wrapper.language_word_dict.get("not_prepare")
127
+ )
128
+ message_box.show()
129
+ else:
130
+ front_engine_logger.info("start play particle")
131
+ monitors = QGuiApplication.screens()
132
+ if self.show_all_screen is False and len(monitors) <= 1:
133
+ particle_widget = self._create_particle_widget(
134
+ monitors[0].availableGeometry().width(),
135
+ monitors[0].availableGeometry().height()
136
+ )
137
+ particle_widget.showFullScreen()
138
+ elif self.show_all_screen is False and len(monitors) >= 2:
139
+ input_dialog, combobox = monitor_choose_dialog(self, monitors)
140
+ result = input_dialog.exec_()
141
+ if result == QDialog.DialogCode.Accepted:
142
+ select_monitor_index = int(combobox.currentText())
143
+ if len(monitors) > select_monitor_index:
144
+ monitor = monitors[select_monitor_index]
145
+ particle_widget = self._create_particle_widget(
146
+ monitor.availableGeometry().width(),
147
+ monitor.availableGeometry().height()
148
+ )
149
+ particle_widget.setScreen(monitor)
150
+ particle_widget.move(monitor.availableGeometry().topLeft())
151
+ particle_widget.showFullScreen()
152
+ else:
153
+ for monitor in monitors:
154
+ particle_widget = self._create_particle_widget(
155
+ monitor.availableGeometry().width(),
156
+ monitor.availableGeometry().height()
157
+ )
158
+ particle_widget.setScreen(monitor)
159
+ particle_widget.move(monitor.availableGeometry().topLeft())
160
+ particle_widget.showFullScreen()
161
+
162
+ def choose_and_copy_file_to_cwd_image_dir_then_play(self) -> None:
163
+ self.ready_label.setText(
164
+ language_wrapper.language_word_dict.get("Not Ready")
165
+ )
166
+ self.ready_to_play = False
167
+ self.image_path = choose_image(self)
168
+ if self.image_path is not None:
169
+ self.ready_label.setText(
170
+ language_wrapper.language_word_dict.get("Ready")
171
+ )
172
+ self.ready_to_play = True
173
+
174
+ def opacity_trick(self) -> None:
175
+ self.opacity_slider_value_label.setText(str(self.opacity_slider.value()))
@@ -1,4 +1,5 @@
1
- from PySide6.QtWidgets import QWidget, QDialog, QGridLayout, QLabel, QComboBox, QPushButton
1
+ from PySide6.QtGui import QScreen
2
+ from PySide6.QtWidgets import QWidget, QDialog, QGridLayout, QLabel, QComboBox, QPushButton, QCheckBox
2
3
 
3
4
  from frontengine.utils.multi_language.language_wrapper import language_wrapper
4
5
 
@@ -21,3 +22,22 @@ def monitor_choose_dialog(parent: QWidget, monitors: list):
21
22
  grid_layout.addWidget(no_button, 2, 1)
22
23
  input_dialog.setLayout(grid_layout)
23
24
  return input_dialog, combobox
25
+
26
+
27
+ def check_show_fullscreen_multi_screen(widget: QWidget, fullscreen_checkbox: QCheckBox, monitor: QScreen):
28
+ if fullscreen_checkbox.isChecked():
29
+ widget.setScreen(monitor)
30
+ widget.move(monitor.availableGeometry().topLeft())
31
+ widget.showFullScreen()
32
+ else:
33
+ widget.setScreen(monitor)
34
+ center = monitor.availableGeometry().center()
35
+ widget.move(center - widget.rect().center())
36
+ widget.show()
37
+
38
+
39
+ def check_show_fullscreen_one_screen(widget: QWidget, fullscreen_checkbox: QCheckBox):
40
+ if fullscreen_checkbox.isChecked():
41
+ widget.showFullScreen()
42
+ else:
43
+ widget.show()
@@ -4,7 +4,8 @@ from PySide6.QtWidgets import QWidget, QGridLayout, QSlider, QLabel, QPushButton
4
4
 
5
5
  from frontengine.show.video.video_player import VideoWidget
6
6
  from frontengine.ui.dialog.choose_file_dialog import choose_video
7
- from frontengine.ui.page.utils import monitor_choose_dialog
7
+ from frontengine.ui.page.utils import monitor_choose_dialog, check_show_fullscreen_multi_screen, \
8
+ check_show_fullscreen_one_screen
8
9
  from frontengine.utils.logging.loggin_instance import front_engine_logger
9
10
  from frontengine.utils.multi_language.language_wrapper import language_wrapper
10
11
 
@@ -13,7 +14,6 @@ class VideoSettingUI(QWidget):
13
14
 
14
15
  def __init__(self):
15
16
  super().__init__()
16
- self.grid_layout = QGridLayout()
17
17
  self.grid_layout = QGridLayout(self)
18
18
  self.grid_layout.setContentsMargins(0, 0, 0, 0)
19
19
  # Init variable
@@ -71,6 +71,11 @@ class VideoSettingUI(QWidget):
71
71
  language_wrapper.language_word_dict.get("video_setting_start_play")
72
72
  )
73
73
  self.start_button.clicked.connect(self.start_play_gif)
74
+ # Expand
75
+ self.fullscreen_checkbox = QCheckBox(
76
+ language_wrapper.language_word_dict.get("fullscreen_checkbox_label")
77
+ )
78
+ self.fullscreen_checkbox.setChecked(True)
74
79
  # Show on all screen
75
80
  self.show_on_all_screen_checkbox = QCheckBox(
76
81
  language_wrapper.language_word_dict.get("Show on all screen")
@@ -93,6 +98,7 @@ class VideoSettingUI(QWidget):
93
98
  self.grid_layout.addWidget(self.choose_file_button, 3, 0)
94
99
  self.grid_layout.addWidget(self.show_on_all_screen_checkbox, 4, 0)
95
100
  self.grid_layout.addWidget(self.show_on_bottom_checkbox, 4, 1)
101
+ self.grid_layout.addWidget(self.fullscreen_checkbox, 4, 2)
96
102
  self.grid_layout.addWidget(self.start_button, 5, 0)
97
103
  self.grid_layout.addWidget(self.ready_label, 5, 1)
98
104
  self.setLayout(self.grid_layout)
@@ -123,7 +129,7 @@ class VideoSettingUI(QWidget):
123
129
  monitors = QGuiApplication.screens()
124
130
  if self.show_all_screen is False and len(monitors) <= 1:
125
131
  video_widget = self._create_video_widget()
126
- video_widget.showFullScreen()
132
+ check_show_fullscreen_one_screen(video_widget, self.fullscreen_checkbox)
127
133
  elif self.show_all_screen is False and len(monitors) >= 2:
128
134
  input_dialog, combobox = monitor_choose_dialog(self, monitors)
129
135
  result = input_dialog.exec_()
@@ -132,18 +138,14 @@ class VideoSettingUI(QWidget):
132
138
  if len(monitors) > select_monitor_index:
133
139
  monitor = monitors[select_monitor_index]
134
140
  video_widget = self._create_video_widget()
135
- video_widget.setScreen(monitor)
136
- video_widget.move(monitor.availableGeometry().topLeft())
137
- video_widget.showFullScreen()
141
+ check_show_fullscreen_multi_screen(video_widget, self.fullscreen_checkbox, monitor)
138
142
  else:
139
143
  count = 0
140
144
  for monitor in monitors:
141
145
  video_widget = self._create_video_widget()
142
146
  if count >= 1:
143
147
  video_widget.media_player.audioOutput().setVolume(0)
144
- video_widget.setScreen(monitor)
145
- video_widget.move(monitor.availableGeometry().topLeft())
146
- video_widget.showFullScreen()
148
+ check_show_fullscreen_multi_screen(video_widget, self.fullscreen_checkbox, monitor)
147
149
  count = count + 1
148
150
 
149
151
  def choose_and_copy_file_to_cwd_gif_dir_then_play(self) -> None:
@@ -62,6 +62,7 @@ english_word_dict = {
62
62
  "show_on_which_monitor": "Show on which monitor",
63
63
  "ok": "ok",
64
64
  "no": "no",
65
+ "fullscreen_checkbox_label": "Fullscreen?",
65
66
  # GIF setting ui
66
67
  "gif_setting_ui_choose_file": "Choose GIF or WEBP file",
67
68
  "gif_setting_ui_play": "Start Play GIF or WEBP",
@@ -108,6 +109,13 @@ english_word_dict = {
108
109
  "scene_input": "load scene file",
109
110
  "scene_script_clear": "clear all script",
110
111
  "scene_script": "Scene script",
112
+ # Particle ui
113
+ "tab_particle_text": "Particle",
114
+ "choose_particle_direction": "Choose particle direction",
115
+ "particle_setting_ui_play": "Start play particle",
116
+ "particle_size": "Particle size",
117
+ "particle_count": "Particle count",
118
+ "particle_speed": "Particle speed",
111
119
  # Chat scene input
112
120
  "chat_scene_input_title": "input chat content",
113
121
  "chat_scene_send_chat": "send text",
@@ -62,6 +62,7 @@ french_word_dict = {
62
62
  "show_on_which_monitor": "Afficher sur quel écran",
63
63
  "ok": "OK",
64
64
  "no": "Non",
65
+ "fullscreen_checkbox_label": "Plein écran?",
65
66
  # GIF setting ui
66
67
  "gif_setting_ui_choose_file": "Choisir un fichier GIF ou WEBP",
67
68
  "gif_setting_ui_play": "Lancer la lecture du GIF ou WEBP",
@@ -109,6 +110,13 @@ french_word_dict = {
109
110
  "scene_input": "Charger le fichier de scène",
110
111
  "scene_script_clear": "Effacer tous les scripts",
111
112
  "scene_script": "Script de scène",
113
+ # Particle ui
114
+ "tab_particle_text": "Particule",
115
+ "choose_particle_direction": "Choisissez la direction des particules",
116
+ "particle_setting_ui_play": "Démarrer la lecture des particules",
117
+ "particle_size": "Taille des particules",
118
+ "particle_count": "Nombre de particules",
119
+ "particle_speed": "Vitesse des particules",
112
120
  # Chat scene input
113
121
  "chat_scene_input_title": "Entrer le contenu de la discussion",
114
122
  "chat_scene_send_chat": "Envoyer le texte",
@@ -62,6 +62,7 @@ germany_word_dict = {
62
62
  "show_on_which_monitor": "Auf welchem Monitor anzeigen",
63
63
  "ok": "OK",
64
64
  "no": "Nein",
65
+ "fullscreen_checkbox_label": "Vollbild?",
65
66
  # GIF-Einstellungs-UI
66
67
  "gif_setting_ui_choose_file": "GIF- oder WEBP-Datei auswählen",
67
68
  "gif_setting_ui_play": "GIF oder WEBP abspielen",
@@ -109,6 +110,13 @@ germany_word_dict = {
109
110
  "scene_input": "Szenendatei laden",
110
111
  "scene_script_clear": "Alle Skripte löschen",
111
112
  "scene_script": "Szenen-Skript",
113
+ # Particle ui
114
+ "tab_particle_text": "Partikel",
115
+ "choose_particle_direction": "Partikelrichtung auswählen",
116
+ "particle_setting_ui_play": "Partikelwiedergabe starten",
117
+ "particle_size": "Partikelgröße",
118
+ "particle_count": "Partikelanzahl",
119
+ "particle_speed": "Partikelgeschwindigkeit",
112
120
  # Chat-Szenen-Eingabe
113
121
  "chat_scene_input_title": "Chat-Inhalt eingeben",
114
122
  "chat_scene_send_chat": "Text senden",
@@ -62,6 +62,7 @@ italian_word_dict = {
62
62
  "show_on_which_monitor": "Mostra su quale schermo",
63
63
  "ok": "OK",
64
64
  "no": "No",
65
+ "fullscreen_checkbox_label": "Schermo intero?",
65
66
  # GIF setting ui
66
67
  "gif_setting_ui_choose_file": "Scegli un file GIF o WEBP",
67
68
  "gif_setting_ui_play": "Avvia la riproduzione di GIF o WEBP",
@@ -109,6 +110,13 @@ italian_word_dict = {
109
110
  "scene_input": "Carica il file di scena",
110
111
  "scene_script_clear": "Cancella tutti gli script",
111
112
  "scene_script": "Script della scena",
113
+ # Particle ui
114
+ "tab_particle_text": "Particella",
115
+ "choose_particle_direction": "Scegli la direzione delle particelle",
116
+ "particle_setting_ui_play": "Avvia la riproduzione delle particelle",
117
+ "particle_size": "Dimensione delle particelle",
118
+ "particle_count": "Numero di particelle",
119
+ "particle_speed": "Velocità delle particelle",
112
120
  # Chat scene input
113
121
  "chat_scene_input_title": "Inserisci il contenuto della chat",
114
122
  "chat_scene_send_chat": "Invia il testo",
@@ -62,6 +62,7 @@ russian_word_dict = {
62
62
  "show_on_which_monitor": "На каком мониторе показать",
63
63
  "ok": "ОК",
64
64
  "no": "Нет",
65
+ "fullscreen_checkbox_label": "Полноэкранный режим?",
65
66
  # GIF setting ui
66
67
  "gif_setting_ui_choose_file": "Выберите файл GIF или WEBP",
67
68
  "gif_setting_ui_play": "Начать воспроизведение GIF или WEBP",
@@ -109,6 +110,13 @@ russian_word_dict = {
109
110
  "scene_input": "Входной файл сцены",
110
111
  "scene_script_clear": "Очистить все скрипты",
111
112
  "scene_script": "Сценарий сцены",
113
+ # Particle ui
114
+ "tab_particle_text": "Частица",
115
+ "choose_particle_direction": "Выберите направление частицы",
116
+ "particle_setting_ui_play": "Начать воспроизведение частиц",
117
+ "particle_size": "Размер частицы",
118
+ "particle_count": "Количество частиц",
119
+ "particle_speed": "Скорость частицы",
112
120
  # Chat scene input
113
121
  "chat_scene_input_title": "Введите содержание чата",
114
122
  "chat_scene_send_chat": "Отправить текст",
@@ -62,6 +62,7 @@ simplified_chinese_word_dict = {
62
62
  "show_on_which_monitor": "显示在哪个屏幕",
63
63
  "ok": "确定",
64
64
  "no": "否",
65
+ "fullscreen_checkbox_label": "全屏?",
65
66
  # GIF 设置 UI
66
67
  "gif_setting_ui_choose_file": "选择 GIF 或 WEBP 文件",
67
68
  "gif_setting_ui_play": "开始播放 GIF 或 WEBP",
@@ -109,6 +110,13 @@ simplified_chinese_word_dict = {
109
110
  "scene_input": "读取场景文件",
110
111
  "scene_script_clear": "清除所有脚本",
111
112
  "scene_script": "场景脚本",
113
+ # Particle ui
114
+ "tab_particle_text": "粒子",
115
+ "choose_particle_direction": "选择粒子方向",
116
+ "particle_setting_ui_play": "开始播放粒子",
117
+ "particle_size": "粒子大小",
118
+ "particle_count": "粒子数量",
119
+ "particle_speed": "粒子速度",
112
120
  # Chat scene input
113
121
  "chat_scene_input_title": "输入聊天内容",
114
122
  "chat_scene_send_chat": "送出文字",
@@ -62,6 +62,7 @@ traditional_chinese_word_dict = {
62
62
  "show_on_which_monitor": "顯示在哪個螢幕",
63
63
  "ok": "確定",
64
64
  "no": "否",
65
+ "fullscreen_checkbox_label": "全螢幕?",
65
66
  # GIF setting ui
66
67
  "gif_setting_ui_choose_file": "選擇 GIF 或 WEBP 檔案",
67
68
  "gif_setting_ui_play": "開始撥放 GIF 或 WEBP",
@@ -109,6 +110,13 @@ traditional_chinese_word_dict = {
109
110
  "scene_input": "讀取場景檔案",
110
111
  "scene_script_clear": "清除所有腳本",
111
112
  "scene_script": "場景腳本",
113
+ # Particle ui
114
+ "tab_particle_text": "粒子",
115
+ "choose_particle_direction": "選擇粒子方向",
116
+ "particle_setting_ui_play": "開始播放粒子",
117
+ "particle_size": "粒子大小",
118
+ "particle_count": "粒子數量",
119
+ "particle_speed": "粒子速度",
112
120
  # Chat scene input
113
121
  "chat_scene_input_title": "輸入聊天內容",
114
122
  "chat_scene_send_chat": "送出文字",
File without changes
@@ -0,0 +1,34 @@
1
+ import traceback
2
+ from typing import Callable
3
+
4
+ from PySide6 import QtCore
5
+ from PySide6.QtCore import Signal, QRunnable, Slot
6
+
7
+
8
+ class QThreadSignal(QtCore.QObject):
9
+ finished = Signal()
10
+ error = Signal(tuple)
11
+ result = Signal(object)
12
+ progress = Signal(int)
13
+
14
+
15
+ class QThreadWorker(QRunnable):
16
+
17
+ def __init__(self, function: Callable, *args, **kwargs):
18
+ super().__init__()
19
+ self.function = function
20
+ self.args = args
21
+ self.kwargs = kwargs
22
+ self.signal = QThreadSignal()
23
+
24
+ @Slot()
25
+ def run(self):
26
+ try:
27
+ result = self.function(*self.args, **self.kwargs)
28
+ except Exception as e:
29
+ traceback.print_exc()
30
+ self.signal.error.emit(e)
31
+ else:
32
+ self.signal.result.emit(result)
33
+ finally:
34
+ self.signal.finished.emit()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: frontengine_dev
3
- Version: 0.0.65
3
+ Version: 0.0.71
4
4
  Summary: FrontEngine is BingGPT that can use-define front end or only use like screen saver
5
5
  Author-email: JE-Chen <jechenmailman@gmail.com>
6
6
  License: MIT
@@ -25,6 +25,10 @@ Requires-Dist: qt-material
25
25
 
26
26
  [FrontEngine Doc Click Here!](https://frontengine.readthedocs.io/en/latest/)
27
27
 
28
+ ## Support this project on steam
29
+
30
+ [SteamStoreLink](https://store.steampowered.com/app/2793470/FrontEngine/)
31
+
28
32
  ## Contents
29
33
 
30
34
  > Project kanban https://github.com/orgs/Integration-Automation/projects/2/views/1
@@ -68,6 +72,7 @@ Requires-Dist: qt-material
68
72
  - [Youtube](https://youtu.be/fewogcb3b8Y)
69
73
 
70
74
 
75
+
71
76
  ## Download
72
77
 
73
78
  ---
@@ -1,11 +1,19 @@
1
1
  frontengine/__init__.py,sha256=kRQu2NKQX6VjF70N7Alqp31mxqJ5SRZL1Ri4abYvz0c,1938
2
+ frontengine/gl_widget/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
3
  frontengine/show/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ frontengine/show/clicker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ frontengine/show/clicker/clicker_scene.py,sha256=pZJdy4xP52fgU1aZP74KNimJdW7jw6RKmjco2Ct_G5Y,149
6
+ frontengine/show/clicker/clicker_ui.py,sha256=XzayxCffi_LKocMzaIWV9WQ6Zpx1DnadFRCWeaB0j3k,1204
3
7
  frontengine/show/gif/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- frontengine/show/gif/paint_gif.py,sha256=N_jj4wf5sPYj1vEjFFqlBDcjCD8hxF45ipRJ5yO6XOs,3024
8
+ frontengine/show/gif/paint_gif.py,sha256=IDF5HVZGKuuKs8fqjGgICe2fWvMTUPrTZJ6u2oteO8U,3080
5
9
  frontengine/show/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- frontengine/show/image/paint_image.py,sha256=BtKyFJP7UdOLMBsCoQ1fnT8ft-cUxDaufFzURgbwpJU,2467
10
+ frontengine/show/image/paint_image.py,sha256=1mlTMYvScXjvxdkIEu3x8TmMsVvFciMaQFUl_STcqrQ,2511
7
11
  frontengine/show/load/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
12
  frontengine/show/load/load_someone_make_ui.py,sha256=yjMrkA76VEYkKXygwKmoKaADymjjDlebI-7PNa6DrEo,1010
13
+ frontengine/show/particle/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ frontengine/show/particle/particle_scene.py,sha256=KH09td30_hnZksdf3pAByugq2WUIHIjKFqM7puNbTCA,3142
15
+ frontengine/show/particle/particle_ui.py,sha256=TacLlBOuWN_18GBYEd1Auqvu5vnM1QYBvY3rDmAeny8,1881
16
+ frontengine/show/particle/particle_utils.py,sha256=ekfRYOidAchPlRpuoAuftFBNROMS3e9aA4Z2shQ3Y9c,2725
9
17
  frontengine/show/scene/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
18
  frontengine/show/scene/extend_graphic_scene.py,sha256=7UiEr_kRbhheGOj_rYeq3fAUtRacq2WH8fQZV0Q-tA4,148
11
19
  frontengine/show/scene/extend_graphic_view.py,sha256=b5yAA_PqMTCnn7-63Q8Fhm9HBiWfjo48_1xjh2nP67I,1999
@@ -16,13 +24,13 @@ frontengine/show/sound_player/sound_player.py,sha256=VOXwKI6-VdMH18u__atCay3wVJF
16
24
  frontengine/show/text/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
25
  frontengine/show/text/draw_text.py,sha256=7uXWXDVU6TE5sfQ52bXCNkl0uBIR3dku7xyZPKOqRD4,3685
18
26
  frontengine/show/video/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- frontengine/show/video/video_player.py,sha256=_Sjbcy0KwY3hdr5JIYDIFtnmeDj2EUP0A8w_nSDPnu0,3358
27
+ frontengine/show/video/video_player.py,sha256=ndiMp4nNvxJ3cpuBw_qvtbdm8dnwdm7Jnxl3ke0i0ZU,3360
20
28
  frontengine/show/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- frontengine/show/web/webview.py,sha256=2-7HW395Fp0SZnjUcrTGW-AWk_5OAAyzgjoXnnPpQoE,2842
29
+ frontengine/show/web/webview.py,sha256=KBu68YCjXDMhd4Y_dN5rILD7YQOo5H-t6v6KafB0Z4I,2974
22
30
  frontengine/system_tray/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
31
  frontengine/system_tray/extend_system_tray.py,sha256=k4u2lEox-fCwmQKy1qnek9SGoqUkMFv8Av_DcNanwcE,1595
24
32
  frontengine/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
- frontengine/ui/main_ui.py,sha256=h_lrgMi04dMEupZ9GMCcbgC1SV6I_uBShRNkPpoenC4,7927
33
+ frontengine/ui/main_ui.py,sha256=I_ZouKjVRNZnO4rBsY08juHbsZiMoVJc5_Vt3o-FLUc,7416
26
34
  frontengine/ui/color/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
35
  frontengine/ui/color/global_color.py,sha256=Rh-R-X2BHVjcK5MTBZ1nEMVHgLj1rP4nk-wTQKbiwFA,125
28
36
  frontengine/ui/dialog/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -33,13 +41,15 @@ frontengine/ui/menu/help_menu.py,sha256=WD6t4Mp5OKAlfI9RDKz2kN9ODBcil2rf4H61REK6
33
41
  frontengine/ui/menu/how_to_menu.py,sha256=s1azoiD8H2lApbFPcrv8QvsR1mwh6O_gFHRngQ7bsbc,952
34
42
  frontengine/ui/menu/language_menu.py,sha256=p0nA4bgxc7CIX8_WxUKlnjNLFyvmqCx-h6GXSazlVeM,4271
35
43
  frontengine/ui/page/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- frontengine/ui/page/utils.py,sha256=UxHVStfVg-6563T20pEjnVMYzMvy9JePAj1VOm8HX_g,1103
44
+ frontengine/ui/page/utils.py,sha256=xhCZuF8DwB4mYn8H76PDIAgSpz1WuIl4V07tSbzm9Ks,1808
37
45
  frontengine/ui/page/control_center/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- frontengine/ui/page/control_center/control_center_ui.py,sha256=zyFdFML00ZHcC8NV2Lws95EssIDM_WUMU6h3qePhU7Y,7992
46
+ frontengine/ui/page/control_center/control_center_ui.py,sha256=BxXlWwW9uf48b1jfWgtTBCGZOShlW03m8kzI43YjpaM,8237
39
47
  frontengine/ui/page/gif/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
- frontengine/ui/page/gif/gif_setting_ui.py,sha256=HherbCmOJgO5TLXHt9sflTspmCQh1pv1IGyfKmp7kog,6908
48
+ frontengine/ui/page/gif/gif_setting_ui.py,sha256=UwtgEozpLcs4n0gbiH26gWDNwcfMMWOgYpWV3Nk9XLA,7151
41
49
  frontengine/ui/page/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
- frontengine/ui/page/image/image_setting_ui.py,sha256=0in02Swq_qM-jZNevgoZe0QzjbnAl5L0ZMHOTHzQbrQ,6038
50
+ frontengine/ui/page/image/image_setting_ui.py,sha256=M09doSyJhjYR0vMsTWhLJ9gqNAH2Qffb3JGOB6EnHk0,6274
51
+ frontengine/ui/page/particle/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ frontengine/ui/page/particle/particle_setting_ui.py,sha256=mYRrXT2weh0Rn-d_Dz9yFR6CHYXjEgHxNlhapTwXD6E,8947
43
53
  frontengine/ui/page/scene_setting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
54
  frontengine/ui/page/scene_setting/scene_manager.py,sha256=3s7UlMbQVTyDZd725wdzDvXqeiunE1Q5UQj5hxWGhIs,4978
45
55
  frontengine/ui/page/scene_setting/scene_setting_ui.py,sha256=jc6BGKHJGmPbFxChyILW3BBU_EF1yT0l63OJNqJYWSM,2590
@@ -55,7 +65,7 @@ frontengine/ui/page/sound_player/sound_player_setting_ui.py,sha256=OFRxUyUXVj3-P
55
65
  frontengine/ui/page/text/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
66
  frontengine/ui/page/text/text_setting_ui.py,sha256=nSrXkezs7X9-7Kd16raaz3WZJFwyL4cuz3j74VQIS9U,6317
57
67
  frontengine/ui/page/video/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
- frontengine/ui/page/video/video_setting_ui.py,sha256=vKSKQwWnT5Fnd94h2XTC-Pye495WlZyY5m1vQDeMvf8,8120
68
+ frontengine/ui/page/video/video_setting_ui.py,sha256=6q_cG6PlTZpAlAm0oB7vEBMjsYtoXQE32dy2GXFrtL4,8313
59
69
  frontengine/ui/page/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
70
  frontengine/ui/page/web/web_setting_ui.py,sha256=FgTCn68WTeFp197mhvilWKK25m0xF0gSZ9b7hfG2ELQ,5596
61
71
  frontengine/user_setting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -83,18 +93,20 @@ frontengine/utils/json_format/json_process.py,sha256=xJt_4Hm_o3sNDoeGtRW9Q7fsRj3
83
93
  frontengine/utils/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
94
  frontengine/utils/logging/loggin_instance.py,sha256=Zjr384o2q8x0QWv_hNoHIM_zCp5-HFgW14t-d30GUcQ,598
85
95
  frontengine/utils/multi_language/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
- frontengine/utils/multi_language/english.py,sha256=9A1Hl9HkRqjhDj3oGYpFCItGMU-VnTbuRfn31xQd5Fk,5849
87
- frontengine/utils/multi_language/france.py,sha256=k_LCWiDB22k6PKvrhIrQq2Inm1BoaH5Gwgb6xyMy8o0,6797
88
- frontengine/utils/multi_language/germany.py,sha256=jwg7KXtCahhES6ZPeeUugLoJgaUpnjgbRxN2ZTlJWXs,6534
89
- frontengine/utils/multi_language/italy.py,sha256=UaxuEyet2TUyLBR9JI1Bb7-zCx9iZ9oERImXTtTOV18,6560
96
+ frontengine/utils/multi_language/english.py,sha256=-Xc9wLLJuqaUIPrPv_g2V7T347FcVmaNKMrjNf2Kpb0,6195
97
+ frontengine/utils/multi_language/france.py,sha256=_N3gNqYsaLqOty8jUrF_ghA_uxwQ72jJzjG3i7_M6WQ,7197
98
+ frontengine/utils/multi_language/germany.py,sha256=RXJ-v9PViP9UkQq_jTj19fFlAhkp4G6IhvcgmJ8Eoag,6898
99
+ frontengine/utils/multi_language/italy.py,sha256=WALzKGHm3iWlUrgKW7qM3YjPJ_bRT--dCg8qDSoEn7o,6974
90
100
  frontengine/utils/multi_language/language_wrapper.py,sha256=GpQxvMlDMiHOAp71Ki0bOM0sL5kiI9tszpE1fQCZC14,1588
91
- frontengine/utils/multi_language/russian.py,sha256=roDQ_TIbbk5B0kOr6sJEjeDMJZGqloz43oapIcaR8PE,8326
92
- frontengine/utils/multi_language/simplified_chinese.py,sha256=wDnne4PiVA3eJ9Q4sxiJ-n_81E-42hi6608698LwsPA,6076
93
- frontengine/utils/multi_language/traditional_chinese.py,sha256=SSE338u2Y_-N0fumIVeBBRhnvjizT92tQdYcOJiMSFM,6083
101
+ frontengine/utils/multi_language/russian.py,sha256=KoORJ56Cjt_qJekBopHIolXjbeu5DRrM2cj6i9-v66o,8821
102
+ frontengine/utils/multi_language/simplified_chinese.py,sha256=ViN7N2XXdscSJmxnefAh7IpSK53-SLMypmxtCZcvv7Y,6403
103
+ frontengine/utils/multi_language/traditional_chinese.py,sha256=Xd4i4uiJz6zyssVPAxEAcU-WzjzkbcUoeI3X9KLNEEU,6413
94
104
  frontengine/utils/redirect_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
105
  frontengine/utils/redirect_manager/redirect_manager_class.py,sha256=zGJeVpjRU12MCnhVAdksAIhK_IhddI4cNKVb7DMgOZA,1888
96
- frontengine_dev-0.0.65.dist-info/LICENSE,sha256=b3VlPBXnrDylKGffOEOLWMgOX-yfd65XC7PA1_sox2o,1085
97
- frontengine_dev-0.0.65.dist-info/METADATA,sha256=HdVEMczSvcydGKn4yMX_bvYQFVgHnTIsLghi_95JQTQ,2055
98
- frontengine_dev-0.0.65.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
99
- frontengine_dev-0.0.65.dist-info/top_level.txt,sha256=btCybScN_ubeQ8phsSDBB0T-HyHjqt7b-WPy61uTox0,12
100
- frontengine_dev-0.0.65.dist-info/RECORD,,
106
+ frontengine/worker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
+ frontengine/worker/qthread_worker.py,sha256=TcmRv4PUlWxYLzMoB_6fUefEZpVhNy5D6_hhShAdKzU,875
108
+ frontengine_dev-0.0.71.dist-info/LICENSE,sha256=b3VlPBXnrDylKGffOEOLWMgOX-yfd65XC7PA1_sox2o,1085
109
+ frontengine_dev-0.0.71.dist-info/METADATA,sha256=k57XkdyAxbNc1_7MMFJEn75IyRk5ZYriq2xUaw0SpGI,2170
110
+ frontengine_dev-0.0.71.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
111
+ frontengine_dev-0.0.71.dist-info/top_level.txt,sha256=btCybScN_ubeQ8phsSDBB0T-HyHjqt7b-WPy61uTox0,12
112
+ frontengine_dev-0.0.71.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5