Browse Source

Favorite instruments

master
Nils 7 months ago
parent
commit
6d2acbe95f
  1. 7
      engine/config.py
  2. 4
      qtgui/chooseDownloadDirectory.py
  3. 65
      qtgui/designer/mainwindow.py
  4. 165
      qtgui/designer/mainwindow.ui
  5. 73
      qtgui/favorites.py
  6. 4
      qtgui/instrument.py
  7. 21
      qtgui/mainwindow.py

7
engine/config.py

@ -58,11 +58,8 @@ numbering system, midi controls etc.
Only "soft" settings, such as filters, can be changed dynamically and will be saved in your project.
At the moment this software is in its ALPHA phase. You need to manually download instrument
files from https://laborejo.org/downloads/tembro-instruments/ . Do not unpack the .tar files!
Download them to a location of your choice set the sample file location from within Tembros Edit
menu. Then restart the program.
""",
At the moment this software is in its ALPHA phase which means that samples libraries will still
change.""",
"dependencies" : "\n".join("* "+dep for dep in ()),
}

4
qtgui/chooseDownloadDirectory.py

@ -222,8 +222,9 @@ class ChooseDownloadDirectory(QtWidgets.QDialog):
self.parentMainWindow.qtApp.processEvents()
indexUrl = "https://www.laborejo.org/downloads/tembro-instruments/downloadindex.json"
indexUrl = "http://0.0.0.0:8000/downloadindex.json"
#indexUrl = "https://download.linuxaudio.org/musical-instrument-libraries/tembro/"
indexDL = SmartDL(indexUrl, progress_bar=False) # Because we didn't pass a destination path to the constructor, temporary path was chosen.
try:
@ -280,7 +281,6 @@ class ChooseDownloadDirectory(QtWidgets.QDialog):
logger.info(f"Downloading {entry['name']}")
obj = SmartDL(urlMirrorList, self.ui.pathComboBox.currentText(), progress_bar=False)
self.currentSmartDL = obj
#With Hash Verification it will not only test the download but also don't double-download an existing file.

65
qtgui/designer/mainwindow.py

@ -35,6 +35,36 @@ class Ui_MainWindow(object):
self.verticalLayout = QtWidgets.QVBoxLayout(self.rightFrame)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.auditionerWidget = QtWidgets.QWidget(self.rightFrame)
self.auditionerWidget.setObjectName("auditionerWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.auditionerWidget)
self.horizontalLayout.setContentsMargins(9, 9, -1, 9)
self.horizontalLayout.setObjectName("horizontalLayout")
self.auditionerVolumeDial = QtWidgets.QDial(self.auditionerWidget)
self.auditionerVolumeDial.setMaximumSize(QtCore.QSize(32, 32))
self.auditionerVolumeDial.setSizeIncrement(QtCore.QSize(3, 0))
self.auditionerVolumeDial.setMinimum(-40)
self.auditionerVolumeDial.setMaximum(0)
self.auditionerVolumeDial.setPageStep(3)
self.auditionerVolumeDial.setProperty("value", -3)
self.auditionerVolumeDial.setWrapping(False)
self.auditionerVolumeDial.setNotchTarget(3.0)
self.auditionerVolumeDial.setNotchesVisible(True)
self.auditionerVolumeDial.setObjectName("auditionerVolumeDial")
self.horizontalLayout.addWidget(self.auditionerVolumeDial)
self.label = QtWidgets.QLabel(self.auditionerWidget)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.auditionerMidiInputComboBox = QtWidgets.QComboBox(self.auditionerWidget)
self.auditionerMidiInputComboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
self.auditionerMidiInputComboBox.setObjectName("auditionerMidiInputComboBox")
self.horizontalLayout.addWidget(self.auditionerMidiInputComboBox)
self.auditionerCurrentInstrument_label = QtWidgets.QLabel(self.auditionerWidget)
self.auditionerCurrentInstrument_label.setObjectName("auditionerCurrentInstrument_label")
self.horizontalLayout.addWidget(self.auditionerCurrentInstrument_label)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.verticalLayout.addWidget(self.auditionerWidget)
self.splitter = QtWidgets.QSplitter(self.rightFrame)
self.splitter.setOrientation(QtCore.Qt.Vertical)
self.splitter.setObjectName("splitter")
@ -77,7 +107,7 @@ class Ui_MainWindow(object):
self.details_scrollArea.setWidgetResizable(True)
self.details_scrollArea.setObjectName("details_scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 993, 106))
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 993, 125))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.formLayout = QtWidgets.QFormLayout(self.scrollAreaWidgetContents)
self.formLayout.setObjectName("formLayout")
@ -101,35 +131,6 @@ class Ui_MainWindow(object):
self.details_scrollArea.setWidget(self.scrollAreaWidgetContents)
self.verticalLayout_3.addWidget(self.details_scrollArea)
self.verticalLayout.addWidget(self.splitter)
self.auditionerWidget = QtWidgets.QWidget(self.rightFrame)
self.auditionerWidget.setObjectName("auditionerWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.auditionerWidget)
self.horizontalLayout.setObjectName("horizontalLayout")
self.auditionerVolumeDial = QtWidgets.QDial(self.auditionerWidget)
self.auditionerVolumeDial.setMaximumSize(QtCore.QSize(32, 32))
self.auditionerVolumeDial.setSizeIncrement(QtCore.QSize(3, 0))
self.auditionerVolumeDial.setMinimum(-40)
self.auditionerVolumeDial.setMaximum(0)
self.auditionerVolumeDial.setPageStep(3)
self.auditionerVolumeDial.setProperty("value", -3)
self.auditionerVolumeDial.setWrapping(False)
self.auditionerVolumeDial.setNotchTarget(3.0)
self.auditionerVolumeDial.setNotchesVisible(True)
self.auditionerVolumeDial.setObjectName("auditionerVolumeDial")
self.horizontalLayout.addWidget(self.auditionerVolumeDial)
self.label = QtWidgets.QLabel(self.auditionerWidget)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.auditionerMidiInputComboBox = QtWidgets.QComboBox(self.auditionerWidget)
self.auditionerMidiInputComboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
self.auditionerMidiInputComboBox.setObjectName("auditionerMidiInputComboBox")
self.horizontalLayout.addWidget(self.auditionerMidiInputComboBox)
self.auditionerCurrentInstrument_label = QtWidgets.QLabel(self.auditionerWidget)
self.auditionerCurrentInstrument_label.setObjectName("auditionerCurrentInstrument_label")
self.horizontalLayout.addWidget(self.auditionerCurrentInstrument_label)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.verticalLayout.addWidget(self.auditionerWidget)
self.horizontalPianoFrame = QtWidgets.QFrame(self.rightFrame)
self.horizontalPianoFrame.setMinimumSize(QtCore.QSize(0, 100))
self.horizontalPianoFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
@ -155,6 +156,8 @@ class Ui_MainWindow(object):
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "Auditioner MIDI Input"))
self.auditionerCurrentInstrument_label.setText(_translate("MainWindow", "TextLabel"))
self.instruments_treeWidget.headerItem().setText(1, _translate("MainWindow", "ID"))
self.instruments_treeWidget.headerItem().setText(2, _translate("MainWindow", "Volume"))
self.instruments_treeWidget.headerItem().setText(3, _translate("MainWindow", "Name"))
@ -171,5 +174,3 @@ class Ui_MainWindow(object):
self.variant_label.setText(_translate("MainWindow", "Variants"))
self.info_label.setText(_translate("MainWindow", "TextLabel"))
self.keySwitch_label.setText(_translate("MainWindow", "KeySwitch"))
self.label.setText(_translate("MainWindow", "Auditioner MIDI Input"))
self.auditionerCurrentInstrument_label.setText(_translate("MainWindow", "TextLabel"))

165
qtgui/designer/mainwindow.ui

@ -69,6 +69,92 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="auditionerWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QDial" name="auditionerVolumeDial">
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>3</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>-40</number>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="pageStep">
<number>3</number>
</property>
<property name="value">
<number>-3</number>
</property>
<property name="wrapping">
<bool>false</bool>
</property>
<property name="notchTarget">
<double>3.000000000000000</double>
</property>
<property name="notchesVisible">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Auditioner MIDI Input</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="auditionerMidiInputComboBox">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="auditionerCurrentInstrument_label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
@ -243,7 +329,7 @@
<x>0</x>
<y>0</y>
<width>993</width>
<height>106</height>
<height>125</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
@ -288,83 +374,6 @@
</widget>
</widget>
</item>
<item>
<widget class="QWidget" name="auditionerWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QDial" name="auditionerVolumeDial">
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>3</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>-40</number>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="pageStep">
<number>3</number>
</property>
<property name="value">
<number>-3</number>
</property>
<property name="wrapping">
<bool>false</bool>
</property>
<property name="notchTarget">
<double>3.000000000000000</double>
</property>
<property name="notchesVisible">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Auditioner MIDI Input</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="auditionerMidiInputComboBox">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="auditionerCurrentInstrument_label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="horizontalPianoFrame">
<property name="minimumSize">

73
qtgui/favorites.py

@ -22,26 +22,81 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging; logger = logging.getLogger(__name__); logger.info("import")
#Standard Library
from collections import Counter
#Third Party
from PyQt5 import QtCore, QtGui, QtWidgets
#Our Qt
from .instrument import InstrumentTreeController
from .instrument import InstrumentTreeController, GuiLibrary, GuiInstrument
#Engine
from engine.config import * #imports METADATA
import engine.api as api
class FavoritesTreeController(InstrumentTreeController):
pass
fakeLibMostUsed = {}
fakeLibMostUsed["tarFilePath"] = ""
fakeLibMostUsed["id"] = 0 #If this is selected in the GUI it will select the default lib in the main instrument view, which is wrong but safe.
fakeLibMostUsed["name"] = QtCore.QCoreApplication.translate("Favorites", "Top 10 - Most Used")
fakeLibMostUsed["description"] = ""
fakeLibMostUsed["license"] = ""
fakeLibMostUsed["vendor"] = ""
fakeLibMostUsed["version"] = "1"
#Most Loaded
#Most Recent
#Manuelle Favoriten?
class FavoritesTreeController(InstrumentTreeController):
#Selection an den anderen weitergeben.+++++
def buildTree(self, data:dict):
"""
Only shows some of the instruments,
depending on the current filter-mode
"""
#Reset everything except our cached data.
self.treeWidget.clear() #will delete the C++ objects. We need to delete the PyQt objects ourselves, like so:
self.guiLibraries = {} # idKey : GuiLibrary idKey is a tuple with second value -1, which would be the instrument.
self.guiInstruments = {} # idKey : GuiInstrument
if data:
self._cachedData = data
else:
assert self._cachedData
data = self._cachedData
#Add all available instruments to the database, but don't use them yet
for libraryId, libraryDict in data.items():
for instrumentdId, instrumentDict in libraryDict.items():
if instrumentdId == "library":
continue
gi = GuiInstrument(parentTreeController=self, instrumentDict=instrumentDict)
self.guiInstruments[instrumentDict["idKey"]] = gi
if instrumentDict["idKey"] in self._cachedLastInstrumentStatus:
gi.updateStatus(self._cachedLastInstrumentStatus[instrumentDict["idKey"]])
mostUsed = GuiLibrary(parentTreeController=self, libraryDict=fakeLibMostUsed)
self.treeWidget.addTopLevelItem(mostUsed)
mostUsed.setExpanded(True)
#mostRecent = GuiLibrary(parentTreeController=self, libraryDict=libraryDict["library"])
top10 = self.getTop10FavoriteInstruments() # Return an ordered list of double tuple ((libid, instid), counter)
for placement, ((libId, instId), counter) in enumerate(top10):
gi = self.guiInstruments[(libId, instId)]
mostUsed.addChild(gi)
gi.injectWidgets() #only possible after gi.init() was done and item inserted.
#Misuse the id as top 10-Counter
gi.setData(gi.columns.index("idKey"), 0, str(placement+1).zfill(2)) #0 is the data role, just standard display text. We combine both IDs to a float number for sorting. If used with setData instead of setText Qt will know how to sort 11 before 1000
self._adjustColumnSize()
def getTop10FavoriteInstruments(self)->list:
"""Return an ordered list of double tuple ((libid, instid), counter)"""
settings = QtCore.QSettings("LaborejoSoftwareSuite", METADATA["shortName"])
if settings.contains("favoriteInstruments"):
database = settings.value("favoriteInstruments", type=dict)
return Counter(database).most_common(10) #python already knows how to create that
else:
return []

4
qtgui/instrument.py

@ -417,11 +417,7 @@ class GuiInstrument(QtWidgets.QTreeWidgetItem):
for the details view.
"""
allItems = {} # instrId : GuiInstrument
def __init__(self, parentTreeController, instrumentDict):
GuiInstrument.allItems[instrumentDict["idKey"]] = self
self.parentTreeController = parentTreeController
self.idKey = instrumentDict["idKey"]

21
qtgui/mainwindow.py

@ -23,7 +23,7 @@ import logging; logging.info("import {}".format(__file__))
#Standard Library Modules
import pathlib
import os
from collections import Counter
#Third Party Modules
from PyQt5 import QtWidgets, QtCore, QtGui
@ -180,6 +180,10 @@ class MainWindow(TemplateMainWindow):
self.menu.addMenuEntry("menuEdit", "actionSampleDirPathDialog", "Sample Files Location", lambda: ChooseDownloadDirectory(parentMainWindow=self))
self.menu.addMenuEntry("menuEdit", "actionLoadSamples", QtCore.QCoreApplication.translate("Menu", "Load all Instrument Samples (slow!)"), api.loadAllInstrumentSamples)
self.menu.addMenuEntry("menuEdit", "actionUnloadSamples", QtCore.QCoreApplication.translate("Menu", "Unload all Instrument Samples (also slow.)"), api.unloadAllInstrumentSamples)
self.menu.addSeparator("menuEdit")
self.menu.addMenuEntry("menuEdit", "actionResetFavoriteInstrumentDatabase", QtCore.QCoreApplication.translate("Menu", "Reset favorite instrument list"), self.resetFavoriteInstrumentDatabase)
#self.menu.connectMenuEntry("actionNils", lambda: print("Override"))
self.menu.addSubmenu("menuView", QtCore.QCoreApplication.translate("Menu", "View"))
@ -287,7 +291,7 @@ class MainWindow(TemplateMainWindow):
def favoriteInstrument(self, idKey:tuple):
"""Count the user-instructed, explicit loading of an instrument in the permanent database.
We work directly with the qt settings without local data. A crash or sigkill will not
prevent the counting."""
reset the counting."""
settings = QtCore.QSettings("LaborejoSoftwareSuite", METADATA["shortName"])
if settings.contains("favoriteInstruments"):
database = settings.value("favoriteInstruments", type=dict)
@ -302,17 +306,12 @@ class MainWindow(TemplateMainWindow):
settings.setValue("favoriteInstruments", database)
self.favoritesTreeController.buildTree(data=None) #rebuild from cache
def resetFavoriteInstrumentDatabase(self):
settings = QtCore.QSettings("LaborejoSoftwareSuite", METADATA["shortName"])
if settings.contains("favoriteInstruments"):
settings.remove("favoriteInstruments")
self.favoriteInstrumentsThisRun = set()
def getTop10FavoriteInstruments(self)->list:
"""Return an ordered list of double tuple ((libid, instid), counter) """
settings = QtCore.QSettings("LaborejoSoftwareSuite", METADATA["shortName"])
if settings.contains("favoriteInstruments"):
database = settings.value("favoriteInstruments", type=dict)
return Counter(database).most_common(10) #python already knows how to create that
else:
return []
self.favoritesTreeController.buildTree(data=None) #rebuild from cache

Loading…
Cancel
Save