fspachinko 0.0.2__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.
- fspachinko/__init__.py +6 -0
- fspachinko/_data/configs/fspachinko.json +60 -0
- fspachinko/_data/configs/logging.json +36 -0
- fspachinko/_data/icons/add_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
- fspachinko/_data/icons/close_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
- fspachinko/_data/icons/file_open_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
- fspachinko/_data/icons/folder_open_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
- fspachinko/_data/icons/icon.icns +0 -0
- fspachinko/_data/icons/icon.ico +0 -0
- fspachinko/_data/icons/play_arrow_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
- fspachinko/_data/icons/remove_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
- fspachinko/_data/icons/save_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
- fspachinko/_data/icons/save_as_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
- fspachinko/_data/icons/stop_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
- fspachinko/_data/icons/sync_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
- fspachinko/_data/icons/windowIcon.png +0 -0
- fspachinko/cli/__init__.py +1 -0
- fspachinko/cli/__main__.py +19 -0
- fspachinko/cli/app.py +62 -0
- fspachinko/cli/observer.py +37 -0
- fspachinko/config/__init__.py +39 -0
- fspachinko/config/config.py +213 -0
- fspachinko/config/converter.py +163 -0
- fspachinko/config/schemas.py +96 -0
- fspachinko/core/__init__.py +20 -0
- fspachinko/core/builder.py +92 -0
- fspachinko/core/engine.py +129 -0
- fspachinko/core/quota.py +46 -0
- fspachinko/core/reporter.py +55 -0
- fspachinko/core/state.py +300 -0
- fspachinko/core/transfer.py +100 -0
- fspachinko/core/validator.py +70 -0
- fspachinko/core/walker.py +184 -0
- fspachinko/gui/__init__.py +1 -0
- fspachinko/gui/__main__.py +43 -0
- fspachinko/gui/actions.py +68 -0
- fspachinko/gui/centralwidget.py +70 -0
- fspachinko/gui/components.py +581 -0
- fspachinko/gui/mainwindow.py +153 -0
- fspachinko/gui/observer.py +54 -0
- fspachinko/gui/qthelpers.py +102 -0
- fspachinko/gui/settings.py +53 -0
- fspachinko/gui/uibuilder.py +127 -0
- fspachinko/gui/workers.py +56 -0
- fspachinko/utils/__init__.py +89 -0
- fspachinko/utils/constants.py +212 -0
- fspachinko/utils/helpers.py +143 -0
- fspachinko/utils/interfaces.py +35 -0
- fspachinko/utils/loggers.py +16 -0
- fspachinko/utils/paths.py +33 -0
- fspachinko/utils/timestamp.py +29 -0
- fspachinko-0.0.2.dist-info/METADATA +322 -0
- fspachinko-0.0.2.dist-info/RECORD +56 -0
- fspachinko-0.0.2.dist-info/WHEEL +4 -0
- fspachinko-0.0.2.dist-info/entry_points.txt +5 -0
- fspachinko-0.0.2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Actions module for QActions."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
|
|
5
|
+
from PySide6.QtGui import QAction, QIcon
|
|
6
|
+
|
|
7
|
+
from ..utils import IconFilename, Paths
|
|
8
|
+
from .components import set_qt_tips
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(slots=True)
|
|
12
|
+
class FileActions:
|
|
13
|
+
"""Main file menu actions."""
|
|
14
|
+
|
|
15
|
+
save: QAction = field(init=False)
|
|
16
|
+
save_as: QAction = field(init=False)
|
|
17
|
+
load: QAction = field(init=False)
|
|
18
|
+
autosave: QAction = field(init=False)
|
|
19
|
+
exit: QAction = field(init=False)
|
|
20
|
+
|
|
21
|
+
def __post_init__(self) -> None:
|
|
22
|
+
"""Initialize the main actions."""
|
|
23
|
+
self.save = QAction(icon=QIcon(Paths.icon(IconFilename.SAVE)), text="&Save Profile")
|
|
24
|
+
self.save.setShortcut("Ctrl+S")
|
|
25
|
+
set_qt_tips(self.save, "Save current GUI profile (Ctrl+S)")
|
|
26
|
+
|
|
27
|
+
self.save_as = QAction(icon=QIcon(Paths.icon(IconFilename.SAVE_AS)), text="Save Profile &As")
|
|
28
|
+
self.save_as.setShortcut("Ctrl+Shift+S")
|
|
29
|
+
set_qt_tips(self.save_as, "Save current GUI profile as ... (Ctrl+Shift+S)")
|
|
30
|
+
|
|
31
|
+
self.load = QAction(icon=QIcon(Paths.icon(IconFilename.OPEN)), text="&Load Profile")
|
|
32
|
+
self.load.setShortcut("Ctrl+O")
|
|
33
|
+
set_qt_tips(self.load, "Load GUI profile (Ctrl+O)")
|
|
34
|
+
|
|
35
|
+
self.autosave = QAction(
|
|
36
|
+
icon=QIcon(Paths.icon(IconFilename.AUTOSAVE)), text="A&utosave Profile", checkable=True, checked=True
|
|
37
|
+
)
|
|
38
|
+
set_qt_tips(self.autosave, "Automatically save profile on exit")
|
|
39
|
+
|
|
40
|
+
self.exit = QAction(icon=QIcon(Paths.icon(IconFilename.CLOSE)), text="&Exit")
|
|
41
|
+
self.exit.setShortcut("Ctrl+W")
|
|
42
|
+
set_qt_tips(self.exit, "Exit application (Ctrl+W)")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(slots=True)
|
|
46
|
+
class RunActions:
|
|
47
|
+
"""Main run actions."""
|
|
48
|
+
|
|
49
|
+
start: QAction = field(init=False)
|
|
50
|
+
stop: QAction = field(init=False)
|
|
51
|
+
|
|
52
|
+
def __post_init__(self) -> None:
|
|
53
|
+
"""Initialize the main actions."""
|
|
54
|
+
self.start = QAction(icon=QIcon(Paths.icon(IconFilename.START)), text="&Start")
|
|
55
|
+
self.start.setShortcut("Ctrl+R")
|
|
56
|
+
set_qt_tips(self.start, "Start (Ctrl+R)")
|
|
57
|
+
|
|
58
|
+
self.stop = QAction(icon=QIcon(Paths.icon(IconFilename.STOP)), text="S&top")
|
|
59
|
+
self.stop.setShortcut("ESC")
|
|
60
|
+
set_qt_tips(self.stop, "Stop (ESC)")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass(slots=True)
|
|
64
|
+
class Actions:
|
|
65
|
+
"""Main actions."""
|
|
66
|
+
|
|
67
|
+
file: FileActions = field(default_factory=FileActions)
|
|
68
|
+
run: RunActions = field(default_factory=RunActions)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Main module."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from PySide6.QtCore import Slot
|
|
6
|
+
from PySide6.QtWidgets import QGroupBox, QWidget
|
|
7
|
+
|
|
8
|
+
from ..utils import PERCENTAGE_100, GUIName
|
|
9
|
+
from .components import ProgressBinder
|
|
10
|
+
from .qthelpers import set_qt_name
|
|
11
|
+
from .uibuilder import UIBuilder
|
|
12
|
+
from .workers import MainThread, MainWorker
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CentralWidget(QWidget):
|
|
18
|
+
"""Main application window."""
|
|
19
|
+
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
"""Initialize the main window."""
|
|
22
|
+
super().__init__()
|
|
23
|
+
set_qt_name(self, GUIName.CENTRAL_WIDGET)
|
|
24
|
+
self.main_thread: MainThread | None = None
|
|
25
|
+
self.ui = UIBuilder()
|
|
26
|
+
layout = self.ui.build_layout()
|
|
27
|
+
self.setLayout(layout)
|
|
28
|
+
self.progress_binder = ProgressBinder(self.ui.progress, self.ui.logging)
|
|
29
|
+
self.window_title_original = ""
|
|
30
|
+
|
|
31
|
+
@Slot()
|
|
32
|
+
def on_start(self) -> None:
|
|
33
|
+
"""Start the process and disable UI elements."""
|
|
34
|
+
try:
|
|
35
|
+
config = self.ui.get_config()
|
|
36
|
+
except Exception:
|
|
37
|
+
logger.exception("")
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
self.main_thread = MainThread(MainWorker.from_config(config))
|
|
41
|
+
self.ui.progress.reset()
|
|
42
|
+
self.window_title_original = self.window().windowTitle()
|
|
43
|
+
self.progress_binder.bind(self.main_thread.worker.signals)
|
|
44
|
+
self.progress_binder.count.connect(self.update_title_progress)
|
|
45
|
+
self.progress_binder.finished.connect(self.on_finished)
|
|
46
|
+
self.toggle_ui(is_enabled=False)
|
|
47
|
+
self.main_thread.start()
|
|
48
|
+
|
|
49
|
+
@Slot()
|
|
50
|
+
def on_stop(self) -> None:
|
|
51
|
+
"""Stop the process."""
|
|
52
|
+
if self.main_thread and self.main_thread.isRunning():
|
|
53
|
+
self.main_thread.stop()
|
|
54
|
+
|
|
55
|
+
@Slot(int)
|
|
56
|
+
def update_title_progress(self, val: int) -> None:
|
|
57
|
+
"""Update window title with progress percentage."""
|
|
58
|
+
pct = int((val / self.ui.progress.progbar_dir.maximum()) * PERCENTAGE_100)
|
|
59
|
+
self.window().setWindowTitle(f"[{pct}%] {self.window_title_original}")
|
|
60
|
+
|
|
61
|
+
@Slot()
|
|
62
|
+
def on_finished(self) -> None:
|
|
63
|
+
"""Handle worker finished signal."""
|
|
64
|
+
self.toggle_ui(is_enabled=True)
|
|
65
|
+
self.window().setWindowTitle(self.window_title_original)
|
|
66
|
+
|
|
67
|
+
def toggle_ui(self, *, is_enabled: bool) -> None:
|
|
68
|
+
"""Lock or unlock UI elements."""
|
|
69
|
+
for child in self.findChildren(QGroupBox):
|
|
70
|
+
child.setEnabled(is_enabled)
|