//////////////////////////////////////////////////////////////////////////////// // // OpenHantek // dsowidget.cpp // // Copyright (C) 2010 Oliver Haag // oliver.haag@gmail.com // // This program 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 . // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include "dsowidget.h" #include "dataanalyzer.h" #include "dso.h" #include "exporter.h" #include "glscope.h" #include "helper.h" #include "levelslider.h" #include "settings.h" //////////////////////////////////////////////////////////////////////////////// // class DsoWidget /// \brief Initializes the components of the oszilloscope-screen. /// \param settings The settings object containing the oscilloscope settings. /// \param dataAnalyzer The data analyzer that should be used as data source. /// \param parent The parent widget. /// \param flags Flags for the window manager. DsoWidget::DsoWidget(DsoSettings *settings, DataAnalyzer *dataAnalyzer, QWidget *parent, Qt::WindowFlags flags) : QWidget(parent, flags) { this->settings = settings; this->dataAnalyzer = dataAnalyzer; // Palette for this widget QPalette palette; palette.setColor(QPalette::Background, this->settings->view.color.screen.background); palette.setColor(QPalette::WindowText, this->settings->view.color.screen.text); // The OpenGL accelerated scope widgets this->generator = new GlGenerator(this->settings, this); this->generator->setDataAnalyzer(this->dataAnalyzer); this->mainScope = new GlScope(this->settings); this->mainScope->setGenerator(this->generator); this->zoomScope = new GlScope(this->settings); this->zoomScope->setGenerator(this->generator); this->zoomScope->setZoomMode(true); // The offset sliders for all possible channels this->offsetSlider = new LevelSlider(Qt::RightArrow); for(int channel = 0; channel < this->settings->scope.voltage.count(); ++channel) { this->offsetSlider->addSlider(this->settings->scope.voltage[channel].name, channel); this->offsetSlider->setColor(channel, this->settings->view.color.screen.voltage[channel]); this->offsetSlider->setLimits(channel, -DIVS_VOLTAGE / 2, DIVS_VOLTAGE / 2); this->offsetSlider->setStep(channel, 0.2); this->offsetSlider->setValue(channel, this->settings->scope.voltage[channel].offset); this->offsetSlider->setVisible(channel, this->settings->scope.voltage[channel].used); } for(int channel = 0; channel < this->settings->scope.voltage.count(); ++channel) { this->offsetSlider->addSlider(this->settings->scope.spectrum[channel].name, this->settings->scope.voltage.count() + channel); this->offsetSlider->setColor(this->settings->scope.voltage.count() + channel, this->settings->view.color.screen.spectrum[channel]); this->offsetSlider->setLimits(this->settings->scope.voltage.count() + channel, -DIVS_VOLTAGE / 2, DIVS_VOLTAGE / 2); this->offsetSlider->setStep(this->settings->scope.voltage.count() + channel, 0.2); this->offsetSlider->setValue(this->settings->scope.voltage.count() + channel, this->settings->scope.spectrum[channel].offset); this->offsetSlider->setVisible(this->settings->scope.voltage.count() + channel, this->settings->scope.spectrum[channel].used); } // The triggerPosition slider this->triggerPositionSlider = new LevelSlider(Qt::DownArrow); this->triggerPositionSlider->addSlider(); this->triggerPositionSlider->setLimits(0, 0.0, 1.0); this->triggerPositionSlider->setStep(0, 0.2 / DIVS_TIME); this->triggerPositionSlider->setValue(0, this->settings->scope.trigger.position); this->triggerPositionSlider->setVisible(0, true); // The sliders for the trigger levels this->triggerLevelSlider = new LevelSlider(Qt::LeftArrow); for(int channel = 0; channel < (int) this->settings->scope.physicalChannels; ++channel) { this->triggerLevelSlider->addSlider(channel); this->triggerLevelSlider->setColor(channel, (!this->settings->scope.trigger.special && channel == (int) this->settings->scope.trigger.source) ? this->settings->view.color.screen.voltage[channel] : this->settings->view.color.screen.voltage[channel].darker()); this->adaptTriggerLevelSlider(channel); this->triggerLevelSlider->setValue(channel, this->settings->scope.voltage[channel].trigger); this->triggerLevelSlider->setVisible(channel, this->settings->scope.voltage[channel].used); } // The marker slider this->markerSlider = new LevelSlider(Qt::UpArrow); for(int marker = 0; marker < MARKER_COUNT; ++marker) { this->markerSlider->addSlider(QString::number(marker + 1), marker); this->markerSlider->setLimits(marker, -DIVS_TIME / 2, DIVS_TIME / 2); this->markerSlider->setStep(marker, 0.2); this->markerSlider->setValue(marker, this->settings->scope.horizontal.marker[marker]); this->markerSlider->setVisible(marker, true); } // The table for the settings this->settingsTriggerLabel = new QLabel(); this->settingsTriggerLabel->setMinimumWidth(160); this->settingsRecordLengthLabel = new QLabel(); this->settingsRecordLengthLabel->setAlignment(Qt::AlignRight); this->settingsRecordLengthLabel->setPalette(palette); this->settingsSamplerateLabel = new QLabel(); this->settingsSamplerateLabel->setAlignment(Qt::AlignRight); this->settingsSamplerateLabel->setPalette(palette); this->settingsTimebaseLabel = new QLabel(); this->settingsTimebaseLabel->setAlignment(Qt::AlignRight); this->settingsTimebaseLabel->setPalette(palette); this->settingsFrequencybaseLabel = new QLabel(); this->settingsFrequencybaseLabel->setAlignment(Qt::AlignRight); this->settingsFrequencybaseLabel->setPalette(palette); this->settingsLayout = new QHBoxLayout(); this->settingsLayout->addWidget(this->settingsTriggerLabel); this->settingsLayout->addWidget(this->settingsRecordLengthLabel, 1); this->settingsLayout->addWidget(this->settingsSamplerateLabel, 1); this->settingsLayout->addWidget(this->settingsTimebaseLabel, 1); this->settingsLayout->addWidget(this->settingsFrequencybaseLabel, 1); // The table for the marker details this->markerInfoLabel = new QLabel(); this->markerInfoLabel->setMinimumWidth(160); this->markerInfoLabel->setPalette(palette); this->markerTimeLabel = new QLabel(); this->markerTimeLabel->setAlignment(Qt::AlignRight); this->markerTimeLabel->setPalette(palette); this->markerFrequencyLabel = new QLabel(); this->markerFrequencyLabel->setAlignment(Qt::AlignRight); this->markerFrequencyLabel->setPalette(palette); this->markerTimebaseLabel = new QLabel(); this->markerTimebaseLabel->setAlignment(Qt::AlignRight); this->markerTimebaseLabel->setPalette(palette); this->markerFrequencybaseLabel = new QLabel(); this->markerFrequencybaseLabel->setAlignment(Qt::AlignRight); this->markerFrequencybaseLabel->setPalette(palette); this->markerLayout = new QHBoxLayout(); this->markerLayout->addWidget(this->markerInfoLabel); this->markerLayout->addWidget(this->markerTimeLabel, 1); this->markerLayout->addWidget(this->markerFrequencyLabel, 1); this->markerLayout->addWidget(this->markerTimebaseLabel, 1); this->markerLayout->addWidget(this->markerFrequencybaseLabel, 1); // The table for the measurements QPalette tablePalette = palette; this->measurementLayout = new QGridLayout(); this->measurementLayout->setColumnMinimumWidth(0, 64); this->measurementLayout->setColumnMinimumWidth(1, 32); this->measurementLayout->setColumnStretch(2, 2); this->measurementLayout->setColumnStretch(3, 2); this->measurementLayout->setColumnStretch(4, 3); this->measurementLayout->setColumnStretch(5, 3); for(int channel = 0; channel < this->settings->scope.voltage.count(); ++channel) { tablePalette.setColor(QPalette::WindowText, this->settings->view.color.screen.voltage[channel]); this->measurementNameLabel.append(new QLabel(this->settings->scope.voltage[channel].name)); this->measurementNameLabel[channel]->setPalette(tablePalette); this->measurementMiscLabel.append(new QLabel()); this->measurementMiscLabel[channel]->setPalette(tablePalette); this->measurementGainLabel.append(new QLabel()); this->measurementGainLabel[channel]->setAlignment(Qt::AlignRight); this->measurementGainLabel[channel]->setPalette(tablePalette); tablePalette.setColor(QPalette::WindowText, this->settings->view.color.screen.spectrum[channel]); this->measurementMagnitudeLabel.append(new QLabel()); this->measurementMagnitudeLabel[channel]->setAlignment(Qt::AlignRight); this->measurementMagnitudeLabel[channel]->setPalette(tablePalette); this->measurementAmplitudeLabel.append(new QLabel()); this->measurementAmplitudeLabel[channel]->setAlignment(Qt::AlignRight); this->measurementAmplitudeLabel[channel]->setPalette(palette); this->measurementFrequencyLabel.append(new QLabel()); this->measurementFrequencyLabel[channel]->setAlignment(Qt::AlignRight); this->measurementFrequencyLabel[channel]->setPalette(palette); this->setMeasurementVisible(channel, this->settings->scope.voltage[channel].used); this->measurementLayout->addWidget(this->measurementNameLabel[channel], channel, 0); this->measurementLayout->addWidget(this->measurementMiscLabel[channel], channel, 1); this->measurementLayout->addWidget(this->measurementGainLabel[channel], channel, 2); this->measurementLayout->addWidget(this->measurementMagnitudeLabel[channel], channel, 3); this->measurementLayout->addWidget(this->measurementAmplitudeLabel[channel], channel, 4); this->measurementLayout->addWidget(this->measurementFrequencyLabel[channel], channel, 5); if((unsigned int) channel < this->settings->scope.physicalChannels) this->updateVoltageCoupling(channel); else this->updateMathMode(); this->updateVoltageDetails(channel); this->updateSpectrumDetails(channel); } // The layout for the widgets this->mainLayout = new QGridLayout(); this->mainLayout->setColumnStretch(2, 1); // Scopes increase their size this->mainLayout->setRowStretch(3, 1); // Bars around the scope, needed because the slider-drawing-area is outside // the scope at min/max this->mainLayout->setColumnMinimumWidth(1, this->triggerPositionSlider->preMargin()); this->mainLayout->setColumnMinimumWidth(3, this->triggerPositionSlider->postMargin()); this->mainLayout->setRowMinimumHeight(2, this->offsetSlider->preMargin()); this->mainLayout->setRowMinimumHeight(4, this->offsetSlider->postMargin()); this->mainLayout->setRowMinimumHeight(6, 4); this->mainLayout->setRowMinimumHeight(8, 4); this->mainLayout->setRowMinimumHeight(10, 8); this->mainLayout->setSpacing(0); this->mainLayout->addLayout(this->settingsLayout, 0, 0, 1, 5); this->mainLayout->addWidget(this->mainScope, 3, 2); this->mainLayout->addWidget(this->offsetSlider, 2, 0, 3, 2, Qt::AlignRight); this->mainLayout->addWidget(this->triggerPositionSlider, 1, 1, 2, 3, Qt::AlignBottom); this->mainLayout->addWidget(this->triggerLevelSlider, 2, 3, 3, 2, Qt::AlignLeft); this->mainLayout->addWidget(this->markerSlider, 4, 1, 2, 3, Qt::AlignTop); this->mainLayout->addLayout(this->markerLayout, 7, 0, 1, 5); this->mainLayout->addWidget(this->zoomScope, 9, 2); this->mainLayout->addLayout(this->measurementLayout, 11, 0, 1, 5); // Apply settings and update measured values this->updateTriggerDetails(); this->updateRecordLength(this->settings->scope.horizontal.recordLength); this->updateFrequencybase(this->settings->scope.horizontal.frequencybase); this->updateSamplerate(this->settings->scope.horizontal.samplerate); this->updateTimebase(this->settings->scope.horizontal.timebase); this->updateZoom(this->settings->view.zoom); // The widget itself this->setPalette(palette); this->setBackgroundRole(QPalette::Background); this->setAutoFillBackground(true); this->setLayout(this->mainLayout); // Connect change-signals of sliders this->connect(this->offsetSlider, SIGNAL(valueChanged(int, double)), this, SLOT(updateOffset(int, double))); this->connect(this->triggerPositionSlider, SIGNAL(valueChanged(int, double)), this, SLOT(updateTriggerPosition(int, double))); this->connect(this->triggerLevelSlider, SIGNAL(valueChanged(int, double)), this, SLOT(updateTriggerLevel(int, double))); this->connect(this->markerSlider, SIGNAL(valueChanged(int, double)), this, SLOT(updateMarker(int, double))); this->connect(this->markerSlider, SIGNAL(valueChanged(int, double)), this->mainScope, SLOT(updateGL())); this->connect(this->markerSlider, SIGNAL(valueChanged(int, double)), this->zoomScope, SLOT(updateGL())); // Connect other signals this->connect(this->dataAnalyzer, SIGNAL(analyzed(unsigned long)), this, SLOT(dataAnalyzed())); this->connect(this->dataAnalyzer, SIGNAL(analyzed(unsigned long)), this, SLOT(updateRecordLength(unsigned long))); } /// \brief Stops the oscilloscope thread and the timer. DsoWidget::~DsoWidget() { } /// \brief Set the trigger level sliders minimum and maximum to the new values. void DsoWidget::adaptTriggerLevelSlider(unsigned int channel) { this->triggerLevelSlider->setLimits(channel, (-DIVS_VOLTAGE / 2 - this->settings->scope.voltage[channel].offset) * this->settings->scope.voltage[channel].gain, (DIVS_VOLTAGE / 2 - this->settings->scope.voltage[channel].offset) * this->settings->scope.voltage[channel].gain); this->triggerLevelSlider->setStep(channel, this->settings->scope.voltage[channel].gain * 0.2); } /// \brief Show/Hide a line of the measurement table. void DsoWidget::setMeasurementVisible(unsigned int channel, bool visible) { this->measurementNameLabel[channel]->setVisible(visible); this->measurementMiscLabel[channel]->setVisible(visible); this->measurementGainLabel[channel]->setVisible(visible); this->measurementMagnitudeLabel[channel]->setVisible(visible); this->measurementAmplitudeLabel[channel]->setVisible(visible); this->measurementFrequencyLabel[channel]->setVisible(visible); if(!visible) { this->measurementGainLabel[channel]->setText(QString()); this->measurementMagnitudeLabel[channel]->setText(QString()); this->measurementAmplitudeLabel[channel]->setText(QString()); this->measurementFrequencyLabel[channel]->setText(QString()); } } /// \brief Update the label about the marker measurements void DsoWidget::updateMarkerDetails() { double divs = fabs(this->settings->scope.horizontal.marker[1] - this->settings->scope.horizontal.marker[0]); double time = divs * this->settings->scope.horizontal.timebase; if(this->settings->view.zoom) { this->markerInfoLabel->setText(tr("Zoom x%L1").arg(DIVS_TIME / divs, -1, 'g', 3)); this->markerTimebaseLabel->setText(Helper::valueToString(time / DIVS_TIME, Helper::UNIT_SECONDS, 3) + tr("/div")); this->markerFrequencybaseLabel->setText(Helper::valueToString(divs * this->settings->scope.horizontal.frequencybase / DIVS_TIME, Helper::UNIT_HERTZ, 4) + tr("/div")); } this->markerTimeLabel->setText(Helper::valueToString(time, Helper::UNIT_SECONDS, 4)); this->markerFrequencyLabel->setText(Helper::valueToString(1.0 / time, Helper::UNIT_HERTZ, 4)); } /// \brief Update the label about the trigger settings void DsoWidget::updateSpectrumDetails(unsigned int channel) { this->setMeasurementVisible(channel, this->settings->scope.voltage[channel].used || this->settings->scope.spectrum[channel].used); if(this->settings->scope.spectrum[channel].used) this->measurementMagnitudeLabel[channel]->setText(Helper::valueToString(this->settings->scope.spectrum[channel].magnitude, Helper::UNIT_DECIBEL, 3) + tr("/div")); else this->measurementMagnitudeLabel[channel]->setText(QString()); } /// \brief Update the label about the trigger settings void DsoWidget::updateTriggerDetails() { // Update the trigger details QPalette tablePalette = this->palette(); tablePalette.setColor(QPalette::WindowText, this->settings->view.color.screen.voltage[this->settings->scope.trigger.source]); this->settingsTriggerLabel->setPalette(tablePalette); QString levelString = Helper::valueToString(this->settings->scope.voltage[this->settings->scope.trigger.source].trigger, Helper::UNIT_VOLTS, 3); QString pretriggerString = tr("%L1%").arg((int) (this->settings->scope.trigger.position * 100 + 0.5)); this->settingsTriggerLabel->setText(tr("%1 %2 %3 %4").arg(this->settings->scope.voltage[this->settings->scope.trigger.source].name, Dso::slopeString(this->settings->scope.trigger.slope), levelString, pretriggerString)); /// \todo This won't work for special trigger sources } /// \brief Update the label about the trigger settings void DsoWidget::updateVoltageDetails(unsigned int channel) { if(channel >= (unsigned int) this->settings->scope.voltage.count()) return; this->setMeasurementVisible(channel, this->settings->scope.voltage[channel].used || this->settings->scope.spectrum[channel].used); if(this->settings->scope.voltage[channel].used) this->measurementGainLabel[channel]->setText(Helper::valueToString(this->settings->scope.voltage[channel].gain, Helper::UNIT_VOLTS, 3) + tr("/div")); else this->measurementGainLabel[channel]->setText(QString()); } /// \brief Handles frequencybaseChanged signal from the horizontal dock. /// \param frequencybase The frequencybase used for displaying the trace. void DsoWidget::updateFrequencybase(double frequencybase) { this->settingsFrequencybaseLabel->setText(Helper::valueToString(frequencybase, Helper::UNIT_HERTZ, 4) + tr("/div")); } /// \brief Updates the samplerate field after changing the samplerate. /// \param samplerate The samplerate set in the oscilloscope. void DsoWidget::updateSamplerate(double samplerate) { this->settingsSamplerateLabel->setText(Helper::valueToString(samplerate, Helper::UNIT_SAMPLES, 4) + tr("/s")); } /// \brief Handles timebaseChanged signal from the horizontal dock. /// \param timebase The timebase used for displaying the trace. void DsoWidget::updateTimebase(double timebase) { this->settingsTimebaseLabel->setText(Helper::valueToString(timebase, Helper::UNIT_SECONDS, 4) + tr("/div")); this->updateMarkerDetails(); } /// \brief Handles magnitudeChanged signal from the spectrum dock. /// \param channel The channel whose magnitude was changed. void DsoWidget::updateSpectrumMagnitude(unsigned int channel) { this->updateSpectrumDetails(channel); } /// \brief Handles usedChanged signal from the spectrum dock. /// \param channel The channel whose used-state was changed. /// \param used The new used-state for the channel. void DsoWidget::updateSpectrumUsed(unsigned int channel, bool used) { if(channel >= (unsigned int) this->settings->scope.voltage.count()) return; this->offsetSlider->setVisible(this->settings->scope.voltage.count() + channel, used); this->updateSpectrumDetails(channel); } /// \brief Handles modeChanged signal from the trigger dock. void DsoWidget::updateTriggerMode() { this->updateTriggerDetails(); } /// \brief Handles slopeChanged signal from the trigger dock. void DsoWidget::updateTriggerSlope() { this->updateTriggerDetails(); } /// \brief Handles sourceChanged signal from the trigger dock. void DsoWidget::updateTriggerSource() { // Change the colors of the trigger sliders if(this->settings->scope.trigger.special || this->settings->scope.trigger.source >= this->settings->scope.physicalChannels) this->triggerPositionSlider->setColor(0, this->settings->view.color.screen.border); else this->triggerPositionSlider->setColor(0, this->settings->view.color.screen.voltage[this->settings->scope.trigger.source]); for(int channel = 0; channel < (int) this->settings->scope.physicalChannels; ++channel) this->triggerLevelSlider->setColor(channel, (!this->settings->scope.trigger.special && channel == (int) this->settings->scope.trigger.source) ? this->settings->view.color.screen.voltage[channel] : this->settings->view.color.screen.voltage[channel].darker()); this->updateTriggerDetails(); } /// \brief Handles couplingChanged signal from the voltage dock. /// \param channel The channel whose coupling was changed. void DsoWidget::updateVoltageCoupling(unsigned int channel) { if(channel >= (unsigned int) this->settings->scope.voltage.count()) return; this->measurementMiscLabel[channel]->setText(Dso::couplingString((Dso::Coupling) this->settings->scope.voltage[channel].misc)); } /// \brief Handles modeChanged signal from the voltage dock. void DsoWidget::updateMathMode() { this->measurementMiscLabel[this->settings->scope.physicalChannels]->setText(Dso::mathModeString((Dso::MathMode) this->settings->scope.voltage[this->settings->scope.physicalChannels].misc)); } /// \brief Handles gainChanged signal from the voltage dock. /// \param channel The channel whose gain was changed. void DsoWidget::updateVoltageGain(unsigned int channel) { if(channel >= (unsigned int) this->settings->scope.voltage.count()) return; if(channel < this->settings->scope.physicalChannels) this->adaptTriggerLevelSlider(channel); this->updateVoltageDetails(channel); } /// \brief Handles usedChanged signal from the voltage dock. /// \param channel The channel whose used-state was changed. /// \param used The new used-state for the channel. void DsoWidget::updateVoltageUsed(unsigned int channel, bool used) { if(channel >= (unsigned int) this->settings->scope.voltage.count()) return; this->offsetSlider->setVisible(channel, used); this->triggerLevelSlider->setVisible(channel, used); this->setMeasurementVisible(channel, this->settings->scope.voltage[channel].used); this->updateVoltageDetails(channel); } /// \brief Change the record length. void DsoWidget::updateRecordLength(unsigned long size) { this->settingsRecordLengthLabel->setText(Helper::valueToString(size, Helper::UNIT_SAMPLES, 4)); } /// \brief Export the oscilloscope screen to a file. /// \return true if the document was exported successfully. bool DsoWidget::exportAs() { QStringList filters; filters << tr("Portable Document Format (*.pdf)") << tr("PostScript (*.ps)") << tr("Image (*.png *.xpm *.jpg)") << tr("Comma-Separated Values (*.csv)"); QFileDialog fileDialog(static_cast(this->parent()), tr("Export file..."), QString(), filters.join(";;")); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setAcceptMode(QFileDialog::AcceptSave); if(fileDialog.exec() != QDialog::Accepted) return false; Exporter exporter(this->settings, this->dataAnalyzer, static_cast(this->parent())); exporter.setFilename(fileDialog.selectedFiles().first()); exporter.setFormat((ExportFormat) (EXPORT_FORMAT_PDF + filters.indexOf(fileDialog.selectedFilter()))); return exporter.doExport(); } /// \brief Print the oscilloscope screen. /// \return true if the document was sent to the printer successfully. bool DsoWidget::print() { Exporter exporter(this->settings, this->dataAnalyzer, static_cast(this->parent())); exporter.setFormat(EXPORT_FORMAT_PRINTER); return exporter.doExport(); } /// \brief Stop the oscilloscope. void DsoWidget::updateZoom(bool enabled) { this->mainLayout->setRowStretch(9, enabled ? 1 : 0); this->zoomScope->setVisible(enabled); // Show time-/frequencybase and zoom factor if the magnified scope is shown this->markerLayout->setStretch(3, enabled ? 1 : 0); this->markerTimebaseLabel->setVisible(enabled); this->markerLayout->setStretch(4, enabled ? 1 : 0); this->markerFrequencybaseLabel->setVisible(enabled); if(enabled) this->updateMarkerDetails(); else this->markerInfoLabel->setText(tr("Marker 1/2")); this->repaint(); } /// \brief Prints analyzed data. void DsoWidget::dataAnalyzed() { for(int channel = 0; channel < this->settings->scope.voltage.count(); ++channel) { if(this->settings->scope.voltage[channel].used && this->dataAnalyzer->data(channel)) { // Amplitude string representation (4 significant digits) this->measurementAmplitudeLabel[channel]->setText(Helper::valueToString(this->dataAnalyzer->data(channel)->amplitude, Helper::UNIT_VOLTS, 4)); // Frequency string representation (5 significant digits) this->measurementFrequencyLabel[channel]->setText(Helper::valueToString(this->dataAnalyzer->data(channel)->frequency, Helper::UNIT_HERTZ, 5)); } } } /// \brief Handles valueChanged signal from the offset sliders. /// \param channel The channel whose offset was changed. /// \param value The new offset for the channel. void DsoWidget::updateOffset(int channel, double value) { if(channel < this->settings->scope.voltage.count()) { this->settings->scope.voltage[channel].offset = value; if(channel < (int) this->settings->scope.physicalChannels) this->adaptTriggerLevelSlider(channel); } else if(channel < this->settings->scope.voltage.count() * 2) this->settings->scope.spectrum[channel - this->settings->scope.voltage.count()].offset = value; emit offsetChanged(channel, value); } /// \brief Handles valueChanged signal from the triggerPosition slider. /// \param index The index of the slider. /// \param value The new triggerPosition in seconds relative to the first sample. void DsoWidget::updateTriggerPosition(int index, double value) { if(index != 0) return; this->settings->scope.trigger.position = value; this->updateTriggerDetails(); emit triggerPositionChanged(value * this->settings->scope.horizontal.timebase * DIVS_TIME); } /// \brief Handles valueChanged signal from the trigger level slider. /// \param channel The index of the slider. /// \param value The new trigger level. void DsoWidget::updateTriggerLevel(int channel, double value) { this->settings->scope.voltage[channel].trigger = value; this->updateTriggerDetails(); emit triggerLevelChanged(channel, value); } /// \brief Handles valueChanged signal from the marker slider. /// \param marker The index of the slider. /// \param value The new marker position. void DsoWidget::updateMarker(int marker, double value) { this->settings->scope.horizontal.marker[marker] = value; this->updateMarkerDetails(); emit markerChanged(marker, value); }