aboutsummaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/actions.py69
-rw-r--r--src/gui/mainwindow.py648
-rw-r--r--src/gui/presetmanager.py157
-rw-r--r--src/gui/preview_thread.py50
-rw-r--r--src/gui/preview_win.py45
5 files changed, 471 insertions, 498 deletions
diff --git a/src/gui/actions.py b/src/gui/actions.py
index afb980a..654b2a0 100644
--- a/src/gui/actions.py
+++ b/src/gui/actions.py
@@ -1,53 +1,61 @@
-'''
- QCommand classes for every undoable user action performed in the MainWindow
-'''
-from PyQt5.QtWidgets import QUndoCommand
+"""
+QCommand classes for every undoable user action performed in the MainWindow
+"""
+
+from PyQt6.QtGui import QUndoCommand
import os
+import logging
from copy import copy
from ..core import Core
+log = logging.getLogger("AVP.Gui.Actions")
+
+
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
# COMPONENT ACTIONS
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
+
class AddComponent(QUndoCommand):
def __init__(self, parent, compI, moduleI):
super().__init__(
- "create new %s component" %
- parent.core.modules[moduleI].Component.name
+ "create new %s component" % parent.core.modules[moduleI].Component.name
)
self.parent = parent
self.moduleI = moduleI
self.compI = compI
self.comp = None
+ self.valid = True
def redo(self):
if self.comp is None:
- self.parent.core.insertComponent(
- self.compI, self.moduleI, self.parent)
+ i = self.parent.core.insertComponent(self.compI, self.moduleI, self.parent)
+ if i != self.compI:
+ self.valid = False
+ if i is not None:
+ log.error(
+ f"Expected new component index to be {self.compI} but received {i}"
+ )
else:
# inserting previously-created component
- self.parent.core.insertComponent(
- self.compI, self.comp, self.parent)
+ self.parent.core.insertComponent(self.compI, self.comp, self.parent)
def undo(self):
+ if not self.valid:
+ return
self.comp = self.parent.core.selectedComponents[self.compI]
self.parent._removeComponent(self.compI)
class RemoveComponent(QUndoCommand):
def __init__(self, parent, selectedRows):
- super().__init__('remove component')
+ super().__init__("remove component")
self.parent = parent
componentList = self.parent.listWidget_componentList
- self.selectedRows = [
- componentList.row(selected) for selected in selectedRows
- ]
- self.components = [
- parent.core.selectedComponents[i] for i in self.selectedRows
- ]
+ self.selectedRows = [componentList.row(selected) for selected in selectedRows]
+ self.components = [parent.core.selectedComponents[i] for i in self.selectedRows]
def redo(self):
self.parent._removeComponent(self.selectedRows[0])
@@ -55,9 +63,7 @@ class RemoveComponent(QUndoCommand):
def undo(self):
componentList = self.parent.listWidget_componentList
for index, comp in zip(self.selectedRows, self.components):
- self.parent.core.insertComponent(
- index, comp, self.parent
- )
+ self.parent.core.insertComponent(index, comp, self.parent)
self.parent.drawPreview()
@@ -70,7 +76,7 @@ class MoveComponent(QUndoCommand):
self.id_ = ord(tag[0])
def id(self):
- '''If 2 consecutive updates have same id, Qt will call mergeWith()'''
+ """If 2 consecutive updates have same id, Qt will call mergeWith()"""
return self.id_
def mergeWith(self, other):
@@ -105,6 +111,7 @@ class MoveComponent(QUndoCommand):
# PRESET ACTIONS
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
+
class ClearPreset(QUndoCommand):
def __init__(self, parent, compI):
super().__init__("clear preset")
@@ -112,7 +119,7 @@ class ClearPreset(QUndoCommand):
self.compI = compI
self.component = self.parent.core.selectedComponents[compI]
self.store = self.component.savePreset()
- self.store['preset'] = self.component.currentPreset
+ self.store["preset"] = self.component.currentPreset
def redo(self):
self.parent.core.clearPreset(self.compI)
@@ -132,20 +139,19 @@ class OpenPreset(QUndoCommand):
comp = self.parent.core.selectedComponents[compI]
self.store = comp.savePreset()
- self.store['preset'] = copy(comp.currentPreset)
+ self.store["preset"] = copy(comp.currentPreset)
def redo(self):
self.parent._openPreset(self.presetName, self.compI)
def undo(self):
- self.parent.core.selectedComponents[self.compI].loadPreset(
- self.store)
+ self.parent.core.selectedComponents[self.compI].loadPreset(self.store)
self.parent.parent.updateComponentTitle(self.compI, self.store)
class RenamePreset(QUndoCommand):
def __init__(self, parent, path, oldName, newName):
- super().__init__('rename preset')
+ super().__init__("rename preset")
self.parent = parent
self.path = path
self.oldName = oldName
@@ -162,14 +168,13 @@ class DeletePreset(QUndoCommand):
def __init__(self, parent, compName, vers, presetFile):
self.parent = parent
self.preset = (compName, vers, presetFile)
- self.path = os.path.join(
- Core.presetDir, compName, str(vers), presetFile
- )
+ self.path = os.path.join(Core.presetDir, compName, str(vers), presetFile)
self.store = self.parent.core.getPreset(self.path)
- self.presetName = self.store['preset']
- super().__init__('delete %s preset (%s)' % (self.presetName, compName))
+ self.presetName = self.store["preset"]
+ super().__init__("delete %s preset (%s)" % (self.presetName, compName))
self.loadedPresets = [
- i for i, comp in enumerate(self.parent.core.selectedComponents)
+ i
+ for i, comp in enumerate(self.parent.core.selectedComponents)
if self.presetName == str(comp.currentPreset)
]
diff --git a/src/gui/mainwindow.py b/src/gui/mainwindow.py
index 159dc02..b0a564b 100644
--- a/src/gui/mainwindow.py
+++ b/src/gui/mainwindow.py
@@ -1,11 +1,13 @@
-'''
- When using GUI mode, this module's object (the main window) takes
- user input to construct a program state (stored in the Core object).
- This shows a preview of the video being created and allows for saving
- projects and exporting the video at a later time.
-'''
-from PyQt5 import QtCore, QtWidgets, uic
-import PyQt5.QtWidgets as QtWidgets
+"""
+When using GUI mode, this module's object (the main window) takes
+user input to construct a program state (stored in the Core object).
+This shows a preview of the video being created and allows for saving
+projects and exporting the video at a later time.
+"""
+
+from PyQt6 import QtCore, QtWidgets, uic
+import PyQt6.QtWidgets as QtWidgets
+from PyQt6.QtGui import QUndoStack, QShortcut
from PIL import Image
from queue import Queue
import sys
@@ -21,46 +23,59 @@ from .preview_win import PreviewWindow
from .presetmanager import PresetManager
from .actions import *
from ..toolkit import (
- disableWhenEncoding, disableWhenOpeningProject, checkOutput, blockSignals
+ disableWhenEncoding,
+ disableWhenOpeningProject,
+ checkOutput,
+ blockSignals,
)
-appName = 'Audio Visualizer'
-log = logging.getLogger('AVP.Gui.MainWindow')
+appName = "Audio Visualizer"
+log = logging.getLogger("AVP.Gui.MainWindow")
+
+
+class MyQUndoStack(QUndoStack):
+ # FIXME move this class
+ @property
+ def encoding(self):
+ return self.parent().encoding
+
+ @disableWhenEncoding
+ def undo(self, *args, **kwargs):
+ super().undo(*args, **kwargs)
+
+ @disableWhenEncoding
+ def redo(self, *args, **kwargs):
+ super().redo(*args, **kwargs)
class MainWindow(QtWidgets.QMainWindow):
- '''
- The MainWindow wraps many Core methods in order to update the GUI
- accordingly. E.g., instead of self.core.openProject(), it will use
- self.openProject() and update the window titlebar within the wrapper.
+ """
+ The MainWindow wraps many Core methods in order to update the GUI
+ accordingly. E.g., instead of self.core.openProject(), it will use
+ self.openProject() and update the window titlebar within the wrapper.
- MainWindow manages the autosave feature, although Core has the
- primary functions for opening and creating project files.
- '''
+ MainWindow manages the autosave feature, although Core has the
+ primary functions for opening and creating project files.
+ """
createVideo = QtCore.pyqtSignal()
newTask = QtCore.pyqtSignal(list) # for the preview window
processTask = QtCore.pyqtSignal()
- def __init__(self, project):
+ def __init__(self, project, dpi):
super().__init__()
- log.debug(
- 'Main thread id: {}'.format(int(QtCore.QThread.currentThreadId())))
+ log.debug("Main thread id: {}".format(int(QtCore.QThread.currentThreadId())))
uic.loadUi(os.path.join(Core.wd, "gui", "mainwindow.ui"), self)
- desk = QtWidgets.QDesktopWidget()
- dpi = desk.physicalDpiX()
- log.info("Detected screen DPI: %s", dpi)
-
- self.resize(
- int(self.width() *
- (dpi / 144)),
- int(self.height() *
- (dpi / 144))
- )
+
+ if dpi:
+ self.resize(
+ int(self.width() * (dpi / 144)),
+ int(self.height() * (dpi / 144)),
+ )
self.core = Core()
- Core.mode = 'GUI'
+ Core.mode = "GUI"
# widgets of component settings
self.pages = []
self.lastAutosave = time.time()
@@ -72,15 +87,13 @@ class MainWindow(QtWidgets.QMainWindow):
# Find settings created by Core object
self.dataDir = Core.dataDir
self.presetDir = Core.presetDir
- self.autosavePath = os.path.join(self.dataDir, 'autosave.avp')
+ self.autosavePath = os.path.join(self.dataDir, "autosave.avp")
self.settings = Core.settings
# Create stack of undoable user actions
- self.undoStack = QtWidgets.QUndoStack(self)
+ self.undoStack = MyQUndoStack(self)
undoLimit = self.settings.value("pref_undoLimit")
self.undoStack.setUndoLimit(undoLimit)
- self.undoStack.undo = disableWhenEncoding(self.undoStack.undo)
- self.undoStack.redo = disableWhenEncoding(self.undoStack.redo)
# Create Undo Dialog - A standard QUndoView on a standard QDialog
self.undoDialog = QtWidgets.QDialog(self)
@@ -94,18 +107,17 @@ class MainWindow(QtWidgets.QMainWindow):
self.presetManager = PresetManager(self)
# Create the preview window and its thread, queues, and timers
- log.debug('Creating preview window')
- self.previewWindow = PreviewWindow(self, os.path.join(
- Core.wd, 'gui', "background.png"))
+ log.debug("Creating preview window")
+ self.previewWindow = PreviewWindow(
+ self, os.path.join(Core.wd, "gui", "background.png")
+ )
self.verticalLayout_previewWrapper.addWidget(self.previewWindow)
- log.debug('Starting preview thread')
+ log.debug("Starting preview thread")
self.previewQueue = Queue()
self.previewThread = QtCore.QThread(self)
self.previewWorker = preview_thread.Worker(
- self.core,
- self.settings,
- self.previewQueue
+ self.core, self.settings, self.previewQueue
)
self.previewWorker.moveToThread(self.previewThread)
self.newTask.connect(self.previewWorker.createPreviewImage)
@@ -113,12 +125,12 @@ class MainWindow(QtWidgets.QMainWindow):
self.previewWorker.error.connect(self.previewWindow.threadError)
self.previewWorker.imageCreated.connect(self.showPreviewImage)
self.previewThread.start()
- self.previewThread.finished.connect(lambda: log.info('Preview thread finished.'))
+ self.previewThread.finished.connect(
+ lambda: log.info("Preview thread finished.")
+ )
timeout = 500
- log.debug(
- 'Preview timer set to trigger when idle for %sms' % str(timeout)
- )
+ log.debug("Preview timer set to trigger when idle for %sms" % str(timeout))
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.processTask.emit)
self.timer.start(timeout)
@@ -128,7 +140,7 @@ class MainWindow(QtWidgets.QMainWindow):
# Undo Feature
def toggleUndoButtonEnabled(*_):
- """ Enable/disable undo button depending on whether UndoStack contains Actions """
+ """Enable/disable undo button depending on whether UndoStack contains Actions"""
try:
undoButton.setEnabled(self.undoStack.count())
except RuntimeError:
@@ -138,50 +150,41 @@ class MainWindow(QtWidgets.QMainWindow):
style = self.pushButton_undo.style()
undoButton = self.pushButton_undo
undoButton.setIcon(
- style.standardIcon(QtWidgets.QStyle.SP_FileDialogBack)
+ style.standardIcon(QtWidgets.QStyle.StandardPixmap.SP_FileDialogBack)
)
undoButton.clicked.connect(self.undoStack.undo)
undoButton.setEnabled(False)
self.undoStack.cleanChanged.connect(toggleUndoButtonEnabled)
self.undoMenu = QtWidgets.QMenu()
- self.undoMenu.addAction(
- self.undoStack.createUndoAction(self)
- )
- self.undoMenu.addAction(
- self.undoStack.createRedoAction(self)
- )
- action = self.undoMenu.addAction('Show History...')
- action.triggered.connect(
- lambda _: self.showUndoStack()
- )
+ self.undoMenu.addAction(self.undoStack.createUndoAction(self))
+ self.undoMenu.addAction(self.undoStack.createRedoAction(self))
+ action = self.undoMenu.addAction("Show History...")
+ action.triggered.connect(lambda _: self.showUndoStack())
undoButton.setMenu(self.undoMenu)
# end of Undo Feature
style = self.pushButton_listMoveUp.style()
self.pushButton_listMoveUp.setIcon(
- style.standardIcon(QtWidgets.QStyle.SP_ArrowUp)
+ style.standardIcon(QtWidgets.QStyle.StandardPixmap.SP_ArrowUp)
)
style = self.pushButton_listMoveDown.style()
self.pushButton_listMoveDown.setIcon(
- style.standardIcon(QtWidgets.QStyle.SP_ArrowDown)
+ style.standardIcon(QtWidgets.QStyle.StandardPixmap.SP_ArrowDown)
)
style = self.pushButton_removeComponent.style()
self.pushButton_removeComponent.setIcon(
- style.standardIcon(QtWidgets.QStyle.SP_DialogDiscardButton)
+ style.standardIcon(QtWidgets.QStyle.StandardPixmap.SP_DialogDiscardButton)
)
- if sys.platform == 'darwin':
- log.debug(
- 'Darwin detected: showing progress label below progress bar')
+ if sys.platform == "darwin":
+ log.debug("Darwin detected: showing progress label below progress bar")
self.progressBar_createVideo.setTextVisible(False)
else:
self.progressLabel.setHidden(True)
- self.toolButton_selectAudioFile.clicked.connect(
- self.openInputFileDialog)
+ self.toolButton_selectAudioFile.clicked.connect(self.openInputFileDialog)
- self.toolButton_selectOutputFile.clicked.connect(
- self.openOutputFileDialog)
+ self.toolButton_selectOutputFile.clicked.connect(self.openOutputFileDialog)
def changedField():
self.autosave()
@@ -192,43 +195,36 @@ class MainWindow(QtWidgets.QMainWindow):
self.progressBar_createVideo.setValue(0)
- self.pushButton_createVideo.clicked.connect(
- self.createAudioVisualization)
+ self.pushButton_createVideo.clicked.connect(self.createAudioVisualization)
self.pushButton_Cancel.clicked.connect(self.stopVideo)
- for i, container in enumerate(Core.encoderOptions['containers']):
- self.comboBox_videoContainer.addItem(container['name'])
- if container['name'] == self.settings.value('outputContainer'):
+ for i, container in enumerate(Core.encoderOptions["containers"]):
+ self.comboBox_videoContainer.addItem(container["name"])
+ if container["name"] == self.settings.value("outputContainer"):
selectedContainer = i
self.comboBox_videoContainer.setCurrentIndex(selectedContainer)
- self.comboBox_videoContainer.currentIndexChanged.connect(
- self.updateCodecs
- )
+ self.comboBox_videoContainer.currentIndexChanged.connect(self.updateCodecs)
self.updateCodecs()
for i in range(self.comboBox_videoCodec.count()):
codec = self.comboBox_videoCodec.itemText(i)
- if codec == self.settings.value('outputVideoCodec'):
+ if codec == self.settings.value("outputVideoCodec"):
self.comboBox_videoCodec.setCurrentIndex(i)
for i in range(self.comboBox_audioCodec.count()):
codec = self.comboBox_audioCodec.itemText(i)
- if codec == self.settings.value('outputAudioCodec'):
+ if codec == self.settings.value("outputAudioCodec"):
self.comboBox_audioCodec.setCurrentIndex(i)
- self.comboBox_videoCodec.currentIndexChanged.connect(
- self.updateCodecSettings
- )
+ self.comboBox_videoCodec.currentIndexChanged.connect(self.updateCodecSettings)
- self.comboBox_audioCodec.currentIndexChanged.connect(
- self.updateCodecSettings
- )
+ self.comboBox_audioCodec.currentIndexChanged.connect(self.updateCodecSettings)
- vBitrate = int(self.settings.value('outputVideoBitrate'))
- aBitrate = int(self.settings.value('outputAudioBitrate'))
+ vBitrate = int(self.settings.value("outputVideoBitrate"))
+ aBitrate = int(self.settings.value("outputAudioBitrate"))
self.spinBox_vBitrate.setValue(vBitrate)
self.spinBox_aBitrate.setValue(aBitrate)
@@ -239,30 +235,27 @@ class MainWindow(QtWidgets.QMainWindow):
self.compMenu = QtWidgets.QMenu()
for i, comp in enumerate(self.core.modules):
action = self.compMenu.addAction(comp.Component.name)
- action.triggered.connect(
- lambda _, item=i: self.addComponent(0, item)
- )
+ action.triggered.connect(lambda _, item=i: self.addComponent(0, item))
self.pushButton_addComponent.setMenu(self.compMenu)
componentList.dropEvent = self.dragComponent
- componentList.itemSelectionChanged.connect(
- self.changeComponentWidget
- )
+ componentList.itemSelectionChanged.connect(self.changeComponentWidget)
componentList.itemSelectionChanged.connect(
self.presetManager.clearPresetListSelection
)
- self.pushButton_removeComponent.clicked.connect(
- lambda: self.removeComponent()
- )
+ self.pushButton_removeComponent.clicked.connect(lambda: self.removeComponent())
- componentList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
- componentList.customContextMenuRequested.connect(
- self.componentContextMenu
+ componentList.setContextMenuPolicy(
+ QtCore.Qt.ContextMenuPolicy.CustomContextMenu
)
+ componentList.customContextMenuRequested.connect(self.componentContextMenu)
- currentRes = str(self.settings.value('outputWidth'))+'x' + \
- str(self.settings.value('outputHeight'))
+ currentRes = (
+ str(self.settings.value("outputWidth"))
+ + "x"
+ + str(self.settings.value("outputHeight"))
+ )
for i, res in enumerate(Core.resolutions):
self.comboBox_resolution.addItem(res)
if res == currentRes:
@@ -272,24 +265,14 @@ class MainWindow(QtWidgets.QMainWindow):
self.updateResolution
)
- self.pushButton_listMoveUp.clicked.connect(
- lambda: self.moveComponent(-1)
- )
- self.pushButton_listMoveDown.clicked.connect(
- lambda: self.moveComponent(1)
- )
+ self.pushButton_listMoveUp.clicked.connect(lambda: self.moveComponent(-1))
+ self.pushButton_listMoveDown.clicked.connect(lambda: self.moveComponent(1))
# Configure the Projects Menu
self.projectMenu = QtWidgets.QMenu()
- self.menuButton_newProject = self.projectMenu.addAction(
- "New Project"
- )
- self.menuButton_newProject.triggered.connect(
- lambda: self.createNewProject()
- )
- self.menuButton_openProject = self.projectMenu.addAction(
- "Open Project"
- )
+ self.menuButton_newProject = self.projectMenu.addAction("New Project")
+ self.menuButton_newProject.triggered.connect(lambda: self.createNewProject())
+ self.menuButton_openProject = self.projectMenu.addAction("Open Project")
self.menuButton_openProject.triggered.connect(
lambda: self.openOpenProjectDialog()
)
@@ -303,22 +286,18 @@ class MainWindow(QtWidgets.QMainWindow):
self.pushButton_projects.setMenu(self.projectMenu)
# Configure the Presets Button
- self.pushButton_presets.clicked.connect(
- self.openPresetManager
- )
+ self.pushButton_presets.clicked.connect(self.openPresetManager)
self.updateWindowTitle()
- log.debug('Showing main window')
+ log.debug("Showing main window")
self.show()
if project and project != self.autosavePath:
- if not project.endswith('.avp'):
- project += '.avp'
+ if not project.endswith(".avp"):
+ project += ".avp"
# open a project from the commandline
if not os.path.dirname(project):
- project = os.path.join(
- self.settings.value("projectDir"), project
- )
+ project = os.path.join(self.settings.value("projectDir"), project)
self.currentProject = project
self.settings.setValue("currentProject", project)
if os.path.exists(self.autosavePath):
@@ -335,7 +314,8 @@ class MainWindow(QtWidgets.QMainWindow):
ch = self.showMessage(
msg="Restore unsaved changes in project '%s'?"
% os.path.basename(self.currentProject)[:-4],
- showCancel=True)
+ showCancel=True,
+ )
if ch:
self.saveProjectChanges()
else:
@@ -352,16 +332,16 @@ class MainWindow(QtWidgets.QMainWindow):
msg="FFmpeg could not be found. This is a critical error. "
"Install FFmpeg, or download it and place the program executable "
"in the same folder as this program.",
- icon='Critical'
+ icon="Critical",
)
else:
if not self.settings.value("ffmpegMsgShown"):
try:
with open(os.devnull, "w") as f:
ffmpegVers = checkOutput(
- [self.core.FFMPEG_BIN, '-version'], stderr=f
+ [self.core.FFMPEG_BIN, "-version"], stderr=f
)
- goodVersion = str(ffmpegVers).split()[2].startswith('4')
+ goodVersion = str(ffmpegVers).split()[2].startswith("4")
except Exception:
goodVersion = False
else:
@@ -375,70 +355,61 @@ class MainWindow(QtWidgets.QMainWindow):
self.settings.setValue("ffmpegMsgShown", True)
# Hotkeys for projects
- QtWidgets.QShortcut("Ctrl+S", self, self.saveCurrentProject)
- QtWidgets.QShortcut("Ctrl+A", self, self.openSaveProjectDialog)
- QtWidgets.QShortcut("Ctrl+O", self, self.openOpenProjectDialog)
- QtWidgets.QShortcut("Ctrl+N", self, self.createNewProject)
+
+ QShortcut("Ctrl+S", self, self.saveCurrentProject)
+ QShortcut("Ctrl+A", self, self.openSaveProjectDialog)
+ QShortcut("Ctrl+O", self, self.openOpenProjectDialog)
+ QShortcut("Ctrl+N", self, self.createNewProject)
# Hotkeys for undo/redo
- QtWidgets.QShortcut("Ctrl+Z", self, self.undoStack.undo)
- QtWidgets.QShortcut("Ctrl+Y", self, self.undoStack.redo)
- QtWidgets.QShortcut("Ctrl+Shift+Z", self, self.undoStack.redo)
+ QShortcut("Ctrl+Z", self, self.undoStack.undo)
+ QShortcut("Ctrl+Y", self, self.undoStack.redo)
+ QShortcut("Ctrl+Shift+Z", self, self.undoStack.redo)
# Hotkeys for component list
- for inskey in ("Ctrl+T", QtCore.Qt.Key_Insert):
- QtWidgets.QShortcut(
- inskey, self,
- activated=lambda: self.pushButton_addComponent.click()
- )
- for delkey in ("Ctrl+R", QtCore.Qt.Key_Delete):
- QtWidgets.QShortcut(
- delkey, self.listWidget_componentList,
- self.removeComponent
+ for inskey in ("Ctrl+T", QtCore.Qt.Key.Key_Insert):
+ QShortcut(
+ inskey,
+ self,
+ activated=lambda: self.pushButton_addComponent.click(),
)
- QtWidgets.QShortcut(
- "Ctrl+Space", self,
- activated=lambda: self.listWidget_componentList.setFocus()
- )
- QtWidgets.QShortcut(
- "Ctrl+Shift+S", self,
- self.presetManager.openSavePresetDialog
- )
- QtWidgets.QShortcut(
- "Ctrl+Shift+C", self, self.presetManager.clearPreset
+ for delkey in ("Ctrl+R", QtCore.Qt.Key.Key_Delete):
+ QShortcut(delkey, self.listWidget_componentList, self.removeComponent)
+ QShortcut(
+ "Ctrl+Space",
+ self,
+ activated=lambda: self.listWidget_componentList.setFocus(),
)
+ QShortcut("Ctrl+Shift+S", self, self.presetManager.openSavePresetDialog)
+ QShortcut("Ctrl+Shift+C", self, self.presetManager.clearPreset)
- QtWidgets.QShortcut(
- "Ctrl+Up", self.listWidget_componentList,
- activated=lambda: self.moveComponent(-1)
+ QShortcut(
+ "Ctrl+Up",
+ self.listWidget_componentList,
+ activated=lambda: self.moveComponent(-1),
)
- QtWidgets.QShortcut(
- "Ctrl+Down", self.listWidget_componentList,
- activated=lambda: self.moveComponent(1)
+ QShortcut(
+ "Ctrl+Down",
+ self.listWidget_componentList,
+ activated=lambda: self.moveComponent(1),
)
- QtWidgets.QShortcut(
- "Ctrl+Home", self.listWidget_componentList,
- activated=lambda: self.moveComponent('top')
+ QShortcut(
+ "Ctrl+Home",
+ self.listWidget_componentList,
+ activated=lambda: self.moveComponent("top"),
)
- QtWidgets.QShortcut(
- "Ctrl+End", self.listWidget_componentList,
- activated=lambda: self.moveComponent('bottom')
+ QShortcut(
+ "Ctrl+End",
+ self.listWidget_componentList,
+ activated=lambda: self.moveComponent("bottom"),
)
- QtWidgets.QShortcut(
- "Ctrl+Shift+F", self, self.showFfmpegCommand
- )
- QtWidgets.QShortcut(
- "Ctrl+Shift+U", self, self.showUndoStack
- )
+ QShortcut("Ctrl+Shift+F", self, self.showFfmpegCommand)
+ QShortcut("Ctrl+Shift+U", self, self.showUndoStack)
if log.isEnabledFor(logging.DEBUG):
- QtWidgets.QShortcut(
- "Ctrl+Alt+Shift+R", self, self.drawPreview
- )
- QtWidgets.QShortcut(
- "Ctrl+Alt+Shift+A", self, lambda: log.debug(repr(self))
- )
+ QShortcut("Ctrl+Alt+Shift+R", self, self.drawPreview)
+ QShortcut("Ctrl+Alt+Shift+A", self, lambda: log.debug(repr(self)))
# Close MainWindow when receiving Ctrl+C from terminal
signal.signal(signal.SIGINT, lambda *args: self.close())
@@ -450,18 +421,27 @@ class MainWindow(QtWidgets.QMainWindow):
def __repr__(self):
return (
- '%s\n'
- '\n%s\n'
- '#####\n'
- 'Preview thread is %s\n' % (
+ "%s\n"
+ "\n%s\n"
+ "#####\n"
+ "Preview thread is %s\n"
+ % (
super().__repr__(),
- "core not initialized" if not hasattr(self, "core") else repr(self.core),
- 'live' if hasattr(self, "previewThread") and self.previewThread.isRunning() else 'dead',
+ (
+ "core not initialized"
+ if not hasattr(self, "core")
+ else repr(self.core)
+ ),
+ (
+ "live"
+ if hasattr(self, "previewThread") and self.previewThread.isRunning()
+ else "dead"
+ ),
)
)
def closeEvent(self, event):
- log.info('Ending the preview thread')
+ log.info("Ending the preview thread")
self.timer.stop()
self.previewThread.quit()
self.previewThread.wait()
@@ -473,11 +453,11 @@ class MainWindow(QtWidgets.QMainWindow):
windowTitle = appName
try:
if self.currentProject:
- windowTitle += ' - %s' % \
- os.path.splitext(
- os.path.basename(self.currentProject))[0]
+ windowTitle += (
+ " - %s" % os.path.splitext(os.path.basename(self.currentProject))[0]
+ )
if self.autosaveExists(identical=False):
- windowTitle += '*'
+ windowTitle += "*"
except AttributeError:
pass
log.verbose(f'Window title is "{windowTitle}"')
@@ -485,38 +465,38 @@ class MainWindow(QtWidgets.QMainWindow):
@QtCore.pyqtSlot(int, dict)
def updateComponentTitle(self, pos, presetStore=False):
- '''
- Sets component title to modified or unmodified when given boolean.
- If given a preset dict, compares it against the component to
- determine if it is modified.
- A component with no preset is always unmodified.
- '''
+ """
+ Sets component title to modified or unmodified when given boolean.
+ If given a preset dict, compares it against the component to
+ determine if it is modified.
+ A component with no preset is always unmodified.
+ """
if type(presetStore) is dict:
- name = presetStore['preset']
+ name = presetStore["preset"]
if name is None or name not in self.core.savedPresets:
modified = False
else:
- modified = (presetStore != self.core.savedPresets[name])
+ modified = presetStore != self.core.savedPresets[name]
modified = bool(presetStore)
if pos < 0:
- pos = len(self.core.selectedComponents)-1
+ pos = len(self.core.selectedComponents) - 1
name = self.core.selectedComponents[pos].name
title = str(name)
if self.core.selectedComponents[pos].currentPreset:
- title += ' - %s' % self.core.selectedComponents[pos].currentPreset
+ title += " - %s" % self.core.selectedComponents[pos].currentPreset
if modified:
- title += '*'
+ title += "*"
if type(presetStore) is bool:
log.debug(
- 'Forcing %s #%s\'s modified status to %s: %s',
- name, pos, modified, title
+ "Forcing %s #%s's modified status to %s: %s",
+ name,
+ pos,
+ modified,
+ title,
)
else:
- log.debug(
- 'Setting %s #%s\'s title: %s',
- name, pos, title
- )
+ log.debug("Setting %s #%s's title: %s", name, pos, title)
self.listWidget_componentList.item(pos).setText(title)
def updateCodecs(self):
@@ -525,20 +505,20 @@ class MainWindow(QtWidgets.QMainWindow):
aCodecWidget = self.comboBox_audioCodec
index = containerWidget.currentIndex()
name = containerWidget.itemText(index)
- self.settings.setValue('outputContainer', name)
+ self.settings.setValue("outputContainer", name)
vCodecWidget.clear()
aCodecWidget.clear()
- for container in Core.encoderOptions['containers']:
- if container['name'] == name:
- for vCodec in container['video-codecs']:
+ for container in Core.encoderOptions["containers"]:
+ if container["name"] == name:
+ for vCodec in container["video-codecs"]:
vCodecWidget.addItem(vCodec)
- for aCodec in container['audio-codecs']:
+ for aCodec in container["audio-codecs"]:
aCodecWidget.addItem(aCodec)
def updateCodecSettings(self):
- '''Updates settings.ini to match encoder option widgets'''
+ """Updates settings.ini to match encoder option widgets"""
vCodecWidget = self.comboBox_videoCodec
vBitrateWidget = self.spinBox_vBitrate
aBitrateWidget = self.spinBox_aBitrate
@@ -549,10 +529,10 @@ class MainWindow(QtWidgets.QMainWindow):
currentAudioCodec = aCodecWidget.currentIndex()
currentAudioCodec = aCodecWidget.itemText(currentAudioCodec)
currentAudioBitrate = aBitrateWidget.value()
- self.settings.setValue('outputVideoCodec', currentVideoCodec)
- self.settings.setValue('outputAudioCodec', currentAudioCodec)
- self.settings.setValue('outputVideoBitrate', currentVideoBitrate)
- self.settings.setValue('outputAudioBitrate', currentAudioBitrate)
+ self.settings.setValue("outputVideoCodec", currentVideoCodec)
+ self.settings.setValue("outputAudioCodec", currentAudioCodec)
+ self.settings.setValue("outputVideoBitrate", currentVideoBitrate)
+ self.settings.setValue("outputAudioBitrate", currentAudioBitrate)
@disableWhenOpeningProject
def autosave(self, force=False):
@@ -567,54 +547,54 @@ class MainWindow(QtWidgets.QMainWindow):
# curve up to 5 seconds cooldown and maintains that for 30 secs
# if a component is continuously updated
timeDiff = self.lastAutosave - self.autosaveTimes.pop()
- if not force and timeDiff >= 1.0 \
- and timeDiff <= 10.0:
+ if not force and timeDiff >= 1.0 and timeDiff <= 10.0:
if self.autosaveCooldown / 4.0 < 0.5:
self.autosaveCooldown += 1.0
- self.autosaveCooldown = (
- 5.0 * (self.autosaveCooldown / 5.0)
- ) + (self.autosaveCooldown / 5.0) * 2
+ self.autosaveCooldown = (5.0 * (self.autosaveCooldown / 5.0)) + (
+ self.autosaveCooldown / 5.0
+ ) * 2
elif force or timeDiff >= self.autosaveCooldown * 5:
self.autosaveCooldown = 0.2
self.autosaveTimes.insert(0, self.lastAutosave)
else:
- log.debug('Autosave rejected by cooldown')
+ log.debug("Autosave rejected by cooldown")
def autosaveExists(self, identical=True):
- '''Determines if creating the autosave should be blocked.'''
+ """Determines if creating the autosave should be blocked."""
try:
- if self.currentProject and os.path.exists(self.autosavePath) \
- and filecmp.cmp(
- self.autosavePath, self.currentProject) == identical:
+ if (
+ self.currentProject
+ and os.path.exists(self.autosavePath)
+ and filecmp.cmp(self.autosavePath, self.currentProject) == identical
+ ):
log.debug(
- 'Autosave found %s to be identical'
- % 'not' if not identical else ''
+ "Autosave found %s to be identical" % "not" if not identical else ""
)
return True
except FileNotFoundError:
- log.error(
- 'Project file couldn\'t be located: %s', self.currentProject)
+ log.error("Project file couldn't be located: %s", self.currentProject)
return identical
return False
def saveProjectChanges(self):
- '''Overwrites project file with autosave file'''
+ """Overwrites project file with autosave file"""
try:
os.remove(self.currentProject)
os.rename(self.autosavePath, self.currentProject)
return True
except (FileNotFoundError, IsADirectoryError) as e:
- self.showMessage(
- msg='Project file couldn\'t be saved.',
- detail=str(e))
+ self.showMessage(msg="Project file couldn't be saved.", detail=str(e))
return False
def openInputFileDialog(self):
inputDir = self.settings.value("inputDir", os.path.expanduser("~"))
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
- self, "Open Audio File",
- inputDir, "Audio Files (%s)" % " ".join(Core.audioFormats))
+ self,
+ "Open Audio File",
+ inputDir,
+ "Audio Files (%s)" % " ".join(Core.audioFormats),
+ )
if fileName:
self.settings.setValue("inputDir", os.path.dirname(fileName))
@@ -624,17 +604,18 @@ class MainWindow(QtWidgets.QMainWindow):
outputDir = self.settings.value("outputDir", os.path.expanduser("~"))
fileName, _ = QtWidgets.QFileDialog.getSaveFileName(
- self, "Set Output Video File",
+ self,
+ "Set Output Video File",
outputDir,
- "Video Files (%s);; All Files (*)" % " ".join(
- Core.videoFormats))
+ "Video Files (%s);; All Files (*)" % " ".join(Core.videoFormats),
+ )
if fileName:
self.settings.setValue("outputDir", os.path.dirname(fileName))
self.lineEdit_outputFile.setText(fileName)
def stopVideo(self):
- log.info('Export cancelled')
+ log.info("Export cancelled")
self.videoWorker.cancel()
self.canceled = True
@@ -645,14 +626,13 @@ class MainWindow(QtWidgets.QMainWindow):
if audioFile and outputPath and self.core.selectedComponents:
if not os.path.dirname(outputPath):
- outputPath = os.path.join(
- os.path.expanduser("~"), outputPath)
+ outputPath = os.path.join(os.path.expanduser("~"), outputPath)
if outputPath and os.path.isdir(outputPath):
self.showMessage(
- msg='Chosen filename matches a directory, which '
- 'cannot be overwritten. Please choose a different '
- 'filename or move the directory.',
- icon='Warning',
+ msg="Chosen filename matches a directory, which "
+ "cannot be overwritten. Please choose a different "
+ "filename or move the directory.",
+ icon="Warning",
)
return
else:
@@ -661,19 +641,14 @@ class MainWindow(QtWidgets.QMainWindow):
msg="You must select an audio file and output filename."
)
elif not self.core.selectedComponents:
- self.showMessage(
- msg="Not enough components."
- )
+ self.showMessage(msg="Not enough components.")
return
self.canceled = False
self.progressBarUpdated(-1)
- self.videoWorker = self.core.newVideoWorker(
- self, audioFile, outputPath
- )
+ self.videoWorker = self.core.newVideoWorker(self, audioFile, outputPath)
self.videoWorker.progressBarUpdate.connect(self.progressBarUpdated)
- self.videoWorker.progressBarSetText.connect(
- self.progressBarSetText)
+ self.videoWorker.progressBarSetText.connect(self.progressBarSetText)
self.videoWorker.imageCreated.connect(self.showPreviewImage)
self.videoWorker.encoding.connect(self.changeEncodingStatus)
self.createVideo.emit()
@@ -683,14 +658,14 @@ class MainWindow(QtWidgets.QMainWindow):
try:
self.stopVideo()
except AttributeError as e:
- if 'videoWorker' not in str(e):
+ if "videoWorker" not in str(e):
raise
self.showMessage(
msg=msg,
detail=detail,
- icon='Critical',
+ icon="Critical",
)
- log.info('%s', repr(self))
+ log.info("%s", repr(self))
def changeEncodingStatus(self, status):
self.encoding = status
@@ -718,7 +693,7 @@ class MainWindow(QtWidgets.QMainWindow):
# Close undo history dialog if open
self.undoDialog.close()
# Show label under progress bar on macOS
- if sys.platform == 'darwin':
+ if sys.platform == "darwin":
self.progressLabel.setHidden(False)
else:
self.pushButton_createVideo.setEnabled(True)
@@ -749,33 +724,33 @@ class MainWindow(QtWidgets.QMainWindow):
@QtCore.pyqtSlot(str)
def progressBarSetText(self, value):
- if sys.platform == 'darwin':
+ if sys.platform == "darwin":
self.progressLabel.setText(value)
else:
self.progressBar_createVideo.setFormat(value)
def updateResolution(self):
resIndex = int(self.comboBox_resolution.currentIndex())
- res = Core.resolutions[resIndex].split('x')
+ res = Core.resolutions[resIndex].split("x")
changed = res[0] != self.settings.value("outputWidth")
- self.settings.setValue('outputWidth', res[0])
- self.settings.setValue('outputHeight', res[1])
+ self.settings.setValue("outputWidth", res[0])
+ self.settings.setValue("outputHeight", res[1])
if changed:
for i in range(len(self.core.selectedComponents)):
self.core.updateComponent(i)
def drawPreview(self, force=False, **kwargs):
- '''Use autosave keyword arg to force saving or not saving if needed'''
+ """Use autosave keyword arg to force saving or not saving if needed"""
self.newTask.emit(self.core.selectedComponents)
# self.processTask.emit()
- if force or 'autosave' in kwargs:
- if force or kwargs['autosave']:
+ if force or "autosave" in kwargs:
+ if force or kwargs["autosave"]:
self.autosave(True)
else:
self.autosave()
self.updateWindowTitle()
- @QtCore.pyqtSlot('QImage')
+ @QtCore.pyqtSlot("QImage")
def showPreviewImage(self, image):
self.previewWindow.changePixmap(image)
@@ -786,36 +761,35 @@ class MainWindow(QtWidgets.QMainWindow):
def showFfmpegCommand(self):
from textwrap import wrap
from ..toolkit.ffmpeg import createFfmpegCommand
+
command = createFfmpegCommand(
self.lineEdit_audioFile.text(),
self.lineEdit_outputFile.text(),
- self.core.selectedComponents
+ self.core.selectedComponents,
)
command = " ".join(command)
log.info(f"FFmpeg command: {command}")
lines = wrap(command, 49)
- self.showMessage(
- msg=f"Current FFmpeg command:\n\n{' '.join(lines)}"
- )
+ self.showMessage(msg=f"Current FFmpeg command:\n\n{' '.join(lines)}")
def addComponent(self, compPos, moduleIndex):
- '''Creates an undoable action that adds a new component.'''
+ """Creates an undoable action that adds a new component."""
action = AddComponent(self, compPos, moduleIndex)
self.undoStack.push(action)
def insertComponent(self, index):
- '''Triggered by Core to finish initializing a new component.'''
+ """Triggered by Core to finish initializing a new component."""
+ if not hasattr(self.core.selectedComponents[index], "page"):
+ log.error("Component failed to initialize")
+ return
componentList = self.listWidget_componentList
stackedWidget = self.stackedWidget
- componentList.insertItem(
- index,
- self.core.selectedComponents[index].name)
+ componentList.insertItem(index, self.core.selectedComponents[index].name)
componentList.setCurrentRow(index)
# connect to signal that adds an asterisk when modified
- self.core.selectedComponents[index].modified.connect(
- self.updateComponentTitle)
+ self.core.selectedComponents[index].modified.connect(self.updateComponentTitle)
self.pages.insert(index, self.core.selectedComponents[index].page)
stackedWidget.insertWidget(index, self.pages[index])
@@ -842,15 +816,15 @@ class MainWindow(QtWidgets.QMainWindow):
@disableWhenEncoding
def moveComponent(self, change):
- '''Moves a component relatively from its current position'''
+ """Moves a component relatively from its current position"""
componentList = self.listWidget_componentList
tag = change
- if change == 'top':
+ if change == "top":
change = -componentList.currentRow()
- elif change == 'bottom':
- change = len(componentList)-componentList.currentRow()-1
+ elif change == "bottom":
+ change = len(componentList) - componentList.currentRow() - 1
else:
- tag = 'down' if change == 1 else 'up'
+ tag = "down" if change == 1 else "up"
row = componentList.currentRow()
newRow = row + change
@@ -859,38 +833,39 @@ class MainWindow(QtWidgets.QMainWindow):
self.undoStack.push(action)
def getComponentListMousePos(self, position):
- '''
+ """
Given a QPos, returns the component index under the mouse cursor
or -1 if no component is there.
- '''
+ """
componentList = self.listWidget_componentList
+ if hasattr(position, "toPointF"):
+ position = position.toPointF()
+ position = position.toPoint()
+
modelIndexes = [
- componentList.model().index(i)
- for i in range(componentList.count())
- ]
- rects = [
- componentList.visualRect(modelIndex)
- for modelIndex in modelIndexes
+ componentList.model().index(i) for i in range(componentList.count())
]
+ rects = [componentList.visualRect(modelIndex) for modelIndex in modelIndexes]
mousePos = [rect.contains(position) for rect in rects]
if not any(mousePos):
# Not clicking a component
mousePos = -1
else:
mousePos = mousePos.index(True)
- log.debug('Click component list row %s' % mousePos)
+ log.debug("Click component list row %s" % mousePos)
return mousePos
@disableWhenEncoding
def dragComponent(self, event):
- '''Used as Qt drop event for the component listwidget'''
+ """Used as Qt drop event for the component listwidget"""
componentList = self.listWidget_componentList
- mousePos = self.getComponentListMousePos(event.pos())
+ mousePos = self.getComponentListMousePos(event.position())
+
if mousePos > -1:
change = (componentList.currentRow() - mousePos) * -1
else:
- change = (componentList.count() - componentList.currentRow() - 1)
+ change = componentList.count() - componentList.currentRow() - 1
self.moveComponent(change)
def changeComponentWidget(self):
@@ -900,30 +875,27 @@ class MainWindow(QtWidgets.QMainWindow):
self.stackedWidget.setCurrentIndex(index)
def openPresetManager(self):
- '''Preset manager for importing, exporting, renaming, deleting'''
+ """Preset manager for importing, exporting, renaming, deleting"""
self.presetManager.show_()
def clear(self):
- '''Get a blank slate'''
+ """Get a blank slate"""
self.core.clearComponents()
self.listWidget_componentList.clear()
for widget in self.pages:
self.stackedWidget.removeWidget(widget)
self.pages = []
- for field in (
- self.lineEdit_audioFile,
- self.lineEdit_outputFile
- ):
+ for field in (self.lineEdit_audioFile, self.lineEdit_outputFile):
with blockSignals(field):
- field.setText('')
+ field.setText("")
self.progressBarUpdated(0)
- self.progressBarSetText('')
+ self.progressBarSetText("")
self.undoStack.clear()
@disableWhenEncoding
def createNewProject(self, prompt=True):
if prompt:
- self.openSaveChangesDialog('starting a new project')
+ self.openSaveChangesDialog("starting a new project")
self.clear()
self.currentProject = None
@@ -946,11 +918,10 @@ class MainWindow(QtWidgets.QMainWindow):
if self.autosaveExists(identical=False):
ch = self.showMessage(
msg="You have unsaved changes in project '%s'. "
- "Save before %s?" % (
- os.path.basename(self.currentProject)[:-4],
- phrase
- ),
- showCancel=True)
+ "Save before %s?"
+ % (os.path.basename(self.currentProject)[:-4], phrase),
+ showCancel=True,
+ )
if ch:
success = self.saveProjectChanges()
@@ -959,13 +930,15 @@ class MainWindow(QtWidgets.QMainWindow):
def openSaveProjectDialog(self):
filename, _ = QtWidgets.QFileDialog.getSaveFileName(
- self, "Create Project File",
+ self,
+ "Create Project File",
self.settings.value("projectDir"),
- "Project Files (*.avp)")
+ "Project Files (*.avp)",
+ )
if not filename:
return
if not filename.endswith(".avp"):
- filename += '.avp'
+ filename += ".avp"
self.settings.setValue("projectDir", os.path.dirname(filename))
self.settings.setValue("currentProject", filename)
self.currentProject = filename
@@ -975,20 +948,25 @@ class MainWindow(QtWidgets.QMainWindow):
@disableWhenEncoding
def openOpenProjectDialog(self):
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
- self, "Open Project File",
+ self,
+ "Open Project File",
self.settings.value("projectDir"),
- "Project Files (*.avp)")
+ "Project Files (*.avp)",
+ )
self.openProject(filename)
def openProject(self, filepath, prompt=True):
- if not filepath or not os.path.exists(filepath) \
- or not filepath.endswith('.avp'):
+ if (
+ not filepath
+ or not os.path.exists(filepath)
+ or not filepath.endswith(".avp")
+ ):
return
self.clear()
# ask to save any changes that are about to get deleted
if prompt:
- self.openSaveChangesDialog('opening another project')
+ self.openSaveChangesDialog("opening another project")
self.currentProject = filepath
self.settings.setValue("currentProject", filepath)
@@ -999,29 +977,32 @@ class MainWindow(QtWidgets.QMainWindow):
self.updateWindowTitle()
def showMessage(self, **kwargs):
- parent = kwargs['parent'] if 'parent' in kwargs else self
+ parent = kwargs["parent"] if "parent" in kwargs else self
msg = QtWidgets.QMessageBox(parent)
msg.setWindowTitle(appName)
msg.setModal(True)
- msg.setText(kwargs['msg'])
+ msg.setText(kwargs["msg"])
msg.setIcon(
- eval('QtWidgets.QMessageBox.%s' % kwargs['icon'])
- if 'icon' in kwargs else QtWidgets.QMessageBox.Information
+ eval("QtWidgets.QMessageBox.Icon.%s" % kwargs["icon"])
+ if "icon" in kwargs
+ else QtWidgets.QMessageBox.Icon.Information
)
- msg.setDetailedText(kwargs['detail'] if 'detail' in kwargs else None)
- if 'showCancel'in kwargs and kwargs['showCancel']:
+ msg.setDetailedText(kwargs["detail"] if "detail" in kwargs else None)
+ if "showCancel" in kwargs and kwargs["showCancel"]:
msg.setStandardButtons(
- QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel)
+ QtWidgets.QMessageBox.StandardButton.Ok
+ | QtWidgets.QMessageBox.StandardButton.Cancel
+ )
else:
- msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
- ch = msg.exec_()
+ msg.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok)
+ ch = msg.exec()
if ch == 1024:
return True
return False
@disableWhenEncoding
def componentContextMenu(self, QPos):
- '''Appears when right-clicking the component list'''
+ """Appears when right-clicking the component list"""
componentList = self.listWidget_componentList
self.menu = QtWidgets.QMenu()
parentPosition = componentList.mapToGlobal(QtCore.QPoint(0, 0))
@@ -1031,9 +1012,7 @@ class MainWindow(QtWidgets.QMainWindow):
# Show preset menu if clicking a component
self.presetManager.findPresets()
menuItem = self.menu.addAction("Save Preset")
- menuItem.triggered.connect(
- self.presetManager.openSavePresetDialog
- )
+ menuItem.triggered.connect(self.presetManager.openSavePresetDialog)
# submenu for opening presets
try:
@@ -1046,17 +1025,16 @@ class MainWindow(QtWidgets.QMainWindow):
for version, presetName in presets:
menuItem = self.presetSubmenu.addAction(presetName)
menuItem.triggered.connect(
- lambda _, presetName=presetName:
- self.presetManager.openPreset(presetName)
+ lambda _, presetName=presetName: self.presetManager.openPreset(
+ presetName
+ )
)
except KeyError:
pass
if self.core.selectedComponents[index].currentPreset:
menuItem = self.menu.addAction("Clear Preset")
- menuItem.triggered.connect(
- self.presetManager.clearPreset
- )
+ menuItem.triggered.connect(self.presetManager.clearPreset)
self.menu.addSeparator()
# "Add Component" submenu
diff --git a/src/gui/presetmanager.py b/src/gui/presetmanager.py
index 9cf95b4..11a9d9b 100644
--- a/src/gui/presetmanager.py
+++ b/src/gui/presetmanager.py
@@ -1,8 +1,9 @@
-'''
- Preset manager object handles all interactions with presets, including
- the context menu accessed from MainWindow.
-'''
-from PyQt5 import QtCore, QtWidgets, uic
+"""
+Preset manager object handles all interactions with presets, including
+the context menu accessed from MainWindow.
+"""
+
+from PyQt6 import QtCore, QtWidgets, uic
import string
import os
import logging
@@ -12,53 +13,43 @@ from ..core import Core
from .actions import *
-log = logging.getLogger('AVP.Gui.PresetManager')
+log = logging.getLogger("AVP.Gui.PresetManager")
class PresetManager(QtWidgets.QDialog):
def __init__(self, parent):
super().__init__()
- uic.loadUi(
- os.path.join(Core.wd, 'gui', 'presetmanager.ui'), self)
+ uic.loadUi(os.path.join(Core.wd, "gui", "presetmanager.ui"), self)
self.parent = parent
self.core = parent.core
self.settings = parent.settings
self.presetDir = parent.presetDir
- if not self.settings.value('presetDir'):
+ if not self.settings.value("presetDir"):
self.settings.setValue(
- "presetDir",
- os.path.join(parent.dataDir, 'projects'))
+ "presetDir", os.path.join(parent.dataDir, "projects")
+ )
self.findPresets()
# window
- self.lastFilter = '*'
+ self.lastFilter = "*"
self.presetRows = [] # list of (comp, vers, name) tuples
- self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
+
+ # FIXME
+ # self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
# connect button signals
- self.pushButton_delete.clicked.connect(
- self.openDeletePresetDialog
- )
- self.pushButton_rename.clicked.connect(
- self.openRenamePresetDialog
- )
- self.pushButton_import.clicked.connect(
- self.openImportDialog
- )
- self.pushButton_export.clicked.connect(
- self.openExportDialog
- )
- self.pushButton_close.clicked.connect(
- self.close
- )
+ self.pushButton_delete.clicked.connect(self.openDeletePresetDialog)
+ self.pushButton_rename.clicked.connect(self.openRenamePresetDialog)
+ self.pushButton_import.clicked.connect(self.openImportDialog)
+ self.pushButton_export.clicked.connect(self.openExportDialog)
+ self.pushButton_close.clicked.connect(self.close)
# create filter box and preset list
self.drawFilterList()
self.comboBox_filter.currentIndexChanged.connect(
lambda: self.drawPresetList(
- self.comboBox_filter.currentText(),
- self.lineEdit_search.text()
+ self.comboBox_filter.currentText(), self.lineEdit_search.text()
)
)
@@ -69,17 +60,16 @@ class PresetManager(QtWidgets.QDialog):
self.lineEdit_search.setCompleter(completer)
self.lineEdit_search.textChanged.connect(
lambda: self.drawPresetList(
- self.comboBox_filter.currentText(),
- self.lineEdit_search.text()
+ self.comboBox_filter.currentText(), self.lineEdit_search.text()
)
)
- self.drawPresetList('*')
+ self.drawPresetList("*")
def show_(self):
- '''Open a new preset manager window from the mainwindow'''
+ """Open a new preset manager window from the mainwindow"""
self.findPresets()
self.drawFilterList()
- self.drawPresetList('*')
+ self.drawPresetList("*")
self.show()
def findPresets(self):
@@ -100,14 +90,12 @@ class PresetManager(QtWidgets.QDialog):
continue
self.presets = {
compName: [
- (vers, preset)
- for name, vers, preset in parseList
- if name == compName
+ (vers, preset) for name, vers, preset in parseList if name == compName
]
for compName, _, __ in parseList
}
- def drawPresetList(self, compFilter=None, presetFilter=''):
+ def drawPresetList(self, compFilter=None, presetFilter=""):
self.listWidget_presets.clear()
if compFilter:
self.lastFilter = str(compFilter)
@@ -116,13 +104,11 @@ class PresetManager(QtWidgets.QDialog):
self.presetRows = []
presetNames = []
for component, presets in self.presets.items():
- if compFilter != '*' and component != compFilter:
+ if compFilter != "*" and component != compFilter:
continue
for vers, preset in presets:
if not presetFilter or presetFilter in preset:
- self.listWidget_presets.addItem(
- '%s: %s' % (component, preset)
- )
+ self.listWidget_presets.addItem("%s: %s" % (component, preset))
self.presetRows.append((component, vers, preset))
if preset not in presetNames:
presetNames.append(preset)
@@ -130,18 +116,18 @@ class PresetManager(QtWidgets.QDialog):
def drawFilterList(self):
self.comboBox_filter.clear()
- self.comboBox_filter.addItem('*')
+ self.comboBox_filter.addItem("*")
for component in self.presets:
self.comboBox_filter.addItem(component)
def clearPreset(self, compI=None):
- '''Functions on mainwindow level from the context menu'''
+ """Functions on mainwindow level from the context menu"""
compI = self.parent.listWidget_componentList.currentRow()
action = ClearPreset(self.parent, compI)
self.parent.undoStack.push(action)
def openSavePresetDialog(self):
- '''Functions on mainwindow level from the context menu'''
+ """Functions on mainwindow level from the context menu"""
selectedComponents = self.core.selectedComponents
componentList = self.parent.listWidget_componentList
@@ -152,10 +138,10 @@ class PresetManager(QtWidgets.QDialog):
currentPreset = selectedComponents[index].currentPreset
newName, OK = QtWidgets.QInputDialog.getText(
self.parent,
- 'Audio Visualizer',
- 'New Preset Name:',
- QtWidgets.QLineEdit.Normal,
- currentPreset
+ "Audio Visualizer",
+ "New Preset Name:",
+ QtWidgets.QLineEdit.EchoMode.Normal,
+ currentPreset,
)
if OK:
if badName(newName):
@@ -164,21 +150,23 @@ class PresetManager(QtWidgets.QDialog):
if newName:
if index != -1:
selectedComponents[index].currentPreset = newName
- saveValueStore = \
- selectedComponents[index].savePreset()
- saveValueStore['preset'] = newName
+ saveValueStore = selectedComponents[index].savePreset()
+ saveValueStore["preset"] = newName
componentName = str(selectedComponents[index]).strip()
vers = selectedComponents[index].version
self.createNewPreset(
- componentName, vers, newName,
- saveValueStore, window=self.parent)
+ componentName,
+ vers,
+ newName,
+ saveValueStore,
+ window=self.parent,
+ )
self.findPresets()
self.drawPresetList()
self.openPreset(newName, index)
break
- def createNewPreset(
- self, compName, vers, filename, saveValueStore, **kwargs):
+ def createNewPreset(self, compName, vers, filename, saveValueStore, **kwargs):
path = os.path.join(self.presetDir, compName, str(vers), filename)
if self.presetExists(path, **kwargs):
return
@@ -188,11 +176,11 @@ class PresetManager(QtWidgets.QDialog):
if os.path.exists(path):
window = kwargs.get("window", self)
ch = self.parent.showMessage(
- msg="%s already exists! Overwrite it?" %
- os.path.basename(path),
+ msg="%s already exists! Overwrite it?" % os.path.basename(path),
showCancel=True,
- icon='Warning',
- parent=window)
+ icon="Warning",
+ parent=window,
+ )
if not ch:
# user clicked cancel
return True
@@ -225,10 +213,10 @@ class PresetManager(QtWidgets.QDialog):
return
comp, vers, name = self.presetRows[row]
ch = self.parent.showMessage(
- msg='Really delete %s?' % name,
+ msg="Really delete %s?" % name,
showCancel=True,
- icon='Warning',
- parent=self
+ icon="Warning",
+ parent=self,
)
if not ch:
return
@@ -240,9 +228,9 @@ class PresetManager(QtWidgets.QDialog):
def warnMessage(self, window=None):
self.parent.showMessage(
- msg='Preset names must contain only letters, '
- 'numbers, and spaces.',
- parent=window if window else self)
+ msg="Preset names must contain only letters, " "numbers, and spaces.",
+ parent=window if window else self,
+ )
def getPresetRow(self):
row = self.listWidget_presets.currentRow()
@@ -262,14 +250,14 @@ class PresetManager(QtWidgets.QDialog):
rowTuple = (
self.core.selectedComponents[compIndex].name,
self.core.selectedComponents[compIndex].version,
- preset
+ preset,
)
for i, tup in enumerate(self.presetRows):
if rowTuple == tup:
index = i
break
else:
- return -1
+ return -1
return index
def openRenamePresetDialog(self):
@@ -281,10 +269,10 @@ class PresetManager(QtWidgets.QDialog):
while True:
newName, OK = QtWidgets.QInputDialog.getText(
self,
- 'Preset Manager',
- 'Rename Preset:',
- QtWidgets.QLineEdit.Normal,
- self.presetRows[index][2]
+ "Preset Manager",
+ "Rename Preset:",
+ QtWidgets.QLineEdit.EchoMode.Normal,
+ self.presetRows[index][2],
)
if OK:
if badName(newName):
@@ -292,8 +280,7 @@ class PresetManager(QtWidgets.QDialog):
continue
if newName:
comp, vers, oldName = self.presetRows[index]
- path = os.path.join(
- self.presetDir, comp, str(vers))
+ path = os.path.join(self.presetDir, comp, str(vers))
newPath = os.path.join(path, newName)
if self.presetExists(newPath):
return
@@ -311,20 +298,21 @@ class PresetManager(QtWidgets.QDialog):
self.drawPresetList()
path = os.path.dirname(newPath)
for i, comp in enumerate(self.core.selectedComponents):
- if self.core.getPresetDir(comp) == path \
- and comp.currentPreset == oldName:
+ if self.core.getPresetDir(comp) == path and comp.currentPreset == oldName:
self.core.openPreset(newPath, i, newName)
self.parent.updateComponentTitle(i, False)
self.parent.drawPreview()
def openImportDialog(self):
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
- self, "Import Preset File",
+ self,
+ "Import Preset File",
self.settings.value("presetDir"),
- "Preset Files (*.avl)")
+ "Preset Files (*.avl)",
+ )
if filename:
# get installed path & ask user to overwrite if needed
- path = ''
+ path = ""
while True:
if path:
if self.presetExists(path):
@@ -345,15 +333,16 @@ class PresetManager(QtWidgets.QDialog):
if index == -1:
return
filename, _ = QtWidgets.QFileDialog.getSaveFileName(
- self, "Export Preset",
+ self,
+ "Export Preset",
self.settings.value("presetDir"),
- "Preset Files (*.avl)")
+ "Preset Files (*.avl)",
+ )
if filename:
comp, vers, name = self.presetRows[index]
if not self.core.exportPreset(filename, comp, vers, name):
self.parent.showMessage(
- msg='Couldn\'t export %s.' % filename,
- parent=self
+ msg="Couldn't export %s." % filename, parent=self
)
self.settings.setValue("presetDir", os.path.dirname(filename))
diff --git a/src/gui/preview_thread.py b/src/gui/preview_thread.py
index 3943a5c..1d78516 100644
--- a/src/gui/preview_thread.py
+++ b/src/gui/preview_thread.py
@@ -1,9 +1,10 @@
-'''
- Thread that runs to create QImages for MainWindow's preview label.
- Processes a queue of component lists.
-'''
-from PyQt5 import QtCore, QtGui, uic
-from PyQt5.QtCore import pyqtSignal, pyqtSlot
+"""
+Thread that runs to create QImages for MainWindow's preview label.
+Processes a queue of component lists.
+"""
+
+from PyQt6 import QtCore, QtGui, uic
+from PyQt6.QtCore import pyqtSignal, pyqtSlot
from PIL import Image
from PIL.ImageQt import ImageQt
from queue import Queue, Empty
@@ -26,8 +27,8 @@ class Worker(QtCore.QObject):
super().__init__()
self.core = core
self.settings = settings
- width = int(self.settings.value('outputWidth'))
- height = int(self.settings.value('outputHeight'))
+ width = int(self.settings.value("outputWidth"))
+ height = int(self.settings.value("outputHeight"))
self.queue = queue
self.background = Checkerboard(width, height)
@@ -35,10 +36,10 @@ class Worker(QtCore.QObject):
@pyqtSlot(list)
def createPreviewImage(self, components):
dic = {
- "components": components,
+ "components": components,
}
self.queue.put(dic)
- log.debug('Preview thread id: {}'.format(int(QtCore.QThread.currentThreadId())))
+ log.debug("Preview thread id: {}".format(int(QtCore.QThread.currentThreadId())))
@pyqtSlot()
def process(self):
@@ -49,31 +50,34 @@ class Worker(QtCore.QObject):
self.queue.get(block=False)
except Empty:
continue
- width = int(self.settings.value('outputWidth'))
- height = int(self.settings.value('outputHeight'))
- if self.background.width != width \
- or self.background.height != height:
+ width = int(self.settings.value("outputWidth"))
+ height = int(self.settings.value("outputHeight"))
+ if self.background.width != width or self.background.height != height:
self.background = Checkerboard(width, height)
frame = self.background.copy()
- log.info('Creating new preview frame')
+ log.info("Creating new preview frame")
components = nextPreviewInformation["components"]
for component in reversed(components):
try:
component.lockSize(width, height)
newFrame = component.previewRender()
component.unlockSize()
- frame = Image.alpha_composite(
- frame, newFrame
- )
+ frame = Image.alpha_composite(frame, newFrame)
except ValueError as e:
- errMsg = "Bad frame returned by %s's preview renderer. " \
- "%s. New frame size was %s*%s; should be %s*%s." % (
- str(component), str(e).capitalize(),
- newFrame.width, newFrame.height,
- width, height
+ errMsg = (
+ "Bad frame returned by %s's preview renderer. "
+ "%s. New frame size was %s*%s; should be %s*%s."
+ % (
+ str(component),
+ str(e).capitalize(),
+ newFrame.width,
+ newFrame.height,
+ width,
+ height,
)
+ )
log.critical(errMsg)
self.error.emit(errMsg)
break
diff --git a/src/gui/preview_win.py b/src/gui/preview_win.py
index d910456..f52f8a3 100644
--- a/src/gui/preview_win.py
+++ b/src/gui/preview_win.py
@@ -1,18 +1,20 @@
-from PyQt5 import QtCore, QtGui, QtWidgets
+from PyQt6 import QtCore, QtGui, QtWidgets
import logging
-log = logging.getLogger('AVP.Gui.PreviewWindow')
+log = logging.getLogger("AVP.Gui.PreviewWindow")
class PreviewWindow(QtWidgets.QLabel):
- '''
- Paints the preview QLabel in MainWindow and maintains the aspect ratio
- when the window is resized.
- '''
+ """
+ Paints the preview QLabel in MainWindow and maintains the aspect ratio
+ when the window is resized.
+ """
+
def __init__(self, parent, img):
super().__init__()
self.parent = parent
- self.setFrameStyle(QtWidgets.QFrame.StyledPanel)
+ # FIXME
+ # self.setFrameStyle(QtWidgets.QFrame.StyledPanel)
self.pixmap = QtGui.QPixmap(img)
def paintEvent(self, event):
@@ -21,12 +23,13 @@ class PreviewWindow(QtWidgets.QLabel):
point = QtCore.QPoint(0, 0)
scaledPix = self.pixmap.scaled(
size,
- QtCore.Qt.KeepAspectRatio,
- transformMode=QtCore.Qt.SmoothTransformation)
+ QtCore.Qt.AspectRatioMode.KeepAspectRatio,
+ transformMode=QtCore.Qt.TransformationMode.SmoothTransformation,
+ )
# start painting the label from left upper corner
- point.setX(int((size.width() - scaledPix.width())/2))
- point.setY(int((size.height() - scaledPix.height())/2))
+ point.setX(int((size.width() - scaledPix.width()) / 2))
+ point.setY(int((size.height() - scaledPix.height()) / 2))
painter.drawPixmap(point, scaledPix)
def changePixmap(self, img):
@@ -40,22 +43,16 @@ class PreviewWindow(QtWidgets.QLabel):
i = self.parent.listWidget_componentList.currentRow()
if i >= 0:
component = self.parent.core.selectedComponents[i]
- if not hasattr(component, 'previewClickEvent'):
+ if not hasattr(component, "previewClickEvent"):
return
- pos = (event.x(), event.y())
+ qpoint = event.position().toPoint()
+ pos = (qpoint.x(), qpoint.y())
size = (self.width(), self.height())
butt = event.button()
- log.info('Click event for #%s: %s button %s' % (
- i, pos, butt))
- component.previewClickEvent(
- pos, size, butt
- )
+ log.info("Click event for #%s: %s button %s" % (i, pos, butt))
+ component.previewClickEvent(pos, size, butt)
@QtCore.pyqtSlot(str)
def threadError(self, msg):
- self.parent.showMessage(
- msg=msg,
- icon='Critical',
- parent=self
- )
- log.info('%', repr(self.parent))
+ self.parent.showMessage(msg=msg, icon="Critical", parent=self)
+ log.info("%", repr(self.parent))