Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gqrx for openSUSE:Factory checked in at 2023-10-12 23:44:45 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gqrx (Old) and /work/SRC/openSUSE:Factory/.gqrx.new.1807 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gqrx" Thu Oct 12 23:44:45 2023 rev:3 rq:1117500 version:2.17.2 Changes: -------- --- /work/SRC/openSUSE:Factory/gqrx/gqrx.changes 2023-10-04 22:32:24.573718904 +0200 +++ /work/SRC/openSUSE:Factory/.gqrx.new.1807/gqrx.changes 2023-10-12 23:48:10.490073747 +0200 @@ -1,0 +2,12 @@ +Wed Oct 11 19:32:29 UTC 2023 - Wojciech Kazubski <w...@ire.pw.edu.pl> + +- Update to version 2.17.2 + * New: FORCE_QT6 and FORCE_QT5 CMake options to force Qt version. +- Update to version 2.17.1 + * New: + + Delete key clears the waterfall. + + I/Q tool can save recordings in SigMF format. + + Holding Ctrl speeds up mouse wheel zoom. + * Improved: Reduced CPU utilization of waterfall display. + +------------------------------------------------------------------- @@ -4 +16 @@ -- Update to version 2.16 +- Update to version 2.17 Old: ---- gqrx-2.17.tar.gz New: ---- gqrx-2.17.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gqrx.spec ++++++ --- /var/tmp/diff_new_pack.ksxvvU/_old 2023-10-12 23:48:10.946090258 +0200 +++ /var/tmp/diff_new_pack.ksxvvU/_new 2023-10-12 23:48:10.946090258 +0200 @@ -17,7 +17,7 @@ Name: gqrx -Version: 2.17 +Version: 2.17.2 Release: 0 Summary: Software defined radio receiver License: GPL-3.0-only ++++++ gqrx-2.17.tar.gz -> gqrx-2.17.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/.github/workflows/build.yml new/gqrx-2.17.2/.github/workflows/build.yml --- old/gqrx-2.17/.github/workflows/build.yml 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/.github/workflows/build.yml 2023-10-10 02:47:54.000000000 +0200 @@ -1,6 +1,6 @@ name: Build -on: [push] +on: [push, pull_request] jobs: appimage: @@ -128,8 +128,16 @@ path: Gqrx-*.AppImage macos: name: MacOS - runs-on: macos-11 + runs-on: macos-12 steps: + - name: Check for Secret availability + id: secret-check + run: | + if [ "${{ secrets.BUILD_CERTIFICATE_BASE64 }}" != '' ]; then + echo "available=true" >> $GITHUB_OUTPUT; + else + echo "available=false" >> $GITHUB_OUTPUT; + fi - name: Install dependencies run: | brew update @@ -195,6 +203,7 @@ LIBRARY_PATH=/usr/local/opt/icu4c/lib make -j4 make install - name: Install Apple certificate + if: ${{ steps.secret-check.outputs.available == 'true' }} env: BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} @@ -221,8 +230,9 @@ working-directory: build run: make -j4 - name: Build app bundle - run: ./macos_bundle.sh + run: ./macos_bundle.sh ${{ steps.secret-check.outputs.available }} - name: Notarize app bundle + if: ${{ steps.secret-check.outputs.available == 'true' }} env: NOTARIZE_USERNAME: ${{ secrets.NOTARIZE_USERNAME }} NOTARIZE_TEAM_ID: ${{ secrets.NOTARIZE_TEAM_ID }} @@ -231,10 +241,14 @@ ditto -c -k --keepParent Gqrx.app Gqrx.zip xcrun notarytool submit Gqrx.zip --apple-id "$NOTARIZE_USERNAME" --team-id "$NOTARIZE_TEAM_ID" --password "$NOTARIZE_PASSWORD" --wait - name: Staple app bundle + if: ${{ steps.secret-check.outputs.available == 'true' }} run: xcrun stapler staple --verbose Gqrx.app - name: Create DMG - run: hdiutil create Gqrx.dmg -srcfolder Gqrx.app -format UDZO -fs HFS+ -volname Gqrx + run: | + GQRX_VERSION=$(<build/version.txt) + hdiutil create Gqrx.dmg -srcfolder Gqrx.app -format UDZO -fs HFS+ -volname "Gqrx $GQRX_VERSION" - name: Notarize DMG + if: ${{ steps.secret-check.outputs.available == 'true' }} env: NOTARIZE_USERNAME: ${{ secrets.NOTARIZE_USERNAME }} NOTARIZE_TEAM_ID: ${{ secrets.NOTARIZE_TEAM_ID }} @@ -242,10 +256,11 @@ run: | xcrun notarytool submit Gqrx.dmg --apple-id "$NOTARIZE_USERNAME" --team-id "$NOTARIZE_TEAM_ID" --password "$NOTARIZE_PASSWORD" --wait - name: Staple DMG + if: ${{ steps.secret-check.outputs.available == 'true' }} run: xcrun stapler staple --verbose Gqrx.dmg - name: Rename DMG run: | - GQRX_VERSION=$(<version.txt) + GQRX_VERSION=$(<build/version.txt) mv Gqrx.dmg Gqrx-$GQRX_VERSION.dmg - name: Save artifact uses: actions/upload-artifact@v3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/.github/workflows/ci.yml new/gqrx-2.17.2/.github/workflows/ci.yml --- old/gqrx-2.17/.github/workflows/ci.yml 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/.github/workflows/ci.yml 2023-10-10 02:47:54.000000000 +0200 @@ -69,7 +69,7 @@ name: MacOS CI strategy: matrix: - os: [macos-11, macos-12] + os: [macos-12] backend: [Portaudio, Gr-audio] runs-on: ${{ matrix.os }} steps: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/.gitignore new/gqrx-2.17.2/.gitignore --- old/gqrx-2.17/.gitignore 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/.gitignore 2023-10-10 02:47:54.000000000 +0200 @@ -5,7 +5,6 @@ /*.dmg /AppDir/ /Gqrx.app/ -/version.txt .idea/ cmake-build*/ /CMakeLists.txt.user diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/CMakeLists.txt new/gqrx-2.17.2/CMakeLists.txt --- old/gqrx-2.17/CMakeLists.txt 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/CMakeLists.txt 2023-10-10 02:47:54.000000000 +0200 @@ -4,7 +4,7 @@ project(gqrx) set(${PROJECT_NAME}_MAJOR "2") set(${PROJECT_NAME}_MINOR "17") -set(${PROJECT_NAME}_PATCH "0") +set(${PROJECT_NAME}_PATCH "2") set(IS_RELEASE TRUE) if(IS_RELEASE) @@ -22,7 +22,7 @@ ) endif() add_definitions(-DVERSION="${VERSION}") -file(WRITE version.txt ${VERSION}) +file(WRITE ${CMAKE_BINARY_DIR}/version.txt ${VERSION}) set(PACKAGE ${PROJECT_NAME}) @@ -122,10 +122,20 @@ endif() # 3rd Party Dependency Stuff -find_package(Qt6 QUIET COMPONENTS Core Network Widgets Svg SvgWidgets) -if(NOT Qt6_FOUND) +option(FORCE_QT6 "Force Qt6 to be used" OFF) +option(FORCE_QT5 "Force Qt5 to be used" OFF) + +if(FORCE_QT6) + find_package(Qt6 QUIET COMPONENTS Core Network Widgets Svg SvgWidgets) +elseif(FORCE_QT5) find_package(Qt5 REQUIRED COMPONENTS Core Network Widgets Svg) +else() + find_package(Qt6 QUIET COMPONENTS Core Network Widgets Svg SvgWidgets) + if(NOT Qt6_FOUND) + find_package(Qt5 REQUIRED COMPONENTS Core Network Widgets Svg) + endif() endif() + include(FindPkgConfig) find_package(Gnuradio-osmosdr REQUIRED) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/README.md new/gqrx-2.17.2/README.md --- old/gqrx-2.17/README.md 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/README.md 2023-10-10 02:47:54.000000000 +0200 @@ -183,6 +183,7 @@ * Andy Sloane * Anthony Willard * Anton Blanchard +* AsciiWolf * Bastian Bloessl * Ben Reese * Bob McGwier, N4HY @@ -196,6 +197,7 @@ * Darin Franklin * Davide Gerhard * Dominic Chen +* Doron Behar * Doug Hammond * Elias Ãnal * Federico Fuga @@ -210,11 +212,13 @@ * Jiawei Chen * JiÅà Pinkava * Joachim Schueth, DL2KCD +* Jon Bergli Heier * Josh Blum * Kate Adams * Kenji Rikitake, JJ1BDX * Kitware Inc. * Konrad Beckmann +* Luna Gräfje * luzpaz * Marco Savelli * Markus Kolb @@ -236,6 +240,7 @@ * Russell Dwarshuis, KB8U * Shuyuan Liu * Stefano Leucci +* Sultan Qasim Khan * Sylvain Munaut * Tarmo Tanilsoo * Tomasz Lemiech diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/appimage.sh new/gqrx-2.17.2/appimage.sh --- old/gqrx-2.17/appimage.sh 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/appimage.sh 2023-10-10 02:47:54.000000000 +0200 @@ -33,7 +33,7 @@ echo "===================================================================" echo "" -export VERSION=$(<version.txt) +export VERSION=$(<build/version.txt) # version notice echo "You are building Gqrx version: $VERSION" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/macos_bundle.sh new/gqrx-2.17.2/macos_bundle.sh --- old/gqrx-2.17/macos_bundle.sh 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/macos_bundle.sh 2023-10-10 02:47:54.000000000 +0200 @@ -1,6 +1,6 @@ #!/bin/bash -e -GQRX_VERSION=$(<version.txt) +GQRX_VERSION=$(<build/version.txt) IDENTITY=Y3GC27WZ4S mkdir -p Gqrx.app/Contents/MacOS @@ -57,11 +57,19 @@ dylibbundler -s /usr/local/opt/icu4c/lib/ -od -b -x Gqrx.app/Contents/MacOS/gqrx -x Gqrx.app/Contents/soapy-modules/libPlutoSDRSupport.so -x Gqrx.app/Contents/soapy-modules/libremoteSupport.so -d Gqrx.app/Contents/libs/ /usr/local/opt/qt@6/bin/macdeployqt Gqrx.app -no-strip -always-overwrite # TODO: Remove macdeployqt workaround -/usr/local/opt/qt@6/bin/macdeployqt Gqrx.app -no-strip -always-overwrite -sign-for-notarization=$IDENTITY +if [ "$1" = "true" ]; then + /usr/local/opt/qt@6/bin/macdeployqt Gqrx.app -no-strip -always-overwrite -sign-for-notarization=$IDENTITY +else + /usr/local/opt/qt@6/bin/macdeployqt Gqrx.app -no-strip -always-overwrite +fi cp /usr/local/lib/libbrotlicommon.1.dylib Gqrx.app/Contents/Frameworks # TODO: Remove macdeployqt workaround install_name_tool -change @loader_path/../../../../opt/libpng/lib/libpng16.16.dylib @executable_path/../Frameworks/libpng16.16.dylib Gqrx.app/Contents/Frameworks/libfreetype.6.dylib for f in Gqrx.app/Contents/libs/*.dylib Gqrx.app/Contents/soapy-modules/*.so Gqrx.app/Contents/Frameworks/*.framework Gqrx.app/Contents/Frameworks/libbrotlicommon.1.dylib Gqrx.app/Contents/Frameworks/libsharpyuv.0.dylib Gqrx.app/Contents/Frameworks/libfreetype.6.dylib Gqrx.app/Contents/MacOS/gqrx do - codesign --force --verify --verbose --timestamp --options runtime --entitlements /tmp/Entitlements.plist --sign $IDENTITY $f + if [ "$1" = "true" ]; then + codesign --force --verify --verbose --timestamp --options runtime --entitlements /tmp/Entitlements.plist --sign $IDENTITY $f + else + codesign --remove-signature $f + fi done diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/resources/gqrx.1 new/gqrx-2.17.2/resources/gqrx.1 --- old/gqrx-2.17/resources/gqrx.1 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/resources/gqrx.1 2023-10-10 02:47:54.000000000 +0200 @@ -1,4 +1,4 @@ -.TH GQRX "1" "October 1, 2023" "gqrx 2.17" "User Commands" +.TH GQRX "1" "October 9, 2023" "gqrx 2.17.2" "User Commands" .SH NAME gqrx \- Software Defined Radio GUI application .SH DESCRIPTION diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/resources/kbd-shortcuts.txt new/gqrx-2.17.2/resources/kbd-shortcuts.txt --- old/gqrx-2.17/resources/kbd-shortcuts.txt 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/resources/kbd-shortcuts.txt 2023-10-10 02:47:54.000000000 +0200 @@ -12,6 +12,7 @@ F11 Toggle full screen mode F Set focus to the frequency controller Z Zero frequency offset + Delete Clear waterfall Ctrl+Q Quit the program Receiver modes: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/resources/news.txt new/gqrx-2.17.2/resources/news.txt --- old/gqrx-2.17/resources/news.txt 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/resources/news.txt 2023-10-10 02:47:54.000000000 +0200 @@ -1,4 +1,18 @@ + 2.17.2: Released October 9, 2023 + + NEW: FORCE_QT6 and FORCE_QT5 CMake options to force Qt version. + + + 2.17.1: Released October 9, 2023 + + NEW: Delete key clears the waterfall. + NEW: I/Q tool can save recordings in SigMF format. + NEW: Holding Ctrl speeds up mouse wheel zoom. + IMPROVED: Reduced CPU utilization of waterfall display. + CHANGED: DMG release requires macOS 12.7 or later. + + 2.17: Released October 1, 2023 NEW: "Avg" plot mode, which displays average of FFT bins. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/applications/gqrx/mainwindow.cpp new/gqrx-2.17.2/src/applications/gqrx/mainwindow.cpp --- old/gqrx-2.17/src/applications/gqrx/mainwindow.cpp 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/applications/gqrx/mainwindow.cpp 2023-10-10 02:47:54.000000000 +0200 @@ -32,6 +32,7 @@ #include <QDialogButtonBox> #include <QFile> #include <QGroupBox> +#include <QJsonDocument> #include <QKeySequence> #include <QLineEdit> #include <QMessageBox> @@ -172,6 +173,9 @@ // toggle markers on/off auto *toggle_markers_shortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_K), this); QObject::connect(toggle_markers_shortcut, &QShortcut::activated, this, &MainWindow::toggleMarkers); + // clear waterfall + auto *clear_waterfall_shortcut = new QShortcut(Qt::Key_Delete, this); + QObject::connect(clear_waterfall_shortcut, SIGNAL(activated()), ui->plotter, SLOT(clearWaterfall())); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); @@ -314,7 +318,7 @@ connect(&DXCSpots::Get(), SIGNAL(dxcSpotsUpdated()), this, SLOT(updateClusterSpots())); // I/Q playback - connect(iq_tool, SIGNAL(startRecording(QString)), this, SLOT(startIqRecording(QString))); + connect(iq_tool, SIGNAL(startRecording(QString, QString)), this, SLOT(startIqRecording(QString, QString))); connect(iq_tool, SIGNAL(stopRecording()), this, SLOT(stopIqRecording())); connect(iq_tool, SIGNAL(startPlayback(QString,float,qint64)), this, SLOT(startIqPlayback(QString,float,qint64))); connect(iq_tool, SIGNAL(stopPlayback()), this, SLOT(stopIqPlayback())); @@ -1626,7 +1630,7 @@ } /** Start I/Q recording. */ -void MainWindow::startIqRecording(const QString& recdir) +void MainWindow::startIqRecording(const QString& recdir, const QString& format) { qDebug() << __func__; // generate file name using date, time, rf freq in kHz and BW in Hz @@ -1634,13 +1638,46 @@ auto freq = qRound64(rx->get_rf_freq()); auto sr = qRound64(rx->get_input_rate()); auto dec = (quint32)(rx->get_input_decim()); - auto lastRec = QDateTime::currentDateTimeUtc(). - toString("%1/gqrx_yyyyMMdd_hhmmss_%2_%3_fc.'raw'") - .arg(recdir).arg(freq).arg(sr/dec); + auto currentDate = QDateTime::currentDateTimeUtc(); + auto filenameTemplate = currentDate.toString("%1/gqrx_yyyyMMdd_hhmmss_%2_%3_fc.%4").arg(recdir).arg(freq).arg(sr/dec); + bool sigmf = (format == "SigMF"); + auto lastRec = filenameTemplate.arg(sigmf ? "sigmf-data" : "raw"); + + QFile metaFile(filenameTemplate.arg("sigmf-meta")); + bool ok = true; + if (sigmf) { + auto meta = QJsonDocument { QJsonObject { + {"global", QJsonObject { +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + {"core:datatype", "cf32_be"}, +#else + {"core:datatype", "cf32_le"}, +#endif + {"core:sample_rate", sr/dec}, + {"core:version", "1.0.0"}, + {"core:recorder", "Gqrx " VERSION}, + {"core:hw", QString("OsmoSDR: ") + m_settings->value("input/device", "").toString()}, + }}, {"captures", QJsonArray { + QJsonObject { + {"core:sample_start", 0}, + {"core:frequency", freq}, + {"core:datetime", currentDate.toString(Qt::ISODateWithMs)}, + }, + }}, {"annotations", QJsonArray {}}, + }}.toJson(); + + if (!metaFile.open(QIODevice::WriteOnly) || metaFile.write(meta) != meta.size()) { + ok = false; + } + } // start recorder; fails if recording already in progress - if (rx->start_iq_recording(lastRec.toStdString())) + if (!ok || rx->start_iq_recording(lastRec.toStdString())) { + // remove metadata file if we managed to open it + if (sigmf && metaFile.isOpen()) + metaFile.remove(); + // reset action status ui->statusBar->showMessage(tr("Error starting I/Q recoder")); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/applications/gqrx/mainwindow.h new/gqrx-2.17.2/src/applications/gqrx/mainwindow.h --- old/gqrx-2.17/src/applications/gqrx/mainwindow.h 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/applications/gqrx/mainwindow.h 2023-10-10 02:47:54.000000000 +0200 @@ -195,7 +195,7 @@ void stopAudioStreaming(); /* I/Q playback and recording*/ - void startIqRecording(const QString& recdir); + void startIqRecording(const QString& recdir, const QString& format); void stopIqRecording(); void startIqPlayback(const QString& filename, float samprate, qint64 center_freq); void stopIqPlayback(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/dsp/afsk1200/cafsk12.cpp new/gqrx-2.17.2/src/dsp/afsk1200/cafsk12.cpp --- old/gqrx-2.17/src/dsp/afsk1200/cafsk12.cpp 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/dsp/afsk1200/cafsk12.cpp 2023-10-10 02:47:54.000000000 +0200 @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <QDebug> #include <QTime> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/dsp/afsk1200/cafsk12.h new/gqrx-2.17.2/src/dsp/afsk1200/cafsk12.h --- old/gqrx-2.17/src/dsp/afsk1200/cafsk12.h 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/dsp/afsk1200/cafsk12.h 2023-10-10 02:47:54.000000000 +0200 @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef CAFSK12_H #define CAFSK12_H diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/dsp/afsk1200/filter.h new/gqrx-2.17.2/src/dsp/afsk1200/filter.h --- old/gqrx-2.17/src/dsp/afsk1200/filter.h 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/dsp/afsk1200/filter.h 2023-10-10 02:47:54.000000000 +0200 @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* ---------------------------------------------------------------------- */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/qtgui/freqctrl.cpp new/gqrx-2.17.2/src/qtgui/freqctrl.cpp --- old/gqrx-2.17/src/qtgui/freqctrl.cpp 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/qtgui/freqctrl.cpp 2023-10-10 02:47:54.000000000 +0200 @@ -98,29 +98,11 @@ void CFreqCtrl::setActiveDigit(int idx) { - for (int i = m_DigStart; i < m_NumDigits; i++) + if (m_ActiveEditDigit != idx) { - if (i == idx) - { - if (!m_DigitInfo[i].editmode) - { - m_DigitInfo[i].editmode = true; - m_ActiveEditDigit = i; - } - } - else - { - // un-highlight the previous digit if moved off it - if (m_DigitInfo[i].editmode) - { - m_DigitInfo[i].editmode = false; - m_DigitInfo[i].modified = true; - } - } + m_ActiveEditDigit = idx; + update(); } - - updateCtrl(false); - } static int fmax_to_numdigits(qint64 fmax) @@ -144,7 +126,6 @@ { int i; qint64 pwr = 1; - m_LastEditDigit = 0; m_Oldfreq = -1; m_NumDigits = NumDigits ? NumDigits : fmax_to_numdigits(Maxf); @@ -174,8 +155,6 @@ { m_DigitInfo[i].weight = pwr; m_DigitInfo[i].incval = pwr; - m_DigitInfo[i].modified = true; - m_DigitInfo[i].editmode = false; m_DigitInfo[i].val = 0; pwr *= 10; } @@ -237,11 +216,7 @@ for (i = m_NumDigits - 1; i >= m_DigStart; i--) { val = (int)(rem / m_DigitInfo[i].weight); - if (m_DigitInfo[i].val != val) - { - m_DigitInfo[i].val = val; - m_DigitInfo[i].modified = true; - } + m_DigitInfo[i].val = val; rem = rem - val * m_DigitInfo[i].weight; acc += val; if ((acc == 0) && (i > m_DecPos)) @@ -250,11 +225,6 @@ } } - // If the sign changed and the frequency is less than 1 unit, - // redraw the leading zero to get the correct sign. - if ((m_Oldfreq ^ m_freq) < 0 && m_DigitInfo[m_LeadZeroPos - 1].val == 0) - m_DigitInfo[m_LeadZeroPos - 1].modified = true; - // When frequency is negative all non-zero digits that // have changed will have a negative sign. This loop will // change all digits back to positive, except the one at @@ -277,17 +247,14 @@ // signal the new frequency to world m_Oldfreq = m_freq; emit newFrequency(m_freq); - updateCtrl(m_LastLeadZeroPos != m_LeadZeroPos); + update(); m_LastLeadZeroPos = m_LeadZeroPos; } void CFreqCtrl::setDigitColor(QColor col) { - m_UpdateAll = true; m_DigitColor = col; - for (int i = m_DigStart; i < m_NumDigits; i++) - m_DigitInfo[i].modified = true; - updateCtrl(true); + update(); } void CFreqCtrl::setUnit(FctlUnit unit) @@ -334,86 +301,44 @@ break; } m_Unit = unit; - m_UpdateAll = true; - updateCtrl(true); + update(); } void CFreqCtrl::setBgColor(QColor col) { - m_UpdateAll = true; m_BkColor = col; - for (int i = m_DigStart; i < m_NumDigits; i++) - m_DigitInfo[i].modified = true; - - updateCtrl(true); + update(); } void CFreqCtrl::setUnitsColor(QColor col) { - m_UpdateAll = true; m_UnitsColor = col; - updateCtrl(true); + update(); } void CFreqCtrl::setHighlightColor(QColor col) { - m_UpdateAll = true; m_HighlightColor = col; - updateCtrl(true); -} - -void CFreqCtrl::updateCtrl(bool all) -{ - if (all) - { - m_UpdateAll = true; - for (int i = m_DigStart; i < m_NumDigits; i++) - m_DigitInfo[i].modified = true; - } update(); } -void CFreqCtrl::resizeEvent(QResizeEvent *) -{ -// qDebug() <<rect.width() << rect.height(); - qreal dpr = devicePixelRatioF(); - m_Pixmap = QPixmap(width() * dpr, height() * dpr); // resize pixmap to current control size - m_Pixmap.setDevicePixelRatio(dpr); - m_Pixmap.fill(m_BkColor); - m_UpdateAll = true; - updateCtrl(true); -} - void CFreqCtrl::leaveEvent(QEvent *) { // called when mouse cursor leaves this control so deactivate any highlights if (m_ActiveEditDigit >= 0) { - if (m_DigitInfo[m_ActiveEditDigit].editmode) - { - m_DigitInfo[m_ActiveEditDigit].editmode = false; - m_DigitInfo[m_ActiveEditDigit].modified = true; - m_ActiveEditDigit = -1; - updateCtrl(false); - } + m_ActiveEditDigit = -1; + update(); } } void CFreqCtrl::paintEvent(QPaintEvent *) { - QPainter painter(&m_Pixmap); + QPainter painter(this); - if (m_UpdateAll) // if need to redraw everything - { - drawBkGround(painter); - m_UpdateAll = false; - } - // draw any modified digits to the m_MemDC + drawBkGround(painter); drawDigits(painter); - // now draw pixmap onto screen - QPainter scrnpainter(this); - scrnpainter.drawPixmap(0, 0, m_Pixmap); // blt to the screen(flickers like a candle, why?) } void CFreqCtrl::mouseMoveEvent(QMouseEvent *event) @@ -537,14 +462,11 @@ case Qt::Key_9: if (m_ActiveEditDigit >= 0) { - if (m_DigitInfo[m_ActiveEditDigit].editmode) - { - tmp = (m_freq / m_DigitInfo[m_ActiveEditDigit].weight) % 10; - m_freq -= tmp * m_DigitInfo[m_ActiveEditDigit].weight; - m_freq = m_freq + (event->key() - '0') * - m_DigitInfo[m_ActiveEditDigit].weight; - setFrequency(m_freq); - } + tmp = (m_freq / m_DigitInfo[m_ActiveEditDigit].weight) % 10; + m_freq -= tmp * m_DigitInfo[m_ActiveEditDigit].weight; + m_freq = m_freq + (event->key() - '0') * + m_DigitInfo[m_ActiveEditDigit].weight; + setFrequency(m_freq); } moveCursorRight(); fSkipMsg = true; @@ -663,7 +585,6 @@ } } -// Draws just the Digits that have been modified void CFreqCtrl::drawDigits(QPainter &Painter) { Painter.setFont(m_DigitFont); @@ -674,28 +595,24 @@ if (m_DigitInfo[i].incval == 0) m_FirstEditableDigit++; - if (m_DigitInfo[i].modified || m_DigitInfo[i].editmode) - { - if (m_DigitInfo[i].editmode && m_DigitInfo[i].incval != 0) - Painter.fillRect(m_DigitInfo[i].dQRect, m_HighlightColor); - else - Painter.fillRect(m_DigitInfo[i].dQRect, m_BkColor); + if (i == m_ActiveEditDigit && m_DigitInfo[i].incval != 0) + Painter.fillRect(m_DigitInfo[i].dQRect, m_HighlightColor); + else + Painter.fillRect(m_DigitInfo[i].dQRect, m_BkColor); - if (i >= m_LeadZeroPos) - Painter.setPen(m_InactiveColor); - else - Painter.setPen(m_DigitColor); + if (i >= m_LeadZeroPos) + Painter.setPen(m_InactiveColor); + else + Painter.setPen(m_DigitColor); - if (m_freq < 0 && i == m_LeadZeroPos - 1 && m_DigitInfo[i].val == 0) - Painter.drawText(m_DigitInfo[i].dQRect, - Qt::AlignHCenter | Qt::AlignVCenter, - QString("-0")); - else - Painter.drawText(m_DigitInfo[i].dQRect, - Qt::AlignHCenter | Qt::AlignVCenter, - QString().number(m_DigitInfo[i].val)); - m_DigitInfo[i].modified = false; - } + if (m_freq < 0 && i == m_LeadZeroPos - 1 && m_DigitInfo[i].val == 0) + Painter.drawText(m_DigitInfo[i].dQRect, + Qt::AlignHCenter | Qt::AlignVCenter, + QString("-0")); + else + Painter.drawText(m_DigitInfo[i].dQRect, + Qt::AlignHCenter | Qt::AlignVCenter, + QString().number(m_DigitInfo[i].val)); } } @@ -708,39 +625,36 @@ if (m_ActiveEditDigit >= 0) { - if (m_DigitInfo[m_ActiveEditDigit].editmode) + if (m_DigitInfo[m_ActiveEditDigit].weight == + m_DigitInfo[m_ActiveEditDigit].incval) { - if (m_DigitInfo[m_ActiveEditDigit].weight == - m_DigitInfo[m_ActiveEditDigit].incval) - { - // get the current digit value - tmp = - (int)((m_freq / m_DigitInfo[m_ActiveEditDigit].weight) % - 10); - // set the current digit value to zero - m_freq -= tmp * m_DigitInfo[m_ActiveEditDigit].weight; - tmp++; - if (tmp > 9) - tmp = 0; - m_freq = m_freq + (qint64)tmp * - m_DigitInfo[m_ActiveEditDigit].weight; - } - else + // get the current digit value + tmp = + (int)((m_freq / m_DigitInfo[m_ActiveEditDigit].weight) % + 10); + // set the current digit value to zero + m_freq -= tmp * m_DigitInfo[m_ActiveEditDigit].weight; + tmp++; + if (tmp > 9) + tmp = 0; + m_freq = m_freq + (qint64)tmp * + m_DigitInfo[m_ActiveEditDigit].weight; + } + else + { + tmp = + (int)((m_freq / m_DigitInfo[m_ActiveEditDigit + 1].weight) % + 10); + tmpl = m_freq + m_DigitInfo[m_ActiveEditDigit].incval; + if (tmp != + (int)((tmpl / m_DigitInfo[m_ActiveEditDigit + 1].weight) % + 10)) { - tmp = - (int)((m_freq / m_DigitInfo[m_ActiveEditDigit + 1].weight) % - 10); - tmpl = m_freq + m_DigitInfo[m_ActiveEditDigit].incval; - if (tmp != - (int)((tmpl / m_DigitInfo[m_ActiveEditDigit + 1].weight) % - 10)) - { - tmpl -= m_DigitInfo[m_ActiveEditDigit + 1].weight; - } - m_freq = tmpl; + tmpl -= m_DigitInfo[m_ActiveEditDigit + 1].weight; } - setFrequency(m_freq); + m_freq = tmpl; } + setFrequency(m_freq); } } @@ -749,18 +663,14 @@ { if (m_ActiveEditDigit >= 0) { - if (m_DigitInfo[m_ActiveEditDigit].editmode) + m_freq += m_DigitInfo[m_ActiveEditDigit].incval; + if (m_ResetLowerDigits) { - m_freq += m_DigitInfo[m_ActiveEditDigit].incval; - if (m_ResetLowerDigits) - { - /* Set digits below the active one to 0 */ - m_freq = m_freq - m_freq % - m_DigitInfo[m_ActiveEditDigit].weight; - } - setFrequency(m_freq); - m_LastEditDigit = m_ActiveEditDigit; + /* Set digits below the active one to 0 */ + m_freq = m_freq - m_freq % + m_DigitInfo[m_ActiveEditDigit].weight; } + setFrequency(m_freq); } } @@ -773,39 +683,36 @@ if (m_ActiveEditDigit >= 0) { - if (m_DigitInfo[m_ActiveEditDigit].editmode) + if (m_DigitInfo[m_ActiveEditDigit].weight == + m_DigitInfo[m_ActiveEditDigit].incval) { - if (m_DigitInfo[m_ActiveEditDigit].weight == - m_DigitInfo[m_ActiveEditDigit].incval) - { - // get the current digit value - tmp = - (int)((m_freq / m_DigitInfo[m_ActiveEditDigit].weight) % - 10); - // set the current digit value to zero - m_freq -= tmp * m_DigitInfo[m_ActiveEditDigit].weight; - tmp--; - if (tmp < 0) - tmp = 9; - m_freq = m_freq + (qint64)tmp * - m_DigitInfo[m_ActiveEditDigit].weight; - } - else + // get the current digit value + tmp = + (int)((m_freq / m_DigitInfo[m_ActiveEditDigit].weight) % + 10); + // set the current digit value to zero + m_freq -= tmp * m_DigitInfo[m_ActiveEditDigit].weight; + tmp--; + if (tmp < 0) + tmp = 9; + m_freq = m_freq + (qint64)tmp * + m_DigitInfo[m_ActiveEditDigit].weight; + } + else + { + tmp = + (int)((m_freq / m_DigitInfo[m_ActiveEditDigit + 1].weight) % + 10); + tmpl = m_freq - m_DigitInfo[m_ActiveEditDigit].incval; + if (tmp != + (int)((tmpl / m_DigitInfo[m_ActiveEditDigit + 1].weight) % + 10)) { - tmp = - (int)((m_freq / m_DigitInfo[m_ActiveEditDigit + 1].weight) % - 10); - tmpl = m_freq - m_DigitInfo[m_ActiveEditDigit].incval; - if (tmp != - (int)((tmpl / m_DigitInfo[m_ActiveEditDigit + 1].weight) % - 10)) - { - tmpl += m_DigitInfo[m_ActiveEditDigit + 1].weight; - } - m_freq = tmpl; + tmpl += m_DigitInfo[m_ActiveEditDigit + 1].weight; } - setFrequency(m_freq); + m_freq = tmpl; } + setFrequency(m_freq); } } @@ -814,19 +721,15 @@ { if (m_ActiveEditDigit >= 0) { - if (m_DigitInfo[m_ActiveEditDigit].editmode) + m_freq -= m_DigitInfo[m_ActiveEditDigit].incval; + if (m_ResetLowerDigits) { - m_freq -= m_DigitInfo[m_ActiveEditDigit].incval; - if (m_ResetLowerDigits) - { - /* digits below the active one are reset to 0 */ - m_freq = m_freq - m_freq % - m_DigitInfo[m_ActiveEditDigit].weight; - } - - setFrequency(m_freq); - m_LastEditDigit = m_ActiveEditDigit; + /* digits below the active one are reset to 0 */ + m_freq = m_freq - m_freq % + m_DigitInfo[m_ActiveEditDigit].weight; } + + setFrequency(m_freq); } } @@ -835,17 +738,13 @@ { if (m_ActiveEditDigit >= 0) { - if (m_DigitInfo[m_ActiveEditDigit].editmode) - { - m_freq -= m_DigitInfo[m_ActiveEditDigit].val * - m_DigitInfo[m_ActiveEditDigit].incval; + m_freq -= m_DigitInfo[m_ActiveEditDigit].val * + m_DigitInfo[m_ActiveEditDigit].incval; - /* digits below the active one are reset to 0 */ - m_freq -= m_freq % m_DigitInfo[m_ActiveEditDigit].weight; + /* digits below the active one are reset to 0 */ + m_freq -= m_freq % m_DigitInfo[m_ActiveEditDigit].weight; - setFrequency(m_freq); - m_LastEditDigit = m_ActiveEditDigit; - } + setFrequency(m_freq); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/qtgui/freqctrl.h new/gqrx-2.17.2/src/qtgui/freqctrl.h --- old/gqrx-2.17/src/qtgui/freqctrl.h 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/qtgui/freqctrl.h 2023-10-10 02:47:54.000000000 +0200 @@ -65,7 +65,6 @@ protected: void paintEvent(QPaintEvent *); - void resizeEvent(QResizeEvent *); void mouseMoveEvent(QMouseEvent *); void mousePressEvent(QMouseEvent *); void wheelEvent(QWheelEvent *); @@ -73,7 +72,6 @@ void keyPressEvent(QKeyEvent *); private: - void updateCtrl(bool all); void drawBkGround(QPainter &Painter); void drawDigits(QPainter &Painter); void incDigit(); @@ -88,8 +86,6 @@ bool inRect(QRect &rect, QPointF &point); void setActiveDigit(int idx); - bool m_UpdateAll; - bool m_ExternalKeyActive; bool m_LRMouseFreqSel; /* Use left/right mouse buttons. If FALSE click area determines up/down. */ bool m_ResetLowerDigits; /* If TRUE digits below the active one will be reset to 0 @@ -103,7 +99,6 @@ int m_NumDigitsForUnit; // number of digits allocated for unit (kHz, MHz, ...) int m_DigStart; int m_ActiveEditDigit; - int m_LastEditDigit; int m_DecPos; int m_NumSeps; int m_CumWheelDelta; @@ -120,11 +115,8 @@ QColor m_UnitsColor; QColor m_HighlightColor; - QPixmap m_Pixmap; - QSize m_Size; FctlUnit m_Unit; - QRect m_rectCtrl; // main control rectangle QRect m_UnitsRect; // rectangle where Units text goes QRect m_SepRect[FCTL_MAX_DIGITS]; // separation rectangles for commas, decimal point, etc. @@ -138,7 +130,5 @@ qint64 incval; // value this digit increments or decrements QRect dQRect; // Digit bounding rectangle int val; // value of this digit(0-9) - bool modified; // set if this digit has been modified - bool editmode; // set if this digit is selected for editing } m_DigitInfo[FCTL_MAX_DIGITS]; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/qtgui/iq_tool.cpp new/gqrx-2.17.2/src/qtgui/iq_tool.cpp --- old/gqrx-2.17/src/qtgui/iq_tool.cpp 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/qtgui/iq_tool.cpp 2023-10-10 02:47:54.000000000 +0200 @@ -52,6 +52,7 @@ //ui->recDirEdit->setText(QDir::currentPath()); recdir = new QDir(QDir::homePath(), "*.raw"); + recdir->setNameFilters(recdir->nameFilters() << "*.sigmf-data"); error_palette = new QPalette(); error_palette->setColor(QPalette::Text, Qt::red); @@ -173,7 +174,7 @@ if (checked) { ui->playButton->setEnabled(false); - emit startRecording(recdir->path()); + emit startRecording(recdir->path(), ui->formatCombo->currentText()); refreshDir(); ui->listWidget->setCurrentRow(ui->listWidget->count()-1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/qtgui/iq_tool.h new/gqrx-2.17.2/src/qtgui/iq_tool.h --- old/gqrx-2.17/src/qtgui/iq_tool.h 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/qtgui/iq_tool.h 2023-10-10 02:47:54.000000000 +0200 @@ -62,7 +62,7 @@ void readSettings(QSettings *settings); signals: - void startRecording(const QString recdir); + void startRecording(const QString recdir, const QString format); void stopRecording(); void startPlayback(const QString filename, float samprate, qint64 center_freq); void stopPlayback(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/qtgui/iq_tool.ui new/gqrx-2.17.2/src/qtgui/iq_tool.ui --- old/gqrx-2.17/src/qtgui/iq_tool.ui 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/qtgui/iq_tool.ui 2023-10-10 02:47:54.000000000 +0200 @@ -33,6 +33,30 @@ <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> + <widget class="QLabel" name="formatLabel"> + <property name="text"> + <string>Format:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="formatCombo"> + <property name="toolTip"> + <string>File format</string> + </property> + <item> + <property name="text"> + <string>Raw</string> + </property> + </item> + <item> + <property name="text"> + <string>SigMF</string> + </property> + </item> + </widget> + </item> + <item> <widget class="QLabel" name="recDirLabel"> <property name="text"> <string>Location:</string> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/qtgui/meter.cpp new/gqrx-2.17.2/src/qtgui/meter.cpp --- old/gqrx-2.17/src/qtgui/meter.cpp 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/qtgui/meter.cpp 2023-10-10 02:47:54.000000000 +0200 @@ -35,11 +35,11 @@ #include "meter.h" // ratio to total control width or height -#define CTRL_MARGIN 0.07 // left/right margin -#define CTRL_MAJOR_START 0.3 // top of major tic line -#define CTRL_MINOR_START 0.3 // top of minor tic line -#define CTRL_XAXIS_HEGHT 0.4 // vertical position of horizontal axis -#define CTRL_NEEDLE_TOP 0.4 // vertical position of top of needle triangle +#define CTRL_MARGIN 0.07 // left/right margin +#define CTRL_MAJOR_START 0.3 // top of major tic line +#define CTRL_MINOR_START 0.34 // top of minor tic line +#define CTRL_XAXIS_HEGHT 0.4 // vertical position of horizontal axis +#define CTRL_NEEDLE_TOP 0.4 // vertical position of top of needle triangle #define MIN_DB -100.0f #define MAX_DB +0.0f @@ -50,23 +50,9 @@ CMeter::CMeter(QWidget *parent) : QFrame(parent) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - setFocusPolicy(Qt::StrongFocus); - setAttribute(Qt::WA_PaintOnScreen,false); - setAutoFillBackground(false); - setAttribute(Qt::WA_OpaquePaintEvent, false); - setAttribute(Qt::WA_NoSystemBackground, true); - setMouseTracking(true); - - m_Font = QFont("Arial"); - m_Font.setWeight(QFont::Normal); - m_2DPixmap = QPixmap(0,0); - m_OverlayPixmap = QPixmap(0,0); - m_Size = QSize(0,0); - m_pixperdb = 0.0; - m_Siglevel = 0; + m_dBFS = MIN_DB; m_Sql = -150.0; - m_SqlLevel = 0.0; } CMeter::~CMeter() @@ -83,167 +69,94 @@ return QSize(100, 30); } -void CMeter::resizeEvent(QResizeEvent *) -{ - if (!size().isValid()) - return; - - if (m_Size != size()) - { - // if size changed, resize pixmaps to new screensize - m_Size = size(); - qreal dpr = devicePixelRatioF(); - m_OverlayPixmap = QPixmap(m_Size.width() * dpr, m_Size.height() * dpr); - m_OverlayPixmap.setDevicePixelRatio(dpr); - m_OverlayPixmap.fill(Qt::black); - m_2DPixmap = QPixmap(m_Size.width() * dpr, m_Size.height() * dpr); - m_2DPixmap.setDevicePixelRatio(dpr); - m_2DPixmap.fill(Qt::black); - - qreal w = (m_2DPixmap.width() / dpr) - 2 * CTRL_MARGIN * (m_2DPixmap.width() / dpr); - m_pixperdb = w / fabs((double)(MAX_DB - MIN_DB)); - setSqlLevel(m_Sql); - } - - DrawOverlay(); - draw(); -} - void CMeter::setLevel(float dbfs) { - if (dbfs < MIN_DB) - dbfs = MIN_DB; - else if (dbfs > MAX_DB) - dbfs = MAX_DB; - - float level = m_dBFS; - float alpha = dbfs < level ? ALPHA_DECAY : ALPHA_RISE; - m_dBFS -= alpha * (level - dbfs); - m_Siglevel = (qreal)(level - MIN_DB) * m_pixperdb; - - draw(); + float alpha = dbfs < m_dBFS ? ALPHA_DECAY : ALPHA_RISE; + m_dBFS -= alpha * (m_dBFS - dbfs); + update(); } void CMeter::setSqlLevel(float dbfs) { - if (dbfs >= 0.f) - m_SqlLevel = 0.0; - else - m_SqlLevel = (qreal)(dbfs - MIN_DB) * m_pixperdb; - - if (m_SqlLevel < 0.0) - m_SqlLevel = 0.0; - - m_Sql = (qreal)dbfs; + m_Sql = dbfs; + update(); } // Called by QT when screen needs to be redrawn void CMeter::paintEvent(QPaintEvent *) { QPainter painter(this); - - painter.drawPixmap(0, 0, m_2DPixmap); - return; + drawOverlay(painter); + draw(painter); } // Called to update s-meter data for displaying on the screen -void CMeter::draw() +void CMeter::draw(QPainter &painter) { - int w; - int h; - - if (m_2DPixmap.isNull()) - return; - - // get/draw the 2D spectrum - w = m_2DPixmap.width() / m_2DPixmap.devicePixelRatioF(); - h = m_2DPixmap.height() / m_2DPixmap.devicePixelRatioF(); - - // first copy into 2Dbitmap the overlay bitmap. - m_2DPixmap = m_OverlayPixmap.copy(0, 0, m_OverlayPixmap.width(), m_OverlayPixmap.height()); - QPainter painter(&m_2DPixmap); - - // DrawCurrent position indicator - qreal hline = (qreal) h * CTRL_XAXIS_HEGHT; - qreal marg = (qreal) w * CTRL_MARGIN; - qreal ht = (qreal) h * CTRL_NEEDLE_TOP; - qreal x = marg + m_Siglevel; + // Draw current position indicator + qreal hline = (qreal) height() * CTRL_XAXIS_HEGHT; + qreal marg = (qreal) width() * CTRL_MARGIN; + qreal ht = (qreal) height() * CTRL_NEEDLE_TOP; + qreal pixperdb = (width() - 2 * CTRL_MARGIN * width()) / (qreal)(MAX_DB - MIN_DB); - if (m_Siglevel > 0.0) + if (m_dBFS > MIN_DB) { QColor color(0, 190, 0, 255); QPen pen(color); pen.setJoinStyle(Qt::MiterJoin); painter.setPen(pen); painter.setBrush(QBrush(color)); - - painter.drawRect(QRectF(marg, ht + 2, x - marg, 4)); + painter.drawRect(QRectF(marg, ht + 2, (qreal)(std::min(m_dBFS, MAX_DB) - MIN_DB) * pixperdb, 4)); } - if (m_SqlLevel > 0.0) + if (m_Sql > MIN_DB) { - x = marg + m_SqlLevel; + qreal x = marg + (qreal)(m_Sql - MIN_DB) * pixperdb; painter.setPen(QPen(Qt::yellow, 1, Qt::SolidLine)); painter.drawLine(QLineF(x, hline, x, hline + 8)); } - int y = (h) / 4; - m_Font.setPixelSize(y); - painter.setFont(m_Font); + QFont font("Arial"); + font.setPixelSize(height() / 4); + painter.setFont(font); painter.setPen(QColor(0xDA, 0xDA, 0xDA, 0xFF)); - m_Str.setNum(m_dBFS, 'f', 1); - painter.drawText(marg, h - 2, m_Str + " dBFS" ); - - update(); + painter.drawText(marg, height() - 2, QString::number((double)m_dBFS, 'f', 1) + " dBFS" ); } // Called to draw an overlay bitmap containing items that // does not need to be recreated every fft data update. -void CMeter::DrawOverlay() +void CMeter::drawOverlay(QPainter &painter) { - if (m_OverlayPixmap.isNull()) - return; - - int w = m_OverlayPixmap.width() / m_OverlayPixmap.devicePixelRatioF(); - int h = m_OverlayPixmap.height() / m_OverlayPixmap.devicePixelRatioF(); - int x,y; - QRect rect; - QPainter painter(&m_OverlayPixmap); - - m_OverlayPixmap.fill(QColor(0x1F, 0x1D, 0x1D, 0xFF)); - // Draw scale lines - qreal marg = (qreal) w * CTRL_MARGIN; - qreal hline = (qreal)h * CTRL_XAXIS_HEGHT; - qreal magstart = (qreal) h * CTRL_MAJOR_START; - qreal minstart = (qreal) h * CTRL_MINOR_START; - qreal hstop = (qreal) w - marg; + qreal marg = (qreal) width() * CTRL_MARGIN; + qreal hline = (qreal) height() * CTRL_XAXIS_HEGHT; + qreal majstart = (qreal) height() * CTRL_MAJOR_START; + qreal minstart = (qreal) height() * CTRL_MINOR_START; + qreal hstop = (qreal) width() - marg; painter.setPen(QPen(Qt::white, 1, Qt::SolidLine)); painter.drawLine(QLineF(marg, hline, hstop, hline)); // top line painter.drawLine(QLineF(marg, hline+8, hstop, hline+8)); // bottom line qreal xpos = marg; - for (x = 0; x < 11; x++) { + for (int x = 0; x <= 10; x++) { if (x & 1) //minor tics painter.drawLine(QLineF(xpos, minstart, xpos, hline)); else - painter.drawLine(QLineF(xpos, magstart, xpos, hline)); + painter.drawLine(QLineF(xpos, majstart, xpos, hline)); xpos += (hstop-marg) / 10.0; } // draw scale text - y = h / 4; - m_Font.setPixelSize(y); - painter.setFont(m_Font); - int rwidth = (int)((hstop - marg) / 5.0); - m_Str = "-100"; - rect.setRect(marg / 2 - 5, 0, rwidth, magstart); + QFont font("Arial"); + font.setPixelSize(height() / 4); + painter.setFont(font); + qreal rwidth = (hstop - marg) / 5.0; + QRectF rect(marg - rwidth / 2, 0, rwidth, majstart); - for (x = MIN_DB; x <= MAX_DB; x += 20) + for (int x = MIN_DB; x <= MAX_DB; x += 20) { - m_Str.setNum(x); - painter.drawText(rect, Qt::AlignHCenter|Qt::AlignVCenter, m_Str); + painter.drawText(rect, Qt::AlignHCenter|Qt::AlignVCenter, QString::number(x)); rect.translate(rwidth, 0); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/qtgui/meter.h new/gqrx-2.17.2/src/qtgui/meter.h --- old/gqrx-2.17/src/qtgui/meter.h 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/qtgui/meter.h 2023-10-10 02:47:54.000000000 +0200 @@ -33,7 +33,6 @@ #include <QtGui> #include <QFrame> -#include <QImage> class CMeter : public QFrame { @@ -41,39 +40,22 @@ public: explicit CMeter(QWidget *parent = 0); - explicit CMeter(float min_level = -100.0, float max_level = 10.0, - QWidget *parent = 0); ~CMeter(); QSize minimumSizeHint() const; QSize sizeHint() const; - void setMin(float min_level); - void setMax(float max_level); - void setRange(float min_level, float max_level); - - void draw(); - void UpdateOverlay(){DrawOverlay();} - public slots: void setLevel(float dbfs); void setSqlLevel(float dbfs); protected: void paintEvent(QPaintEvent *event); - void resizeEvent(QResizeEvent* event); private: - void DrawOverlay(); + void draw(QPainter &painter); + void drawOverlay(QPainter &painter); - QFont m_Font; - QPixmap m_2DPixmap; - QPixmap m_OverlayPixmap; - QSize m_Size; - QString m_Str; - qreal m_pixperdb; // pixels / dB - qreal m_Siglevel; float m_dBFS; - qreal m_Sql; - qreal m_SqlLevel; + float m_Sql; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/qtgui/plotter.cpp new/gqrx-2.17.2/src/qtgui/plotter.cpp --- old/gqrx-2.17/src/qtgui/plotter.cpp 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/qtgui/plotter.cpp 2023-10-10 02:47:54.000000000 +0200 @@ -149,7 +149,7 @@ m_DrawOverlay = true; m_2DPixmap = QPixmap(); m_OverlayPixmap = QPixmap(); - m_WaterfallPixmap = QPixmap(); + m_WaterfallImage = QImage(); m_Size = QSize(0,0); m_GrabPosition = 0; m_Percent2DScreen = 35; //percent of screen used for 2D display @@ -586,10 +586,10 @@ { wf_span = span_ms; quint64 tnow = QDateTime::currentMSecsSinceEpoch(); - if (!m_WaterfallPixmap.isNull()) { + if (!m_WaterfallImage.isNull()) { wf_epoch = tnow; wf_count = 0; - msec_per_wfline = (double)wf_span / (qreal)m_WaterfallPixmap.height(); + msec_per_wfline = (double)wf_span / (qreal)m_WaterfallImage.height(); } wf_valid_since_ms = tnow; clearWaterfallBuf(); @@ -930,12 +930,14 @@ // delta is in eigths of a degree, 15 degrees is one step int delta = m_InvertScrolling? -event->angleDelta().y() : event->angleDelta().y(); double numSteps = delta / (8.0 * 15.0); + // zoom faster when Ctrl is held + double zoomBase = (event->modifiers() & Qt::ControlModifier) ? 0.7 : 0.9; if (m_CursorCaptured == YAXIS) { // Vertical zoom. Wheel down: zoom out, wheel up: zoom in // During zoom we try to keep the point (dB or kHz) under the cursor fixed - float zoom_fac = pow(0.9, numSteps); + float zoom_fac = pow(zoomBase, numSteps); float ratio = (float) py / (float) h; float db_range = m_PandMaxdB - m_PandMindB; float y_range = (float) h; @@ -957,7 +959,7 @@ } else if (m_CursorCaptured == XAXIS) { - zoomStepX(pow(0.9, numSteps), px); + zoomStepX(pow(zoomBase, numSteps), px); } else if (event->modifiers() & Qt::ControlModifier) { @@ -1022,32 +1024,31 @@ m_2DPixmap = QPixmap(w, plotHeight); m_2DPixmap.fill(QColor::fromRgba(PLOTTER_BGD_COLOR)); - // No waterfall, use null pixmap + // No waterfall, use null image if (wfHeight == 0) { - m_WaterfallPixmap = QPixmap(); + m_WaterfallImage = QImage(); } // New waterfall, create blank area - else if (m_WaterfallPixmap.isNull()) { - m_WaterfallPixmap = QPixmap(w, wfHeight); - m_WaterfallPixmap.fill(Qt::black); + else if (m_WaterfallImage.isNull()) { + m_WaterfallImage = QImage(w, wfHeight, QImage::Format_RGB32); + m_WaterfallImage.setDevicePixelRatio(m_DPR); + m_WaterfallImage.fill(Qt::black); } // Existing waterfall, rescale width but no height as that would // invalidate time else { - QPixmap oldWaterfall = m_WaterfallPixmap.scaled( - w, m_WaterfallPixmap.height(), + QImage oldWaterfall = m_WaterfallImage.scaled( + w, m_WaterfallImage.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - m_WaterfallPixmap = QPixmap(w, wfHeight); - m_WaterfallPixmap.fill(Qt::black); - QRect copyRect(0, 0, - qMin(w, oldWaterfall.width()), - qMin(wfHeight, oldWaterfall.height())); - QPainter painter(&m_WaterfallPixmap); - painter.drawPixmap(QPointF(0.0, 0.0), oldWaterfall, copyRect); + m_WaterfallImage = QImage(w, wfHeight, QImage::Format_RGB32); + m_WaterfallImage.setDevicePixelRatio(m_DPR); + m_WaterfallImage.fill(Qt::black); + memcpy(m_WaterfallImage.bits(), oldWaterfall.bits(), + m_WaterfallImage.bytesPerLine() * std::min(m_WaterfallImage.height(), oldWaterfall.height())); } // Invalidate on resize @@ -1090,17 +1091,9 @@ painter.drawPixmap(plotRectT, m_2DPixmap, plotRectS); } - if (!m_WaterfallPixmap.isNull()) + if (!m_WaterfallImage.isNull()) { - const int wfWidthS = m_WaterfallPixmap.width(); - const int wfHeightS = m_WaterfallPixmap.height(); - const QRectF wfRectS(0.0, 0.0, wfWidthS, wfHeightS); - - const int wfWidthT = qRound((qreal)wfWidthS / m_DPR); - const int wfHeightT = qRound((qreal)wfHeightS / m_DPR); - const QRectF wfRectT(0.0, plotHeightT, wfWidthT, wfHeightT); - - painter.drawPixmap(wfRectT, m_WaterfallPixmap, wfRectS); + painter.drawImage(QPointF(0.0, plotHeightT), m_WaterfallImage); } } @@ -1168,7 +1161,7 @@ const qint32 maxbin = std::min(endBin + 1, m_fftDataSize - 1); const qint32 xmin = qRound((double)(minbin - startBin) * xScale); - const qint32 xmax = qRound((double)(maxbin - startBin) * xScale); + const qint32 xmax = std::min(qRound((double)(maxbin - startBin) * xScale), qRound(w)); const float frameTime = 1.0f / (float)fft_rate; @@ -1201,7 +1194,7 @@ // Waterfall is advanced only if visible and running, and if there is new // data. Repaints for other reasons do not require any action here. - const bool doWaterfall = !m_WaterfallPixmap.isNull() && m_Running && newData; + const bool doWaterfall = !m_WaterfallImage.isNull() && m_Running && newData; // Draw avg line, except in max mode. Suppress if it would clutter histogram. const bool doAvgLine = m_PlotMode != PLOT_MODE_MAX @@ -1414,15 +1407,12 @@ tlast_wf_drawn_ms = tnow_ms; // move current data down one line(must do before attaching a QPainter object) - m_WaterfallPixmap.scroll(0, 1, m_WaterfallPixmap.rect()); - - QPainter painter1(&m_WaterfallPixmap); + memmove(m_WaterfallImage.scanLine(1), m_WaterfallImage.scanLine(0), + m_WaterfallImage.bytesPerLine() * (m_WaterfallImage.height() - 1)); // draw new line of fft data at top of waterfall bitmap // draw black areas where data will not be draw - painter1.setPen(QPen(Qt::black)); - painter1.drawLine(0.0, 0.0, xmin - 1, 0.0); - painter1.drawLine(xmax, 0.0, w - 1, 0.0); + memset(m_WaterfallImage.scanLine(0), 0, m_WaterfallImage.bytesPerLine()); const bool useWfBuf = msec_per_wfline > 0; float _lineFactor; @@ -1437,12 +1427,10 @@ for (i = 0; i < npts; ++i) { const int ix = i + xmin; - const qreal ixPlot = (qreal)ix; const float v = useWfBuf ? m_wfbuf[ix] * lineFactor : dataSource[ix]; qint32 cidx = qRound((m_WfMaxdB - 10.0f * log10f(v)) * wfdBGainFactor); cidx = std::max(std::min(cidx, 255), 0); - painter1.setPen(m_ColorTbl[255 - cidx]); - painter1.drawPoint(QPointF(ixPlot, 0)); + m_WaterfallImage.setPixel(ix, 0, m_ColorTbl[255 - cidx].rgb()); } wf_avg_count = 0; @@ -2455,6 +2443,13 @@ updateOverlay(); } +void CPlotter::clearWaterfall() +{ + if (!m_WaterfallImage.isNull()) { + m_WaterfallImage.fill(Qt::black); + } +} + void CPlotter::calcDivSize (qint64 low, qint64 high, int divswanted, qint64 &adjlow, qint64 &step, int& divs) { qCDebug(plotter) << "low:" << low; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gqrx-2.17/src/qtgui/plotter.h new/gqrx-2.17.2/src/qtgui/plotter.h --- old/gqrx-2.17/src/qtgui/plotter.h 2023-10-01 21:07:08.000000000 +0200 +++ new/gqrx-2.17.2/src/qtgui/plotter.h 2023-10-10 02:47:54.000000000 +0200 @@ -181,6 +181,7 @@ void enableBandPlan(bool enable); void enableMarkers(bool enabled); void setMarkers(qint64 a, qint64 b); + void clearWaterfall(); void updateOverlay(); void setPercent2DScreen(int percent) @@ -258,7 +259,7 @@ eCapturetype m_CursorCaptured; QPixmap m_2DPixmap; // Composite of everything displayed in the 2D plotter area QPixmap m_OverlayPixmap; // Grid, axes ... things that need to be drawn infrequently - QPixmap m_WaterfallPixmap; + QImage m_WaterfallImage; QColor m_ColorTbl[256]; QSize m_Size; qreal m_DPR{};