-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Showing
10 changed files
with
516 additions
and
1 deletion.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
|
||
import os | ||
from PyQt5 import QtWidgets, QtCore, QtGui, uic | ||
from widgets import widgets | ||
|
||
|
||
class EffectTableModel(QtCore.QAbstractTableModel): | ||
_signalEffectsUpdate = QtCore.pyqtSignal() | ||
|
||
def __init__(self, parent = None): | ||
super().__init__(parent) | ||
self.pipActiveEffects = None | ||
self.sortColumn = 0 | ||
self.sortReversed = False | ||
self.effectList = [] | ||
self.showPermanent = False | ||
self.showEmptySources = False | ||
self.showInactive = False | ||
self._signalEffectsUpdate.connect(self._slotEffectsUpdate) | ||
|
||
@QtCore.pyqtSlot(bool) | ||
def setShowPermanent(self, value, signal = True): | ||
self.showPermanent = value | ||
if signal: | ||
self._signalEffectsUpdate.emit() | ||
|
||
@QtCore.pyqtSlot(bool) | ||
def setShowEmptySources(self, value, signal = True): | ||
self.showEmptySources = value | ||
if signal: | ||
self._signalEffectsUpdate.emit() | ||
|
||
@QtCore.pyqtSlot(bool) | ||
def setShowInactive(self, value, signal = True): | ||
self.showInactive = value | ||
if signal: | ||
self._signalEffectsUpdate.emit() | ||
|
||
def setPipActiveEffects(self, pipValue): | ||
self.modelAboutToBeReset.emit() | ||
self.pipActiveEffects = pipValue | ||
self._createEffectList() | ||
self._sortEffectList() | ||
self.modelReset.emit() | ||
self.pipActiveEffects.registerValueUpdatedListener(self._onPipEffectsUpdate, 99) | ||
|
||
def _onPipEffectsUpdate(self, caller, value, pathObjs): | ||
self._signalEffectsUpdate.emit() | ||
|
||
@QtCore.pyqtSlot() | ||
def _slotEffectsUpdate(self): | ||
self.layoutAboutToBeChanged.emit() | ||
self._createEffectList() | ||
self._sortEffectList() | ||
self.layoutChanged.emit() | ||
|
||
def _createEffectList(self): | ||
self.effectList = [] | ||
for s in self.pipActiveEffects.value(): | ||
for e in s.child('Effects').value(): | ||
if (self.showPermanent or self._data(e, 2) > 0.0) and (self.showEmptySources or self._data(e, 1)) and (self.showInactive or self._data(e, 7)): | ||
self.effectList.append(e) | ||
|
||
|
||
def _sortEffectList(self): | ||
def _sortKey(pipValue): | ||
return self._data(pipValue, self.sortColumn) | ||
self.effectList.sort(key=_sortKey, reverse=self.sortReversed) | ||
|
||
def rowCount(self, parent = QtCore.QModelIndex()): | ||
return len(self.effectList) | ||
|
||
def columnCount(self, parent = QtCore.QModelIndex()): | ||
return 8 | ||
|
||
def headerData(self, section, orientation, role = QtCore.Qt.DisplayRole): | ||
if orientation == QtCore.Qt.Horizontal: | ||
if role == QtCore.Qt.DisplayRole: | ||
if section == 0: | ||
return 'Name' | ||
elif section == 1: | ||
return 'Source' | ||
elif section == 2: | ||
return 'Duration' | ||
elif section == 3: | ||
return 'Value' | ||
elif section == 4: | ||
return 'Type' | ||
elif section == 5: | ||
return 'pipID' | ||
elif section == 6: | ||
return 'showAsPercent' | ||
elif section == 7: | ||
return 'IsActive' | ||
return None | ||
|
||
def data(self, index, role = QtCore.Qt.DisplayRole): | ||
effect = self.effectList[index.row()] | ||
return self._data(effect, index.column(), role) | ||
|
||
def _data(self, effect, column, role = QtCore.Qt.DisplayRole): | ||
if role == QtCore.Qt.DisplayRole: | ||
if column == 0: | ||
customDesc = effect.child('CustomDesc') | ||
if customDesc and customDesc.value(): | ||
return effect.child('Name').value() | ||
else: | ||
text = effect.child('Name').value() | ||
value = effect.child('Value').value() | ||
if value > 0: | ||
text += ' +' + str(value) | ||
elif value < 0: | ||
text += ' ' + str(value) | ||
return text | ||
elif column == 1: | ||
# Immediate parent is the enclosing array, therefore we need parent.parent | ||
return effect.pipParent.pipParent.child('Source').value() | ||
elif column == 2: | ||
duration = effect.child('duration') | ||
if duration: | ||
return duration.value() | ||
return 0.0 | ||
elif column == 3: | ||
value = effect.child('Value') | ||
if value: | ||
return value.value() | ||
return 0.0 | ||
elif column == 4: | ||
# Immediate parent is the enclosing array, therefore we need parent.parent | ||
return str(effect.pipParent.pipParent.child('type').value()) | ||
elif column == 5: | ||
# Immediate parent is the enclosing array, therefore we need parent.parent | ||
return effect.pipId | ||
elif column == 6: | ||
sap = effect.child('showAsPercent') | ||
if sap: | ||
return sap.value() | ||
return False | ||
elif column == 7: | ||
return effect.child('IsActive').value() | ||
elif role == QtCore.Qt.FontRole: | ||
if effect.child('IsActive').value(): | ||
font = QtGui.QFont() | ||
font.setBold(True) | ||
return font | ||
#elif role == QtCore.Qt.ForegroundRole: | ||
# if not effect.child('IsActive').value(): | ||
# return QtGui.QColor.fromRgb(150,150,150) | ||
return None | ||
|
||
def sort(self, column, order = QtCore.Qt.AscendingOrder): | ||
self.layoutAboutToBeChanged.emit() | ||
self.sortColumn = column | ||
if order == QtCore.Qt.DescendingOrder: | ||
self.sortReversed = True | ||
else: | ||
self.sortReversed = False | ||
self._sortEffectList() | ||
self.layoutChanged.emit() | ||
|
||
def getPipValue(self, row): | ||
if self.effectList and len(self.effectList) > row: | ||
return self.effectList[row] | ||
else: | ||
return None | ||
|
||
|
||
|
||
|
||
class EffectWidget(widgets.WidgetBase): | ||
|
||
def __init__(self, mhandle, parent): | ||
super().__init__('Effects', parent) | ||
self.widget = uic.loadUi(os.path.join(mhandle.basepath, 'ui', 'effectwidget.ui')) | ||
self.setWidget(self.widget) | ||
|
||
def init(self, app, datamanager): | ||
super().init(app, datamanager) | ||
self.effectsViewModel = EffectTableModel() | ||
self.widget.effectsView.setModel(self.effectsViewModel) | ||
self.widget.effectsView.setColumnWidth(0, 300) | ||
self.widget.showPermanentCheckBox.stateChanged.connect(self.effectsViewModel.setShowPermanent) | ||
self.widget.showEmptySourcesCheckBox.stateChanged.connect(self.effectsViewModel.setShowEmptySources) | ||
self.widget.showInactiveCheckBox.stateChanged.connect(self.effectsViewModel.setShowInactive) | ||
self.dataManager = datamanager | ||
self.dataManager.registerRootObjectListener(self._onPipRootObjectEvent) | ||
|
||
|
||
def _onPipRootObjectEvent(self, rootObject): | ||
self.pipStats = rootObject.child('Stats') | ||
if self.pipStats: | ||
self.pipStats.registerValueUpdatedListener(self._onPipStatsUpdated) | ||
self.pipActiveEffects = self.pipStats.child('ActiveEffects') | ||
if self.pipActiveEffects: | ||
self.effectsViewModel.setPipActiveEffects(self.pipActiveEffects) | ||
|
||
def _onPipStatsUpdated(self, caller, value, pathObjs): | ||
self.pipActiveEffects = self.pipStats.child('ActiveEffects') | ||
if self.pipActiveEffects: | ||
self.effectsViewModel.setPipActiveEffects(self.pipActiveEffects) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
|
||
from widgets import widgets | ||
|
||
from .effectswidget import EffectWidget | ||
|
||
class ModuleInfo(widgets.ModuleInfoBase): | ||
|
||
LABEL = 'effects' | ||
NAME = 'Effects' | ||
|
||
@staticmethod | ||
def createWidgets(handle, parent): | ||
return EffectWidget(handle, parent) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ui version="4.0"> | ||
<class>Form</class> | ||
<widget class="QWidget" name="Form"> | ||
<property name="geometry"> | ||
<rect> | ||
<x>0</x> | ||
<y>0</y> | ||
<width>516</width> | ||
<height>300</height> | ||
</rect> | ||
</property> | ||
<property name="windowTitle"> | ||
<string>Form</string> | ||
</property> | ||
<layout class="QVBoxLayout" name="verticalLayout_2"> | ||
<item> | ||
<widget class="QSplitter" name="splitter"> | ||
<property name="orientation"> | ||
<enum>Qt::Horizontal</enum> | ||
</property> | ||
<widget class="QTableView" name="effectsView"> | ||
<property name="alternatingRowColors"> | ||
<bool>true</bool> | ||
</property> | ||
<property name="selectionMode"> | ||
<enum>QAbstractItemView::SingleSelection</enum> | ||
</property> | ||
<property name="selectionBehavior"> | ||
<enum>QAbstractItemView::SelectRows</enum> | ||
</property> | ||
<property name="sortingEnabled"> | ||
<bool>true</bool> | ||
</property> | ||
</widget> | ||
<widget class="QWidget" name="widget" native="true"> | ||
<layout class="QVBoxLayout" name="verticalLayout"> | ||
<item> | ||
<widget class="QCheckBox" name="showPermanentCheckBox"> | ||
<property name="text"> | ||
<string>Show Permanent Effects</string> | ||
</property> | ||
</widget> | ||
</item> | ||
<item> | ||
<widget class="QCheckBox" name="showEmptySourcesCheckBox"> | ||
<property name="text"> | ||
<string>Show Empty Sources</string> | ||
</property> | ||
</widget> | ||
</item> | ||
<item> | ||
<widget class="QCheckBox" name="showInactiveCheckBox"> | ||
<property name="text"> | ||
<string>Show Inactive</string> | ||
</property> | ||
</widget> | ||
</item> | ||
<item> | ||
<spacer name="verticalSpacer"> | ||
<property name="orientation"> | ||
<enum>Qt::Vertical</enum> | ||
</property> | ||
<property name="sizeHint" stdset="0"> | ||
<size> | ||
<width>20</width> | ||
<height>40</height> | ||
</size> | ||
</property> | ||
</spacer> | ||
</item> | ||
</layout> | ||
</widget> | ||
</widget> | ||
</item> | ||
</layout> | ||
</widget> | ||
<resources/> | ||
<connections/> | ||
</ui> |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
|
||
from widgets import widgets | ||
|
||
from .radiowidget import EffectWidget | ||
|
||
class ModuleInfo(widgets.ModuleInfoBase): | ||
|
||
LABEL = 'radio' | ||
NAME = 'Radio' | ||
|
||
@staticmethod | ||
def createWidgets(handle, parent): | ||
return EffectWidget(handle, parent) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
|
||
import os | ||
from PyQt5 import QtWidgets, QtCore, QtGui, uic | ||
from widgets import widgets | ||
|
||
|
||
class EffectTableModel(QtCore.QAbstractTableModel): | ||
_signalEffectsUpdate = QtCore.pyqtSignal() | ||
|
||
def __init__(self, parent = None): | ||
super().__init__(parent) | ||
self.pipRadio = None | ||
self.sortColumn = 0 | ||
self.sortReversed = False | ||
self.itemList = [] | ||
self._signalEffectsUpdate.connect(self._slotRadioUpdate) | ||
|
||
def setPipRadio(self, pipValue): | ||
self.modelAboutToBeReset.emit() | ||
self.pipRadio = pipValue | ||
self.itemList = self.pipRadio.value() | ||
self._sortItemList() | ||
self.modelReset.emit() | ||
self.pipRadio.registerValueUpdatedListener(self._onPipRadioUpdate, 2) | ||
|
||
def _onPipRadioUpdate(self, caller, value, pathObjs): | ||
self._signalEffectsUpdate.emit() | ||
|
||
@QtCore.pyqtSlot() | ||
def _slotRadioUpdate(self): | ||
self.layoutAboutToBeChanged.emit() | ||
self.itemList = self.pipRadio.value() | ||
self._sortItemList() | ||
self.layoutChanged.emit() | ||
|
||
|
||
def _sortItemList(self): | ||
def _sortKey(pipValue): | ||
if self.sortColumn == 0: | ||
return pipValue.child('text').value() | ||
elif self.sortColumn == 1: | ||
return pipValue.child('frequency').value() | ||
elif self.sortColumn == 2: | ||
return pipValue.child('inRange').value() | ||
self.itemList.sort(key=_sortKey, reverse=self.sortReversed) | ||
|
||
|
||
def rowCount(self, parent = QtCore.QModelIndex()): | ||
if self.pipRadio: | ||
return self.pipRadio.childCount() | ||
else: | ||
return 0 | ||
|
||
def columnCount(self, parent = QtCore.QModelIndex()): | ||
return 3 | ||
|
||
def headerData(self, section, orientation, role = QtCore.Qt.DisplayRole): | ||
if orientation == QtCore.Qt.Horizontal: | ||
if role == QtCore.Qt.DisplayRole: | ||
if section == 0: | ||
return 'Name' | ||
elif section == 1: | ||
return 'Frequency' | ||
elif section == 2: | ||
return 'In Range' | ||
return None | ||
|
||
def data(self, index, role = QtCore.Qt.DisplayRole): | ||
if role == QtCore.Qt.DisplayRole: | ||
radio = self.itemList[index.row()] | ||
if index.column() == 0: | ||
return radio.child('text').value() | ||
elif index.column() == 1: | ||
return radio.child('frequency').value() | ||
elif index.column() == 2: | ||
return radio.child('inRange').value() | ||
elif role == QtCore.Qt.FontRole: | ||
radio = self.itemList[index.row()] | ||
if radio.child('active').value(): | ||
font = QtGui.QFont() | ||
font.setBold(True) | ||
return font | ||
elif role == QtCore.Qt.ForegroundRole: | ||
radio = self.itemList[index.row()] | ||
if not radio.child('inRange').value(): | ||
return QtGui.QColor.fromRgb(150,150,150) | ||
return None | ||
|
||
def sort(self, column, order = QtCore.Qt.AscendingOrder): | ||
self.layoutAboutToBeChanged.emit() | ||
self.sortColumn = column | ||
if order == QtCore.Qt.DescendingOrder: | ||
self.sortReversed = True | ||
else: | ||
self.sortReversed = False | ||
self._sortItemList() | ||
self.layoutChanged.emit() | ||
|
||
def getPipValue(self, row): | ||
if self.itemList and len(self.itemList) > row: | ||
return self.itemList[row] | ||
else: | ||
return None | ||
|
||
|
||
|
||
|
||
class EffectWidget(widgets.WidgetBase): | ||
|
||
def __init__(self, mhandle, parent): | ||
super().__init__('Radio', parent) | ||
self.widget = uic.loadUi(os.path.join(mhandle.basepath, 'ui', 'radiowidget.ui')) | ||
self.setWidget(self.widget) | ||
|
||
def init(self, app, datamanager): | ||
super().init(app, datamanager) | ||
self.radioViewModel = EffectTableModel() | ||
self.widget.radioView.setModel(self.radioViewModel) | ||
self.widget.radioView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) | ||
self.widget.radioView.customContextMenuRequested.connect(self._slotTableContextMenu) | ||
self.widget.radioView.doubleClicked.connect(self._slotTableDoubleClicked) | ||
self.widget.radioView.setColumnWidth(0, 300) | ||
self.dataManager = datamanager | ||
self.dataManager.registerRootObjectListener(self._onPipRootObjectEvent) | ||
|
||
@QtCore.pyqtSlot(QtCore.QPoint) | ||
def _slotTableContextMenu(self, pos): | ||
index = self.widget.radioView.selectionModel().currentIndex() | ||
if index.isValid(): | ||
value = self.radioViewModel.getPipValue(index.row()) | ||
if value: | ||
menu = QtWidgets.QMenu(self.widget.radioView) | ||
def _toggleRadio(): | ||
self.dataManager.rpcToggleRadioStation(value) | ||
taction = menu.addAction('Toggle Radio') | ||
taction.triggered.connect(_toggleRadio) | ||
menu.exec(self.widget.radioView.mapToGlobal(pos)) | ||
|
||
@QtCore.pyqtSlot(QtCore.QModelIndex) | ||
def _slotTableDoubleClicked(self, index): | ||
value = self.radioViewModel.getPipValue(index.row()) | ||
if value: | ||
self.dataManager.rpcToggleRadioStation(value) | ||
|
||
|
||
def _onPipRootObjectEvent(self, rootObject): | ||
self.pipRadio = rootObject.child('Radio') | ||
if self.pipRadio: | ||
self.radioViewModel.setPipRadio(self.pipRadio) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ui version="4.0"> | ||
<class>Form</class> | ||
<widget class="QWidget" name="Form"> | ||
<property name="geometry"> | ||
<rect> | ||
<x>0</x> | ||
<y>0</y> | ||
<width>400</width> | ||
<height>300</height> | ||
</rect> | ||
</property> | ||
<property name="windowTitle"> | ||
<string>Form</string> | ||
</property> | ||
<layout class="QVBoxLayout" name="verticalLayout"> | ||
<property name="leftMargin"> | ||
<number>4</number> | ||
</property> | ||
<property name="topMargin"> | ||
<number>4</number> | ||
</property> | ||
<property name="rightMargin"> | ||
<number>4</number> | ||
</property> | ||
<property name="bottomMargin"> | ||
<number>4</number> | ||
</property> | ||
<item> | ||
<widget class="QTableView" name="radioView"> | ||
<property name="alternatingRowColors"> | ||
<bool>true</bool> | ||
</property> | ||
<property name="selectionMode"> | ||
<enum>QAbstractItemView::SingleSelection</enum> | ||
</property> | ||
<property name="selectionBehavior"> | ||
<enum>QAbstractItemView::SelectRows</enum> | ||
</property> | ||
<property name="sortingEnabled"> | ||
<bool>true</bool> | ||
</property> | ||
</widget> | ||
</item> | ||
</layout> | ||
</widget> | ||
<resources/> | ||
<connections/> | ||
</ui> |