Feature/tinysa (#616)

* TinySA and PyQt6 fixes
pull/617/head
Holger Müller 2023-03-14 19:22:46 +01:00 zatwierdzone przez GitHub
rodzic b322d3dc09
commit dd2f5b8a5d
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
23 zmienionych plików z 176 dodań i 137 usunięć

1
.gitignore vendored
Wyświetl plik

@ -52,3 +52,4 @@ MANIFEST
.venv*/ .venv*/
.conda*/ .conda*/
.python-version .python-version
**/_version.py

Wyświetl plik

@ -1,33 +1,26 @@
.. role:: raw-html-m2r(raw) .. role:: raw-html-m2r(raw)
:format: html :format: html
.. image:: https://img.shields.io/github/v/release/NanoVNA-Saver/nanovna-saver.svg .. image:: https://img.shields.io/github/v/release/NanoVNA-Saver/nanovna-saver.svg
:target: https://github.com/NanoVNA-Saver/nanovna-saver/releases/latest :target: https://github.com/NanoVNA-Saver/nanovna-saver/releases/latest
:alt: Latest Release :alt: Latest Release
.. image:: https://img.shields.io/github/license/NanoVNA-Saver/nanovna-saver.svg .. image:: https://img.shields.io/github/license/NanoVNA-Saver/nanovna-saver.svg
:target: https://github.com/NanoVNA-Saver/nanovna-saver/blob/master/LICENSE.txt :target: https://github.com/NanoVNA-Saver/nanovna-saver/blob/master/LICENSE.txt
:alt: License :alt: License
.. image:: https://img.shields.io/github/downloads/NanoVNA-Saver/nanovna-saver/total.svg .. image:: https://img.shields.io/github/downloads/NanoVNA-Saver/nanovna-saver/total.svg
:target: https://github.com/NanoVNA-Saver/nanovna-saver/releases/ :target: https://github.com/NanoVNA-Saver/nanovna-saver/releases/
:alt: Downloads :alt: Downloads
.. image:: https://img.shields.io/github/downloads/NanoVNA-Saver/nanovna-saver/latest/total .. image:: https://img.shields.io/github/downloads/NanoVNA-Saver/nanovna-saver/latest/total
:target: https://github.com/NanoVNA-Saver/nanovna-saver/releases/latest :target: https://github.com/NanoVNA-Saver/nanovna-saver/releases/latest
:alt: GitHub Releases :alt: GitHub Releases
.. image:: https://img.shields.io/badge/paypal-donate-yellow.svg .. image:: https://img.shields.io/badge/paypal-donate-yellow.svg
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=T8KTGVDQF5K6E&item_name=NanoVNASaver+Development&currency_code=EUR&source=url :target: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=T8KTGVDQF5K6E&item_name=NanoVNASaver+Development&currency_code=EUR&source=url
:alt: Donate :alt: Donate
NanoVNASaver NanoVNASaver
============ ============
@ -57,6 +50,7 @@ Current features
* Reading data from a NanoVNA -- Compatible devices: NanoVNA, NanoVNA-H, * Reading data from a NanoVNA -- Compatible devices: NanoVNA, NanoVNA-H,
NanoVNA-H4, NanoVNA-F, AVNA via Teensy NanoVNA-H4, NanoVNA-F, AVNA via Teensy
* Reading data from a TinySA
* Splitting a frequency range into multiple segments to increase resolution * Splitting a frequency range into multiple segments to increase resolution
(tried up to >10k points) (tried up to >10k points)
* Averaging data for better results particularly at higher frequencies * Averaging data for better results particularly at higher frequencies
@ -189,6 +183,7 @@ Latest Changes
* Using PyQt6 * Using PyQt6
* Moved to PyScaffold project structure * Moved to PyScaffold project structure
* Fixed crash in resonance analysis * Fixed crash in resonance analysis
* Added TinySA readout and screenshot
Changes in 0.5.5 Changes in 0.5.5

Wyświetl plik

@ -1,12 +1,17 @@
[build-system] [build-system]
# AVOID CHANGING REQUIRES: IT WILL BE UPDATED BY PYSCAFFOLD! # AVOID CHANGING REQUIRES: IT WILL BE UPDATED BY PYSCAFFOLD!
requires = ["setuptools>=46.1.0", "setuptools_scm[toml]>=5"] requires = ["setuptools>=46.1.0", "setuptools_scm[toml]>=6.2"]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"
[NanoVNASaver]
dynamic = ["version"]
[tool.setuptools_scm] [tool.setuptools_scm]
# For smarter version schemes and other configuration options, # For smarter version schemes and other configuration options,
# check out https://github.com/pypa/setuptools_scm # check out https://github.com/pypa/setuptools_scm
version_scheme = "no-guess-dev" version_scheme = "no-guess-dev"
write_to = "src/NanoVNASaver/_version.py"
[tool.pytest.ini_options] [tool.pytest.ini_options]
pythonpath = [ pythonpath = [

Wyświetl plik

@ -3,3 +3,5 @@ PyQt6==5.15.9
numpy==1.24.2 numpy==1.24.2
scipy==1.10.1 scipy==1.10.1
Cython==0.29.33 Cython==0.29.33
setuptools==65.3.0
setuptools-scm==7.1.0

Wyświetl plik

@ -17,14 +17,16 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
VERSION = "0.6.0-pre" from setuptools_scm import get_version
version = get_version() # root='.', relative_to=__file__)
VERSION_URL = ( VERSION_URL = (
"https://raw.githubusercontent.com/" "https://raw.githubusercontent.com/"
"NanoVNA-Saver/nanovna-saver/master/NanoVNASaver/About.py" "NanoVNA-Saver/nanovna-saver/master/NanoVNASaver/About.py"
) )
INFO_URL = "https://github.com/NanoVNA-Saver/nanovna-saver" INFO_URL = "https://github.com/NanoVNA-Saver/nanovna-saver"
INFO = f"""NanoVNASaver {VERSION} INFO = f"""NanoVNASaver {version}
Copyright (C) 2019, 2020 Rune B. Broberg Copyright (C) 2019, 2020 Rune B. Broberg
Copyright (C) 2020ff NanoVNA-Saver Authors Copyright (C) 2020ff NanoVNA-Saver Authors

Wyświetl plik

@ -71,7 +71,7 @@ class PeakSearchAnalysis(SimplePeakSearchAnalysis):
# Having found the peaks, get the prominence data # Having found the peaks, get the prominence data
for i, p in np.ndenumerate(peaks): for i, p in np.ndenumerate(peaks):
logger.debug("Peak %i at %d", i, p) logger.debug("Peak %s at %s", i, p)
prominences = peak_prominences(data, peaks)[0] prominences = peak_prominences(data, peaks)[0]
logger.debug("%d prominences", len(prominences)) logger.debug("%d prominences", len(prominences))

Wyświetl plik

@ -219,16 +219,21 @@ class Chart(QtWidgets.QWidget):
if event.buttons() == Qt.MouseButton.MiddleButton: if event.buttons() == Qt.MouseButton.MiddleButton:
# Drag event # Drag event
event.accept() event.accept()
self.dragbox.move_x = event.x() self.dragbox.move_x = event.position().x()
self.dragbox.move_y = event.y() self.dragbox.move_y = event.position().y()
return return
if event.modifiers() == Qt.KeyboardModifier.ControlModifier: if event.modifiers() == Qt.KeyboardModifier.ControlModifier:
event.accept() event.accept()
self.dragbox.state = True self.dragbox.state = True
self.dragbox.pos_start = (event.x(), event.y()) self.dragbox.pos_start = (
event.position().x(),
event.position().y(),
)
return return
if event.modifiers() == Qt.KeyboardModifier.ShiftModifier: if event.modifiers() == Qt.KeyboardModifier.ShiftModifier:
self.draggedMarker = self.getNearestMarker(event.x(), event.y()) self.draggedMarker = self.getNearestMarker(
event.position().x(), event.position().y()
)
self.mouseMoveEvent(event) self.mouseMoveEvent(event)
def mouseReleaseEvent(self, a0: QtGui.QMouseEvent): def mouseReleaseEvent(self, a0: QtGui.QMouseEvent):

Wyświetl plik

@ -311,14 +311,15 @@ class FrequencyChart(Chart):
) )
if not selected: if not selected:
return return
text = text.replace("dB", "")
min_val = parse_value(text) min_val = parse_value(text)
yspan = abs(self.maxDisplayValue - self.minDisplayValue) yspan = abs(self.maxDisplayValue - self.minDisplayValue)
self.minDisplayValue = min_val self.minDisplayValue = min_val
if self.minDisplayValue >= self.maxDisplayValue: if self.minDisplayValue >= self.maxDisplayValue:
self.maxDisplayValue = self.minDisplayValue + yspan self.maxDisplayValue = self.minDisplayValue + yspan
# TODO: negativ logarythmical scale # TODO: negativ logarythmical scale
if self.logarithmicY and min_val <= 0: # if self.logarithmicY and min_val <= 0:
self.minDisplayValue = 0.01 # self.minDisplayValue = 0.01
self.fixedValues = True self.fixedValues = True
self.update() self.update()
@ -329,6 +330,7 @@ class FrequencyChart(Chart):
"Set maximum value", "Set maximum value",
text=format_y_axis(self.maxDisplayValue, self.name_unit), text=format_y_axis(self.maxDisplayValue, self.name_unit),
) )
text = text.replace("dB", "")
if not selected: if not selected:
return return
max_val = parse_value(text) max_val = parse_value(text)
@ -627,7 +629,7 @@ class FrequencyChart(Chart):
ticks = math.floor(self.dim.width / 100) ticks = math.floor(self.dim.width / 100)
# try to adapt format to span # try to adapt format to span
if int(fspan / ticks / self.fstart * 10000) > 2: if self.fstart == 0 or int(fspan / ticks / self.fstart * 10000) > 2:
my_format_frequency = format_frequency_chart my_format_frequency = format_frequency_chart
else: else:
my_format_frequency = format_frequency_chart_2 my_format_frequency = format_frequency_chart_2

Wyświetl plik

@ -97,7 +97,7 @@ class SerialControl(Control):
logger.error("Unable to connect to VNA: %s", exc) logger.error("Unable to connect to VNA: %s", exc)
self.app.vna.validateInput = self.app.settings.value( self.app.vna.validateInput = self.app.settings.value(
"SerialInputValidation", True, bool "SerialInputValidation", False, bool
) )
# connected # connected

Wyświetl plik

@ -34,7 +34,7 @@ from NanoVNASaver.Hardware.NanoVNA_F_V2 import NanoVNA_F_V2
from NanoVNASaver.Hardware.NanoVNA_H import NanoVNA_H from NanoVNASaver.Hardware.NanoVNA_H import NanoVNA_H
from NanoVNASaver.Hardware.NanoVNA_H4 import NanoVNA_H4 from NanoVNASaver.Hardware.NanoVNA_H4 import NanoVNA_H4
from NanoVNASaver.Hardware.NanoVNA_V2 import NanoVNA_V2 from NanoVNASaver.Hardware.NanoVNA_V2 import NanoVNA_V2
from NanoVNASaver.Hardware.TinySA import TinySA from NanoVNASaver.Hardware.TinySA import TinySA, TinySA_Ultra
from NanoVNASaver.Hardware.Serial import drain_serial, Interface from NanoVNASaver.Hardware.Serial import drain_serial, Interface
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -59,6 +59,7 @@ NAME2DEVICE = {
"F": NanoVNA_F, "F": NanoVNA_F,
"NanoVNA": NanoVNA, "NanoVNA": NanoVNA,
"tinySA": TinySA, "tinySA": TinySA,
"tinySA_Ultra": TinySA_Ultra,
"Unknown": NanoVNA, "Unknown": NanoVNA,
} }
@ -152,6 +153,7 @@ def get_comment(iface: Interface) -> str:
("NanoVNA-F_V2", "F_V2"), ("NanoVNA-F_V2", "F_V2"),
("NanoVNA-F", "F"), ("NanoVNA-F", "F"),
("NanoVNA", "NanoVNA"), ("NanoVNA", "NanoVNA"),
("tinySA4", "tinySA_Ultra"),
("tinySA", "tinySA"), ("tinySA", "tinySA"),
): ):
if info.find(search) >= 0: if info.find(search) >= 0:

Wyświetl plik

@ -22,7 +22,7 @@ from typing import List
import serial import serial
import numpy as np import numpy as np
from PyQt6 import QtGui from PyQt6.QtGui import QImage, QPixmap
from NanoVNASaver.Hardware.Serial import drain_serial, Interface from NanoVNASaver.Hardware.Serial import drain_serial, Interface
from NanoVNASaver.Hardware.VNA import VNA from NanoVNASaver.Hardware.VNA import VNA
@ -82,23 +82,23 @@ class NanoVNA(VNA):
+ ((rgb_array & 0x001F) << 3) + ((rgb_array & 0x001F) << 3)
) )
def getScreenshot(self) -> QtGui.QPixmap: def getScreenshot(self) -> QPixmap:
logger.debug("Capturing screenshot...") logger.debug("Capturing screenshot...")
if not self.connected(): if not self.connected():
return QtGui.QPixmap() return QPixmap()
try: try:
rgba_array = self._convert_data(self._capture_data()) rgba_array = self._convert_data(self._capture_data())
image = QtGui.QImage( image = QImage(
rgba_array, rgba_array,
self.screenwidth, self.screenwidth,
self.screenheight, self.screenheight,
QtGui.QImage.Format_ARGB32, QImage.Format_ARGB32,
) )
logger.debug("Captured screenshot") logger.debug("Captured screenshot")
return QtGui.QPixmap(image) return QPixmap(image)
except serial.SerialException as exc: except serial.SerialException as exc:
logger.exception("Exception while capturing screenshot: %s", exc) logger.exception("Exception while capturing screenshot: %s", exc)
return QtGui.QPixmap() return QPixmap()
def resetSweep(self, start: int, stop: int): def resetSweep(self, start: int, stop: int):
list(self.exec_command(f"sweep {start} {stop} {self.datapoints}")) list(self.exec_command(f"sweep {start} {stop} {self.datapoints}"))

Wyświetl plik

@ -19,7 +19,7 @@
import logging import logging
import serial import serial
from PyQt6 import QtGui from PyQt6.QtGui import QImage, QPixmap
from NanoVNASaver.Hardware.NanoVNA import NanoVNA from NanoVNASaver.Hardware.NanoVNA import NanoVNA
from NanoVNASaver.Hardware.Serial import Interface from NanoVNASaver.Hardware.Serial import Interface
@ -36,20 +36,20 @@ class NanoVNA_F_V2(NanoVNA):
super().__init__(iface) super().__init__(iface)
self.sweep_max_freq_Hz = 3e9 self.sweep_max_freq_Hz = 3e9
def getScreenshot(self) -> QtGui.QPixmap: def getScreenshot(self) -> QPixmap:
logger.debug("Capturing screenshot...") logger.debug("Capturing screenshot...")
if not self.connected(): if not self.connected():
return QtGui.QPixmap() return QPixmap()
try: try:
rgba_array = self._capture_data() rgba_array = self._capture_data()
image = QtGui.QImage( image = QImage(
rgba_array, rgba_array,
self.screenwidth, self.screenwidth,
self.screenheight, self.screenheight,
QtGui.QImage.Format_RGB16, QImage.Format.Format_RGB16,
) )
logger.debug("Captured screenshot") logger.debug("Captured screenshot")
return QtGui.QPixmap(image) return QPixmap(image)
except serial.SerialException as exc: except serial.SerialException as exc:
logger.exception("Exception while capturing screenshot: %s", exc) logger.exception("Exception while capturing screenshot: %s", exc)
return QtGui.QPixmap() return QPixmap()

Wyświetl plik

@ -22,7 +22,7 @@ from typing import List
import serial import serial
import numpy as np import numpy as np
from PyQt6 import QtGui from PyQt6.QtGui import QImage, QPixmap
from NanoVNASaver.Hardware.Serial import drain_serial, Interface from NanoVNASaver.Hardware.Serial import drain_serial, Interface
from NanoVNASaver.Hardware.VNA import VNA from NanoVNASaver.Hardware.VNA import VNA
@ -43,6 +43,7 @@ class TinySA(VNA):
self.start, self.stop = self._get_running_frequencies() self.start, self.stop = self._get_running_frequencies()
self.sweep_max_freq_Hz = 950e6 self.sweep_max_freq_Hz = 950e6
self._sweepdata = [] self._sweepdata = []
self.validateInput = False
def _get_running_frequencies(self): def _get_running_frequencies(self):
logger.debug("Reading values: frequencies") logger.debug("Reading values: frequencies")
@ -81,23 +82,23 @@ class TinySA(VNA):
+ ((rgb_array & 0x001F) << 3) + ((rgb_array & 0x001F) << 3)
) )
def getScreenshot(self) -> QtGui.QPixmap: def getScreenshot(self) -> QPixmap:
logger.debug("Capturing screenshot...") logger.debug("Capturing screenshot...")
if not self.connected(): if not self.connected():
return QtGui.QPixmap() return QPixmap()
try: try:
rgba_array = self._convert_data(self._capture_data()) rgba_array = self._convert_data(self._capture_data())
image = QtGui.QImage( image = QImage(
rgba_array, rgba_array,
self.screenwidth, self.screenwidth,
self.screenheight, self.screenheight,
QtGui.QImage.Format_ARGB32, QImage.Format.Format_ARGB32,
) )
logger.debug("Captured screenshot") logger.debug("Captured screenshot")
return QtGui.QPixmap(image) return QPixmap(image)
except serial.SerialException as exc: except serial.SerialException as exc:
logger.exception("Exception while capturing screenshot: %s", exc) logger.exception("Exception while capturing screenshot: %s", exc)
return QtGui.QPixmap() return QPixmap()
def resetSweep(self, start: int, stop: int): def resetSweep(self, start: int, stop: int):
return return
@ -113,9 +114,32 @@ class TinySA(VNA):
return [int(line) for line in self.exec_command("frequencies")] return [int(line) for line in self.exec_command("frequencies")]
def readValues(self, value) -> List[str]: def readValues(self, value) -> List[str]:
def conv2float(data: str) -> float:
try:
return 10 ** (float(data.strip()) / 20)
except ValueError:
return 0.0
logger.debug("Read: %s", value) logger.debug("Read: %s", value)
if value == "data 0": if value == "data 0":
self._sweepdata = [ self._sweepdata = [
f"0 {line.strip()}" for line in self.exec_command("data") f"{conv2float(line)} 0.0"
for line in self.exec_command("data 0")
] ]
return self._sweepdata return self._sweepdata
class TinySA_Ultra(TinySA):
name = "tinySA Ultra"
screenwidth = 480
screenheight = 320
valid_datapoints = (450, 51, 101, 145, 290)
def __init__(self, iface: Interface):
super().__init__(iface)
self.features = {"Screenshots", "Customizable data points"}
logger.debug("Setting initial start,stop")
self.start, self.stop = self._get_running_frequencies()
self.sweep_max_freq_Hz = 5.4e9
self._sweepdata = []
self.validateInput = False

Wyświetl plik

@ -33,13 +33,16 @@ class FrequencyInputWidget(QtWidgets.QLineEdit):
class MarkerFrequencyInputWidget(FrequencyInputWidget): class MarkerFrequencyInputWidget(FrequencyInputWidget):
def keyPressEvent(self, a0: QtGui.QKeyEvent) -> None: def keyPressEvent(self, a0: QtGui.QKeyEvent) -> None:
if a0.type() == QtCore.QEvent.KeyPress: if a0.type() == QtGui.QKeyEvent.Type.KeyPress:
if a0.key() == QtCore.Qt.Key_Up and self.nextFrequency != -1: if a0.key() == QtCore.Qt.Key.Key_Up and self.nextFrequency != -1:
a0.accept() a0.accept()
self.setText(str(self.nextFrequency)) self.setText(str(self.nextFrequency))
self.editingFinished.emit() # self.text()) self.editingFinished.emit() # self.text())
return return
if a0.key() == QtCore.Qt.Key_Down and self.previousFrequency != -1: if (
a0.key() == QtCore.Qt.Key.Key_Down
and self.previousFrequency != -1
):
a0.accept() a0.accept()
self.setText(str(self.previousFrequency)) self.setText(str(self.previousFrequency))
self.editingFinished.emit() # self.text()) self.editingFinished.emit() # self.text())

Wyświetl plik

@ -101,6 +101,6 @@ class Value:
] ]
self.freq = s11[1].freq self.freq = s11[1].freq
self.s11 = s11[index - 1: index + 2] self.s11 = s11[index - 1 : index + 2]
if s21: if s21:
self.s21 = s21[index - 1: index + 2] self.s21 = s21[index - 1 : index + 2]

Wyświetl plik

@ -23,6 +23,7 @@ import threading
from time import strftime, localtime from time import strftime, localtime
from PyQt6 import QtWidgets, QtCore, QtGui from PyQt6 import QtWidgets, QtCore, QtGui
from PyQt6.QtCore import QObject
from PyQt6.QtWidgets import QWidget from PyQt6.QtWidgets import QWidget
from NanoVNASaver import Defaults from NanoVNASaver import Defaults
@ -74,18 +75,22 @@ from .SweepWorker import SweepWorker
from .Settings.Bands import BandsModel from .Settings.Bands import BandsModel
from .Settings.Sweep import Sweep from .Settings.Sweep import Sweep
from .Touchstone import Touchstone from .Touchstone import Touchstone
from .About import VERSION from .About import version
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Communicate(QObject):
data_available = QtCore.pyqtSignal()
class NanoVNASaver(QWidget): class NanoVNASaver(QWidget):
version = VERSION version = version
dataAvailable = QtCore.pyqtSignal()
scaleFactor = 1 scaleFactor = 1
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.communicate = Communicate()
self.s21att = 0.0 self.s21att = 0.0
if getattr(sys, "frozen", False): if getattr(sys, "frozen", False):
logger.debug("Running from pyinstaller bundle") logger.debug("Running from pyinstaller bundle")
@ -186,6 +191,7 @@ class NanoVNASaver(QWidget):
"smith": SmithChart("S11 Smith Chart"), "smith": SmithChart("S11 Smith Chart"),
"s_parameter": SParameterChart("S11 Real/Imaginary"), "s_parameter": SParameterChart("S11 Real/Imaginary"),
"vswr": VSWRChart("S11 VSWR"), "vswr": VSWRChart("S11 VSWR"),
"sa_dbm": LogMagChart("Signal Analyser dBm"),
}, },
"s21": { "s21": {
"group_delay": GroupDelayChart( "group_delay": GroupDelayChart(
@ -589,7 +595,7 @@ class NanoVNASaver(QWidget):
self.s21_max_gain_label.setText("") self.s21_max_gain_label.setText("")
self.updateTitle() self.updateTitle()
self.dataAvailable.emit() self.communicate.data_available.emit()
def sweepFinished(self): def sweepFinished(self):
self._sweep_control(start=False) self._sweep_control(start=False)

Wyświetl plik

@ -54,7 +54,7 @@ class Datapoint(NamedTuple):
@property @property
def wavelength(self) -> float: def wavelength(self) -> float:
return 299792458 / self.freq return 299792458 / self.freq if self.freq else math.inf
def impedance(self, ref_impedance: float = 50) -> complex: def impedance(self, ref_impedance: float = 50) -> complex:
return gamma_to_impedance(self.z, ref_impedance) return gamma_to_impedance(self.z, ref_impedance)

Wyświetl plik

@ -101,7 +101,7 @@ class Sweep:
if ( if (
self.segments <= 0 self.segments <= 0
or self.points <= 0 or self.points <= 0
or self.start <= 0 or self.start < 0
or self.end <= 0 or self.end <= 0
or self.stepsize < 1 or self.stepsize < 1
): ):

Wyświetl plik

@ -128,9 +128,9 @@ class AnalysisWindow(QtWidgets.QWidget):
self.update() self.update()
def toggleAutomaticRun(self, state: Qt.CheckState): def toggleAutomaticRun(self, state: Qt.CheckState):
if state == Qt.CheckState.Checked: if state == Qt.CheckState.Checked.value:
self.analysis_list.setDisabled(True) self.analysis_list.setDisabled(True)
self.app.dataAvailable.connect(self.runAnalysis) self.app.communicate.data_available.connect(self.runAnalysis)
else: else:
self.analysis_list.setDisabled(False) self.analysis_list.setDisabled(False)
self.app.dataAvailable.disconnect(self.runAnalysis) self.app.communicate.data_available.disconnect(self.runAnalysis)

Wyświetl plik

@ -19,8 +19,8 @@
import logging import logging
from typing import List from typing import List
from PyQt6 import QtWidgets, QtCore, QtGui from PyQt6 import QtWidgets, QtCore
from PyQt6.QtGui import QColorConstants from PyQt6.QtGui import QColor, QColorConstants, QPalette, QShortcut
from NanoVNASaver import Defaults from NanoVNASaver import Defaults
from NanoVNASaver.Charts.Chart import Chart, ChartColors from NanoVNASaver.Charts.Chart import Chart, ChartColors
@ -42,7 +42,7 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
self.marker_window = MarkerSettingsWindow(self.app) self.marker_window = MarkerSettingsWindow(self.app)
self.callback_params = {} self.callback_params = {}
QtGui.QShortcut(QtCore.Qt.Key.Key_Escape, self, self.hide) QShortcut(QtCore.Qt.Key.Key_Escape, self, self.hide)
layout = QtWidgets.QHBoxLayout() layout = QtWidgets.QHBoxLayout()
make_scrollable(self, layout) make_scrollable(self, layout)
@ -273,18 +273,60 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
charts_box = QtWidgets.QGroupBox("Displayed charts") charts_box = QtWidgets.QGroupBox("Displayed charts")
charts_layout = QtWidgets.QGridLayout(charts_box) charts_layout = QtWidgets.QGridLayout(charts_box)
# selections = ["S11 Smith chart",
# "S11 LogMag",
# "S11 VSWR",
# "S11 Phase",
# "S21 Smith chart",
# "S21 LogMag",
# "S21 Phase",
# "None"]
selections = [c.name for c in self.app.selectable_charts] selections = [c.name for c in self.app.selectable_charts]
selections.append("None") selections.append("None")
self._chart_selection(charts_layout, selections)
chart_colors = ChartColors()
Chart.color.background = self.app.settings.value(
"BackgroundColor",
defaultValue=chart_colors.background,
type=QColor,
)
Chart.color.foreground = self.app.settings.value(
"ForegroundColor",
defaultValue=chart_colors.foreground,
type=QColor,
)
Chart.color.text = self.app.settings.value(
"TextColor", defaultValue=chart_colors.text, type=QColor
)
self.bandsColor = self.app.settings.value(
"BandsColor", defaultValue=chart_colors.bands, type=QColor
)
self.app.bands.color = Chart.color.bands
Chart.color.swr = self.app.settings.value(
"VSWRColor", defaultValue=chart_colors.swr, type=QColor
)
self.dark_mode_option.setChecked(Defaults.cfg.gui.dark_mode)
self.show_lines_option.setChecked(Defaults.cfg.chart.show_lines)
self.show_marker_number_option.setChecked(
Defaults.cfg.chart.marker_label
)
self.filled_marker_option.setChecked(Defaults.cfg.chart.marker_filled)
if self.app.settings.value(
"UseCustomColors", defaultValue=False, type=bool
):
self.dark_mode_option.setDisabled(True)
self.dark_mode_option.setChecked(False)
self.use_custom_colors.setChecked(True)
left_layout.addWidget(display_options_box)
left_layout.addWidget(charts_box)
left_layout.addWidget(markers_box)
left_layout.addStretch(1)
right_layout.addWidget(color_options_box)
right_layout.addWidget(font_options_box)
right_layout.addWidget(bands_box)
right_layout.addWidget(vswr_marker_box)
right_layout.addStretch(1)
self.update()
def _chart_selection(self, charts_layout, selections):
chart00_selection = QtWidgets.QComboBox() chart00_selection = QtWidgets.QComboBox()
chart00_selection.setMinimumHeight(30) chart00_selection.setMinimumHeight(30)
chart00_selection.addItems(selections) chart00_selection.addItems(selections)
@ -370,54 +412,6 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
self.changeChart(1, 1, chart11_selection.currentText()) self.changeChart(1, 1, chart11_selection.currentText())
self.changeChart(1, 2, chart12_selection.currentText()) self.changeChart(1, 2, chart12_selection.currentText())
chart_colors = ChartColors()
Chart.color.background = self.app.settings.value(
"BackgroundColor",
defaultValue=chart_colors.background,
type=QtGui.QColor,
)
Chart.color.foreground = self.app.settings.value(
"ForegroundColor",
defaultValue=chart_colors.foreground,
type=QtGui.QColor,
)
Chart.color.text = self.app.settings.value(
"TextColor", defaultValue=chart_colors.text, type=QtGui.QColor
)
self.bandsColor = self.app.settings.value(
"BandsColor", defaultValue=chart_colors.bands, type=QtGui.QColor
)
self.app.bands.color = Chart.color.bands
Chart.color.swr = self.app.settings.value(
"VSWRColor", defaultValue=chart_colors.swr, type=QtGui.QColor
)
self.dark_mode_option.setChecked(Defaults.cfg.gui.dark_mode)
self.show_lines_option.setChecked(Defaults.cfg.chart.show_lines)
self.show_marker_number_option.setChecked(
Defaults.cfg.chart.marker_label
)
self.filled_marker_option.setChecked(Defaults.cfg.chart.marker_filled)
if self.app.settings.value(
"UseCustomColors", defaultValue=False, type=bool
):
self.dark_mode_option.setDisabled(True)
self.dark_mode_option.setChecked(False)
self.use_custom_colors.setChecked(True)
left_layout.addWidget(display_options_box)
left_layout.addWidget(charts_box)
left_layout.addWidget(markers_box)
left_layout.addStretch(1)
right_layout.addWidget(color_options_box)
right_layout.addWidget(font_options_box)
right_layout.addWidget(bands_box)
right_layout.addWidget(vswr_marker_box)
right_layout.addStretch(1)
self.update()
def trace_colors(self, layout: QtWidgets.QLayout): def trace_colors(self, layout: QtWidgets.QLayout):
for setting, name, attr in ( for setting, name, attr in (
("SweepColor", "Sweep color", "sweep"), ("SweepColor", "Sweep color", "sweep"),
@ -447,15 +441,13 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
cp.setMinimumHeight(20) cp.setMinimumHeight(20)
default = getattr(Chart.color, attr) default = getattr(Chart.color, attr)
color = self.app.settings.value( color = self.app.settings.value(
setting, defaultValue=default, type=QtGui.QColor setting, defaultValue=default, type=QColor
) )
setattr(Chart.color, attr, color) setattr(Chart.color, attr, color)
self.callback_params[cp] = (setting, attr) self.callback_params[cp] = (setting, attr)
cp.clicked.connect(self.setColor) cp.clicked.connect(self.setColor)
p = cp.palette() p = cp.palette()
p.setColor( p.setColor(QPalette.ColorRole.ButtonText, getattr(Chart.color, attr))
QtGui.QPalette.ColorRole.ButtonText, getattr(Chart.color, attr)
)
cp.setPalette(p) cp.setPalette(p)
return cp return cp
@ -529,13 +521,13 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
def changeDarkMode(self): def changeDarkMode(self):
state = self.dark_mode_option.isChecked() state = self.dark_mode_option.isChecked()
Defaults.cfg.gui.dark_mode = bool(state) Defaults.cfg.gui.dark_mode = bool(state)
Chart.color.foreground = QtGui.QColor(QColorConstants.LightGray) Chart.color.foreground = QColor(QColorConstants.LightGray)
if state: if state:
Chart.color.background = QtGui.QColor(QColorConstants.Black) Chart.color.background = QColor(QColorConstants.Black)
Chart.color.text = QtGui.QColor(QColorConstants.White) Chart.color.text = QColor(QColorConstants.White)
else: else:
Chart.color.background = QtGui.QColor(QColorConstants.White) Chart.color.background = QColor(QColorConstants.White)
Chart.color.text = QtGui.QColor(QColorConstants.Black) Chart.color.text = QColor(QColorConstants.Black)
Chart.color.swr = Chart.color.swr Chart.color.swr = Chart.color.swr
self.updateCharts() self.updateCharts()
@ -561,7 +553,7 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
return return
palette = sender.palette() palette = sender.palette()
palette.setColor(QtGui.QPalette.ButtonText, color) palette.setColor(QPalette.ButtonText, color)
sender.setPalette(palette) sender.setPalette(palette)
self.changeSetting(setting, color) self.changeSetting(setting, color)

Wyświetl plik

@ -62,8 +62,8 @@ class ScreenshotWindow(QtWidgets.QLabel):
self.setPixmap( self.setPixmap(
self.pix.scaled( self.pix.scaled(
self.size(), self.size(),
QtCore.Qt.KeepAspectRatio, QtCore.Qt.AspectRatioMode.KeepAspectRatio,
QtCore.Qt.FastTransformation, QtCore.Qt.TransformationMode.FastTransformation,
) )
) )
w, h = pixmap.width(), pixmap.height() w, h = pixmap.width(), pixmap.height()
@ -104,8 +104,8 @@ class ScreenshotWindow(QtWidgets.QLabel):
self.setPixmap( self.setPixmap(
self.pix.scaled( self.pix.scaled(
self.size(), self.size(),
QtCore.Qt.KeepAspectRatio, QtCore.Qt.AspectRatioMode.KeepAspectRatio,
QtCore.Qt.FastTransformation, QtCore.Qt.TransformationMode.FastTransformation,
) )
) )

Wyświetl plik

@ -32,7 +32,7 @@ import sys
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
from NanoVNASaver.About import VERSION, INFO from NanoVNASaver.About import version, INFO
from NanoVNASaver.NanoVNASaver import NanoVNASaver from NanoVNASaver.NanoVNASaver import NanoVNASaver
from NanoVNASaver.Touchstone import Touchstone from NanoVNASaver.Touchstone import Touchstone
@ -59,7 +59,7 @@ def main():
help="Touchstone file to load as reference for off" " device usage", help="Touchstone file to load as reference for off" " device usage",
) )
parser.add_argument( parser.add_argument(
"--version", action="version", version=f"NanoVNASaver {VERSION}" "--version", action="version", version=f"NanoVNASaver {version}"
) )
args = parser.parse_args() args = parser.parse_args()

Wyświetl plik

@ -36,12 +36,12 @@ class TestCases(unittest.TestCase):
def setUp(self) -> None: def setUp(self) -> None:
self.settings_1 = CFG.AppSettings( self.settings_1 = CFG.AppSettings(
CFG.QSettings.IniFormat, CFG.QSettings.Format.IniFormat,
CFG.QSettings.UserScope, CFG.QSettings.Scope.UserScope,
"NanoVNASaver", "Test_1") "NanoVNASaver", "Test_1")
self.settings_2 = CFG.AppSettings( self.settings_2 = CFG.AppSettings(
CFG.QSettings.IniFormat, CFG.QSettings.Format.IniFormat,
CFG.QSettings.UserScope, CFG.QSettings.Scope.UserScope,
"NanoVNASaver", "Test_2") "NanoVNASaver", "Test_2")
self.config_1 = TConfig() self.config_1 = TConfig()
self.config_2 = TConfig( self.config_2 = TConfig(