add component in context menu, del/ins hotkeys

+ preset manager uses mainwindow component list
This commit is contained in:
tassaron 2017-07-20 22:37:15 -04:00
parent f454814867
commit 450b944b87
8 changed files with 123 additions and 69 deletions

View File

@ -2,7 +2,7 @@ from cx_Freeze import setup, Executable
import sys
import os
from setup import VERSION
from setup import __version__
deps = [os.path.join('src', p) for p in os.listdir('src') if p]
@ -52,7 +52,7 @@ executables = [
setup(
name='audio-visualizer-python',
version=VERSION,
version=__version__,
description='GUI tool to render visualization videos of audio files',
options=dict(build_exe=buildOptions),
executables=executables

View File

@ -2,7 +2,7 @@ from setuptools import setup
import os
VERSION = '2.0.0.rc1'
__version__ = '2.0.0.rc1'
def package_files(directory):
@ -15,7 +15,7 @@ def package_files(directory):
setup(
name='audio_visualizer_python',
version=VERSION,
version=__version__,
url='https://github.com/djfun/audio-visualizer-python/tree/feature-newgui',
license='MIT',
description='Create audio visualization videos from a GUI or commandline',

View File

@ -0,0 +1 @@

View File

@ -16,7 +16,7 @@ class Video:
'''Video Component Frame-Fetcher'''
def __init__(self, **kwargs):
mandatoryArgs = [
'ffmpeg', # path to ffmpeg, usually core.FFMPEG_BIN
'ffmpeg', # path to ffmpeg, usually Core.FFMPEG_BIN
'videoPath',
'width',
'height',
@ -28,7 +28,7 @@ class Video:
]
for arg in mandatoryArgs:
try:
exec('self.%s = kwargs[arg]' % arg)
setattr(self, arg, kwargs[arg])
except KeyError:
raise BadComponentInit(arg, self.__doc__)

View File

@ -15,16 +15,14 @@ import video_thread
class Core:
'''
MainWindow and Command module both use an instance of this class
to store the main program state. This object tracks the components
as an instance, has methods for managing the components and for
opening/creating project files and presets.
to store the core program state. This object tracks the components,
talks to the components and handles opening/creating project files
and presets. The class also stores constants as class variables.
'''
@classmethod
def storeSettings(cls):
'''
Stores settings/paths to directories as class variables
'''
'''Store settings/paths to directories as class variables.'''
if getattr(sys, 'frozen', False):
# frozen
wd = os.path.dirname(sys.executable)

View File

@ -178,7 +178,6 @@ class MainWindow(QtWidgets.QMainWindow):
# Make component buttons
self.compMenu = QMenu()
self.compActions = []
for i, comp in enumerate(self.core.modules):
action = self.compMenu.addAction(comp.Component.name)
action.triggered.connect(
@ -191,6 +190,9 @@ class MainWindow(QtWidgets.QMainWindow):
componentList.itemSelectionChanged.connect(
self.changeComponentWidget
)
componentList.itemSelectionChanged.connect(
self.presetManager.clearPresetListSelection
)
self.window.pushButton_removeComponent.clicked.connect(
lambda: self.removeComponent()
)
@ -313,22 +315,23 @@ class MainWindow(QtWidgets.QMainWindow):
)
self.settings.setValue("ffmpegMsgShown", True)
# Setup Hotkeys
# Hotkeys for projects
QtWidgets.QShortcut("Ctrl+S", self.window, self.saveCurrentProject)
QtWidgets.QShortcut("Ctrl+A", self.window, self.openSaveProjectDialog)
QtWidgets.QShortcut("Ctrl+O", self.window, self.openOpenProjectDialog)
QtWidgets.QShortcut("Ctrl+N", self.window, self.createNewProject)
QtWidgets.QShortcut(
"Ctrl+Alt+Shift+R", self.window, self.drawPreview
)
QtWidgets.QShortcut(
"Ctrl+Alt+Shift+F", self.window, self.showFfmpegCommand
)
QtWidgets.QShortcut(
"Ctrl+T", self.window,
activated=lambda: self.window.pushButton_addComponent.click()
)
# Hotkeys for component list
for inskey in ("Ctrl+T", QtCore.Qt.Key_Insert):
QtWidgets.QShortcut(
inskey, self.window,
activated=lambda: self.window.pushButton_addComponent.click()
)
for delkey in ("Ctrl+R", QtCore.Qt.Key_Delete):
QtWidgets.QShortcut(
delkey, self.window.listWidget_componentList,
self.removeComponent
)
QtWidgets.QShortcut(
"Ctrl+Space", self.window,
activated=lambda: self.window.listWidget_componentList.setFocus()
@ -342,22 +345,29 @@ class MainWindow(QtWidgets.QMainWindow):
)
QtWidgets.QShortcut(
"Ctrl+Up", self.window,
"Ctrl+Up", self.window.listWidget_componentList,
activated=lambda: self.moveComponent(-1)
)
QtWidgets.QShortcut(
"Ctrl+Down", self.window,
"Ctrl+Down", self.window.listWidget_componentList,
activated=lambda: self.moveComponent(1)
)
QtWidgets.QShortcut(
"Ctrl+Home", self.window,
"Ctrl+Home", self.window.listWidget_componentList,
activated=lambda: self.moveComponent('top')
)
QtWidgets.QShortcut(
"Ctrl+End", self.window,
"Ctrl+End", self.window.listWidget_componentList,
activated=lambda: self.moveComponent('bottom')
)
QtWidgets.QShortcut("Ctrl+r", self.window, self.removeComponent)
# Debug Hotkeys
QtWidgets.QShortcut(
"Ctrl+Alt+Shift+R", self.window, self.drawPreview
)
QtWidgets.QShortcut(
"Ctrl+Alt+Shift+F", self.window, self.showFfmpegCommand
)
@QtCore.pyqtSlot()
def cleanUp(self):
@ -677,9 +687,7 @@ class MainWindow(QtWidgets.QMainWindow):
stackedWidget.setCurrentIndex(newRow)
self.drawPreview()
@disableWhenEncoding
def dragComponent(self, event):
'''Used as Qt drop event for the component listwidget'''
def getComponentListRects(self):
componentList = self.window.listWidget_componentList
modelIndexes = [
@ -690,6 +698,13 @@ class MainWindow(QtWidgets.QMainWindow):
componentList.visualRect(modelIndex)
for modelIndex in modelIndexes
]
return rects
@disableWhenEncoding
def dragComponent(self, event):
'''Used as Qt drop event for the component listwidget'''
componentList = self.window.listWidget_componentList
rects = self.getComponentListRects()
rowPos = [rect.contains(event.pos()) for rect in rects]
if not any(rowPos):
@ -826,47 +841,63 @@ class MainWindow(QtWidgets.QMainWindow):
@disableWhenEncoding
def componentContextMenu(self, QPos):
'''Appears when right-clicking a component in the list'''
'''Appears when right-clicking the component list'''
componentList = self.window.listWidget_componentList
if not componentList.selectedItems():
return
# don't show menu if clicking empty space
parentPosition = componentList.mapToGlobal(QtCore.QPoint(0, 0))
index = componentList.currentRow()
modelIndex = componentList.model().index(index)
if not componentList.visualRect(modelIndex).contains(QPos):
return
self.presetManager.findPresets()
self.menu = QMenu()
menuItem = self.menu.addAction("Save Preset")
menuItem.triggered.connect(
self.presetManager.openSavePresetDialog
)
parentPosition = componentList.mapToGlobal(QtCore.QPoint(0, 0))
# submenu for opening presets
try:
presets = self.presetManager.presets[
str(self.core.selectedComponents[index])
]
self.submenu = QMenu("Open Preset")
self.menu.addMenu(self.submenu)
rects = self.getComponentListRects()
rowPos = [rect.contains(QPos) for rect in rects]
if not any(rowPos):
# Insert components at the top if clicking nothing
rowPos = 0
else:
rowPos = rowPos.index(True)
for version, presetName in presets:
menuItem = self.submenu.addAction(presetName)
menuItem.triggered.connect(
lambda _, presetName=presetName:
self.presetManager.openPreset(presetName)
)
except KeyError:
pass
if self.core.selectedComponents[index].currentPreset:
menuItem = self.menu.addAction("Clear Preset")
if index == rowPos:
# Show preset menu if clicking a component
self.presetManager.findPresets()
menuItem = self.menu.addAction("Save Preset")
menuItem.triggered.connect(
self.presetManager.clearPreset
self.presetManager.openSavePresetDialog
)
# submenu for opening presets
try:
presets = self.presetManager.presets[
str(self.core.selectedComponents[index])
]
self.presetSubmenu = QMenu("Open Preset")
self.menu.addMenu(self.presetSubmenu)
for version, presetName in presets:
menuItem = self.presetSubmenu.addAction(presetName)
menuItem.triggered.connect(
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
)
self.menu.addSeparator()
# "Add Component" submenu
self.submenu = QMenu("Add")
self.menu.addMenu(self.submenu)
for i, comp in enumerate(self.core.modules):
menuItem = self.submenu.addAction(comp.Component.name)
menuItem.triggered.connect(
lambda _, item=i: self.core.insertComponent(
rowPos, item, self
)
)
self.menu.move(parentPosition + QPos)
self.menu.show()

View File

@ -245,11 +245,25 @@ class PresetManager(QtWidgets.QDialog):
def openRenamePresetDialog(self):
# TODO: maintain consistency by changing this to call createNewPreset()
presetList = self.window.listWidget_presets
if presetList.currentRow() == -1:
return
index = presetList.currentRow()
if index == -1:
# check if component selected in MainWindow has preset loaded
componentList = self.parent.window.listWidget_componentList
compIndex = componentList.currentRow()
if compIndex == -1:
return
preset = self.core.selectedComponents[compIndex].currentPreset
if not preset:
return
else:
for i, tup in enumerate(self.presetRows):
if preset == tup[2]:
index = i
break
else:
return
while True:
index = presetList.currentRow()
newName, OK = QtWidgets.QInputDialog.getText(
self.window,
'Preset Manager',
@ -321,3 +335,6 @@ class PresetManager(QtWidgets.QDialog):
parent=self.window
)
self.settings.setValue("presetDir", os.path.dirname(filename))
def clearPresetListSelection(self):
self.window.listWidget_presets.setCurrentRow(-1)

View File

@ -113,7 +113,7 @@ def createFfmpegCommand(inputFile, outputFile, components, duration=-1):
'-t', safeDuration,
# Tell ffmpeg about shorter clips (seemingly not needed)
# streamDuration = getAudioDuration(extraInputFile)
# if streamDuration > float(safeDuration)
# if streamDuration and streamDuration > float(safeDuration)
# else "{0:.3f}".format(streamDuration),
'-i', extraInputFile
])
@ -228,11 +228,18 @@ def getAudioDuration(filename):
d = d.split(' ')[3]
d = d.split(':')
duration = float(d[0])*3600 + float(d[1])*60 + float(d[2])
break
else:
# String not found in output
return False
return duration
def readAudioFile(filename, parent):
duration = getAudioDuration(filename)
if not duration:
print('Audio file doesn\'t exist or unreadable.')
return
command = [
Core.FFMPEG_BIN,