219 lines
6.4 KiB
C++
219 lines
6.4 KiB
C++
#include "tracesetselector.h"
|
|
|
|
#include <QGridLayout>
|
|
#include <QLabel>
|
|
|
|
TraceSetSelector::TraceSetSelector(QWidget *parent) :
|
|
QWidget(parent),
|
|
model(nullptr)
|
|
{
|
|
points = 0;
|
|
ports = 0;
|
|
lowerFreq = upperFreq = 0;
|
|
referenceImpedance = 50.0;
|
|
freqsSet = false;
|
|
partialSelectionAllowed = false;
|
|
|
|
setLayout(new QGridLayout);
|
|
setPorts(2);
|
|
}
|
|
|
|
TraceSetSelector::~TraceSetSelector()
|
|
{
|
|
blockSignals(true);
|
|
// this will free all created widgets
|
|
setPorts(0);
|
|
blockSignals(false);
|
|
}
|
|
|
|
unsigned int TraceSetSelector::getPorts() const
|
|
{
|
|
return ports;
|
|
}
|
|
|
|
void TraceSetSelector::setPorts(unsigned int newPorts)
|
|
{
|
|
if(!model) {
|
|
return;
|
|
}
|
|
QGridLayout *layout = static_cast<QGridLayout*>(this->layout());
|
|
if(newPorts != ports) {
|
|
ports = newPorts;
|
|
// remove the previous widgets
|
|
QLayoutItem *child;
|
|
while ((child = layout->takeAt(0)) != 0) {
|
|
delete child->widget();
|
|
delete child;
|
|
}
|
|
cTraces.clear();
|
|
for(unsigned int i=0;i<ports;i++) {
|
|
cTraces.push_back(std::vector<QComboBox*>());
|
|
for(unsigned int j=0;j<ports;j++) {
|
|
auto l = new QLabel("S"+QString::number(i+1)+QString::number(j+1)+":");
|
|
auto c = new QComboBox();
|
|
cTraces[i].push_back(c);
|
|
connect(c, qOverload<int>(&QComboBox::currentIndexChanged), [=](int) {
|
|
selectionChanged(c);
|
|
});
|
|
layout->addWidget(l, i, j*2);
|
|
layout->addWidget(c, i, j*2 + 1);
|
|
}
|
|
}
|
|
}
|
|
auto availableTraces = model->getTraces();
|
|
for(unsigned int i=0;i<ports;i++) {
|
|
for(unsigned int j=0;j<ports;j++) {
|
|
auto c = cTraces[i][j];
|
|
c->blockSignals(true);
|
|
c->clear();
|
|
// create possible trace selections
|
|
c->addItem("None");
|
|
for(auto t : availableTraces) {
|
|
if(t->getDataType() != Trace::DataType::Frequency) {
|
|
// can only add frequency traces
|
|
continue;
|
|
}
|
|
if(i == j && !t->isReflection()) {
|
|
// can not add through measurement at reflection port
|
|
continue;
|
|
} else if(i != j && t->isReflection()) {
|
|
// can not add reflection measurement at through port
|
|
continue;
|
|
}
|
|
c->addItem(t->name(), QVariant::fromValue<Trace*>(t));
|
|
}
|
|
c->blockSignals(false);
|
|
}
|
|
}
|
|
emit selectionChanged();
|
|
}
|
|
|
|
bool TraceSetSelector::setTrace(unsigned int destPort, unsigned int srcPort, Trace *t)
|
|
{
|
|
if(destPort < 1 || destPort > ports || srcPort < 1 || srcPort > ports) {
|
|
// invalid port selection
|
|
return false;
|
|
}
|
|
auto c = cTraces[destPort-1][srcPort-1];
|
|
// find required trace
|
|
for(unsigned int i=1;i<(unsigned int) c->count();i++) {
|
|
if(qvariant_cast<Trace*>(c->itemData(i)) == t) {
|
|
c->setCurrentIndex(i);
|
|
return true;
|
|
}
|
|
}
|
|
// requested trace not found, unable to set
|
|
return false;
|
|
}
|
|
|
|
Trace *TraceSetSelector::getTrace(unsigned int destPort, unsigned int srcPort)
|
|
{
|
|
if(destPort < 1 || destPort > ports || srcPort < 1 || srcPort > ports) {
|
|
// invalid port selection
|
|
return nullptr;
|
|
}
|
|
auto c = cTraces[destPort-1][srcPort-1];
|
|
if(c->currentIndex() == 0) {
|
|
// no trace selected
|
|
return nullptr;
|
|
} else {
|
|
return qvariant_cast<Trace*>(c->itemData(c->currentIndex()));
|
|
}
|
|
}
|
|
|
|
bool TraceSetSelector::selectionValid()
|
|
{
|
|
for(unsigned int i=1;i<=ports;i++) {
|
|
for(unsigned int j=1;j<=ports;j++) {
|
|
auto t = getTrace(i, j);
|
|
if(!t && !partialSelectionAllowed) {
|
|
// at least one trace is missing
|
|
return false;
|
|
}
|
|
if(t && partialSelectionAllowed) {
|
|
// at least one trace is present
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
// if we get here, either:
|
|
// - all traces are valid and partial selection is not allowed -> whole selection valid
|
|
// or:
|
|
// - all traces are invalid and partial selection is allowed -> whole selection invalid
|
|
return !partialSelectionAllowed;
|
|
}
|
|
|
|
void TraceSetSelector::selectionChanged(QComboBox *c)
|
|
{
|
|
if(c->currentIndex() != 0 && !freqsSet) {
|
|
// the first trace has been selected, extract frequency info
|
|
Trace *t = qvariant_cast<Trace*>(c->itemData(c->currentIndex()));
|
|
points = t->size();
|
|
referenceImpedance = t->getReferenceImpedance();
|
|
if(points > 0) {
|
|
lowerFreq = t->minX();
|
|
upperFreq = t->maxX();
|
|
}
|
|
freqsSet = true;
|
|
// remove all trace options with incompatible frequencies
|
|
for(auto v1 : cTraces) {
|
|
for(auto c : v1) {
|
|
for(int i=1;i<c->count();i++) {
|
|
Trace *t = qvariant_cast<Trace*>(c->itemData(i));
|
|
if(t->getReferenceImpedance() != referenceImpedance || t->size() != points || (points > 0 && (t->minX() != lowerFreq || t->maxX() != upperFreq))) {
|
|
// this trace is not available anymore
|
|
c->removeItem(i);
|
|
// decrement to check the next index in the next loop iteration
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if(c->currentIndex() == 0 && freqsSet) {
|
|
// Check if all trace selections are set for none
|
|
for(auto v1 : cTraces) {
|
|
for(auto c : v1) {
|
|
if(c->currentIndex() != 0) {
|
|
// some trace is still selected, abort
|
|
emit selectionChanged();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
// all traces set for none
|
|
freqsSet = false;
|
|
setPorts(ports);
|
|
}
|
|
emit selectionChanged();
|
|
}
|
|
|
|
double TraceSetSelector::getReferenceImpedance() const
|
|
{
|
|
return referenceImpedance;
|
|
}
|
|
|
|
double TraceSetSelector::getUpperFreq() const
|
|
{
|
|
return upperFreq;
|
|
}
|
|
|
|
double TraceSetSelector::getLowerFreq() const
|
|
{
|
|
return lowerFreq;
|
|
}
|
|
|
|
unsigned int TraceSetSelector::getPoints() const
|
|
{
|
|
return points;
|
|
}
|
|
|
|
void TraceSetSelector::setModel(TraceModel *newModel)
|
|
{
|
|
model = newModel;
|
|
}
|
|
|
|
void TraceSetSelector::setPartialSelectionAllowed(bool newPartialSelectionAllowed)
|
|
{
|
|
partialSelectionAllowed = newPartialSelectionAllowed;
|
|
}
|