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.

161 lines
5.6 KiB

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2022, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
Laborejo2 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")
#Third Party
from PyQt5 import QtCore, QtGui, QtWidgets
#Template Modules
#Our Modules
import engine.api as api
class TrackListWidget(QtWidgets.QWidget):
"""Small container wrapper for a title, checkboxes etc."""
def __init__(self, mainWindow, parentSplitter):
super().__init__(parentSplitter)
self.mainWindow = mainWindow
self.layout = QtWidgets.QVBoxLayout(self)
self.trackLabel = QtWidgets.QLabel("Hello")
self.showEverythingCheckBox = QtWidgets.QCheckBox(QtCore.QCoreApplication.translate("TrackListWidget", "Show Everything"))
self.showEverythingCheckBox.setChecked(True)
self.showEverythingCheckBox.toggled.connect(self.reactShowEverything)
self.realTrackListWidget = _TrackListWidget(mainWindow, self)
self.layout.addWidget(self.trackLabel)
self.layout.addWidget(self.showEverythingCheckBox)
self.layout.addWidget(self.realTrackListWidget, stretch=1)
api.callbacks.setCursor.append(self.setCursor)
def reactShowEverything(self, newState:bool):
self.realTrackListWidget.showEverything(newState)
def setCursor(self, c:dict):
self.trackLabel.setText( "<b>{}-{}</b>".format(c["trackIndex"]+1, c["trackName"]) )
class _TrackListWidget(QtWidgets.QListWidget):
"""The TrackListWidget holds all tracks as text-only variants with cursor access.
It will show one track at a time, the current one.
It is meant as alternative access for hard-to-reach items, such as zero-duration-items.
The cursor decides which track is currently handled as items.
But track content changes can come it for any track at any time.
In opposite to the ScoreScene we do not deal with deleted and hidden tracks.
We recreate the items on track change.
"""
def __init__(self, mainWindow, parentWidget):
super().__init__()
self.mainWindow = mainWindow
self._lastCurrentTrackId = None
self.tracks = {} # engineTrackId : engineExportData
self.itemPressed.connect(self._react_itemPressed)
self._showEverything = True
api.callbacks.tracksChanged.append(self.syncTracks)
api.callbacks.updateTrack.append(self.updateTrack)
api.callbacks.setCursor.append(self.setCursor)
def showEverything(self, state:bool):
"""Can be called externally to filter out the most common items.
The indexing and cursor will still work"""
self._showEverything = state
self.showTrack(self._lastCurrentTrackId)
def setCursor(self, cursorExportObject):
if not self._lastCurrentTrackId == cursorExportObject["trackId"]:
self._lastCurrentTrackId = cursorExportObject["trackId"]
self.showTrack(cursorExportObject["trackId"])
self.blockSignals(True)
self.setCurrentRow(cursorExportObject["position"])
self.blockSignals(False)
def _react_itemPressed(self, item):
"""This is gui->api cursor setting
It only happens when the mouse etc. actually pressed an item.
This list cannot be activated by cursor keys etc. directly.
"""
api.toPosition(self.currentRow()) #currentRow is calculated after we already are on the item.
def syncTracks(self, listOfStaticTrackRepresentations):
"""Handles the number of tracks and track meta-data changes,
but not track contents, which is handled by self.updateTrack through a different callback"""
for trackExportObject in listOfStaticTrackRepresentations:
if not trackExportObject["id"] in self.tracks:
self.tracks[trackExportObject["id"]] = None
def updateTrack(self, trackId, staticRepresentationList):
"""Callback: The content of a single track has changed"""
if not trackId in self.tracks:
#hidden track. But this can still happen through the data editor
return
self.tracks[trackId] = staticRepresentationList
if trackId == self._lastCurrentTrackId:
self.showTrack(trackId)
def showTrack(self, trackId):
"""Cursor moved to a different track.
This is essentially destroy-and-recreate in Qt """
self.clear()
staticRepresentationList = self.tracks[trackId]
count = 0
filterTypes = set(("Chord", "Rest"))
if self._showEverything:
for staticItem in staticRepresentationList:
self.addItem(staticItem["UIstring"])
else: #Hide Chords and Rests. The indexing and cursor will still work
for staticItem in staticRepresentationList:
item = QtWidgets.QListWidgetItem(staticItem["UIstring"])
self.addItem(item)
if staticItem["type"] in filterTypes:
item.setHidden(True)
self.addItem("|") #Appending