// DataSelectionWidget class definition // // The partials / residual bands selector widget // // QATSH Copyright 2009 Jean-Philippe MEURET #include #include "ATSModelManager.h" #include "ATSPartialsProxyModel.h" #include "ATSResidualsProxyModel.h" #include "DataSelectionWidget.h" #include "ui_DataSelectionWidget.h" // Note for partial amplitude-related data types (for each partial, independently) : // * Peak=Max. amplitude = max(partial.amp(frame) for frame in [0, nFrames]) // * RMS power amplitude = sqrt(sum(partial.amp(frame)**2 for frame in [0, nFrames]) / nFrames) // Partial are selected iif computedAmplitude >= 10**(UserThreshold_dB/20) // Const data for available value types for each possible data types static const int KNMaxValueTypes = 5; static const int KNValueTypes[TypesAndConstants::eDataTypeNumber] = { 5, 4 }; static const char* KPSZValueTypeNames[TypesAndConstants::eDataTypeNumber][KNMaxValueTypes] = { // ePartial { "Maximum amplitude (raw)", "Maximum amplitude (dB)", "RMS power amplitude (dB)", "Signal to Mask Ratio (dB)", "Frequency (Hz)" }, // eResidualBand { "Maximum energy (raw)", "Maximum energy (dB)", "RMS power energy (dB)", "Frequency (Hz)", 0 } }; enum { eMin=0, eMax, eMinMax }; static const double KDValueRanges[TypesAndConstants::eDataTypeNumber] [KNMaxValueTypes][eMinMax] = { // ePartial { // min max { 0.0, 100000.0 }, // Maximum amplitude (raw) { -1000.0, 1000.0 }, // Maximum amplitude (dB) { -1000.0, 1000.0 }, // RMS power amplitude (dB) { -1000.0, 1000.0 }, // Signal to Mask Ratio (dB) { 0.0, 100000.0 } // Frequency (Hz) }, // eResidualBand { // min max { 0.0, 100000.0 }, // Maximum energy (raw) { -1000.0, 1000.0 }, // Maximum energy (dB) { -1000.0, 1000.0 }, // RMS power energy (dB) { 0.0, 100000.0 }, // Frequency (Hz) { 0.0, 0.0 } // Not used } }; static const double KDValueDefaults[TypesAndConstants::eDataTypeNumber] [KNMaxValueTypes][eMinMax] = { // ePartial { // min max { 0.0, 1.0 }, // Maximum amplitude (raw) { -30.0, 0.0 }, // Maximum amplitude (dB) { -30.0, 0.0 }, // RMS power amplitude (dB) { -30.0, 0.0 }, // Mean Signal to Mask Ratio (dB) { 20.0, 20000.0 } // Mean frequency (Hz) }, // eResidualBand { // min max { 0.0, 10.0 }, // Maximum energy (raw) { -30.0, 0.0 }, // Maximum energy (dB) { -30.0, 0.0 }, // RMS power energy (dB) { 20.0, 20000.0 }, // Minimal frequency (Hz) { 0.0, 0.0 } // Not used } }; static const DataSelectionWidget::EValueThresholdType KEValueThresholdTypes[TypesAndConstants::eDataTypeNumber][KNMaxValueTypes] = { // ePartial { DataSelectionWidget::ePeakAmplitude, DataSelectionWidget::eRMSPowerAmplitude, DataSelectionWidget::eSignalToMaskRatio, DataSelectionWidget::eFrequency }, // eResidualBand { DataSelectionWidget::ePeakAmplitude, DataSelectionWidget::eRMSPowerAmplitude, DataSelectionWidget::eFrequency, DataSelectionWidget::eThresholdTypeNumber } }; // Constructor / Destructor ========================================== DataSelectionWidget::DataSelectionWidget(QWidget *parent) : QWidget(parent), _pui(new Ui::DataSelectionWidget), _pModelMgr(0), _eDataType(TypesAndConstants::ePartial), _nMaxItemIndex(0) { _pui->setupUi(this); // Enable control value synchronization _bSynchronizeControls = true; // Connect controls to local changed() slots for synchronisation // 1) Index sliders connect(_pui->qsdFromIndex, SIGNAL(valueChanged(int)), this, SLOT(onFromIndexChanged(int))); connect(_pui->qsdToIndex, SIGNAL(valueChanged(int)), this, SLOT(onToIndexChanged(int))); // 2) Index spin-boxes connect(_pui->qsbFromIndex, SIGNAL(valueChanged(int)), this, SLOT(onFromIndexChanged(int))); connect(_pui->qsbToIndex, SIGNAL(valueChanged(int)), this, SLOT(onToIndexChanged(int))); // 3) Min / max value use connect(_pui->qckMinValue, SIGNAL(stateChanged(int)), this, SLOT(onUseMinValueChanged(int))); connect(_pui->qckMaxValue, SIGNAL(stateChanged(int)), this, SLOT(onUseMaxValueChanged(int))); // 4) Value type combo-box. connect(_pui->qcbValueType, SIGNAL(currentIndexChanged(int)), this, SLOT(onValueTypeChanged(int))); } DataSelectionWidget::~DataSelectionWidget() { delete _pui; } // Model management ================================================== void DataSelectionWidget::setModelManager(ATSModelManager* pModelMgr) { _pModelMgr = pModelMgr; } void DataSelectionWidget::resetControls() { _pui->qsdFromIndex->setMaximum(_nMaxItemIndex); _pui->qsdToIndex->setMaximum(_nMaxItemIndex); // Reset maximum value for index spin-boxes _pui->qsbFromIndex->setMaximum(_nMaxItemIndex); _pui->qsbToIndex->setMaximum(_nMaxItemIndex); // Reset tick interval for sliders _pui->qsdFromIndex->setTickInterval(_nMaxItemIndex > 3 ? (_nMaxItemIndex + 1) / 4 : 1); _pui->qsdToIndex->setTickInterval(_nMaxItemIndex > 3 ? (_nMaxItemIndex + 1) / 4 : 1); // Reset value type combo-box. _pui->qcbValueType->clear(); for (int nValTypInd = 0; nValTypInd < KNValueTypes[_eDataType]; nValTypInd++) _pui->qcbValueType->addItem(tr(KPSZValueTypeNames[_eDataType][nValTypInd])); } void DataSelectionWidget::switchDataType(TypesAndConstants::EDataType eDataType) { // Save new current data type. _eDataType = eDataType; // Determine new current number of data items. switch(eDataType) { case TypesAndConstants::ePartial: disconnect(_pModelMgr->residualsModel(), SIGNAL(modelReset()), this, SLOT(onModelReset())); connect(_pModelMgr->partialsModel(), SIGNAL(modelReset()), this, SLOT(onModelReset())); _nMaxItemIndex = _pModelMgr->partialsModel()->nbPartials() - 1; break; case TypesAndConstants::eResidualBand: disconnect(_pModelMgr->partialsModel(), SIGNAL(modelReset()), this, SLOT(onModelReset())); connect(_pModelMgr->residualsModel(), SIGNAL(modelReset()), this, SLOT(onModelReset())); _nMaxItemIndex = _pModelMgr->residualsModel()->nbResiduals() - 1; break; default: break; } // Reset maximum value for sliders resetControls(); } // State management ================================================== DataSelectionWidget::SState DataSelectionWidget::getState() const { // Get state from controls SState state; state.nFromIndex = _pui->qsbFromIndex->value(); state.nToIndex = _pui->qsbToIndex->value(); state.nIndexStep = _pui->qsbIndexStep->value(); state.nValueTypeIndex = _pui->qcbValueType->currentIndex(); state.bUseMinValue = _pui->qckMinValue->isChecked(); state.dMinValue = _pui->qsbMinValue->value(); state.bUseMaxValue = _pui->qckMaxValue->isChecked(); state.dMaxValue = _pui->qsbMaxValue->value(); return state; } void DataSelectionWidget::setState(const SState& state) { // Check/fix/initialize the selector state as needed. SState fixedState = state; if (fixedState.nToIndex < 0 || fixedState.nToIndex > _nMaxItemIndex) fixedState.nToIndex = _nMaxItemIndex; if (fixedState.nFromIndex > fixedState.nToIndex) fixedState.nFromIndex = fixedState.nToIndex; // Set state to controls (auto-synchonization will do its job for the sliders). _pui->qsbFromIndex->setValue(fixedState.nFromIndex); _pui->qsbToIndex->setValue(fixedState.nToIndex); _pui->qsbIndexStep->setValue(fixedState.nIndexStep); _pui->qcbValueType->setCurrentIndex(fixedState.nValueTypeIndex); _pui->qckMinValue->setChecked(fixedState.bUseMinValue); _pui->qsbMinValue->setValue(fixedState.dMinValue); _pui->qckMaxValue->setChecked(fixedState.bUseMaxValue); _pui->qsbMaxValue->setValue(fixedState.dMaxValue); } // Slots to synchronize with model ==================================== void DataSelectionWidget::onModelReset() { // Simply re-initialize controls for the current data type. resetControls(); } // Slots to synchronize control values/state=========================== void DataSelectionWidget::onFromIndexChanged(int nNewIndex) { // Nothing to do if control synchronization is blocked. if (!_bSynchronizeControls) return; // Synchronize attached controls. _bSynchronizeControls = false; _pui->qsbFromIndex->setValue(nNewIndex); _pui->qsdFromIndex->setValue(nNewIndex); _bSynchronizeControls = true; // From can't be greater than To if (nNewIndex > _pui->qsbToIndex->value()) _pui->qsbToIndex->setValue(nNewIndex); // Warn everyone of the selection change. emit dataIndexSelectionChanged(_eDataType, nNewIndex, _pui->qsbToIndex->value()); } void DataSelectionWidget::onToIndexChanged(int nNewIndex) { // Nothing to do if control synchronization is blocked. if (!_bSynchronizeControls) return; // Synchronize attached controls. _bSynchronizeControls = false; _pui->qsbToIndex->setValue(nNewIndex); _pui->qsdToIndex->setValue(nNewIndex); _bSynchronizeControls = true; // To can't be lower than From if (nNewIndex < _pui->qsbFromIndex->value()) _pui->qsbFromIndex->setValue(nNewIndex); // Warn everyone of the selection change. emit dataIndexSelectionChanged(_eDataType, _pui->qsbFromIndex->value(), nNewIndex); } void DataSelectionWidget::onUseMinValueChanged(int nNewState) { // Enable or disable min value spin-box _pui->qsbMinValue->setEnabled(nNewState != Qt::Unchecked); // Warn everyone of the selection change. emit dataValueSelectionChanged (_eDataType, KEValueThresholdTypes[_eDataType][_pui->qcbValueType->currentIndex()], _pui->qckMinValue->isChecked(), _pui->qsbMinValue->value(), _pui->qckMaxValue->isChecked(), _pui->qsbMaxValue->value()); } void DataSelectionWidget::onUseMaxValueChanged(int nNewState) { // Enable or disable min value spin-box _pui->qsbMaxValue->setEnabled(nNewState != Qt::Unchecked); // Warn everyone of the selection change. emit dataValueSelectionChanged (_eDataType, KEValueThresholdTypes[_eDataType][_pui->qcbValueType->currentIndex()], _pui->qckMinValue->isChecked(), _pui->qsbMinValue->value(), _pui->qckMaxValue->isChecked(), _pui->qsbMaxValue->value()); } void DataSelectionWidget::onValueTypeChanged(int nNewIndex) { // Reset min/max and default value for min and max values. _pui->qsbMinValue->setMinimum(KDValueRanges[_eDataType][nNewIndex][eMin]); _pui->qsbMinValue->setMaximum(KDValueRanges[_eDataType][nNewIndex][eMax]); _pui->qsbMinValue->setValue(KDValueDefaults[_eDataType][nNewIndex][eMin]); _pui->qsbMaxValue->setMinimum(KDValueRanges[_eDataType][nNewIndex][eMin]); _pui->qsbMaxValue->setMaximum(KDValueRanges[_eDataType][nNewIndex][eMax]); _pui->qsbMaxValue->setValue(KDValueDefaults[_eDataType][nNewIndex][eMax]); } // Event management ================================================== void DataSelectionWidget::changeEvent(QEvent *e) { switch (e->type()) { case QEvent::LanguageChange: _pui->retranslateUi(this); break; default: break; } }