# NanoVNASaver # # A python program to view and export Touchstone data from a NanoVNA # Copyright (C) 2019, 2020 Rune B. Broberg # Copyright (C) 2020,2021 NanoVNA-Saver Authors # # 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 . import logging from PyQt5 import QtWidgets, QtCore from NanoVNASaver.Windows.Defaults import make_scrollable from NanoVNASaver.Windows.Screenshot import ScreenshotWindow logger = logging.getLogger(__name__) class DeviceSettingsWindow(QtWidgets.QWidget): def __init__(self, app: QtWidgets.QWidget): super().__init__() self.app = app self.setWindowTitle("Device settings") self.setWindowIcon(self.app.icon) QtWidgets.QShortcut(QtCore.Qt.Key_Escape, self, self.hide) self.label = { "status": QtWidgets.QLabel("Not connected."), "firmware": QtWidgets.QLabel("Not connected."), "calibration": QtWidgets.QLabel("Not connected."), } top_layout = QtWidgets.QHBoxLayout() left_layout = QtWidgets.QVBoxLayout() right_layout = QtWidgets.QVBoxLayout() top_layout.addLayout(left_layout) top_layout.addLayout(right_layout) make_scrollable(self, top_layout) status_box = QtWidgets.QGroupBox("Status") status_layout = QtWidgets.QFormLayout(status_box) status_layout.addRow("Status:", self.label["status"]) status_layout.addRow("Firmware:", self.label["firmware"]) status_layout.addRow("Calibration:", self.label["calibration"]) status_layout.addRow(QtWidgets.QLabel("Features:")) self.featureList = QtWidgets.QListWidget() status_layout.addRow(self.featureList) settings_box = QtWidgets.QGroupBox("Settings") settings_layout = QtWidgets.QFormLayout(settings_box) self.chkValidateInputData = QtWidgets.QCheckBox( "Validate received data" ) validate_input = self.app.settings.value( "SerialInputValidation", False, bool ) self.chkValidateInputData.setChecked(validate_input) self.chkValidateInputData.stateChanged.connect(self.updateValidation) settings_layout.addRow("Validation", self.chkValidateInputData) control_layout = QtWidgets.QHBoxLayout() self.btnRefresh = QtWidgets.QPushButton("Refresh") self.btnRefresh.clicked.connect(self.updateFields) control_layout.addWidget(self.btnRefresh) self.screenshotWindow = ScreenshotWindow() self.btnCaptureScreenshot = QtWidgets.QPushButton("Screenshot") self.btnCaptureScreenshot.clicked.connect(self.captureScreenshot) control_layout.addWidget(self.btnCaptureScreenshot) left_layout.addWidget(status_box) left_layout.addLayout(control_layout) self.datapoints = QtWidgets.QComboBox() self.datapoints.addItem(str(self.app.vna.datapoints)) self.datapoints.currentIndexChanged.connect(self.updateNrDatapoints) self.bandwidth = QtWidgets.QComboBox() self.bandwidth.addItem(str(self.app.vna.bandwidth)) self.bandwidth.currentIndexChanged.connect(self.updateBandwidth) form_layout = QtWidgets.QFormLayout() form_layout.addRow(QtWidgets.QLabel("Datapoints"), self.datapoints) form_layout.addRow(QtWidgets.QLabel("Bandwidth"), self.bandwidth) right_layout.addWidget(settings_box) settings_layout.addRow(form_layout) def _set_datapoint_index(self, dpoints: int): self.datapoints.setCurrentIndex(self.datapoints.findText(str(dpoints))) def _set_bandwidth_index(self, bw: int): self.bandwidth.setCurrentIndex(self.bandwidth.findText(str(bw))) def show(self): super().show() self.updateFields() def updateFields(self): if not self.app.vna.connected(): self.label["status"].setText("Not connected.") self.label["firmware"].setText("Not connected.") self.label["calibration"].setText("Not connected.") self.featureList.clear() self.btnCaptureScreenshot.setDisabled(True) return self.label["status"].setText(f"Connected to {self.app.vna.name}.") self.label["firmware"].setText( f"{self.app.vna.name} v{self.app.vna.version}" ) if self.app.worker.running: self.label["calibration"].setText("(Sweep running)") else: self.label["calibration"].setText(self.app.vna.getCalibration()) self.featureList.clear() features = self.app.vna.getFeatures() for item in features: self.featureList.addItem(item) self.btnCaptureScreenshot.setDisabled("Screenshots" not in features) if "Customizable data points" in features: self.datapoints.clear() cur_dps = self.app.vna.datapoints for d in sorted(self.app.vna.valid_datapoints): self.datapoints.addItem(str(d)) self._set_datapoint_index(cur_dps) self.datapoints.setDisabled(False) else: self.datapoints.setDisabled(True) if "Bandwidth" in features: self.bandwidth.clear() cur_bw = self.app.vna.bandwidth for d in sorted(self.app.vna.get_bandwidths()): self.bandwidth.addItem(str(d)) self._set_bandwidth_index(cur_bw) self.bandwidth.setDisabled(False) else: self.bandwidth.setDisabled(True) def updateValidation(self, validate_data: bool): self.app.vna.validateInput = validate_data self.app.settings.setValue("SerialInputValidation", validate_data) def captureScreenshot(self): if not self.app.worker.running: pixmap = self.app.vna.getScreenshot() self.screenshotWindow.setScreenshot(pixmap) self.screenshotWindow.show() # TODO: Tell the user no screenshots while sweep is running? # TODO: Consider having a list of widgets that want to be # disabled when a sweep is running? def updateNrDatapoints(self, i): if i < 0 or self.app.worker.running: return logger.debug("DP: %s", self.datapoints.itemText(i)) self.app.vna.datapoints = int(self.datapoints.itemText(i)) with self.app.sweep.lock: self.app.sweep.points = self.app.vna.datapoints self.app.sweep_control.update_step_size() def updateBandwidth(self, i): if i < 0 or self.app.worker.running: return logger.debug("Bandwidth: %s", self.bandwidth.itemText(i)) self.app.vna.set_bandwidth(int(self.bandwidth.itemText(i)))