From f55d7d120639cc4b83850699b8de57e036977288 Mon Sep 17 00:00:00 2001 From: tassaron Date: Thu, 1 Jun 2017 13:17:36 -0400 Subject: [PATCH 1/7] saveable titleFont, xPosition glitches fixed --- components/text.py | 24 +++++++++++++++++------- main.py | 4 +++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/components/text.py b/components/text.py index 716030b..9237167 100644 --- a/components/text.py +++ b/components/text.py @@ -61,21 +61,29 @@ class Component(__base__.Component): self.xPosition = self.page.spinBox_xTextAlign.value() self.yPosition = self.page.spinBox_yTextAlign.value() self.textColor = self.RGBFromString(self.page.lineEdit_textColor.text()) + + self.parent.drawPreview() + + def getXY(self): + '''Returns true x, y after considering alignment settings''' fm = QtGui.QFontMetrics(self.titleFont) if self.alignment == 0: #Left - self.xPosition = self.xPosition + x = self.xPosition if self.alignment == 1: #Middle - self.xPosition = self.xPosition - fm.width(self.title)/2 + x = self.xPosition - fm.width(self.title)/2 if self.alignment == 2: #Right - self.xPosition = self.xPosition - fm.width(self.title) - self.parent.drawPreview() - + x = self.xPosition - fm.width(self.title) + return x, self.yPosition + + def loadPreset(self, pr): self.page.lineEdit_title.setText(pr['title']) + font = QFont(); font.fromString(pr['titleFont']) + self.page.fontComboBox_titleFont.setCurrentFont(font) self.page.spinBox_fontSize.setValue(pr['fontSize']) + self.page.comboBox_textAlign.setCurrentIndex(pr['alignment']) self.page.spinBox_xTextAlign.setValue(pr['xPosition']) self.page.spinBox_yTextAlign.setValue(pr['yPosition']) - self.page.comboBox_textAlign.setCurrentIndex(pr['alignment']) self.page.lineEdit_textColor.setText('%s,%s,%s' % pr['textColor']) btnStyle = "QPushButton { background-color : %s; outline: none; }" % QColor(*pr['textColor']).name() self.page.pushButton_textColor.setStyleSheet(btnStyle) @@ -83,6 +91,7 @@ class Component(__base__.Component): def savePreset(self): return { 'title' : self.title, + 'titleFont' : self.titleFont.toString(), 'alignment' : self.alignment, 'fontSize' : self.fontSize, 'xPosition' : self.xPosition, @@ -105,6 +114,7 @@ class Component(__base__.Component): return self.addText(width, height) def addText(self, width, height): + x, y = self.getXY() im = Image.new("RGBA", (width, height),(0,0,0,0)) image = ImageQt(im) @@ -112,7 +122,7 @@ class Component(__base__.Component): self.titleFont.setPixelSize(self.fontSize) painter.setFont(self.titleFont) painter.setPen(QColor(*self.textColor)) - painter.drawText(self.xPosition, self.yPosition, self.title) + painter.drawText(x, y, self.title) painter.end() buffer = QtCore.QBuffer() diff --git a/main.py b/main.py index 1cbe1db..c8ad4e8 100644 --- a/main.py +++ b/main.py @@ -388,12 +388,14 @@ class Main(QtCore.QObject): if ch != 1024: # 1024 = OK return # remove old copies of the preset - for i in range(0, self.windowcomboBox_openPreset.count()): + presetLen = self.window.comboBox_openPreset.count() + for i in range(0, presetLen): if self.window.comboBox_openPreset.itemText(i) == filename: self.window.comboBox_openPreset.removeItem(i) with open(filepath, 'w') as f: f.write('%s' % repr(saveValueStore)) self.window.comboBox_openPreset.addItem(filename) + self.window.comboBox_openPreset.setCurrentIndex(presetLen-1) def openPreset(self): if self.window.comboBox_openPreset.currentIndex() < 1: From 1a24922fee9cb86bf8814f57c0f8f2dd77f27a3f Mon Sep 17 00:00:00 2001 From: tassaron Date: Thu, 1 Jun 2017 16:16:42 -0400 Subject: [PATCH 2/7] restrict presets to boring characters --- main.py | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/main.py b/main.py index c8ad4e8..00ba96b 100644 --- a/main.py +++ b/main.py @@ -1,8 +1,6 @@ -import sys, io, os +import sys, io, os, atexit, string, signal from os.path import expanduser -import atexit from queue import Queue -import signal from importlib import import_module from PyQt4 import QtCore, QtGui, uic from PyQt4.QtCore import QSettings, QModelIndex @@ -365,14 +363,28 @@ class Main(QtCore.QObject): def openSavePresetDialog(self): if self.window.listWidget_componentList.currentRow() == -1: return - newName, OK = QtGui.QInputDialog.getText(QtGui.QWidget(), 'Audio Visualizer', 'New Preset Name:') - if OK and newName: - index = self.window.listWidget_componentList.currentRow() - if index != -1: - saveValueStore = self.selectedComponents[index].savePreset() - componentName = str(self.selectedComponents[index]).strip() - vers = self.selectedComponents[index].version() - self.createPresetFile(componentName, vers, saveValueStore, newName) + while True: + newName, OK = QtGui.QInputDialog.getText(QtGui.QWidget(), 'Audio Visualizer', 'New Preset Name:') + badName = False + for letter in newName: + if letter in string.punctuation: + badName = True + if badName: + # some filesystems don't like bizarre characters + msg = QtGui.QMessageBox() + msg.setIcon(QtGui.QMessageBox.Information) + msg.setText("Preset names must contain only letters, numbers, and spaces.") + msg.setStandardButtons(QtGui.QMessageBox.Ok) + msg.exec_() + continue + if OK and newName: + index = self.window.listWidget_componentList.currentRow() + if index != -1: + saveValueStore = self.selectedComponents[index].savePreset() + componentName = str(self.selectedComponents[index]).strip() + vers = self.selectedComponents[index].version() + self.createPresetFile(componentName, vers, saveValueStore, newName) + break def createPresetFile(self, componentName, version, saveValueStore, filename): dirname = os.path.join(self.dataDir, 'presets', componentName, str(version)) @@ -388,21 +400,19 @@ class Main(QtCore.QObject): if ch != 1024: # 1024 = OK return # remove old copies of the preset - presetLen = self.window.comboBox_openPreset.count() - for i in range(0, presetLen): + for i in range(0, self.window.comboBox_openPreset.count()): if self.window.comboBox_openPreset.itemText(i) == filename: self.window.comboBox_openPreset.removeItem(i) with open(filepath, 'w') as f: f.write('%s' % repr(saveValueStore)) self.window.comboBox_openPreset.addItem(filename) - self.window.comboBox_openPreset.setCurrentIndex(presetLen-1) + self.window.comboBox_openPreset.setCurrentIndex(self.window.comboBox_openPreset.count()-1) def openPreset(self): if self.window.comboBox_openPreset.currentIndex() < 1: return index = self.window.listWidget_componentList.currentRow() if index == -1: - # no component selected return filename = self.window.comboBox_openPreset.itemText(self.window.comboBox_openPreset.currentIndex()) componentName = str(self.selectedComponents[index]).strip() From 907ba33e93b5e8c33be8c74dd787f78e1b3fa109 Mon Sep 17 00:00:00 2001 From: tassaron Date: Thu, 1 Jun 2017 17:34:04 -0400 Subject: [PATCH 3/7] a handy showMessage() method and starting on the project buttons --- main.py | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/main.py b/main.py index 00ba96b..dc18179 100644 --- a/main.py +++ b/main.py @@ -178,6 +178,8 @@ class Main(QtCore.QObject): self.window.pushButton_savePreset.clicked.connect(self.openSavePresetDialog) self.window.comboBox_openPreset.currentIndexChanged.connect(self.openPreset) + self.window.pushButton_saveProject.clicked.connect(self.openSaveProjectDialog) + #self.window.pushButton_openProject self.drawPreview() @@ -249,8 +251,7 @@ class Main(QtCore.QObject): self.window.lineEdit_outputFile.text(), self.selectedComponents) else: - # TODO: use QMessageBox or similar to alert user that fields are empty - pass + self.showMessage("You must select an audio file and output filename.") def progressBarUpdated(self, value): self.window.progressBar_createVideo.setValue(value) @@ -371,11 +372,7 @@ class Main(QtCore.QObject): badName = True if badName: # some filesystems don't like bizarre characters - msg = QtGui.QMessageBox() - msg.setIcon(QtGui.QMessageBox.Information) - msg.setText("Preset names must contain only letters, numbers, and spaces.") - msg.setStandardButtons(QtGui.QMessageBox.Ok) - msg.exec_() + self.showMessage("Preset names must contain only letters, numbers, and spaces.") continue if OK and newName: index = self.window.listWidget_componentList.currentRow() @@ -392,19 +389,15 @@ class Main(QtCore.QObject): os.makedirs(dirname) filepath = os.path.join(dirname, filename) if os.path.exists(filepath): - msg = QtGui.QMessageBox() - msg.setIcon(QtGui.QMessageBox.Warning) - msg.setText("%s already exists! Overwrite it?" % filename) - msg.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) - ch = msg.exec_() - if ch != 1024: # 1024 = OK + ch = self.showMessage("%s already exists! Overwrite it?" % filename, QtGui.QMessageBox.Warning, True) + if not ch: return # remove old copies of the preset for i in range(0, self.window.comboBox_openPreset.count()): if self.window.comboBox_openPreset.itemText(i) == filename: self.window.comboBox_openPreset.removeItem(i) with open(filepath, 'w') as f: - f.write('%s' % repr(saveValueStore)) + f.write(repr(saveValueStore)) self.window.comboBox_openPreset.addItem(filename) self.window.comboBox_openPreset.setCurrentIndex(self.window.comboBox_openPreset.count()-1) @@ -429,6 +422,33 @@ class Main(QtCore.QObject): self.selectedComponents[index].loadPreset(saveValueStore) self.drawPreview() + def openSaveProjectDialog(self): + outputDir = os.path.join(self.dataDir, 'projects') + filename = QtGui.QFileDialog.getSaveFileName(self.window, + "Create Project File", outputDir) + if not filename: + return + filepath = os.path.join(outputDir, filename) + with open(filepath, 'w') as f: + for comp in self.selectedComponents: + saveValueStore = comp.savePreset() + f.write('%s\n' % str(comp)) + f.write('%s\n' % str(comp.version())) + f.write('%s\n' % repr(saveValueStore)) + + def showMessage(self, string, icon=QtGui.QMessageBox.Information, showCancel=False): + msg = QtGui.QMessageBox() + msg.setIcon(icon) + msg.setText(string) + if showCancel: + msg.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) + else: + msg.setStandardButtons(QtGui.QMessageBox.Ok) + ch = msg.exec_() + if ch == 1024: + return True + return False + def LoadDefaultSettings(self): self.resolutions = [ '1920x1080', From 00f5c885842c15ef86cae9c0fdabca997016182b Mon Sep 17 00:00:00 2001 From: tassaron Date: Thu, 1 Jun 2017 18:47:47 -0400 Subject: [PATCH 4/7] components can be saved and loaded as projects --- main.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/main.py b/main.py index dc18179..220d594 100644 --- a/main.py +++ b/main.py @@ -121,6 +121,7 @@ class Main(QtCore.QObject): self.core = core.Core() self.settings = QSettings('settings.ini', QSettings.IniFormat) LoadDefaultSettings(self) + self.currentProject = None # create data directory structure if needed self.dataDir = QDesktopServices.storageLocation(QDesktopServices.DataLocation) @@ -136,10 +137,8 @@ class Main(QtCore.QObject): self.previewThread = QtCore.QThread(self) self.previewWorker = preview_thread.Worker(self, self.previewQueue) - self.previewWorker.moveToThread(self.previewThread) self.previewWorker.imageCreated.connect(self.showPreviewImage) - self.previewThread.start() self.timer = QtCore.QTimer(self) @@ -178,8 +177,9 @@ class Main(QtCore.QObject): self.window.pushButton_savePreset.clicked.connect(self.openSavePresetDialog) self.window.comboBox_openPreset.currentIndexChanged.connect(self.openPreset) - self.window.pushButton_saveProject.clicked.connect(self.openSaveProjectDialog) - #self.window.pushButton_openProject + self.window.pushButton_saveAs.clicked.connect(self.openSaveProjectDialog) + self.window.pushButton_saveProject.clicked.connect(self.saveCurrentProject) + self.window.pushButton_openProject.clicked.connect(self.openOpenProjectDialog) self.drawPreview() @@ -422,19 +422,55 @@ class Main(QtCore.QObject): self.selectedComponents[index].loadPreset(saveValueStore) self.drawPreview() + def saveCurrentProject(self): + if self.currentProject: + self.createProjectFile(self.currentProject) + else: + self.openSaveProjectDialog() + def openSaveProjectDialog(self): outputDir = os.path.join(self.dataDir, 'projects') - filename = QtGui.QFileDialog.getSaveFileName(self.window, - "Create Project File", outputDir) + filename = QtGui.QFileDialog.getSaveFileName(self.window, "Create Project File", outputDir) if not filename: return filepath = os.path.join(outputDir, filename) + self.currentProject = filepath + self.createProjectFile(filepath) + + def createProjectFile(self, filepath): with open(filepath, 'w') as f: for comp in self.selectedComponents: saveValueStore = comp.savePreset() f.write('%s\n' % str(comp)) f.write('%s\n' % str(comp.version())) f.write('%s\n' % repr(saveValueStore)) + + def openOpenProjectDialog(self): + inputDir = os.path.join(self.dataDir, 'projects') + filename = QtGui.QFileDialog.getOpenFileName(self.window, "Open Project File", inputDir) + if not filename: + return + filepath = os.path.join(inputDir, filename) + self.openProject(filepath) + + def openProject(self, filepath): + self.clear() + self.currentProject = filepath + compNames = [mod.Component.__doc__ for mod in self.modules] + with open(filepath, 'r') as f: + i = 0 + for line in f: + if i == 0: + compIndex = compNames.index(line.strip()) + self.addComponent(compIndex) + i += 1 + elif i == 1: + # version, not used yet + i += 1 + elif i == 2: + saveValueStore = eval(line.strip()) + self.selectedComponents[-1].loadPreset(saveValueStore) + i = 0 def showMessage(self, string, icon=QtGui.QMessageBox.Information, showCancel=False): msg = QtGui.QMessageBox() @@ -448,6 +484,14 @@ class Main(QtCore.QObject): if ch == 1024: return True return False + + def clear(self): + ''' empty out all components and fields, get a blank slate ''' + self.selectedComponents = [] + self.window.listWidget_componentList.clear() + for widget in self.pages: + self.window.stackedWidget.removeWidget(widget) + self.pages = [] def LoadDefaultSettings(self): self.resolutions = [ From 610db2060678b8b848785dc8f309944de2a96e9a Mon Sep 17 00:00:00 2001 From: tassaron Date: Thu, 1 Jun 2017 19:54:50 -0400 Subject: [PATCH 5/7] settings.ini now saved/loaded with projects --- main.py | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/main.py b/main.py index 220d594..470a0a9 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -import sys, io, os, atexit, string, signal +import sys, io, os, shutil, atexit, string, signal from os.path import expanduser from queue import Queue from importlib import import_module @@ -119,22 +119,21 @@ class Main(QtCore.QObject): # print('main thread id: {}'.format(QtCore.QThread.currentThreadId())) self.window = window self.core = core.Core() - self.settings = QSettings('settings.ini', QSettings.IniFormat) - LoadDefaultSettings(self) self.currentProject = None + self.pages = [] + self.selectedComponents = [] # create data directory structure if needed self.dataDir = QDesktopServices.storageLocation(QDesktopServices.DataLocation) if not os.path.exists(self.dataDir): os.makedirs(self.dataDir) - for neededDirectory in ('projects', 'presets'): + for neededDirectory in ('projects', 'project-settings', 'presets'): if not os.path.exists(os.path.join(self.dataDir, neededDirectory)): os.mkdir(os.path.join(self.dataDir, neededDirectory)) - - self.pages = [] + self.settings = QSettings(os.path.join(self.dataDir, 'settings.ini'), QSettings.IniFormat) + LoadDefaultSettings(self) self.previewQueue = Queue() - self.previewThread = QtCore.QThread(self) self.previewWorker = preview_thread.Worker(self, self.previewQueue) self.previewWorker.moveToThread(self.previewThread) @@ -152,12 +151,11 @@ class Main(QtCore.QObject): window.progressBar_createVideo.setValue(0) window.pushButton_createVideo.clicked.connect(self.createAudioVisualisation) window.setWindowTitle("Audio Visualizer") - + self.modules = self.findComponents() for component in self.modules: window.comboBox_componentSelection.addItem(component.Component.__doc__) window.listWidget_componentList.clicked.connect(lambda _: self.changeComponentWidget()) - self.selectedComponents = [] self.window.pushButton_addComponent.clicked.connect( \ lambda _: self.addComponent(self.window.comboBox_componentSelection.currentIndex()) @@ -189,16 +187,11 @@ class Main(QtCore.QObject): self.timer.stop() self.previewThread.quit() self.previewThread.wait() - # TODO: replace remembered settings with presets/projects - ''' - self.settings.setValue("titleFont", self.window.fontComboBox_titleFont.currentFont().toString()) - self.settings.setValue("alignment", str(self.window.comboBox_textAlign.currentIndex())) - self.settings.setValue("fontSize", str(self.window.spinBox_fontSize.value())) - self.settings.setValue("xPosition", str(self.window.spinBox_xTextAlign.value())) - self.settings.setValue("yPosition", str(self.window.spinBox_yTextAlign.value())) - self.settings.setValue("visColor", self.window.lineEdit_visColor.text()) - self.settings.setValue("textColor", self.window.lineEdit_textColor.text()) - ''' + backupPath = os.path.join(self.dataDir, 'settings.ini~') + settingsPath = os.path.join(self.dataDir, 'settings.ini') + if self.currentProject: + os.remove(settingsPath) + os.rename(backupPath, settingsPath) def openInputFileDialog(self): inputDir = self.settings.value("inputDir", expanduser("~")) @@ -444,6 +437,8 @@ class Main(QtCore.QObject): f.write('%s\n' % str(comp)) f.write('%s\n' % str(comp.version())) f.write('%s\n' % repr(saveValueStore)) + dir_ = os.path.join(self.dataDir, 'project-settings') + shutil.copyfile(self.settings.fileName(), os.path.join(dir_, os.path.basename('%s.ini' % filepath))) def openOpenProjectDialog(self): inputDir = os.path.join(self.dataDir, 'projects') @@ -471,6 +466,15 @@ class Main(QtCore.QObject): saveValueStore = eval(line.strip()) self.selectedComponents[-1].loadPreset(saveValueStore) i = 0 + projSettingsPath = os.path.join(self.dataDir, 'project-settings', '%s.ini' % os.path.basename(filepath)) + backupPath = os.path.join(self.dataDir, 'settings.ini~') + settingsPath = os.path.join(self.dataDir, 'settings.ini') + if os.path.exists(backupPath): + os.remove(backupPath) + os.rename(settingsPath, backupPath) + #os.remove(settingsPath) + shutil.copyfile(projSettingsPath, settingsPath) + self.settings.sync() def showMessage(self, string, icon=QtGui.QMessageBox.Information, showCancel=False): msg = QtGui.QMessageBox() @@ -510,7 +514,6 @@ def LoadDefaultSettings(self): "outputVideoFormat": "yuv420p", "outputPreset": "medium", "outputFormat": "mp4", - "visLayout": 0 } for parm, value in default.items(): From d31add0d955f58d1fa375d3166ac519a21f80c6b Mon Sep 17 00:00:00 2001 From: tassaron Date: Thu, 1 Jun 2017 20:21:26 -0400 Subject: [PATCH 6/7] tidying up --- main.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index 470a0a9..ba62c2c 100644 --- a/main.py +++ b/main.py @@ -188,7 +188,7 @@ class Main(QtCore.QObject): self.previewThread.quit() self.previewThread.wait() backupPath = os.path.join(self.dataDir, 'settings.ini~') - settingsPath = os.path.join(self.dataDir, 'settings.ini') + settingsPath = self.settings.fileName() if self.currentProject: os.remove(settingsPath) os.rename(backupPath, settingsPath) @@ -327,6 +327,7 @@ class Main(QtCore.QObject): self.window.stackedWidget.insertWidget(row - 1, page) self.window.listWidget_componentList.setCurrentRow(row - 1) self.window.stackedWidget.setCurrentIndex(row -1) + self.drawPreview() def moveComponentDown(self): row = self.window.listWidget_componentList.currentRow() @@ -343,6 +344,7 @@ class Main(QtCore.QObject): self.window.stackedWidget.insertWidget(row + 1, page) self.window.listWidget_componentList.setCurrentRow(row + 1) self.window.stackedWidget.setCurrentIndex(row + 1) + self.drawPreview() def updateOpenPresetComboBox(self, component): self.window.comboBox_openPreset.clear() @@ -437,8 +439,8 @@ class Main(QtCore.QObject): f.write('%s\n' % str(comp)) f.write('%s\n' % str(comp.version())) f.write('%s\n' % repr(saveValueStore)) - dir_ = os.path.join(self.dataDir, 'project-settings') - shutil.copyfile(self.settings.fileName(), os.path.join(dir_, os.path.basename('%s.ini' % filepath))) + projSettingsPath = os.path.join(self.dataDir, 'project-settings', os.path.basename('%s.ini' % filepath)) + shutil.copyfile(self.settings.fileName(), projSettingsPath) def openOpenProjectDialog(self): inputDir = os.path.join(self.dataDir, 'projects') @@ -468,11 +470,10 @@ class Main(QtCore.QObject): i = 0 projSettingsPath = os.path.join(self.dataDir, 'project-settings', '%s.ini' % os.path.basename(filepath)) backupPath = os.path.join(self.dataDir, 'settings.ini~') - settingsPath = os.path.join(self.dataDir, 'settings.ini') + settingsPath = self.settings.fileName() if os.path.exists(backupPath): os.remove(backupPath) os.rename(settingsPath, backupPath) - #os.remove(settingsPath) shutil.copyfile(projSettingsPath, settingsPath) self.settings.sync() From 2768084b30da136dcfcb0c4e2e4264ad66083e4e Mon Sep 17 00:00:00 2001 From: tassaron Date: Thu, 1 Jun 2017 20:31:15 -0400 Subject: [PATCH 7/7] resolution comboBox gets updated --- main.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index ba62c2c..8bbbf08 100644 --- a/main.py +++ b/main.py @@ -354,7 +354,7 @@ class Main(QtCore.QObject): if not os.path.exists(destination): os.makedirs(destination) for f in os.listdir(destination): - self.window.comboBox_openPreset.addItem(f) + self.window.comboBox_openPreset.addItem(f) def openSavePresetDialog(self): if self.window.listWidget_componentList.currentRow() == -1: @@ -476,6 +476,11 @@ class Main(QtCore.QObject): os.rename(settingsPath, backupPath) shutil.copyfile(projSettingsPath, settingsPath) self.settings.sync() + currentRes = str(self.settings.value('outputWidth'))+'x'+str(self.settings.value('outputHeight')) + for i in range(self.window.comboBox_resolution.count()-1): + if self.window.comboBox_resolution.itemText(i) == currentRes: + self.window.comboBox_resolution.setCurrentIndex(i) + break def showMessage(self, string, icon=QtGui.QMessageBox.Information, showCancel=False): msg = QtGui.QMessageBox()