diff --git a/PKGBUILD b/PKGBUILD index 2a3c938..bf9ddea 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Michal Krenek (Mikos) pkgname=qspectrumanalyzer -pkgver=1.1.1 +pkgver=1.2.0 pkgrel=1 pkgdesc="Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)" arch=('any') @@ -8,6 +8,7 @@ url="https://github.com/xmikos/qspectrumanalyzer" license=('GPL3') depends=('python-pyqt4' 'python-pyqtgraph' 'rtl-sdr') makedepends=('python-setuptools') +optdepends=('rtl_power_fftw-git: alternative rtl_power implementation using FFTW library') source=(https://github.com/xmikos/qspectrumanalyzer/archive/v$pkgver.tar.gz) build() { diff --git a/qspectrumanalyzer.desktop b/qspectrumanalyzer.desktop index 732ca5b..57dd62a 100644 --- a/qspectrumanalyzer.desktop +++ b/qspectrumanalyzer.desktop @@ -1,6 +1,6 @@ [Desktop Entry] Encoding=UTF-8 -Version=1.1.1 +Version=1.2.0 Name=QSpectrumAnalyzer GenericName=Spectrum analyzer Comment=Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph) diff --git a/qspectrumanalyzer/__main__.py b/qspectrumanalyzer/__main__.py index 28768ee..bb2664e 100755 --- a/qspectrumanalyzer/__main__.py +++ b/qspectrumanalyzer/__main__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -import sys, csv, subprocess, signal +import sys, subprocess, signal, math, time, pprint import numpy as np import pyqtgraph as pg @@ -28,21 +28,36 @@ class QSpectrumAnalyzerSettings(QtGui.QDialog, Ui_QSpectrumAnalyzerSettings): # Load settings settings = QtCore.QSettings() - self.rtlPowerExecutableEdit.setText(str(settings.value("rtl_power_executable") or "rtl_power")) + self.executableEdit.setText(str(settings.value("rtl_power_executable") or "rtl_power")) self.waterfallHistorySizeSpinBox.setValue(int(settings.value("waterfall_history_size") or 100)) + self.sampleRateSpinBox.setValue(int(settings.value("sample_rate") or 2560000)) + + backend = str(settings.value("backend") or "rtl_power") + i = self.backendComboBox.findText(backend) + if i == -1: + self.backendComboBox.setCurrentIndex(0) + else: + self.backendComboBox.setCurrentIndex(i) @QtCore.pyqtSlot() - def on_rtlPowerExecutableButton_clicked(self): + def on_executableButton_clicked(self): """Open file dialog when button is clicked""" - filename = QtGui.QFileDialog.getOpenFileName(self, "QSpectrumAnalyzer - rtl_power executable") + filename = QtGui.QFileDialog.getOpenFileName(self, "QSpectrumAnalyzer - executable") if filename: - self.rtlPowerExecutableEdit.setText(filename) + self.executableEdit.setText(filename) + + @QtCore.pyqtSlot(str) + def on_backendComboBox_currentIndexChanged(self, text): + """Change executable when backend is changed""" + self.executableEdit.setText(text) def accept(self): """Save settings when dialog is accepted""" settings = QtCore.QSettings() - settings.setValue("rtl_power_executable", self.rtlPowerExecutableEdit.text()) + settings.setValue("rtl_power_executable", self.executableEdit.text()) settings.setValue("waterfall_history_size", self.waterfallHistorySizeSpinBox.value()) + settings.setValue("sample_rate", self.sampleRateSpinBox.value()) + settings.setValue("backend", self.backendComboBox.currentText()) QtGui.QDialog.accept(self) @@ -56,10 +71,9 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin # Setup rtl_power thread and connect signals self.waterfall_history_size = 100 self.datacounter = 0 - self.rtl_power_thread = RtlPowerThread() - self.rtl_power_thread.dataUpdated.connect(self.update_data) - self.rtl_power_thread.rtlPowerStarted.connect(self.update_buttons) - self.rtl_power_thread.rtlPowerStopped.connect(self.update_buttons) + self.datatimestamp = 0 + self.rtl_power_thread = None + self.setup_rtl_power_thread() # Update UI self.create_plot() @@ -67,6 +81,22 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin self.update_buttons() self.load_settings() + def setup_rtl_power_thread(self): + """Create rtl_power_thread and connect signals to slots""" + if self.rtl_power_thread: + self.stop() + + settings = QtCore.QSettings() + backend = str(settings.value("backend") or "rtl_power") + if backend == "rtl_power_fftw": + self.rtl_power_thread = RtlPowerFftwThread() + else: + self.rtl_power_thread = RtlPowerThread() + + self.rtl_power_thread.dataUpdated.connect(self.update_data) + self.rtl_power_thread.rtlPowerStarted.connect(self.update_buttons) + self.rtl_power_thread.rtlPowerStopped.connect(self.update_buttons) + def create_plot(self): """Create main spectrum plot""" self.posLabel = self.mainPlotLayout.addLabel(row=0, col=0, justify="right") @@ -135,6 +165,10 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin self.update_plot(data) self.update_waterfall(data) + timestamp = time.time() + self.show_status("Sweep time: {:.2f} s".format(timestamp - self.datatimestamp), timeout=0) + self.datatimestamp = timestamp + def update_plot(self, data): """Update main spectrum plot""" self.curve.setData(data["x"], data["y"]) @@ -171,7 +205,7 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin self.startFreqSpinBox.setValue(float(settings.value("start_freq") or 87.0)) self.stopFreqSpinBox.setValue(float(settings.value("stop_freq") or 108.0)) self.binSizeSpinBox.setValue(float(settings.value("bin_size") or 10.0)) - self.intervalSpinBox.setValue(int(settings.value("interval") or 10)) + self.intervalSpinBox.setValue(float(settings.value("interval") or 10.0)) self.gainSpinBox.setValue(int(settings.value("gain") or 0)) self.ppmSpinBox.setValue(int(settings.value("ppm") or 0)) self.cropSpinBox.setValue(int(settings.value("crop") or 0)) @@ -189,7 +223,7 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin settings.setValue("start_freq", float(self.startFreqSpinBox.value())) settings.setValue("stop_freq", float(self.stopFreqSpinBox.value())) settings.setValue("bin_size", float(self.binSizeSpinBox.value())) - settings.setValue("interval", int(self.intervalSpinBox.value())) + settings.setValue("interval", float(self.intervalSpinBox.value())) settings.setValue("gain", int(self.gainSpinBox.value())) settings.setValue("ppm", int(self.ppmSpinBox.value())) settings.setValue("crop", int(self.cropSpinBox.value())) @@ -207,15 +241,17 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin settings = QtCore.QSettings() self.waterfall_history_size = int(settings.value("waterfall_history_size") or 100) self.datacounter = 0 + self.datatimestamp = time.time() if not self.rtl_power_thread.alive: self.rtl_power_thread.setup(float(self.startFreqSpinBox.value()), float(self.stopFreqSpinBox.value()), float(self.binSizeSpinBox.value()), - interval=int(self.intervalSpinBox.value()), + interval=float(self.intervalSpinBox.value()), gain=int(self.gainSpinBox.value()), ppm=int(self.ppmSpinBox.value()), crop=int(self.cropSpinBox.value()) / 100.0, - single_shot=single_shot) + single_shot=single_shot, + sample_rate=int(settings.value("sample_rate") or 2560000)) self.rtl_power_thread.start() def stop(self): @@ -238,7 +274,8 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin @QtCore.pyqtSlot() def on_action_Settings_triggered(self): dialog = QSpectrumAnalyzerSettings(self) - dialog.exec_() + if dialog.exec_(): + self.setup_rtl_power_thread() @QtCore.pyqtSlot() def on_action_About_triggered(self): @@ -250,11 +287,11 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin def closeEvent(self, event): """Save settings when main window is closed""" - self.rtl_power_thread.stop() + self.stop() self.save_settings() -class RtlPowerThread(QtCore.QThread): +class RtlPowerBaseThread(QtCore.QThread): """Thread which runs rtl_power process""" dataUpdated = QtCore.pyqtSignal(object) rtlPowerStarted = QtCore.pyqtSignal() @@ -264,9 +301,6 @@ class RtlPowerThread(QtCore.QThread): super().__init__(parent) self.alive = False self.process = None - self.params = {} - self.databuffer = {} - self.last_timestamp = "" def stop(self): """Stop rtl_power thread""" @@ -274,8 +308,49 @@ class RtlPowerThread(QtCore.QThread): self.alive = False self.wait() - def setup(self, start_freq, stop_freq, bin_size, interval=10, - gain=-1, ppm=0, crop=0, single_shot=False): + def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1, + ppm=0, crop=0, single_shot=False, sample_rate=2560000): + """Setup rtl_power params""" + raise NotImplementedError + + def process_start(self): + """Start rtl_power process""" + raise NotImplementedError + + def process_stop(self): + """Terminate rtl_power process""" + if self.process: + try: + self.process.terminate() + except ProcessLookupError: + pass + self.process.wait() + self.process = None + + def parse_output(self, line): + """Parse one line of output from rtl_power""" + raise NotImplementedError + + def run(self): + """Rtl_power thread main loop""" + self.process_start() + self.alive = True + self.rtlPowerStarted.emit() + + for line in self.process.stdout: + if not self.alive: + break + self.parse_output(line) + + self.process_stop() + self.alive = False + self.rtlPowerStopped.emit() + + +class RtlPowerThread(RtlPowerBaseThread): + """Thread which runs rtl_power process""" + def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1, + ppm=0, crop=0, single_shot=False, sample_rate=2560000): """Setup rtl_power params""" self.params = { "start_freq": start_freq, @@ -287,16 +362,12 @@ class RtlPowerThread(QtCore.QThread): "crop": crop, "single_shot": single_shot } + self.databuffer = {} + self.last_timestamp = "" - def process_stop(self): - """Terminate rtl_power process""" - if self.process: - try: - self.process.terminate() - except ProcessLookupError: - pass - self.process.wait() - self.process = None + print("rtl_power params:") + pprint.pprint(self.params) + print() def process_start(self): """Start rtl_power process""" @@ -321,7 +392,8 @@ class RtlPowerThread(QtCore.QThread): universal_newlines=True) def parse_output(self, line): - """Parse one preprocessed line of output from rtl_power""" + """Parse one line of output from rtl_power""" + line = [col.strip() for col in line.split(",")] timestamp = " ".join(line[:2]) start_freq = int(line[2]) stop_freq = int(line[3]) @@ -352,24 +424,131 @@ class RtlPowerThread(QtCore.QThread): # if stop_freq == self.params["stop_freq"] * 1e6: if stop_freq > (self.params["stop_freq"] * 1e6) - step: self.dataUpdated.emit(self.databuffer) - return self.databuffer - def run(self): - """Rtl_power thread main loop""" - self.process_start() - self.alive = True - self.rtlPowerStarted.emit() - reader = csv.reader(self.process.stdout, skipinitialspace=True, - delimiter=",", quoting=csv.QUOTE_NONE) - for line in reader: - if not self.alive: - break - self.parse_output(line) +class RtlPowerFftwThread(RtlPowerBaseThread): + """Thread which runs rtl_power_fftw process""" + def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1, + ppm=0, crop=0, single_shot=False, sample_rate=2560000): + """Setup rtl_power_fftw params""" + crop = crop * 100 + overlap = crop * 2 + freq_range = stop_freq * 1e6 - start_freq * 1e6 + min_overhang = sample_rate * overlap * 0.01 + hops = math.ceil((freq_range - min_overhang) / (sample_rate - min_overhang)) + overhang = (hops * sample_rate - freq_range) / (hops - 1) if hops > 1 else 0 + bins = math.ceil(sample_rate / (bin_size * 1e3)) + crop_freq = sample_rate * crop * 0.01 - self.process_stop() - self.alive = False - self.rtlPowerStopped.emit() + self.params = { + "start_freq": start_freq, + "stop_freq": stop_freq, + "freq_range": freq_range, + "sample_rate": sample_rate, + "bin_size": bin_size, + "bins": bins, + "interval": interval, + "hops": hops, + "time": interval / hops, + "gain": gain * 10, + "ppm": ppm, + "crop": crop, + "overlap": overlap, + "min_overhang": min_overhang, + "overhang": overhang, + "single_shot": single_shot + } + self.freqs = [self.get_hop_freq(hop) for hop in range(hops)] + self.freqs_crop = [(f[0] + crop_freq, f[1] - crop_freq) for f in self.freqs] + self.databuffer = {"timestamp": [], "x": [], "y": []} + self.databuffer_hop = {"timestamp": [], "x": [], "y": []} + self.hop = 0 + self.prev_line = "" + + print("rtl_power_fftw params:") + pprint.pprint(self.params) + print() + + def get_hop_freq(self, hop): + """Get start and stop frequency for particular hop""" + start_freq = self.params["start_freq"] * 1e6 + (self.params["sample_rate"] - self.params["overhang"]) * hop + stop_freq = start_freq + self.params["sample_rate"] - (self.params["sample_rate"] / self.params["bins"]) + return (start_freq, stop_freq) + + def process_start(self): + """Start rtl_power_fftw process""" + if not self.process and self.params: + settings = QtCore.QSettings() + cmdline = [ + str(settings.value("rtl_power_executable") or "rtl_power_fftw"), + "-f", "{}M:{}M".format(self.params["start_freq"], + self.params["stop_freq"]), + "-b", "{}".format(self.params["bins"]), + "-t", "{}".format(self.params["time"]), + "-r", "{}".format(self.params["sample_rate"]), + "-p", "{}".format(self.params["ppm"]), + ] + + if self.params["gain"] >= 0: + cmdline.extend(["-g", "{}".format(self.params["gain"])]) + if self.params["overlap"] > 0: + cmdline.extend(["-o", "{}".format(self.params["overlap"])]) + if not self.params["single_shot"]: + cmdline.append("-c") + + self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, + universal_newlines=True) + + def parse_output(self, line): + """Parse one line of output from rtl_power_fftw""" + line = line.strip() + + # One empty line => new hop + if not line and self.prev_line: + self.hop += 1 + self.databuffer["x"].extend(self.databuffer_hop["x"]) + self.databuffer["y"].extend(self.databuffer_hop["y"]) + self.databuffer_hop = {"timestamp": [], "x": [], "y": []} + + # Two empty lines => new set + elif not line and not self.prev_line: + self.hop = 0 + self.dataUpdated.emit(self.databuffer) + self.databuffer = {"timestamp": [], "x": [], "y": []} + + # Get timestamp for new hop and set + elif line.startswith("# Acquisition start:"): + timestamp = line.split(":", 1)[1].strip() + if not self.databuffer_hop["timestamp"]: + self.databuffer_hop["timestamp"] = timestamp + if not self.databuffer["timestamp"]: + self.databuffer["timestamp"] = timestamp + + # Skip other comments + elif line.startswith("#"): + pass + + # Parse frequency and power + elif line[0].isdigit(): + freq, power = line.split() + freq, power = float(freq), float(power) + start_freq, stop_freq = self.freqs_crop[self.hop] + + # Apply cropping + if freq >= start_freq and freq <= stop_freq: + # Skip overlapping frequencies + if not self.databuffer["x"] or freq > self.databuffer["x"][-1]: + #print(" {:.3f} MHz".format(freq / 1e6)) + self.databuffer_hop["x"].append(freq) + self.databuffer_hop["y"].append(power) + else: + #print(" Overlapping {:.3f} MHz".format(freq / 1e6)) + pass + else: + #print(" Cropping {:.3f} MHz".format(freq / 1e6)) + pass + + self.prev_line = line def main(): diff --git a/qspectrumanalyzer/languages/qspectrumanalyzer_cs.ts b/qspectrumanalyzer/languages/qspectrumanalyzer_cs.ts index 9ec2dd3..2b964c0 100644 --- a/qspectrumanalyzer/languages/qspectrumanalyzer_cs.ts +++ b/qspectrumanalyzer/languages/qspectrumanalyzer_cs.ts @@ -3,132 +3,132 @@ QSpectrumAnalyzerMainWindow - + QSpectrumAnalyzer - + Settings - + MHz - + kHz - + auto - + Frequency - + Controls - + Levels - + About - + QSpectrumAnalyzer {} - + &File - + &Help - + &Start - + S&top - + Si&ngle shot - + &Settings... - + &Quit - + Ctrl+Q - + &About - + Interval [s]: - + Gain [dB]: - + Corr. [ppm]: - + Crop [%]: - + Start: - + Stop: - + Bin size: @@ -136,29 +136,44 @@ QSpectrumAnalyzerSettings - + QSpectrumAnalyzer - Settings - - Rtl_power executable: - - - - + rtl_power - + ... - + Waterfall history size: + + + Backend: + + + + + rtl_power_fftw + + + + + Executable: + + + + + Sample rate: + + diff --git a/qspectrumanalyzer/qspectrumanalyzer.ui b/qspectrumanalyzer/qspectrumanalyzer.ui index e6bdf2e..1e65605 100644 --- a/qspectrumanalyzer/qspectrumanalyzer.ui +++ b/qspectrumanalyzer/qspectrumanalyzer.ui @@ -7,7 +7,7 @@ 0 0 1100 - 680 + 731 @@ -52,7 +52,7 @@ 0 0 1100 - 27 + 30 @@ -240,22 +240,6 @@ - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 1 - - - 3600 - - - 10 - - - @@ -315,6 +299,19 @@ + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999.000000000000000 + + + 1.000000000000000 + + + diff --git a/qspectrumanalyzer/qspectrumanalyzer_settings.ui b/qspectrumanalyzer/qspectrumanalyzer_settings.ui index 49b34ae..51182cb 100644 --- a/qspectrumanalyzer/qspectrumanalyzer_settings.ui +++ b/qspectrumanalyzer/qspectrumanalyzer_settings.ui @@ -6,8 +6,8 @@ 0 0 - 500 - 150 + 350 + 210 @@ -17,23 +17,44 @@ - + - Rtl_power executable: + Backend: + + + + rtl_power + + + + + rtl_power_fftw + + + + + + + + Executable: + + + + - + rtl_power - + ... @@ -41,14 +62,14 @@ - + Waterfall history size: - + 1 @@ -61,6 +82,29 @@ + + + + Sample rate: + + + + + + + 0 + + + 25000000 + + + 10000 + + + 2560000 + + + @@ -89,8 +133,8 @@ - rtlPowerExecutableEdit - rtlPowerExecutableButton + executableEdit + executableButton waterfallHistorySizeSpinBox buttonBox diff --git a/qspectrumanalyzer/ui_qspectrumanalyzer.py b/qspectrumanalyzer/ui_qspectrumanalyzer.py index 0a35528..23f2707 100644 --- a/qspectrumanalyzer/ui_qspectrumanalyzer.py +++ b/qspectrumanalyzer/ui_qspectrumanalyzer.py @@ -2,8 +2,7 @@ # Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer.ui' # -# Created: Mon Mar 2 23:12:42 2015 -# by: PyQt4 UI code generator 4.11.3 +# Created by: PyQt4 UI code generator 4.11.4 # # WARNING! All changes made in this file will be lost! @@ -26,7 +25,7 @@ except AttributeError: class Ui_QSpectrumAnalyzerMainWindow(object): def setupUi(self, QSpectrumAnalyzerMainWindow): QSpectrumAnalyzerMainWindow.setObjectName(_fromUtf8("QSpectrumAnalyzerMainWindow")) - QSpectrumAnalyzerMainWindow.resize(1100, 680) + QSpectrumAnalyzerMainWindow.resize(1100, 731) self.centralwidget = QtGui.QWidget(QSpectrumAnalyzerMainWindow) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget) @@ -56,7 +55,7 @@ class Ui_QSpectrumAnalyzerMainWindow(object): self.horizontalLayout.addWidget(self.plotSplitter) QSpectrumAnalyzerMainWindow.setCentralWidget(self.centralwidget) self.menubar = QtGui.QMenuBar(QSpectrumAnalyzerMainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1100, 27)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1100, 30)) self.menubar.setObjectName(_fromUtf8("menubar")) self.menu_File = QtGui.QMenu(self.menubar) self.menu_File.setObjectName(_fromUtf8("menu_File")) @@ -134,13 +133,6 @@ class Ui_QSpectrumAnalyzerMainWindow(object): self.label_6 = QtGui.QLabel(self.groupBox_3) self.label_6.setObjectName(_fromUtf8("label_6")) self.gridLayout_2.addWidget(self.label_6, 0, 1, 1, 1) - self.intervalSpinBox = QtGui.QSpinBox(self.groupBox_3) - self.intervalSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.intervalSpinBox.setMinimum(1) - self.intervalSpinBox.setMaximum(3600) - self.intervalSpinBox.setProperty("value", 10) - self.intervalSpinBox.setObjectName(_fromUtf8("intervalSpinBox")) - self.gridLayout_2.addWidget(self.intervalSpinBox, 1, 0, 1, 1) self.gainSpinBox = QtGui.QSpinBox(self.groupBox_3) self.gainSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.gainSpinBox.setMinimum(-1) @@ -164,6 +156,12 @@ class Ui_QSpectrumAnalyzerMainWindow(object): self.cropSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.cropSpinBox.setObjectName(_fromUtf8("cropSpinBox")) self.gridLayout_2.addWidget(self.cropSpinBox, 3, 1, 1, 1) + self.intervalSpinBox = QtGui.QDoubleSpinBox(self.groupBox_3) + self.intervalSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.intervalSpinBox.setMaximum(999.0) + self.intervalSpinBox.setProperty("value", 1.0) + self.intervalSpinBox.setObjectName(_fromUtf8("intervalSpinBox")) + self.gridLayout_2.addWidget(self.intervalSpinBox, 1, 0, 1, 1) self.verticalLayout_3.addWidget(self.groupBox_3) self.groupBox_4 = QtGui.QGroupBox(self.dockWidgetContents) self.groupBox_4.setObjectName(_fromUtf8("groupBox_4")) diff --git a/qspectrumanalyzer/ui_qspectrumanalyzer_settings.py b/qspectrumanalyzer/ui_qspectrumanalyzer_settings.py index ec13f2a..6f5a554 100644 --- a/qspectrumanalyzer/ui_qspectrumanalyzer_settings.py +++ b/qspectrumanalyzer/ui_qspectrumanalyzer_settings.py @@ -2,8 +2,7 @@ # Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_settings.ui' # -# Created: Mon Mar 2 23:12:42 2015 -# by: PyQt4 UI code generator 4.11.3 +# Created by: PyQt4 UI code generator 4.11.4 # # WARNING! All changes made in this file will be lost! @@ -26,32 +25,50 @@ except AttributeError: class Ui_QSpectrumAnalyzerSettings(object): def setupUi(self, QSpectrumAnalyzerSettings): QSpectrumAnalyzerSettings.setObjectName(_fromUtf8("QSpectrumAnalyzerSettings")) - QSpectrumAnalyzerSettings.resize(500, 150) + QSpectrumAnalyzerSettings.resize(350, 210) self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerSettings) self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) self.formLayout = QtGui.QFormLayout() self.formLayout.setObjectName(_fromUtf8("formLayout")) + self.label_3 = QtGui.QLabel(QSpectrumAnalyzerSettings) + self.label_3.setObjectName(_fromUtf8("label_3")) + self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_3) + self.backendComboBox = QtGui.QComboBox(QSpectrumAnalyzerSettings) + self.backendComboBox.setObjectName(_fromUtf8("backendComboBox")) + self.backendComboBox.addItem(_fromUtf8("")) + self.backendComboBox.addItem(_fromUtf8("")) + self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.backendComboBox) self.label = QtGui.QLabel(QSpectrumAnalyzerSettings) self.label.setObjectName(_fromUtf8("label")) - self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label) + self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label) self.horizontalLayout = QtGui.QHBoxLayout() self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout")) - self.rtlPowerExecutableEdit = QtGui.QLineEdit(QSpectrumAnalyzerSettings) - self.rtlPowerExecutableEdit.setObjectName(_fromUtf8("rtlPowerExecutableEdit")) - self.horizontalLayout.addWidget(self.rtlPowerExecutableEdit) - self.rtlPowerExecutableButton = QtGui.QToolButton(QSpectrumAnalyzerSettings) - self.rtlPowerExecutableButton.setObjectName(_fromUtf8("rtlPowerExecutableButton")) - self.horizontalLayout.addWidget(self.rtlPowerExecutableButton) - self.formLayout.setLayout(0, QtGui.QFormLayout.FieldRole, self.horizontalLayout) + self.executableEdit = QtGui.QLineEdit(QSpectrumAnalyzerSettings) + self.executableEdit.setObjectName(_fromUtf8("executableEdit")) + self.horizontalLayout.addWidget(self.executableEdit) + self.executableButton = QtGui.QToolButton(QSpectrumAnalyzerSettings) + self.executableButton.setObjectName(_fromUtf8("executableButton")) + self.horizontalLayout.addWidget(self.executableButton) + self.formLayout.setLayout(1, QtGui.QFormLayout.FieldRole, self.horizontalLayout) self.label_2 = QtGui.QLabel(QSpectrumAnalyzerSettings) self.label_2.setObjectName(_fromUtf8("label_2")) - self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_2) + self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_2) self.waterfallHistorySizeSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerSettings) self.waterfallHistorySizeSpinBox.setMinimum(1) self.waterfallHistorySizeSpinBox.setMaximum(10000000) self.waterfallHistorySizeSpinBox.setProperty("value", 100) self.waterfallHistorySizeSpinBox.setObjectName(_fromUtf8("waterfallHistorySizeSpinBox")) - self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.waterfallHistorySizeSpinBox) + self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.waterfallHistorySizeSpinBox) + self.label_4 = QtGui.QLabel(QSpectrumAnalyzerSettings) + self.label_4.setObjectName(_fromUtf8("label_4")) + self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_4) + self.sampleRateSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerSettings) + self.sampleRateSpinBox.setMinimum(0) + self.sampleRateSpinBox.setMaximum(25000000) + self.sampleRateSpinBox.setSingleStep(10000) + self.sampleRateSpinBox.setProperty("value", 2560000) + self.sampleRateSpinBox.setObjectName(_fromUtf8("sampleRateSpinBox")) + self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.sampleRateSpinBox) self.verticalLayout.addLayout(self.formLayout) spacerItem = QtGui.QSpacerItem(20, 21, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) @@ -65,14 +82,18 @@ class Ui_QSpectrumAnalyzerSettings(object): QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerSettings.accept) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerSettings.reject) QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerSettings) - QSpectrumAnalyzerSettings.setTabOrder(self.rtlPowerExecutableEdit, self.rtlPowerExecutableButton) - QSpectrumAnalyzerSettings.setTabOrder(self.rtlPowerExecutableButton, self.waterfallHistorySizeSpinBox) + QSpectrumAnalyzerSettings.setTabOrder(self.executableEdit, self.executableButton) + QSpectrumAnalyzerSettings.setTabOrder(self.executableButton, self.waterfallHistorySizeSpinBox) QSpectrumAnalyzerSettings.setTabOrder(self.waterfallHistorySizeSpinBox, self.buttonBox) def retranslateUi(self, QSpectrumAnalyzerSettings): QSpectrumAnalyzerSettings.setWindowTitle(_translate("QSpectrumAnalyzerSettings", "QSpectrumAnalyzer - Settings", None)) - self.label.setText(_translate("QSpectrumAnalyzerSettings", "Rtl_power executable:", None)) - self.rtlPowerExecutableEdit.setText(_translate("QSpectrumAnalyzerSettings", "rtl_power", None)) - self.rtlPowerExecutableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None)) + self.label_3.setText(_translate("QSpectrumAnalyzerSettings", "Backend:", None)) + self.backendComboBox.setItemText(0, _translate("QSpectrumAnalyzerSettings", "rtl_power", None)) + self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw", None)) + self.label.setText(_translate("QSpectrumAnalyzerSettings", "Executable:", None)) + self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "rtl_power", None)) + self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None)) self.label_2.setText(_translate("QSpectrumAnalyzerSettings", "Waterfall history size:", None)) + self.label_4.setText(_translate("QSpectrumAnalyzerSettings", "Sample rate:", None)) diff --git a/qspectrumanalyzer/version.py b/qspectrumanalyzer/version.py index a82b376..c68196d 100644 --- a/qspectrumanalyzer/version.py +++ b/qspectrumanalyzer/version.py @@ -1 +1 @@ -__version__ = "1.1.1" +__version__ = "1.2.0"