2017-10-22 19:12:43 +02:00
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
// written by Christian Daniel //
2023-11-19 13:31:45 +01:00
// Copyright (C) 2014 John Greb <hexameron@spam.no> //
// Copyright (C) 2015-2023 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// Copyright (C) 2017 Ziga S <ziga.svetina@gmail.com> //
// Copyright (C) 2018 beta-tester <alpha-beta-release@gmx.net> //
// Copyright (C) 2019 Vort <vvort@yandex.ru> //
// Copyright (C) 2019 Davide Gerhard <rainbow@irh.it> //
// Copyright (C) 2019 Stefan Biereigel <stefan@biereigel.de> //
// Copyright (C) 2020-2023 Jon Beniston, M7RCE <jon@beniston.com> //
// Copyright (C) 2022 CRD716 <crd716@gmail.com> //
// Copyright (C) 2023 Mohamed <mohamedadlyi@github.com> //
2017-10-22 19:12:43 +02:00
// //
// 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 //
2019-04-11 14:43:33 +02:00
// (at your option) any later version. //
2017-10-22 19:12:43 +02:00
// //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QInputDialog>
#include <QMessageBox>
2022-12-20 21:06:39 +00:00
#include <QProgressDialog>
2017-10-22 19:12:43 +02:00
#include <QLabel>
2022-12-20 21:06:39 +00:00
#include <QToolButton>
2017-10-22 19:12:43 +02:00
#include <QFile>
#include <QFileInfo>
#include <QFileDialog>
#include <QTextStream>
#include <QDateTime>
#include <QSysInfo>
2018-01-05 05:05:12 +01:00
#include <QKeyEvent>
2018-02-18 23:01:02 +01:00
#include <QResource>
2018-05-07 03:14:18 +02:00
#include <QFontDatabase>
2021-10-31 11:16:17 +01:00
#include <QStandardPaths>
2021-11-24 11:31:51 +00:00
#include <QDesktopServices>
2022-04-04 16:13:42 +02:00
#include <QProcess>
2022-12-20 21:06:39 +00:00
#include <QDirIterator>
2022-04-04 10:23:52 +02:00
#include <QAction>
#include <QMenuBar>
#include <QStatusBar>
2022-12-20 21:06:39 +00:00
#include <QScreen>
2022-04-04 10:23:52 +02:00
2020-10-09 08:52:30 +02:00
#include "device/devicegui.h"
2019-05-08 22:11:53 +02:00
#include "device/deviceapi.h"
2017-10-24 18:34:39 +02:00
#include "device/deviceuiset.h"
2020-10-11 08:27:58 +02:00
#include "device/deviceset.h"
2017-11-02 03:30:54 +01:00
#include "device/deviceenumerator.h"
2020-10-03 05:16:19 +02:00
#include "channel/channelapi.h"
2020-10-04 06:16:15 +02:00
#include "channel/channelgui.h"
2022-08-27 10:18:17 +01:00
#include "channel/channelwebapiutils.h"
2020-09-20 01:06:34 +02:00
#include "feature/featureuiset.h"
2020-10-11 00:22:42 +02:00
#include "feature/featureset.h"
2020-10-03 05:26:07 +02:00
#include "feature/feature.h"
2022-04-04 10:23:52 +02:00
#include "feature/featuregui.h"
2025-01-20 10:54:21 +00:00
#include "feature/featurewebapiutils.h"
2022-04-09 13:38:22 +02:00
#include "mainspectrum/mainspectrumgui.h"
2022-01-06 22:47:41 +01:00
#include "commands/commandkeyreceiver.h"
2017-10-22 19:12:43 +02:00
#include "gui/presetitem.h"
#include "gui/pluginsdialog.h"
#include "gui/aboutdialog.h"
#include "gui/audiodialog.h"
2022-06-18 12:35:44 +01:00
#include "gui/graphicsdialog.h"
2017-11-11 19:26:23 +01:00
#include "gui/loggingdialog.h"
2019-06-12 18:50:53 +02:00
#include "gui/deviceuserargsdialog.h"
2019-05-14 19:23:13 +02:00
#include "gui/sdrangelsplash.h"
2023-11-14 14:49:39 +00:00
#include "gui/mdiutils.h"
2017-10-22 19:12:43 +02:00
#include "gui/mypositiondialog.h"
2023-08-13 23:52:57 +01:00
#include "gui/fftdialog.h"
2021-11-02 01:04:43 +01:00
#include "gui/fftwisdomdialog.h"
2022-04-04 10:23:52 +02:00
#include "gui/workspace.h"
#include "gui/featurepresetsdialog.h"
2022-04-13 18:43:37 +02:00
#include "gui/devicesetpresetsdialog.h"
2022-04-04 16:13:42 +02:00
#include "gui/commandsdialog.h"
2022-04-05 16:26:57 +02:00
#include "gui/configurationsdialog.h"
2022-12-20 21:06:39 +00:00
#include "gui/dialogpositioner.h"
#include "gui/welcomedialog.h"
2023-08-13 23:52:57 +01:00
#include "gui/profiledialog.h"
2017-10-22 19:12:43 +02:00
#include "dsp/dspengine.h"
#include "dsp/spectrumvis.h"
#include "dsp/dspcommands.h"
#include "dsp/devicesamplesource.h"
#include "dsp/devicesamplesink.h"
2019-05-18 11:59:56 +02:00
#include "dsp/devicesamplemimo.h"
2019-05-08 22:11:53 +02:00
#include "dsp/dspdevicesourceengine.h"
#include "dsp/dspdevicesinkengine.h"
2019-05-18 11:59:56 +02:00
#include "dsp/dspdevicemimoengine.h"
2017-10-22 19:12:43 +02:00
#include "plugin/pluginapi.h"
#include "gui/glspectrum.h"
2017-11-12 02:23:55 +01:00
#include "loggerwithfile.h"
2017-11-17 08:52:15 +01:00
#include "webapi/webapirequestmapper.h"
#include "webapi/webapiserver.h"
2020-10-11 12:39:30 +02:00
#include "webapi/webapiadapter.h"
2018-01-04 11:11:53 +01:00
#include "commands/command.h"
2023-08-24 15:51:50 +01:00
#include "settings/serializableinterface.h"
2022-12-20 21:06:39 +00:00
#ifdef ANDROID
#include "util/android.h"
#endif
2017-10-22 19:12:43 +02:00
2025-06-20 15:43:01 +01:00
#include "remotetcpsinkstarter.h"
2017-10-24 18:34:39 +02:00
#include "mainwindow.h"
2018-03-23 18:08:38 +01:00
#include <audio/audiodevicemanager.h>
2022-04-04 10:23:52 +02:00
//#include "ui_mainwindow.h"
#include <QtWidgets/QApplication>
2017-10-24 18:34:39 +02:00
2017-10-22 19:12:43 +02:00
#include <string>
#include <QDebug>
2019-05-14 19:23:13 +02:00
#include <QSplashScreen>
2022-04-12 16:20:45 +02:00
#include <QProgressDialog>
2017-10-22 19:12:43 +02:00
2023-04-28 15:58:57 +01:00
#include "gui/accessiblevaluedial.h"
#include "gui/accessiblevaluedialz.h"
2024-08-24 13:17:02 +02:00
MainWindow * MainWindow :: m_instance = nullptr ;
2017-10-24 13:45:10 +02:00
2017-11-18 05:06:43 +01:00
MainWindow :: MainWindow ( qtwebapp :: LoggerWithFile * logger , const MainParser & parser , QWidget * parent ) :
2017-10-22 19:12:43 +02:00
QMainWindow ( parent ),
2022-04-04 10:23:52 +02:00
// ui(new Ui::MainWindow),
m_currentWorkspace ( nullptr ),
2020-10-10 20:08:11 +02:00
m_mainCore ( MainCore :: instance ()),
2017-10-22 19:12:43 +02:00
m_dspEngine ( DSPEngine :: instance ()),
2019-05-08 22:11:53 +02:00
m_lastEngineState ( DeviceAPI :: StNotStarted ),
2022-12-20 21:06:39 +00:00
m_dateTimeWidget ( nullptr ),
m_showSystemWidget ( nullptr ),
2022-10-25 22:53:10 +02:00
m_commandKeyReceiver ( nullptr ),
2023-08-13 23:52:57 +01:00
m_profileDialog ( nullptr ),
2024-10-10 13:57:11 +01:00
#if QT_CONFIG(process)
m_fftWisdomProcess ( nullptr ),
#endif
2025-06-20 15:43:01 +01:00
m_settingsSaved ( false ),
m_parser ( parser )
2017-10-22 19:12:43 +02:00
{
2023-04-28 15:58:57 +01:00
QAccessible :: installFactory ( AccessibleValueDial :: factory );
QAccessible :: installFactory ( AccessibleValueDialZ :: factory );
2017-10-22 19:12:43 +02:00
qDebug () << "MainWindow::MainWindow: start" ;
2022-04-28 00:19:54 +02:00
setWindowTitle ( "SDRangel" );
2017-10-22 19:12:43 +02:00
2024-10-10 13:57:11 +01:00
QApplication :: setOverrideCursor ( Qt :: WaitCursor );
2017-10-24 13:45:10 +02:00
m_instance = this ;
2020-10-10 20:08:11 +02:00
m_mainCore -> m_logger = logger ;
m_mainCore -> m_masterTabIndex = 0 ;
m_mainCore -> m_mainMessageQueue = & m_inputMessageQueue ;
m_mainCore -> m_settings . setAudioDeviceManager ( m_dspEngine -> getAudioDeviceManager ());
2017-10-22 19:12:43 +02:00
2018-05-07 03:14:18 +02:00
QFontDatabase :: addApplicationFont ( ":/LiberationSans-Regular.ttf" );
QFontDatabase :: addApplicationFont ( ":/LiberationMono-Regular.ttf" );
QFont font ( "Liberation Sans" );
font . setPointSize ( 9 );
qApp -> setFont ( font );
2019-05-14 19:23:13 +02:00
QPixmap logoPixmap ( ":/sdrangel_logo.png" );
2024-08-24 13:17:02 +02:00
auto * splash = new SDRangelSplash ( logoPixmap );
2019-06-09 23:10:12 +02:00
splash -> setMessageRect ( QRect ( 10 , 80 , 350 , 16 ));
2019-05-14 19:23:13 +02:00
splash -> show ();
2019-08-12 01:46:27 +02:00
splash -> showStatusMessage ( "starting..." , Qt :: white );
2019-05-14 19:23:13 +02:00
splash -> showStatusMessage ( "starting..." , Qt :: white );
2022-04-04 10:23:52 +02:00
setWindowIcon ( QIcon ( ":/sdrangel_icon.png" ));
2022-12-20 21:06:39 +00:00
#ifndef ANDROID
// To save screen space on Android, don't have menu bar. Instead menus are accessed via toolbar button
createMenuBar ( nullptr );
createStatusBar ();
#endif
2017-10-22 19:12:43 +02:00
2022-12-20 21:06:39 +00:00
#ifdef ANDROID
if ( screen () -> isLandscape ( screen () -> primaryOrientation ())) {
setTabPosition ( Qt :: LeftDockWidgetArea , QTabWidget :: West );
} else {
setTabPosition ( Qt :: LeftDockWidgetArea , QTabWidget :: South );
}
#else
2022-04-04 10:23:52 +02:00
setTabPosition ( Qt :: LeftDockWidgetArea , QTabWidget :: West );
2022-12-20 21:06:39 +00:00
#endif
2022-04-04 10:23:52 +02:00
setTabPosition ( Qt :: RightDockWidgetArea , QTabWidget :: East );
2017-10-22 19:12:43 +02:00
setCorner ( Qt :: TopLeftCorner , Qt :: LeftDockWidgetArea );
setCorner ( Qt :: BottomLeftCorner , Qt :: LeftDockWidgetArea );
setCorner ( Qt :: TopRightCorner , Qt :: RightDockWidgetArea );
setCorner ( Qt :: BottomRightCorner , Qt :: RightDockWidgetArea );
connect ( & m_inputMessageQueue , SIGNAL ( messageEnqueued ()), this , SLOT ( handleMessages ()), Qt :: QueuedConnection );
2022-12-20 21:06:39 +00:00
connect ( screen (), & QScreen :: orientationChanged , this , & MainWindow :: orientationChanged );
2023-03-13 03:11:22 +02:00
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
2022-12-20 21:06:39 +00:00
screen () -> setOrientationUpdateMask ( Qt :: PortraitOrientation
2024-08-24 13:17:02 +02:00
| Qt :: LandscapeOrientation
| Qt :: InvertedPortraitOrientation
| Qt :: InvertedLandscapeOrientation );
2023-03-13 03:11:22 +02:00
#endif
2022-12-20 21:06:39 +00:00
2017-10-22 19:12:43 +02:00
connect ( & m_statusTimer , SIGNAL ( timeout ()), this , SLOT ( updateStatus ()));
m_statusTimer . start ( 1000 );
2023-08-13 23:52:57 +01:00
splash -> showStatusMessage ( "load settings..." , Qt :: white );
qDebug () << "MainWindow::MainWindow: load settings..." ;
loadSettings ();
2020-03-12 06:27:38 +01:00
splash -> showStatusMessage ( "allocate FFTs..." , Qt :: white );
2021-10-31 11:16:17 +01:00
if ( parser . getFFTWFWisdomFileName (). length () != 0 )
{
m_dspEngine -> createFFTFactory ( parser . getFFTWFWisdomFileName ());
}
else
{
2021-11-04 19:19:17 +01:00
QString filePath = QStandardPaths :: writableLocation ( QStandardPaths :: AppDataLocation );
filePath += QDir :: separator ();
filePath += "fftw-wisdom" ;
2024-08-24 13:17:02 +02:00
auto fileInfo = QFileInfo ( filePath );
2021-11-04 19:19:17 +01:00
if ( fileInfo . exists ()) {
m_dspEngine -> createFFTFactory ( filePath );
} else {
m_dspEngine -> createFFTFactory ( "" );
2021-10-31 11:16:17 +01:00
}
}
2020-03-12 06:27:38 +01:00
m_dspEngine -> preAllocateFFTs ();
2019-05-14 19:23:13 +02:00
splash -> showStatusMessage ( "load plugins..." , Qt :: white );
2018-02-22 06:42:41 +01:00
qDebug () << "MainWindow::MainWindow: load plugins..." ;
m_pluginManager = new PluginManager ( this );
2020-10-11 08:27:58 +02:00
m_mainCore -> m_pluginManager = m_pluginManager ;
2022-04-30 12:52:25 +02:00
m_pluginManager -> setEnableSoapy ( parser . getSoapy ());
2018-02-22 06:42:41 +01:00
m_pluginManager -> loadPlugins ( QString ( "plugins" ));
2020-10-10 20:08:11 +02:00
m_pluginManager -> loadPluginsNonDiscoverable ( m_mainCore -> m_settings . getDeviceUserArgs ());
2018-02-22 06:42:41 +01:00
2022-10-25 22:53:10 +02:00
splash -> showStatusMessage ( "Add command key receiver..." , Qt :: white );
m_commandKeyReceiver = new CommandKeyReceiver ();
m_commandKeyReceiver -> setRelease ( true );
this -> installEventFilter ( m_commandKeyReceiver );
2022-04-07 16:32:03 +02:00
splash -> showStatusMessage ( "Add unique feature set..." , Qt :: white );
2022-04-15 10:04:24 +02:00
addFeatureSet (); // Create the uniuefeature set
2020-10-11 12:39:30 +02:00
m_apiAdapter = new WebAPIAdapter ();
2022-04-14 03:49:32 +02:00
2019-05-14 19:23:13 +02:00
splash -> showStatusMessage ( "finishing..." , Qt :: white );
2017-10-22 19:12:43 +02:00
2018-02-18 23:01:02 +01:00
QString applicationDirPath = qApp -> applicationDirPath ();
2019-06-02 20:34:49 +02:00
#ifdef _MSC_VER
if ( QResource :: registerResource ( applicationDirPath + "/sdrbase.rcc" )) {
qDebug ( "MainWindow::MainWindow: registered resource file %s/%s" , qPrintable ( applicationDirPath ), "sdrbase.rcc" );
} else {
qWarning ( "MainWindow::MainWindow: could not register resource file %s/%s" , qPrintable ( applicationDirPath ), "sdrbase.rcc" );
}
#endif
2017-12-18 00:00:21 +01:00
m_requestMapper = new WebAPIRequestMapper ( this );
2017-11-18 19:34:47 +01:00
m_requestMapper -> setAdapter ( m_apiAdapter );
2018-01-12 00:57:05 +01:00
m_apiHost = parser . getServerAddress ();
m_apiPort = parser . getServerPort ();
2024-08-24 13:17:02 +02:00
m_apiServer = new WebAPIServer ( m_apiHost , ( uint16_t ) m_apiPort , m_requestMapper );
2017-11-17 08:52:15 +01:00
m_apiServer -> start ();
2022-04-14 03:49:32 +02:00
m_dspEngine -> setMIMOSupport ( true );
2019-05-12 10:25:55 +02:00
2021-07-01 15:28:43 +01:00
// Restore window size and position
QSettings s ;
2021-07-01 16:07:25 +01:00
restoreGeometry ( qUncompress ( QByteArray :: fromBase64 ( s . value ( "mainWindowGeometry" ). toByteArray ())));
restoreState ( qUncompress ( QByteArray :: fromBase64 ( s . value ( "mainWindowState" ). toByteArray ())));
2021-07-01 15:28:43 +01:00
2024-10-10 13:57:11 +01:00
// Load initial configuration
2025-06-20 15:43:01 +01:00
InitFSM * fsm = new InitFSM ( this , splash , ! parser . getScratch () && ! parser . getRemoteTCPSink (), ! parser . getRemoteTCPSink ());
2024-10-10 13:57:11 +01:00
connect ( fsm , & InitFSM :: finished , fsm , & InitFSM :: deleteLater );
connect ( fsm , & InitFSM :: finished , splash , & SDRangelSplash :: deleteLater );
2025-06-20 15:43:01 +01:00
if ( parser . getRemoteTCPSink ()) {
connect ( fsm , & InitFSM :: finished , this , & MainWindow :: startRemoteTCPSink );
} else if ( parser . getStart ()) {
2025-01-20 10:54:21 +00:00
connect ( fsm , & InitFSM :: finished , this , & MainWindow :: startAllAfterDelay );
}
2024-10-10 13:57:11 +01:00
fsm -> start ();
2022-12-20 21:06:39 +00:00
2017-10-22 19:12:43 +02:00
qDebug () << "MainWindow::MainWindow: end" ;
}
MainWindow ::~ MainWindow ()
{
2022-04-07 16:32:03 +02:00
qDebug () << "MainWindow::~MainWindow" ;
2022-09-13 17:04:51 +01:00
m_statusTimer . stop ();
2017-11-17 08:52:15 +01:00
m_apiServer -> stop ();
delete m_apiServer ;
delete m_requestMapper ;
2017-11-18 19:34:47 +01:00
delete m_apiAdapter ;
2017-11-17 08:52:15 +01:00
2017-10-22 19:12:43 +02:00
delete m_pluginManager ;
delete m_dateTimeWidget ;
delete m_showSystemWidget ;
2020-09-20 01:06:34 +02:00
removeAllFeatureSets ();
2018-02-15 10:52:34 +01:00
delete m_commandKeyReceiver ;
2023-08-13 23:52:57 +01:00
delete m_profileDialog ;
2022-04-04 10:23:52 +02:00
for ( const auto & workspace : m_workspaces ) {
delete workspace ;
}
2022-04-07 16:32:03 +02:00
qDebug () << "MainWindow::~MainWindow: end" ;
2017-10-22 19:12:43 +02:00
}
2024-10-10 13:57:11 +01:00
MainWindowFSM :: MainWindowFSM ( MainWindow * mainWindow , QObject * parent ) :
QStateMachine ( parent ),
m_mainWindow ( mainWindow ),
m_finalState ( nullptr )
{
}
void MainWindowFSM :: createStates ( int states )
{
for ( int i = 0 ; i < states - 1 ; i ++ ) {
m_states . append ( new QState ());
}
m_finalState = new QFinalState ();
for ( int i = 0 ; i < m_states . size (); i ++ ) {
addState ( m_states [ i ]);
}
addState ( m_finalState );
setInitialState ( m_states [ 0 ]);
}
AddSampleSourceFSM :: AddSampleSourceFSM ( MainWindow * mainWindow , Workspace * deviceWorkspace , Workspace * spectrumWorkspace , int deviceIndex , bool loadDefaults , QObject * parent ) :
MainWindowFSM ( mainWindow , parent ),
m_deviceWorkspace ( deviceWorkspace ),
m_spectrumWorkspace ( spectrumWorkspace ),
m_deviceIndex ( deviceIndex ),
m_loadDefaults ( loadDefaults ),
m_deviceSetIndex ( - 1 ),
m_deviceAPI ( nullptr ),
m_deviceUISet ( nullptr )
2017-10-22 19:12:43 +02:00
{
2024-10-10 13:57:11 +01:00
// Create source engine
addEngine ();
// Create FSM
createStates ( 3 );
m_states [ 0 ] -> addTransition ( m_dspDeviceSourceEngine , & DSPDeviceSourceEngine :: sampleSet , m_states [ 1 ]);
m_states [ 1 ] -> addTransition ( m_finalState );
connect ( m_states [ 0 ], & QState :: entered , this , & AddSampleSourceFSM :: addDevice );
connect ( m_states [ 1 ], & QState :: entered , this , & AddSampleSourceFSM :: addDeviceUI );
}
2017-10-22 19:12:43 +02:00
2024-10-10 13:57:11 +01:00
void AddSampleSourceFSM :: addEngine ()
{
// Create the source engine
m_dspDeviceSourceEngine = m_mainWindow -> m_dspEngine -> addDeviceSourceEngine ();
}
2017-10-22 19:12:43 +02:00
2024-10-10 13:57:11 +01:00
void AddSampleSourceFSM :: addDevice ()
{
m_deviceSetIndex = ( int ) m_mainWindow -> m_deviceUIs . size ();
m_mainWindow -> m_mainCore -> appendDeviceSet ( 0 );
2017-10-22 19:12:43 +02:00
2024-10-10 13:57:11 +01:00
DeviceSet * deviceSet = m_mainWindow -> m_mainCore -> getDeviceSets (). back ();
m_deviceUISet = new DeviceUISet ( m_deviceSetIndex , deviceSet );
m_mainWindow -> m_deviceUIs . push_back ( m_deviceUISet );
m_deviceUISet -> m_deviceSourceEngine = m_dspDeviceSourceEngine ;
deviceSet -> m_deviceSourceEngine = m_dspDeviceSourceEngine ;
m_deviceUISet -> m_deviceSinkEngine = nullptr ;
deviceSet -> m_deviceSinkEngine = nullptr ;
m_deviceUISet -> m_deviceMIMOEngine = nullptr ;
deviceSet -> m_deviceMIMOEngine = nullptr ;
m_deviceAPI = new DeviceAPI ( DeviceAPI :: StreamSingleRx , m_deviceSetIndex , m_dspDeviceSourceEngine , nullptr , nullptr );
m_deviceUISet -> m_deviceAPI = m_deviceAPI ;
deviceSet -> m_deviceAPI = m_deviceAPI ;
2017-11-01 08:32:44 +01:00
QList < QString > channelNames ;
2024-10-10 13:57:11 +01:00
m_mainWindow -> m_pluginManager -> listRxChannels ( channelNames );
m_deviceUISet -> setNumberOfAvailableRxChannels ( channelNames . size ());
2017-10-22 19:12:43 +02:00
2024-10-10 13:57:11 +01:00
m_dspDeviceSourceEngine -> addSink ( m_deviceUISet -> m_spectrumVis );
2017-10-22 19:12:43 +02:00
2017-12-25 09:10:19 +01:00
// Create a file source instance by default if requested device was not enumerated (index = -1)
2024-10-10 13:57:11 +01:00
if ( m_deviceIndex < 0 ) {
m_deviceIndex = DeviceEnumerator :: instance () -> getFileInputDeviceIndex ();
2017-12-25 09:10:19 +01:00
}
2024-10-10 13:57:11 +01:00
m_mainWindow -> sampleSourceCreate ( m_deviceSetIndex , m_deviceIndex , m_deviceUISet );
}
void AddSampleSourceFSM :: addDeviceUI ()
{
m_mainWindow -> sampleSourceCreateUI ( m_deviceSetIndex , m_deviceIndex , m_deviceUISet );
m_deviceUISet -> m_deviceGUI -> setWorkspaceIndex ( m_deviceWorkspace -> getIndex ());
m_deviceUISet -> m_mainSpectrumGUI -> setWorkspaceIndex ( m_spectrumWorkspace -> getIndex ());
MainSpectrumGUI * mainSpectrumGUI = m_deviceUISet -> m_mainSpectrumGUI ;
2022-04-09 13:38:22 +02:00
QObject :: connect (
2022-04-14 03:07:33 +02:00
mainSpectrumGUI ,
2022-04-09 13:38:22 +02:00
& MainSpectrumGUI :: moveToWorkspace ,
2024-10-10 13:57:11 +01:00
m_mainWindow ,
[ m_mainWindow = m_mainWindow , mainSpectrumGUI ]( int wsIndexDest ){ m_mainWindow -> mainSpectrumMove ( mainSpectrumGUI , wsIndexDest ); }
2022-04-09 13:38:22 +02:00
);
2022-04-12 16:20:45 +02:00
QObject :: connect (
2024-10-10 13:57:11 +01:00
m_deviceUISet -> m_deviceGUI ,
2022-04-12 16:20:45 +02:00
& DeviceGUI :: addChannelEmitted ,
2024-10-10 13:57:11 +01:00
m_mainWindow ,
[ m_mainWindow = m_mainWindow , m_deviceWorkspace = m_deviceWorkspace , m_deviceSetIndex = m_deviceSetIndex ]( int channelPluginIndex ){
m_mainWindow -> channelAddClicked ( m_deviceWorkspace , m_deviceSetIndex , channelPluginIndex );
}
2022-04-12 16:20:45 +02:00
);
2022-06-24 22:52:17 +02:00
QObject :: connect (
mainSpectrumGUI ,
& MainSpectrumGUI :: requestCenterFrequency ,
2024-10-10 13:57:11 +01:00
m_mainWindow ,
2022-06-24 22:52:17 +02:00
& MainWindow :: mainSpectrumRequestDeviceCenterFrequency
);
2022-08-27 10:18:17 +01:00
QObject :: connect (
2024-10-10 13:57:11 +01:00
m_deviceAPI ,
2022-08-27 10:18:17 +01:00
& DeviceAPI :: stateChanged ,
2024-10-10 13:57:11 +01:00
m_mainWindow ,
& MainWindow :: deviceStateChanged
);
m_deviceWorkspace -> addToMdiArea ( m_deviceUISet -> m_deviceGUI );
m_spectrumWorkspace -> addToMdiArea ( m_deviceUISet -> m_mainSpectrumGUI );
2024-10-10 15:56:27 +01:00
if ( m_loadDefaults ) {
2024-10-10 13:57:11 +01:00
m_mainWindow -> loadDefaultPreset ( m_deviceAPI -> getSamplingDeviceId (), m_deviceUISet );
2024-10-10 15:56:27 +01:00
}
2024-10-10 13:57:11 +01:00
emit m_mainWindow -> m_mainCore -> deviceSetAdded ( m_deviceSetIndex , m_deviceAPI );
#ifdef ANDROID
// Seemingly needed on some versions of Android, otherwise the new windows aren't always displayed??
m_deviceWorkspace -> repaint ();
#endif
}
AddSampleSinkFSM :: AddSampleSinkFSM ( MainWindow * mainWindow , Workspace * deviceWorkspace , Workspace * spectrumWorkspace , int deviceIndex , bool loadDefaults , QObject * parent ) :
MainWindowFSM ( mainWindow , parent ),
m_deviceWorkspace ( deviceWorkspace ),
m_spectrumWorkspace ( spectrumWorkspace ),
m_deviceIndex ( deviceIndex ),
m_loadDefaults ( loadDefaults ),
m_deviceSetIndex ( - 1 ),
m_deviceAPI ( nullptr ),
m_deviceUISet ( nullptr )
{
// Create source engine
addEngine ();
// Create FSM
createStates ( 3 );
m_states [ 0 ] -> addTransition ( m_dspDeviceSinkEngine , & DSPDeviceSinkEngine :: sampleSet , m_states [ 1 ]);
m_states [ 1 ] -> addTransition ( m_finalState );
connect ( m_states [ 0 ], & QState :: entered , this , & AddSampleSinkFSM :: addDevice );
connect ( m_states [ 1 ], & QState :: entered , this , & AddSampleSinkFSM :: addDeviceUI );
}
void AddSampleSinkFSM :: addEngine ()
{
// Create the source engine
m_dspDeviceSinkEngine = m_mainWindow -> m_dspEngine -> addDeviceSinkEngine ();
}
void AddSampleSinkFSM :: addDevice ()
{
m_deviceSetIndex = ( int ) m_mainWindow -> m_deviceUIs . size ();
m_mainWindow -> m_mainCore -> appendDeviceSet ( 1 );
DeviceSet * deviceSet = m_mainWindow -> m_mainCore -> getDeviceSets (). back ();
m_deviceUISet = new DeviceUISet ( m_deviceSetIndex , deviceSet );
m_mainWindow -> m_deviceUIs . push_back ( m_deviceUISet );
m_deviceUISet -> m_deviceSourceEngine = nullptr ;
deviceSet -> m_deviceSourceEngine = nullptr ;
m_deviceUISet -> m_deviceSinkEngine = m_dspDeviceSinkEngine ;
deviceSet -> m_deviceSinkEngine = m_dspDeviceSinkEngine ;
m_deviceUISet -> m_deviceMIMOEngine = nullptr ;
deviceSet -> m_deviceMIMOEngine = nullptr ;
m_deviceAPI = new DeviceAPI ( DeviceAPI :: StreamSingleTx , m_deviceSetIndex , nullptr , m_dspDeviceSinkEngine , nullptr );
m_deviceUISet -> m_deviceAPI = m_deviceAPI ;
deviceSet -> m_deviceAPI = m_deviceAPI ;
QList < QString > channelNames ;
m_mainWindow -> m_pluginManager -> listTxChannels ( channelNames );
m_deviceUISet -> setNumberOfAvailableTxChannels ( channelNames . size ());
m_dspDeviceSinkEngine -> addSpectrumSink ( m_deviceUISet -> m_spectrumVis );
m_deviceUISet -> m_spectrum -> setDisplayedStream ( false , 0 );
// Create a file sink instance by default if requested device was not enumerated (index = -1)
if ( m_deviceIndex < 0 ) {
m_deviceIndex = DeviceEnumerator :: instance () -> getFileOutputDeviceIndex ();
}
m_mainWindow -> sampleSinkCreate ( m_deviceSetIndex , m_deviceIndex , m_deviceUISet );
}
void AddSampleSinkFSM :: addDeviceUI ()
{
m_mainWindow -> sampleSinkCreateUI ( m_deviceSetIndex , m_deviceIndex , m_deviceUISet );
m_deviceUISet -> m_deviceGUI -> setWorkspaceIndex ( m_deviceWorkspace -> getIndex ());
m_deviceUISet -> m_mainSpectrumGUI -> setWorkspaceIndex ( m_spectrumWorkspace -> getIndex ());
MainSpectrumGUI * mainSpectrumGUI = m_deviceUISet -> m_mainSpectrumGUI ;
QObject :: connect (
mainSpectrumGUI ,
& MainSpectrumGUI :: moveToWorkspace ,
m_mainWindow ,
[ m_mainWindow = m_mainWindow , mainSpectrumGUI ]( int wsIndexDest ){ m_mainWindow -> mainSpectrumMove ( mainSpectrumGUI , wsIndexDest ); }
);
QObject :: connect (
m_deviceUISet -> m_deviceGUI ,
& DeviceGUI :: addChannelEmitted ,
m_mainWindow ,
[ m_mainWindow = m_mainWindow , m_deviceWorkspace = m_deviceWorkspace , m_deviceSetIndex = m_deviceSetIndex ]( int channelPluginIndex ){
m_mainWindow -> channelAddClicked ( m_deviceWorkspace , m_deviceSetIndex , channelPluginIndex );
}
);
QObject :: connect (
mainSpectrumGUI ,
& MainSpectrumGUI :: requestCenterFrequency ,
m_mainWindow ,
& MainWindow :: mainSpectrumRequestDeviceCenterFrequency
);
QObject :: connect (
m_deviceAPI ,
& DeviceAPI :: stateChanged ,
m_mainWindow ,
& MainWindow :: deviceStateChanged
);
m_deviceWorkspace -> addToMdiArea ( m_deviceUISet -> m_deviceGUI );
m_spectrumWorkspace -> addToMdiArea ( m_deviceUISet -> m_mainSpectrumGUI );
2024-10-10 15:56:27 +01:00
if ( m_loadDefaults ) {
2024-10-10 13:57:11 +01:00
m_mainWindow -> loadDefaultPreset ( m_deviceAPI -> getSamplingDeviceId (), m_deviceUISet );
2024-10-10 15:56:27 +01:00
}
2024-10-10 13:57:11 +01:00
emit m_mainWindow -> m_mainCore -> deviceSetAdded ( m_deviceSetIndex , m_deviceAPI );
#ifdef ANDROID
// Seemingly needed on some versions of Android, otherwise the new windows aren't always displayed??
m_deviceWorkspace -> repaint ();
#endif
}
AddSampleMIMOFSM :: AddSampleMIMOFSM ( MainWindow * mainWindow , Workspace * deviceWorkspace , Workspace * spectrumWorkspace , int deviceIndex , bool loadDefaults , QObject * parent ) :
MainWindowFSM ( mainWindow , parent ),
m_deviceWorkspace ( deviceWorkspace ),
m_spectrumWorkspace ( spectrumWorkspace ),
m_deviceIndex ( deviceIndex ),
m_loadDefaults ( loadDefaults ),
m_deviceSetIndex ( - 1 ),
m_deviceAPI ( nullptr ),
m_deviceUISet ( nullptr )
{
// Create source engine
addEngine ();
// Create FSM
createStates ( 3 );
m_states [ 0 ] -> addTransition ( m_dspDeviceMIMOEngine , & DSPDeviceMIMOEngine :: sampleSet , m_states [ 1 ]);
m_states [ 1 ] -> addTransition ( m_finalState );
connect ( m_states [ 0 ], & QState :: entered , this , & AddSampleMIMOFSM :: addDevice );
connect ( m_states [ 1 ], & QState :: entered , this , & AddSampleMIMOFSM :: addDeviceUI );
}
void AddSampleMIMOFSM :: addEngine ()
{
// Create the source engine
m_dspDeviceMIMOEngine = m_mainWindow -> m_dspEngine -> addDeviceMIMOEngine ();
}
void AddSampleMIMOFSM :: addDevice ()
{
m_deviceSetIndex = ( int ) m_mainWindow -> m_deviceUIs . size ();
m_mainWindow -> m_mainCore -> appendDeviceSet ( 2 );
DeviceSet * deviceSet = m_mainWindow -> m_mainCore -> getDeviceSets (). back ();
m_deviceUISet = new DeviceUISet ( m_deviceSetIndex , deviceSet );
m_mainWindow -> m_deviceUIs . push_back ( m_deviceUISet );
m_deviceUISet -> m_deviceSourceEngine = nullptr ;
deviceSet -> m_deviceSourceEngine = nullptr ;
m_deviceUISet -> m_deviceSinkEngine = nullptr ;
deviceSet -> m_deviceSinkEngine = nullptr ;
m_deviceUISet -> m_deviceMIMOEngine = m_dspDeviceMIMOEngine ;
deviceSet -> m_deviceMIMOEngine = m_dspDeviceMIMOEngine ;
m_deviceAPI = new DeviceAPI ( DeviceAPI :: StreamMIMO , m_deviceSetIndex , nullptr , nullptr , m_dspDeviceMIMOEngine );
m_deviceUISet -> m_deviceAPI = m_deviceAPI ;
deviceSet -> m_deviceAPI = m_deviceAPI ;
QList < QString > mimoChannelNames ;
m_mainWindow -> m_pluginManager -> listMIMOChannels ( mimoChannelNames );
m_deviceUISet -> setNumberOfAvailableMIMOChannels ( mimoChannelNames . size ());
// Add Rx channels
QList < QString > rxChannelNames ;
m_mainWindow -> m_pluginManager -> listRxChannels ( rxChannelNames );
m_deviceUISet -> setNumberOfAvailableRxChannels ( rxChannelNames . size ());
// Add Tx channels
QList < QString > txChannelNames ;
m_mainWindow -> m_pluginManager -> listTxChannels ( txChannelNames );
m_deviceUISet -> setNumberOfAvailableTxChannels ( txChannelNames . size ());
m_dspDeviceMIMOEngine -> addSpectrumSink ( m_deviceUISet -> m_spectrumVis );
// Create a Test MIMO instance by default if requested device was not enumerated (index = -1)
if ( m_deviceIndex < 0 ) {
m_deviceIndex = DeviceEnumerator :: instance () -> getTestMIMODeviceIndex ();
}
m_mainWindow -> sampleMIMOCreate ( m_deviceSetIndex , m_deviceIndex , m_deviceUISet );
}
void AddSampleMIMOFSM :: addDeviceUI ()
{
m_mainWindow -> sampleMIMOCreateUI ( m_deviceSetIndex , m_deviceIndex , m_deviceUISet );
m_deviceUISet -> m_deviceGUI -> setWorkspaceIndex ( m_deviceWorkspace -> getIndex ());
m_deviceUISet -> m_mainSpectrumGUI -> setWorkspaceIndex ( m_spectrumWorkspace -> getIndex ());
MainSpectrumGUI * mainSpectrumGUI = m_deviceUISet -> m_mainSpectrumGUI ;
QObject :: connect (
m_deviceUISet -> m_deviceGUI ,
& DeviceGUI :: addChannelEmitted ,
m_mainWindow ,
[ m_mainWindow = m_mainWindow , m_deviceWorkspace = m_deviceWorkspace , m_deviceSetIndex = m_deviceSetIndex ]( int channelPluginIndex ){
m_mainWindow -> channelAddClicked ( m_deviceWorkspace , m_deviceSetIndex , channelPluginIndex );
}
);
QObject :: connect (
mainSpectrumGUI ,
& MainSpectrumGUI :: requestCenterFrequency ,
m_mainWindow ,
& MainWindow :: mainSpectrumRequestDeviceCenterFrequency
);
QObject :: connect (
m_deviceAPI ,
& DeviceAPI :: stateChanged ,
m_mainWindow ,
2022-08-27 10:18:17 +01:00
& MainWindow :: deviceStateChanged
);
2024-10-10 13:57:11 +01:00
m_deviceWorkspace -> addToMdiArea ( m_deviceUISet -> m_deviceGUI );
m_spectrumWorkspace -> addToMdiArea ( m_deviceUISet -> m_mainSpectrumGUI );
2024-10-10 15:56:27 +01:00
if ( m_loadDefaults ) {
2024-10-10 13:57:11 +01:00
m_mainWindow -> loadDefaultPreset ( m_deviceAPI -> getSamplingDeviceId (), m_deviceUISet );
2024-10-10 15:56:27 +01:00
}
2024-10-10 13:57:11 +01:00
emit m_mainWindow -> m_mainCore -> deviceSetAdded ( m_deviceSetIndex , m_deviceAPI );
2022-12-20 21:06:39 +00:00
#ifdef ANDROID
// Seemingly needed on some versions of Android, otherwise the new windows aren't always displayed??
2024-10-10 13:57:11 +01:00
m_deviceWorkspace -> repaint ();
2022-12-20 21:06:39 +00:00
#endif
2022-04-07 16:32:03 +02:00
}
2024-10-10 13:57:11 +01:00
RemoveDeviceSetFSM :: RemoveDeviceSetFSM ( MainWindow * mainWindow , int deviceSetIndex , QObject * parent ) :
MainWindowFSM ( mainWindow , parent ),
m_deviceSetIndex ( deviceSetIndex ),
m_deviceSourceEngine ( nullptr ),
m_deviceSinkEngine ( nullptr ),
m_deviceMIMOEngine ( nullptr ),
m_t1 ( nullptr ),
m_t2 ( nullptr )
{
// Create FSM
createStates ( 6 );
m_deviceUISet = m_mainWindow -> m_deviceUIs [ m_deviceSetIndex ];
if ( m_deviceUISet -> m_deviceSourceEngine )
{
m_deviceSourceEngine = m_deviceUISet -> m_deviceSourceEngine ;
m_t1 = new QSignalTransition ( m_deviceSourceEngine , & DSPDeviceSourceEngine :: acquistionStopped , m_states [ 0 ]);
m_t1 -> setTargetState ( m_states [ 1 ]);
m_t2 = new QSignalTransition ( m_deviceSourceEngine , & DSPDeviceSourceEngine :: sinkRemoved , m_states [ 1 ]);
m_t2 -> setTargetState ( m_states [ 2 ]);
}
else if ( m_deviceUISet -> m_deviceSinkEngine )
{
m_deviceSinkEngine = m_deviceUISet -> m_deviceSinkEngine ;
m_t1 = new QSignalTransition ( m_deviceSinkEngine , & DSPDeviceSinkEngine :: generationStopped , m_states [ 0 ]);
m_t1 -> setTargetState ( m_states [ 1 ]);
m_t2 = new QSignalTransition ( m_deviceSinkEngine , & DSPDeviceSinkEngine :: spectrumSinkRemoved , m_states [ 1 ]);
m_t2 -> setTargetState ( m_states [ 2 ]);
}
else if ( m_deviceUISet -> m_deviceMIMOEngine )
{
m_deviceMIMOEngine = m_deviceUISet -> m_deviceMIMOEngine ;
m_t1 = new QSignalTransition ( m_deviceMIMOEngine , & DSPDeviceMIMOEngine :: acquisitionStopped , m_states [ 0 ]);
m_t1 -> setTargetState ( m_states [ 1 ]);
m_t2 = new QSignalTransition ( m_deviceMIMOEngine , & DSPDeviceMIMOEngine :: spectrumSinkRemoved , m_states [ 1 ]);
m_t2 -> setTargetState ( m_states [ 2 ]);
}
m_states [ 2 ] -> addTransition ( m_states [ 3 ]);
m_states [ 3 ] -> addTransition ( m_mainWindow , & MainWindow :: engineStopped , m_states [ 4 ]);
m_states [ 4 ] -> addTransition ( m_finalState );
connect ( m_states [ 0 ], & QState :: entered , this , & RemoveDeviceSetFSM :: stopAcquisition );
connect ( m_states [ 1 ], & QState :: entered , this , & RemoveDeviceSetFSM :: removeSink );
connect ( m_states [ 2 ], & QState :: entered , this , & RemoveDeviceSetFSM :: removeUI );
connect ( m_states [ 3 ], & QState :: entered , this , & RemoveDeviceSetFSM :: stopEngine );
connect ( m_states [ 4 ], & QState :: entered , this , & RemoveDeviceSetFSM :: removeDeviceSet );
}
void RemoveDeviceSetFSM :: stopAcquisition ()
{
qDebug () << "RemoveDeviceSetFSM::stopAcquisition" ;
if ( m_deviceSourceEngine )
{
m_deviceSourceEngine -> stopAcquistion ();
}
else if ( m_deviceSinkEngine )
{
m_deviceSinkEngine -> stopGeneration ();
}
else
{
m_deviceMIMOEngine -> stopProcess ( 1 ); // Tx side
m_deviceMIMOEngine -> stopProcess ( 0 ); // Rx side
}
}
void RemoveDeviceSetFSM :: removeSink ()
{
qDebug () << "RemoveDeviceSetFSM::removeSink" ;
if ( m_deviceSourceEngine ) {
2024-11-25 17:16:08 +00:00
m_deviceSourceEngine -> removeSink ( m_deviceUISet -> m_spectrumVis , false );
2024-10-10 13:57:11 +01:00
} else if ( m_deviceSinkEngine ) {
m_deviceSinkEngine -> removeSpectrumSink ( m_deviceUISet -> m_spectrumVis );
} else {
m_deviceMIMOEngine -> removeSpectrumSink ( m_deviceUISet -> m_spectrumVis );
}
}
void RemoveDeviceSetFSM :: removeUI ()
{
qDebug () << "RemoveDeviceSetFSM::removeUI" ;
// Remove transitions, as we will delete the object (DSPDevice*Engine) that is the source of these signals
m_states [ 0 ] -> removeTransition ( m_t1 );
delete m_t1 ;
m_t1 = nullptr ;
m_states [ 1 ] -> removeTransition ( m_t2 );
delete m_t2 ;
m_t2 = nullptr ;
m_deviceUISet -> freeChannels (); // destroys the channel instances
if ( m_deviceSourceEngine ) {
m_deviceUISet -> m_deviceAPI -> getSampleSource () -> setMessageQueueToGUI ( nullptr ); // have source stop sending messages to the GUI
} else if ( m_deviceSinkEngine ) {
m_deviceUISet -> m_deviceAPI -> getSampleSink () -> setMessageQueueToGUI ( nullptr ); // have sink stop sending messages to the GUI
} else {
m_deviceUISet -> m_deviceAPI -> getSampleMIMO () -> setMessageQueueToGUI ( nullptr ); // have sink stop sending messages to the GUI
}
delete m_deviceUISet -> m_deviceGUI ;
m_deviceUISet -> m_deviceAPI -> resetSamplingDeviceId ();
if ( ! m_deviceMIMOEngine ) {
m_deviceUISet -> m_deviceAPI -> clearBuddiesLists (); // clear old API buddies lists
}
}
void RemoveDeviceSetFSM :: stopEngine ()
{
qDebug () << "RemoveDeviceSetFSM::stopEngine" ;
2024-11-14 11:42:53 +00:00
QThread * thread = m_mainWindow -> m_dspEngine -> getDeviceEngineThread ( m_deviceSetIndex );
if ( thread )
2024-10-10 13:57:11 +01:00
{
2024-11-14 11:42:53 +00:00
bool finished = thread -> isFinished ();
if ( ! finished ) {
connect ( thread , & QThread :: finished , m_mainWindow , & MainWindow :: engineStopped );
}
m_mainWindow -> m_dspEngine -> removeDeviceEngineAt ( m_deviceSetIndex );
if ( finished ) {
emit m_mainWindow -> engineStopped ();
}
2024-10-10 13:57:11 +01:00
}
else
{
emit m_mainWindow -> engineStopped ();
}
}
void RemoveDeviceSetFSM :: removeDeviceSet ()
{
if ( m_deviceSourceEngine ) {
DeviceEnumerator :: instance () -> removeRxSelection ( m_deviceSetIndex );
} else if ( m_deviceSinkEngine ) {
DeviceEnumerator :: instance () -> removeTxSelection ( m_deviceSetIndex );
} else {
DeviceEnumerator :: instance () -> removeMIMOSelection ( m_deviceSetIndex );
}
DeviceAPI * deviceAPI = m_deviceUISet -> m_deviceAPI ;
delete m_deviceUISet ;
2024-11-14 11:42:53 +00:00
if ( m_deviceSourceEngine )
{
2024-10-10 13:57:11 +01:00
delete deviceAPI -> getSampleSource ();
2024-11-14 11:42:53 +00:00
delete m_deviceSourceEngine ;
}
else if ( m_deviceSinkEngine )
{
2024-10-10 13:57:11 +01:00
delete deviceAPI -> getSampleSink ();
2024-11-14 11:42:53 +00:00
delete m_deviceSinkEngine ;
}
else
{
2024-10-10 13:57:11 +01:00
delete deviceAPI -> getSampleMIMO ();
2024-11-14 11:42:53 +00:00
delete m_deviceMIMOEngine ;
2024-10-10 13:57:11 +01:00
}
delete deviceAPI ;
m_mainWindow -> m_deviceUIs . erase ( m_mainWindow -> m_deviceUIs . begin () + m_deviceSetIndex );
m_mainWindow -> m_mainCore -> removeDeviceSet ( m_deviceSetIndex );
DeviceEnumerator :: instance () -> renumeratetabIndex ( m_deviceSetIndex );
// Renumerate
for ( int i = 0 ; i < ( int ) m_mainWindow -> m_deviceUIs . size (); i ++ )
{
DeviceUISet * xDeviceUISet = m_mainWindow -> m_deviceUIs [ i ];
xDeviceUISet -> setIndex ( i );
const DeviceGUI * deviceGUI = m_mainWindow -> m_deviceUIs [ i ] -> m_deviceGUI ;
Workspace * deviceWorkspace = m_mainWindow -> m_workspaces [ deviceGUI -> getWorkspaceIndex ()];
QObject :: disconnect (
deviceGUI ,
& DeviceGUI :: addChannelEmitted ,
this ,
nullptr
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: addChannelEmitted ,
this ,
[ this , deviceWorkspace , i ]( int channelPluginIndex ){ m_mainWindow -> channelAddClicked ( deviceWorkspace , i , channelPluginIndex ); }
);
}
emit m_mainWindow -> m_mainCore -> deviceSetRemoved ( m_deviceSetIndex );
}
RemoveAllDeviceSetsFSM :: RemoveAllDeviceSetsFSM ( MainWindow * mainWindow , QObject * parent ) :
MainWindowFSM ( mainWindow , parent )
{
// Create FSM
createStates ( 2 );
m_states [ 0 ] -> addTransition ( m_mainWindow -> m_mainCore , & MainCore :: deviceSetRemoved , m_states [ 0 ]);
m_states [ 0 ] -> addTransition ( m_mainWindow , & MainWindow :: allDeviceSetsRemoved , m_finalState );
connect ( m_states [ 0 ], & QState :: entered , this , & RemoveAllDeviceSetsFSM :: removeNext );
}
void RemoveAllDeviceSetsFSM :: removeNext ()
{
qDebug () << "RemoveAllDeviceSetsFSM::removeNext" ;
if ( m_mainWindow -> m_deviceUIs . size () > 0 ) {
m_mainWindow -> removeDeviceSet ( m_mainWindow -> m_deviceUIs . size () - 1 );
} else {
emit m_mainWindow -> allDeviceSetsRemoved ();
}
}
RemoveAllWorkspacesFSM :: RemoveAllWorkspacesFSM ( MainWindow * mainWindow , QObject * parent ) :
MainWindowFSM ( mainWindow , parent )
{
// Create FSM
createStates ( 3 );
m_removeAllDeviceSetsFSM = new RemoveAllDeviceSetsFSM ( m_mainWindow , this );
m_states [ 0 ] -> addTransition ( m_removeAllDeviceSetsFSM , & RemoveAllDeviceSetsFSM :: finished , m_states [ 1 ]);
m_states [ 1 ] -> addTransition ( m_finalState );
connect ( m_states [ 0 ], & QState :: entered , this , & RemoveAllWorkspacesFSM :: removeDeviceSets );
connect ( m_states [ 1 ], & QState :: entered , this , & RemoveAllWorkspacesFSM :: removeWorkspaces );
}
void RemoveAllWorkspacesFSM :: removeDeviceSets ()
{
qDebug () << "RemoveAllWorkspacesFSM::removeDeviceSets" ;
m_removeAllDeviceSetsFSM -> start ();
}
void RemoveAllWorkspacesFSM :: removeWorkspaces ()
{
qDebug () << "RemoveAllWorkspacesFSM::removeWorkspaces" ;
// Features
m_mainWindow -> m_featureUIs [ 0 ] -> freeFeatures ();
// Workspaces
for ( const auto & workspace : m_mainWindow -> m_workspaces ) {
delete workspace ;
}
m_mainWindow -> m_workspaces . clear ();
qDebug () << "RemoveAllWorkspacesFSM::removeWorkspaces done" ;
}
LoadConfigurationFSM :: LoadConfigurationFSM ( MainWindow * mainWindow , const Configuration * configuration , QProgressDialog * waitBox , QObject * parent ) :
2024-10-10 14:36:06 +01:00
MainWindowFSM ( mainWindow , parent ),
2024-10-10 13:57:11 +01:00
m_configuration ( configuration ),
m_waitBox ( waitBox )
{
// Create FSM
createStates ( 7 );
m_removeAllWorkspacesFSM = new RemoveAllWorkspacesFSM ( m_mainWindow , this );
m_states [ 0 ] -> addTransition ( m_removeAllWorkspacesFSM , & RemoveAllWorkspacesFSM :: finished , m_states [ 1 ]);
m_states [ 1 ] -> addTransition ( m_states [ 2 ]);
m_states [ 2 ] -> addTransition ( m_mainWindow , & MainWindow :: allDeviceSetsAdded , m_states [ 3 ]);
m_states [ 3 ] -> addTransition ( m_states [ 4 ]);
m_states [ 4 ] -> addTransition ( m_states [ 5 ]);
m_states [ 5 ] -> addTransition ( m_finalState );
connect ( m_states [ 0 ], & QState :: entered , this , & LoadConfigurationFSM :: clearWorkspace );
connect ( m_states [ 1 ], & QState :: entered , this , & LoadConfigurationFSM :: createWorkspaces );
connect ( m_states [ 2 ], & QState :: entered , this , & LoadConfigurationFSM :: loadDeviceSets );
connect ( m_states [ 3 ], & QState :: entered , this , & LoadConfigurationFSM :: loadDeviceSetSettings );
connect ( m_states [ 4 ], & QState :: entered , this , & LoadConfigurationFSM :: loadFeatureSets );
connect ( m_states [ 5 ], & QState :: entered , this , & LoadConfigurationFSM :: restoreGeometry );
}
void LoadConfigurationFSM :: clearWorkspace ()
{
qDebug () << "LoadConfigurationFSM::clearWorkspace" ;
if ( m_waitBox )
{
m_waitBox -> setLabelText ( "Deleting existing..." );
m_waitBox -> setValue ( 5 );
}
m_removeAllWorkspacesFSM -> start ();
}
void LoadConfigurationFSM :: createWorkspaces ()
{
qDebug () << "LoadConfigurationFSM::createWorkspaces" ;
if ( m_waitBox )
{
m_waitBox -> setLabelText ( "Creating workspaces..." );
m_waitBox -> setValue ( 20 );
}
// Workspaces
for ( int i = 0 ; i < m_configuration -> getNumberOfWorkspaceGeometries (); i ++ )
{
m_mainWindow -> addWorkspace ();
m_mainWindow -> m_workspaces [ i ] -> setAutoStackOption ( m_configuration -> getWorkspaceAutoStackOptions ()[ i ]);
m_mainWindow -> m_workspaces [ i ] -> setTabSubWindowsOption ( m_configuration -> getWorkspaceTabSubWindowsOptions ()[ i ]);
}
}
void LoadConfigurationFSM :: loadDeviceSets ()
{
qDebug () << "LoadConfigurationFSM::loadDeviceSets" ;
if ( m_waitBox )
{
m_waitBox -> setLabelText ( "Loading device sets..." );
m_waitBox -> setValue ( 25 );
}
const QList < Preset >& deviceSetPresets = m_configuration -> getDeviceSetPresets ();
// State machine that runs all of the individual AddSampleSourceFSM, AddSampleSinkFSM, AddSampleMIMOFSMs
QStateMachine * m_addDevicesFSM = new QStateMachine ();
QState * sInitial = nullptr ;
QState * sPrev = nullptr ;
QFinalState * sFinal = new QFinalState ();
2025-03-06 17:09:16 +00:00
connect ( m_addDevicesFSM , & QStateMachine :: finished , this , [ = ](){
// Wait slighter longer than the 100ms timer used in Device GUI sendSettings, so we know devices should be initialised
QTimer :: singleShot ( 250 , [ this ] {
emit m_mainWindow -> allDeviceSetsAdded ();
});
});
2024-10-10 13:57:11 +01:00
connect ( m_addDevicesFSM , & QStateMachine :: finished , m_addDevicesFSM , & QStateMachine :: deleteLater );
for ( const auto & deviceSetPreset : deviceSetPresets )
{
MainWindowFSM * fsm = nullptr ;
int deviceWorkspaceIndex = deviceSetPreset . getDeviceWorkspaceIndex () < m_mainWindow -> m_workspaces . size () ?
deviceSetPreset . getDeviceWorkspaceIndex () :
0 ;
int spectrumWorkspaceIndex = deviceSetPreset . getSpectrumWorkspaceIndex () < m_mainWindow -> m_workspaces . size () ?
deviceSetPreset . getSpectrumWorkspaceIndex () :
deviceWorkspaceIndex ;
if ( deviceSetPreset . isSourcePreset ())
{
int bestDeviceIndex = DeviceEnumerator :: instance () -> getBestRxSamplingDeviceIndex (
deviceSetPreset . getSelectedDevice (). m_deviceId ,
deviceSetPreset . getSelectedDevice (). m_deviceSerial ,
deviceSetPreset . getSelectedDevice (). m_deviceSequence ,
deviceSetPreset . getSelectedDevice (). m_deviceItemIndex
);
qDebug ( "MainWindow::loadConfiguration: add source %s in workspace %d spectrum in %d" ,
qPrintable ( deviceSetPreset . getSelectedDevice (). m_deviceId ),
deviceSetPreset . getDeviceWorkspaceIndex (),
deviceSetPreset . getSpectrumWorkspaceIndex ());
fsm = new AddSampleSourceFSM ( m_mainWindow ,
m_mainWindow -> m_workspaces [ deviceWorkspaceIndex ],
m_mainWindow -> m_workspaces [ spectrumWorkspaceIndex ],
bestDeviceIndex , false , m_addDevicesFSM );
}
else if ( deviceSetPreset . isSinkPreset ())
{
int bestDeviceIndex = DeviceEnumerator :: instance () -> getBestTxSamplingDeviceIndex (
deviceSetPreset . getSelectedDevice (). m_deviceId ,
deviceSetPreset . getSelectedDevice (). m_deviceSerial ,
deviceSetPreset . getSelectedDevice (). m_deviceSequence ,
deviceSetPreset . getSelectedDevice (). m_deviceItemIndex
);
qDebug ( "MainWindow::loadConfiguration: add sink %s in workspace %d spectrum in %d" ,
qPrintable ( deviceSetPreset . getSelectedDevice (). m_deviceId ),
deviceSetPreset . getDeviceWorkspaceIndex (),
deviceSetPreset . getSpectrumWorkspaceIndex ());
fsm = new AddSampleSinkFSM ( m_mainWindow ,
m_mainWindow -> m_workspaces [ deviceWorkspaceIndex ],
m_mainWindow -> m_workspaces [ spectrumWorkspaceIndex ],
bestDeviceIndex , false , m_addDevicesFSM );
}
else if ( deviceSetPreset . isMIMOPreset ())
{
int bestDeviceIndex = DeviceEnumerator :: instance () -> getBestMIMOSamplingDeviceIndex (
deviceSetPreset . getSelectedDevice (). m_deviceId ,
deviceSetPreset . getSelectedDevice (). m_deviceSerial ,
deviceSetPreset . getSelectedDevice (). m_deviceSequence
);
qDebug ( "MainWindow::loadConfiguration: add MIMO %s in workspace %d spectrum in %d" ,
qPrintable ( deviceSetPreset . getSelectedDevice (). m_deviceId ),
deviceSetPreset . getDeviceWorkspaceIndex (),
deviceSetPreset . getSpectrumWorkspaceIndex ());
fsm = new AddSampleMIMOFSM ( m_mainWindow ,
m_mainWindow -> m_workspaces [ deviceWorkspaceIndex ],
m_mainWindow -> m_workspaces [ spectrumWorkspaceIndex ],
bestDeviceIndex , false , m_addDevicesFSM );
}
else
{
qDebug () << "MainWindow::loadConfiguration: Unknown preset type: " << deviceSetPreset . getPresetType ();
}
// Chain the FSMs together
if ( fsm )
{
m_addDevicesFSM -> addState ( fsm );
if ( ! sInitial ) {
sInitial = fsm ;
}
if ( sPrev ) {
sPrev -> addTransition ( sPrev , & QState :: finished , fsm );
}
sPrev = fsm ;
}
}
m_addDevicesFSM -> addState ( sFinal );
if ( sPrev )
{
m_addDevicesFSM -> setInitialState ( sInitial );
sPrev -> addTransition ( sPrev , & QState :: finished , sFinal );
}
else
{
m_addDevicesFSM -> setInitialState ( sFinal );
}
// Run all the FSMs
m_addDevicesFSM -> start ();
}
void LoadConfigurationFSM :: loadDeviceSetSettings ()
{
qDebug () << "LoadConfigurationFSM::loadDeviceSetSettings" ;
if ( m_waitBox )
{
m_waitBox -> setLabelText ( "Loading device set settings..." );
m_waitBox -> setValue ( 70 );
}
const QList < Preset >& deviceSetPresets = m_configuration -> getDeviceSetPresets ();
int deviceSetIndex = 0 ;
for ( const auto & deviceSetPreset : deviceSetPresets )
{
2024-10-10 14:36:06 +01:00
if ((( int ) m_mainWindow -> m_deviceUIs . size ()) > deviceSetIndex )
2024-10-10 13:57:11 +01:00
{
MDIUtils :: restoreMDIGeometry ( m_mainWindow -> m_deviceUIs [ deviceSetIndex ] -> m_deviceGUI , deviceSetPreset . getDeviceGeometry ());
MDIUtils :: restoreMDIGeometry ( m_mainWindow -> m_deviceUIs [ deviceSetIndex ] -> m_mainSpectrumGUI , deviceSetPreset . getSpectrumGeometry ());
m_mainWindow -> m_deviceUIs [ deviceSetIndex ] -> loadDeviceSetSettings ( & deviceSetPreset , m_mainWindow -> m_pluginManager -> getPluginAPI (), & m_mainWindow -> m_workspaces , nullptr );
deviceSetIndex ++ ;
}
}
}
void LoadConfigurationFSM :: loadFeatureSets ()
{
qDebug () << "LoadConfigurationFSM::loadFeatureSets" ;
if ( m_waitBox )
{
m_waitBox -> setLabelText ( "Loading feature sets..." );
m_waitBox -> setValue ( 75 );
}
m_mainWindow -> m_featureUIs [ 0 ] -> loadFeatureSetSettings (
& m_configuration -> getFeatureSetPreset (),
m_mainWindow -> m_pluginManager -> getPluginAPI (),
m_mainWindow -> m_apiAdapter ,
& m_mainWindow -> m_workspaces ,
nullptr
);
for ( int i = 0 ; i < m_mainWindow -> m_featureUIs [ 0 ] -> getNumberOfFeatures (); i ++ )
{
FeatureGUI * gui = m_mainWindow -> m_featureUIs [ 0 ] -> getFeatureGuiAt ( i );
QObject :: connect (
gui ,
& FeatureGUI :: moveToWorkspace ,
2025-09-01 10:51:42 +01:00
m_mainWindow ,
2024-10-10 13:57:11 +01:00
[ m_mainWindow = m_mainWindow , gui ]( int wsIndexDest ){ m_mainWindow -> featureMove ( gui , wsIndexDest ); }
);
}
}
void LoadConfigurationFSM :: restoreGeometry ()
{
qDebug () << "LoadConfigurationFSM::restoreGeometry" ;
// Lastly restore workspaces geometry
if ( m_waitBox )
{
m_waitBox -> setValue ( 90 );
m_waitBox -> setLabelText ( "Finalizing..." );
}
for ( int i = 0 ; i < m_configuration -> getNumberOfWorkspaceGeometries (); i ++ )
{
m_mainWindow -> m_workspaces [ i ] -> restoreGeometry ( m_configuration -> getWorkspaceGeometries ()[ i ]);
m_mainWindow -> m_workspaces [ i ] -> restoreGeometry ( m_configuration -> getWorkspaceGeometries ()[ i ]);
m_mainWindow -> m_workspaces [ i ] -> adjustSubWindowsAfterRestore ();
#ifdef ANDROID
// On Android, workspaces seem to be restored to 0,20, rather than 0,0
2024-10-21 17:05:19 +01:00
m_mainWindow -> m_workspaces [ i ] -> move ( m_mainWindow -> m_workspaces [ i ] -> pos (). x (), 0 );
2024-10-10 13:57:11 +01:00
// Need to call updateGeometry, otherwise sometimes the layout is corrupted
m_mainWindow -> m_workspaces [ i ] -> updateGeometry ();
#endif
if ( m_mainWindow -> m_workspaces [ i ] -> getAutoStackOption ()) {
m_mainWindow -> m_workspaces [ i ] -> layoutSubWindows ();
}
}
if ( m_waitBox ) {
m_waitBox -> setValue ( 100 );
}
}
2025-06-20 15:43:01 +01:00
InitFSM :: InitFSM ( MainWindow * mainWindow , SDRangelSplash * splash , bool loadDefault , bool showConfigs , QObject * parent ) :
2024-10-10 13:57:11 +01:00
MainWindowFSM ( mainWindow , parent ),
2025-06-20 15:43:01 +01:00
m_splash ( splash ),
m_showConfigs ( showConfigs )
2024-10-10 13:57:11 +01:00
{
// Create FSM
createStates ( 2 );
2024-10-10 14:36:06 +01:00
if ( loadDefault )
{
2025-06-20 15:43:01 +01:00
m_loadConfigurationFSM = new LoadConfigurationFSM ( m_mainWindow , m_mainWindow -> m_mainCore -> getMutableSettings (). getWorkingConfiguration (), nullptr , this );
2024-10-10 13:57:11 +01:00
2025-06-20 15:43:01 +01:00
m_states [ 0 ] -> addTransition ( m_loadConfigurationFSM , & LoadConfigurationFSM :: finished , m_finalState );
2024-10-10 13:57:11 +01:00
2025-06-20 15:43:01 +01:00
connect ( m_states [ 0 ], & QState :: entered , this , & InitFSM :: loadDefaultConfiguration );
2024-10-10 14:36:06 +01:00
}
else
{
m_states [ 0 ] -> addTransition ( m_finalState );
}
2024-10-10 13:57:11 +01:00
connect ( m_finalState , & QState :: entered , this , & InitFSM :: showDefaultConfigurations );
}
void InitFSM :: loadDefaultConfiguration ()
{
m_splash -> showStatusMessage ( "load current configuration..." , Qt :: white );
qDebug () << "MainWindow::MainWindow: load current configuration..." ;
m_loadConfigurationFSM -> start ();
}
void InitFSM :: showDefaultConfigurations ()
{
QApplication :: restoreOverrideCursor ();
//m_mainWindow->show();
if ( m_mainWindow -> m_workspaces . size () == 0 )
{
qDebug () << "MainWindow::MainWindow: no or empty current configuration, creating empty workspace..." ;
m_mainWindow -> addWorkspace ();
2025-06-20 15:43:01 +01:00
if ( m_showConfigs )
{
// If no configurations, load some basic examples
if ( m_mainWindow -> m_mainCore -> getMutableSettings (). getConfigurations () -> size () == 0 ) {
m_mainWindow -> loadDefaultConfigurations ();
}
2024-10-10 13:57:11 +01:00
#if defined(ANDROID) || defined(__EMSCRIPTEN__)
2025-06-20 15:43:01 +01:00
// Show welcome dialog
m_mainWindow -> on_action_Welcome_triggered ();
2024-10-10 13:57:11 +01:00
#endif
2025-06-20 15:43:01 +01:00
// Show configurations
m_mainWindow -> openConfigurationDialog ( true );
}
}
2024-10-10 13:57:11 +01:00
}
CloseFSM :: CloseFSM ( MainWindow * mainWindow , QObject * parent ) :
MainWindowFSM ( mainWindow , parent )
{
// Create FSM
createStates ( 2 );
m_states [ 0 ] -> addTransition ( m_mainWindow , & MainWindow :: allDeviceSetsRemoved , m_finalState );
connect ( this , & QStateMachine :: started , this , & CloseFSM :: on_started );
connect ( this , & QStateMachine :: finished , this , & CloseFSM :: on_finished );
}
void CloseFSM :: on_started ()
{
m_mainWindow -> removeAllDeviceSets ();
}
void CloseFSM :: on_finished ()
{
m_mainWindow -> close ();
}
void MainWindow :: sampleSourceAdd ( Workspace * deviceWorkspace , Workspace * spectrumWorkspace , int deviceIndex )
{
AddSampleSourceFSM * fsm = new AddSampleSourceFSM ( this , deviceWorkspace , spectrumWorkspace , deviceIndex , true );
connect ( fsm , & AddSampleSourceFSM :: finished , fsm , & AddSampleSourceFSM :: deleteLater );
fsm -> start ();
}
2022-04-09 13:38:22 +02:00
void MainWindow :: sampleSourceCreate (
2022-04-07 16:32:03 +02:00
int deviceSetIndex ,
2024-10-10 15:56:27 +01:00
int & deviceIndex ,
2022-04-09 13:38:22 +02:00
DeviceUISet * deviceUISet
2022-04-07 16:32:03 +02:00
)
{
2022-04-14 20:41:32 +02:00
DeviceAPI * deviceAPI = deviceUISet -> m_deviceAPI ;
2022-04-07 16:32:03 +02:00
DeviceEnumerator :: instance () -> changeRxSelection ( deviceSetIndex , deviceIndex );
2019-05-09 01:12:40 +02:00
const PluginInterface :: SamplingDevice * samplingDevice = DeviceEnumerator :: instance () -> getRxSamplingDevice ( deviceIndex );
2020-10-11 08:27:58 +02:00
deviceAPI -> setSamplingDeviceSequence ( samplingDevice -> sequence );
deviceAPI -> setDeviceNbItems ( samplingDevice -> deviceNbItems );
deviceAPI -> setDeviceItemIndex ( samplingDevice -> deviceItemIndex );
deviceAPI -> setHardwareId ( samplingDevice -> hardwareId );
deviceAPI -> setSamplingDeviceId ( samplingDevice -> id );
deviceAPI -> setSamplingDeviceSerial ( samplingDevice -> serial );
deviceAPI -> setSamplingDeviceDisplayName ( samplingDevice -> displayedName );
deviceAPI -> setSamplingDevicePluginInterface ( DeviceEnumerator :: instance () -> getRxPluginInterface ( deviceIndex ));
2017-11-02 03:30:54 +01:00
2022-05-14 11:18:09 +02:00
qDebug () << "MainWindow::sampleSourceCreate:"
<< "deviceSetIndex:" << deviceSetIndex
2022-04-07 16:32:03 +02:00
<< "deviceIndex:" << deviceIndex
<< "hardwareId:" << samplingDevice -> hardwareId
<< "sequence:" << samplingDevice -> sequence
<< "id:" << samplingDevice -> id
<< "serial:" << samplingDevice -> serial
<< "displayedName:" << samplingDevice -> displayedName ;
if ( deviceAPI -> getSamplingDeviceId (). size () == 0 ) // non existent device => replace by default
{
2022-05-14 11:18:09 +02:00
qDebug ( "MainWindow::sampleSourceCreate: non existent device replaced by File Input" );
2022-04-07 16:32:03 +02:00
int fileInputDeviceIndex = DeviceEnumerator :: instance () -> getFileInputDeviceIndex ();
2024-10-10 15:56:27 +01:00
deviceIndex = fileInputDeviceIndex ;
2022-04-07 16:32:03 +02:00
samplingDevice = DeviceEnumerator :: instance () -> getRxSamplingDevice ( fileInputDeviceIndex );
deviceAPI -> setSamplingDeviceSequence ( samplingDevice -> sequence );
deviceAPI -> setDeviceNbItems ( samplingDevice -> deviceNbItems );
deviceAPI -> setDeviceItemIndex ( samplingDevice -> deviceItemIndex );
deviceAPI -> setHardwareId ( samplingDevice -> hardwareId );
deviceAPI -> setSamplingDeviceId ( samplingDevice -> id );
deviceAPI -> setSamplingDeviceSerial ( samplingDevice -> serial );
deviceAPI -> setSamplingDeviceDisplayName ( samplingDevice -> displayedName );
deviceAPI -> setSamplingDevicePluginInterface ( DeviceEnumerator :: instance () -> getRxPluginInterface ( fileInputDeviceIndex ));
}
2020-10-10 20:08:11 +02:00
QString userArgs = m_mainCore -> m_settings . getDeviceUserArgs (). findUserArgs ( samplingDevice -> hardwareId , samplingDevice -> sequence );
2019-06-13 18:43:06 +02:00
if ( userArgs . size () > 0 ) {
2020-10-11 08:27:58 +02:00
deviceAPI -> setHardwareUserArguments ( userArgs );
2019-06-13 18:43:06 +02:00
}
2022-04-07 16:32:03 +02:00
// add to buddies list
2024-08-24 13:17:02 +02:00
auto it = m_deviceUIs . begin ();
2022-04-07 16:32:03 +02:00
int nbOfBuddies = 0 ;
2017-10-30 02:15:59 +01:00
2022-04-07 16:32:03 +02:00
for (; it != m_deviceUIs . end (); ++ it )
{
2024-08-24 13:17:02 +02:00
if (( * it != deviceUISet ) && // do not add to itself
( deviceUISet -> m_deviceAPI -> getHardwareId () == ( * it ) -> m_deviceAPI -> getHardwareId ()) &&
( deviceUISet -> m_deviceAPI -> getSamplingDeviceSerial () == ( * it ) -> m_deviceAPI -> getSamplingDeviceSerial ()))
2022-04-07 16:32:03 +02:00
{
2024-08-24 13:17:02 +02:00
( * it ) -> m_deviceAPI -> addBuddy ( deviceUISet -> m_deviceAPI );
nbOfBuddies ++ ;
2022-04-07 16:32:03 +02:00
}
}
if ( nbOfBuddies == 0 ) {
deviceUISet -> m_deviceAPI -> setBuddyLeader ( true );
}
// constructs new GUI and input object
2020-10-11 08:27:58 +02:00
DeviceSampleSource * source = deviceAPI -> getPluginInterface () -> createSampleSourcePluginInstance (
deviceAPI -> getSamplingDeviceId (), deviceAPI );
deviceAPI -> setSampleSource ( source );
2024-10-10 13:57:11 +01:00
}
void MainWindow :: sampleSourceCreateUI (
int deviceSetIndex ,
int deviceIndex ,
DeviceUISet * deviceUISet
)
{
DeviceAPI * deviceAPI = deviceUISet -> m_deviceAPI ;
2017-10-22 19:12:43 +02:00
QWidget * gui ;
2022-04-07 16:32:03 +02:00
DeviceGUI * deviceGUI = deviceAPI -> getPluginInterface () -> createSampleSourcePluginInstanceGUI (
2020-10-11 08:27:58 +02:00
deviceAPI -> getSamplingDeviceId (),
2017-10-30 00:02:28 +01:00
& gui ,
2022-04-07 16:32:03 +02:00
deviceUISet
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: moveToWorkspace ,
this ,
2024-08-24 13:17:02 +02:00
[ this , deviceGUI ]( int wsIndexDest ){ this -> deviceMove ( deviceGUI , wsIndexDest ); }
2022-04-07 16:32:03 +02:00
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: deviceChange ,
this ,
2024-08-24 13:17:02 +02:00
[ this , deviceGUI ]( int newDeviceIndex ){ this -> samplingDeviceChangeHandler ( deviceGUI , newDeviceIndex ); }
2022-04-07 16:32:03 +02:00
);
2022-04-10 00:11:23 +02:00
QObject :: connect (
deviceGUI ,
& DeviceGUI :: showSpectrum ,
this ,
2022-04-28 00:01:08 +02:00
& MainWindow :: mainSpectrumShow
2022-04-10 00:11:23 +02:00
);
2022-04-12 16:20:45 +02:00
QObject :: connect (
deviceGUI ,
& DeviceGUI :: showAllChannels ,
this ,
& MainWindow :: showAllChannels
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: closing ,
this ,
2024-08-24 13:17:02 +02:00
[ this , deviceGUI ](){ this -> removeDeviceSet ( deviceGUI -> getIndex ()); }
2022-04-12 16:20:45 +02:00
);
2022-04-13 18:43:37 +02:00
QObject :: connect (
deviceGUI ,
& DeviceGUI :: deviceSetPresetsDialogRequested ,
this ,
& MainWindow :: openDeviceSetPresetsDialog
);
2022-04-12 16:20:45 +02:00
2024-10-10 13:57:11 +01:00
deviceAPI -> getSampleSource () -> setMessageQueueToGUI ( deviceGUI -> getInputMessageQueue ());
deviceUISet -> m_deviceGUI = deviceGUI ;
2024-10-10 15:56:27 +01:00
const PluginInterface :: SamplingDevice * samplingDevice = DeviceEnumerator :: instance () -> getRxSamplingDevice ( deviceIndex );
const PluginInterface :: SamplingDevice * selectedDevice = DeviceEnumerator :: instance () -> getRxSamplingDevice ( deviceIndex ); // FIXME: Why not use samplingDevice?
2024-10-10 13:57:11 +01:00
deviceUISet -> m_selectedDeviceId = selectedDevice -> id ;
deviceUISet -> m_selectedDeviceSerial = selectedDevice -> serial ;
deviceUISet -> m_selectedDeviceSequence = selectedDevice -> sequence ;
deviceUISet -> m_selectedDeviceItemImdex = selectedDevice -> deviceItemIndex ;
deviceUISet -> m_deviceAPI -> getSampleSource () -> init ();
// Finalize GUI setup and add it to workspace MDI
deviceGUI -> setDeviceType ( DeviceGUI :: DeviceRx );
deviceGUI -> setIndex ( deviceSetIndex );
deviceGUI -> setToolTip ( samplingDevice -> displayedName );
deviceGUI -> setTitle ( samplingDevice -> displayedName . split ( " " )[ 0 ]);
2026-01-28 02:48:42 +01:00
deviceGUI -> setDefaultTitle ( samplingDevice -> displayedName . split ( " " )[ 0 ]);
2024-10-10 15:56:27 +01:00
deviceGUI -> setCurrentDeviceIndex ( deviceIndex );
2024-10-10 13:57:11 +01:00
QStringList channelNames ;
m_pluginManager -> listRxChannels ( channelNames );
deviceGUI -> setChannelNames ( channelNames );
MainSpectrumGUI * mainSpectrumGUI = deviceUISet -> m_mainSpectrumGUI ;
mainSpectrumGUI -> setDeviceType ( MainSpectrumGUI :: DeviceRx );
mainSpectrumGUI -> setIndex ( deviceSetIndex );
mainSpectrumGUI -> setToolTip ( samplingDevice -> displayedName );
mainSpectrumGUI -> setTitle ( samplingDevice -> displayedName . split ( " " )[ 0 ]);
2022-04-07 16:32:03 +02:00
}
2024-10-10 13:57:11 +01:00
void MainWindow :: sampleSinkAdd ( Workspace * deviceWorkspace , Workspace * spectrumWorkspace , int deviceIndex )
{
AddSampleSinkFSM * fsm = new AddSampleSinkFSM ( this , deviceWorkspace , spectrumWorkspace , deviceIndex , true );
connect ( fsm , & AddSampleSinkFSM :: finished , fsm , & AddSampleSinkFSM :: deleteLater );
fsm -> start ();
}
2022-04-09 13:38:22 +02:00
void MainWindow :: sampleSinkCreate (
2022-04-07 16:32:03 +02:00
int deviceSetIndex ,
2024-10-10 15:56:27 +01:00
int & deviceIndex ,
2022-04-09 13:38:22 +02:00
DeviceUISet * deviceUISet
2022-04-07 16:32:03 +02:00
)
{
2022-04-14 20:41:32 +02:00
DeviceAPI * deviceAPI = deviceUISet -> m_deviceAPI ;
2022-04-07 16:32:03 +02:00
DeviceEnumerator :: instance () -> changeTxSelection ( deviceSetIndex , deviceIndex );
const PluginInterface :: SamplingDevice * samplingDevice = DeviceEnumerator :: instance () -> getTxSamplingDevice ( deviceIndex );
2020-10-11 08:27:58 +02:00
deviceAPI -> setSamplingDeviceSequence ( samplingDevice -> sequence );
deviceAPI -> setDeviceNbItems ( samplingDevice -> deviceNbItems );
deviceAPI -> setDeviceItemIndex ( samplingDevice -> deviceItemIndex );
deviceAPI -> setHardwareId ( samplingDevice -> hardwareId );
deviceAPI -> setSamplingDeviceId ( samplingDevice -> id );
deviceAPI -> setSamplingDeviceSerial ( samplingDevice -> serial );
deviceAPI -> setSamplingDeviceDisplayName ( samplingDevice -> displayedName );
2022-04-07 16:32:03 +02:00
deviceAPI -> setSamplingDevicePluginInterface ( DeviceEnumerator :: instance () -> getTxPluginInterface ( deviceIndex ));
2022-05-14 11:18:09 +02:00
qDebug () << "MainWindow::sampleSinkCreate:"
<< "deviceSetIndex:" << deviceSetIndex
2022-04-07 16:32:03 +02:00
<< "newDeviceIndex:" << deviceIndex
<< "hardwareId:" << samplingDevice -> hardwareId
<< "sequence:" << samplingDevice -> sequence
<< "id:" << samplingDevice -> id
<< "serial:" << samplingDevice -> serial
<< "displayedName:" << samplingDevice -> displayedName ;
if ( deviceAPI -> getSamplingDeviceId (). size () == 0 ) // non existent device => replace by default
{
2022-05-14 11:18:09 +02:00
qDebug ( "MainWindow::sampleSinkCreate: non existent device replaced by File Sink" );
2022-04-07 16:32:03 +02:00
int fileSinkDeviceIndex = DeviceEnumerator :: instance () -> getFileOutputDeviceIndex ();
2024-10-10 15:56:27 +01:00
deviceIndex = fileSinkDeviceIndex ;
2024-08-24 13:17:02 +02:00
samplingDevice = DeviceEnumerator :: instance () -> getTxSamplingDevice ( fileSinkDeviceIndex );
2022-04-07 16:32:03 +02:00
deviceAPI -> setSamplingDeviceSequence ( samplingDevice -> sequence );
deviceAPI -> setDeviceNbItems ( samplingDevice -> deviceNbItems );
deviceAPI -> setDeviceItemIndex ( samplingDevice -> deviceItemIndex );
deviceAPI -> setHardwareId ( samplingDevice -> hardwareId );
deviceAPI -> setSamplingDeviceId ( samplingDevice -> id );
deviceAPI -> setSamplingDeviceSerial ( samplingDevice -> serial );
deviceAPI -> setSamplingDeviceDisplayName ( samplingDevice -> displayedName );
deviceAPI -> setSamplingDevicePluginInterface ( DeviceEnumerator :: instance () -> getTxPluginInterface ( fileSinkDeviceIndex ));
}
2017-11-02 03:30:54 +01:00
2020-10-10 20:08:11 +02:00
QString userArgs = m_mainCore -> m_settings . getDeviceUserArgs (). findUserArgs ( samplingDevice -> hardwareId , samplingDevice -> sequence );
2019-06-13 18:43:06 +02:00
if ( userArgs . size () > 0 ) {
2020-10-11 08:27:58 +02:00
deviceAPI -> setHardwareUserArguments ( userArgs );
2019-06-13 18:43:06 +02:00
}
2022-04-07 16:32:03 +02:00
// add to buddies list
2024-08-24 13:17:02 +02:00
auto it = m_deviceUIs . begin ();
2022-04-07 16:32:03 +02:00
int nbOfBuddies = 0 ;
for (; it != m_deviceUIs . end (); ++ it )
{
2024-08-24 13:17:02 +02:00
if (( * it != deviceUISet ) && // do not add to itself
( deviceAPI -> getHardwareId () == ( * it ) -> m_deviceAPI -> getHardwareId ()) &&
( deviceAPI -> getSamplingDeviceSerial () == ( * it ) -> m_deviceAPI -> getSamplingDeviceSerial ()))
2022-04-07 16:32:03 +02:00
{
2024-08-24 13:17:02 +02:00
( * it ) -> m_deviceAPI -> addBuddy ( deviceAPI );
nbOfBuddies ++ ;
2022-04-07 16:32:03 +02:00
}
}
if ( nbOfBuddies == 0 ) {
deviceAPI -> setBuddyLeader ( true );
}
2017-10-30 02:23:06 +01:00
2022-04-07 16:32:03 +02:00
// constructs new GUI and output object
2020-10-11 08:27:58 +02:00
DeviceSampleSink * sink = deviceAPI -> getPluginInterface () -> createSampleSinkPluginInstance (
deviceAPI -> getSamplingDeviceId (), deviceAPI );
deviceAPI -> setSampleSink ( sink );
2024-10-10 13:57:11 +01:00
}
void MainWindow :: sampleSinkCreateUI (
int deviceSetIndex ,
int deviceIndex ,
DeviceUISet * deviceUISet
)
{
DeviceAPI * deviceAPI = deviceUISet -> m_deviceAPI ;
2017-10-22 19:12:43 +02:00
QWidget * gui ;
2022-04-07 16:32:03 +02:00
DeviceGUI * deviceGUI = deviceAPI -> getPluginInterface () -> createSampleSinkPluginInstanceGUI (
2020-10-11 08:27:58 +02:00
deviceAPI -> getSamplingDeviceId (),
2017-10-30 01:11:35 +01:00
& gui ,
2022-04-07 16:32:03 +02:00
deviceUISet
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: moveToWorkspace ,
this ,
2024-08-24 13:17:02 +02:00
[ this , deviceGUI ]( int wsIndexDest ){ this -> deviceMove ( deviceGUI , wsIndexDest ); }
2022-04-07 16:32:03 +02:00
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: deviceChange ,
this ,
2024-08-24 13:17:02 +02:00
[ this , deviceGUI ]( int newDeviceIndex ){ this -> samplingDeviceChangeHandler ( deviceGUI , newDeviceIndex ); }
2022-04-07 16:32:03 +02:00
);
2022-04-12 16:20:45 +02:00
QObject :: connect (
deviceGUI ,
& DeviceGUI :: showSpectrum ,
this ,
2022-04-28 00:01:08 +02:00
& MainWindow :: mainSpectrumShow
2022-04-12 16:20:45 +02:00
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: showAllChannels ,
this ,
& MainWindow :: showAllChannels
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: closing ,
this ,
2024-08-24 13:17:02 +02:00
[ this , deviceGUI ](){ this -> removeDeviceSet ( deviceGUI -> getIndex ()); }
2022-04-12 16:20:45 +02:00
);
2022-04-13 18:43:37 +02:00
QObject :: connect (
deviceGUI ,
& DeviceGUI :: deviceSetPresetsDialogRequested ,
this ,
& MainWindow :: openDeviceSetPresetsDialog
);
2022-04-07 16:32:03 +02:00
deviceAPI -> getSampleSink () -> setMessageQueueToGUI ( deviceGUI -> getInputMessageQueue ());
deviceUISet -> m_deviceGUI = deviceGUI ;
2024-10-10 15:56:27 +01:00
const PluginInterface :: SamplingDevice * samplingDevice = DeviceEnumerator :: instance () -> getTxSamplingDevice ( deviceIndex );
const PluginInterface :: SamplingDevice * selectedDevice = DeviceEnumerator :: instance () -> getRxSamplingDevice ( deviceIndex ); // FIXME: Why getRxSamplingDevice?
2022-04-09 13:38:22 +02:00
deviceUISet -> m_selectedDeviceId = selectedDevice -> id ;
deviceUISet -> m_selectedDeviceSerial = selectedDevice -> serial ;
deviceUISet -> m_selectedDeviceSequence = selectedDevice -> sequence ;
deviceUISet -> m_selectedDeviceItemImdex = selectedDevice -> deviceItemIndex ;
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> getSampleSink () -> init ();
// Finalize GUI setup and add it to workspace MDI
deviceGUI -> setDeviceType ( DeviceGUI :: DeviceTx );
deviceGUI -> setIndex ( deviceSetIndex );
deviceGUI -> setToolTip ( samplingDevice -> displayedName );
deviceGUI -> setTitle ( samplingDevice -> displayedName . split ( " " )[ 0 ]);
2026-01-28 02:48:42 +01:00
deviceGUI -> setDefaultTitle ( samplingDevice -> displayedName . split ( " " )[ 0 ]);
2024-10-10 15:56:27 +01:00
deviceGUI -> setCurrentDeviceIndex ( deviceIndex );
2022-04-12 16:20:45 +02:00
QStringList channelNames ;
m_pluginManager -> listTxChannels ( channelNames );
deviceGUI -> setChannelNames ( channelNames );
2022-04-09 13:38:22 +02:00
MainSpectrumGUI * spectrumGUI = deviceUISet -> m_mainSpectrumGUI ;
spectrumGUI -> setDeviceType ( MainSpectrumGUI :: DeviceTx );
spectrumGUI -> setIndex ( deviceSetIndex );
spectrumGUI -> setToolTip ( samplingDevice -> displayedName );
spectrumGUI -> setTitle ( samplingDevice -> displayedName . split ( " " )[ 0 ]);
2017-10-22 19:12:43 +02:00
}
2022-04-14 03:07:33 +02:00
void MainWindow :: sampleMIMOAdd ( Workspace * deviceWorkspace , Workspace * spectrumWorkspace , int deviceIndex )
2020-11-10 12:08:58 +01:00
{
2024-10-10 13:57:11 +01:00
AddSampleMIMOFSM * fsm = new AddSampleMIMOFSM ( this , deviceWorkspace , spectrumWorkspace , deviceIndex , true );
connect ( fsm , & AddSampleMIMOFSM :: finished , fsm , & AddSampleSinkFSM :: deleteLater );
fsm -> start ();
2022-04-07 16:32:03 +02:00
}
2022-04-09 13:38:22 +02:00
void MainWindow :: sampleMIMOCreate (
2022-04-07 16:32:03 +02:00
int deviceSetIndex ,
2024-10-10 15:56:27 +01:00
int & deviceIndex ,
2022-04-09 13:38:22 +02:00
DeviceUISet * deviceUISet
2022-04-07 16:32:03 +02:00
)
{
2022-04-14 20:41:32 +02:00
DeviceAPI * deviceAPI = deviceUISet -> m_deviceAPI ;
2022-04-07 16:32:03 +02:00
DeviceEnumerator :: instance () -> changeMIMOSelection ( deviceSetIndex , deviceIndex );
const PluginInterface :: SamplingDevice * samplingDevice = DeviceEnumerator :: instance () -> getMIMOSamplingDevice ( deviceIndex );
2020-11-10 12:08:58 +01:00
deviceAPI -> setSamplingDeviceSequence ( samplingDevice -> sequence );
deviceAPI -> setDeviceNbItems ( samplingDevice -> deviceNbItems );
deviceAPI -> setDeviceItemIndex ( samplingDevice -> deviceItemIndex );
deviceAPI -> setHardwareId ( samplingDevice -> hardwareId );
deviceAPI -> setSamplingDeviceId ( samplingDevice -> id );
deviceAPI -> setSamplingDeviceSerial ( samplingDevice -> serial );
deviceAPI -> setSamplingDeviceDisplayName ( samplingDevice -> displayedName );
2022-04-07 16:32:03 +02:00
deviceAPI -> setSamplingDevicePluginInterface ( DeviceEnumerator :: instance () -> getMIMOPluginInterface ( deviceIndex ));
2022-05-14 11:18:09 +02:00
qDebug () << "MainWindow::sampleMIMOCreate:"
<< "deviceSetIndex" << deviceSetIndex
2022-04-07 16:32:03 +02:00
<< "newDeviceIndex:" << deviceIndex
<< "hardwareId:" << samplingDevice -> hardwareId
<< "sequence:" << samplingDevice -> sequence
<< "id:" << samplingDevice -> id
<< "serial:" << samplingDevice -> serial
<< "displayedName:" << samplingDevice -> displayedName ;
if ( deviceAPI -> getSamplingDeviceId (). size () == 0 ) // non existent device => replace by default
{
2022-05-14 11:18:09 +02:00
qDebug ( "MainWindow::sampleMIMOCreate: non existent device replaced by Test MIMO" );
2022-04-07 16:32:03 +02:00
int testMIMODeviceIndex = DeviceEnumerator :: instance () -> getTestMIMODeviceIndex ();
2024-10-10 15:56:27 +01:00
deviceIndex = testMIMODeviceIndex ;
2024-08-24 13:17:02 +02:00
samplingDevice = DeviceEnumerator :: instance () -> getMIMOSamplingDevice ( testMIMODeviceIndex );
2022-04-07 16:32:03 +02:00
deviceAPI -> setSamplingDeviceSequence ( samplingDevice -> sequence );
deviceAPI -> setDeviceNbItems ( samplingDevice -> deviceNbItems );
deviceAPI -> setDeviceItemIndex ( samplingDevice -> deviceItemIndex );
deviceAPI -> setHardwareId ( samplingDevice -> hardwareId );
deviceAPI -> setSamplingDeviceId ( samplingDevice -> id );
deviceAPI -> setSamplingDeviceSerial ( samplingDevice -> serial );
deviceAPI -> setSamplingDeviceDisplayName ( samplingDevice -> displayedName );
deviceAPI -> setSamplingDevicePluginInterface ( DeviceEnumerator :: instance () -> getMIMOPluginInterface ( testMIMODeviceIndex ));
}
2020-11-10 12:08:58 +01:00
QString userArgs = m_mainCore -> m_settings . getDeviceUserArgs (). findUserArgs ( samplingDevice -> hardwareId , samplingDevice -> sequence );
if ( userArgs . size () > 0 ) {
deviceAPI -> setHardwareUserArguments ( userArgs );
}
2022-04-07 16:32:03 +02:00
// constructs new GUI and output object
2020-11-10 12:08:58 +01:00
DeviceSampleMIMO * mimo = deviceAPI -> getPluginInterface () -> createSampleMIMOPluginInstance (
deviceAPI -> getSamplingDeviceId (), deviceAPI );
deviceAPI -> setSampleMIMO ( mimo );
2024-10-10 13:57:11 +01:00
}
void MainWindow :: sampleMIMOCreateUI (
int deviceSetIndex ,
int deviceIndex ,
DeviceUISet * deviceUISet
)
{
DeviceAPI * deviceAPI = deviceUISet -> m_deviceAPI ;
2020-11-10 12:08:58 +01:00
QWidget * gui ;
2022-04-07 16:32:03 +02:00
DeviceGUI * deviceGUI = deviceAPI -> getPluginInterface () -> createSampleMIMOPluginInstanceGUI (
2020-11-10 12:08:58 +01:00
deviceAPI -> getSamplingDeviceId (),
& gui ,
2022-04-07 16:32:03 +02:00
deviceUISet
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: moveToWorkspace ,
this ,
2024-08-24 13:17:02 +02:00
[ this , deviceGUI ]( int wsIndexDest ){ this -> deviceMove ( deviceGUI , wsIndexDest ); }
2022-04-07 16:32:03 +02:00
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: deviceChange ,
this ,
2024-08-24 13:17:02 +02:00
[ this , deviceGUI ]( int newDeviceIndex ){ this -> samplingDeviceChangeHandler ( deviceGUI , newDeviceIndex ); }
2022-04-07 16:32:03 +02:00
);
2022-04-12 16:20:45 +02:00
QObject :: connect (
deviceGUI ,
& DeviceGUI :: showSpectrum ,
this ,
2022-04-28 00:01:08 +02:00
& MainWindow :: mainSpectrumShow
2022-04-12 16:20:45 +02:00
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: showAllChannels ,
this ,
& MainWindow :: showAllChannels
);
QObject :: connect (
deviceGUI ,
& DeviceGUI :: closing ,
this ,
2024-08-24 13:17:02 +02:00
[ this , deviceGUI ](){ this -> removeDeviceSet ( deviceGUI -> getIndex ()); }
2022-04-12 16:20:45 +02:00
);
2022-04-13 18:43:37 +02:00
QObject :: connect (
deviceGUI ,
& DeviceGUI :: deviceSetPresetsDialogRequested ,
this ,
& MainWindow :: openDeviceSetPresetsDialog
);
2022-04-07 16:32:03 +02:00
deviceAPI -> getSampleMIMO () -> setMessageQueueToGUI ( deviceGUI -> getInputMessageQueue ());
deviceUISet -> m_deviceGUI = deviceGUI ;
2024-10-10 15:56:27 +01:00
const PluginInterface :: SamplingDevice * samplingDevice = DeviceEnumerator :: instance () -> getMIMOSamplingDevice ( deviceIndex );
const PluginInterface :: SamplingDevice * selectedDevice = DeviceEnumerator :: instance () -> getRxSamplingDevice ( deviceIndex ); // FIXME: Why getRxSamplingDevice?
2022-04-09 13:38:22 +02:00
deviceUISet -> m_selectedDeviceId = selectedDevice -> id ;
deviceUISet -> m_selectedDeviceSerial = selectedDevice -> serial ;
deviceUISet -> m_selectedDeviceSequence = selectedDevice -> sequence ;
deviceUISet -> m_selectedDeviceItemImdex = selectedDevice -> deviceItemIndex ;
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> getSampleMIMO () -> init ();
// Finalize GUI setup and add it to workspace MDI
deviceGUI -> setDeviceType ( DeviceGUI :: DeviceMIMO );
deviceGUI -> setIndex ( deviceSetIndex );
deviceGUI -> setToolTip ( samplingDevice -> displayedName );
deviceGUI -> setTitle ( samplingDevice -> displayedName . split ( " " )[ 0 ]);
2026-01-28 02:48:42 +01:00
deviceGUI -> setDefaultTitle ( samplingDevice -> displayedName . split ( " " )[ 0 ]);
2024-10-10 15:56:27 +01:00
deviceGUI -> setCurrentDeviceIndex ( deviceIndex );
2024-08-24 13:17:02 +02:00
QStringList channelNames ;
QStringList tmpChannelNames ;
2022-04-12 16:20:45 +02:00
m_pluginManager -> listMIMOChannels ( channelNames );
2022-04-18 01:42:03 +02:00
m_pluginManager -> listRxChannels ( tmpChannelNames );
channelNames . append ( tmpChannelNames );
m_pluginManager -> listTxChannels ( tmpChannelNames );
channelNames . append ( tmpChannelNames );
2022-04-12 16:20:45 +02:00
deviceGUI -> setChannelNames ( channelNames );
2022-04-09 13:38:22 +02:00
MainSpectrumGUI * spectrumGUI = deviceUISet -> m_mainSpectrumGUI ;
spectrumGUI -> setDeviceType ( MainSpectrumGUI :: DeviceMIMO );
spectrumGUI -> setIndex ( deviceSetIndex );
spectrumGUI -> setToolTip ( samplingDevice -> displayedName );
spectrumGUI -> setTitle ( samplingDevice -> displayedName . split ( " " )[ 0 ]);
2020-11-10 12:08:58 +01:00
}
2022-04-12 16:20:45 +02:00
void MainWindow :: removeDeviceSet ( int deviceSetIndex )
{
2022-04-14 20:41:32 +02:00
qDebug ( "MainWindow::removeDeviceSet: index: %d" , deviceSetIndex );
2022-04-12 16:20:45 +02:00
if ( deviceSetIndex >= ( int ) m_deviceUIs . size ()) {
return ;
}
2024-10-10 13:57:11 +01:00
RemoveDeviceSetFSM * fsm = new RemoveDeviceSetFSM ( this , deviceSetIndex );
connect ( fsm , & RemoveDeviceSetFSM :: finished , fsm , & RemoveDeviceSetFSM :: deleteLater );
fsm -> start ();
2022-04-12 16:20:45 +02:00
}
2024-10-10 13:57:11 +01:00
void MainWindow :: removeAllDeviceSets ()
2022-04-12 16:20:45 +02:00
{
2024-10-10 13:57:11 +01:00
qDebug () << "MainWindow::removeAllDeviceSets" ;
RemoveAllDeviceSetsFSM * fsm = new RemoveAllDeviceSetsFSM ( this );
connect ( fsm , & RemoveAllDeviceSetsFSM :: finished , fsm , & RemoveAllDeviceSetsFSM :: deleteLater );
fsm -> start ();
2022-04-12 16:20:45 +02:00
}
2022-04-15 10:04:24 +02:00
void MainWindow :: removeLastDeviceSet ()
2017-10-22 19:12:43 +02:00
{
2024-10-10 13:57:11 +01:00
if ( m_deviceUIs . size () > 0 )
{
2024-08-17 11:24:19 +02:00
qDebug ( "MainWindow::removeLastDeviceSet: %s" , qPrintable ( m_deviceUIs . back () -> m_deviceAPI -> getHardwareId ()));
2024-10-10 13:57:11 +01:00
removeDeviceSet ( m_deviceUIs . size () - 1 );
2017-10-22 19:12:43 +02:00
}
}
2020-09-20 01:06:34 +02:00
void MainWindow :: addFeatureSet ()
{
2024-08-24 13:17:02 +02:00
auto newFeatureSetIndex = ( int ) m_featureUIs . size ();
2022-05-16 20:51:15 +02:00
if ( newFeatureSetIndex != 0 )
{
qWarning ( "MainWindow::addFeatureSet: attempt to add more than one feature set (%d)" , newFeatureSetIndex );
return ;
}
2020-10-11 00:22:42 +02:00
m_mainCore -> appendFeatureSet ();
2022-05-16 20:51:15 +02:00
m_featureUIs . push_back ( new FeatureUISet ( newFeatureSetIndex , m_mainCore -> m_featureSets [ newFeatureSetIndex ]));
emit m_mainCore -> featureSetAdded ( newFeatureSetIndex );
2020-09-20 01:06:34 +02:00
}
2020-11-14 22:08:06 +01:00
void MainWindow :: removeFeatureSet ( unsigned int tabIndex )
2020-09-20 01:06:34 +02:00
{
if ( tabIndex < m_featureUIs . size ())
{
delete m_featureUIs [ tabIndex ];
2021-12-04 10:54:19 +01:00
m_featureUIs . pop_back ();
2020-10-11 00:22:42 +02:00
m_mainCore -> removeFeatureSet ( tabIndex );
2022-03-23 05:53:12 +01:00
emit m_mainCore -> featureSetRemoved ( tabIndex );
2020-09-20 01:06:34 +02:00
}
}
void MainWindow :: removeAllFeatureSets ()
{
2024-08-24 13:17:02 +02:00
while ( ! m_featureUIs . empty ())
2020-09-20 01:06:34 +02:00
{
delete m_featureUIs . back ();
2021-12-04 10:54:19 +01:00
m_featureUIs . pop_back ();
m_mainCore -> removeLastFeatureSet ();
2020-09-20 01:06:34 +02:00
}
}
2017-12-23 23:41:37 +01:00
void MainWindow :: deleteChannel ( int deviceSetIndex , int channelIndex )
{
if (( deviceSetIndex >= 0 ) && ( deviceSetIndex < ( int ) m_deviceUIs . size ()))
{
DeviceUISet * deviceSet = m_deviceUIs [ deviceSetIndex ];
2019-09-08 00:44:56 +02:00
deviceSet -> deleteChannel ( channelIndex );
2017-12-23 23:41:37 +01:00
}
}
2017-10-22 19:12:43 +02:00
void MainWindow :: loadSettings ()
{
qDebug () << "MainWindow::loadSettings" ;
2020-10-10 20:08:11 +02:00
m_mainCore -> m_settings . load ();
m_mainCore -> m_settings . sortPresets ();
m_mainCore -> m_settings . sortCommands ();
2022-12-20 21:06:39 +00:00
if ( m_mainCore -> m_logger ) {
m_mainCore -> setLoggingOptions ();
}
2017-10-22 19:12:43 +02:00
}
2022-04-09 13:38:22 +02:00
void MainWindow :: loadDeviceSetPresetSettings ( const Preset * preset , int deviceSetIndex )
2017-10-22 19:12:43 +02:00
{
2022-04-09 13:38:22 +02:00
qDebug ( "MainWindow::loadDeviceSetPresetSettings: preset [%s | %s]" ,
2017-10-22 19:12:43 +02:00
qPrintable ( preset -> getGroup ()),
qPrintable ( preset -> getDescription ()));
2022-04-09 13:38:22 +02:00
if ( deviceSetIndex >= 0 )
2017-10-22 19:12:43 +02:00
{
2022-04-09 13:38:22 +02:00
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
deviceUISet -> loadDeviceSetSettings ( preset , m_pluginManager -> getPluginAPI (), & m_workspaces , nullptr );
2017-10-22 19:12:43 +02:00
}
}
2022-04-09 13:38:22 +02:00
void MainWindow :: saveDeviceSetPresetSettings ( Preset * preset , int deviceSetIndex )
2017-10-22 19:12:43 +02:00
{
2022-04-09 13:38:22 +02:00
qDebug ( "MainWindow::saveDeviceSetPresetSettings: preset [%s | %s]" ,
2017-10-22 19:12:43 +02:00
qPrintable ( preset -> getGroup ()),
qPrintable ( preset -> getDescription ()));
// Save from currently selected source tab
//int currentSourceTabIndex = ui->tabInputsView->currentIndex();
2024-08-24 13:17:02 +02:00
const DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
2022-04-09 13:38:22 +02:00
deviceUISet -> saveDeviceSetSettings ( preset );
2017-10-22 19:12:43 +02:00
}
2022-04-04 10:23:52 +02:00
void MainWindow :: loadFeatureSetPresetSettings ( const FeatureSetPreset * preset , int featureSetIndex , Workspace * workspace )
2020-09-24 05:38:05 +02:00
{
qDebug ( "MainWindow::loadFeatureSetPresetSettings: preset [%s | %s]" ,
qPrintable ( preset -> getGroup ()),
qPrintable ( preset -> getDescription ()));
if ( featureSetIndex >= 0 )
{
FeatureUISet * featureSetUI = m_featureUIs [ featureSetIndex ];
2020-09-28 00:20:37 +02:00
qDebug ( "MainWindow::loadFeatureSetPresetSettings: m_apiAdapter: %p" , m_apiAdapter );
2022-04-09 13:38:22 +02:00
featureSetUI -> loadFeatureSetSettings ( preset , m_pluginManager -> getPluginAPI (), m_apiAdapter , & m_workspaces , workspace );
2020-09-24 05:38:05 +02:00
}
}
void MainWindow :: saveFeatureSetPresetSettings ( FeatureSetPreset * preset , int featureSetIndex )
{
qDebug ( "MainWindow::saveFeatureSetPresetSettings: preset [%s | %s]" ,
qPrintable ( preset -> getGroup ()),
qPrintable ( preset -> getDescription ()));
// Save from currently selected source tab
//int currentSourceTabIndex = ui->tabInputsView->currentIndex();
FeatureUISet * featureUI = m_featureUIs [ featureSetIndex ];
preset -> clearFeatures ();
featureUI -> saveFeatureSetSettings ( preset );
}
2024-08-24 13:17:02 +02:00
void MainWindow :: loadDefaultConfigurations () const
2022-12-20 21:06:39 +00:00
{
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 ();
}
}
}
}
2022-04-12 16:20:45 +02:00
void MainWindow :: loadConfiguration ( const Configuration * configuration , bool fromDialog )
2018-01-05 11:54:05 +01:00
{
2022-04-09 13:38:22 +02:00
qDebug ( "MainWindow::loadConfiguration: configuration [%s | %s] %d workspace(s) - %d device set(s) - %d feature(s)" ,
2022-04-05 16:26:57 +02:00
qPrintable ( configuration -> getGroup ()),
qPrintable ( configuration -> getDescription ()),
2024-09-03 18:38:32 +03:00
( int ) configuration -> getNumberOfWorkspaceGeometries (),
( int ) configuration -> getDeviceSetPresets (). size (),
( int ) configuration -> getFeatureSetPreset (). getFeatureCount ()
2022-04-05 16:26:57 +02:00
);
2022-12-20 21:06:39 +00:00
QProgressDialog * waitBox = nullptr ;
2022-04-12 16:20:45 +02:00
if ( fromDialog )
{
2022-12-20 21:06:39 +00:00
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 );
2022-12-20 23:16:56 +00:00
QApplication :: processEvents ();
2022-04-12 16:20:45 +02:00
}
2024-10-10 13:57:11 +01:00
LoadConfigurationFSM * fsm = new LoadConfigurationFSM ( this , configuration , waitBox );
connect ( fsm , & LoadConfigurationFSM :: finished , fsm , & LoadConfigurationFSM :: deleteLater );
fsm -> start ();
2022-04-12 16:20:45 +02:00
}
2022-04-05 16:26:57 +02:00
void MainWindow :: saveConfiguration ( Configuration * configuration )
{
qDebug ( "MainWindow::saveConfiguration: configuration [%s | %s] %d workspaces" ,
qPrintable ( configuration -> getGroup ()),
qPrintable ( configuration -> getDescription ()),
2024-09-03 18:38:32 +03:00
( int ) m_workspaces . size ()
2022-04-05 16:26:57 +02:00
);
configuration -> clearData ();
2022-04-09 13:38:22 +02:00
QList < Preset >& deviceSetPresets = configuration -> getDeviceSetPresets ();
for ( const auto & deviceUISet : m_deviceUIs )
{
deviceSetPresets . push_back ( Preset ());
deviceUISet -> saveDeviceSetSettings ( & deviceSetPresets . back ());
2023-11-14 14:49:39 +00:00
deviceSetPresets . back (). setSpectrumGeometry ( MDIUtils :: saveMDIGeometry ( deviceUISet -> m_mainSpectrumGUI ));
2022-04-09 13:38:22 +02:00
deviceSetPresets . back (). setSpectrumWorkspaceIndex ( deviceUISet -> m_mainSpectrumGUI -> getWorkspaceIndex ());
2023-11-14 14:49:39 +00:00
deviceSetPresets . back (). setDeviceGeometry ( MDIUtils :: saveMDIGeometry ( deviceUISet -> m_deviceGUI ));
2022-04-09 13:38:22 +02:00
deviceSetPresets . back (). setDeviceWorkspaceIndex ( deviceUISet -> m_deviceGUI -> getWorkspaceIndex ());
2022-04-20 20:08:41 +02:00
qDebug ( "MainWindow::saveConfiguration: %s device in workspace %d spectrum in %d" ,
2022-04-14 03:07:33 +02:00
qPrintable ( deviceUISet -> m_deviceAPI -> getSamplingDeviceId ()),
deviceUISet -> m_deviceGUI -> getWorkspaceIndex (),
deviceUISet -> m_mainSpectrumGUI -> getWorkspaceIndex ());
2022-04-09 13:38:22 +02:00
}
2022-04-05 16:26:57 +02:00
m_featureUIs [ 0 ] -> saveFeatureSetSettings ( & configuration -> getFeatureSetPreset ());
2022-05-19 15:48:14 +02:00
for ( const auto & workspace : m_workspaces )
{
2022-04-05 16:26:57 +02:00
configuration -> getWorkspaceGeometries (). push_back ( workspace -> saveGeometry ());
2022-05-19 15:48:14 +02:00
configuration -> getWorkspaceAutoStackOptions (). push_back ( workspace -> getAutoStackOption ());
2022-12-20 21:06:39 +00:00
configuration -> getWorkspaceTabSubWindowsOptions (). push_back ( workspace -> getTabSubWindowsOption ());
2022-04-05 16:26:57 +02:00
}
2018-01-05 11:54:05 +01:00
}
2024-08-24 13:17:02 +02:00
QString MainWindow :: openGLVersion () const
2021-12-13 10:23:05 +00:00
{
2024-08-24 13:17:02 +02:00
const QOpenGLContext * glCurrentContext = QOpenGLContext :: globalShareContext ();
2021-12-13 10:23:05 +00:00
if ( glCurrentContext )
{
if ( glCurrentContext -> isValid ())
{
int major = glCurrentContext -> format (). majorVersion ();
int minor = glCurrentContext -> format (). minorVersion ();
bool es = glCurrentContext -> isOpenGLES ();
QString version = QString ( "%1.%2%3" ). arg ( major ). arg ( minor ). arg ( es ? " ES" : "" );
2022-05-16 12:43:07 +01:00
// Waterfall doesn't work if version is less than 2.1, so display in red
if (( major < 2 ) || (( major == 2 ) && ( minor == 0 ))) {
2021-12-13 10:23:05 +00:00
version = "<span style= \" color:red \" >" + version + "</span>" ;
}
return version ;
}
else
{
return "N/A" ;
}
}
else
{
return "N/A" ;
}
}
2024-08-24 13:17:02 +02:00
void MainWindow :: createMenuBar ( QToolButton * button ) const
2022-04-04 10:23:52 +02:00
{
2024-08-24 13:17:02 +02:00
QMenu * fileMenu ;
QMenu * viewMenu ;
QMenu * workspacesMenu ;
QMenu * preferencesMenu ;
QMenu * helpMenu ;
2022-12-20 21:06:39 +00:00
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
{
2024-08-24 13:17:02 +02:00
auto * menu = new QMenu ();
2022-12-20 21:06:39 +00:00
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 );
}
2022-04-04 10:23:52 +02:00
2022-04-20 21:33:18 +02:00
QAction * exitAction = fileMenu -> addAction ( "E&xit" );
2022-04-04 10:23:52 +02:00
exitAction -> setShortcut ( QKeySequence ( Qt :: CTRL + Qt :: Key_Q ));
exitAction -> setToolTip ( "Exit" );
QObject :: connect ( exitAction , & QAction :: triggered , this , & QMainWindow :: close );
2022-04-20 21:33:18 +02:00
QAction * fullscreenAction = viewMenu -> addAction ( "&Fullscreen" );
2022-04-04 10:23:52 +02:00
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 );
2023-02-17 21:57:09 +00:00
#ifdef ANDROID
QAction * keepscreenonAction = viewMenu -> addAction ( "&Keep screen on" );
keepscreenonAction -> setToolTip ( "Prevent screen from switching off" );
keepscreenonAction -> setCheckable ( true );
QObject :: connect ( keepscreenonAction , & QAction :: triggered , this , & MainWindow :: on_action_View_KeepScreenOn_toggled );
#endif
2023-08-13 23:52:57 +01:00
#ifdef ENABLE_PROFILER
QAction * profileAction = viewMenu -> addAction ( "&Profile data..." );
profileAction -> setToolTip ( "View profile data" );
QObject :: connect ( profileAction , & QAction :: triggered , this , & MainWindow :: on_action_Profile_triggered );
#endif
2022-04-04 10:23:52 +02:00
2022-04-20 21:33:18 +02:00
QAction * newWorkspaceAction = workspacesMenu -> addAction ( "&New" );
2022-04-04 10:23:52 +02:00
newWorkspaceAction -> setToolTip ( "Add a new workspace" );
QObject :: connect ( newWorkspaceAction , & QAction :: triggered , this , & MainWindow :: addWorkspace );
2022-04-20 21:33:18 +02:00
QAction * viewAllWorkspacesAction = workspacesMenu -> addAction ( "&View all" );
2022-04-04 10:23:52 +02:00
viewAllWorkspacesAction -> setToolTip ( "View all workspaces" );
QObject :: connect ( viewAllWorkspacesAction , & QAction :: triggered , this , & MainWindow :: viewAllWorkspaces );
2022-04-20 21:33:18 +02:00
QAction * removeEmptyWorkspacesAction = workspacesMenu -> addAction ( "&Remove empty" );
2022-04-05 16:26:57 +02:00
removeEmptyWorkspacesAction -> setToolTip ( "Remove empty workspaces" );
QObject :: connect ( removeEmptyWorkspacesAction , & QAction :: triggered , this , & MainWindow :: removeEmptyWorkspaces );
2022-04-04 10:23:52 +02:00
2022-04-20 21:33:18 +02:00
QAction * configurationsAction = preferencesMenu -> addAction ( "&Configurations..." );
2022-04-05 16:26:57 +02:00
configurationsAction -> setToolTip ( "Manage configurations" );
QObject :: connect ( configurationsAction , & QAction :: triggered , this , & MainWindow :: on_action_Configurations_triggered );
2022-04-20 21:33:18 +02:00
QAction * audioAction = preferencesMenu -> addAction ( "&Audio..." );
2022-04-04 10:23:52 +02:00
audioAction -> setToolTip ( "Audio preferences" );
QObject :: connect ( audioAction , & QAction :: triggered , this , & MainWindow :: on_action_Audio_triggered );
2022-06-18 12:35:44 +01:00
QAction * graphicsAction = preferencesMenu -> addAction ( "&Graphics..." );
graphicsAction -> setToolTip ( "Graphics preferences" );
QObject :: connect ( graphicsAction , & QAction :: triggered , this , & MainWindow :: on_action_Graphics_triggered );
2022-04-20 21:33:18 +02:00
QAction * loggingAction = preferencesMenu -> addAction ( "&Logging..." );
2022-04-04 10:23:52 +02:00
loggingAction -> setToolTip ( "Logging preferences" );
QObject :: connect ( loggingAction , & QAction :: triggered , this , & MainWindow :: on_action_Logging_triggered );
2022-04-20 21:33:18 +02:00
QAction * myPositionAction = preferencesMenu -> addAction ( "My &Position..." );
2022-04-04 10:23:52 +02:00
myPositionAction -> setToolTip ( "Set station position" );
QObject :: connect ( myPositionAction , & QAction :: triggered , this , & MainWindow :: on_action_My_Position_triggered );
2022-04-20 21:33:18 +02:00
QAction * fftAction = preferencesMenu -> addAction ( "&FFT..." );
2023-08-13 23:52:57 +01:00
fftAction -> setToolTip ( "Set FFT preferences" );
2022-04-04 10:23:52 +02:00
QObject :: connect ( fftAction , & QAction :: triggered , this , & MainWindow :: on_action_FFT_triggered );
2024-10-10 13:57:11 +01:00
#if QT_CONFIG(process)
2023-08-13 23:52:57 +01:00
QAction * fftWisdomAction = preferencesMenu -> addAction ( "&FFTW Wisdom..." );
fftWisdomAction -> setToolTip ( "Set FFTW cache" );
QObject :: connect ( fftWisdomAction , & QAction :: triggered , this , & MainWindow :: on_action_FFTWisdom_triggered );
2024-10-10 13:57:11 +01:00
#endif
2022-04-20 21:33:18 +02:00
QMenu * devicesMenu = preferencesMenu -> addMenu ( "&Devices" );
QAction * userArgumentsAction = devicesMenu -> addAction ( "&User arguments..." );
2022-04-04 10:23:52 +02:00
userArgumentsAction -> setToolTip ( "Device custom user arguments" );
QObject :: connect ( userArgumentsAction , & QAction :: triggered , this , & MainWindow :: on_action_DeviceUserArguments_triggered );
2024-10-10 13:57:11 +01:00
#if QT_CONFIG(process)
2022-04-20 21:33:18 +02:00
QAction * commandsAction = preferencesMenu -> addAction ( "C&ommands..." );
2022-04-04 16:13:42 +02:00
commandsAction -> setToolTip ( "External commands dialog" );
QObject :: connect ( commandsAction , & QAction :: triggered , this , & MainWindow :: on_action_commands_triggered );
2024-10-10 13:57:11 +01:00
#endif
2022-04-20 21:33:18 +02:00
QAction * saveAllAction = preferencesMenu -> addAction ( "&Save all" );
2022-04-05 16:26:57 +02:00
saveAllAction -> setToolTip ( "Save all current settings" );
QObject :: connect ( saveAllAction , & QAction :: triggered , this , & MainWindow :: on_action_saveAll_triggered );
2022-04-04 10:23:52 +02:00
2024-10-10 13:57:11 +01:00
#if defined(ANDROID) || defined(__EMSCRIPTEN__)
QAction * welcomeAction = helpMenu -> addAction ( "&Welcome..." );
welcomeAction -> setToolTip ( "Show welcome dialog" );
QObject :: connect ( welcomeAction , & QAction :: triggered , this , & MainWindow :: on_action_Welcome_triggered );
#endif
2022-04-20 21:33:18 +02:00
QAction * quickStartAction = helpMenu -> addAction ( "&Quick start..." );
2022-04-04 10:23:52 +02:00
quickStartAction -> setToolTip ( "Instructions for quick start" );
QObject :: connect ( quickStartAction , & QAction :: triggered , this , & MainWindow :: on_action_Quick_Start_triggered );
2022-04-20 21:33:18 +02:00
QAction * mainWindowAction = helpMenu -> addAction ( "&Main Window..." );
2022-04-04 10:23:52 +02:00
mainWindowAction -> setToolTip ( "Help on main window details" );
QObject :: connect ( mainWindowAction , & QAction :: triggered , this , & MainWindow :: on_action_Main_Window_triggered );
2022-04-20 21:33:18 +02:00
QAction * loadedPluginsAction = helpMenu -> addAction ( "Loaded &Plugins..." );
2022-04-04 10:23:52 +02:00
loadedPluginsAction -> setToolTip ( "List available plugins" );
QObject :: connect ( loadedPluginsAction , & QAction :: triggered , this , & MainWindow :: on_action_Loaded_Plugins_triggered );
2022-04-20 21:33:18 +02:00
QAction * aboutAction = helpMenu -> addAction ( "&About SDRangel..." );
2022-04-04 10:23:52 +02:00
aboutAction -> setToolTip ( "SDRangel application details" );
QObject :: connect ( aboutAction , & QAction :: triggered , this , & MainWindow :: on_action_About_triggered );
}
2017-10-22 19:12:43 +02:00
void MainWindow :: createStatusBar ()
{
QString qtVersionStr = QString ( "Qt %1 " ). arg ( QT_VERSION_STR );
2021-12-13 10:23:05 +00:00
QString openGLVersionStr = QString ( "OpenGL %1 " ). arg ( openGLVersion ());
2020-11-04 22:52:15 +01:00
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
2021-12-13 10:23:05 +00:00
m_showSystemWidget = new QLabel ( "SDRangel " + qApp -> applicationVersion () + " " + qtVersionStr + openGLVersionStr
2018-01-07 01:33:57 +01:00
+ QSysInfo :: currentCpuArchitecture () + " " + QSysInfo :: prettyProductName (), this );
2017-10-22 19:12:43 +02:00
#else
2021-12-13 10:23:05 +00:00
m_showSystemWidget = new QLabel ( "SDRangel " + qApp -> applicationVersion () + " " + qtVersionStr + openGLVersionStr , this );
2017-10-22 19:12:43 +02:00
#endif
statusBar () -> addPermanentWidget ( m_showSystemWidget );
m_dateTimeWidget = new QLabel ( tr ( "Date" ), this );
m_dateTimeWidget -> setToolTip ( tr ( "Current date/time" ));
statusBar () -> addPermanentWidget ( m_dateTimeWidget );
}
2019-07-22 18:49:24 +02:00
void MainWindow :: closeEvent ( QCloseEvent * closeEvent )
2017-10-22 19:12:43 +02:00
{
2019-07-22 18:49:24 +02:00
qDebug ( "MainWindow::closeEvent" );
2024-10-10 13:57:11 +01:00
if ( ! m_settingsSaved )
{
2021-07-01 15:28:43 +01:00
// Save window size and position
QSettings s ;
2021-07-01 16:07:25 +01:00
s . setValue ( "mainWindowGeometry" , qCompress ( saveGeometry ()). toBase64 ());
s . setValue ( "mainWindowState" , qCompress ( saveState ()). toBase64 ());
2021-07-01 15:28:43 +01:00
2022-04-05 16:26:57 +02:00
saveConfiguration ( m_mainCore -> m_settings . getWorkingConfiguration ());
m_mainCore -> m_settings . save ();
2019-07-22 18:49:24 +02:00
2024-10-10 13:57:11 +01:00
m_settingsSaved = true ;
}
if ( m_deviceUIs . size () > 0 )
{
CloseFSM * fsm = new CloseFSM ( this );
connect ( fsm , & CloseFSM :: finished , fsm , & CloseFSM :: deleteLater );
fsm -> start ();
closeEvent -> ignore (); // CloseFSM will call close again later once all devices closed
return ;
2022-04-09 13:38:22 +02:00
}
2019-07-22 18:49:24 +02:00
2023-08-13 23:52:57 +01:00
if ( m_profileDialog ) {
m_profileDialog -> close ();
}
2019-07-22 18:49:24 +02:00
closeEvent -> accept ();
2017-10-22 19:12:43 +02:00
}
void MainWindow :: applySettings ()
{
2022-04-05 16:26:57 +02:00
loadConfiguration ( m_mainCore -> m_settings . getWorkingConfiguration ());
2019-08-12 01:46:27 +02:00
2020-10-10 20:08:11 +02:00
m_mainCore -> m_settings . sortPresets ();
m_mainCore -> setLoggingOptions ();
2017-10-22 19:12:43 +02:00
}
2017-11-25 16:08:18 +01:00
bool MainWindow :: handleMessage ( const Message & cmd )
{
2020-10-10 20:08:11 +02:00
if ( MainCore :: MsgLoadPreset :: match ( cmd ))
2017-11-25 16:08:18 +01:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgLoadPreset & ) cmd ;
2022-04-13 18:43:37 +02:00
int deviceSetIndex = notif . getDeviceSetIndex ();
const Preset * preset = notif . getPreset ();
if ( deviceSetIndex < ( int ) m_deviceUIs . size ())
{
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
deviceUISet -> loadDeviceSetSettings ( preset , m_pluginManager -> getPluginAPI (), & m_workspaces , nullptr );
}
2017-11-25 16:08:18 +01:00
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgSavePreset :: match ( cmd ))
2017-11-25 16:47:13 +01:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgSavePreset & ) cmd ;
2022-05-16 20:51:15 +02:00
saveDeviceSetPresetSettings ( notif . getPreset (), notif . getDeviceSetIndex ());
m_mainCore -> m_settings . sortPresets ();
m_mainCore -> m_settings . save ();
2020-09-24 05:38:05 +02:00
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgLoadFeatureSetPreset :: match ( cmd ))
2020-09-24 05:38:05 +02:00
{
2024-08-24 13:17:02 +02:00
if ( ! m_workspaces . empty ())
2022-04-04 10:23:52 +02:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgLoadFeatureSetPreset & ) cmd ;
2022-04-04 10:23:52 +02:00
loadFeatureSetPresetSettings ( notif . getPreset (), notif . getFeatureSetIndex (), m_workspaces [ 0 ]);
}
2020-09-24 05:38:05 +02:00
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgSaveFeatureSetPreset :: match ( cmd ))
2020-09-24 05:38:05 +02:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgSaveFeatureSetPreset & ) cmd ;
2020-09-24 05:38:05 +02:00
saveFeatureSetPresetSettings ( notif . getPreset (), notif . getFeatureSetIndex ());
2020-10-10 20:08:11 +02:00
m_mainCore -> m_settings . sortFeatureSetPresets ();
m_mainCore -> m_settings . save ();
2017-11-25 16:47:13 +01:00
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgDeletePreset :: match ( cmd ))
2017-11-25 19:42:56 +01:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgDeletePreset & ) cmd ;
2017-11-25 19:42:56 +01:00
const Preset * presetToDelete = notif . getPreset ();
// remove preset from settings
2020-10-10 20:08:11 +02:00
m_mainCore -> m_settings . deletePreset ( presetToDelete );
2017-11-25 19:42:56 +01:00
return true ;
}
2022-05-08 19:33:10 +02:00
else if ( MainCore :: MsgLoadConfiguration :: match ( cmd ))
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgLoadConfiguration & ) cmd ;
2022-05-08 19:33:10 +02:00
const Configuration * configuration = notif . getConfiguration ();
loadConfiguration ( configuration , false );
return true ;
}
else if ( MainCore :: MsgSaveConfiguration :: match ( cmd ))
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgSaveConfiguration & ) cmd ;
2022-05-08 19:33:10 +02:00
Configuration * configuration = notif . getConfiguration ();
saveConfiguration ( configuration );
return true ;
}
else if ( MainCore :: MsgDeleteConfiguration :: match ( cmd ))
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgDeleteConfiguration & ) cmd ;
2022-05-08 19:33:10 +02:00
const Configuration * configurationToDelete = notif . getConfiguration ();
// remove configuration from settings
m_mainCore -> m_settings . deleteConfiguration ( configurationToDelete );
return true ;
}
2022-05-09 21:31:14 +02:00
else if ( MainCore :: MsgDeleteEmptyWorkspaces :: match ( cmd ))
{
removeEmptyWorkspaces ();
return true ;
}
else if ( MainCore :: MsgAddWorkspace :: match ( cmd ))
{
addWorkspace ();
return true ;
}
2021-09-04 05:58:06 +02:00
else if ( MainCore :: MsgDeleteFeatureSetPreset :: match ( cmd ))
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgDeleteFeatureSetPreset & ) cmd ;
2021-09-04 05:58:06 +02:00
const FeatureSetPreset * presetToDelete = notif . getPreset ();
// remove preset from settings
m_mainCore -> m_settings . deleteFeatureSetPreset ( presetToDelete );
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgAddDeviceSet :: match ( cmd ))
2017-11-25 22:52:24 +01:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgAddDeviceSet & ) cmd ;
2019-05-09 01:12:40 +02:00
int direction = notif . getDirection ();
2017-11-25 22:52:24 +01:00
2024-08-24 13:17:02 +02:00
if ( ! m_workspaces . empty ())
2022-05-16 20:51:15 +02:00
{
if ( direction == 1 ) { // Single stream Tx
sampleSinkAdd ( m_workspaces [ 0 ], m_workspaces [ 0 ], - 1 ); // create with file output device by default
} else if ( direction == 0 ) { // Single stream Rx
sampleSourceAdd ( m_workspaces [ 0 ], m_workspaces [ 0 ], - 1 ); // create with file input device by default
} else if ( direction == 2 ) { // MIMO
sampleMIMOAdd ( m_workspaces [ 0 ], m_workspaces [ 0 ], - 1 ); // create with testMI MIMO device by default
}
2019-05-18 11:59:56 +02:00
}
2017-11-25 22:52:24 +01:00
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgRemoveLastDeviceSet :: match ( cmd ))
2017-11-25 22:52:24 +01:00
{
2024-08-24 13:17:02 +02:00
if ( ! m_deviceUIs . empty ()) {
2022-04-15 10:04:24 +02:00
removeLastDeviceSet ();
2017-11-25 22:52:24 +01:00
}
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgSetDevice :: match ( cmd ))
2017-11-27 08:14:07 +01:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgSetDevice & ) cmd ;
2022-05-16 20:51:15 +02:00
int deviceSetIndex = notif . getDeviceSetIndex ();
2022-04-07 16:32:03 +02:00
2022-05-16 20:51:15 +02:00
if (( deviceSetIndex >= 0 ) && ( deviceSetIndex < ( int ) m_deviceUIs . size ()))
{
Workspace * workspace = m_workspaces [ m_deviceUIs [ deviceSetIndex ] -> m_deviceGUI -> getWorkspaceIndex ()];
sampleDeviceChange ( notif . getDeviceType (), notif . getDeviceSetIndex (), notif . getDeviceIndex (), workspace );
2021-08-21 20:09:57 +02:00
}
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgAddChannel :: match ( cmd ))
2017-12-11 01:18:10 +01:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgAddChannel & ) cmd ;
2022-05-16 20:51:15 +02:00
int deviceSetIndex = notif . getDeviceSetIndex ();
if (( deviceSetIndex >= 0 ) && ( deviceSetIndex < ( int ) m_deviceUIs . size ()))
{
2024-08-24 13:17:02 +02:00
const DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
2022-05-16 20:51:15 +02:00
int deviceWorkspaceIndex = deviceUISet -> m_deviceGUI -> getWorkspaceIndex ();
deviceWorkspaceIndex = deviceWorkspaceIndex < m_workspaces . size () ? deviceWorkspaceIndex : 0 ;
int channelRegistrationIndex ;
if ( deviceUISet -> m_deviceMIMOEngine )
{
int nbMIMOChannels = deviceUISet -> getNumberOfAvailableMIMOChannels ();
int nbRxChannels = deviceUISet -> getNumberOfAvailableRxChannels ();
int direction = notif . getDirection ();
if ( direction == 2 ) {
channelRegistrationIndex = notif . getChannelRegistrationIndex ();
} else if ( direction == 0 ) {
channelRegistrationIndex = nbMIMOChannels + notif . getChannelRegistrationIndex ();
} else {
channelRegistrationIndex = nbMIMOChannels + nbRxChannels + notif . getChannelRegistrationIndex ();
}
}
else
{
channelRegistrationIndex = notif . getChannelRegistrationIndex ();
}
channelAddClicked ( m_workspaces [ deviceWorkspaceIndex ], deviceSetIndex , channelRegistrationIndex );
}
2017-12-11 01:18:10 +01:00
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgDeleteChannel :: match ( cmd ))
2017-12-23 23:41:37 +01:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgDeleteChannel & ) cmd ;
2017-12-23 23:41:37 +01:00
deleteChannel ( notif . getDeviceSetIndex (), notif . getChannelIndex ());
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgAddFeature :: match ( cmd ))
2020-09-21 03:13:36 +02:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgAddFeature & ) cmd ;
2022-05-16 20:51:15 +02:00
2024-08-24 13:17:02 +02:00
if ( ! m_workspaces . empty ()) {
2022-05-16 20:51:15 +02:00
featureAddClicked ( m_workspaces [ 0 ], notif . getFeatureRegistrationIndex ());
}
2020-09-21 03:13:36 +02:00
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgDeleteFeature :: match ( cmd ))
2020-09-21 03:13:36 +02:00
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgDeleteFeature & ) cmd ;
2022-05-16 20:51:15 +02:00
deleteFeature ( 0 , notif . getFeatureIndex ());
2020-09-21 03:13:36 +02:00
return true ;
}
2022-05-13 22:24:48 +02:00
else if ( MainCore :: MsgMoveDeviceUIToWorkspace :: match ( cmd ))
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgMoveDeviceUIToWorkspace & ) cmd ;
2022-05-13 22:24:48 +02:00
int deviceSetIndex = notif . getDeviceSetIndex ();
if ( deviceSetIndex < ( int ) m_deviceUIs . size ())
{
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
DeviceGUI * gui = deviceUISet -> m_deviceGUI ;
deviceMove ( gui , notif . getWorkspaceIndex ());
}
return true ;
}
else if ( MainCore :: MsgMoveMainSpectrumUIToWorkspace :: match ( cmd ))
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgMoveMainSpectrumUIToWorkspace & ) cmd ;
2022-05-13 22:24:48 +02:00
int deviceSetIndex = notif . getDeviceSetIndex ();
if ( deviceSetIndex < ( int ) m_deviceUIs . size ())
{
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
MainSpectrumGUI * gui = deviceUISet -> m_mainSpectrumGUI ;
mainSpectrumMove ( gui , notif . getWorkspaceIndex ());
}
return true ;
}
else if ( MainCore :: MsgMoveFeatureUIToWorkspace :: match ( cmd ))
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgMoveFeatureUIToWorkspace & ) cmd ;
2022-05-13 22:24:48 +02:00
int featureIndex = notif . getFeatureIndex ();
2024-08-24 13:17:02 +02:00
if ( featureIndex < m_featureUIs [ 0 ] -> getNumberOfFeatures ())
2022-05-13 22:24:48 +02:00
{
FeatureGUI * gui = m_featureUIs [ 0 ] -> getFeatureGuiAt ( featureIndex );
featureMove ( gui , notif . getWorkspaceIndex ());
}
return true ;
}
else if ( MainCore :: MsgMoveChannelUIToWorkspace :: match ( cmd ))
{
2024-08-24 13:17:02 +02:00
auto & notif = ( const MainCore :: MsgMoveChannelUIToWorkspace & ) cmd ;
2022-05-13 22:24:48 +02:00
int deviceSetIndex = notif . getDeviceSetIndex ();
if ( deviceSetIndex < ( int ) m_deviceUIs . size ())
{
int channelIndex = notif . getChannelIndex ();
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
if ( channelIndex < deviceUISet -> getNumberOfChannels ())
{
ChannelGUI * gui = deviceUISet -> getChannelGUIAt ( channelIndex );
channelMove ( gui , notif . getWorkspaceIndex ());
}
}
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgApplySettings :: match ( cmd ))
2019-08-11 01:27:19 +02:00
{
applySettings ();
return true ;
}
2020-10-10 20:08:11 +02:00
else if ( MainCore :: MsgDVSerial :: match ( cmd ))
{
return true ;
}
2017-11-25 16:08:18 +01:00
return false ;
}
2017-10-22 19:12:43 +02:00
void MainWindow :: handleMessages ()
{
Message * message ;
2024-08-24 13:17:02 +02:00
while (( message = m_inputMessageQueue . pop ()) != nullptr )
2017-10-22 19:12:43 +02:00
{
qDebug ( "MainWindow::handleMessages: message: %s" , message -> getIdentifier ());
2017-11-25 16:08:18 +01:00
handleMessage ( * message );
2017-10-22 19:12:43 +02:00
delete message ;
}
}
2022-04-04 10:23:52 +02:00
void MainWindow :: handleWorkspaceVisibility ( Workspace * workspace , bool visibility )
2017-10-22 19:12:43 +02:00
{
2022-04-04 10:23:52 +02:00
qDebug ( "MainWindow::handleWorkspaceHasFocus: index: %d %s" ,
workspace -> getIndex (), visibility ? "visible" : "non visible" );
m_currentWorkspace = workspace ;
2017-10-22 19:12:43 +02:00
}
2022-04-04 10:23:52 +02:00
void MainWindow :: addWorkspace ()
2018-01-04 11:11:53 +01:00
{
2022-04-04 10:23:52 +02:00
int workspaceIndex = m_workspaces . size ();
2024-08-24 13:17:02 +02:00
auto * workspace = new Workspace ( workspaceIndex );
2022-12-20 21:06:39 +00:00
m_workspaces . push_back ( workspace );
if ( workspace -> getMenuButton ()) {
createMenuBar ( workspace -> getMenuButton ());
}
2022-04-04 10:23:52 +02:00
QStringList featureNames ;
m_pluginManager -> listFeatures ( featureNames );
m_workspaces . back () -> addAvailableFeatures ( featureNames );
this -> addDockWidget ( Qt :: LeftDockWidgetArea , m_workspaces . back ());
2018-01-04 11:11:53 +01:00
2022-04-07 16:32:03 +02:00
QObject :: connect (
m_workspaces . back (),
& Workspace :: addRxDevice ,
this ,
2024-08-24 13:17:02 +02:00
[ this ]( Workspace * inWorkspace , int deviceIndex ) { this -> sampleSourceAdd ( inWorkspace , inWorkspace , deviceIndex ); }
2022-04-07 16:32:03 +02:00
);
QObject :: connect (
m_workspaces . back (),
& Workspace :: addTxDevice ,
this ,
2024-08-24 13:17:02 +02:00
[ this ]( Workspace * inWorkspace , int deviceIndex ) { this -> sampleSinkAdd ( inWorkspace , inWorkspace , deviceIndex ); }
2022-04-07 16:32:03 +02:00
);
QObject :: connect (
m_workspaces . back (),
& Workspace :: addMIMODevice ,
this ,
2024-08-24 13:17:02 +02:00
[ this ]( Workspace * inWorkspace , int deviceIndex ) { this -> sampleMIMOAdd ( inWorkspace , inWorkspace , deviceIndex ); }
2022-04-07 16:32:03 +02:00
);
2022-04-04 10:23:52 +02:00
QObject :: connect (
m_workspaces . back (),
& Workspace :: addFeature ,
this ,
& MainWindow :: featureAddClicked
);
2018-01-04 11:11:53 +01:00
2022-04-04 10:23:52 +02:00
QObject :: connect (
m_workspaces . back (),
& Workspace :: featurePresetsDialogRequested ,
this ,
& MainWindow :: openFeaturePresetsDialog
);
2018-01-04 11:11:53 +01:00
2022-12-20 21:06:39 +00:00
QObject :: connect (
m_workspaces . back (),
& Workspace :: configurationPresetsDialogRequested ,
this ,
& MainWindow :: on_action_Configurations_triggered
);
2022-08-27 10:18:17 +01:00
QObject :: connect (
m_workspaces . back (),
& Workspace :: startAllDevices ,
this ,
& MainWindow :: startAllDevices
);
QObject :: connect (
m_workspaces . back (),
& Workspace :: stopAllDevices ,
this ,
& MainWindow :: stopAllDevices
);
2022-04-04 10:23:52 +02:00
if ( m_workspaces . size () > 1 )
2018-01-04 11:11:53 +01:00
{
2022-04-04 10:23:52 +02:00
for ( int i = 1 ; i < m_workspaces . size (); i ++ ) {
tabifyDockWidget ( m_workspaces [ 0 ], m_workspaces [ i ]);
2018-01-04 11:11:53 +01:00
}
2022-04-04 10:23:52 +02:00
m_workspaces . back () -> show ();
m_workspaces . back () -> raise ();
2018-01-04 11:11:53 +01:00
}
2022-12-20 21:06:39 +00:00
}
2018-01-04 11:11:53 +01:00
2024-08-24 13:17:02 +02:00
void MainWindow :: viewAllWorkspaces () const
2018-01-04 11:11:53 +01:00
{
2022-04-04 10:23:52 +02:00
for ( const auto & workspace : m_workspaces )
2018-01-04 11:11:53 +01:00
{
2022-04-04 10:23:52 +02:00
if ( workspace -> isHidden ()) {
workspace -> show ();
2018-01-05 11:45:20 +01:00
}
}
2022-04-04 10:23:52 +02:00
}
2018-01-04 11:11:53 +01:00
2022-04-05 16:26:57 +02:00
void MainWindow :: removeEmptyWorkspaces ()
{
2024-08-24 13:17:02 +02:00
auto it = m_workspaces . begin ();
2022-04-05 16:26:57 +02:00
while ( it != m_workspaces . end ())
{
if (( * it ) -> getNumberOfSubWindows () == 0 )
{
removeDockWidget ( * it );
it = m_workspaces . erase ( it );
}
else
{
++ it ;
}
}
2022-04-25 23:48:14 +02:00
// Renumerate
for ( int i = 0 ; i < m_workspaces . size (); i ++ )
{
Workspace * workspace = m_workspaces [ i ];
workspace -> setIndex ( i );
QList < QMdiSubWindow *> subWindows = workspace -> getSubWindowList ();
for ( auto & subWindow : subWindows )
{
if ( qobject_cast < DeviceGUI *> ( subWindow )) {
qobject_cast < DeviceGUI *> ( subWindow ) -> setWorkspaceIndex ( i );
}
if ( qobject_cast < MainSpectrumGUI *> ( subWindow )) {
qobject_cast < MainSpectrumGUI *> ( subWindow ) -> setWorkspaceIndex ( i );
}
if ( qobject_cast < ChannelGUI *> ( subWindow )) {
qobject_cast < ChannelGUI *> ( subWindow ) -> setWorkspaceIndex ( i );
}
if ( qobject_cast < FeatureGUI *> ( subWindow )) {
qobject_cast < FeatureGUI *> ( subWindow ) -> setWorkspaceIndex ( i );
}
}
}
2022-12-20 21:06:39 +00:00
#ifdef ANDROID
// Need at least one workspace on Android, as no menus without
if ( m_workspaces . size () == 0 ) {
addWorkspace ();
}
#endif
2022-04-05 16:26:57 +02:00
}
2023-02-17 21:57:09 +00:00
#ifdef ANDROID
void MainWindow :: on_action_View_KeepScreenOn_toggled ( bool checked )
{
if ( checked ) {
Android :: acquireScreenLock ();
} else {
Android :: releaseScreenLock ();
}
}
#endif
2022-04-04 10:23:52 +02:00
void MainWindow :: on_action_View_Fullscreen_toggled ( bool checked )
{
if ( checked ) {
showFullScreen ();
} else {
showNormal ();
}
}
2018-01-04 11:11:53 +01:00
2023-08-13 23:52:57 +01:00
void MainWindow :: on_action_Profile_triggered ()
{
if ( m_profileDialog == nullptr )
{
m_profileDialog = new ProfileDialog ();
new DialogPositioner ( m_profileDialog , true );
}
m_profileDialog -> show ();
m_profileDialog -> raise ();
}
2024-08-24 13:17:02 +02:00
void MainWindow :: commandKeysConnect ( const QObject * object , const char * slot )
2019-07-29 18:54:50 +02:00
{
setFocus ();
2022-04-04 16:13:42 +02:00
connect (
m_commandKeyReceiver ,
SIGNAL ( capturedKey ( Qt :: Key , Qt :: KeyboardModifiers , bool )),
object ,
slot
);
2019-07-29 18:54:50 +02:00
}
2024-08-24 13:17:02 +02:00
void MainWindow :: commandKeysDisconnect ( const QObject * object , const char * slot ) const
2019-07-29 18:54:50 +02:00
{
2022-04-04 16:13:42 +02:00
disconnect (
m_commandKeyReceiver ,
SIGNAL ( capturedKey ( Qt :: Key , Qt :: KeyboardModifiers , bool )),
object ,
slot
);
2018-01-05 05:05:12 +01:00
}
2022-04-05 16:26:57 +02:00
void MainWindow :: on_action_saveAll_triggered ()
2017-10-22 19:12:43 +02:00
{
2022-04-05 16:26:57 +02:00
saveConfiguration ( m_mainCore -> m_settings . getWorkingConfiguration ());
2020-10-10 20:08:11 +02:00
m_mainCore -> m_settings . save ();
2022-10-27 21:52:57 -05:00
QMessageBox :: information ( this , tr ( "Done" ), tr ( "All current settings saved" ));
2017-10-22 19:12:43 +02:00
}
2024-10-10 13:57:11 +01:00
void MainWindow :: on_action_Welcome_triggered ()
{
// Show welcome dialog
WelcomeDialog welcomeDialog ( this );
new DialogPositioner ( & welcomeDialog , true );
welcomeDialog . exec ();
}
2024-08-24 13:17:02 +02:00
void MainWindow :: on_action_Quick_Start_triggered () const
2021-11-24 11:31:51 +00:00
{
2022-05-15 11:11:56 +02:00
QDesktopServices :: openUrl ( QUrl ( "https://github.com/f4exb/sdrangel/wiki/Quick-start" ));
2021-11-24 11:31:51 +00:00
}
2024-08-24 13:17:02 +02:00
void MainWindow :: on_action_Main_Window_triggered () const
2021-11-24 11:31:51 +00:00
{
2022-05-15 11:11:56 +02:00
QDesktopServices :: openUrl ( QUrl ( "https://github.com/f4exb/sdrangel/blob/master/sdrgui/readme.md" ));
2021-11-24 11:31:51 +00:00
}
2017-10-22 19:12:43 +02:00
void MainWindow :: on_action_Loaded_Plugins_triggered ()
{
PluginsDialog pluginsDialog ( m_pluginManager , this );
pluginsDialog . exec ();
}
2022-04-05 16:26:57 +02:00
void MainWindow :: on_action_Configurations_triggered ()
{
2022-12-20 21:06:39 +00:00
openConfigurationDialog ( false );
}
void MainWindow :: openConfigurationDialog ( bool openOnly )
{
ConfigurationsDialog dialog ( openOnly , this );
2022-04-05 16:26:57 +02:00
dialog . setConfigurations ( m_mainCore -> m_settings . getConfigurations ());
dialog . populateTree ();
QObject :: connect (
& dialog ,
& ConfigurationsDialog :: saveConfiguration ,
this ,
& MainWindow :: saveConfiguration
);
QObject :: connect (
& dialog ,
& ConfigurationsDialog :: loadConfiguration ,
this ,
2024-08-24 13:17:02 +02:00
[ this ]( const Configuration * configuration ) { this -> loadConfiguration ( configuration , true ); }
2022-04-05 16:26:57 +02:00
);
2022-12-20 21:06:39 +00:00
new DialogPositioner ( & dialog , true );
2022-04-05 16:26:57 +02:00
dialog . exec ();
}
2017-10-22 19:12:43 +02:00
void MainWindow :: on_action_Audio_triggered ()
{
2018-03-25 13:36:09 +02:00
AudioDialogX audioDialog ( m_dspEngine -> getAudioDeviceManager (), this );
2022-12-20 21:06:39 +00:00
new DialogPositioner ( & audioDialog , true );
2017-10-22 19:12:43 +02:00
audioDialog . exec ();
}
2022-06-18 12:35:44 +01:00
void MainWindow :: on_action_Graphics_triggered ()
{
GraphicsDialog graphicsDialog ( m_mainCore -> m_settings , this );
2022-12-20 21:06:39 +00:00
new DialogPositioner ( & graphicsDialog , true );
2022-06-18 12:35:44 +01:00
graphicsDialog . exec ();
}
2017-11-11 19:26:23 +01:00
void MainWindow :: on_action_Logging_triggered ()
{
2020-10-10 20:08:11 +02:00
LoggingDialog loggingDialog ( m_mainCore -> m_settings , this );
2022-12-20 21:06:39 +00:00
new DialogPositioner ( & loggingDialog , true );
2017-11-11 19:26:23 +01:00
loggingDialog . exec ();
2020-10-10 20:08:11 +02:00
m_mainCore -> setLoggingOptions ();
2017-11-11 19:26:23 +01:00
}
2017-10-22 19:12:43 +02:00
void MainWindow :: on_action_My_Position_triggered ()
{
2020-10-10 20:08:11 +02:00
MyPositionDialog myPositionDialog ( m_mainCore -> m_settings , this );
2022-12-20 21:06:39 +00:00
new DialogPositioner ( & myPositionDialog , true );
2017-10-22 19:12:43 +02:00
myPositionDialog . exec ();
}
2019-06-12 18:50:53 +02:00
void MainWindow :: on_action_DeviceUserArguments_triggered ()
{
qDebug ( "MainWindow::on_action_DeviceUserArguments_triggered" );
2020-10-10 20:08:11 +02:00
DeviceUserArgsDialog deviceUserArgsDialog ( DeviceEnumerator :: instance (), m_mainCore -> m_settings . getDeviceUserArgs (), this );
2022-12-20 21:06:39 +00:00
new DialogPositioner ( & deviceUserArgsDialog , true );
2019-06-12 18:50:53 +02:00
deviceUserArgsDialog . exec ();
}
2024-10-10 13:57:11 +01:00
#if QT_CONFIG(process)
2022-04-04 16:13:42 +02:00
void MainWindow :: on_action_commands_triggered ()
{
qDebug ( "MainWindow::on_action_commands_triggered" );
CommandsDialog commandsDialog ( this );
commandsDialog . setApiHost ( m_apiServer -> getHost ());
commandsDialog . setApiPort ( m_apiServer -> getPort ());
commandsDialog . setCommandKeyReceiver ( m_commandKeyReceiver );
commandsDialog . populateTree ();
2022-12-20 21:06:39 +00:00
new DialogPositioner ( & commandsDialog , true );
2022-04-04 16:13:42 +02:00
commandsDialog . exec ();
}
2024-10-10 13:57:11 +01:00
#endif
2022-04-04 16:13:42 +02:00
2021-11-02 01:04:43 +01:00
void MainWindow :: on_action_FFT_triggered ()
{
qDebug ( "MainWindow::on_action_FFT_triggered" );
2023-08-13 23:52:57 +01:00
FFTDialog fftDialog ( m_mainCore -> m_settings , this );
new DialogPositioner ( & fftDialog , true );
fftDialog . exec ();
}
2024-10-10 13:57:11 +01:00
#if QT_CONFIG(process)
2023-08-13 23:52:57 +01:00
void MainWindow :: on_action_FFTWisdom_triggered ()
{
qDebug ( "MainWindow::on_action_FFTWisdom_triggered" );
2021-11-02 07:57:10 +01:00
if ( m_fftWisdomProcess )
{
QMessageBox :: information ( this , "FFTW Wisdom" , QString ( "Process %1 is already running" ). arg ( m_fftWisdomProcess -> processId ()));
return ;
}
2021-11-02 01:04:43 +01:00
m_fftWisdomProcess = new QProcess ( this );
connect ( m_fftWisdomProcess ,
SIGNAL ( finished ( int , QProcess :: ExitStatus )),
this ,
SLOT ( fftWisdomProcessFinished ( int , QProcess :: ExitStatus )));
FFTWisdomDialog fftWisdomDialog ( m_fftWisdomProcess , this );
2022-12-20 21:06:39 +00:00
new DialogPositioner ( & fftWisdomDialog , true );
2021-11-02 01:04:43 +01:00
if ( fftWisdomDialog . exec () == QDialog :: Rejected )
{
disconnect ( m_fftWisdomProcess ,
SIGNAL ( finished ( int , QProcess :: ExitStatus )),
this ,
SLOT ( fftWisdomProcessFinished ( int , QProcess :: ExitStatus )));
delete m_fftWisdomProcess ;
2021-11-02 07:57:10 +01:00
m_fftWisdomProcess = nullptr ;
2021-11-02 01:04:43 +01:00
}
else
{
QMessageBox :: information ( this , "FFTW Wisdom" , QString ( "Process %1 started" ). arg ( m_fftWisdomProcess -> processId ()));
}
}
void MainWindow :: fftWisdomProcessFinished ( int exitCode , QProcess :: ExitStatus exitStatus )
{
qDebug ( "MainWindow::fftWisdomProcessFinished: process finished rc=%d (%d)" , exitCode , ( int ) exitStatus );
if (( exitCode != 0 ) || ( exitStatus != QProcess :: NormalExit ))
{
QMessageBox :: critical ( this , "FFTW Wisdom" , "fftwf-widdsom program failed" );
}
else
{
QString log = m_fftWisdomProcess -> readAllStandardOutput ();
QMessageBox :: information ( this , "FFTW Wisdom" , QString ( "Success \n %1" ). arg ( log ));
}
delete m_fftWisdomProcess ;
2021-11-04 19:19:17 +01:00
m_fftWisdomProcess = nullptr ;
2021-11-02 01:04:43 +01:00
}
2024-10-10 14:36:06 +01:00
#endif
2021-11-02 01:04:43 +01:00
2024-08-24 13:17:02 +02:00
void MainWindow :: samplingDeviceChangeHandler ( const DeviceGUI * deviceGUI , int newDeviceIndex )
2020-09-13 17:50:24 +02:00
{
2024-08-24 13:17:02 +02:00
auto deviceType = ( int ) deviceGUI -> getDeviceType ();
2022-04-07 16:32:03 +02:00
int deviceSetIndex = deviceGUI -> getIndex ();
Workspace * workspace = m_workspaces [ deviceGUI -> getWorkspaceIndex ()];
sampleDeviceChange ( deviceType , deviceSetIndex , newDeviceIndex , workspace );
}
2020-09-13 17:50:24 +02:00
2022-04-07 16:32:03 +02:00
void MainWindow :: sampleDeviceChange ( int deviceType , int deviceSetIndex , int newDeviceIndex , Workspace * workspace )
{
qDebug ( "MainWindow::sampleDeviceChange: deviceType: %d deviceSetIndex: %d newDeviceIndex: %d" ,
deviceType , deviceSetIndex , newDeviceIndex );
2020-09-13 17:50:24 +02:00
if ( deviceType == 0 ) {
2022-04-07 16:32:03 +02:00
sampleSourceChange ( deviceSetIndex , newDeviceIndex , workspace );
2020-09-13 17:50:24 +02:00
} else if ( deviceType == 1 ) {
2022-04-07 16:32:03 +02:00
sampleSinkChange ( deviceSetIndex , newDeviceIndex , workspace );
2020-11-10 12:08:58 +01:00
} else if ( deviceType == 2 ) {
2022-04-07 16:32:03 +02:00
sampleMIMOChange ( deviceSetIndex , newDeviceIndex , workspace );
2020-09-13 17:50:24 +02:00
}
2022-03-12 05:45:24 +01:00
2022-04-07 16:32:03 +02:00
emit MainCore :: instance () -> deviceChanged ( deviceSetIndex );
2020-09-13 17:50:24 +02:00
}
2022-04-07 16:32:03 +02:00
void MainWindow :: sampleSourceChange ( int deviceSetIndex , int newDeviceIndex , Workspace * workspace )
2020-09-13 17:50:24 +02:00
{
2022-04-07 16:32:03 +02:00
if ( deviceSetIndex >= 0 )
2020-09-13 17:50:24 +02:00
{
2022-04-07 16:32:03 +02:00
qDebug ( "MainWindow::sampleSourceChange: deviceSet %d workspace: %d" , deviceSetIndex , workspace -> getIndex ());
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
2022-04-30 11:47:05 +02:00
QPoint p = deviceUISet -> m_deviceGUI -> pos ();
2022-04-14 20:41:32 +02:00
workspace -> removeFromMdiArea ( deviceUISet -> m_deviceGUI );
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> stopDeviceEngine ();
2020-09-13 17:50:24 +02:00
// deletes old UI and input object
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> getSampleSource () -> setMessageQueueToGUI ( nullptr ); // have source stop sending messages to the GUI
2022-04-14 20:41:32 +02:00
2024-09-07 21:50:42 +02:00
delete deviceUISet -> m_deviceGUI ;
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> resetSamplingDeviceId ();
deviceUISet -> m_deviceAPI -> getPluginInterface () -> deleteSampleSourcePluginInstanceInput ( deviceUISet -> m_deviceAPI -> getSampleSource ());
deviceUISet -> m_deviceAPI -> clearBuddiesLists (); // clear old API buddies lists
2020-09-13 17:50:24 +02:00
2022-04-14 20:41:32 +02:00
sampleSourceCreate ( deviceSetIndex , newDeviceIndex , deviceUISet );
2024-10-10 13:57:11 +01:00
sampleSourceCreateUI ( deviceSetIndex , newDeviceIndex , deviceUISet );
2022-04-09 13:38:22 +02:00
deviceUISet -> m_deviceGUI -> setWorkspaceIndex ( workspace -> getIndex ());
workspace -> addToMdiArea ( deviceUISet -> m_deviceGUI );
2022-04-30 11:47:05 +02:00
deviceUISet -> m_deviceGUI -> move ( p );
2022-04-12 16:20:45 +02:00
QObject :: connect (
deviceUISet -> m_deviceGUI ,
& DeviceGUI :: addChannelEmitted ,
this ,
2024-08-24 13:17:02 +02:00
[ this , workspace , deviceSetIndex ]( int channelPluginIndex ){ this -> channelAddClicked ( workspace , deviceSetIndex , channelPluginIndex ); }
2022-04-12 16:20:45 +02:00
);
2020-09-13 17:50:24 +02:00
}
}
2022-04-07 16:32:03 +02:00
void MainWindow :: sampleSinkChange ( int deviceSetIndex , int newDeviceIndex , Workspace * workspace )
2020-09-13 17:50:24 +02:00
{
2022-04-07 16:32:03 +02:00
if ( deviceSetIndex >= 0 )
2020-09-13 17:50:24 +02:00
{
2022-04-07 16:32:03 +02:00
qDebug ( "MainWindow::sampleSinkChange: deviceSet %d workspace: %d" , deviceSetIndex , workspace -> getIndex ());
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
2022-04-30 11:47:05 +02:00
QPoint p = deviceUISet -> m_deviceGUI -> pos ();
workspace -> removeFromMdiArea ( deviceUISet -> m_deviceGUI );
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> saveSamplingDeviceSettings ( m_mainCore -> m_settings . getWorkingPreset ()); // save old API settings
deviceUISet -> m_deviceAPI -> stopDeviceEngine ();
2020-09-13 17:50:24 +02:00
// deletes old UI and output object
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> getSampleSink () -> setMessageQueueToGUI ( nullptr ); // have sink stop sending messages to the GUI
2024-09-07 21:50:42 +02:00
delete m_deviceUIs [ deviceSetIndex ] -> m_deviceGUI ;
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> resetSamplingDeviceId ();
deviceUISet -> m_deviceAPI -> getPluginInterface () -> deleteSampleSinkPluginInstanceOutput ( deviceUISet -> m_deviceAPI -> getSampleSink ());
deviceUISet -> m_deviceAPI -> clearBuddiesLists (); // clear old API buddies lists
2020-09-13 17:50:24 +02:00
2022-04-14 20:41:32 +02:00
sampleSinkCreate ( deviceSetIndex , newDeviceIndex , deviceUISet );
2024-10-10 13:57:11 +01:00
sampleSinkCreateUI ( deviceSetIndex , newDeviceIndex , deviceUISet );
2022-04-09 13:38:22 +02:00
deviceUISet -> m_deviceGUI -> setWorkspaceIndex ( workspace -> getIndex ());
workspace -> addToMdiArea ( deviceUISet -> m_deviceGUI );
2022-04-30 11:47:05 +02:00
deviceUISet -> m_deviceGUI -> move ( p );
2022-04-12 16:20:45 +02:00
QObject :: connect (
deviceUISet -> m_deviceGUI ,
& DeviceGUI :: addChannelEmitted ,
this ,
2024-08-24 13:17:02 +02:00
[ this , workspace , deviceSetIndex ]( int channelPluginIndex ){ this -> channelAddClicked ( workspace , deviceSetIndex , channelPluginIndex ); }
2022-04-12 16:20:45 +02:00
);
2020-09-13 17:50:24 +02:00
}
}
2022-04-07 16:32:03 +02:00
void MainWindow :: sampleMIMOChange ( int deviceSetIndex , int newDeviceIndex , Workspace * workspace )
2020-11-10 12:08:58 +01:00
{
2022-04-07 16:32:03 +02:00
if ( deviceSetIndex >= 0 )
2020-11-10 12:08:58 +01:00
{
2022-04-07 16:32:03 +02:00
qDebug ( "MainWindow::sampleSinkChange: deviceSet %d workspace: %d" , deviceSetIndex , workspace -> getIndex ());
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
2022-04-30 11:47:05 +02:00
QPoint p = deviceUISet -> m_deviceGUI -> pos ();
workspace -> removeFromMdiArea ( deviceUISet -> m_deviceGUI );
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> saveSamplingDeviceSettings ( m_mainCore -> m_settings . getWorkingPreset ()); // save old API settings
deviceUISet -> m_deviceAPI -> stopDeviceEngine ();
2020-11-10 12:08:58 +01:00
// deletes old UI and output object
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> getSampleMIMO () -> setMessageQueueToGUI ( nullptr ); // have sink stop sending messages to the GUI
2024-09-07 21:50:42 +02:00
delete deviceUISet -> m_deviceGUI ;
2022-04-07 16:32:03 +02:00
deviceUISet -> m_deviceAPI -> resetSamplingDeviceId ();
deviceUISet -> m_deviceAPI -> getPluginInterface () -> deleteSampleMIMOPluginInstanceMIMO ( deviceUISet -> m_deviceAPI -> getSampleMIMO ());
2020-11-10 12:08:58 +01:00
2022-04-14 20:41:32 +02:00
sampleMIMOCreate ( deviceSetIndex , newDeviceIndex , deviceUISet );
2024-10-10 13:57:11 +01:00
sampleMIMOCreateUI ( deviceSetIndex , newDeviceIndex , deviceUISet );
2022-04-09 13:38:22 +02:00
deviceUISet -> m_deviceGUI -> setWorkspaceIndex ( workspace -> getIndex ());
workspace -> addToMdiArea ( deviceUISet -> m_deviceGUI );
2022-04-30 11:47:05 +02:00
deviceUISet -> m_deviceGUI -> move ( p );
2022-04-12 16:20:45 +02:00
QObject :: connect (
deviceUISet -> m_deviceGUI ,
& DeviceGUI :: addChannelEmitted ,
this ,
2024-08-24 13:17:02 +02:00
[ this , workspace , deviceSetIndex ]( int channelPluginIndex ){ this -> channelAddClicked ( workspace , deviceSetIndex , channelPluginIndex ); }
2022-04-12 16:20:45 +02:00
);
2020-11-10 12:08:58 +01:00
}
}
2022-04-16 16:45:53 +02:00
void MainWindow :: channelMoveToDeviceSet ( ChannelGUI * gui , int dsIndexDestination )
{
int deviceSetIndex = gui -> getDeviceSetIndex ();
int channelIndex = gui -> getIndex ();
qDebug ( "MainWindow::channelMoveToDeviceSet: %s at %d:%d to %d" ,
qPrintable ( gui -> getTitle ()), deviceSetIndex , channelIndex , dsIndexDestination );
if (( deviceSetIndex < ( int ) m_deviceUIs . size ()) && ( dsIndexDestination < ( int ) m_deviceUIs . size ()))
{
DeviceUISet * deviceUI = m_deviceUIs [ deviceSetIndex ];
DeviceUISet * destDeviceUI = m_deviceUIs [ dsIndexDestination ];
ChannelAPI * channelAPI = deviceUI -> getChannelAt ( channelIndex );
deviceUI -> unregisterChannelInstanceAt ( channelIndex );
if ( deviceUI -> m_deviceSourceEngine ) // source devices
{
destDeviceUI -> registerRxChannelInstance ( channelAPI , gui );
}
else if ( deviceUI -> m_deviceSinkEngine ) // sink devices
{
destDeviceUI -> registerTxChannelInstance ( channelAPI , gui );
}
else if ( deviceUI -> m_deviceMIMOEngine ) // MIMO devices
{
destDeviceUI -> registerChannelInstance ( channelAPI , gui );
}
gui -> setIndex ( channelAPI -> getIndexInDeviceSet ());
gui -> setDeviceSetIndex ( dsIndexDestination );
DeviceAPI * destDeviceAPI = destDeviceUI -> m_deviceAPI ;
2022-04-18 12:08:33 +02:00
gui -> setIndexToolTip ( destDeviceAPI -> getSamplingDeviceDisplayName ());
2022-04-16 16:45:53 +02:00
channelAPI -> setDeviceAPI ( destDeviceAPI );
deviceUI -> removeChannelMarker ( & gui -> getChannelMarker ());
destDeviceUI -> addChannelMarker ( & gui -> getChannelMarker ());
}
}
2024-08-24 13:17:02 +02:00
void MainWindow :: channelDuplicate ( const ChannelGUI * sourceChannelGUI )
2017-10-22 19:12:43 +02:00
{
2022-04-16 16:45:53 +02:00
channelDuplicateToDeviceSet ( sourceChannelGUI , sourceChannelGUI -> getDeviceSetIndex ()); // Duplicate in same device set
}
2022-04-15 18:59:29 +02:00
2024-08-24 13:17:02 +02:00
void MainWindow :: channelDuplicateToDeviceSet ( const ChannelGUI * sourceChannelGUI , int dsIndexDestination )
2022-04-16 16:45:53 +02:00
{
int dsIndexSource = sourceChannelGUI -> getDeviceSetIndex ();
int sourceChannelIndex = sourceChannelGUI -> getIndex ();
2022-04-15 18:59:29 +02:00
2022-04-16 16:45:53 +02:00
qDebug ( "MainWindow::channelDuplicateToDeviceSet: %s at %d:%d to %d in workspace %d" ,
qPrintable ( sourceChannelGUI -> getTitle ()), dsIndexSource , sourceChannelIndex , dsIndexDestination , sourceChannelGUI -> getWorkspaceIndex ());
if (( dsIndexSource < ( int ) m_deviceUIs . size ()) && ( dsIndexDestination < ( int ) m_deviceUIs . size ()))
2022-04-15 18:59:29 +02:00
{
2022-04-16 16:45:53 +02:00
DeviceUISet * sourceDeviceUI = m_deviceUIs [ dsIndexSource ];
2024-08-24 13:17:02 +02:00
const ChannelAPI * sourceChannelAPI = sourceDeviceUI -> getChannelAt ( sourceChannelIndex );
2022-04-16 16:45:53 +02:00
ChannelGUI * destChannelGUI = nullptr ;
DeviceUISet * destDeviceUI = m_deviceUIs [ dsIndexDestination ];
2022-04-15 18:59:29 +02:00
2022-04-16 16:45:53 +02:00
if ( destDeviceUI -> m_deviceSourceEngine ) // source device => Rx channels
2022-04-15 18:59:29 +02:00
{
2024-08-24 13:17:02 +02:00
const PluginAPI :: ChannelRegistrations * channelRegistrations = m_pluginManager -> getRxChannelRegistrations ();
const PluginInterface * pluginInterface = nullptr ;
2022-04-15 18:59:29 +02:00
for ( const auto & channelRegistration : * channelRegistrations )
{
if ( channelRegistration . m_channelIdURI == sourceChannelAPI -> getURI ())
{
pluginInterface = channelRegistration . m_plugin ;
break ;
}
}
if ( pluginInterface )
{
2024-08-25 23:36:46 +02:00
ChannelAPI * channelAPI ;
2024-08-24 13:17:02 +02:00
BasebandSampleSink * rxChannel = nullptr ;
2022-04-16 16:45:53 +02:00
pluginInterface -> createRxChannel ( destDeviceUI -> m_deviceAPI , & rxChannel , & channelAPI );
destChannelGUI = pluginInterface -> createRxChannelGUI ( destDeviceUI , rxChannel );
destDeviceUI -> registerRxChannelInstance ( channelAPI , destChannelGUI );
2024-08-25 23:36:46 +02:00
destChannelGUI -> setDeviceType ( ChannelGUI :: DeviceType :: DeviceRx );
2022-04-16 16:45:53 +02:00
destChannelGUI -> setIndex ( channelAPI -> getIndexInDeviceSet ());
2022-04-15 18:59:29 +02:00
QByteArray b = sourceChannelGUI -> serialize ();
2022-04-16 16:45:53 +02:00
destChannelGUI -> deserialize ( b );
2022-04-15 18:59:29 +02:00
}
}
2022-04-16 16:45:53 +02:00
else if ( destDeviceUI -> m_deviceSinkEngine ) // sink device => Tx channels
2022-04-15 18:59:29 +02:00
{
2024-08-24 13:17:02 +02:00
const PluginAPI :: ChannelRegistrations * channelRegistrations = m_pluginManager -> getTxChannelRegistrations (); // Available channel plugins
const PluginInterface * pluginInterface = nullptr ;
2022-04-15 18:59:29 +02:00
for ( const auto & channelRegistration : * channelRegistrations )
{
if ( channelRegistration . m_channelIdURI == sourceChannelAPI -> getURI ())
{
pluginInterface = channelRegistration . m_plugin ;
break ;
}
}
if ( pluginInterface )
{
ChannelAPI * channelAPI ;
2024-08-24 13:17:02 +02:00
BasebandSampleSource * txChannel = nullptr ;
2022-04-16 16:45:53 +02:00
pluginInterface -> createTxChannel ( destDeviceUI -> m_deviceAPI , & txChannel , & channelAPI );
destChannelGUI = pluginInterface -> createTxChannelGUI ( destDeviceUI , txChannel );
destDeviceUI -> registerTxChannelInstance ( channelAPI , destChannelGUI );
2024-08-25 23:36:46 +02:00
destChannelGUI -> setDeviceType ( ChannelGUI :: DeviceType :: DeviceTx );
2022-04-16 16:45:53 +02:00
destChannelGUI -> setIndex ( channelAPI -> getIndexInDeviceSet ());
2022-04-15 18:59:29 +02:00
QByteArray b = sourceChannelGUI -> serialize ();
2022-04-16 16:45:53 +02:00
destChannelGUI -> deserialize ( b );
2022-04-15 18:59:29 +02:00
}
}
2022-04-16 16:45:53 +02:00
else if ( destDeviceUI -> m_deviceMIMOEngine ) // MIMO device => Any type of channel is possible
2022-04-15 18:59:29 +02:00
{
2024-08-24 13:17:02 +02:00
const PluginAPI :: ChannelRegistrations * rxChannelRegistrations = m_pluginManager -> getRxChannelRegistrations ();
const PluginAPI :: ChannelRegistrations * txChannelRegistrations = m_pluginManager -> getTxChannelRegistrations ();
const PluginAPI :: ChannelRegistrations * mimoChannelRegistrations = m_pluginManager -> getMIMOChannelRegistrations ();
const PluginInterface * pluginInterface = nullptr ;
2022-04-15 18:59:29 +02:00
for ( const auto & channelRegistration : * rxChannelRegistrations )
{
if ( channelRegistration . m_channelIdURI == sourceChannelAPI -> getURI ())
{
pluginInterface = channelRegistration . m_plugin ;
break ;
}
}
if ( pluginInterface ) // Rx channel
{
ChannelAPI * channelAPI ;
2024-08-24 13:17:02 +02:00
BasebandSampleSink * rxChannel = nullptr ;
2022-04-16 16:45:53 +02:00
pluginInterface -> createRxChannel ( destDeviceUI -> m_deviceAPI , & rxChannel , & channelAPI );
destChannelGUI = pluginInterface -> createRxChannelGUI ( destDeviceUI , rxChannel );
destDeviceUI -> registerRxChannelInstance ( channelAPI , destChannelGUI );
2024-08-25 23:36:46 +02:00
destChannelGUI -> setDeviceType ( ChannelGUI :: DeviceType :: DeviceMIMO );
2022-04-16 16:45:53 +02:00
destChannelGUI -> setIndex ( channelAPI -> getIndexInDeviceSet ());
2022-04-15 18:59:29 +02:00
QByteArray b = sourceChannelGUI -> serialize ();
2022-04-16 16:45:53 +02:00
destChannelGUI -> deserialize ( b );
2022-04-15 18:59:29 +02:00
}
else
{
for ( const auto & channelRegistration : * txChannelRegistrations )
{
if ( channelRegistration . m_channelIdURI == sourceChannelAPI -> getURI ())
{
pluginInterface = channelRegistration . m_plugin ;
break ;
}
}
if ( pluginInterface ) // Tx channel
{
ChannelAPI * channelAPI ;
2024-08-24 13:17:02 +02:00
BasebandSampleSource * txChannel = nullptr ;
2022-04-16 16:45:53 +02:00
pluginInterface -> createTxChannel ( destDeviceUI -> m_deviceAPI , & txChannel , & channelAPI );
destChannelGUI = pluginInterface -> createTxChannelGUI ( destDeviceUI , txChannel );
destDeviceUI -> registerTxChannelInstance ( channelAPI , destChannelGUI );
2024-08-25 23:36:46 +02:00
destChannelGUI -> setDeviceType ( ChannelGUI :: DeviceType :: DeviceMIMO );
2022-04-16 16:45:53 +02:00
destChannelGUI -> setIndex ( channelAPI -> getIndexInDeviceSet ());
2022-04-15 18:59:29 +02:00
QByteArray b = sourceChannelGUI -> serialize ();
2022-04-16 16:45:53 +02:00
destChannelGUI -> deserialize ( b );
2022-04-15 18:59:29 +02:00
}
else
{
for ( const auto & channelRegistration : * mimoChannelRegistrations )
{
if ( channelRegistration . m_channelIdURI == sourceChannelAPI -> getURI ())
{
pluginInterface = channelRegistration . m_plugin ;
break ;
}
}
if ( pluginInterface )
{
ChannelAPI * channelAPI ;
2024-08-24 13:17:02 +02:00
MIMOChannel * mimoChannel = nullptr ;
2022-04-16 16:45:53 +02:00
pluginInterface -> createMIMOChannel ( destDeviceUI -> m_deviceAPI , & mimoChannel , & channelAPI );
destChannelGUI = pluginInterface -> createMIMOChannelGUI ( destDeviceUI , mimoChannel );
destDeviceUI -> registerChannelInstance ( channelAPI , destChannelGUI );
2024-08-25 23:36:46 +02:00
destChannelGUI -> setDeviceType ( ChannelGUI :: DeviceType :: DeviceMIMO );
2022-04-16 16:45:53 +02:00
destChannelGUI -> setIndex ( channelAPI -> getIndexInDeviceSet ());
2022-04-15 18:59:29 +02:00
QByteArray b = sourceChannelGUI -> serialize ();
2022-04-16 16:45:53 +02:00
destChannelGUI -> deserialize ( b );
2022-04-15 18:59:29 +02:00
}
}
}
}
2024-08-24 13:17:02 +02:00
const DeviceAPI * destDeviceAPI = destDeviceUI -> m_deviceAPI ;
2022-04-15 18:59:29 +02:00
int workspaceIndex = sourceChannelGUI -> getWorkspaceIndex ();
Workspace * workspace = workspaceIndex < m_workspaces . size () ? m_workspaces [ sourceChannelGUI -> getWorkspaceIndex ()] : nullptr ;
2022-04-16 16:45:53 +02:00
if ( destChannelGUI && workspace )
2022-04-15 18:59:29 +02:00
{
QObject :: connect (
2022-04-16 16:45:53 +02:00
destChannelGUI ,
2022-04-15 18:59:29 +02:00
& ChannelGUI :: moveToWorkspace ,
this ,
2024-08-24 13:17:02 +02:00
[ this , destChannelGUI ]( int wsIndexDest ){ this -> channelMove ( destChannelGUI , wsIndexDest ); }
2022-04-15 18:59:29 +02:00
);
QObject :: connect (
2022-04-16 16:45:53 +02:00
destChannelGUI ,
2022-04-15 18:59:29 +02:00
& ChannelGUI :: duplicateChannelEmitted ,
this ,
2024-08-24 13:17:02 +02:00
[ this , destChannelGUI ](){ this -> channelDuplicate ( destChannelGUI ); }
2022-04-16 16:45:53 +02:00
);
QObject :: connect (
destChannelGUI ,
& ChannelGUI :: moveToDeviceSet ,
this ,
2024-08-24 13:17:02 +02:00
[ this , destChannelGUI ]( int dsIndexDest ){ this -> channelMoveToDeviceSet ( destChannelGUI , dsIndexDest ); }
2022-04-15 18:59:29 +02:00
);
2022-04-16 16:45:53 +02:00
destChannelGUI -> setDeviceSetIndex ( dsIndexDestination );
2022-04-18 12:08:33 +02:00
destChannelGUI -> setIndexToolTip ( destDeviceAPI -> getSamplingDeviceDisplayName ());
2022-04-16 16:45:53 +02:00
destChannelGUI -> setWorkspaceIndex ( workspace -> getIndex ());
2022-04-15 18:59:29 +02:00
qDebug ( "MainWindow::channelDuplicate: adding %s to workspace #%d" ,
2022-04-16 16:45:53 +02:00
qPrintable ( destChannelGUI -> getTitle ()), workspace -> getIndex ());
workspace -> addToMdiArea (( QMdiSubWindow * ) destChannelGUI );
2022-04-15 18:59:29 +02:00
}
}
}
void MainWindow :: channelAddClicked ( Workspace * workspace , int deviceSetIndex , int channelPluginIndex )
{
if ( deviceSetIndex < ( int ) m_deviceUIs . size ())
2022-04-12 16:20:45 +02:00
{
DeviceUISet * deviceUI = m_deviceUIs [ deviceSetIndex ];
2024-08-24 13:17:02 +02:00
ChannelGUI * gui ;
2023-08-24 15:51:50 +01:00
ChannelAPI * channelAPI ;
2024-08-24 13:17:02 +02:00
const DeviceAPI * deviceAPI = deviceUI -> m_deviceAPI ;
2022-04-04 10:23:52 +02:00
2022-04-12 16:20:45 +02:00
if ( deviceUI -> m_deviceSourceEngine ) // source device => Rx channels
{
PluginAPI :: ChannelRegistrations * channelRegistrations = m_pluginManager -> getRxChannelRegistrations (); // Available channel plugins
2024-08-24 13:17:02 +02:00
const PluginInterface * pluginInterface = ( * channelRegistrations )[ channelPluginIndex ]. m_plugin ;
BasebandSampleSink * rxChannel = nullptr ;
2022-04-12 16:20:45 +02:00
pluginInterface -> createRxChannel ( deviceUI -> m_deviceAPI , & rxChannel , & channelAPI );
gui = pluginInterface -> createRxChannelGUI ( deviceUI , rxChannel );
deviceUI -> registerRxChannelInstance ( channelAPI , gui );
2024-08-25 23:36:46 +02:00
gui -> setDeviceType ( ChannelGUI :: DeviceType :: DeviceRx );
2022-04-12 16:20:45 +02:00
gui -> setIndex ( channelAPI -> getIndexInDeviceSet ());
2022-04-17 10:20:07 +02:00
gui -> setDisplayedame ( pluginInterface -> getPluginDescriptor (). displayedName );
2022-04-12 16:20:45 +02:00
}
else if ( deviceUI -> m_deviceSinkEngine ) // sink device => Tx channels
{
PluginAPI :: ChannelRegistrations * channelRegistrations = m_pluginManager -> getTxChannelRegistrations (); // Available channel plugins
2024-08-24 13:17:02 +02:00
const PluginInterface * pluginInterface = ( * channelRegistrations )[ channelPluginIndex ]. m_plugin ;
BasebandSampleSource * txChannel = nullptr ;
2022-04-12 16:20:45 +02:00
pluginInterface -> createTxChannel ( deviceUI -> m_deviceAPI , & txChannel , & channelAPI );
gui = pluginInterface -> createTxChannelGUI ( deviceUI , txChannel );
deviceUI -> registerTxChannelInstance ( channelAPI , gui );
2024-08-25 23:36:46 +02:00
gui -> setDeviceType ( ChannelGUI :: DeviceType :: DeviceTx );
2022-04-12 16:20:45 +02:00
gui -> setIndex ( channelAPI -> getIndexInDeviceSet ());
2022-04-17 10:20:07 +02:00
gui -> setDisplayedame ( pluginInterface -> getPluginDescriptor (). displayedName );
2022-04-12 16:20:45 +02:00
}
else if ( deviceUI -> m_deviceMIMOEngine ) // MIMO device => all possible channels. Depends on index range
{
int nbMIMOChannels = deviceUI -> getNumberOfAvailableMIMOChannels ();
int nbRxChannels = deviceUI -> getNumberOfAvailableRxChannels ();
int nbTxChannels = deviceUI -> getNumberOfAvailableTxChannels ();
qDebug ( "MainWindow::channelAddClicked: MIMO: dev %d : nbMIMO: %d nbRx: %d nbTx: %d selected: %d" ,
2022-04-15 18:59:29 +02:00
deviceSetIndex , nbMIMOChannels , nbRxChannels , nbTxChannels , channelPluginIndex );
2022-04-04 10:23:52 +02:00
2022-04-15 18:59:29 +02:00
if ( channelPluginIndex < nbMIMOChannels )
2022-04-12 16:20:45 +02:00
{
PluginAPI :: ChannelRegistrations * channelRegistrations = m_pluginManager -> getMIMOChannelRegistrations (); // Available channel plugins
2024-08-24 13:17:02 +02:00
const PluginInterface * pluginInterface = ( * channelRegistrations )[ channelPluginIndex ]. m_plugin ;
MIMOChannel * mimoChannel = nullptr ;
2022-04-12 16:20:45 +02:00
pluginInterface -> createMIMOChannel ( deviceUI -> m_deviceAPI , & mimoChannel , & channelAPI );
gui = pluginInterface -> createMIMOChannelGUI ( deviceUI , mimoChannel );
deviceUI -> registerChannelInstance ( channelAPI , gui );
gui -> setIndex ( channelAPI -> getIndexInDeviceSet ());
2022-04-17 10:20:07 +02:00
gui -> setDisplayedame ( pluginInterface -> getPluginDescriptor (). displayedName );
2022-04-12 16:20:45 +02:00
}
2022-04-15 18:59:29 +02:00
else if ( channelPluginIndex < nbMIMOChannels + nbRxChannels ) // Rx
2022-04-12 16:20:45 +02:00
{
PluginAPI :: ChannelRegistrations * channelRegistrations = m_pluginManager -> getRxChannelRegistrations (); // Available channel plugins
2024-08-24 13:17:02 +02:00
const PluginInterface * pluginInterface = ( * channelRegistrations )[ channelPluginIndex - nbMIMOChannels ]. m_plugin ;
BasebandSampleSink * rxChannel = nullptr ;
2022-04-12 16:20:45 +02:00
pluginInterface -> createRxChannel ( deviceUI -> m_deviceAPI , & rxChannel , & channelAPI );
gui = pluginInterface -> createRxChannelGUI ( deviceUI , rxChannel );
deviceUI -> registerRxChannelInstance ( channelAPI , gui );
gui -> setIndex ( channelAPI -> getIndexInDeviceSet ());
2022-04-17 10:20:07 +02:00
gui -> setDisplayedame ( pluginInterface -> getPluginDescriptor (). displayedName );
2022-04-12 16:20:45 +02:00
}
2022-04-15 18:59:29 +02:00
else if ( channelPluginIndex < nbMIMOChannels + nbRxChannels + nbTxChannels )
2022-04-12 16:20:45 +02:00
{
PluginAPI :: ChannelRegistrations * channelRegistrations = m_pluginManager -> getTxChannelRegistrations (); // Available channel plugins
2024-08-24 13:17:02 +02:00
const PluginInterface * pluginInterface = ( * channelRegistrations )[ channelPluginIndex - nbMIMOChannels - nbRxChannels ]. m_plugin ;
BasebandSampleSource * txChannel = nullptr ;
2022-04-12 16:20:45 +02:00
pluginInterface -> createTxChannel ( deviceUI -> m_deviceAPI , & txChannel , & channelAPI );
gui = pluginInterface -> createTxChannelGUI ( deviceUI , txChannel );
deviceUI -> registerTxChannelInstance ( channelAPI , gui );
gui -> setIndex ( channelAPI -> getIndexInDeviceSet ());
2022-04-17 10:20:07 +02:00
gui -> setDisplayedame ( pluginInterface -> getPluginDescriptor (). displayedName );
2022-04-12 16:20:45 +02:00
}
2024-08-24 13:17:02 +02:00
else
{
return ;
}
2022-04-04 10:23:52 +02:00
2024-08-25 23:36:46 +02:00
gui -> setDeviceType ( ChannelGUI :: DeviceType :: DeviceMIMO );
2022-04-12 16:20:45 +02:00
}
2024-08-24 13:17:02 +02:00
else
{
return ;
}
2022-04-12 16:20:45 +02:00
if ( gui )
{
QObject :: connect (
gui ,
& ChannelGUI :: moveToWorkspace ,
this ,
2024-08-24 13:17:02 +02:00
[ this , gui ]( int wsIndexDest ){ this -> channelMove ( gui , wsIndexDest ); }
2022-04-12 16:20:45 +02:00
);
2022-04-15 18:59:29 +02:00
QObject :: connect (
gui ,
& ChannelGUI :: duplicateChannelEmitted ,
this ,
2024-08-24 13:17:02 +02:00
[ this , gui ](){ this -> channelDuplicate ( gui ); }
2022-04-15 18:59:29 +02:00
);
2022-04-16 16:45:53 +02:00
QObject :: connect (
gui ,
& ChannelGUI :: moveToDeviceSet ,
this ,
2024-08-24 13:17:02 +02:00
[ this , gui ]( int dsIndexDest ){ this -> channelMoveToDeviceSet ( gui , dsIndexDest ); }
2022-04-16 16:45:53 +02:00
);
2022-04-12 16:20:45 +02:00
gui -> setDeviceSetIndex ( deviceSetIndex );
2022-04-18 12:08:33 +02:00
gui -> setIndexToolTip ( deviceAPI -> getSamplingDeviceDisplayName ());
2022-04-12 16:20:45 +02:00
gui -> setWorkspaceIndex ( workspace -> getIndex ());
qDebug ( "MainWindow::channelAddClicked: adding %s to workspace #%d" ,
qPrintable ( gui -> getTitle ()), workspace -> getIndex ());
workspace -> addToMdiArea (( QMdiSubWindow * ) gui );
2023-08-24 15:51:50 +01:00
loadDefaultPreset ( channelAPI -> getURI (), gui );
2022-04-12 16:20:45 +02:00
}
}
2022-04-04 10:23:52 +02:00
}
void MainWindow :: featureAddClicked ( Workspace * workspace , int featureIndex )
{
qDebug ( "MainWindow::featureAddClicked: W%d feature at %d" , workspace -> getIndex (), featureIndex );
2022-04-15 10:04:24 +02:00
int currentFeatureSetIndex = 0 ; // Do it in the unique set
FeatureUISet * featureUISet = m_featureUIs [ currentFeatureSetIndex ];
2022-04-04 10:23:52 +02:00
qDebug ( "MainWindow::featureAddClicked: m_apiAdapter: %p" , m_apiAdapter );
PluginAPI :: FeatureRegistrations * featureRegistrations = m_pluginManager -> getFeatureRegistrations (); // Available feature plugins
2024-08-24 13:17:02 +02:00
const PluginInterface * pluginInterface = ( * featureRegistrations )[ featureIndex ]. m_plugin ;
2022-04-04 10:23:52 +02:00
Feature * feature = pluginInterface -> createFeature ( m_apiAdapter );
FeatureGUI * gui = pluginInterface -> createFeatureGUI ( featureUISet , feature );
featureUISet -> registerFeatureInstance ( gui , feature );
gui -> setIndex ( feature -> getIndexInFeatureSet ());
gui -> setWorkspaceIndex ( workspace -> getIndex ());
2022-04-18 12:08:33 +02:00
gui -> setDisplayedame ( pluginInterface -> getPluginDescriptor (). displayedName );
2022-04-04 10:23:52 +02:00
workspace -> addToMdiArea (( QMdiSubWindow * ) gui );
2023-08-24 15:51:50 +01:00
loadDefaultPreset ( feature -> getURI (), gui );
2022-04-04 10:23:52 +02:00
QObject :: connect (
gui ,
& FeatureGUI :: moveToWorkspace ,
this ,
2024-08-24 13:17:02 +02:00
[ this , gui ]( int wsIndexDest ){ this -> featureMove ( gui , wsIndexDest ); }
2022-04-04 10:23:52 +02:00
);
}
2017-10-22 19:12:43 +02:00
2022-04-04 10:23:52 +02:00
void MainWindow :: featureMove ( FeatureGUI * gui , int wsIndexDestnation )
{
int wsIndexOrigin = gui -> getWorkspaceIndex ();
2019-05-18 15:40:00 +02:00
2022-04-04 10:23:52 +02:00
if ( wsIndexOrigin == wsIndexDestnation ) {
return ;
2017-10-22 19:12:43 +02:00
}
2022-04-04 10:23:52 +02:00
m_workspaces [ wsIndexOrigin ] -> removeFromMdiArea ( gui );
gui -> setWorkspaceIndex ( wsIndexDestnation );
m_workspaces [ wsIndexDestnation ] -> addToMdiArea ( gui );
2017-10-22 19:12:43 +02:00
}
2022-04-07 16:32:03 +02:00
void MainWindow :: deviceMove ( DeviceGUI * gui , int wsIndexDestnation )
{
int wsIndexOrigin = gui -> getWorkspaceIndex ();
2022-04-14 03:07:33 +02:00
qDebug ( "MainWindow::deviceMove: %s from %d to %d" ,
qPrintable ( gui -> getTitle ()), wsIndexOrigin , wsIndexDestnation );
2022-04-07 16:32:03 +02:00
if ( wsIndexOrigin == wsIndexDestnation ) {
return ;
}
m_workspaces [ wsIndexOrigin ] -> removeFromMdiArea ( gui );
gui -> setWorkspaceIndex ( wsIndexDestnation );
m_workspaces [ wsIndexDestnation ] -> addToMdiArea ( gui );
}
2022-04-12 16:20:45 +02:00
void MainWindow :: channelMove ( ChannelGUI * gui , int wsIndexDestnation )
{
int wsIndexOrigin = gui -> getWorkspaceIndex ();
if ( wsIndexOrigin == wsIndexDestnation ) {
return ;
}
m_workspaces [ wsIndexOrigin ] -> removeFromMdiArea ( gui );
gui -> setWorkspaceIndex ( wsIndexDestnation );
m_workspaces [ wsIndexDestnation ] -> addToMdiArea ( gui );
}
2022-04-09 13:38:22 +02:00
void MainWindow :: mainSpectrumMove ( MainSpectrumGUI * gui , int wsIndexDestnation )
{
int wsIndexOrigin = gui -> getWorkspaceIndex ();
2022-04-14 03:07:33 +02:00
qDebug ( "MainWindow::mainSpectrumMove: %s from %d to %d" ,
qPrintable ( gui -> getTitle ()), wsIndexOrigin , wsIndexDestnation );
2022-04-09 13:38:22 +02:00
if ( wsIndexOrigin == wsIndexDestnation ) {
return ;
}
m_workspaces [ wsIndexOrigin ] -> removeFromMdiArea ( gui );
gui -> setWorkspaceIndex ( wsIndexDestnation );
m_workspaces [ wsIndexDestnation ] -> addToMdiArea ( gui );
}
2022-04-28 00:01:08 +02:00
void MainWindow :: mainSpectrumShow ( int deviceSetIndex )
2022-04-10 00:11:23 +02:00
{
2022-04-28 00:01:08 +02:00
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
deviceUISet -> m_mainSpectrumGUI -> show ();
deviceUISet -> m_mainSpectrumGUI -> raise ();
2022-04-10 00:11:23 +02:00
}
2022-06-24 22:52:17 +02:00
void MainWindow :: mainSpectrumRequestDeviceCenterFrequency ( int deviceSetIndex , qint64 deviceCenterFrequency )
{
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
DeviceAPI * deviceAPI = deviceUISet -> m_deviceAPI ;
if ( deviceAPI -> getSampleSource ()) {
deviceAPI -> getSampleSource () -> setCenterFrequency ( deviceCenterFrequency );
} else if ( deviceAPI -> getSampleSink ()) {
deviceAPI -> getSampleSink () -> setCenterFrequency ( deviceCenterFrequency );
}
// Not implemented for MIMO
}
2022-04-12 16:20:45 +02:00
void MainWindow :: showAllChannels ( int deviceSetIndex )
{
DeviceUISet * deviceUISet = m_deviceUIs [ deviceSetIndex ];
2022-04-18 10:21:47 +02:00
for ( int i = 0 ; i < deviceUISet -> getNumberOfChannels (); i ++ )
{
2022-04-12 16:20:45 +02:00
deviceUISet -> getChannelGUIAt ( i ) -> show ();
2022-04-18 10:21:47 +02:00
deviceUISet -> getChannelGUIAt ( i ) -> raise ();
2022-04-12 16:20:45 +02:00
}
}
2025-06-20 15:43:01 +01:00
void MainWindow :: startRemoteTCPSink ()
{
RemoteTCPSinkStarter :: start ( m_parser );
}
2025-01-20 10:54:21 +00:00
void MainWindow :: startAllAfterDelay ()
{
// Wait a little bit before starting all devices and features,
// as some devices, such as FileSinks, can fail to start if run before initialised
// Is there a better way than this arbitrary time?
QTimer :: singleShot ( 1000 , this , & MainWindow :: startAll );
}
// Start all devices and features in all workspaces
void MainWindow :: startAll ()
{
// Start all devices
for ( const auto & workspace : m_workspaces ) {
startAllDevices ( workspace );
}
// Start all features
2026-03-25 18:58:43 +00:00
for ( std :: size_t featureSetIndex = 0 ; featureSetIndex < m_featureUIs . size (); featureSetIndex ++ )
2025-01-20 10:54:21 +00:00
{
for ( int featureIndex = 0 ; featureIndex < m_featureUIs [ featureSetIndex ] -> getNumberOfFeatures (); featureIndex ++ ) {
FeatureWebAPIUtils :: run ( featureSetIndex , featureIndex );
}
}
}
2022-08-27 10:18:17 +01:00
// Start all devices in the workspace
2024-08-24 13:17:02 +02:00
void MainWindow :: startAllDevices ( const Workspace * workspace ) const
2022-08-27 10:18:17 +01:00
{
int workspaceIndex = workspace -> getIndex ();
for ( auto deviceUI : m_deviceUIs )
{
if ( deviceUI -> m_deviceAPI -> getWorkspaceIndex () == workspaceIndex )
{
// We use WebAPI rather than call deviceUI->m_deviceAPI->startDeviceEngine();
// so that the start/stop button in the Device GUI is correctly updated
int deviceIndex = deviceUI -> m_deviceAPI -> getDeviceSetIndex ();
ChannelWebAPIUtils :: run ( deviceIndex );
}
}
}
// Stop all devices in the workspace
2024-08-24 13:17:02 +02:00
void MainWindow :: stopAllDevices ( const Workspace * workspace ) const
2022-08-27 10:18:17 +01:00
{
int workspaceIndex = workspace -> getIndex ();
for ( auto deviceUI : m_deviceUIs )
{
if ( deviceUI -> m_deviceAPI -> getWorkspaceIndex () == workspaceIndex )
{
int deviceIndex = deviceUI -> m_deviceAPI -> getDeviceSetIndex ();
ChannelWebAPIUtils :: stop ( deviceIndex );
}
}
}
void MainWindow :: deviceStateChanged ( DeviceAPI * deviceAPI )
{
emit m_mainCore -> deviceStateChanged ( deviceAPI -> getDeviceSetIndex (), deviceAPI );
}
2022-04-04 10:23:52 +02:00
void MainWindow :: openFeaturePresetsDialog ( QPoint p , Workspace * workspace )
2020-09-20 01:06:34 +02:00
{
2022-04-04 10:23:52 +02:00
FeaturePresetsDialog dialog ;
dialog . setFeatureUISet ( m_featureUIs [ 0 ]);
dialog . setPresets ( m_mainCore -> m_settings . getFeatureSetPresets ());
dialog . setPluginAPI ( m_pluginManager -> getPluginAPI ());
dialog . setWebAPIAdapter ( m_apiAdapter );
2022-04-09 13:38:22 +02:00
dialog . setCurrentWorkspace ( workspace );
dialog . setWorkspaces ( & m_workspaces );
2022-04-04 10:23:52 +02:00
dialog . populateTree ();
dialog . move ( p );
2022-12-20 21:06:39 +00:00
new DialogPositioner ( & dialog , true );
2022-04-04 10:23:52 +02:00
dialog . exec ();
2022-04-05 16:26:57 +02:00
if ( dialog . wasPresetLoaded ())
{
for ( int i = 0 ; i < m_featureUIs [ 0 ] -> getNumberOfFeatures (); i ++ )
{
FeatureGUI * gui = m_featureUIs [ 0 ] -> getFeatureGuiAt ( i );
QObject :: connect (
gui ,
& FeatureGUI :: moveToWorkspace ,
this ,
2024-08-24 13:17:02 +02:00
[ this , gui ]( int wsIndexDest ){ this -> featureMove ( gui , wsIndexDest ); }
2022-04-05 16:26:57 +02:00
);
}
}
2020-09-20 01:06:34 +02:00
}
2024-08-24 13:17:02 +02:00
void MainWindow :: openDeviceSetPresetsDialog ( QPoint p , const DeviceGUI * deviceGUI )
2022-04-13 18:43:37 +02:00
{
Workspace * workspace = m_workspaces [ deviceGUI -> getWorkspaceIndex ()];
DeviceUISet * deviceUISet = m_deviceUIs [ deviceGUI -> getIndex ()];
DeviceSetPresetsDialog dialog ;
dialog . setDeviceUISet ( deviceUISet );
dialog . setPresets ( m_mainCore -> m_settings . getPresets ());
dialog . setPluginAPI ( m_pluginManager -> getPluginAPI ());
dialog . setCurrentWorkspace ( workspace );
dialog . setWorkspaces ( & m_workspaces );
dialog . populateTree (( int ) deviceGUI -> getDeviceType ());
dialog . move ( p );
2022-12-20 21:06:39 +00:00
new DialogPositioner ( & dialog , true );
2022-04-13 18:43:37 +02:00
dialog . exec ();
}
2020-09-21 03:13:36 +02:00
void MainWindow :: deleteFeature ( int featureSetIndex , int featureIndex )
{
if (( featureSetIndex >= 0 ) && ( featureSetIndex < ( int ) m_featureUIs . size ()))
{
2021-11-26 08:41:42 +01:00
FeatureUISet * featureUISet = m_featureUIs [ featureSetIndex ];
featureUISet -> deleteFeature ( featureIndex );
2020-09-21 03:13:36 +02:00
}
}
2023-08-24 15:51:50 +01:00
// Look for and load a preset named Defaults/Default for the given plugin id
void MainWindow :: loadDefaultPreset ( const QString & pluginId , SerializableInterface * serializableInterface )
{
2024-08-24 13:17:02 +02:00
const QList < PluginPreset *>* presets = m_mainCore -> m_settings . getPluginPresets ();
2023-08-24 15:51:50 +01:00
for ( const auto preset : * presets )
{
if ( preset -> getGroup () == "Defaults"
&& preset -> getDescription () == "Default"
&& preset -> getPluginIdURI () == pluginId )
{
qDebug () << "MainWindow::loadDefaultPreset: Loading " << preset -> getGroup () << preset -> getDescription () << "for" << pluginId ;
serializableInterface -> deserialize ( preset -> getConfig ());
}
}
}
2017-10-22 19:12:43 +02:00
void MainWindow :: on_action_About_triggered ()
{
2024-07-20 19:20:17 +02:00
AboutDialog dlg ( m_apiHost . isEmpty () ? "0.0.0.0" : m_apiHost , m_apiPort , m_mainCore -> m_settings , this );
2017-10-22 19:12:43 +02:00
dlg . exec ();
}
void MainWindow :: updateStatus ()
{
2022-12-20 21:06:39 +00:00
if ( m_dateTimeWidget ) {
m_dateTimeWidget -> setText ( QDateTime :: currentDateTime (). toString ( "yyyy-MM-dd HH:mm:ss t" ));
}
2017-10-22 19:12:43 +02:00
}
2017-11-11 19:26:23 +01:00
2024-08-24 13:17:02 +02:00
void MainWindow :: commandKeyPressed ( Qt :: Key key , Qt :: KeyboardModifiers keyModifiers , bool release ) const
2018-01-05 05:05:12 +01:00
{
2022-04-04 16:13:42 +02:00
qDebug ( "MainWindow::commandKeyPressed: key: %x mod: %x %s" , ( int ) key , ( int ) keyModifiers , release ? "release" : "press" );
int currentDeviceSetIndex = 0 ;
2018-01-05 10:28:32 +01:00
2022-04-04 16:13:42 +02:00
for ( int i = 0 ; i < m_mainCore -> m_settings . getCommandCount (); ++ i )
{
const Command * command = m_mainCore -> m_settings . getCommand ( i );
2018-01-05 10:28:32 +01:00
2022-04-04 16:13:42 +02:00
if ( command -> getAssociateKey ()
&& ( command -> getRelease () == release )
&& ( command -> getKey () == key )
&& ( command -> getKeyModifiers () == keyModifiers ))
{
2024-08-24 13:17:02 +02:00
auto * command_mod = const_cast < Command *> ( command );
2022-04-04 16:13:42 +02:00
command_mod -> run ( m_apiServer -> getHost (), m_apiServer -> getPort (), currentDeviceSetIndex );
}
}
2018-01-05 05:05:12 +01:00
}
2022-12-20 21:06:39 +00:00
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 );
}
}
2024-09-03 18:38:32 +03:00
void MainWindow :: orientationChanged ( Qt :: ScreenOrientation orientation )
2022-12-20 21:06:39 +00:00
{
#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 );
2023-01-02 15:22:07 +00:00
}
2022-12-28 20:33:28 +01:00
#else
( void ) orientation ;
2022-12-20 21:06:39 +00:00
#endif
}