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.
167 lines
6.2 KiB
167 lines
6.2 KiB
![]()
2 years ago
|
#! /usr/bin/env python3
|
||
|
# -*- coding: utf-8 -*-
|
||
|
"""
|
||
|
Copyright 2021, 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
|
||
|
|
||
|
#Third Party
|
||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||
|
|
||
|
#Our Qt
|
||
|
|
||
|
#Engine
|
||
|
import engine.api as api
|
||
|
|
||
|
|
||
|
|
||
|
class SelectedInstrumentController(object):
|
||
|
"""Not a qt class. We externally control a collection of widgets.
|
||
|
There is only one set of widgets. We change their contents dynamically.
|
||
|
"""
|
||
|
|
||
|
def __init__(self, parentMainWindow):
|
||
|
self.parentMainWindow = parentMainWindow
|
||
|
self.currentIdKey = None
|
||
|
self.engineData = {} # id-key tuple : engine library metadata dict.
|
||
|
self.statusUpdates = {} # same as engineData, but with incremental status updates. One is guranteed to exist at startup
|
||
|
|
||
|
#Our Widgets
|
||
|
self.ui = parentMainWindow.ui
|
||
|
self.ui.details_groupBox.setTitle("")
|
||
|
self.ui.details_scrollArea.hide() #until the first instrument was selected
|
||
|
|
||
|
self.ui.variants_comboBox.activated.connect(self._newVariantChosen)
|
||
|
|
||
|
|
||
|
#Callbacks
|
||
|
api.callbacks.instrumentListMetadata.append(self.react_initialInstrumentList)
|
||
|
api.callbacks.instrumentStatusChanged.append(self.react_instrumentStatusChanged)
|
||
|
|
||
|
|
||
|
|
||
|
def directLibrary(self, idkey:tuple):
|
||
|
"""User clicked on a library treeItem"""
|
||
|
libraryId, instrumentId = idkey
|
||
|
self.currentIdKey = None
|
||
|
self.ui.details_scrollArea.show()
|
||
|
self.ui.variants_comboBox.hide()
|
||
|
self.ui.variant_label.hide()
|
||
|
|
||
|
metadata = self.engineData[libraryId]["library"]
|
||
|
|
||
|
self.ui.details_groupBox.setTitle(metadata["name"])
|
||
|
|
||
|
|
||
|
self.ui.info_label.setText(self._metadataToDescriptionLabel(metadata))
|
||
|
|
||
|
def _metadataToDescriptionLabel(self, metadata:dict)->str:
|
||
|
"""Can work with instruments and libraries alike"""
|
||
|
|
||
|
if "variants" in metadata: #this is an instrument
|
||
|
fullText = metadata["description"] + "\n\nVendor: " + metadata["vendor"] + "\n\nLicense: " + metadata["license"]
|
||
|
else:
|
||
|
fullText = metadata["description"] + "\n\nVendor: " + metadata["vendor"]
|
||
|
return fullText
|
||
|
|
||
|
def _newVariantChosen(self, index:int):
|
||
|
"""User chose a new variant through the combo box"""
|
||
|
assert self.ui.variants_comboBox.currentIndex() == index
|
||
|
assert self.currentIdKey
|
||
|
api.chooseVariantByIndex(self.currentIdKey, index)
|
||
|
|
||
|
def instrumentChanged(self, idkey:tuple):
|
||
|
"""This is a GUI-internal function. The user selected a different instrument from
|
||
|
the list. Single click, arrow keys etc.
|
||
|
|
||
|
We combine static metadata, which we saved ourselves, with the current instrument status
|
||
|
(e.g. which variant was chosen).
|
||
|
"""
|
||
|
libraryId, instrumentId = idkey
|
||
|
self.currentIdKey = idkey
|
||
|
|
||
|
self.ui.details_scrollArea.show()
|
||
|
|
||
|
#Static
|
||
|
instrumentData = self.engineData[libraryId][instrumentId]
|
||
|
self.ui.details_groupBox.setTitle(instrumentData["name"])
|
||
|
|
||
|
self.ui.variant_label.show()
|
||
|
self.ui.variants_comboBox.show()
|
||
|
self.ui.variants_comboBox.clear()
|
||
|
self.ui.variants_comboBox.addItems(instrumentData["variantsWithoutSfzExtension"])
|
||
|
|
||
|
self.ui.info_label.setText(self._metadataToDescriptionLabel(instrumentData))
|
||
|
|
||
|
#Dynamic
|
||
|
self.react_instrumentStatusChanged(self.statusUpdates[libraryId][instrumentId])
|
||
|
|
||
|
|
||
|
def react_instrumentStatusChanged(self, instrumentStatus:dict):
|
||
|
"""Callback from the api. Has nothing to do with any GUI state or selection.
|
||
|
Data:
|
||
|
#Static ids
|
||
|
result["id"] = self.metadata["id"]
|
||
|
result["id-key"] = self.idKey #redundancy for convenience.
|
||
|
|
||
|
#Dynamic data
|
||
|
result["currentVariant"] = self.currentVariant # str
|
||
|
result["state"] = self.enabled #bool
|
||
|
"""
|
||
|
idkey = instrumentStatus["id-key"]
|
||
|
libraryId, instrumentId = idkey
|
||
|
|
||
|
if not libraryId in self.statusUpdates:
|
||
|
self.statusUpdates[libraryId] = {} #empty library. status dict
|
||
|
self.statusUpdates[libraryId][instrumentId] = instrumentStatus #create or overwrite / keep up to date
|
||
|
|
||
|
loadState = instrumentStatus["state"]
|
||
|
|
||
|
instrumentData = self.engineData[libraryId][instrumentId]
|
||
|
instrumentStatus = self.statusUpdates[libraryId][instrumentId]
|
||
|
if loadState: #None if not loaded
|
||
|
self.ui.variants_comboBox.setEnabled(True)
|
||
|
currentVariantIndex = instrumentData["variantsWithoutSfzExtension"].index(instrumentStatus["currentVariantWithoutSfzExtension"])
|
||
|
self.ui.variants_comboBox.setCurrentIndex(currentVariantIndex)
|
||
|
else:
|
||
|
self.ui.variants_comboBox.setEnabled(False)
|
||
|
defaultVariantIndex = instrumentData["variantsWithoutSfzExtension"].index(instrumentData["defaultVariantWithoutSfzExtension"])
|
||
|
self.ui.variants_comboBox.setCurrentIndex(defaultVariantIndex)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
def react_initialInstrumentList(self, data:dict):
|
||
|
"""For data form see docstring of instrument.py buildTree()
|
||
|
Summary:
|
||
|
libraryid : dict ->
|
||
|
instrumentid : metadatadict
|
||
|
|
||
|
Dict-Keys are always the same. Some always have data, some can be empty.
|
||
|
|
||
|
We receive this once at program start and build our permanent GUI widgets from it.
|
||
|
The additional status update callback for dynamic data is handled in
|
||
|
self.react_instrumentStatusChanged
|
||
|
"""
|
||
|
self.engineData = data
|
||
|
|
||
|
|