Skip to content

Commit

Permalink
Close to first releasable version
Browse files Browse the repository at this point in the history
  • Loading branch information
Gazoo101 committed Feb 26, 2023
1 parent 7a2816c commit 08e349e
Show file tree
Hide file tree
Showing 14 changed files with 558 additions and 187 deletions.
2 changes: 2 additions & 0 deletions freeze-lyricmanager.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
REM Builds LyricManager GUI. Read commentary in setup.py.
python freeze.py build
66 changes: 66 additions & 0 deletions freeze.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
A cx_Freeze-based packaging/freezing script for LyricManager.
Execute this build script be either:
- Running freeze-lyricmanager.bat (in the right Python Venv)
- Executing 'Python freeze.py build' (in the right Python Venv)
Python 3.8+ is required as it (apparently) handles packaging/freezing libraries in a different (better) manner.
See this discussion with cx_Freeze maintainer: https://github.com/marcelotduarte/cx_Freeze/issues/1498
"""
# Python
import sys
import os

# 3rd Party
from cx_Freeze import Executable, setup


# 1st Party
# According to this post: https://stackoverflow.com/questions/27496021/cx-freeze-including-my-own-modules
# Setup-tools / cx-Freeze apparently discovers local modules by having the sys.path modified.


# The base primarily determines whether a command-line window will be shown during execution or not.
base = None
# While LyricManager is under heavy development, we want the command-line window to show
# if sys.platform == "win32":
# base = "Win32GUI"

options = {
"build_exe": {
# Circular import failures (previously caused by svspy importing sklearn) can be resolved by explicitly
# adding parts of the packages triggering the circular imports, as shown below.
# Consider explicitly including one or more of these if circular import error occurs.
# "packages": [
# "scipy.optimize",
# "scipy.integrate"
# ],
# exclude packages that are not really needed
"excludes": [
"tkinter",
"unittest", # Including svspy triggers this package to be required
#"email", # Needed by .genius?
"xml",
#"pydoc", # it was needed by svspy?
],
"include_files": [
("resources/lyric_manager_v3.ui", "resources/lyric_manager_v3.ui")
]
}
}

executables = [Executable(
"lyric_manager_gui.py",
base=base
#icon="resources/nameofanicon.ico"
)]

setup(
name="LyricManager",
version="0.1",
description="A lyric management tool.",
options=options,
executables=executables,
)
263 changes: 164 additions & 99 deletions lyric_manager_gui.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions resources/lyric_manager_v2.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>923</width>
<width>1091</width>
<height>762</height>
</rect>
</property>
Expand Down Expand Up @@ -143,7 +143,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>923</width>
<width>1091</width>
<height>22</height>
</rect>
</property>
Expand Down
182 changes: 182 additions & 0 deletions resources/lyric_manager_v3.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>979</width>
<height>789</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QProgressBar" name="progressBar_overall">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="value">
<number>24</number>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_start_processing">
<property name="minimumSize">
<size>
<width>130</width>
<height>40</height>
</size>
</property>
<property name="text">
<string>Start Processing</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QSplitter" name="splitter_horizontal">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="widget_4" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Lyric Sources</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listWidget_lyricSources"/>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Lyric Aligners</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listWidget_lyricAligners"/>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Folders to process</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listWidget_localDataSources"/>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QCheckBox" name="checkBox_recursively_parse_folders_to_process">
<property name="text">
<string>Recursively parse folders to process</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_overwrite_existing_generated_files">
<property name="text">
<string>Overwrite existing generated files</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="widget_5" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QSplitter" name="splitter_vertical">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTableWidget" name="tableWidget_songs_processed">
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>120</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<column>
<property name="text">
<string>Filename</string>
</property>
</column>
<column>
<property name="text">
<string>Progress</string>
</property>
</column>
<column>
<property name="text">
<string>Note</string>
</property>
</column>
</widget>
<widget class="QPlainTextEdit" name="plainTextEdit_log">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>979</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
5 changes: 3 additions & 2 deletions src/developer_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class DeveloperOptions():


""" Major options """
version = 0.2
version = 0.4

class ExecutionMode(Enum):
# Standard internal release. Should override all debugging related options.
Expand All @@ -38,7 +38,8 @@ def is_release(cls):
# The Qt Gui uses multi-threading to allow the interface to remain responsive while performing computationally
# intensive work. Settings this flag to false forces LyricManager to be single-threaded, significantly easing debugging
# and developing new code.
gui_multithreading_enabled = False
gui_multithreading_enabled = True
#gui_multithreading_enabled = False

@classmethod
def is_multithreading_enabled(cls):
Expand Down
1 change: 1 addition & 0 deletions src/gui/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .gui_worker import GuiWorker
from .qlistwidget_drag_and_drop import QListWidgetDragAndDrop
from .logging_handler_signal import LoggingHandlerSignal
from .progress_item_generator_gui import ProgressItemGeneratorGUI
59 changes: 59 additions & 0 deletions src/gui/gui_worker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Python
import sys
import logging
import traceback

# 3rd Party
# The error "version `GLIBC_2.28' not found" will occur on Ubuntu 18.04, as Qt6 requires Ubuntu 20.04
from PySide6 import QtCore


# 1st Party


class WorkerSignals(QtCore.QObject):
""" Defines a small set of signals to be provided via worker a thread, defined below. """
finished = QtCore.Signal(object)
progress = QtCore.Signal(float)
task_description = QtCore.Signal(str)
error = QtCore.Signal(tuple)
# result = QtCore.Signal(object)


# Inspiration: https://www.pythonguis.com/tutorials/multithreading-pyside6-applications-qthreadpool/
class GuiWorker(QtCore.QRunnable):
""" A simple worker class accepting a single function along with arguments to be passed to it upon execution. """

def __init__(self, fn, *args, **kwargs):
super(GuiWorker, self).__init__()

# Store constructor arguments (re-used for processing)
self.fn = fn
self.args = args
self.kwargs = kwargs

self.signals = WorkerSignals()

def set_fn(self, fn, *args, **kwargs):
self.fn = fn
self.args = args
self.kwargs = kwargs

# At the time of writing, it is unclear to me if this function benefits from being declared a @QtCore.Slot().
# It depends on whether the function is triggered via a Signal or not, I think.
@QtCore.Slot()
def run(self):
""" Executes self.fn with the provided parameters in self.args and self.kwargs. """
try:
logging.info(f"worker executing: {self.kwargs}")
# result currently remains unused.
result = self.fn(*self.args, **self.kwargs)
#result = self.fn(*self.args, **self.kwargs, progress=self.signals.progress)
except:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
# else:
# self.signals.result.emit(result) # Return the result of the processing
finally:
self.signals.finished.emit(result) # Done
Loading

0 comments on commit 08e349e

Please sign in to comment.