Music production session manager
https://www.laborejo.org
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
5.5 KiB
130 lines
5.5 KiB
#! /usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
|
|
|
|
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ).
|
|
|
|
This application is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
import logging; logger = logging.getLogger(__name__); logger.info("import")
|
|
|
|
#Standard Library
|
|
|
|
#Engine
|
|
import engine.api as api
|
|
|
|
#Third Party
|
|
from PyQt5 import QtCore, QtWidgets
|
|
|
|
class PromptWidget(QtWidgets.QDialog):
|
|
|
|
wordlist = None
|
|
minlen = None
|
|
|
|
def __init__(self, parent):
|
|
super().__init__(parent)
|
|
layout = QtWidgets.QFormLayout()
|
|
#layout = QtWidgets.QVBoxLayout()
|
|
|
|
updateWordlist() #this is a fast index update, we can call that every time to be sure. Otherwise newly added executable-PATHs will not be reflected in the dialog without a program-database update, which takes too long to be convenient.
|
|
|
|
self.setLayout(layout)
|
|
self.setWindowFlag(QtCore.Qt.Popup, True)
|
|
|
|
self.comboBox = QtWidgets.QComboBox(self)
|
|
self.comboBox.setEditable(True)
|
|
|
|
self.comboBox.currentTextChanged.connect(self.check) #not called when text is changed programatically
|
|
|
|
if PromptWidget.wordlist:
|
|
completer = QtWidgets.QCompleter(PromptWidget.wordlist)
|
|
completer.setModelSorting(QtWidgets.QCompleter.CaseInsensitivelySortedModel)
|
|
completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
|
completer.setCompletionMode(QtWidgets.QCompleter.PopupCompletion)
|
|
completer.activated.connect(self.process) #To avoid double-press enter to select one we hook into the activated signal and trigger process
|
|
self.comboBox.setCompleter(completer)
|
|
self.comboBox.setMinimumContentsLength(PromptWidget.minlen)
|
|
labelString = QtCore.QCoreApplication.translate("PromptWidget", "Type in the name of an executable file on your system.")
|
|
else:
|
|
labelString = QtCore.QCoreApplication.translate("PromptWidget", "No program database found. Please update through Control menu.")
|
|
|
|
label = QtWidgets.QLabel(labelString)
|
|
layout.addWidget(label)
|
|
self.comboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength)
|
|
|
|
layout.addWidget(self.comboBox)
|
|
|
|
errorString = QtCore.QCoreApplication.translate("PromptWidget", "Command not found or not accepted!<br>Parameters, --switches and relative paths are not allowed.<br>Use nsm-proxy or write a starter-script instead.")
|
|
errorString = "<i>" + errorString + "</i>"
|
|
self.errorLabel = QtWidgets.QLabel(errorString)
|
|
layout.addWidget(self.errorLabel)
|
|
self.errorLabel.hide() #shown in process or check
|
|
|
|
self.buttonBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
|
|
self.buttonBox.accepted.connect(self.process)
|
|
self.buttonBox.rejected.connect(self.reject)
|
|
layout.addWidget(self.buttonBox)
|
|
|
|
self.exec() #blocks until the dialog gets closed
|
|
|
|
def abortHandler(self):
|
|
pass
|
|
|
|
|
|
def check(self, currentText):
|
|
"""Called every keypress.
|
|
We do preliminary error and collision checking here, so the engine does not have to throw
|
|
an error """
|
|
self.errorLabel.hide() #start in good faith
|
|
ok = self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok)
|
|
if currentText in PromptWidget.wordlist: #this is taken literally. Any extra char or whitespace counts as false
|
|
ok.setEnabled(True)
|
|
else:
|
|
ok.setEnabled(False)
|
|
self.errorLabel.show()
|
|
|
|
|
|
def process(self):
|
|
"""Careful! Calling this eats python errors without notice.
|
|
Make sure your objects exists and your syntax is correct"""
|
|
assert PromptWidget.wordlist
|
|
assert PromptWidget.minlen
|
|
|
|
curText = self.comboBox.currentText()
|
|
if not curText or curText == " ": #TODO: qt weirdness. This is a case when focus is lost from a valid entry. The field is filled from a chosen value, from the list. But it says " ".
|
|
#Do not show the errorLabel. This is a qt bug or so.
|
|
return
|
|
|
|
if curText in PromptWidget.wordlist:
|
|
api.clientAdd(curText)
|
|
logger.info(f"Prompt accepted {curText} and will send it to clientAdd")
|
|
self.done(True)
|
|
else:
|
|
logger.info(f"Prompt did not accept {curText}.Showing info to the user.")
|
|
self.errorLabel.show()
|
|
|
|
|
|
def updateWordlist():
|
|
"""in case programs are installed while the session is running the user can
|
|
manually call a database update"""
|
|
PromptWidget.wordlist = api.getUnfilteredExecutables()
|
|
if PromptWidget.wordlist:
|
|
PromptWidget.minlen = len(max(PromptWidget.wordlist, key=len))
|
|
else:
|
|
logger.error("Executable list came back empty! Most likely an error in application database build. Not trivial!")
|
|
|
|
def askForExecutable(parent):
|
|
PromptWidget(parent)
|
|
|