fixed issues with undoing relative widgets

This commit is contained in:
tassaron 2017-08-19 18:32:12 -04:00
parent 87e762a8aa
commit c07f2426ce
17 changed files with 215 additions and 81 deletions

View File

@ -9,6 +9,7 @@ import sys
import math import math
import time import time
import logging import logging
from copy import copy
from toolkit.frame import BlankFrame from toolkit.frame import BlankFrame
from toolkit import ( from toolkit import (
@ -113,14 +114,20 @@ class ComponentMetaclass(type(QtCore.QObject)):
def presetWrapper(self, *args): def presetWrapper(self, *args):
with openingPreset(self): with openingPreset(self):
return func(self, *args) try:
return func(self, *args)
except Exception:
try:
raise ComponentError(self, 'preset loader')
except ComponentError:
return
return presetWrapper return presetWrapper
def updateWrapper(func): def updateWrapper(func):
''' '''
For undoable updates triggered by the user, Calls _preUpdate before every subclass update().
call _userUpdate() after the subclass's update() method. Afterwards, for non-user updates, calls _autoUpdate().
For non-user updates, call _autoUpdate() For undoable updates triggered by the user, calls _userUpdate()
''' '''
class wrap: class wrap:
def __init__(self, comp, auto): def __init__(self, comp, auto):
@ -128,24 +135,57 @@ class ComponentMetaclass(type(QtCore.QObject)):
self.auto = auto self.auto = auto
def __enter__(self): def __enter__(self):
pass self.comp._preUpdate()
def __exit__(self, *args): def __exit__(self, *args):
if self.auto or self.comp.openingPreset \ if self.auto or self.comp.openingPreset \
or not hasattr(self.comp.parent, 'undoStack'): or not hasattr(self.comp.parent, 'undoStack'):
log.verbose('Automatic update')
self.comp._autoUpdate() self.comp._autoUpdate()
else: else:
log.verbose('User update')
self.comp._userUpdate() self.comp._userUpdate()
def updateWrapper(self, **kwargs): def updateWrapper(self, **kwargs):
auto = False auto = kwargs['auto'] if 'auto' in kwargs else False
if 'auto' in kwargs:
auto = kwargs['auto']
with wrap(self, auto): with wrap(self, auto):
return func(self) try:
return func(self)
except Exception:
try:
raise ComponentError(self, 'update method')
except ComponentError:
return
return updateWrapper return updateWrapper
def widgetWrapper(func):
'''Connects all widgets to update method after the subclass's method'''
class wrap:
def __init__(self, comp):
self.comp = comp
def __enter__(self):
pass
def __exit__(self, *args):
for widgetList in self.comp._allWidgets.values():
for widget in widgetList:
log.verbose('Connecting %s' % str(
widget.__class__.__name__))
connectWidget(widget, self.comp.update)
def widgetWrapper(self, *args, **kwargs):
auto = kwargs['auto'] if 'auto' in kwargs else False
with wrap(self):
try:
return func(self, *args, **kwargs)
except Exception:
try:
raise ComponentError(self, 'widget creation')
except ComponentError:
return
return widgetWrapper
def __new__(cls, name, parents, attrs): def __new__(cls, name, parents, attrs):
if 'ui' not in attrs: if 'ui' not in attrs:
# Use module name as ui filename by default # Use module name as ui filename by default
@ -153,13 +193,12 @@ class ComponentMetaclass(type(QtCore.QObject)):
attrs['__module__'].split('.')[-1] attrs['__module__'].split('.')[-1]
)[0] )[0]
# if parents[0] == QtCore.QObject: else:
decorate = ( decorate = (
'names', # Class methods 'names', # Class methods
'error', 'audio', 'properties', # Properties 'error', 'audio', 'properties', # Properties
'preFrameRender', 'previewRender', 'preFrameRender', 'previewRender',
'frameRender', 'command', 'frameRender', 'command',
'loadPreset', 'update' 'loadPreset', 'update', 'widget',
) )
# Auto-decorate methods # Auto-decorate methods
@ -184,6 +223,8 @@ class ComponentMetaclass(type(QtCore.QObject)):
attrs[key] = cls.loadPresetWrapper(attrs[key]) attrs[key] = cls.loadPresetWrapper(attrs[key])
elif key == 'update': elif key == 'update':
attrs[key] = cls.updateWrapper(attrs[key]) attrs[key] = cls.updateWrapper(attrs[key])
elif key == 'widget' and parents[0] != QtCore.QObject:
attrs[key] = cls.widgetWrapper(attrs[key])
# Turn version string into a number # Turn version string into a number
try: try:
@ -224,23 +265,28 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self.moduleIndex = moduleIndex self.moduleIndex = moduleIndex
self.compPos = compPos self.compPos = compPos
self.core = core self.core = core
self.currentPreset = None
self.openingPreset = False
# STATUS VARIABLES
self.currentPreset = None
self._allWidgets = {}
self._trackedWidgets = {} self._trackedWidgets = {}
self._presetNames = {} self._presetNames = {}
self._commandArgs = {} self._commandArgs = {}
self._colorWidgets = {} self._colorWidgets = {}
self._colorFuncs = {} self._colorFuncs = {}
self._relativeWidgets = {} self._relativeWidgets = {}
# pixel values stored as floats # Pixel values stored as floats
self._relativeValues = {} self._relativeValues = {}
# maximum values of spinBoxes at 1080p (Core.resolutions[0]) # Maximum values of spinBoxes at 1080p (Core.resolutions[0])
self._relativeMaximums = {} self._relativeMaximums = {}
# LOCKING VARIABLES
self.openingPreset = False
self._lockedProperties = None self._lockedProperties = None
self._lockedError = None self._lockedError = None
self._lockedSize = None self._lockedSize = None
# If set to a dict, values are used as basis to update relative widgets
self.oldAttrs = None
# Stop lengthy processes in response to this variable # Stop lengthy processes in response to this variable
self.canceled = False self.canceled = False
@ -338,21 +384,21 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
''' '''
self.parent = parent self.parent = parent
self.settings = parent.settings self.settings = parent.settings
log.verbose('Creating UI for %s #%s\'s widget' % (
self.name, self.compPos
))
self.page = self.loadUi(self.__class__.ui) self.page = self.loadUi(self.__class__.ui)
# Connect widget signals # Find all normal widgets which will be connected after subclass method
widgets = { self._allWidgets = {
'lineEdit': self.page.findChildren(QtWidgets.QLineEdit), 'lineEdit': self.page.findChildren(QtWidgets.QLineEdit),
'checkBox': self.page.findChildren(QtWidgets.QCheckBox), 'checkBox': self.page.findChildren(QtWidgets.QCheckBox),
'spinBox': self.page.findChildren(QtWidgets.QSpinBox), 'spinBox': self.page.findChildren(QtWidgets.QSpinBox),
'comboBox': self.page.findChildren(QtWidgets.QComboBox), 'comboBox': self.page.findChildren(QtWidgets.QComboBox),
} }
widgets['spinBox'].extend( self._allWidgets['spinBox'].extend(
self.page.findChildren(QtWidgets.QDoubleSpinBox) self.page.findChildren(QtWidgets.QDoubleSpinBox)
) )
for widgetList in widgets.values():
for widget in widgetList:
connectWidget(widget, self.update)
def update(self): def update(self):
''' '''
@ -427,10 +473,15 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~ # =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
# "Private" Methods # "Private" Methods
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~ # =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
def _preUpdate(self):
'''Happens before subclass update()'''
for attr in self._relativeWidgets:
self.updateRelativeWidget(attr)
def _userUpdate(self): def _userUpdate(self):
'''An undoable component update triggered by the user''' '''Happens after subclass update() for an undoable update by user.'''
oldWidgetVals = { oldWidgetVals = {
attr: getattr(self, attr) attr: copy(getattr(self, attr))
for attr in self._trackedWidgets for attr in self._trackedWidgets
} }
newWidgetVals = { newWidgetVals = {
@ -443,13 +494,12 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
for attr, val in newWidgetVals.items() for attr, val in newWidgetVals.items()
if val != oldWidgetVals[attr] if val != oldWidgetVals[attr]
} }
if modifiedWidgets: if modifiedWidgets:
action = ComponentUpdate(self, oldWidgetVals, modifiedWidgets) action = ComponentUpdate(self, oldWidgetVals, modifiedWidgets)
self.parent.undoStack.push(action) self.parent.undoStack.push(action)
def _autoUpdate(self): def _autoUpdate(self):
'''An internal component update that is not undoable''' '''Happens after subclass update() for an internal component update.'''
newWidgetVals = { newWidgetVals = {
attr: getWidgetValue(widget) attr: getWidgetValue(widget)
for attr, widget in self._trackedWidgets.items() for attr, widget in self._trackedWidgets.items()
@ -459,12 +509,12 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
def setAttrs(self, attrDict): def setAttrs(self, attrDict):
''' '''
Sets attrs (linked to trackedWidgets) in this preset to Sets attrs (linked to trackedWidgets) in this component to
the values in the attrDict. Mutates certain widget values if needed the values in the attrDict. Mutates certain widget values if needed
''' '''
for attr, val in attrDict.items(): for attr, val in attrDict.items():
if attr in self._colorWidgets: if attr in self._colorWidgets:
# Color Widgets: text stored as tuple & update the button color # Color Widgets must have a tuple & have a button to update
if type(val) is tuple: if type(val) is tuple:
rgbTuple = val rgbTuple = val
else: else:
@ -475,15 +525,25 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self._colorWidgets[attr].setStyleSheet(btnStyle) self._colorWidgets[attr].setStyleSheet(btnStyle)
setattr(self, attr, rgbTuple) setattr(self, attr, rgbTuple)
elif attr in self._relativeWidgets:
# Relative widgets: number scales to fit export resolution
self.updateRelativeWidget(attr)
setattr(self, attr, val)
else: else:
# Normal tracked widget # Normal tracked widget
setattr(self, attr, val) setattr(self, attr, val)
def setWidgetValues(self, attrDict):
'''
Sets widgets defined by keys in trackedWidgets in this preset to
the values in the attrDict.
'''
affectedWidgets = [
self._trackedWidgets[attr] for attr in attrDict
]
with blockSignals(affectedWidgets):
for attr, val in attrDict.items():
widget = self._trackedWidgets[attr]
if attr in self._colorWidgets:
val = '%s,%s,%s' % val
setWidgetValue(widget, val)
def _sendUpdateSignal(self): def _sendUpdateSignal(self):
if not self.core.openingProject: if not self.core.openingProject:
self.parent.drawPreview() self.parent.drawPreview()
@ -499,6 +559,8 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
Optional args: Optional args:
'presetNames': preset variable names to replace attr names 'presetNames': preset variable names to replace attr names
'commandArgs': arg keywords that differ from attr names 'commandArgs': arg keywords that differ from attr names
'colorWidgets': identify attr as RGB tuple & update button CSS
'relativeWidgets': change value proportionally to resolution
NOTE: Any kwarg key set to None will selectively disable tracking. NOTE: Any kwarg key set to None will selectively disable tracking.
''' '''
@ -542,6 +604,8 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self._relativeMaximums[attr] = \ self._relativeMaximums[attr] = \
self._trackedWidgets[attr].maximum() self._trackedWidgets[attr].maximum()
self.updateRelativeWidgetMaximum(attr) self.updateRelativeWidgetMaximum(attr)
self._preUpdate()
self._autoUpdate()
def pickColor(self, textWidget, button): def pickColor(self, textWidget, button):
'''Use color picker to get color input from the user.''' '''Use color picker to get color input from the user.'''
@ -627,12 +691,28 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
def setRelativeWidget(self, attr, floatVal): def setRelativeWidget(self, attr, floatVal):
'''Set a relative widget using a float''' '''Set a relative widget using a float'''
pixelVal = self.pixelValForAttr(attr, floatVal) pixelVal = self.pixelValForAttr(attr, floatVal)
self._trackedWidgets[attr].setValue(pixelVal) with blockSignals(self._allWidgets):
self._trackedWidgets[attr].setValue(pixelVal)
self.update(auto=True)
def getOldAttr(self, attr):
'''
Returns previous state of this attr. Used to determine whether
a relative widget must be updated. Required because undoing/redoing
can make determining the 'previous' value tricky.
'''
if self.oldAttrs is not None:
log.verbose('Using nonstandard oldAttr for %s' % attr)
return self.oldAttrs[attr]
else:
return getattr(self, attr)
def updateRelativeWidget(self, attr): def updateRelativeWidget(self, attr):
'''Called by _preUpdate() for each relativeWidget before each update'''
try: try:
oldUserValue = getattr(self, attr) oldUserValue = self.getOldAttr(attr)
except AttributeError: except (AttributeError, KeyError):
log.info('Using visible values as basis for relative widgets')
oldUserValue = self._trackedWidgets[attr].value() oldUserValue = self._trackedWidgets[attr].value()
newUserValue = self._trackedWidgets[attr].value() newUserValue = self._trackedWidgets[attr].value()
newRelativeVal = self.floatValForAttr(attr, newUserValue) newRelativeVal = self.floatValForAttr(attr, newUserValue)
@ -645,11 +725,10 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
# means the pixel value needs to be updated # means the pixel value needs to be updated
log.debug('Updating %s #%s\'s relative widget: %s' % ( log.debug('Updating %s #%s\'s relative widget: %s' % (
self.name, self.compPos, attr)) self.name, self.compPos, attr))
self._trackedWidgets[attr].blockSignals(True) with blockSignals(self._trackedWidgets[attr]):
self.updateRelativeWidgetMaximum(attr) self.updateRelativeWidgetMaximum(attr)
pixelVal = self.pixelValForAttr(attr, oldRelativeVal) pixelVal = self.pixelValForAttr(attr, oldRelativeVal)
self._trackedWidgets[attr].setValue(pixelVal) self._trackedWidgets[attr].setValue(pixelVal)
self._trackedWidgets[attr].blockSignals(False)
if attr not in self._relativeValues \ if attr not in self._relativeValues \
or oldUserValue != newUserValue: or oldUserValue != newUserValue:
@ -725,14 +804,22 @@ class ComponentUpdate(QtWidgets.QUndoCommand):
parent.name, parent.compPos parent.name, parent.compPos
) )
) )
self.undone = False
self.parent = parent self.parent = parent
self.oldWidgetVals = { self.oldWidgetVals = {
attr: val attr: copy(val)
for attr, val in oldWidgetVals.items() for attr, val in oldWidgetVals.items()
if attr in modifiedVals if attr in modifiedVals
} }
self.modifiedVals = modifiedVals self.modifiedVals = modifiedVals
# Because relative widgets change themselves every update based on
# their previous value, we must store ALL their values in case of undo
self.redoRelativeWidgetVals = {
attr: copy(getattr(self.parent, attr))
for attr in self.parent._relativeWidgets
}
# Determine if this update is mergeable # Determine if this update is mergeable
self.id_ = -1 self.id_ = -1
if len(self.modifiedVals) == 1: if len(self.modifiedVals) == 1:
@ -755,15 +842,26 @@ class ComponentUpdate(QtWidgets.QUndoCommand):
return True return True
def redo(self): def redo(self):
if self.undone:
log.debug('Redoing component update')
self.parent.setWidgetValues(self.modifiedVals)
self.parent.setAttrs(self.modifiedVals) self.parent.setAttrs(self.modifiedVals)
self.parent._sendUpdateSignal() if self.undone:
self.parent.oldAttrs = self.redoRelativeWidgetVals
self.parent.update(auto=True)
self.parent.oldAttrs = None
else:
self.undoRelativeWidgetVals = {
attr: copy(getattr(self.parent, attr))
for attr in self.parent._relativeWidgets
}
self.parent._sendUpdateSignal()
def undo(self): def undo(self):
log.debug('Undoing component update')
self.undone = True
self.parent.oldAttrs = self.undoRelativeWidgetVals
self.parent.setWidgetValues(self.oldWidgetVals)
self.parent.setAttrs(self.oldWidgetVals) self.parent.setAttrs(self.oldWidgetVals)
with blockSignals(self.parent): self.parent.update(auto=True)
for attr, val in self.oldWidgetVals.items(): self.parent.oldAttrs = None
widget = self.parent._trackedWidgets[attr]
if attr in self.parent._colorWidgets:
val = '%s,%s,%s' % val
setWidgetValue(widget, val)
self.parent._sendUpdateSignal()

View File

@ -82,8 +82,6 @@ class Component(Component):
self.page.pushButton_color2.setEnabled(False) self.page.pushButton_color2.setEnabled(False)
self.page.fillWidget.setCurrentIndex(fillType) self.page.fillWidget.setCurrentIndex(fillType)
super().update()
def previewRender(self): def previewRender(self):
return self.drawFrame(self.width, self.height) return self.drawFrame(self.width, self.height)

View File

@ -84,7 +84,6 @@ class Component(Component):
if filename: if filename:
self.settings.setValue("componentDir", os.path.dirname(filename)) self.settings.setValue("componentDir", os.path.dirname(filename))
self.page.lineEdit_image.setText(filename) self.page.lineEdit_image.setText(filename)
self.update()
def command(self, arg): def command(self, arg):
if '=' in arg: if '=' in arg:
@ -123,4 +122,3 @@ class Component(Component):
else: else:
scaleBox.setVisible(True) scaleBox.setVisible(True)
stretchScaleBox.setVisible(False) stretchScaleBox.setVisible(False)
super().update()

View File

@ -53,7 +53,6 @@ class Component(Component):
if filename: if filename:
self.settings.setValue("componentDir", os.path.dirname(filename)) self.settings.setValue("componentDir", os.path.dirname(filename))
self.page.lineEdit_image.setText(filename) self.page.lineEdit_image.setText(filename)
self.update()
def shiftGrid(self, d): def shiftGrid(self, d):
def newGrid(Xchange, Ychange): def newGrid(Xchange, Ychange):

View File

@ -53,7 +53,6 @@ class Component(Component):
if filename: if filename:
self.settings.setValue("componentDir", os.path.dirname(filename)) self.settings.setValue("componentDir", os.path.dirname(filename))
self.page.lineEdit_sound.setText(filename) self.page.lineEdit_sound.setText(filename)
self.update()
def commandHelp(self): def commandHelp(self):
print('Path to audio file:\n path=/filepath/to/sound.ogg') print('Path to audio file:\n path=/filepath/to/sound.ogg')

View File

@ -76,8 +76,6 @@ class Component(Component):
else: else:
self.page.checkBox_mono.setEnabled(True) self.page.checkBox_mono.setEnabled(True)
super().update()
def previewRender(self): def previewRender(self):
changedSize = self.updateChunksize() changedSize = self.updateChunksize()
if not changedSize \ if not changedSize \
@ -138,7 +136,7 @@ class Component(Component):
'-r', self.settings.value("outputFrameRate"), '-r', self.settings.value("outputFrameRate"),
'-ss', "{0:.3f}".format(startPt), '-ss', "{0:.3f}".format(startPt),
'-i', '-i',
os.path.join(self.core.wd, 'background.png') self.core.junkStream
if genericPreview else inputFile, if genericPreview else inputFile,
'-f', 'image2pipe', '-f', 'image2pipe',
'-pix_fmt', 'rgba', '-pix_fmt', 'rgba',

View File

@ -68,7 +68,6 @@ class Component(Component):
self.page.spinBox_shadY.setHidden(True) self.page.spinBox_shadY.setHidden(True)
self.page.label_shadBlur.setHidden(True) self.page.label_shadBlur.setHidden(True)
self.page.spinBox_shadBlur.setHidden(True) self.page.spinBox_shadBlur.setHidden(True)
super().update()
def centerXY(self): def centerXY(self):
self.setRelativeWidget('xPosition', 0.5) self.setRelativeWidget('xPosition', 0.5)

View File

@ -52,7 +52,6 @@ class Component(Component):
else: else:
self.page.label_volume.setEnabled(False) self.page.label_volume.setEnabled(False)
self.page.spinBox_volume.setEnabled(False) self.page.spinBox_volume.setEnabled(False)
super().update()
def previewRender(self): def previewRender(self):
self.updateChunksize() self.updateChunksize()
@ -119,7 +118,6 @@ class Component(Component):
if filename: if filename:
self.settings.setValue("componentDir", os.path.dirname(filename)) self.settings.setValue("componentDir", os.path.dirname(filename))
self.page.lineEdit_video.setText(filename) self.page.lineEdit_video.setText(filename)
self.update()
def getPreviewFrame(self, width, height): def getPreviewFrame(self, width, height):
if not self.videoPath or not os.path.exists(self.videoPath): if not self.videoPath or not os.path.exists(self.videoPath):

View File

@ -98,7 +98,7 @@ class Component(Component):
'-r', self.settings.value("outputFrameRate"), '-r', self.settings.value("outputFrameRate"),
'-ss', "{0:.3f}".format(startPt), '-ss', "{0:.3f}".format(startPt),
'-i', '-i',
os.path.join(self.core.wd, 'background.png') self.core.junkStream
if genericPreview else inputFile, if genericPreview else inputFile,
'-f', 'image2pipe', '-f', 'image2pipe',
'-pix_fmt', 'rgba', '-pix_fmt', 'rgba',

View File

@ -13,7 +13,7 @@ import toolkit
log = logging.getLogger('AVP.Core') log = logging.getLogger('AVP.Core')
STDOUT_LOGLVL = logging.WARNING STDOUT_LOGLVL = logging.VERBOSE
FILE_LOGLVL = logging.DEBUG FILE_LOGLVL = logging.DEBUG
@ -81,10 +81,7 @@ class Core:
component = self.modules[moduleIndex].Component( component = self.modules[moduleIndex].Component(
moduleIndex, compPos, self moduleIndex, compPos, self
) )
# init component's widget for loading/saving presets
component.widget(loader) component.widget(loader)
# use autoUpdate() method before update() this 1 time to set attrs
component._autoUpdate()
else: else:
moduleIndex = -1 moduleIndex = -1
log.debug( log.debug(
@ -186,9 +183,8 @@ class Core:
if hasattr(loader, 'window'): if hasattr(loader, 'window'):
for widget, value in data['WindowFields']: for widget, value in data['WindowFields']:
widget = eval('loader.window.%s' % widget) widget = eval('loader.window.%s' % widget)
widget.blockSignals(True) with toolkit.blockSignals(widget):
toolkit.setWidgetValue(widget, value) toolkit.setWidgetValue(widget, value)
widget.blockSignals(False)
for key, value in data['Settings']: for key, value in data['Settings']:
Core.settings.setValue(key, value) Core.settings.setValue(key, value)
@ -474,6 +470,7 @@ class Core:
'logDir': os.path.join(dataDir, 'log'), 'logDir': os.path.join(dataDir, 'log'),
'presetDir': os.path.join(dataDir, 'presets'), 'presetDir': os.path.join(dataDir, 'presets'),
'componentsPath': os.path.join(wd, 'components'), 'componentsPath': os.path.join(wd, 'components'),
'junkStream': os.path.join(wd, 'gui', 'background.png'),
'encoderOptions': encoderOptions, 'encoderOptions': encoderOptions,
'resolutions': [ 'resolutions': [
'1920x1080', '1920x1080',

View File

@ -20,11 +20,20 @@ class AddComponent(QUndoCommand):
self.parent = parent self.parent = parent
self.moduleI = moduleI self.moduleI = moduleI
self.compI = compI self.compI = compI
self.comp = None
def redo(self): def redo(self):
self.parent.core.insertComponent(self.compI, self.moduleI, self.parent) if self.comp is None:
self.parent.core.insertComponent(
self.compI, self.moduleI, self.parent)
else:
# inserting previously-created component
self.parent.core.insertComponent(
self.compI, self.comp, self.parent)
def undo(self): def undo(self):
self.comp = self.parent.core.selectedComponents[self.compI]
self.parent._removeComponent(self.compI) self.parent._removeComponent(self.compI)

View File

@ -25,7 +25,7 @@ from toolkit import (
) )
log = logging.getLogger('AVP.MainWindow') log = logging.getLogger('AVP.Gui.MainWindow')
class MainWindow(QtWidgets.QMainWindow): class MainWindow(QtWidgets.QMainWindow):
@ -76,7 +76,7 @@ class MainWindow(QtWidgets.QMainWindow):
# Create the preview window and its thread, queues, and timers # Create the preview window and its thread, queues, and timers
log.debug('Creating preview window') log.debug('Creating preview window')
self.previewWindow = PreviewWindow(self, os.path.join( self.previewWindow = PreviewWindow(self, os.path.join(
Core.wd, "background.png")) Core.wd, 'gui', "background.png"))
window.verticalLayout_previewWrapper.addWidget(self.previewWindow) window.verticalLayout_previewWrapper.addWidget(self.previewWindow)
log.debug('Starting preview thread') log.debug('Starting preview thread')

View File

@ -5,12 +5,16 @@
from PyQt5 import QtCore, QtWidgets from PyQt5 import QtCore, QtWidgets
import string import string
import os import os
import logging
from toolkit import badName from toolkit import badName
from core import Core from core import Core
from gui.actions import * from gui.actions import *
log = logging.getLogger('AVP.Gui.PresetManager')
class PresetManager(QtWidgets.QDialog): class PresetManager(QtWidgets.QDialog):
def __init__(self, window, parent): def __init__(self, window, parent):
super().__init__(parent.window) super().__init__(parent.window)

View File

@ -14,7 +14,7 @@ from toolkit.frame import Checkerboard
from toolkit import disableWhenOpeningProject from toolkit import disableWhenOpeningProject
log = logging.getLogger("AVP.PreviewThread") log = logging.getLogger("AVP.Gui.PreviewThread")
class Worker(QtCore.QObject): class Worker(QtCore.QObject):

View File

@ -7,7 +7,7 @@ class PreviewWindow(QtWidgets.QLabel):
Paints the preview QLabel in MainWindow and maintains the aspect ratio Paints the preview QLabel in MainWindow and maintains the aspect ratio
when the window is resized. when the window is resized.
''' '''
log = logging.getLogger('AVP.PreviewWindow') log = logging.getLogger('AVP.Gui.PreviewWindow')
def __init__(self, parent, img): def __init__(self, parent, img):
super(PreviewWindow, self).__init__() super(PreviewWindow, self).__init__()

View File

@ -6,7 +6,7 @@ import logging
from __init__ import wd from __init__ import wd
log = logging.getLogger('AVP.Entrypoint') log = logging.getLogger('AVP.Main')
def main(): def main():

View File

@ -6,19 +6,53 @@ import string
import os import os
import sys import sys
import subprocess import subprocess
import logging
from copy import copy
from collections import OrderedDict from collections import OrderedDict
log = logging.getLogger('AVP.Toolkit.Common')
class blockSignals: class blockSignals:
'''A context manager to temporarily block a Qt widget from updating''' '''
def __init__(self, widget): Context manager to temporarily block list of QtWidgets from updating,
self.widget = widget and guarantee restoring the previous state afterwards.
'''
def __init__(self, widgets):
if type(widgets) is dict:
self.widgets = concatDictVals(widgets)
else:
self.widgets = (
widgets if hasattr(widgets, '__iter__')
else [widgets]
)
def __enter__(self): def __enter__(self):
self.widget.blockSignals(True) log.verbose('Blocking signals for %s' % ", ".join([
str(w.__class__.__name__) for w in self.widgets
]))
self.oldStates = [w.signalsBlocked() for w in self.widgets]
for w in self.widgets:
w.blockSignals(True)
def __exit__(self, *args): def __exit__(self, *args):
self.widget.blockSignals(False) log.verbose('Resetting blockSignals to %s' % sum(self.oldStates))
for w, state in zip(self.widgets, self.oldStates):
w.blockSignals(state)
def concatDictVals(d):
'''Concatenates all values in given dict into one list.'''
key, value = d.popitem()
d[key] = value
final = copy(value)
if type(final) is not list:
final = [final]
final.extend([val for val in d.values()])
else:
value.extend([item for val in d.values() for item in val])
return final
def badName(name): def badName(name):
@ -119,12 +153,14 @@ def connectWidget(widget, func):
elif type(widget) == QtWidgets.QComboBox: elif type(widget) == QtWidgets.QComboBox:
widget.currentIndexChanged.connect(func) widget.currentIndexChanged.connect(func)
else: else:
log.warning('Failed to connect %s ' % str(widget.__class__.__name__))
return False return False
return True return True
def setWidgetValue(widget, val): def setWidgetValue(widget, val):
'''Generic setValue method for use with any typical QtWidget''' '''Generic setValue method for use with any typical QtWidget'''
log.verbose('Setting %s to %s' % (str(widget.__class__.__name__), val))
if type(widget) == QtWidgets.QLineEdit: if type(widget) == QtWidgets.QLineEdit:
widget.setText(val) widget.setText(val)
elif type(widget) == QtWidgets.QSpinBox \ elif type(widget) == QtWidgets.QSpinBox \
@ -135,6 +171,7 @@ def setWidgetValue(widget, val):
elif type(widget) == QtWidgets.QComboBox: elif type(widget) == QtWidgets.QComboBox:
widget.setCurrentIndex(val) widget.setCurrentIndex(val)
else: else:
log.warning('Failed to set %s ' % str(widget.__class__.__name__))
return False return False
return True return True