mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-02-03 09:44:01 -05:00
Merge pull request #1542 from srcejon/android
MainWindow updates for Android and example configurations
This commit is contained in:
commit
53c1fdb877
250
CMakeLists.txt
250
CMakeLists.txt
@ -368,6 +368,106 @@ elseif (WIN32)
|
||||
"${EXTERNAL_LIBRARY_FOLDER}/libusb/MS64/dll"
|
||||
"${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/bin"
|
||||
)
|
||||
elseif(ANDROID)
|
||||
set(EXTERNAL_LIBRARY_FOLDER "${CMAKE_SOURCE_DIR}/external/android")
|
||||
|
||||
set(FFTW3F_FOUND ON CACHE INTERNAL "")
|
||||
set(FFTW3F_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/fftw-3/include" CACHE INTERNAL "")
|
||||
set(FFTW3F_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/fftw-3/lib/libfftw3f.a" CACHE INTERNAL "")
|
||||
|
||||
set(OPUS_FOUND ON CACHE INTERNAL "")
|
||||
set(OPUS_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/libopus/include" CACHE INTERNAL "")
|
||||
set(OPUS_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/libopus/lib/libopus.a" CACHE INTERNAL "")
|
||||
|
||||
set(CODEC2_FOUND ON CACHE INTERNAL "")
|
||||
set(CODEC2_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/codec2/include" CACHE INTERNAL "")
|
||||
set(CODEC2_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/codec2/lib/libcodec2.a" CACHE INTERNAL "")
|
||||
|
||||
set(APT_FOUND ON CACHE INTERNAL "")
|
||||
set(APT_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/aptdec/include/apt" CACHE INTERNAL "")
|
||||
set(APT_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/aptdec/lib/libaptstatic.a" CACHE INTERNAL "")
|
||||
|
||||
set(SGP4_FOUND ON CACHE INTERNAL "")
|
||||
set(SGP4_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/sgp4/include/libsgp4" CACHE INTERNAL "")
|
||||
set(SGP4_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/sgp4/lib/libsgp4.a" CACHE INTERNAL "")
|
||||
|
||||
set(ZLIB_FOUND ON CACHE INTERNAL "")
|
||||
set(ZLIB_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/zlib/include" CACHE INTERNAL "")
|
||||
set(ZLIB_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/zlib/lib/libz.a" CACHE INTERNAL "")
|
||||
|
||||
set(FAAD_FOUND ON CACHE INTERNAL "")
|
||||
set(FAAD_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/faad2/include" CACHE INTERNAL "")
|
||||
set(FAAD_LIBRARY "${EXTERNAL_LIBRARY_FOLDER}/faad2/lib/liblibfaadstatic.a" CACHE INTERNAL "")
|
||||
|
||||
set(DAB_FOUND ON CACHE INTERNAL "")
|
||||
set(DAB_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/libdab/include/dab_lib" CACHE INTERNAL "")
|
||||
set(DAB_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/libdab/lib/libdab_lib.so" CACHE INTERNAL "")
|
||||
|
||||
set(LIBMBE_FOUND ON CACHE INTERNAL "")
|
||||
set(LIBMBE_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/mbelib/include/" CACHE INTERNAL "")
|
||||
set(LIBMBE_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/mbelib/lib/libmbe.a" CACHE INTERNAL "")
|
||||
|
||||
set(LIBDSDCC_FOUND ON CACHE INTERNAL "")
|
||||
set(LIBDSDCC_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/dsdcc/include/" CACHE INTERNAL "")
|
||||
set(LIBDSDCC_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/dsdcc/lib/libdsdcc.so" CACHE INTERNAL "")
|
||||
|
||||
set(FFMPEG_FOUND ON CACHE INTERNAL "")
|
||||
set(FFMEG_SKIP_CHECK ON CACHE INTERNAL "")
|
||||
set(FFMPEG_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
|
||||
set(FFMPEG_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/bin" CACHE INTERNAL "")
|
||||
set(AVCODEC_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
|
||||
set(AVCODEC_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libavcodec.so" CACHE INTERNAL "")
|
||||
set(AVFORMAT_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
|
||||
set(AVFORMAT_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libavformat.so" CACHE INTERNAL "")
|
||||
set(AVUTIL_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
|
||||
set(AVUTIL_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libavutil.so" CACHE INTERNAL "")
|
||||
set(SWRESAMPLE_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
|
||||
set(SWRESAMPLE_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libswresample.so" CACHE INTERNAL "")
|
||||
set(SWSCALE_INCLUDE_DIRS "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/include" CACHE INTERNAL "")
|
||||
set(SWSCALE_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libswscale.so" CACHE INTERNAL "")
|
||||
|
||||
set(LIBUSB_FOUND ON CACHE INTERNAL "")
|
||||
set(LIBUSB_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/libusb/include/" CACHE INTERNAL "")
|
||||
set(LIBUSB_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/libusb/lib/libusb1.0.so" CACHE INTERNAL "")
|
||||
|
||||
set(LIBAIRSPYHF_FOUND ON CACHE INTERNAL "")
|
||||
set(LIBAIRSPYHF_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/airspyhf/include/" CACHE INTERNAL "")
|
||||
set(LIBAIRSPYHF_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/airspyhf/lib/libairspyhf.a" CACHE INTERNAL "")
|
||||
|
||||
set(LIBAIRSPY_FOUND ON CACHE INTERNAL "")
|
||||
set(LIBAIRSPY_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/airspy/include/" CACHE INTERNAL "")
|
||||
set(LIBAIRSPY_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/airspy/lib/libairspy.a" CACHE INTERNAL "")
|
||||
|
||||
set(LIBRTLSDR_FOUND ON CACHE INTERNAL "")
|
||||
set(LIBRTLSDR_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/librtlsdr/include/" CACHE INTERNAL "")
|
||||
set(LIBRTLSDR_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/librtlsdr/lib/librtlsdr.a" CACHE INTERNAL "")
|
||||
|
||||
set(LIMESUITE_FOUND ON CACHE INTERNAL "")
|
||||
set(LIMESUITE_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/limesuite/include/" CACHE INTERNAL "")
|
||||
set(LIMESUITE_LIBRARY "${EXTERNAL_LIBRARY_FOLDER}/limesuite/lib/libLimeSuite.a" CACHE INTERNAL "")
|
||||
|
||||
set(ANDROID_EXTRA_LIBS
|
||||
${Qt6_DIR}/../../../android_arm64_v8a/lib/libQt6Charts_arm64-v8a.so
|
||||
${Qt6_DIR}/../../../android_arm64_v8a/lib/libQt6Concurrent_arm64-v8a.so
|
||||
${Qt6_DIR}/../../../android_arm64_v8a/lib/libQt6MultimediaWidgets_arm64-v8a.so
|
||||
${Qt6_DIR}/../../../android_arm64_v8a/lib/libQt6SerialPort_arm64-v8a.so
|
||||
${Qt6_DIR}/../../../android_arm64_v8a/lib/libQt6TextToSpeech_arm64-v8a.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/android_openssl/latest/arm64/libssl_1_1.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/android_openssl/latest/arm64/libcrypto_1_1.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libavcodec.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libavdevice.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libavfilter.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libavformat.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libavutil.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libswresample.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libswscale.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/ffmpeg/lib/libc++_shared.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/libdab/lib/libdab_lib.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/dsdcc/lib/libdsdcc.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/libusb/lib/libunrooted_android.so
|
||||
${EXTERNAL_LIBRARY_FOLDER}/libusb/lib/libusb1.0.so
|
||||
CACHE INTERNAL ""
|
||||
)
|
||||
endif()
|
||||
|
||||
# When building a bundle on MacOS, we want to keep build paths in the library
|
||||
@ -440,35 +540,62 @@ endif()
|
||||
|
||||
# for the server we don't need OpenGL/Qt Quick components
|
||||
if (BUILD_GUI)
|
||||
find_package(OpenGL REQUIRED)
|
||||
if (ENABLE_QT6)
|
||||
find_package(Qt6
|
||||
REQUIRED COMPONENTS
|
||||
OpenGL
|
||||
OpenGLWidgets
|
||||
Quick
|
||||
QuickWidgets
|
||||
OPTIONAL_COMPONENTS
|
||||
WebEngineQuick
|
||||
WebEngineCore
|
||||
WebEngineWidgets
|
||||
TextToSpeech)
|
||||
if(ANDROID)
|
||||
# WebEngine not supported on Android
|
||||
if (ENABLE_QT6)
|
||||
find_package(Qt6
|
||||
REQUIRED COMPONENTS
|
||||
OpenGL
|
||||
OpenGLWidgets
|
||||
Quick
|
||||
QuickWidgets
|
||||
TextToSpeech
|
||||
Svg)
|
||||
else()
|
||||
find_package(Qt5
|
||||
REQUIRED COMPONENTS
|
||||
OpenGL
|
||||
Quick
|
||||
QuickWidgets
|
||||
Location
|
||||
TextToSpeech
|
||||
Svg
|
||||
AndroidExtras)
|
||||
endif()
|
||||
else()
|
||||
find_package(Qt5
|
||||
REQUIRED COMPONENTS
|
||||
OpenGL
|
||||
Quick
|
||||
QuickWidgets
|
||||
Location
|
||||
TextToSpeech
|
||||
WebEngine
|
||||
WebEngineCore
|
||||
WebEngineWidgets)
|
||||
find_package(OpenGL REQUIRED)
|
||||
if (ENABLE_QT6)
|
||||
find_package(Qt6
|
||||
REQUIRED COMPONENTS
|
||||
OpenGL
|
||||
OpenGLWidgets
|
||||
Quick
|
||||
QuickWidgets
|
||||
OPTIONAL_COMPONENTS
|
||||
WebEngineQuick
|
||||
WebEngineCore
|
||||
WebEngineWidgets
|
||||
TextToSpeech)
|
||||
else()
|
||||
find_package(Qt5
|
||||
REQUIRED COMPONENTS
|
||||
OpenGL
|
||||
Quick
|
||||
QuickWidgets
|
||||
Location
|
||||
TextToSpeech
|
||||
OPTIONAL_COMPONENTS
|
||||
WebEngine
|
||||
WebEngineCore
|
||||
WebEngineWidgets)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# other requirements
|
||||
find_package(PkgConfig REQUIRED)
|
||||
if(NOT ANDROID)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
find_package(ICONV)
|
||||
@ -506,7 +633,9 @@ if(ENABLE_EXTERNAL_LIBRARIES)
|
||||
else()
|
||||
find_package(Boost REQUIRED)
|
||||
find_package(FFTW3F REQUIRED)
|
||||
find_package(LibUSB REQUIRED) # used by so many packages
|
||||
if(NOT ANDROID)
|
||||
find_package(LibUSB REQUIRED) # used by so many packages
|
||||
endif()
|
||||
find_package(OpenCV OPTIONAL_COMPONENTS core highgui imgproc imgcodecs videoio) # channeltx/modatv
|
||||
find_package(LibSigMF) # SigMF recording files support
|
||||
find_package(ZLIB) # For DAB
|
||||
@ -514,7 +643,7 @@ else()
|
||||
find_package(Codec2)
|
||||
find_package(CM256cc)
|
||||
find_package(LibMbe)
|
||||
find_package(SerialDV REQUIRED)
|
||||
find_package(SerialDV)
|
||||
find_package(LibDSDcc)
|
||||
find_package(Sgp4)
|
||||
find_package(AptDec)
|
||||
@ -608,8 +737,12 @@ include_directories(
|
||||
${CMAKE_SOURCE_DIR}/sdrsrv
|
||||
${CMAKE_SOURCE_DIR}/sdrbench
|
||||
${CMAKE_SOURCE_DIR}/logging
|
||||
${OPENGL_INCLUDE_DIR}
|
||||
)
|
||||
if(NOT ANDROID)
|
||||
include_directories(
|
||||
${OPENGL_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Set up optional make target for developer doc
|
||||
find_package(Doxygen)
|
||||
@ -669,20 +802,61 @@ if (BUILD_GUI)
|
||||
set(sdrangel_SOURCES
|
||||
app/main.cpp
|
||||
sdrgui/resources/sdrangel.rc
|
||||
settings/settings.qrc
|
||||
)
|
||||
|
||||
add_executable(${CMAKE_PROJECT_NAME}
|
||||
${sdrangel_SOURCES}
|
||||
)
|
||||
if(ANDROID AND NOT ENABLE_QT6)
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED ${sdrangel_SOURCES})
|
||||
elseif(ANDROID)
|
||||
qt_add_executable(${CMAKE_PROJECT_NAME} ${sdrangel_SOURCES})
|
||||
set_property(TARGET ${CMAKE_PROJECT_NAME} PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_SOURCE_DIR}/android/qt6)
|
||||
set_property(TARGET ${CMAKE_PROJECT_NAME} PROPERTY QT_ANDROID_EXTRA_PLUGINS ${CMAKE_BINARY_DIR}/lib/plugins)
|
||||
set_property(TARGET ${CMAKE_PROJECT_NAME} PROPERTY QT_ANDROID_EXTRA_LIBS ${ANDROID_EXTRA_LIBS})
|
||||
else()
|
||||
add_executable(${CMAKE_PROJECT_NAME} ${sdrangel_SOURCES})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
${OPENGL_LIBRARIES}
|
||||
Qt::Widgets
|
||||
Qt::Multimedia
|
||||
sdrbase
|
||||
sdrgui
|
||||
logging
|
||||
)
|
||||
if(ANDROID)
|
||||
if(ENABLE_QT6)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC
|
||||
${OPENGL_LIBRARIES}
|
||||
Qt::Widgets
|
||||
Qt::Multimedia
|
||||
Qt::Svg
|
||||
Qt::QmlModels
|
||||
Qt::Quick
|
||||
sdrbase
|
||||
sdrgui
|
||||
logging
|
||||
android
|
||||
log
|
||||
)
|
||||
else()
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
${OPENGL_LIBRARIES}
|
||||
Qt::Widgets
|
||||
Qt::Multimedia
|
||||
Qt::Svg
|
||||
Qt::QmlModels
|
||||
Qt::Quick
|
||||
Qt::AndroidExtras
|
||||
sdrbase
|
||||
sdrgui
|
||||
logging
|
||||
android
|
||||
log
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
${OPENGL_LIBRARIES}
|
||||
Qt::Widgets
|
||||
Qt::Multimedia
|
||||
sdrbase
|
||||
sdrgui
|
||||
logging
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
|
||||
|
30
app/main.cpp
30
app/main.cpp
@ -26,6 +26,9 @@
|
||||
#include <QGLFormat>
|
||||
#include <QSurfaceFormat>
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
#include "util/android.h"
|
||||
#endif
|
||||
|
||||
#include "loggerwithfile.h"
|
||||
#include "mainwindow.h"
|
||||
@ -49,6 +52,9 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) && (QT_VERSION <= QT_VERSION_CHECK(6, 0, 0))
|
||||
QApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
|
||||
#endif
|
||||
#ifndef ANDROID
|
||||
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs); // Don't use on Android, otherwise we can't access files on internal storage
|
||||
#endif
|
||||
|
||||
QApplication a(argc, argv);
|
||||
|
||||
@ -111,6 +117,20 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
// Default sized sliders can be hard to move using touch GUIs, so increase szie
|
||||
// FIXME: How can we do a double border around the handle, as Fusion style seems to use?
|
||||
// Dialog borders are hard to see as is (perhaps as Android doesn't have a title bar), so use same color as for MDI
|
||||
qApp->setStyleSheet("QSlider {min-height: 20px; } "
|
||||
"QSlider::groove:horizontal { border: 1px solid #2e2e2e; height: 1px; background: #444444; margin: 1px 0;}"
|
||||
"QSlider::handle:horizontal { background: #585858; border: 1px double #676767; width: 16px; margin: -8px 0px; border-radius: 3px;}"
|
||||
"QSlider::sub-page {background: #ff8c00; border: 1px solid #2e2e2e;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-top-left-radius: 5px;border-bottom-left-radius: 5px;}"
|
||||
"QSlider::add-page {background: #444444; border: 1px solid #2e2e2e;border-top-right-radius: 5px;border-bottom-right-radius: 5px;border-top-left-radius: 0px;border-bottom-left-radius: 0px;}"
|
||||
"QDialog { border: 1px solid #ff8c00;}"
|
||||
);
|
||||
#endif
|
||||
|
||||
MainParser parser;
|
||||
parser.parse(*qApp);
|
||||
|
||||
@ -160,10 +180,18 @@ int main(int argc, char* argv[])
|
||||
QSurfaceFormat::setDefaultFormat(sfc);
|
||||
#endif
|
||||
|
||||
qtwebapp::LoggerWithFile *logger = new qtwebapp::LoggerWithFile(qApp);
|
||||
#ifdef ANDROID
|
||||
qtwebapp::LoggerWithFile *logger = nullptr;
|
||||
qInstallMessageHandler(Android::messageHandler);
|
||||
#else
|
||||
qtwebapp::LoggerWithFile *logger = new qtwebapp::LoggerWithFile(qApp);
|
||||
logger->installMsgHandler();
|
||||
#endif
|
||||
|
||||
int res = runQtApplication(argc, argv, logger);
|
||||
|
||||
delete logger;
|
||||
|
||||
qWarning("SDRangel quit.");
|
||||
return res;
|
||||
}
|
||||
|
@ -315,10 +315,11 @@ bool ADSBDemodSettings::deserialize(const QByteArray& data)
|
||||
d.readBlob(60, &m_geometryBytes);
|
||||
d.readBool(61, &m_hidden, false);
|
||||
d.readString(62, &m_checkWXAPIKey, "");
|
||||
#ifdef LINUX
|
||||
d.readString(63, &m_mapProvider, "mapboxgl");
|
||||
#else
|
||||
d.readString(63, &m_mapProvider, "osm");
|
||||
#ifdef LINUX
|
||||
if (m_mapProvider == "osm") {
|
||||
m_mapProvider = "mapboxgl";
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) {
|
||||
|
@ -183,10 +183,11 @@ bool MapSettings::deserialize(const QByteArray& data)
|
||||
QByteArray blob;
|
||||
|
||||
d.readBool(1, &m_displayNames, true);
|
||||
#ifdef LINUX
|
||||
d.readString(2, &m_mapProvider, "mapboxgl");
|
||||
#else
|
||||
d.readString(2, &m_mapProvider, "osm");
|
||||
#ifdef LINUX
|
||||
if (m_mapProvider == "osm") {
|
||||
m_mapProvider = "mapboxgl";
|
||||
}
|
||||
#endif
|
||||
d.readString(3, &m_mapBoxAPIKey, "");
|
||||
d.readString(4, &m_mapBoxStyles, "");
|
||||
|
@ -1,6 +1,7 @@
|
||||
project (sdrbase)
|
||||
|
||||
if(WIN32)
|
||||
# This should probably be in ../CMakeLists.txt with the other variables like it
|
||||
set(OPUS_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/external/windows/libopus/include")
|
||||
set(OPUS_LIBRARIES "${CMAKE_SOURCE_DIR}/external/windows/libopus/lib/x64/libopus.lib")
|
||||
endif()
|
||||
@ -45,10 +46,11 @@ if (LIBSIGMF_FOUND AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(sdrbase_LIBSIGMF_LIB ${LIBSIGMF_LIBRARIES})
|
||||
endif()
|
||||
|
||||
# serialdv now required
|
||||
add_definitions(-DDSD_USE_SERIALDV)
|
||||
include_directories(${LIBSERIALDV_INCLUDE_DIR})
|
||||
set(sdrbase_SERIALDV_LIB ${LIBSERIALDV_LIBRARY})
|
||||
if (LIBSERIALDV_FOUND)
|
||||
add_definitions(-DDSD_USE_SERIALDV)
|
||||
include_directories(${LIBSERIALDV_INCLUDE_DIR})
|
||||
set(sdrbase_SERIALDV_LIB ${LIBSERIALDV_LIBRARY})
|
||||
endif()
|
||||
|
||||
set(sdrbase_SOURCES
|
||||
${sdrbase_SOURCES}
|
||||
@ -168,6 +170,7 @@ set(sdrbase_SOURCES
|
||||
settings/rollupstate.cpp
|
||||
|
||||
util/ais.cpp
|
||||
util/android.cpp
|
||||
util/aviationweather.cpp
|
||||
util/ax25.cpp
|
||||
util/aprs.cpp
|
||||
@ -388,6 +391,7 @@ set(sdrbase_HEADERS
|
||||
settings/rollupstate.h
|
||||
|
||||
util/ais.h
|
||||
util/android.h
|
||||
util/aviationweather.h
|
||||
util/ax25.h
|
||||
util/aprs.h
|
||||
@ -491,6 +495,7 @@ target_link_libraries(sdrbase
|
||||
Qt::Core
|
||||
Qt::Multimedia
|
||||
Qt::WebSockets
|
||||
Qt::Positioning
|
||||
httpserver
|
||||
logging
|
||||
qrtplib
|
||||
@ -499,8 +504,15 @@ target_link_libraries(sdrbase
|
||||
if (Qt6_FOUND)
|
||||
target_link_libraries(sdrbase
|
||||
Qt::Core5Compat
|
||||
Qt::CorePrivate
|
||||
)
|
||||
endif()
|
||||
if(ANDROID AND NOT ENABLE_QT6)
|
||||
target_link_libraries(sdrbase Qt::AndroidExtras)
|
||||
endif()
|
||||
if(ANDROID)
|
||||
target_link_libraries(sdrbase log)
|
||||
endif()
|
||||
|
||||
install(TARGETS sdrbase DESTINATION ${INSTALL_LIB_DIR})
|
||||
|
||||
|
@ -17,8 +17,6 @@
|
||||
|
||||
#include <QGlobalStatic>
|
||||
|
||||
#include "plugin/pluginmanager.h"
|
||||
|
||||
#include "deviceenumerator.h"
|
||||
|
||||
Q_GLOBAL_STATIC(DeviceEnumerator, deviceEnumerator)
|
||||
@ -246,89 +244,101 @@ bool DeviceEnumerator::isMIMOEnumerated(const QString& deviceHwId, int deviceSeq
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceEnumerator::enumerateRxDevices(PluginManager *pluginManager)
|
||||
void DeviceEnumerator::enumerateDevices(PluginAPI::SamplingDeviceRegistrations& deviceRegistrations, DevicesEnumeration& enumeration, PluginInterface::SamplingDevice::StreamType type)
|
||||
{
|
||||
m_rxEnumeration.clear();
|
||||
PluginAPI::SamplingDeviceRegistrations& rxDeviceRegistrations = pluginManager->getSourceDeviceRegistrations();
|
||||
int index = 0;
|
||||
DevicesEnumeration tempEnumeration;
|
||||
PluginInterface::OriginDevices originDevices;
|
||||
QStringList originDevicesHwIds;
|
||||
|
||||
for (int i = 0; i < rxDeviceRegistrations.count(); i++)
|
||||
for (int i = 0; i < deviceRegistrations.count(); i++)
|
||||
{
|
||||
qDebug("DeviceEnumerator::enumerateRxDevices: %s", qPrintable(rxDeviceRegistrations[i].m_deviceId));
|
||||
rxDeviceRegistrations[i].m_plugin->enumOriginDevices(m_originDevicesHwIds, m_originDevices);
|
||||
PluginInterface::SamplingDevices samplingDevices = rxDeviceRegistrations[i].m_plugin->enumSampleSources(m_originDevices);
|
||||
qDebug("DeviceEnumerator::enumerateDevices: %s", qPrintable(deviceRegistrations[i].m_deviceId));
|
||||
deviceRegistrations[i].m_plugin->enumOriginDevices(originDevicesHwIds, originDevices);
|
||||
PluginInterface::SamplingDevices samplingDevices;
|
||||
if (type == PluginInterface::SamplingDevice::StreamSingleRx) {
|
||||
samplingDevices = deviceRegistrations[i].m_plugin->enumSampleSources(originDevices);
|
||||
} else if (type == PluginInterface::SamplingDevice::StreamSingleTx) {
|
||||
samplingDevices = deviceRegistrations[i].m_plugin->enumSampleSinks(originDevices);
|
||||
} else {
|
||||
samplingDevices = deviceRegistrations[i].m_plugin->enumSampleMIMO(originDevices);
|
||||
}
|
||||
|
||||
for (int j = 0; j < samplingDevices.count(); j++)
|
||||
{
|
||||
m_rxEnumeration.push_back(
|
||||
tempEnumeration.push_back(
|
||||
DeviceEnumeration(
|
||||
samplingDevices[j],
|
||||
rxDeviceRegistrations[i].m_plugin,
|
||||
index
|
||||
deviceRegistrations[i].m_plugin,
|
||||
0 // Index will be set when adding to enumeration below
|
||||
)
|
||||
);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// We don't remove devices that are no-longer found from the enumeration list, in case their
|
||||
// index is referenced in some other object (E.g. DeviceGUI)
|
||||
// Instead we mark as removed. If later re-added, then we re-use the same index
|
||||
for (DevicesEnumeration::iterator it = enumeration.begin(); it != enumeration.end(); ++it)
|
||||
{
|
||||
bool found = false;
|
||||
for (DevicesEnumeration::iterator it2 = tempEnumeration.begin(); it2 != tempEnumeration.end(); ++it2)
|
||||
{
|
||||
if (it->m_samplingDevice == it2->m_samplingDevice)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
it->m_samplingDevice.removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Add new entries and update existing (in case re-added or sequence number has changed)
|
||||
int index = enumeration.size();
|
||||
for (DevicesEnumeration::iterator it = tempEnumeration.begin(); it != tempEnumeration.end(); ++it)
|
||||
{
|
||||
|
||||
bool found = false;
|
||||
for (DevicesEnumeration::iterator it2 = enumeration.begin(); it2 != enumeration.end(); ++it2)
|
||||
{
|
||||
if (it->m_samplingDevice == it2->m_samplingDevice)
|
||||
{
|
||||
it2->m_samplingDevice.removed = false;
|
||||
it2->m_samplingDevice.displayedName = it->m_samplingDevice.displayedName;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
it->m_index = index++;
|
||||
enumeration.push_back(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceEnumerator::enumerateRxDevices(PluginManager *pluginManager)
|
||||
{
|
||||
enumerateDevices(pluginManager->getSourceDeviceRegistrations(), m_rxEnumeration, PluginInterface::SamplingDevice::StreamSingleRx);
|
||||
}
|
||||
|
||||
void DeviceEnumerator::enumerateTxDevices(PluginManager *pluginManager)
|
||||
{
|
||||
m_txEnumeration.clear();
|
||||
PluginAPI::SamplingDeviceRegistrations& txDeviceRegistrations = pluginManager->getSinkDeviceRegistrations();
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < txDeviceRegistrations.count(); i++)
|
||||
{
|
||||
qDebug("DeviceEnumerator::enumerateTxDevices: %s", qPrintable(txDeviceRegistrations[i].m_deviceId));
|
||||
txDeviceRegistrations[i].m_plugin->enumOriginDevices(m_originDevicesHwIds, m_originDevices);
|
||||
PluginInterface::SamplingDevices samplingDevices = txDeviceRegistrations[i].m_plugin->enumSampleSinks(m_originDevices);
|
||||
|
||||
for (int j = 0; j < samplingDevices.count(); j++)
|
||||
{
|
||||
m_txEnumeration.push_back(
|
||||
DeviceEnumeration(
|
||||
samplingDevices[j],
|
||||
txDeviceRegistrations[i].m_plugin,
|
||||
index
|
||||
)
|
||||
);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
enumerateDevices(pluginManager->getSinkDeviceRegistrations(), m_txEnumeration, PluginInterface::SamplingDevice::StreamSingleTx);
|
||||
}
|
||||
|
||||
void DeviceEnumerator::enumerateMIMODevices(PluginManager *pluginManager)
|
||||
{
|
||||
m_mimoEnumeration.clear();
|
||||
PluginAPI::SamplingDeviceRegistrations& mimoDeviceRegistrations = pluginManager->getMIMODeviceRegistrations();
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < mimoDeviceRegistrations.count(); i++)
|
||||
{
|
||||
qDebug("DeviceEnumerator::enumerateMIMODevices: %s", qPrintable(mimoDeviceRegistrations[i].m_deviceId));
|
||||
mimoDeviceRegistrations[i].m_plugin->enumOriginDevices(m_originDevicesHwIds, m_originDevices);
|
||||
PluginInterface::SamplingDevices samplingDevices = mimoDeviceRegistrations[i].m_plugin->enumSampleMIMO(m_originDevices);
|
||||
|
||||
for (int j = 0; j < samplingDevices.count(); j++)
|
||||
{
|
||||
m_mimoEnumeration.push_back(
|
||||
DeviceEnumeration(
|
||||
samplingDevices[j],
|
||||
mimoDeviceRegistrations[i].m_plugin,
|
||||
index
|
||||
)
|
||||
);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
enumerateDevices(pluginManager->getMIMODeviceRegistrations(), m_mimoEnumeration, PluginInterface::SamplingDevice::StreamMIMO);
|
||||
}
|
||||
|
||||
void DeviceEnumerator::listRxDeviceNames(QList<QString>& list, std::vector<int>& indexes) const
|
||||
{
|
||||
for (DevicesEnumeration::const_iterator it = m_rxEnumeration.begin(); it != m_rxEnumeration.end(); ++it)
|
||||
{
|
||||
if ((it->m_samplingDevice.claimed < 0) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice))
|
||||
if (((it->m_samplingDevice.claimed < 0) && (!it->m_samplingDevice.removed)) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice))
|
||||
{
|
||||
list.append(it->m_samplingDevice.displayedName);
|
||||
indexes.push_back(it->m_index);
|
||||
@ -340,7 +350,7 @@ void DeviceEnumerator::listTxDeviceNames(QList<QString>& list, std::vector<int>&
|
||||
{
|
||||
for (DevicesEnumeration::const_iterator it = m_txEnumeration.begin(); it != m_txEnumeration.end(); ++it)
|
||||
{
|
||||
if ((it->m_samplingDevice.claimed < 0) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice))
|
||||
if (((it->m_samplingDevice.claimed < 0) && (!it->m_samplingDevice.removed)) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice))
|
||||
{
|
||||
list.append(it->m_samplingDevice.displayedName);
|
||||
indexes.push_back(it->m_index);
|
||||
@ -352,7 +362,7 @@ void DeviceEnumerator::listMIMODeviceNames(QList<QString>& list, std::vector<int
|
||||
{
|
||||
for (DevicesEnumeration::const_iterator it = m_mimoEnumeration.begin(); it != m_mimoEnumeration.end(); ++it)
|
||||
{
|
||||
if ((it->m_samplingDevice.claimed < 0) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice))
|
||||
if (((it->m_samplingDevice.claimed < 0) && (!it->m_samplingDevice.removed)) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice))
|
||||
{
|
||||
list.append(it->m_samplingDevice.displayedName);
|
||||
indexes.push_back(it->m_index);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "plugin/plugininterface.h"
|
||||
#include "plugin/pluginmanager.h"
|
||||
#include "device/deviceuserargs.h"
|
||||
#include "export.h"
|
||||
|
||||
@ -85,9 +86,8 @@ private:
|
||||
DevicesEnumeration m_rxEnumeration;
|
||||
DevicesEnumeration m_txEnumeration;
|
||||
DevicesEnumeration m_mimoEnumeration;
|
||||
PluginInterface::OriginDevices m_originDevices;
|
||||
QStringList m_originDevicesHwIds;
|
||||
|
||||
void enumerateDevices(PluginAPI::SamplingDeviceRegistrations& deviceRegistrations, DevicesEnumeration& enumeration, PluginInterface::SamplingDevice::StreamType type);
|
||||
PluginInterface *getRxRegisteredPlugin(PluginManager *pluginManager, const QString& deviceHwId);
|
||||
PluginInterface *getTxRegisteredPlugin(PluginManager *pluginManager, const QString& deviceHwId);
|
||||
PluginInterface *getMIMORegisteredPlugin(PluginManager *pluginManager, const QString& deviceHwId);
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <QGlobalStatic>
|
||||
#include <QCoreApplication>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QGeoPositionInfoSource>
|
||||
|
||||
#include "loggerwithfile.h"
|
||||
#include "dsp/dsptypes.h"
|
||||
@ -71,6 +73,8 @@ MainCore::MainCore()
|
||||
m_masterTimer.start(50);
|
||||
m_startMsecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
|
||||
m_masterElapsedTimer.start();
|
||||
// Position can take a while to determine, so we start updates at program startup
|
||||
initPosition();
|
||||
}
|
||||
|
||||
MainCore::~MainCore()
|
||||
@ -335,3 +339,36 @@ void MainCore::debugMaps()
|
||||
feIt.value()->getIndex(), feIt.key()->getIndexInFeatureSet(), qPrintable(feIt.key()->getURI()), qPrintable(feIt.key()->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
void MainCore::initPosition()
|
||||
{
|
||||
m_positionSource = QGeoPositionInfoSource::createDefaultSource(this);
|
||||
if (m_positionSource)
|
||||
{
|
||||
connect(m_positionSource, &QGeoPositionInfoSource::positionUpdated, this, &MainCore::positionUpdated);
|
||||
m_positionSource->startUpdates();
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "MainCore::initPosition: No position source.";
|
||||
}
|
||||
}
|
||||
|
||||
const QGeoPositionInfo& MainCore::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
void MainCore::positionUpdated(const QGeoPositionInfo &info)
|
||||
{
|
||||
if (info.isValid())
|
||||
{
|
||||
m_position = info;
|
||||
if (m_settings.getAutoUpdatePosition())
|
||||
{
|
||||
m_settings.setLatitude(m_position.coordinate().latitude());
|
||||
m_settings.setLongitude(m_position.coordinate().longitude());
|
||||
m_settings.setAltitude(m_position.coordinate().altitude());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <QElapsedTimer>
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QGeoPositionInfo>
|
||||
|
||||
#include "export.h"
|
||||
#include "settings/mainsettings.h"
|
||||
@ -38,6 +39,7 @@ class FeatureSet;
|
||||
class Feature;
|
||||
class PluginManager;
|
||||
class MessageQueue;
|
||||
class QGeoPositionInfoSource;
|
||||
|
||||
namespace qtwebapp {
|
||||
class LoggerWithFile;
|
||||
@ -846,7 +848,7 @@ public:
|
||||
qint64 getStartMsecsSinceEpoch() const { return m_startMsecsSinceEpoch; } //!< Epoch timestamp in millisecodns close to elapsed timer start
|
||||
const MainSettings& getSettings() const { return m_settings; }
|
||||
MessageQueue *getMainMessageQueue() { return m_mainMessageQueue; }
|
||||
const PluginManager *getPluginManager() const { return m_pluginManager; }
|
||||
PluginManager *getPluginManager() const { return m_pluginManager; }
|
||||
std::vector<DeviceSet*>& getDeviceSets() { return m_deviceSets; }
|
||||
std::vector<FeatureSet*>& getFeatureeSets() { return m_featureSets; }
|
||||
void setLoggingOptions();
|
||||
@ -875,6 +877,8 @@ public:
|
||||
// pipes
|
||||
MessagePipes& getMessagePipes() { return m_messagePipes; }
|
||||
DataPipes& getDataPipes() { return m_dataPipes; }
|
||||
// Position
|
||||
const QGeoPositionInfo& getPosition() const;
|
||||
|
||||
friend class MainServer;
|
||||
friend class MainWindow;
|
||||
@ -883,6 +887,9 @@ public:
|
||||
friend class DeviceSetPresetsDialog;
|
||||
friend class ConfigurationsDialog;
|
||||
|
||||
public slots:
|
||||
void positionUpdated(const QGeoPositionInfo &info);
|
||||
|
||||
signals:
|
||||
void deviceSetAdded(int index, DeviceAPI *device);
|
||||
void deviceChanged(int index);
|
||||
@ -912,7 +919,10 @@ private:
|
||||
PluginManager* m_pluginManager;
|
||||
MessagePipes m_messagePipes;
|
||||
DataPipes m_dataPipes;
|
||||
QGeoPositionInfoSource *m_positionSource;
|
||||
QGeoPositionInfo m_position;
|
||||
|
||||
void initPosition();
|
||||
void debugMaps();
|
||||
};
|
||||
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
int deviceNbItems; //!< Number of items (or streams) in the device. >1 for composite devices.
|
||||
int deviceItemIndex; //!< For composite devices this is the Rx or Tx stream index. -1 if not initialized
|
||||
int claimed; //!< This is the device set index if claimed else -1
|
||||
bool removed; //!< Set if device has been removed
|
||||
|
||||
SamplingDevice(const QString& _displayedName,
|
||||
const QString& _hardwareId,
|
||||
@ -85,8 +86,17 @@ public:
|
||||
streamType(_streamType),
|
||||
deviceNbItems(_deviceNbItems),
|
||||
deviceItemIndex(_deviceItemIndex),
|
||||
claimed(-1)
|
||||
claimed(-1),
|
||||
removed(false)
|
||||
{ }
|
||||
|
||||
bool operator==(const SamplingDevice& rhs) const
|
||||
{
|
||||
return displayedName == rhs.displayedName
|
||||
&& hardwareId == rhs.hardwareId
|
||||
&& id == rhs.id
|
||||
&& serial == rhs.serial;
|
||||
}
|
||||
};
|
||||
typedef QList<SamplingDevice> SamplingDevices;
|
||||
|
||||
|
@ -151,6 +151,12 @@ public:
|
||||
emit preferenceChanged(Preferences::Altitude);
|
||||
}
|
||||
|
||||
bool getAutoUpdatePosition() const { return m_preferences.getAutoUpdatePosition(); }
|
||||
void setAutoUpdatePosition(bool autoUpdatePosition)
|
||||
{
|
||||
m_preferences.setAutoUpdatePosition(autoUpdatePosition);
|
||||
}
|
||||
|
||||
QtMsgType getConsoleMinLogLevel() const { return m_preferences.getConsoleMinLogLevel(); }
|
||||
void setConsoleMinLogLevel(const QtMsgType& minLogLevel)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ void Preferences::resetToDefaults()
|
||||
m_latitude = 49.012423; // Set an interesting location so map doesn't open up in the middle of the ocean
|
||||
m_longitude = 8.418125;
|
||||
m_altitude = 0.0f;
|
||||
m_autoUpdatePosition = true;
|
||||
m_useLogFile = false;
|
||||
m_logFileName = "sdrangel.log";
|
||||
m_consoleMinLogLevel = QtDebugMsg;
|
||||
@ -41,6 +42,7 @@ QByteArray Preferences::serialize() const
|
||||
s.writeFloat((int) Altitude, m_altitude);
|
||||
s.writeS32((int) SourceItemIndex, m_sourceItemIndex);
|
||||
s.writeS32((int) Multisampling, m_multisampling);
|
||||
s.writeBool((int) AutoUpdatePosition, m_autoUpdatePosition);
|
||||
return s.final();
|
||||
}
|
||||
|
||||
@ -95,9 +97,11 @@ bool Preferences::deserialize(const QByteArray& data)
|
||||
}
|
||||
|
||||
d.readS32((int) Multisampling, &m_multisampling, 0);
|
||||
d.readBool((int) AutoUpdatePosition, &m_autoUpdatePosition, true);
|
||||
|
||||
return true;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
|
@ -22,7 +22,8 @@ public:
|
||||
StationName,
|
||||
Altitude,
|
||||
SourceItemIndex,
|
||||
Multisampling
|
||||
Multisampling,
|
||||
AutoUpdatePosition
|
||||
};
|
||||
|
||||
Preferences();
|
||||
@ -60,6 +61,9 @@ public:
|
||||
float getAltitude() const { return m_altitude; }
|
||||
void setAltitude(float altitude) { m_altitude = altitude; }
|
||||
|
||||
bool getAutoUpdatePosition() const { return m_autoUpdatePosition; }
|
||||
void setAutoUpdatePosition(bool autoUpdatePosition) { m_autoUpdatePosition = autoUpdatePosition; }
|
||||
|
||||
QtMsgType getConsoleMinLogLevel() const { return m_consoleMinLogLevel; }
|
||||
void setConsoleMinLogLevel(const QtMsgType& minLogLevel) { m_consoleMinLogLevel = minLogLevel; }
|
||||
|
||||
@ -87,6 +91,7 @@ protected:
|
||||
float m_latitude; //!< Position of the station
|
||||
float m_longitude;
|
||||
float m_altitude; //!< Altitude in metres
|
||||
bool m_autoUpdatePosition; //!< Automatically update position from GPS
|
||||
|
||||
QtMsgType m_consoleMinLogLevel;
|
||||
QtMsgType m_fileMinLogLevel;
|
||||
|
213
sdrbase/util/android.cpp
Normal file
213
sdrbase/util/android.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#include "android.h"
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
|
||||
#include <QtCore/private/qandroidextras_p.h>
|
||||
#include <QJniObject>
|
||||
#include <QJniEnvironment>
|
||||
|
||||
void Android::sendIntent()
|
||||
{
|
||||
QJniObject url = QJniObject::fromString("iqsrc://-f 1090000000 -p 1234 -s 2000000 -a 127.0.0.1 -g 100");
|
||||
QJniObject intent = QJniObject::callStaticObjectMethod("android/content/Intent", "parseUri", "(Ljava/lang/String;I)Landroid/content/Intent;", url.object<jstring>(), 0x00000001); // Creates Intent(ACTION_VIEW, url)
|
||||
QtAndroidPrivate::startActivity(intent, 0, [](int requestCode, int resultCode, const QJniObject &data) {
|
||||
(void) data;
|
||||
|
||||
qDebug() << "MainCore::sendIntent " << requestCode << resultCode;
|
||||
});
|
||||
}
|
||||
|
||||
QStringList Android::listUSBDeviceSerials(int vid, int pid)
|
||||
{
|
||||
QStringList serials;
|
||||
QJniEnvironment jniEnv;
|
||||
|
||||
QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
|
||||
if (activity.isValid())
|
||||
{
|
||||
QJniObject serialsObj = activity.callObjectMethod("listUSBDeviceSerials", "(II)[Ljava/lang/String;", vid, pid);
|
||||
int serialsLen = jniEnv->GetArrayLength(serialsObj.object<jarray>());
|
||||
for (int i = 0; i < serialsLen; i++)
|
||||
{
|
||||
QJniObject arrayElement = jniEnv->GetObjectArrayElement(serialsObj.object<jobjectArray>(), i);
|
||||
QString serial = arrayElement.toString();
|
||||
serials.append(serial);
|
||||
}
|
||||
}
|
||||
|
||||
return serials;
|
||||
}
|
||||
|
||||
int Android::openUSBDevice(const QString &serial)
|
||||
{
|
||||
int fd = -1;
|
||||
QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
|
||||
if (activity.isValid())
|
||||
{
|
||||
QJniObject serialsObj = QJniObject::fromString(serial);
|
||||
fd = activity.callMethod<jint>("openUSBDevice", "(Ljava/lang/String;)I", serialsObj.object<jstring>());
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void Android::closeUSBDevice(int fd)
|
||||
{
|
||||
if (fd >= 0)
|
||||
{
|
||||
QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
|
||||
if (activity.isValid()) {
|
||||
activity.callMethod<void>("closeUSBDevice", "(I)V", fd);
|
||||
} else {
|
||||
qCritical() << "MainCore::closeUSBDevice: activity is not valid.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Android::moveTaskToBack()
|
||||
{
|
||||
QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
|
||||
if (activity.isValid()) {
|
||||
activity.callMethod<jboolean>("moveTaskToBack", "(Z)Z", true);
|
||||
}
|
||||
}
|
||||
|
||||
#else // QT_VERSION
|
||||
|
||||
#include <QtAndroid>
|
||||
#include <QAndroidIntent>
|
||||
#include <QAndroidJniObject>
|
||||
#include <QAndroidJniEnvironment>
|
||||
#include <QAndroidActivityResultReceiver>
|
||||
|
||||
void Android::sendIntent()
|
||||
{
|
||||
QAndroidJniObject url = QAndroidJniObject::fromString("iqsrc://-f 1090000000 -p 1234 -s 2000000 -a 127.0.0.1 -g 100");
|
||||
QAndroidJniObject intent = QAndroidJniObject::callStaticObjectMethod("android/content/Intent", "parseUri", "(Ljava/lang/String;I)Landroid/content/Intent;", url.object<jstring>(), 0x00000001); // Creates Intent(ACTION_VIEW, url)
|
||||
QtAndroid::startActivity(intent, 0, [](int requestCode, int resultCode, const QAndroidJniObject &data) {
|
||||
(void) data;
|
||||
|
||||
qDebug() << "MainCore::sendIntent " << requestCode << resultCode;
|
||||
});
|
||||
}
|
||||
|
||||
QStringList Android::listUSBDeviceSerials(int vid, int pid)
|
||||
{
|
||||
QStringList serials;
|
||||
QAndroidJniEnvironment jniEnv;
|
||||
|
||||
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
|
||||
if (activity.isValid())
|
||||
{
|
||||
QAndroidJniObject serialsObj = activity.callObjectMethod("listUSBDeviceSerials", "(II)[Ljava/lang/String;", vid, pid);
|
||||
int serialsLen = jniEnv->GetArrayLength(serialsObj.object<jarray>());
|
||||
for (int i = 0; i < serialsLen; i++)
|
||||
{
|
||||
QAndroidJniObject arrayElement = jniEnv->GetObjectArrayElement(serialsObj.object<jobjectArray>(), i);
|
||||
QString serial = arrayElement.toString();
|
||||
serials.append(serial);
|
||||
}
|
||||
}
|
||||
|
||||
return serials;
|
||||
}
|
||||
|
||||
int Android::openUSBDevice(const QString &serial)
|
||||
{
|
||||
int fd = -1;
|
||||
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
|
||||
if (activity.isValid())
|
||||
{
|
||||
QAndroidJniObject serialsObj = QAndroidJniObject::fromString(serial);
|
||||
fd = activity.callMethod<jint>("openUSBDevice", "(Ljava/lang/String;)I", serialsObj.object<jstring>());
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void Android::closeUSBDevice(int fd)
|
||||
{
|
||||
if (fd >= 0)
|
||||
{
|
||||
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
|
||||
if (activity.isValid()) {
|
||||
activity.callMethod<void>("closeUSBDevice", "(I)V", fd);
|
||||
} else {
|
||||
qCritical() << "MainCore::closeUSBDevice: activity is not valid.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Android::moveTaskToBack()
|
||||
{
|
||||
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
|
||||
if (activity.isValid()) {
|
||||
activity.callMethod<jboolean>("moveTaskToBack", "(Z)Z", true);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // QT6
|
||||
|
||||
// Redirect qDebug/qWarning to Android log, so we can view remotely with adb
|
||||
void Android::messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
|
||||
{
|
||||
QString report = msg;
|
||||
if (context.file && !QString(context.file).isEmpty())
|
||||
{
|
||||
report += " in file ";
|
||||
report += QString(context.file);
|
||||
report += " line ";
|
||||
report += QString::number(context.line);
|
||||
}
|
||||
if (context.function && !QString(context.function).isEmpty())
|
||||
{
|
||||
report += +" function ";
|
||||
report += QString(context.function);
|
||||
}
|
||||
const char * const local = report.toLocal8Bit().constData();
|
||||
const char * const applicationName = "sdrangel";
|
||||
switch (type)
|
||||
{
|
||||
case QtDebugMsg:
|
||||
__android_log_write(ANDROID_LOG_DEBUG, applicationName, local);
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
__android_log_write(ANDROID_LOG_INFO, applicationName, local);
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
__android_log_write(ANDROID_LOG_WARN, applicationName, local);
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
__android_log_write(ANDROID_LOG_ERROR, applicationName, local);
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
default:
|
||||
__android_log_write(ANDROID_LOG_FATAL, applicationName, local);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ANDROID
|
44
sdrbase/util/android.h
Normal file
44
sdrbase/util/android.h
Normal file
@ -0,0 +1,44 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SDRBASE_ANDROID_H_
|
||||
#define SDRBASE_ANDROID_H_
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QString>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
// Android specific functions
|
||||
class SDRBASE_API Android
|
||||
{
|
||||
public:
|
||||
|
||||
static void sendIntent();
|
||||
static QStringList listUSBDeviceSerials(int vid, int pid);
|
||||
static int openUSBDevice(const QString &serial);
|
||||
static void closeUSBDevice(int fd);
|
||||
static void moveTaskToBack();
|
||||
static void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
|
||||
|
||||
};
|
||||
|
||||
#endif // ANDROID
|
||||
|
||||
#endif // SDRBASE_ANDROID_H_
|
@ -27,11 +27,26 @@
|
||||
|
||||
#include "settings/configuration.h"
|
||||
|
||||
ConfigurationsDialog::ConfigurationsDialog(QWidget* parent) :
|
||||
ConfigurationsDialog::ConfigurationsDialog(bool openOnly, QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ConfigurationsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
if (openOnly)
|
||||
{
|
||||
ui->buttonBox->setStandardButtons(QDialogButtonBox::Close | QDialogButtonBox::Open);
|
||||
ui->configurationDelete->setVisible(false);
|
||||
ui->configurationEdit->setVisible(false);
|
||||
ui->configurationExport->setVisible(false);
|
||||
ui->configurationImport->setVisible(false);
|
||||
ui->configurationLoad->setVisible(false);
|
||||
ui->configurationSave->setVisible(false);
|
||||
ui->configurationUpdate->setVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->description->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigurationsDialog::~ConfigurationsDialog()
|
||||
@ -354,9 +369,7 @@ void ConfigurationsDialog::on_configurationExport_clicked()
|
||||
tr("Open preset export file"),
|
||||
".",
|
||||
tr("Configuration export files (*.cfgx)"),
|
||||
0,
|
||||
QFileDialog::DontUseNativeDialog
|
||||
);
|
||||
0);
|
||||
|
||||
if (fileName != "")
|
||||
{
|
||||
@ -404,8 +417,7 @@ void ConfigurationsDialog::on_configurationImport_clicked()
|
||||
tr("Open preset export file"),
|
||||
".",
|
||||
tr("Preset export files (*.cfgx)"),
|
||||
0,
|
||||
QFileDialog::DontUseNativeDialog
|
||||
0
|
||||
);
|
||||
|
||||
if (fileName != "")
|
||||
@ -497,3 +509,9 @@ void ConfigurationsDialog::deleteConfigurationGroup(const QString& groupName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurationsDialog::accept()
|
||||
{
|
||||
on_configurationLoad_clicked();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ namespace Ui {
|
||||
class SDRGUI_API ConfigurationsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ConfigurationsDialog(QWidget* parent = nullptr);
|
||||
explicit ConfigurationsDialog(bool openOnly, QWidget* parent = nullptr);
|
||||
~ConfigurationsDialog();
|
||||
void setConfigurations(QList<Configuration*>* configurations) { m_configurations = configurations; }
|
||||
void populateTree();
|
||||
@ -71,6 +71,7 @@ private slots:
|
||||
void on_configurationLoad_clicked();
|
||||
void on_configurationTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
|
||||
void on_configurationTree_itemActivated(QTreeWidgetItem *item, int column);
|
||||
void accept() override;
|
||||
|
||||
signals:
|
||||
void saveConfiguration(Configuration*);
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>392</width>
|
||||
<height>414</height>
|
||||
<width>410</width>
|
||||
<height>424</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
@ -19,218 +19,207 @@
|
||||
<property name="windowTitle">
|
||||
<string>Configurations</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>40</x>
|
||||
<y>380</y>
|
||||
<width>341</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>10</y>
|
||||
<width>392</width>
|
||||
<height>310</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="configurationsTree">
|
||||
<property name="toolTip">
|
||||
<string>List of configurations</string>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>5</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="description">
|
||||
<property name="text">
|
||||
<string>Select configuration to load:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="configurationsTree">
|
||||
<property name="toolTip">
|
||||
<string>List of configurations</string>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>5</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="configurationsControl">
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationSave">
|
||||
<property name="toolTip">
|
||||
<string>Save current workspaces configuration as new configuration</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>330</y>
|
||||
<width>392</width>
|
||||
<height>34</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="configurationsControl">
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationSave">
|
||||
<property name="toolTip">
|
||||
<string>Save current workspaces configuration as new configuration</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/create.png</normaloff>:/create.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationUpdate">
|
||||
<property name="toolTip">
|
||||
<string>Update selected configuration with current workspaces configuration</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationEdit">
|
||||
<property name="toolTip">
|
||||
<string>Edit configuration details</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/edit.png</normaloff>:/edit.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationExport">
|
||||
<property name="toolTip">
|
||||
<string>Export current configuration to file</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/export.png</normaloff>:/export.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationImport">
|
||||
<property name="toolTip">
|
||||
<string>Import configuration from file into current group</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/import.png</normaloff>:/import.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationDelete">
|
||||
<property name="toolTip">
|
||||
<string>Delete selected configuration</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/bin.png</normaloff>:/bin.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationLoad">
|
||||
<property name="toolTip">
|
||||
<string>Load selected configuration</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/load.png</normaloff>:/load.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/create.png</normaloff>:/create.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationUpdate">
|
||||
<property name="toolTip">
|
||||
<string>Update selected configuration with current workspaces configuration</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationEdit">
|
||||
<property name="toolTip">
|
||||
<string>Edit configuration details</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/edit.png</normaloff>:/edit.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationExport">
|
||||
<property name="toolTip">
|
||||
<string>Export current configuration to file</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/export.png</normaloff>:/export.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationImport">
|
||||
<property name="toolTip">
|
||||
<string>Import configuration from file into current group</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/import.png</normaloff>:/import.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationDelete">
|
||||
<property name="toolTip">
|
||||
<string>Delete selected configuration</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/bin.png</normaloff>:/bin.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="configurationLoad">
|
||||
<property name="toolTip">
|
||||
<string>Load selected configuration</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/load.png</normaloff>:/load.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../resources/res.qrc"/>
|
||||
|
@ -292,8 +292,7 @@ void DeviceSetPresetsDialog::on_presetExport_clicked()
|
||||
tr("Open preset export file"),
|
||||
".",
|
||||
tr("Preset export files (*.prex)"),
|
||||
0,
|
||||
QFileDialog::DontUseNativeDialog
|
||||
0
|
||||
);
|
||||
|
||||
if (fileName != "")
|
||||
@ -342,8 +341,7 @@ void DeviceSetPresetsDialog::on_presetImport_clicked()
|
||||
tr("Open preset export file"),
|
||||
".",
|
||||
tr("Preset export files (*.prex)"),
|
||||
0,
|
||||
QFileDialog::DontUseNativeDialog
|
||||
0
|
||||
);
|
||||
|
||||
if (fileName != "")
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>324</width>
|
||||
<height>229</height>
|
||||
<height>201</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
@ -19,44 +19,24 @@
|
||||
<property name="windowTitle">
|
||||
<string>My Position</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>My Station Position</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="latitudeLabel">
|
||||
<property name="text">
|
||||
<string>Latitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="longitudeLabel">
|
||||
<property name="text">
|
||||
<string>Longitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="longitudeSpinBox">
|
||||
<property name="toolTip">
|
||||
<string>Longitude in decimal degrees</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="latitudeSpinBox">
|
||||
<property name="toolTip">
|
||||
<string>Latitude in decimal degrees</string>
|
||||
@ -72,24 +52,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="altitudeSpinBox">
|
||||
<property name="toolTip">
|
||||
<string>Altitude in metres</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>50000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="altitudeLabel">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="latitudeLabel">
|
||||
<property name="text">
|
||||
<string>Altitude (m)</string>
|
||||
<string>Latitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="name">
|
||||
<property name="toolTip">
|
||||
<string>Enter the name of your station</string>
|
||||
@ -99,6 +69,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="altitudeLabel">
|
||||
<property name="text">
|
||||
<string>Altitude (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="longitudeLabel">
|
||||
<property name="text">
|
||||
<string>Longitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="text">
|
||||
@ -106,19 +90,66 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="autoUpdatePosition">
|
||||
<property name="toolTip">
|
||||
<string>Automatically update position using GPS (when available)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="longitudeSpinBox">
|
||||
<property name="toolTip">
|
||||
<string>Longitude in decimal degrees</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="autoUpdatePositionLabel">
|
||||
<property name="text">
|
||||
<string>Auto-update from GPS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QToolButton" name="gps">
|
||||
<property name="toolTip">
|
||||
<string>Set position using GPS (if available)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/gps.png</normaloff>:/gps.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="altitudeSpinBox">
|
||||
<property name="toolTip">
|
||||
<string>Altitude in metres</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>50000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
@ -127,7 +158,9 @@
|
||||
<tabstop>longitudeSpinBox</tabstop>
|
||||
<tabstop>altitudeSpinBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../resources/res.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
|
@ -2,9 +2,6 @@
|
||||
// Copyright (C) 2016 F4EXB //
|
||||
// written by Edouard Griffiths //
|
||||
// //
|
||||
// OpenGL interface modernization. //
|
||||
// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
@ -21,7 +18,9 @@
|
||||
|
||||
#include "gui/mypositiondialog.h"
|
||||
#include "ui_myposdialog.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include <QGeoCoordinate>
|
||||
|
||||
MyPositionDialog::MyPositionDialog(MainSettings& mainSettings, QWidget* parent) :
|
||||
QDialog(parent),
|
||||
@ -33,6 +32,7 @@ MyPositionDialog::MyPositionDialog(MainSettings& mainSettings, QWidget* parent)
|
||||
ui->latitudeSpinBox->setValue(m_mainSettings.getLatitude());
|
||||
ui->longitudeSpinBox->setValue(m_mainSettings.getLongitude());
|
||||
ui->altitudeSpinBox->setValue(m_mainSettings.getAltitude());
|
||||
ui->autoUpdatePosition->setChecked(m_mainSettings.getAutoUpdatePosition());
|
||||
}
|
||||
|
||||
MyPositionDialog::~MyPositionDialog()
|
||||
@ -46,5 +46,22 @@ void MyPositionDialog::accept()
|
||||
m_mainSettings.setLatitude(ui->latitudeSpinBox->value());
|
||||
m_mainSettings.setLongitude(ui->longitudeSpinBox->value());
|
||||
m_mainSettings.setAltitude(ui->altitudeSpinBox->value());
|
||||
m_mainSettings.setAutoUpdatePosition(ui->autoUpdatePosition->isChecked());
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void MyPositionDialog::on_gps_clicked()
|
||||
{
|
||||
const QGeoPositionInfo& position = MainCore::instance()->getPosition();
|
||||
if (position.isValid())
|
||||
{
|
||||
QGeoCoordinate coord = position.coordinate();
|
||||
ui->latitudeSpinBox->setValue(coord.latitude());
|
||||
ui->longitudeSpinBox->setValue(coord.longitude());
|
||||
ui->altitudeSpinBox->setValue(coord.altitude());
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "MyPositionDialog::on_gps_clicked: Position is not valid.";
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,6 @@
|
||||
// Copyright (C) 2016 F4EXB //
|
||||
// written by Edouard Griffiths //
|
||||
// //
|
||||
// OpenGL interface modernization. //
|
||||
// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
@ -43,6 +40,7 @@ private:
|
||||
|
||||
private slots:
|
||||
void accept();
|
||||
void on_gps_clicked();
|
||||
};
|
||||
|
||||
#endif /* SDRBASE_GUI_MYPOSITIONDIALOG_H_ */
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "samplingdevicedialog.h"
|
||||
#include "ui_samplingdevicedialog.h"
|
||||
#include "device/deviceenumerator.h"
|
||||
|
||||
#include "maincore.h"
|
||||
|
||||
SamplingDeviceDialog::SamplingDeviceDialog(int deviceType, QWidget* parent) :
|
||||
QDialog(parent),
|
||||
@ -32,19 +32,7 @@ SamplingDeviceDialog::SamplingDeviceDialog(int deviceType, QWidget* parent) :
|
||||
m_hasChanged(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QList<QString> deviceDisplayNames;
|
||||
|
||||
if (m_deviceType == 0) { // Single Rx
|
||||
DeviceEnumerator::instance()->listRxDeviceNames(deviceDisplayNames, m_deviceIndexes);
|
||||
} else if (m_deviceType == 1) { // Single Tx
|
||||
DeviceEnumerator::instance()->listTxDeviceNames(deviceDisplayNames, m_deviceIndexes);
|
||||
} else if (m_deviceType == 2) { // MIMO
|
||||
DeviceEnumerator::instance()->listMIMODeviceNames(deviceDisplayNames, m_deviceIndexes);
|
||||
}
|
||||
|
||||
QStringList devicesNamesList(deviceDisplayNames);
|
||||
ui->deviceSelect->addItems(devicesNamesList);
|
||||
on_refreshDevices_clicked();
|
||||
}
|
||||
|
||||
SamplingDeviceDialog::~SamplingDeviceDialog()
|
||||
@ -58,6 +46,23 @@ int SamplingDeviceDialog::exec()
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
void SamplingDeviceDialog::displayDevices()
|
||||
{
|
||||
QList<QString> deviceDisplayNames;
|
||||
|
||||
m_deviceIndexes.clear();
|
||||
if (m_deviceType == 0) { // Single Rx
|
||||
DeviceEnumerator::instance()->listRxDeviceNames(deviceDisplayNames, m_deviceIndexes);
|
||||
} else if (m_deviceType == 1) { // Single Tx
|
||||
DeviceEnumerator::instance()->listTxDeviceNames(deviceDisplayNames, m_deviceIndexes);
|
||||
} else if (m_deviceType == 2) { // MIMO
|
||||
DeviceEnumerator::instance()->listMIMODeviceNames(deviceDisplayNames, m_deviceIndexes);
|
||||
}
|
||||
|
||||
ui->deviceSelect->clear();
|
||||
ui->deviceSelect->addItems(deviceDisplayNames);
|
||||
}
|
||||
|
||||
void SamplingDeviceDialog::setSelectedDeviceIndex(int deviceIndex)
|
||||
{
|
||||
ui->deviceSelect->blockSignals(true);
|
||||
@ -77,6 +82,21 @@ void SamplingDeviceDialog::on_deviceSelect_currentIndexChanged(int index)
|
||||
m_hasChanged = true;
|
||||
}
|
||||
|
||||
void SamplingDeviceDialog::on_refreshDevices_clicked()
|
||||
{
|
||||
PluginManager *pluginManager = MainCore::instance()->getPluginManager();
|
||||
|
||||
if (m_deviceType == 0) {
|
||||
DeviceEnumerator::instance()->enumerateRxDevices(pluginManager);
|
||||
} else if (m_deviceType == 1) {
|
||||
DeviceEnumerator::instance()->enumerateTxDevices(pluginManager);
|
||||
} else if (m_deviceType == 2) {
|
||||
DeviceEnumerator::instance()->enumerateMIMODevices(pluginManager);
|
||||
}
|
||||
|
||||
displayDevices();
|
||||
}
|
||||
|
||||
void SamplingDeviceDialog::accept()
|
||||
{
|
||||
m_selectedDeviceIndex = m_deviceIndexes[ui->deviceSelect->currentIndex()];
|
||||
|
@ -50,8 +50,11 @@ private:
|
||||
std::vector<int> m_deviceIndexes;
|
||||
bool m_hasChanged;
|
||||
|
||||
void displayDevices();
|
||||
|
||||
private slots:
|
||||
void on_deviceSelect_currentIndexChanged(int index);
|
||||
void on_refreshDevices_clicked();
|
||||
void accept();
|
||||
void reject();
|
||||
};
|
||||
|
@ -31,8 +31,8 @@
|
||||
<property name="title">
|
||||
<string>Select from list</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="deviceSelect">
|
||||
<property name="font">
|
||||
<font>
|
||||
@ -42,6 +42,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="refreshDevices">
|
||||
<property name="toolTip">
|
||||
<string>Refresh list of devices</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -66,7 +80,9 @@
|
||||
<tabstops>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../resources/res.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
|
@ -501,7 +501,7 @@ void Workspace::stackVerticalSubWindows()
|
||||
|
||||
// Calculate spare vertical space, to be shared between non-fixed windows
|
||||
int spareSpacePerWindow;
|
||||
if (requiresVScrollBar) {
|
||||
if (requiresVScrollBar || (nonFixedWindows == 0)) {
|
||||
spareSpacePerWindow = 0;
|
||||
} else {
|
||||
spareSpacePerWindow = (mdiSize.height() - minHeight) / nonFixedWindows;
|
||||
|
@ -18,7 +18,9 @@
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressDialog>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QFileDialog>
|
||||
@ -31,10 +33,11 @@
|
||||
#include <QStandardPaths>
|
||||
#include <QDesktopServices>
|
||||
#include <QProcess>
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QAction>
|
||||
#include <QMenuBar>
|
||||
#include <QStatusBar>
|
||||
#include <QScreen>
|
||||
|
||||
#include "device/devicegui.h"
|
||||
#include "device/deviceapi.h"
|
||||
@ -68,6 +71,8 @@
|
||||
#include "gui/devicesetpresetsdialog.h"
|
||||
#include "gui/commandsdialog.h"
|
||||
#include "gui/configurationsdialog.h"
|
||||
#include "gui/dialogpositioner.h"
|
||||
#include "gui/welcomedialog.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/spectrumvis.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
@ -85,6 +90,9 @@
|
||||
#include "webapi/webapiserver.h"
|
||||
#include "webapi/webapiadapter.h"
|
||||
#include "commands/command.h"
|
||||
#ifdef ANDROID
|
||||
#include "util/android.h"
|
||||
#endif
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
@ -107,9 +115,17 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
|
||||
m_mainCore(MainCore::instance()),
|
||||
m_dspEngine(DSPEngine::instance()),
|
||||
m_lastEngineState(DeviceAPI::StNotStarted),
|
||||
m_dateTimeWidget(nullptr),
|
||||
m_showSystemWidget(nullptr),
|
||||
m_commandKeyReceiver(nullptr),
|
||||
m_fftWisdomProcess(nullptr)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
bool showWelcome = true;
|
||||
#else
|
||||
bool showWelcome = false;
|
||||
#endif
|
||||
|
||||
qDebug() << "MainWindow::MainWindow: start";
|
||||
setWindowTitle("SDRangel");
|
||||
|
||||
@ -134,10 +150,21 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
|
||||
splash->showStatusMessage("starting...", Qt::white);
|
||||
|
||||
setWindowIcon(QIcon(":/sdrangel_icon.png"));
|
||||
createMenuBar();
|
||||
createStatusBar();
|
||||
#ifndef ANDROID
|
||||
// To save screen space on Android, don't have menu bar. Instead menus are accessed via toolbar button
|
||||
createMenuBar(nullptr);
|
||||
createStatusBar();
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
if (screen()->isLandscape(screen()->primaryOrientation())) {
|
||||
setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::West);
|
||||
} else {
|
||||
setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::South);
|
||||
}
|
||||
#else
|
||||
setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::West);
|
||||
#endif
|
||||
setTabPosition(Qt::RightDockWidgetArea, QTabWidget::East);
|
||||
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
|
||||
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
|
||||
@ -146,6 +173,12 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
|
||||
|
||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleMessages()), Qt::QueuedConnection);
|
||||
|
||||
connect(screen(), &QScreen::orientationChanged, this, &MainWindow::orientationChanged);
|
||||
screen()->setOrientationUpdateMask(Qt::PortraitOrientation
|
||||
| Qt::LandscapeOrientation
|
||||
| Qt::InvertedPortraitOrientation
|
||||
| Qt::InvertedLandscapeOrientation);
|
||||
|
||||
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
||||
m_statusTimer.start(1000);
|
||||
|
||||
@ -209,6 +242,16 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
|
||||
{
|
||||
qDebug() << "MainWindow::MainWindow: no or empty current configuration, creating empty workspace...";
|
||||
addWorkspace();
|
||||
|
||||
// If no configurations, load some basic examples
|
||||
if (m_mainCore->m_settings.getConfigurations()->size() == 0) {
|
||||
loadDefaultConfigurations();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only show welcome dialog first time program is run
|
||||
showWelcome = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,6 +283,16 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
|
||||
restoreGeometry(qUncompress(QByteArray::fromBase64(s.value("mainWindowGeometry").toByteArray())));
|
||||
restoreState(qUncompress(QByteArray::fromBase64(s.value("mainWindowState").toByteArray())));
|
||||
|
||||
if (showWelcome)
|
||||
{
|
||||
// Show welcome dialog
|
||||
WelcomeDialog welcomeDialog(this);
|
||||
new DialogPositioner(&welcomeDialog, true);
|
||||
welcomeDialog.exec();
|
||||
// Show configurations
|
||||
openConfigurationDialog(true);
|
||||
}
|
||||
|
||||
qDebug() << "MainWindow::MainWindow: end";
|
||||
}
|
||||
|
||||
@ -340,6 +393,11 @@ void MainWindow::sampleSourceAdd(Workspace *deviceWorkspace, Workspace *spectrum
|
||||
deviceWorkspace->addToMdiArea(m_deviceUIs.back()->m_deviceGUI);
|
||||
spectrumWorkspace->addToMdiArea(m_deviceUIs.back()->m_mainSpectrumGUI);
|
||||
emit m_mainCore->deviceSetAdded(deviceSetIndex, deviceAPI);
|
||||
|
||||
#ifdef ANDROID
|
||||
// Seemingly needed on some versions of Android, otherwise the new windows aren't always displayed??
|
||||
deviceWorkspace->repaint();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::sampleSourceCreate(
|
||||
@ -1165,7 +1223,9 @@ void MainWindow::loadSettings()
|
||||
m_mainCore->m_settings.load();
|
||||
m_mainCore->m_settings.sortPresets();
|
||||
m_mainCore->m_settings.sortCommands();
|
||||
m_mainCore->setLoggingOptions();
|
||||
if (m_mainCore->m_logger) {
|
||||
m_mainCore->setLoggingOptions();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::loadDeviceSetPresetSettings(const Preset* preset, int deviceSetIndex)
|
||||
@ -1230,6 +1290,59 @@ void MainWindow::saveFeatureSetPresetSettings(FeatureSetPreset* preset, int feat
|
||||
featureUI->saveFeatureSetSettings(preset);
|
||||
}
|
||||
|
||||
void MainWindow::loadDefaultConfigurations()
|
||||
{
|
||||
QDirIterator configurationsIt(":configurations", QDirIterator::Subdirectories);
|
||||
while (configurationsIt.hasNext())
|
||||
{
|
||||
QString group = configurationsIt.next();
|
||||
QDirIterator groupIt(group, {"*.cfgx"}, QDir::Files);
|
||||
while (groupIt.hasNext())
|
||||
{
|
||||
QFile file(groupIt.next());
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
QByteArray base64Str;
|
||||
QTextStream instream(&file);
|
||||
instream >> base64Str;
|
||||
file.close();
|
||||
|
||||
Configuration* configuration = MainCore::instance()->m_settings.newConfiguration("", "");
|
||||
configuration->deserialize(QByteArray::fromBase64(base64Str));
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "MainWindow::loadDefaultConfigurations: Failed to open configuration " << file.fileName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QDirIterator presetIt(":presets", QDirIterator::Subdirectories);
|
||||
while (presetIt.hasNext())
|
||||
{
|
||||
QString group = presetIt.next();
|
||||
QDirIterator groupIt(group, {"*.prex"}, QDir::Files);
|
||||
while (groupIt.hasNext())
|
||||
{
|
||||
QFile file(groupIt.next());
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
QByteArray base64Str;
|
||||
QTextStream instream(&file);
|
||||
instream >> base64Str;
|
||||
file.close();
|
||||
|
||||
Preset* preset = MainCore::instance()->m_settings.newPreset("", "");
|
||||
preset->deserialize(QByteArray::fromBase64(base64Str));
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "MainWindow::loadDefaultConfigurations: Failed to open preset " << file.fileName();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::loadConfiguration(const Configuration *configuration, bool fromDialog)
|
||||
{
|
||||
qDebug("MainWindow::loadConfiguration: configuration [%s | %s] %d workspace(s) - %d device set(s) - %d feature(s)",
|
||||
@ -1240,23 +1353,26 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from
|
||||
configuration->getFeatureSetPreset().getFeatureCount()
|
||||
);
|
||||
|
||||
QMessageBox *waitBox = nullptr;
|
||||
QProgressDialog *waitBox = nullptr;
|
||||
|
||||
if (fromDialog)
|
||||
{
|
||||
waitBox = new QMessageBox(this);
|
||||
waitBox->setStandardButtons(QMessageBox::NoButton);
|
||||
waitBox->setWindowModality(Qt::NonModal);
|
||||
waitBox->setIcon(QMessageBox::Information);
|
||||
waitBox->setText("Loading configuration ");
|
||||
waitBox->setInformativeText("Deleting existing...");
|
||||
waitBox->setWindowTitle("Please wait");
|
||||
waitBox->show();
|
||||
waitBox->raise();
|
||||
waitBox = new QProgressDialog("Loading configuration...", "", 0, 100, this);
|
||||
waitBox->setWindowModality(Qt::WindowModal);
|
||||
waitBox->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
waitBox->setMinimumDuration(0);
|
||||
waitBox->setCancelButton(nullptr);
|
||||
waitBox->setValue(1);
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
||||
// Wipe out everything first
|
||||
|
||||
if (waitBox)
|
||||
{
|
||||
waitBox->setLabelText("Deleting existing...");
|
||||
waitBox->setValue(5);
|
||||
QApplication::processEvents();
|
||||
}
|
||||
// Device sets
|
||||
while (m_deviceUIs.size() > 0) {
|
||||
removeLastDeviceSet();
|
||||
@ -1276,6 +1392,7 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from
|
||||
{
|
||||
addWorkspace();
|
||||
m_workspaces[i]->setAutoStackOption(configuration->getWorkspaceAutoStackOptions()[i]);
|
||||
m_workspaces[i]->setTabSubWindowsOption(configuration->getWorkspaceTabSubWindowsOptions()[i]);
|
||||
}
|
||||
|
||||
if (m_workspaces.size() <= 0) { // cannot go further if there are no workspaces
|
||||
@ -1283,8 +1400,11 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from
|
||||
}
|
||||
|
||||
// Device sets
|
||||
if (waitBox) {
|
||||
waitBox->setInformativeText("Loading device sets...");
|
||||
if (waitBox)
|
||||
{
|
||||
waitBox->setLabelText("Loading device sets...");
|
||||
waitBox->setValue(25);
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
||||
const QList<Preset>& deviceSetPresets = configuration->getDeviceSetPresets();
|
||||
@ -1354,11 +1474,20 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from
|
||||
m_deviceUIs.back()->m_deviceGUI->restoreGeometry(deviceSetPreset.getDeviceGeometry());
|
||||
m_deviceUIs.back()->m_mainSpectrumGUI->restoreGeometry(deviceSetPreset.getSpectrumGeometry());
|
||||
m_deviceUIs.back()->loadDeviceSetSettings(&deviceSetPreset, m_pluginManager->getPluginAPI(), &m_workspaces, nullptr);
|
||||
|
||||
if (waitBox)
|
||||
{
|
||||
waitBox->setValue(waitBox->value() + 50/deviceSetPresets.size());
|
||||
QApplication::processEvents();
|
||||
}
|
||||
}
|
||||
|
||||
// Features
|
||||
if (waitBox) {
|
||||
waitBox->setInformativeText("Loading device sets...");
|
||||
if (waitBox)
|
||||
{
|
||||
waitBox->setLabelText("Loading feature sets...");
|
||||
waitBox->setValue(75);
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
||||
m_featureUIs[0]->loadFeatureSetSettings(
|
||||
@ -1381,8 +1510,11 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from
|
||||
}
|
||||
|
||||
// Lastly restore workspaces geometry
|
||||
if (waitBox) {
|
||||
waitBox->setInformativeText("Finalizing...");
|
||||
if (waitBox)
|
||||
{
|
||||
waitBox->setValue(90);
|
||||
waitBox->setLabelText("Finalizing...");
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
||||
for (int i = 0; i < configuration->getNumberOfWorkspaceGeometries(); i++)
|
||||
@ -1390,12 +1522,16 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from
|
||||
m_workspaces[i]->restoreGeometry(configuration->getWorkspaceGeometries()[i]);
|
||||
m_workspaces[i]->restoreGeometry(configuration->getWorkspaceGeometries()[i]);
|
||||
m_workspaces[i]->adjustSubWindowsAfterRestore();
|
||||
#ifdef ANDROID
|
||||
// On Android, workspaces seem to be restored to 0,20, rather than 0,0
|
||||
m_workspaces[i]->move(m_workspaces[i]->pos().x(), 0);
|
||||
// Need to call updateGeometry, otherwise sometimes the layout is corrupted
|
||||
m_workspaces[i]->updateGeometry();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (waitBox)
|
||||
{
|
||||
waitBox->close();
|
||||
delete waitBox;
|
||||
if (waitBox) {
|
||||
waitBox->setValue(100);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1430,6 +1566,7 @@ void MainWindow::saveConfiguration(Configuration *configuration)
|
||||
{
|
||||
configuration->getWorkspaceGeometries().push_back(workspace->saveGeometry());
|
||||
configuration->getWorkspaceAutoStackOptions().push_back(workspace->getAutoStackOption());
|
||||
configuration->getWorkspaceTabSubWindowsOptions().push_back(workspace->getTabSubWindowsOption());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1461,24 +1598,46 @@ QString MainWindow::openGLVersion()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::createMenuBar()
|
||||
void MainWindow::createMenuBar(QToolButton *button)
|
||||
{
|
||||
QMenuBar *menuBar = this->menuBar();
|
||||
QMenu *fileMenu, *viewMenu, *workspacesMenu, *preferencesMenu, *helpMenu;
|
||||
|
||||
if (button == nullptr)
|
||||
{
|
||||
QMenuBar *menuBar = this->menuBar();
|
||||
fileMenu = menuBar->addMenu("&File");
|
||||
viewMenu = menuBar->addMenu("&View");
|
||||
workspacesMenu = menuBar->addMenu("&Workspaces");
|
||||
preferencesMenu = menuBar->addMenu("&Preferences");
|
||||
helpMenu = menuBar->addMenu("&Help");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMenu *menu = new QMenu();
|
||||
fileMenu = new QMenu("&File");
|
||||
menu->addMenu(fileMenu);
|
||||
viewMenu = new QMenu("&View");
|
||||
menu->addMenu(viewMenu);
|
||||
workspacesMenu = new QMenu("&Workspaces");
|
||||
menu->addMenu(workspacesMenu);
|
||||
preferencesMenu = new QMenu("&Preferences");
|
||||
menu->addMenu(preferencesMenu);
|
||||
helpMenu = new QMenu("&Help");
|
||||
menu->addMenu(helpMenu);
|
||||
button->setMenu(menu);
|
||||
}
|
||||
|
||||
QMenu *fileMenu = menuBar->addMenu("&File");
|
||||
QAction *exitAction = fileMenu->addAction("E&xit");
|
||||
exitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
|
||||
exitAction->setToolTip("Exit");
|
||||
QObject::connect(exitAction, &QAction::triggered, this, &QMainWindow::close);
|
||||
|
||||
QMenu *viewMenu = menuBar->addMenu("&View");
|
||||
QAction *fullscreenAction = viewMenu->addAction("&Fullscreen");
|
||||
fullscreenAction->setShortcut(QKeySequence(Qt::Key_F11));
|
||||
fullscreenAction->setToolTip("Toggle fullscreen view");
|
||||
fullscreenAction->setCheckable(true);
|
||||
QObject::connect(fullscreenAction, &QAction::triggered, this, &MainWindow::on_action_View_Fullscreen_toggled);
|
||||
|
||||
QMenu *workspacesMenu = menuBar->addMenu("&Workspaces");
|
||||
QAction *newWorkspaceAction = workspacesMenu->addAction("&New");
|
||||
newWorkspaceAction->setToolTip("Add a new workspace");
|
||||
QObject::connect(newWorkspaceAction, &QAction::triggered, this, &MainWindow::addWorkspace);
|
||||
@ -1489,7 +1648,6 @@ void MainWindow::createMenuBar()
|
||||
removeEmptyWorkspacesAction->setToolTip("Remove empty workspaces");
|
||||
QObject::connect(removeEmptyWorkspacesAction, &QAction::triggered, this, &MainWindow::removeEmptyWorkspaces);
|
||||
|
||||
QMenu *preferencesMenu = menuBar->addMenu("&Preferences");
|
||||
QAction *configurationsAction = preferencesMenu->addAction("&Configurations...");
|
||||
configurationsAction->setToolTip("Manage configurations");
|
||||
QObject::connect(configurationsAction, &QAction::triggered, this, &MainWindow::on_action_Configurations_triggered);
|
||||
@ -1519,7 +1677,6 @@ void MainWindow::createMenuBar()
|
||||
saveAllAction->setToolTip("Save all current settings");
|
||||
QObject::connect(saveAllAction, &QAction::triggered, this, &MainWindow::on_action_saveAll_triggered);
|
||||
|
||||
QMenu *helpMenu = menuBar->addMenu("&Help");
|
||||
QAction *quickStartAction = helpMenu->addAction("&Quick start...");
|
||||
quickStartAction->setToolTip("Instructions for quick start");
|
||||
QObject::connect(quickStartAction, &QAction::triggered, this, &MainWindow::on_action_Quick_Start_triggered);
|
||||
@ -1882,7 +2039,11 @@ void MainWindow::handleWorkspaceVisibility(Workspace *workspace, bool visibility
|
||||
void MainWindow::addWorkspace()
|
||||
{
|
||||
int workspaceIndex = m_workspaces.size();
|
||||
m_workspaces.push_back(new Workspace(workspaceIndex));
|
||||
Workspace *workspace = new Workspace(workspaceIndex);
|
||||
m_workspaces.push_back(workspace);
|
||||
if (workspace->getMenuButton()) {
|
||||
createMenuBar(workspace->getMenuButton());
|
||||
}
|
||||
QStringList featureNames;
|
||||
m_pluginManager->listFeatures(featureNames);
|
||||
m_workspaces.back()->addAvailableFeatures(featureNames);
|
||||
@ -1923,6 +2084,13 @@ void MainWindow::addWorkspace()
|
||||
&MainWindow::openFeaturePresetsDialog
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
m_workspaces.back(),
|
||||
&Workspace::configurationPresetsDialogRequested,
|
||||
this,
|
||||
&MainWindow::on_action_Configurations_triggered
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
m_workspaces.back(),
|
||||
&Workspace::startAllDevices,
|
||||
@ -1951,7 +2119,7 @@ void MainWindow::addWorkspace()
|
||||
// tabBars.back()->setStyleSheet("QTabBar::tab:selected { background: rgb(128,70,0); }"); // change text color so it is visible
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::viewAllWorkspaces()
|
||||
{
|
||||
@ -2006,6 +2174,13 @@ void MainWindow::removeEmptyWorkspaces()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
// Need at least one workspace on Android, as no menus without
|
||||
if (m_workspaces.size() == 0) {
|
||||
addWorkspace();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::on_action_View_Fullscreen_toggled(bool checked)
|
||||
@ -2063,7 +2238,12 @@ void MainWindow::on_action_Loaded_Plugins_triggered()
|
||||
|
||||
void MainWindow::on_action_Configurations_triggered()
|
||||
{
|
||||
ConfigurationsDialog dialog(this);
|
||||
openConfigurationDialog(false);
|
||||
}
|
||||
|
||||
void MainWindow::openConfigurationDialog(bool openOnly)
|
||||
{
|
||||
ConfigurationsDialog dialog(openOnly, this);
|
||||
dialog.setConfigurations(m_mainCore->m_settings.getConfigurations());
|
||||
dialog.populateTree();
|
||||
QObject::connect(
|
||||
@ -2078,24 +2258,28 @@ void MainWindow::on_action_Configurations_triggered()
|
||||
this,
|
||||
[=](const Configuration* configuration) { this->loadConfiguration(configuration, true); }
|
||||
);
|
||||
new DialogPositioner(&dialog, true);
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Audio_triggered()
|
||||
{
|
||||
AudioDialogX audioDialog(m_dspEngine->getAudioDeviceManager(), this);
|
||||
new DialogPositioner(&audioDialog, true);
|
||||
audioDialog.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Graphics_triggered()
|
||||
{
|
||||
GraphicsDialog graphicsDialog(m_mainCore->m_settings, this);
|
||||
new DialogPositioner(&graphicsDialog, true);
|
||||
graphicsDialog.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Logging_triggered()
|
||||
{
|
||||
LoggingDialog loggingDialog(m_mainCore->m_settings, this);
|
||||
new DialogPositioner(&loggingDialog, true);
|
||||
loggingDialog.exec();
|
||||
m_mainCore->setLoggingOptions();
|
||||
}
|
||||
@ -2103,6 +2287,7 @@ void MainWindow::on_action_Logging_triggered()
|
||||
void MainWindow::on_action_My_Position_triggered()
|
||||
{
|
||||
MyPositionDialog myPositionDialog(m_mainCore->m_settings, this);
|
||||
new DialogPositioner(&myPositionDialog, true);
|
||||
myPositionDialog.exec();
|
||||
}
|
||||
|
||||
@ -2110,6 +2295,7 @@ void MainWindow::on_action_DeviceUserArguments_triggered()
|
||||
{
|
||||
qDebug("MainWindow::on_action_DeviceUserArguments_triggered");
|
||||
DeviceUserArgsDialog deviceUserArgsDialog(DeviceEnumerator::instance(), m_mainCore->m_settings.getDeviceUserArgs(), this);
|
||||
new DialogPositioner(&deviceUserArgsDialog, true);
|
||||
deviceUserArgsDialog.exec();
|
||||
}
|
||||
|
||||
@ -2121,6 +2307,7 @@ void MainWindow::on_action_commands_triggered()
|
||||
commandsDialog.setApiPort(m_apiServer->getPort());
|
||||
commandsDialog.setCommandKeyReceiver(m_commandKeyReceiver);
|
||||
commandsDialog.populateTree();
|
||||
new DialogPositioner(&commandsDialog, true);
|
||||
commandsDialog.exec();
|
||||
}
|
||||
|
||||
@ -2140,6 +2327,7 @@ void MainWindow::on_action_FFT_triggered()
|
||||
this,
|
||||
SLOT(fftWisdomProcessFinished(int, QProcess::ExitStatus)));
|
||||
FFTWisdomDialog fftWisdomDialog(m_fftWisdomProcess, this);
|
||||
new DialogPositioner(&fftWisdomDialog, true);
|
||||
|
||||
if (fftWisdomDialog.exec() == QDialog::Rejected)
|
||||
{
|
||||
@ -2790,6 +2978,7 @@ void MainWindow::openFeaturePresetsDialog(QPoint p, Workspace *workspace)
|
||||
dialog.setWorkspaces(&m_workspaces);
|
||||
dialog.populateTree();
|
||||
dialog.move(p);
|
||||
new DialogPositioner(&dialog, true);
|
||||
dialog.exec();
|
||||
|
||||
if (dialog.wasPresetLoaded())
|
||||
@ -2820,6 +3009,7 @@ void MainWindow::openDeviceSetPresetsDialog(QPoint p, DeviceGUI *deviceGUI)
|
||||
dialog.setWorkspaces(&m_workspaces);
|
||||
dialog.populateTree((int) deviceGUI->getDeviceType());
|
||||
dialog.move(p);
|
||||
new DialogPositioner(&dialog, true);
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
@ -2840,7 +3030,9 @@ void MainWindow::on_action_About_triggered()
|
||||
|
||||
void MainWindow::updateStatus()
|
||||
{
|
||||
m_dateTimeWidget->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss t"));
|
||||
if (m_dateTimeWidget) {
|
||||
m_dateTimeWidget->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss t"));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release)
|
||||
@ -2862,3 +3054,30 @@ void MainWindow::commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifie
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
if (event->key() == Qt::Key_Back)
|
||||
{
|
||||
// On Android, we don't want to exit when back key is pressed, just run in the background
|
||||
Android::moveTaskToBack();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
QMainWindow::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::orientationChanged(Qt::ScreenOrientation orientation)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
// Adjust workspace tab position, to leave max space for MDI windows
|
||||
if ((orientation == Qt::LandscapeOrientation) || (orientation == Qt::InvertedLandscapeOrientation)) {
|
||||
setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::West);
|
||||
} else {
|
||||
setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::South);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
class QLabel;
|
||||
class QTreeWidgetItem;
|
||||
class QDir;
|
||||
class QToolButton;
|
||||
|
||||
class DSPEngine;
|
||||
class DSPDeviceSourceEngine;
|
||||
@ -136,7 +137,7 @@ private:
|
||||
void saveFeatureSetPresetSettings(FeatureSetPreset* preset, int featureSetIndex);
|
||||
|
||||
QString openGLVersion();
|
||||
void createMenuBar();
|
||||
void createMenuBar(QToolButton *button);
|
||||
void createStatusBar();
|
||||
void closeEvent(QCloseEvent*);
|
||||
void applySettings();
|
||||
@ -171,6 +172,9 @@ private:
|
||||
|
||||
bool handleMessage(const Message& cmd);
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
private slots:
|
||||
void handleMessages();
|
||||
void handleWorkspaceVisibility(Workspace *workspace, bool visibility);
|
||||
@ -194,6 +198,8 @@ private slots:
|
||||
void addWorkspace();
|
||||
void viewAllWorkspaces();
|
||||
void removeEmptyWorkspaces();
|
||||
void openConfigurationDialog(bool openOnly);
|
||||
void loadDefaultConfigurations();
|
||||
void loadConfiguration(const Configuration *configuration, bool fromDialog = false);
|
||||
void saveConfiguration(Configuration *configuration);
|
||||
void sampleSourceAdd(Workspace *deviceWorkspace, Workspace *spectrumWorkspace, int deviceIndex);
|
||||
@ -215,6 +221,7 @@ private slots:
|
||||
void openDeviceSetPresetsDialog(QPoint p, DeviceGUI *deviceGUI);
|
||||
void commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release);
|
||||
void fftWisdomProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void orientationChanged(Qt::ScreenOrientation orientation);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_MAINWINDOW_H
|
||||
|
1
settings/configurations/airspyhf/radioclockeu.cfgx
Normal file
1
settings/configurations/airspyhf/radioclockeu.cfgx
Normal file
@ -0,0 +1 @@
|
||||
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
|
1
settings/configurations/rtlsdr/adsb.cfgx
Normal file
1
settings/configurations/rtlsdr/adsb.cfgx
Normal file
@ -0,0 +1 @@
|
||||
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
|
1
settings/configurations/rtlsdr/ais.cfgx
Normal file
1
settings/configurations/rtlsdr/ais.cfgx
Normal file
File diff suppressed because one or more lines are too long
1
settings/configurations/rtlsdr/apt.cfgx
Normal file
1
settings/configurations/rtlsdr/apt.cfgx
Normal file
File diff suppressed because one or more lines are too long
1
settings/configurations/rtlsdr/dab.cfgx
Normal file
1
settings/configurations/rtlsdr/dab.cfgx
Normal file
@ -0,0 +1 @@
|
||||
kAABAXABB1JUTCBTRFJwAgNEQUKAAxuQAAEBcAEHZGVmYXVsdHACB25vIG5hbWUAZAAAZAEBgGVCAdnQywADAAAAAAAAAAAAAAAAAZoAAAMlAAAAAAAAAAAAAAGaAAADJQAAAAAAAAAAAZsAAAAAAAAAAAAAAZoAAAMlAMgBAYHJBB2QAAEBcAEHZGVmYXVsdHACB25vIG5hbWUwAwQNcx2AgAQAgAXikAABAQABAgQAAAIAAAMBBEAEBAAAAABABQRCjAAAYAYBAWAHAQFgCAEAYAkBAAAKAQFgCwEBAA0BEgAOAQEADwEeYBABAQARATJAEgQ/KPXDABMBAQAUAQpgFQEAcBYJMTI3LjAuMC4xEBcCIrdgGAEAYBkBAQAaATJgGwEAABwBAmAdAQAAHgBgHwEAACABA3AhBUFuZ2VsACIBAgAjAAAkAicQACUCJxAAJgInEAAnAQVgKgEBACsBBQAsAQEALQEBAC4AYC8BAGAwAQAAZAAAbgCAKAQAAAAAgCkEAAAAAGAGAQEABwBgCAEBgAlCAdnQywADAAAAABOIAAAAAAAAFQMAAAFuAAATiAAAAAAAABUDAAABbv////8AAAAAAZsAABOIAAAAAAAAFQMAAAFuAAoAgAtCAdnQywADAAAAABOIAAAAAAAAFPMAAAEEAAATiAAAAAAAABTzAAABBP////8AAAAAAZsAABOIAAAAAAAAFPMAAAEEAAwAcA0cc2RyYW5nZWwuc2FtcGxlc291cmNlLnJ0bHNkcnAOCDAwMDAwMDAxAA8AABAAABQBAXAYHHNkcmFuZ2VsLnNhbXBsZXNvdXJjZS5ydGxzZHJwGQgwMDAwMDAwMQAaAIAbXpAAAQEAAgIBpAADABAEAGAFAQBgBgEAAAcBAgAIAx9AAGAJAQBgCgEAYAsBAGAMAQAgDQAQDgMmJaBgDwEAYBABAHARCTEyNy4wLjAuMRASAiK4EBMAYBQBAWAVAQAAyAEBcMkZc2RyYW5nZWwuY2hhbm5lbC5kYWJkZW1vZIHKAZWQAAEBAAEAAAIAcAMAQAQESbufQEAFBECgAABgBgEAcAcVU3lzdGVtIGRlZmF1bHQgZGV2aWNlgAgjkAABAQABABACBP9NaRlwAw9EQUIgRGVtb2R1bGF0b3IABwAQCQT/TWkZcAoPREFCIERlbW9kdWxhdG9yYAsBAHAMCTEyNy4wLjAuMRANAiK4EA4AEA8AgBCeAAAA/wAAAAAAAAAEAAAAIgBzAGUAdAB0AGkAbgBnAHMAQwBvAG4AdABhAGkAbgBlAHIAAAABAAAAIABwAHIAbwBnAHIAYQBtAEMAbwBuAHQAYQBpAG4AZQByAAAAAQAAABwAYwB1AHIAcgBlAG4AdABQAHIAbwBnAHIAYQBtAAAAAQAAABQAcwB0AGEAdABpAHMAdABpAGMAcwAAAAEAEQCAEkIB2dDLAAMAAAAAAAAAAAAAAAABmgAAAvwAAAAAAAAAAP////7////+AAAAAAIAAAABmwAAAAAAAAAAAAABmgAAAvxgEwEAAGQAAGUBAQBmAQIAyAH/AMkB/wDKAf8EASwBAWQBLQEABAGQAQFkAZEBAQ==
|
1
settings/configurations/rtlsdr/isspacket.cfgx
Normal file
1
settings/configurations/rtlsdr/isspacket.cfgx
Normal file
File diff suppressed because one or more lines are too long
1
settings/configurations/rtlsdr/radiosonde.cfgx
Normal file
1
settings/configurations/rtlsdr/radiosonde.cfgx
Normal file
File diff suppressed because one or more lines are too long
1
settings/presets/rtlsdr/noaa18.prex
Normal file
1
settings/presets/rtlsdr/noaa18.prex
Normal file
@ -0,0 +1 @@
|
||||
kAABAXABB1JUTCBTRFJwAgdOT0FBIDE4MAMECDgI0IAEAIEFAWmQAAEBAAECBAAAAgAAAwEEQAQEAAAAAEAFBEKMAABgBgEBYAcBAWAIAQBgCQEAAAoBAWALAQEADQESAA4BAQAPAR5gEAEBABEBMkASBD8o9cMAEwEBABQBCmAVAQBwFgkxMjcuMC4wLjEQFwIit2AYAQBgGQEBABoBMmAbAQAAHAECYB0BAAAeAGAfAQAAIAEDcCEFQW5nZWwAIgECACMAACQCJxAAJQInEAAmAicQACcBBWAqAQEAKwEFACwBAQAtAQEALgBgLwEAYDABAABkAABuAIAoiwAAAAMAAAAACDOcAAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADUAAAAACDgQoAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADgAAAAACCuswAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADmAKQQAAAAAYAYBAQAHAGAIAQGACUIB2dDLAAMAAAAAE4gAAAAAAAAVAwAAAW4AABOIAAAAAAAAFQMAAAFu/////wAAAAABmwAAE4gAAAAAAAAVAwAAAW4ACgCAC0IB2dDLAAMAAAAAAAAAAAAAAAABfwAAARAAAAAAAAAAFAAAAWsAAAEYAAAAAAIAAAABmwAAAAAAAAAAAAABfwAAARAADABwDRxzZHJhbmdlbC5zYW1wbGVzb3VyY2UucnRsc2RycA4IMDAwMDAwMDEADwAAEAAAFAEBcBgcc2RyYW5nZWwuc2FtcGxlc291cmNlLnJ0bHNkcnAZCDAwMDAwMDAxABoAgBtfkAABAQACAgGkAAMAEAQBA2AFAQBgBgEAAAcBAgAIAw9CQGAJAQBgCgEAYAsBAGAMAQAgDQAQDgMmJaBgDwEAYBABAHARCTEyNy4wLjAuMRASAiK4EBMAYBQBAWAVAQAAyAEBcMkZc2RyYW5nZWwuY2hhbm5lbC5hcHRkZW1vZIHKAYmQAAEBAAECVfAAAgBAAwRHHEAAQAQERoTQAGAFAQBgBgEBYAcBAGAIAQBgCQEAYAoBAAALAGAMAQBgDQEBcA4DQWxsYA8BAHAQAAARAgDIYBIBAAATARSAFCWQAAEBAAECVfAQAgT/2HCpcAMPQVBUIERlbW9kdWxhdG9yAAcAEBUE/9hwqXAWD0FQVCBEZW1vZHVsYXRvcmAXAQBwGAkxMjcuMC4wLjEQGQIiuBAaABAbAIAcWgAAAP8AAAAAAAAAAgAAACIAcwBlAHQAdABpAG4AZwBzAEMAbwBuAHQAYQBpAG4AZQByAAAAAQAAABwAaQBtAGEAZwBlAEMAbwBuAHQAYQBpAG4AZQByAAAAAWAdAQFgHgEAAB8BZAAgAgDIcCEAACIAACMBCgAkARRAJQQAAAAAQCYEAAAAAAAnAIAoQgHZ0MsAAwAAAAATiAAAAAAAABUiAAADBwAAE4gAAAAAAAAVIgAAAwf/////AAAAAAGbAAATiAAAAAAAABUiAAADB2ApAQA=
|
1
settings/presets/rtlsdr/noaa19.prex
Normal file
1
settings/presets/rtlsdr/noaa19.prex
Normal file
@ -0,0 +1 @@
|
||||
kAABAXABB1JUTCBTRFJwAgdOT0FBIDE5MAMECCuk8IAEAIEFAWmQAAEBAAECBAAAAgAAAwEEQAQEAAAAAEAFBEKMAABgBgEBYAcBAWAIAQBgCQEAAAoBAWALAQEADQESAA4BAQAPAR5gEAEBABEBMkASBD8o9cMAEwEBABQBCmAVAQBwFgkxMjcuMC4wLjEQFwIit2AYAQBgGQEBABoBMmAbAQAAHAECYB0BAAAeAGAfAQAAIAEDcCEFQW5nZWwAIgECACMAACQCJxAAJQInEAAmAicQACcBBWAqAQEAKwEFACwBAQAtAQEALgBgLwEAYDABAABkAABuAIAoiwAAAAMAAAAACDOcAAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADUAAAAACDgQoAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADgAAAAACCuswAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADmAKQQAAAAAYAYBAQAHAGAIAQGACUIB2dDLAAMAAAAAE4gAAAAAAAAVAwAAAW4AABOIAAAAAAAAFQMAAAFu/////wAAAAABmwAAE4gAAAAAAAAVAwAAAW4ACgCAC0IB2dDLAAMAAAAAAAAAAAAAAAABfwAAARAAAAAAAAAAFAAAAWsAAAEYAAAAAAIAAAABmwAAAAAAAAAAAAABfwAAARAADABwDRxzZHJhbmdlbC5zYW1wbGVzb3VyY2UucnRsc2RycA4IMDAwMDAwMDEADwAAEAAAFAEBcBgcc2RyYW5nZWwuc2FtcGxlc291cmNlLnJ0bHNkcnAZCDAwMDAwMDAxABoAgBtfkAABAQACAgGkAAMAEAQBA2AFAQBgBgEAAAcBAgAIAw9CQGAJAQBgCgEAYAsBAGAMAQAgDQAQDgMmJaBgDwEAYBABAHARCTEyNy4wLjAuMRASAiK4EBMAYBQBAWAVAQAAyAEBcMkZc2RyYW5nZWwuY2hhbm5lbC5hcHRkZW1vZIHKAYmQAAEBAAECVfAAAgBAAwRHHEAAQAQERoTQAGAFAQBgBgEBYAcBAGAIAQBgCQEAYAoBAAALAGAMAQBgDQEBcA4DQWxsYA8BAHAQAAARAgDIYBIBAAATARSAFCWQAAEBAAECVfAQAgT/2HCpcAMPQVBUIERlbW9kdWxhdG9yAAcAEBUE/9hwqXAWD0FQVCBEZW1vZHVsYXRvcmAXAQBwGAkxMjcuMC4wLjEQGQIiuBAaABAbAIAcWgAAAP8AAAAAAAAAAgAAACIAcwBlAHQAdABpAG4AZwBzAEMAbwBuAHQAYQBpAG4AZQByAAAAAQAAABwAaQBtAGEAZwBlAEMAbwBuAHQAYQBpAG4AZQByAAAAAWAdAQFgHgEAAB8BZAAgAgDIcCEAACIAACMBCgAkARRAJQQAAAAAQCYEAAAAAAAnAIAoQgHZ0MsAAwAAAAATiAAAAAAAABUiAAADBwAAE4gAAAAAAAAVIgAAAwf/////AAAAAAGbAAATiAAAAAAAABUiAAADB2ApAQA=
|
13
settings/settings.qrc
Normal file
13
settings/settings.qrc
Normal file
@ -0,0 +1,13 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>configurations/rtlsdr/adsb.cfgx</file>
|
||||
<file>configurations/rtlsdr/ais.cfgx</file>
|
||||
<file>configurations/rtlsdr/apt.cfgx</file>
|
||||
<file>configurations/rtlsdr/dab.cfgx</file>
|
||||
<file>configurations/rtlsdr/isspacket.cfgx</file>
|
||||
<file>configurations/rtlsdr/radiosonde.cfgx</file>
|
||||
<file>configurations/airspyhf/radioclockeu.cfgx</file>
|
||||
<file>presets/rtlsdr/noaa18.prex</file>
|
||||
<file>presets/rtlsdr/noaa19.prex</file>
|
||||
</qresource>
|
||||
</RCC>
|
Loading…
Reference in New Issue
Block a user