mirror of
https://github.com/f4exb/sdrangel.git
synced 2026-05-02 20:24:00 -04:00
Feature plugins framework initial commit
This commit is contained in:
parent
08b7b8e305
commit
4db3c5240a
@ -150,6 +150,8 @@ set(sdrbase_SOURCES
|
||||
device/deviceuserargs.cpp
|
||||
device/deviceutils.cpp
|
||||
|
||||
feature/feature.cpp
|
||||
|
||||
limerfe/limerfeusbcalib.cpp
|
||||
|
||||
settings/preferences.cpp
|
||||
@ -298,6 +300,8 @@ set(sdrbase_HEADERS
|
||||
device/deviceuserargs.h
|
||||
device/deviceutils.h
|
||||
|
||||
feature/feature.h
|
||||
|
||||
limerfe/limerfeusbcalib.h
|
||||
|
||||
plugin/plugininstancegui.h
|
||||
|
||||
43
sdrbase/feature/feature.cpp
Normal file
43
sdrbase/feature/feature.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// API for features //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "util/uid.h"
|
||||
#include "util/message.h"
|
||||
|
||||
#include "feature.h"
|
||||
|
||||
Feature::Feature(const QString& name, WebAPIAdapterInterface *webAPIAdapterInterface) :
|
||||
m_name(name),
|
||||
m_uid(UidCalculator::getNewObjectId()),
|
||||
m_webAPIAdapterInterface(webAPIAdapterInterface)
|
||||
{
|
||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
}
|
||||
|
||||
void Feature::handleInputMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = m_inputMessageQueue.pop()))
|
||||
{
|
||||
if (handleMessage(*message)) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
sdrbase/feature/feature.h
Normal file
79
sdrbase/feature/feature.h
Normal file
@ -0,0 +1,79 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// API for features //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SDRBASE_FETURE_FEATUREAPI_H_
|
||||
#define SDRBASE_FETURE_FEATUREAPI_H_
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "export.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
class WebAPIAdapterInterface;
|
||||
|
||||
class SDRBASE_API Feature : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum FeatureState {
|
||||
StNotStarted, //!< feature is before initialization
|
||||
StIdle, //!< feature is idle
|
||||
StRunning, //!< feature is running
|
||||
StError //!< feature is in error
|
||||
};
|
||||
|
||||
Feature(const QString& name, WebAPIAdapterInterface *webAPIAdapterInterface);
|
||||
virtual ~Feature() {}
|
||||
virtual void destroy() = 0;
|
||||
virtual bool handleMessage(const Message& cmd) = 0; //!< Processing of a message. Returns true if message has actually been processed
|
||||
|
||||
virtual void getIdentifier(QString& id) = 0;
|
||||
virtual void getTitle(QString& title) = 0;
|
||||
virtual void setName(const QString& name) { m_name = name; }
|
||||
virtual const QString& getName() const { return m_name; }
|
||||
|
||||
virtual QByteArray serialize() const = 0;
|
||||
virtual bool deserialize(const QByteArray& data) = 0;
|
||||
|
||||
|
||||
uint64_t getUID() const { return m_uid; }
|
||||
FeatureState getState() const { return m_state; }
|
||||
const QString& getErrorMessage() const { return m_errorMessage; }
|
||||
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
|
||||
MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; }
|
||||
|
||||
protected:
|
||||
MessageQueue m_inputMessageQueue;
|
||||
MessageQueue *m_guiMessageQueue; //!< Input message queue to the GUI
|
||||
FeatureState m_state;
|
||||
QString m_errorMessage;
|
||||
WebAPIAdapterInterface *m_webAPIAdapterInterface;
|
||||
|
||||
protected slots:
|
||||
void handleInputMessages();
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
uint64_t m_uid;
|
||||
};
|
||||
|
||||
#endif // SDRBASE_FETURE_FEATUREAPI_H_
|
||||
@ -46,6 +46,16 @@ void PluginAPI::registerSampleMIMO(const QString& mimoName, PluginInterface* plu
|
||||
m_pluginManager->registerSampleMIMO(mimoName, plugin);
|
||||
}
|
||||
|
||||
void PluginAPI::registerFeature(const QString& featureIdURI, const QString& featureId, PluginInterface* plugin)
|
||||
{
|
||||
m_pluginManager->registerFeature(featureIdURI, featureId, plugin);
|
||||
}
|
||||
|
||||
PluginAPI::FeatureRegistrations *PluginAPI::getFeatureRegistrations()
|
||||
{
|
||||
return m_pluginManager->getFeatureRegistrations();
|
||||
}
|
||||
|
||||
PluginAPI::PluginAPI(PluginManager* pluginManager) :
|
||||
m_pluginManager(pluginManager)
|
||||
{
|
||||
|
||||
@ -45,6 +45,20 @@ public:
|
||||
|
||||
typedef QList<ChannelRegistration> ChannelRegistrations;
|
||||
|
||||
struct FeatureRegistration
|
||||
{
|
||||
QString m_featureIdURI; //!< Feature type ID in URI form
|
||||
QString m_featureId; //!< Feature type ID in short form from object name
|
||||
PluginInterface *m_plugin;
|
||||
FeatureRegistration(const QString& featureIdURI, const QString& featureId, PluginInterface* plugin) :
|
||||
m_featureIdURI(featureIdURI),
|
||||
m_featureId(featureId),
|
||||
m_plugin(plugin)
|
||||
{ }
|
||||
};
|
||||
|
||||
typedef QList<FeatureRegistration> FeatureRegistrations;
|
||||
|
||||
// Rx Channel stuff
|
||||
void registerRxChannel(const QString& channelIdURI, const QString& channelId, PluginInterface* plugin);
|
||||
ChannelRegistrations *getRxChannelRegistrations();
|
||||
@ -66,6 +80,10 @@ public:
|
||||
// Sample MIMO stuff
|
||||
void registerSampleMIMO(const QString& sinkName, PluginInterface* plugin);
|
||||
|
||||
// Feature stuff
|
||||
void registerFeature(const QString& featureIdURI, const QString& featureId, PluginInterface* plugin);
|
||||
FeatureRegistrations *getFeatureRegistrations();
|
||||
|
||||
protected:
|
||||
PluginManager* m_pluginManager;
|
||||
|
||||
|
||||
@ -20,6 +20,8 @@ struct SDRBASE_API PluginDescriptor {
|
||||
class PluginAPI;
|
||||
class DeviceAPI;
|
||||
class DeviceUISet;
|
||||
class FeatureUISet;
|
||||
class WebAPIAdapterInterface;
|
||||
class PluginInstanceGUI;
|
||||
class QWidget;
|
||||
class DeviceSampleSource;
|
||||
@ -31,6 +33,7 @@ class MIMOChannel;
|
||||
class ChannelAPI;
|
||||
class ChannelWebAPIAdapter;
|
||||
class DeviceWebAPIAdapter;
|
||||
class Feature;
|
||||
|
||||
class SDRBASE_API PluginInterface {
|
||||
public:
|
||||
@ -316,6 +319,18 @@ public:
|
||||
virtual DeviceWebAPIAdapter* createDeviceWebAPIAdapter() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Features
|
||||
|
||||
virtual PluginInstanceGUI* createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual Feature* createFeature(WebAPIAdapterInterface *webAPIAdapterInterface) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
Q_DECLARE_INTERFACE(PluginInterface, "SDRangel.PluginInterface/0.1")
|
||||
|
||||
@ -192,6 +192,15 @@ void PluginManager::registerSampleMIMO(const QString& mimoName, PluginInterface*
|
||||
));
|
||||
}
|
||||
|
||||
void PluginManager::registerFeature(const QString& featureIdURI, const QString& featureId, PluginInterface* plugin)
|
||||
{
|
||||
qDebug() << "PluginManager::registerFeature "
|
||||
<< plugin->getPluginDescriptor().displayedName.toStdString().c_str()
|
||||
<< " with channel name " << featureIdURI;
|
||||
|
||||
m_featureRegistrations.append(PluginAPI::FeatureRegistration(featureIdURI, featureId, plugin));
|
||||
}
|
||||
|
||||
void PluginManager::loadPluginsDir(const QDir& dir)
|
||||
{
|
||||
QDir pluginsDir(dir);
|
||||
@ -259,6 +268,17 @@ void PluginManager::listMIMOChannels(QList<QString>& list)
|
||||
}
|
||||
}
|
||||
|
||||
void PluginManager::listFeatures(QList<QString>& list)
|
||||
{
|
||||
list.clear();
|
||||
|
||||
for (PluginAPI::FeatureRegistrations::iterator it = m_featureRegistrations.begin(); it != m_featureRegistrations.end(); ++it)
|
||||
{
|
||||
const PluginDescriptor& pluginDesciptor = it->m_plugin->getPluginDescriptor();
|
||||
list.append(pluginDesciptor.displayedName);
|
||||
}
|
||||
}
|
||||
|
||||
void PluginManager::createRxChannelInstance(int channelPluginIndex, DeviceUISet *deviceUISet, DeviceAPI *deviceAPI)
|
||||
{
|
||||
if (channelPluginIndex < m_rxChannelRegistrations.size())
|
||||
@ -289,6 +309,16 @@ void PluginManager::createMIMOChannelInstance(int channelPluginIndex, DeviceUISe
|
||||
}
|
||||
}
|
||||
|
||||
void PluginManager::createFeatureInstance(int featurePluginIndex, FeatureUISet *featureUISet, WebAPIAdapterInterface *webAPIAdapterInterface)
|
||||
{
|
||||
if (featurePluginIndex < m_featureRegistrations.size())
|
||||
{
|
||||
PluginInterface *pluginInterface = m_featureRegistrations[featurePluginIndex].m_plugin;
|
||||
Feature *feature = pluginInterface->createFeature(webAPIAdapterInterface);
|
||||
pluginInterface->createFeatureGUI(featureUISet, feature);
|
||||
}
|
||||
}
|
||||
|
||||
const PluginInterface *PluginManager::getChannelPluginInterface(const QString& channelIdURI) const
|
||||
{
|
||||
for (PluginAPI::ChannelRegistrations::const_iterator it = m_rxChannelRegistrations.begin(); it != m_rxChannelRegistrations.end(); ++it)
|
||||
|
||||
@ -35,6 +35,7 @@ class Message;
|
||||
class MessageQueue;
|
||||
class DeviceAPI;
|
||||
class DeviceUserArgs;
|
||||
class WebAPIAdapterInterface;
|
||||
|
||||
class SDRBASE_API PluginManager : public QObject {
|
||||
Q_OBJECT
|
||||
@ -70,6 +71,7 @@ public:
|
||||
void registerSampleSource(const QString& sourceName, PluginInterface* plugin);
|
||||
void registerSampleSink(const QString& sinkName, PluginInterface* plugin);
|
||||
void registerSampleMIMO(const QString& mimoName, PluginInterface* plugin);
|
||||
void registerFeature(const QString& featureIdURI, const QString& featureId, PluginInterface* plugin);
|
||||
|
||||
PluginAPI::SamplingDeviceRegistrations& getSourceDeviceRegistrations() { return m_sampleSourceRegistrations; }
|
||||
PluginAPI::SamplingDeviceRegistrations& getSinkDeviceRegistrations() { return m_sampleSinkRegistrations; }
|
||||
@ -77,6 +79,7 @@ public:
|
||||
PluginAPI::ChannelRegistrations *getRxChannelRegistrations() { return &m_rxChannelRegistrations; }
|
||||
PluginAPI::ChannelRegistrations *getTxChannelRegistrations() { return &m_txChannelRegistrations; }
|
||||
PluginAPI::ChannelRegistrations *getMIMOChannelRegistrations() { return &m_mimoChannelRegistrations; }
|
||||
PluginAPI::FeatureRegistrations *getFeatureRegistrations() { return &m_featureRegistrations; }
|
||||
|
||||
void createRxChannelInstance(int channelPluginIndex, DeviceUISet *deviceUISet, DeviceAPI *deviceAPI);
|
||||
void listRxChannels(QList<QString>& list);
|
||||
@ -87,6 +90,9 @@ public:
|
||||
void createMIMOChannelInstance(int channelPluginIndex, DeviceUISet *deviceUISet, DeviceAPI *deviceAPI);
|
||||
void listMIMOChannels(QList<QString>& list);
|
||||
|
||||
void createFeatureInstance(int featurePluginIndex, FeatureUISet *featureUISet, WebAPIAdapterInterface *webAPIAdapterInterface);
|
||||
void listFeatures(QList<QString>& list);
|
||||
|
||||
const PluginInterface *getChannelPluginInterface(const QString& channelIdURI) const;
|
||||
const PluginInterface *getDevicePluginInterface(const QString& deviceId) const;
|
||||
|
||||
@ -131,6 +137,8 @@ private:
|
||||
PluginAPI::SamplingDeviceRegistrations m_sampleSinkRegistrations; //!< Output sink plugins (one per device kind) register here
|
||||
PluginAPI::SamplingDeviceRegistrations m_sampleMIMORegistrations; //!< MIMO sink plugins (one per device kind) register here
|
||||
|
||||
PluginAPI::FeatureRegistrations m_featureRegistrations; //!< Feature plugins register here
|
||||
|
||||
// "Local" sample source device IDs
|
||||
static const QString m_localInputHardwareID; //!< Local input hardware ID
|
||||
static const QString m_localInputDeviceTypeID; //!< Local input plugin ID
|
||||
|
||||
@ -13,6 +13,7 @@ set(sdrgui_SOURCES
|
||||
gui/audioselectdialog.cpp
|
||||
gui/basicchannelsettingsdialog.cpp
|
||||
gui/basicdevicesettingsdialog.cpp
|
||||
gui/basicfeaturesettingsdialog.cpp
|
||||
gui/buttonswitch.cpp
|
||||
gui/channeladddialog.cpp
|
||||
gui/channelsdock.cpp
|
||||
@ -31,6 +32,9 @@ set(sdrgui_SOURCES
|
||||
gui/editcommanddialog.cpp
|
||||
gui/externalclockbutton.cpp
|
||||
gui/externalclockdialog.cpp
|
||||
gui/featureadddialog.cpp
|
||||
gui/featuresdock.cpp
|
||||
gui/featurewindow.cpp
|
||||
gui/glscope.cpp
|
||||
gui/glscopegui.cpp
|
||||
gui/glshadercolors.cpp
|
||||
@ -65,6 +69,8 @@ set(sdrgui_SOURCES
|
||||
|
||||
device/deviceuiset.cpp
|
||||
|
||||
feature/featureuiset.cpp
|
||||
|
||||
soapygui/discreterangegui.cpp
|
||||
soapygui/intervalrangegui.cpp
|
||||
soapygui/itemsettinggui.cpp
|
||||
@ -89,6 +95,7 @@ set(sdrgui_HEADERS
|
||||
gui/audioselectdialog.h
|
||||
gui/basicchannelsettingsdialog.h
|
||||
gui/basicdevicesettingsdialog.h
|
||||
gui/basicfeaturesettingsdialog.h
|
||||
gui/buttonswitch.h
|
||||
gui/channeladddialog.h
|
||||
gui/channelsdock.h
|
||||
@ -107,6 +114,9 @@ set(sdrgui_HEADERS
|
||||
gui/editcommanddialog.h
|
||||
gui/externalclockbutton.h
|
||||
gui/externalclockdialog.h
|
||||
gui/featureadddialog.h
|
||||
gui/featuresdock.h
|
||||
gui/featurewindow.h
|
||||
gui/glscope.h
|
||||
gui/glscopegui.h
|
||||
gui/glshadercolors.h
|
||||
@ -142,6 +152,8 @@ set(sdrgui_HEADERS
|
||||
|
||||
device/deviceuiset.h
|
||||
|
||||
feature/featureuiset.h
|
||||
|
||||
soapygui/discreterangegui.h
|
||||
soapygui/intervalrangegui.h
|
||||
soapygui/itemsettinggui.h
|
||||
@ -162,6 +174,7 @@ set(sdrgui_FORMS
|
||||
gui/ambedevicesdialog.ui
|
||||
gui/basicchannelsettingsdialog.ui
|
||||
gui/basicdevicesettingsdialog.ui
|
||||
gui/basicfeaturesettingsdialog.ui
|
||||
gui/channeladddialog.ui
|
||||
gui/commandoutputdialog.ui
|
||||
gui/cwkeyergui.ui
|
||||
@ -169,6 +182,7 @@ set(sdrgui_FORMS
|
||||
gui/deviceuserargsdialog.ui
|
||||
gui/editcommanddialog.ui
|
||||
gui/externalclockdialog.ui
|
||||
gui/featureadddialog.ui
|
||||
gui/glscopegui.ui
|
||||
gui/glspectrumgui.ui
|
||||
gui/pluginsdialog.ui
|
||||
|
||||
85
sdrgui/feature/featureuiset.cpp
Normal file
85
sdrgui/feature/featureuiset.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "gui/featurewindow.h"
|
||||
#include "plugin/plugininstancegui.h"
|
||||
|
||||
#include "featureuiset.h"
|
||||
|
||||
FeatureUISet::FeatureUISet(int tabIndex)
|
||||
{
|
||||
m_featureWindow = new FeatureWindow;
|
||||
m_featureTabIndex = tabIndex;
|
||||
}
|
||||
|
||||
FeatureUISet::~FeatureUISet()
|
||||
{
|
||||
delete m_featureWindow;
|
||||
}
|
||||
|
||||
void FeatureUISet::addRollupWidget(QWidget *widget)
|
||||
{
|
||||
m_featureWindow->addRollupWidget(widget);
|
||||
}
|
||||
|
||||
void FeatureUISet::registerFeatureInstance(const QString& featureName, PluginInstanceGUI* pluginGUI)
|
||||
{
|
||||
m_featureInstanceRegistrations.append(FeatureInstanceRegistration(featureName, pluginGUI));
|
||||
renameFeatureInstances();
|
||||
}
|
||||
|
||||
void FeatureUISet::removeFeatureInstance(PluginInstanceGUI* pluginGUI)
|
||||
{
|
||||
for (FeatureInstanceRegistrations::iterator it = m_featureInstanceRegistrations.begin(); it != m_featureInstanceRegistrations.end(); ++it)
|
||||
{
|
||||
if (it->m_gui == pluginGUI)
|
||||
{
|
||||
m_featureInstanceRegistrations.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
renameFeatureInstances();
|
||||
}
|
||||
|
||||
void FeatureUISet::renameFeatureInstances()
|
||||
{
|
||||
for (int i = 0; i < m_featureInstanceRegistrations.count(); i++) {
|
||||
m_featureInstanceRegistrations[i].m_gui->setName(QString("%1:%2").arg(m_featureInstanceRegistrations[i].m_featureName).arg(i));
|
||||
}
|
||||
}
|
||||
|
||||
void FeatureUISet::freeFeatures()
|
||||
{
|
||||
for(int i = 0; i < m_featureInstanceRegistrations.count(); i++)
|
||||
{
|
||||
qDebug("FeatureUISet::freeFeatures: destroying feature [%s]", qPrintable(m_featureInstanceRegistrations[i].m_featureName));
|
||||
m_featureInstanceRegistrations[i].m_gui->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void FeatureUISet::deleteFeature(int featureIndex)
|
||||
{
|
||||
if ((featureIndex >= 0) && (featureIndex < m_featureInstanceRegistrations.count()))
|
||||
{
|
||||
qDebug("FeatureUISet::deleteFeature: delete feature [%s] at %d",
|
||||
qPrintable(m_featureInstanceRegistrations[featureIndex].m_featureName),
|
||||
featureIndex);
|
||||
m_featureInstanceRegistrations[featureIndex].m_gui->destroy();
|
||||
renameFeatureInstances();
|
||||
}
|
||||
}
|
||||
72
sdrgui/feature/featureuiset.h
Normal file
72
sdrgui/feature/featureuiset.h
Normal file
@ -0,0 +1,72 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SDRGUI_FEATURE_FEATUREUISET_H_
|
||||
#define SDRGUI_FEATURE_FEATUREUISET_H_
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
class QWidget;
|
||||
class FeatureWindow;
|
||||
class PluginInstanceGUI;
|
||||
|
||||
class SDRGUI_API FeatureUISet
|
||||
{
|
||||
public:
|
||||
FeatureUISet(int tabIndex);
|
||||
~FeatureUISet();
|
||||
|
||||
void addRollupWidget(QWidget *widget); //!< Add feature rollup widget to feature window
|
||||
int getNumberOfFeatures() const { return m_featureInstanceRegistrations.size(); }
|
||||
void registerFeatureInstance(const QString& featureName, PluginInstanceGUI* pluginGUI);
|
||||
void removeFeatureInstance(PluginInstanceGUI* pluginGUI);
|
||||
void freeFeatures();
|
||||
void deleteFeature(int featureIndex);
|
||||
|
||||
FeatureWindow *m_featureWindow;
|
||||
|
||||
private:
|
||||
struct FeatureInstanceRegistration
|
||||
{
|
||||
QString m_featureName;
|
||||
PluginInstanceGUI* m_gui;
|
||||
|
||||
FeatureInstanceRegistration() :
|
||||
m_featureName(),
|
||||
m_gui(nullptr)
|
||||
{ }
|
||||
|
||||
FeatureInstanceRegistration(const QString& featureName, PluginInstanceGUI* pluginGUI) :
|
||||
m_featureName(featureName),
|
||||
m_gui(pluginGUI)
|
||||
{ }
|
||||
|
||||
bool operator<(const FeatureInstanceRegistration& other) const;
|
||||
};
|
||||
|
||||
typedef QList<FeatureInstanceRegistration> FeatureInstanceRegistrations;
|
||||
|
||||
FeatureInstanceRegistrations m_featureInstanceRegistrations;
|
||||
int m_featureTabIndex;
|
||||
|
||||
void renameFeatureInstances();
|
||||
};
|
||||
|
||||
#endif // SDRGUI_FEATURE_FEATUREUISET_H_
|
||||
68
sdrgui/gui/basicfeaturesettingsdialog.cpp
Normal file
68
sdrgui/gui/basicfeaturesettingsdialog.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <QColorDialog>
|
||||
|
||||
#include "basicfeaturesettingsdialog.h"
|
||||
#include "ui_basicfeaturesettingsdialog.h"
|
||||
|
||||
BasicFeatureSettingsDialog::BasicFeatureSettingsDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::BasicFeatureSettingsDialog),
|
||||
m_hasChanged(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->title->setText(m_title);
|
||||
m_color =m_color;
|
||||
paintColor();
|
||||
}
|
||||
|
||||
BasicFeatureSettingsDialog::~BasicFeatureSettingsDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void BasicFeatureSettingsDialog::setTitle(const QString& title)
|
||||
{
|
||||
ui->title->blockSignals(true);
|
||||
ui->title->setText(title);
|
||||
m_title = title;
|
||||
ui->title->blockSignals(false);
|
||||
}
|
||||
|
||||
void BasicFeatureSettingsDialog::setColor(const QColor& color)
|
||||
{
|
||||
m_color = color;
|
||||
paintColor();
|
||||
}
|
||||
|
||||
void BasicFeatureSettingsDialog::paintColor()
|
||||
{
|
||||
QPixmap pm(24, 24);
|
||||
pm.fill(m_color);
|
||||
ui->colorBtn->setIcon(pm);
|
||||
ui->colorText->setText(tr("#%1%2%3")
|
||||
.arg(m_color.red(), 2, 16, QChar('0'))
|
||||
.arg(m_color.green(), 2, 16, QChar('0'))
|
||||
.arg(m_color.blue(), 2, 16, QChar('0')));
|
||||
}
|
||||
|
||||
void BasicFeatureSettingsDialog::on_colorBtn_clicked()
|
||||
{
|
||||
QColor c = m_color;
|
||||
c = QColorDialog::getColor(c, this, tr("Select Color for Channel"), QColorDialog::DontUseNativeDialog);
|
||||
|
||||
if (c.isValid())
|
||||
{
|
||||
m_color = c;
|
||||
paintColor();
|
||||
}
|
||||
}
|
||||
|
||||
void BasicFeatureSettingsDialog::on_title_editingFinished()
|
||||
{
|
||||
m_title = ui->title->text();
|
||||
}
|
||||
|
||||
void BasicFeatureSettingsDialog::accept()
|
||||
{
|
||||
m_hasChanged = true;
|
||||
QDialog::accept();
|
||||
}
|
||||
56
sdrgui/gui/basicfeaturesettingsdialog.h
Normal file
56
sdrgui/gui/basicfeaturesettingsdialog.h
Normal file
@ -0,0 +1,56 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDE_SDRGUI_BASICFEATURESETTINGSDIALOG_H
|
||||
#define INCLUDE_SDRGUI_BASICFEATURESETTINGSDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "../../exports/export.h"
|
||||
|
||||
namespace Ui {
|
||||
class BasicFeatureSettingsDialog;
|
||||
}
|
||||
|
||||
class SDRGUI_API BasicFeatureSettingsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BasicFeatureSettingsDialog(QWidget *parent = nullptr);
|
||||
~BasicFeatureSettingsDialog();
|
||||
void setTitle(const QString& title);
|
||||
void setColor(const QColor& color);
|
||||
const QString& getTitle() const { return m_title; }
|
||||
const QColor& getColor() const { return m_color; }
|
||||
bool hasChanged() const { return m_hasChanged; }
|
||||
|
||||
private slots:
|
||||
void on_colorBtn_clicked();
|
||||
void on_title_editingFinished();
|
||||
void accept();
|
||||
|
||||
private:
|
||||
Ui::BasicFeatureSettingsDialog *ui;
|
||||
QColor m_color;
|
||||
QString m_title;
|
||||
bool m_hasChanged;
|
||||
|
||||
void paintColor();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_SDRGUI_BASICFEATURESETTINGSDIALOG_H
|
||||
141
sdrgui/gui/basicfeaturesettingsdialog.ui
Normal file
141
sdrgui/gui/basicfeaturesettingsdialog.ui
Normal file
@ -0,0 +1,141 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BasicFeatureSettingsDialog</class>
|
||||
<widget class="QDialog" name="BasicFeatureSettingsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>158</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Basic feature settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="titleLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="titleLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="title">
|
||||
<property name="toolTip">
|
||||
<string>Channel marker title</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="colorLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="colorLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="colorBtn">
|
||||
<property name="toolTip">
|
||||
<string>Channel marker color</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="colorText">
|
||||
<property name="text">
|
||||
<string>#ff0000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>BasicFeatureSettingsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>BasicFeatureSettingsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@ -22,12 +22,6 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>70</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
|
||||
54
sdrgui/gui/featureadddialog.cpp
Normal file
54
sdrgui/gui/featureadddialog.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 F4EXB //
|
||||
// written by Edouard Griffiths //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
#include "featureadddialog.h"
|
||||
#include "ui_featureadddialog.h"
|
||||
|
||||
FeatureAddDialog::FeatureAddDialog(QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::FeatureAddDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(apply(QAbstractButton*)));
|
||||
}
|
||||
|
||||
FeatureAddDialog::~FeatureAddDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void FeatureAddDialog::resetFeatureNames()
|
||||
{
|
||||
ui->featureSelect->clear();
|
||||
}
|
||||
|
||||
void FeatureAddDialog::addFeatureNames(const QStringList& featureNames)
|
||||
{
|
||||
ui->featureSelect->addItems(featureNames);
|
||||
}
|
||||
|
||||
void FeatureAddDialog::apply(QAbstractButton *button)
|
||||
{
|
||||
if (button == (QAbstractButton*) ui->buttonBox->button(QDialogButtonBox::Apply))
|
||||
{
|
||||
int selectedFeatureIndex = ui->featureSelect->currentIndex();
|
||||
emit(addFeature(selectedFeatureIndex));
|
||||
}
|
||||
}
|
||||
54
sdrgui/gui/featureadddialog.h
Normal file
54
sdrgui/gui/featureadddialog.h
Normal file
@ -0,0 +1,54 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 F4EXB //
|
||||
// written by Edouard Griffiths //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SDRGUI_GUI_FEATUREADDDIALOG_H_
|
||||
#define SDRGUI_GUI_FEATUREADDDIALOG_H_
|
||||
|
||||
#include <QDialog>
|
||||
#include <vector>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
class QStringList;
|
||||
class QAbstractButton;
|
||||
|
||||
namespace Ui {
|
||||
class FeatureAddDialog;
|
||||
}
|
||||
|
||||
class SDRGUI_API FeatureAddDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FeatureAddDialog(QWidget* parent = nullptr);
|
||||
~FeatureAddDialog();
|
||||
|
||||
void resetFeatureNames();
|
||||
void addFeatureNames(const QStringList& featureNames);
|
||||
|
||||
private:
|
||||
Ui::FeatureAddDialog* ui;
|
||||
std::vector<int> m_featureIndexes;
|
||||
|
||||
private slots:
|
||||
void apply(QAbstractButton*);
|
||||
|
||||
signals:
|
||||
void addFeature(int);
|
||||
};
|
||||
|
||||
#endif /* SDRGUI_GUI_FEATUREADDDIALOG_H_ */
|
||||
104
sdrgui/gui/featureadddialog.ui
Normal file
104
sdrgui/gui/featureadddialog.ui
Normal file
@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FeatureAddDialog</class>
|
||||
<widget class="QDialog" name="FeatureAddDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>324</width>
|
||||
<height>139</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Add Features</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Available features</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="featureSelect">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>FeatureAddDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>257</x>
|
||||
<y>194</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>203</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>FeatureAddDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>314</x>
|
||||
<y>194</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>203</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
110
sdrgui/gui/featuresdock.cpp
Normal file
110
sdrgui/gui/featuresdock.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 F4EXB //
|
||||
// written by Edouard Griffiths //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QStyle>
|
||||
|
||||
#include "featuresdock.h"
|
||||
|
||||
FeaturesDock::FeaturesDock(QWidget *parent, Qt::WindowFlags flags) :
|
||||
QDockWidget(parent, flags),
|
||||
m_featureAddDialog(this)
|
||||
{
|
||||
m_titleBar = new QWidget();
|
||||
m_titleBarLayout = new QHBoxLayout();
|
||||
m_titleBarLayout->setMargin(0);
|
||||
m_titleBar->setLayout(m_titleBarLayout);
|
||||
|
||||
m_titleLabel = new QLabel();
|
||||
m_titleLabel->setText(QString("Features"));
|
||||
|
||||
m_addFeatureButton = new QPushButton();
|
||||
QIcon addIcon(":/create.png");
|
||||
m_addFeatureButton->setIcon(addIcon);
|
||||
m_addFeatureButton->setToolTip("Add features");
|
||||
m_addFeatureButton->setFixedSize(16, 16);
|
||||
|
||||
m_normalButton = new QPushButton();
|
||||
QIcon normalIcon = style()->standardIcon(QStyle::SP_TitleBarNormalButton, 0, this);
|
||||
m_normalButton->setIcon(normalIcon);
|
||||
m_normalButton->setFixedSize(12, 12);
|
||||
|
||||
m_closeButton = new QPushButton();
|
||||
QIcon closeIcon = style()->standardIcon(QStyle::SP_TitleBarCloseButton, 0, this);
|
||||
m_closeButton->setIcon(closeIcon);
|
||||
m_closeButton->setFixedSize(12, 12);
|
||||
|
||||
m_titleBarLayout->addWidget(m_addFeatureButton);
|
||||
m_titleBarLayout->addWidget(m_titleLabel);
|
||||
m_titleBarLayout->addWidget(m_normalButton);
|
||||
m_titleBarLayout->addWidget(m_closeButton);
|
||||
setTitleBarWidget(m_titleBar);
|
||||
|
||||
QObject::connect(
|
||||
m_addFeatureButton,
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&FeaturesDock::addFeatureDialog
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
m_normalButton,
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&FeaturesDock::toggleFloating
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
&m_featureAddDialog,
|
||||
&FeatureAddDialog::addFeature,
|
||||
this,
|
||||
&FeaturesDock::addFeatureEmitted
|
||||
);
|
||||
|
||||
connect(m_closeButton, SIGNAL(clicked()), this, SLOT(hide()));
|
||||
}
|
||||
|
||||
FeaturesDock::~FeaturesDock()
|
||||
{
|
||||
delete m_closeButton;
|
||||
delete m_normalButton;
|
||||
delete m_addFeatureButton;
|
||||
delete m_titleLabel;
|
||||
delete m_titleBarLayout;
|
||||
delete m_titleBar;
|
||||
}
|
||||
|
||||
void FeaturesDock::toggleFloating()
|
||||
{
|
||||
setFloating(!isFloating());
|
||||
}
|
||||
|
||||
void FeaturesDock::addFeatureDialog()
|
||||
{
|
||||
m_featureAddDialog.exec();
|
||||
|
||||
}
|
||||
|
||||
void FeaturesDock::addFeatureEmitted(int featureIndex)
|
||||
{
|
||||
if (featureIndex >= 0) {
|
||||
emit addFeature(featureIndex);
|
||||
}
|
||||
}
|
||||
59
sdrgui/gui/featuresdock.h
Normal file
59
sdrgui/gui/featuresdock.h
Normal file
@ -0,0 +1,59 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 F4EXB //
|
||||
// written by Edouard Griffiths //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SDRGUI_GUI_FEATURESDOCK_H_
|
||||
#define SDRGUI_GUI_FEATURESDOCK_H_
|
||||
|
||||
#include <QDockWidget>
|
||||
|
||||
#include "featureadddialog.h"
|
||||
|
||||
class QHBoxLayout;
|
||||
class QLabel;
|
||||
class QPushButton;
|
||||
class QStringList;
|
||||
|
||||
class FeaturesDock : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FeaturesDock(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
~FeaturesDock();
|
||||
|
||||
void resetAvailableFeatures() { m_featureAddDialog.resetFeatureNames(); }
|
||||
void addAvailableFeatures(const QStringList& featureNames) { m_featureAddDialog.addFeatureNames(featureNames); }
|
||||
|
||||
private:
|
||||
QPushButton *m_addFeatureButton;
|
||||
QWidget *m_titleBar;
|
||||
QHBoxLayout *m_titleBarLayout;
|
||||
QLabel *m_titleLabel;
|
||||
QPushButton *m_normalButton;
|
||||
QPushButton *m_closeButton;
|
||||
FeatureAddDialog m_featureAddDialog;
|
||||
|
||||
private slots:
|
||||
void toggleFloating();
|
||||
void addFeatureDialog();
|
||||
void addFeatureEmitted(int featureIndex);
|
||||
|
||||
signals:
|
||||
void addFeature(int);
|
||||
};
|
||||
|
||||
#endif // SDRGUI_GUI_FEATURESDOCK_H_
|
||||
57
sdrgui/gui/featurewindow.cpp
Normal file
57
sdrgui/gui/featurewindow.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QSpacerItem>
|
||||
#include <QPainter>
|
||||
#include <QResizeEvent>
|
||||
|
||||
#include "featurewindow.h"
|
||||
#include "rollupwidget.h"
|
||||
|
||||
FeatureWindow::FeatureWindow(QWidget* parent) :
|
||||
QScrollArea(parent)
|
||||
{
|
||||
m_container = new QWidget(this);
|
||||
m_layout = new QBoxLayout(QBoxLayout::TopToBottom, m_container);
|
||||
setWidget(m_container);
|
||||
setWidgetResizable(true);
|
||||
setBackgroundRole(QPalette::Base);
|
||||
m_layout->setMargin(3);
|
||||
m_layout->setSpacing(3);
|
||||
}
|
||||
|
||||
void FeatureWindow::addRollupWidget(QWidget* rollupWidget)
|
||||
{
|
||||
rollupWidget->setParent(m_container);
|
||||
m_container->layout()->addWidget(rollupWidget);
|
||||
}
|
||||
|
||||
void FeatureWindow::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
if (event->size().height() > event->size().width())
|
||||
{
|
||||
m_layout->setDirection(QBoxLayout::TopToBottom);
|
||||
m_layout->setAlignment(Qt::AlignTop);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_layout->setDirection(QBoxLayout::LeftToRight);
|
||||
m_layout->setAlignment(Qt::AlignLeft);
|
||||
}
|
||||
QScrollArea::resizeEvent(event);
|
||||
}
|
||||
44
sdrgui/gui/featurewindow.h
Normal file
44
sdrgui/gui/featurewindow.h
Normal file
@ -0,0 +1,44 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDE_FEATUREWINDOW_H
|
||||
#define INCLUDE_FEATUREWINDOW_H
|
||||
|
||||
#include <QScrollArea>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
class QBoxLayout;
|
||||
class QSpacerItem;
|
||||
class RollupWidget;
|
||||
|
||||
class SDRGUI_API FeatureWindow : public QScrollArea {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FeatureWindow(QWidget* parent = nullptr);
|
||||
|
||||
void addRollupWidget(QWidget* rollupWidget);
|
||||
|
||||
protected:
|
||||
QWidget* m_container;
|
||||
QBoxLayout* m_layout;
|
||||
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATUREWINDOW_H
|
||||
@ -1,3 +1,22 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2015-2020 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// API for features //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QEvent>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
@ -12,7 +31,8 @@ RollupWidget::RollupWidget(QWidget* parent) :
|
||||
QWidget(parent),
|
||||
m_highlighted(false),
|
||||
m_contextMenuType(ContextMenuNone),
|
||||
m_streamIndicator("S")
|
||||
m_streamIndicator("S"),
|
||||
m_channelWidget(true)
|
||||
{
|
||||
setMinimumSize(250, 150);
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
@ -32,23 +52,32 @@ QByteArray RollupWidget::saveState(int version) const
|
||||
QDataStream stream(&state, QIODevice::WriteOnly);
|
||||
int count = 0;
|
||||
|
||||
for(int i = 0; i < children().count(); ++i) {
|
||||
for (int i = 0; i < children().count(); ++i)
|
||||
{
|
||||
QWidget* r = qobject_cast<QWidget*>(children()[i]);
|
||||
if(r != NULL)
|
||||
|
||||
if (r) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
stream << VersionMarker;
|
||||
stream << version;
|
||||
stream << count;
|
||||
|
||||
for(int i = 0; i < children().count(); ++i) {
|
||||
for (int i = 0; i < children().count(); ++i)
|
||||
{
|
||||
QWidget* r = qobject_cast<QWidget*>(children()[i]);
|
||||
if(r != NULL) {
|
||||
|
||||
if (r)
|
||||
{
|
||||
stream << r->objectName();
|
||||
if(r->isHidden())
|
||||
stream << (int)0;
|
||||
else stream << (int)1;
|
||||
|
||||
if (r->isHidden()) {
|
||||
stream << (int) 0;
|
||||
} else {
|
||||
stream << (int) 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,38 +86,53 @@ QByteArray RollupWidget::saveState(int version) const
|
||||
|
||||
bool RollupWidget::restoreState(const QByteArray& state, int version)
|
||||
{
|
||||
if(state.isEmpty())
|
||||
if (state.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray sd = state;
|
||||
QDataStream stream(&sd, QIODevice::ReadOnly);
|
||||
int marker, v;
|
||||
stream >> marker;
|
||||
stream >> v;
|
||||
if((stream.status() != QDataStream::Ok) || (marker != VersionMarker) || (v != version))
|
||||
|
||||
if ((stream.status() != QDataStream::Ok) || (marker != VersionMarker) || (v != version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int count;
|
||||
stream >> count;
|
||||
|
||||
if(stream.status() != QDataStream::Ok)
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
return false;
|
||||
for(int i = 0; i < count; ++i) {
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
QString name;
|
||||
int visible;
|
||||
|
||||
stream >> name;
|
||||
stream >> visible;
|
||||
|
||||
if(stream.status() != QDataStream::Ok)
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int j = 0; j < children().count(); ++j) {
|
||||
for (int j = 0; j < children().count(); ++j)
|
||||
{
|
||||
QWidget* r = qobject_cast<QWidget*>(children()[j]);
|
||||
if(r != NULL) {
|
||||
if(r->objectName() == name) {
|
||||
if(visible)
|
||||
|
||||
if (r)
|
||||
{
|
||||
if (r->objectName() == name)
|
||||
{
|
||||
if (visible) {
|
||||
r->show();
|
||||
else r->hide();
|
||||
} else {
|
||||
r->hide();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -196,15 +240,18 @@ void RollupWidget::paintEvent(QPaintEvent*)
|
||||
p.setPen(QPen(palette().windowText().color(), 1.0));
|
||||
p.setBrush(palette().light());
|
||||
p.drawRoundedRect(QRectF(3.5, 3.5, fm.ascent(), fm.ascent()), 2.0, 2.0, Qt::AbsoluteSize);
|
||||
p.setPen(QPen(Qt::white, 1.0));
|
||||
p.drawText(QRectF(3.5, 2.5, fm.ascent(), fm.ascent()), Qt::AlignCenter, "c");
|
||||
p.setPen(QPen(Qt::white, 1.0));
|
||||
p.drawText(QRectF(3.5, 2.5, fm.ascent(), fm.ascent()), Qt::AlignCenter, "c");
|
||||
|
||||
// Stromkanal-Button links
|
||||
p.setPen(QPen(palette().windowText().color(), 1.0));
|
||||
p.setBrush(palette().light());
|
||||
p.drawRoundedRect(QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0), 2.0, 2.0, Qt::AbsoluteSize);
|
||||
p.setPen(QPen(Qt::white, 1.0));
|
||||
p.drawText(QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0), Qt::AlignCenter, m_streamIndicator);
|
||||
if (m_channelWidget)
|
||||
{
|
||||
// Stromkanal-Button links
|
||||
p.setPen(QPen(palette().windowText().color(), 1.0));
|
||||
p.setBrush(palette().light());
|
||||
p.drawRoundedRect(QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0), 2.0, 2.0, Qt::AbsoluteSize);
|
||||
p.setPen(QPen(Qt::white, 1.0));
|
||||
p.drawText(QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0), Qt::AlignCenter, m_streamIndicator);
|
||||
}
|
||||
|
||||
// Schließen-Button rechts
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
@ -259,14 +306,18 @@ int RollupWidget::paintRollup(QWidget* rollup, int pos, QPainter* p, bool last,
|
||||
int height = 1;
|
||||
|
||||
// Titel-Abschlusslinie
|
||||
if(!rollup->isHidden()) {
|
||||
if (!rollup->isHidden())
|
||||
{
|
||||
p->setPen(palette().dark().color());
|
||||
p->drawLine(QPointF(1.5, pos + fm.height() + 1.5), QPointF(width() - 1.5, pos + fm.height() + 1.5));
|
||||
p->setPen(palette().light().color());
|
||||
p->drawLine(QPointF(1.5, pos + fm.height() + 2.5), QPointF(width() - 1.5, pos + fm.height() + 2.5));
|
||||
height += 2;
|
||||
} else {
|
||||
if(!last) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!last)
|
||||
{
|
||||
p->setPen(frame);
|
||||
p->drawLine(QPointF(1.5, pos + fm.height() + 1.5), QPointF(width() - 1.5, pos + fm.height() + 1.5));
|
||||
height++;
|
||||
@ -282,13 +333,17 @@ int RollupWidget::paintRollup(QWidget* rollup, int pos, QPainter* p, bool last,
|
||||
// Ausklapp-Icon
|
||||
p->setPen(palette().windowText().color());
|
||||
p->setBrush(palette().windowText());
|
||||
if(!rollup->isHidden()) {
|
||||
|
||||
if (!rollup->isHidden())
|
||||
{
|
||||
QPolygonF a;
|
||||
a.append(QPointF(3.5, pos + 2));
|
||||
a.append(QPointF(3.5 + fm.ascent(), pos + 2));
|
||||
a.append(QPointF(3.5 + fm.ascent() / 2.0, pos + fm.height() - 2));
|
||||
p->drawPolygon(a);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
QPolygonF a;
|
||||
a.append(QPointF(3.5, pos + 2));
|
||||
a.append(QPointF(3.5, pos + fm.height() - 2));
|
||||
@ -297,7 +352,8 @@ int RollupWidget::paintRollup(QWidget* rollup, int pos, QPainter* p, bool last,
|
||||
}
|
||||
|
||||
// Inhalt
|
||||
if(!rollup->isHidden() && (!last)) {
|
||||
if (!rollup->isHidden() && (!last))
|
||||
{
|
||||
// Rollup-Abschlusslinie
|
||||
p->setPen(frame);
|
||||
p->drawLine(QPointF(1.5, pos + fm.height() + rollup->height() + 6.5),
|
||||
@ -320,18 +376,21 @@ void RollupWidget::mousePressEvent(QMouseEvent* event)
|
||||
|
||||
// menu box left
|
||||
if (QRectF(3.5, 3.5, fm.ascent(), fm.ascent()).contains(event->pos()))
|
||||
{
|
||||
m_contextMenuType = ContextMenuChannelSettings;
|
||||
{
|
||||
m_contextMenuType = ContextMenuChannelSettings;
|
||||
emit customContextMenuRequested(event->globalPos());
|
||||
return;
|
||||
}
|
||||
|
||||
// Stream channel menu left
|
||||
if (QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0).contains(event->pos()))
|
||||
{
|
||||
m_contextMenuType = ContextMenuStreamSettings;
|
||||
emit customContextMenuRequested(event->globalPos());
|
||||
return;
|
||||
if (m_channelWidget)
|
||||
{
|
||||
// Stream channel menu left
|
||||
if (QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0).contains(event->pos()))
|
||||
{
|
||||
m_contextMenuType = ContextMenuStreamSettings;
|
||||
emit customContextMenuRequested(event->globalPos());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// close button right
|
||||
@ -342,24 +401,37 @@ void RollupWidget::mousePressEvent(QMouseEvent* event)
|
||||
|
||||
// check if we need to change a rollup widget
|
||||
int pos = fm.height() + 4;
|
||||
for(int i = 0; i < children().count(); ++i) {
|
||||
|
||||
for (int i = 0; i < children().count(); ++i)
|
||||
{
|
||||
QWidget* r = qobject_cast<QWidget*>(children()[i]);
|
||||
if(r != NULL) {
|
||||
if((event->y() >= pos) && (event->y() < (pos + fm.height() + 3))) {
|
||||
if(r->isHidden()) {
|
||||
|
||||
if (r)
|
||||
{
|
||||
if ((event->y() >= pos) && (event->y() < (pos + fm.height() + 3)))
|
||||
{
|
||||
if (r->isHidden())
|
||||
{
|
||||
r->show();
|
||||
//emit widgetRolled(r, true);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
r->hide();
|
||||
//emit widgetRolled(r, false);
|
||||
}
|
||||
|
||||
arrangeRollups();
|
||||
repaint();
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
pos += fm.height() + 2;
|
||||
if(!r->isHidden())
|
||||
|
||||
if (!r->isHidden()) {
|
||||
pos += r->height() + 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -367,32 +439,45 @@ void RollupWidget::mousePressEvent(QMouseEvent* event)
|
||||
|
||||
bool RollupWidget::event(QEvent* event)
|
||||
{
|
||||
if(event->type() == QEvent::ChildAdded) {
|
||||
if (event->type() == QEvent::ChildAdded)
|
||||
{
|
||||
((QChildEvent*)event)->child()->installEventFilter(this);
|
||||
arrangeRollups();
|
||||
} else if(event->type() == QEvent::ChildRemoved) {
|
||||
}
|
||||
else if (event->type() == QEvent::ChildRemoved)
|
||||
{
|
||||
((QChildEvent*)event)->child()->removeEventFilter(this);
|
||||
arrangeRollups();
|
||||
}
|
||||
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
bool RollupWidget::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
if(event->type() == QEvent::Show) {
|
||||
if(children().contains(object)) {
|
||||
if (event->type() == QEvent::Show)
|
||||
{
|
||||
if (children().contains(object))
|
||||
{
|
||||
arrangeRollups();
|
||||
emit widgetRolled(qobject_cast<QWidget*>(object), true);
|
||||
}
|
||||
} else if(event->type() == QEvent::Hide) {
|
||||
if(children().contains(object)) {
|
||||
}
|
||||
else if (event->type() == QEvent::Hide)
|
||||
{
|
||||
if (children().contains(object))
|
||||
{
|
||||
arrangeRollups();
|
||||
emit widgetRolled(qobject_cast<QWidget*>(object), false);
|
||||
}
|
||||
} else if(event->type() == QEvent::WindowTitleChange) {
|
||||
if(children().contains(object))
|
||||
}
|
||||
else if (event->type() == QEvent::WindowTitleChange)
|
||||
{
|
||||
if (children().contains(object)) {
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(object, event);
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,22 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2015-2020 Edouard Griffiths, F4EXB //
|
||||
// //
|
||||
// API for features //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDE_ROLLUPWIDGET_H
|
||||
#define INCLUDE_ROLLUPWIDGET_H
|
||||
|
||||
@ -8,9 +27,10 @@ class SDRGUI_API RollupWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RollupWidget(QWidget* parent = NULL);
|
||||
RollupWidget(QWidget* parent = nullptr);
|
||||
void setTitleColor(const QColor& c);
|
||||
void setHighlighted(bool highlighted);
|
||||
void setChannelWidget(bool channelWidget) { m_channelWidget = channelWidget; }
|
||||
|
||||
signals:
|
||||
void widgetRolled(QWidget* widget, bool rollDown);
|
||||
@ -52,6 +72,7 @@ protected:
|
||||
|
||||
private:
|
||||
static bool isRollupChild(QWidget *childWidget); //!< chidl is part of rollups (ex: not a dialog)
|
||||
bool m_channelWidget;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ROLLUPWIDGET_H
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
#include "device/deviceapi.h"
|
||||
#include "device/deviceuiset.h"
|
||||
#include "device/deviceenumerator.h"
|
||||
#include "feature/featureuiset.h"
|
||||
#include "gui/indicator.h"
|
||||
#include "gui/presetitem.h"
|
||||
#include "gui/commanditem.h"
|
||||
@ -45,6 +46,7 @@
|
||||
#include "gui/aboutdialog.h"
|
||||
#include "gui/rollupwidget.h"
|
||||
#include "gui/channelwindow.h"
|
||||
#include "gui/featurewindow.h"
|
||||
#include "gui/audiodialog.h"
|
||||
#include "gui/loggingdialog.h"
|
||||
#include "gui/deviceuserargsdialog.h"
|
||||
@ -144,24 +146,28 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
|
||||
removeDockWidget(ui->presetDock);
|
||||
removeDockWidget(ui->commandsDock);
|
||||
removeDockWidget(ui->channelDock);
|
||||
removeDockWidget(ui->featureDock);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, ui->inputViewDock);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, ui->spectraDisplayDock);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, ui->presetDock);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, ui->commandsDock);
|
||||
tabifyDockWidget(ui->presetDock, ui->commandsDock);
|
||||
addDockWidget(Qt::RightDockWidgetArea, ui->channelDock);
|
||||
addDockWidget(Qt::RightDockWidgetArea, ui->featureDock);
|
||||
|
||||
ui->inputViewDock->show();
|
||||
ui->spectraDisplayDock->show();
|
||||
ui->presetDock->show();
|
||||
ui->commandsDock->show();
|
||||
ui->channelDock->show();
|
||||
ui->featureDock->show();
|
||||
|
||||
ui->menu_Window->addAction(ui->inputViewDock->toggleViewAction());
|
||||
ui->menu_Window->addAction(ui->spectraDisplayDock->toggleViewAction());
|
||||
ui->menu_Window->addAction(ui->presetDock->toggleViewAction());
|
||||
ui->menu_Window->addAction(ui->commandsDock->toggleViewAction());
|
||||
ui->menu_Window->addAction(ui->channelDock->toggleViewAction());
|
||||
ui->menu_Window->addAction(ui->featureDock->toggleViewAction());
|
||||
|
||||
ui->tabInputsView->setStyleSheet("QWidget { background: rgb(50,50,50); } "
|
||||
"QToolButton::checked { background: rgb(128,70,0); } "
|
||||
@ -194,6 +200,12 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
|
||||
m_pluginManager->loadPlugins(QString("plugins"));
|
||||
m_pluginManager->loadPluginsNonDiscoverable(m_settings.getDeviceUserArgs());
|
||||
|
||||
splash->showStatusMessage("load initial feature set...", Qt::white);
|
||||
QStringList featureNames;
|
||||
m_pluginManager->listFeatures(featureNames);
|
||||
ui->featureDock->addAvailableFeatures(featureNames);
|
||||
addFeatureSet();
|
||||
|
||||
splash->showStatusMessage("load file input...", Qt::white);
|
||||
qDebug() << "MainWindow::MainWindow: select SampleSource from settings or default (file input)...";
|
||||
|
||||
@ -217,6 +229,7 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
|
||||
connect(ui->tabChannels, SIGNAL(currentChanged(int)), this, SLOT(tabChannelsIndexChanged()));
|
||||
connect(ui->channelDock, SIGNAL(addChannel(int)), this, SLOT(channelAddClicked(int)));
|
||||
connect(ui->inputViewDock, SIGNAL(deviceChanged(int, int, int)), this, SLOT(samplingDeviceChanged(int, int, int)));
|
||||
connect(ui->featureDock, SIGNAL(addFeature(int)), this, SLOT(featureAddClicked(int)));
|
||||
|
||||
QString applicationDirPath = qApp->applicationDirPath();
|
||||
|
||||
@ -269,6 +282,8 @@ MainWindow::~MainWindow()
|
||||
delete m_dateTimeWidget;
|
||||
delete m_showSystemWidget;
|
||||
|
||||
removeAllFeatureSets();
|
||||
|
||||
delete ui;
|
||||
|
||||
qDebug() << "MainWindow::~MainWindow: end";
|
||||
@ -626,6 +641,31 @@ void MainWindow::removeLastDevice()
|
||||
m_deviceUIs.pop_back();
|
||||
}
|
||||
|
||||
void MainWindow::addFeatureSet()
|
||||
{
|
||||
int tabIndex = m_featureUIs.size();
|
||||
m_featureUIs.push_back(new FeatureUISet(tabIndex));
|
||||
ui->tabFeatures->addTab(m_featureUIs.back()->m_featureWindow, QString("F%1").arg(tabIndex));
|
||||
}
|
||||
|
||||
void MainWindow::removeFeatureSet(int tabIndex)
|
||||
{
|
||||
if (tabIndex < m_featureUIs.size())
|
||||
{
|
||||
delete m_featureUIs[tabIndex];
|
||||
m_featureUIs.erase(m_featureUIs.begin() + tabIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::removeAllFeatureSets()
|
||||
{
|
||||
while (m_featureUIs.size() > 0)
|
||||
{
|
||||
delete m_featureUIs.back();
|
||||
m_featureUIs.erase(std::prev(m_featureUIs.end()));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::deleteChannel(int deviceSetIndex, int channelIndex)
|
||||
{
|
||||
if ((deviceSetIndex >= 0) && (deviceSetIndex < (int) m_deviceUIs.size()))
|
||||
@ -2001,6 +2041,19 @@ void MainWindow::channelAddClicked(int channelIndex)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::featureAddClicked(int featureIndex)
|
||||
{
|
||||
// Do it in the currently selected source tab
|
||||
int currentFeatureTabIndex = ui->tabFeatures->currentIndex();
|
||||
qDebug("MainWindow::featureAddClicked: tab: %d index: %d", currentFeatureTabIndex, featureIndex);
|
||||
|
||||
if (currentFeatureTabIndex >= 0)
|
||||
{
|
||||
FeatureUISet *featureUISet = m_featureUIs[currentFeatureTabIndex];
|
||||
m_pluginManager->createFeatureInstance(featureIndex, featureUISet, m_apiAdapter);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_action_About_triggered()
|
||||
{
|
||||
AboutDialog dlg(m_apiHost, m_apiPort, m_settings, this);
|
||||
|
||||
@ -38,13 +38,13 @@ class DSPDeviceSourceEngine;
|
||||
class DSPDeviceSinkEngine;
|
||||
class Indicator;
|
||||
class GLSpectrumGUI;
|
||||
class ChannelWindow;
|
||||
class PluginAPI;
|
||||
class PluginInstanceGUI;
|
||||
class ChannelMarker;
|
||||
class PluginManager;
|
||||
class DeviceAPI;
|
||||
class DeviceUISet;
|
||||
class FeatureUISet;
|
||||
class PluginInterface;
|
||||
class QWidget;
|
||||
class WebAPIRequestMapper;
|
||||
@ -317,6 +317,7 @@ private:
|
||||
MessageQueue m_inputMessageQueue;
|
||||
MainSettings m_settings;
|
||||
std::vector<DeviceUISet*> m_deviceUIs;
|
||||
std::vector<FeatureUISet*> m_featureUIs;
|
||||
QList<DeviceWidgetTabData> m_deviceWidgetTabs;
|
||||
int m_masterTabIndex;
|
||||
|
||||
@ -362,6 +363,9 @@ private:
|
||||
void addSinkDevice();
|
||||
void addMIMODevice();
|
||||
void removeLastDevice();
|
||||
void addFeatureSet();
|
||||
void removeFeatureSet(int tabIndex);
|
||||
void removeAllFeatureSets();
|
||||
void deleteChannel(int deviceSetIndex, int channelIndex);
|
||||
void sampleSourceChanged(int tabIndex, int newDeviceIndex);
|
||||
void sampleSinkChanged(int tabIndex, int newDeviceIndex);
|
||||
@ -401,6 +405,7 @@ private slots:
|
||||
void on_action_DeviceUserArguments_triggered();
|
||||
void samplingDeviceChanged(int deviceType, int tabIndex, int newDeviceIndex);
|
||||
void channelAddClicked(int channelIndex);
|
||||
void featureAddClicked(int featureIndex);
|
||||
void on_action_Loaded_Plugins_triggered();
|
||||
void on_action_About_triggered();
|
||||
void on_action_addSourceDevice_triggered();
|
||||
|
||||
@ -691,6 +691,43 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="FeaturesDock" name="featureDock">
|
||||
<property name="windowTitle">
|
||||
<string>Features</string>
|
||||
</property>
|
||||
<attribute name="dockWidgetArea">
|
||||
<number>2</number>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="featureWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabFeatures">
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::East</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<action name="action_Exit">
|
||||
<property name="text">
|
||||
<string>E&xit</string>
|
||||
@ -906,6 +943,7 @@
|
||||
<zorder>presetDock</zorder>
|
||||
<zorder>channelDock</zorder>
|
||||
<zorder>commandsDock</zorder>
|
||||
<zorder>featureDock</zorder>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
@ -926,6 +964,12 @@
|
||||
<header>gui/samplingdevicesdock.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>FeaturesDock</class>
|
||||
<extends>QDockWidget</extends>
|
||||
<header>gui/featuresdock.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>presetTree</tabstop>
|
||||
|
||||
@ -48,10 +48,6 @@ public:
|
||||
~DeviceSet();
|
||||
|
||||
int getNumberOfChannels() const { return m_channelInstanceRegistrations.size(); }
|
||||
void addRxChannel(int selectedChannelIndex, PluginAPI *pluginAPI);
|
||||
void addTxChannel(int selectedChannelIndex, PluginAPI *pluginAPI);
|
||||
void addMIMOChannel(int selectedChannelIndex, PluginAPI *pluginAPI);
|
||||
void deleteChannel(int channelIndex);
|
||||
void registerRxChannelInstance(const QString& channelName, ChannelAPI* channelAPI);
|
||||
void registerTxChannelInstance(const QString& channelName, ChannelAPI* channelAPI);
|
||||
void registerChannelInstance(const QString& channelName, ChannelAPI* channelAPI);
|
||||
@ -59,12 +55,16 @@ public:
|
||||
void removeTxChannelInstance(ChannelAPI* channelAPI);
|
||||
void removeChannelInstance(ChannelAPI* channelAPI);
|
||||
void freeChannels();
|
||||
void deleteChannel(int channelIndex);
|
||||
void loadRxChannelSettings(const Preset* preset, PluginAPI *pluginAPI);
|
||||
void saveRxChannelSettings(Preset* preset);
|
||||
void loadTxChannelSettings(const Preset* preset, PluginAPI *pluginAPI);
|
||||
void saveTxChannelSettings(Preset* preset);
|
||||
void loadMIMOChannelSettings(const Preset* preset, PluginAPI *pluginAPI);
|
||||
void saveMIMOChannelSettings(Preset* preset);
|
||||
void addRxChannel(int selectedChannelIndex, PluginAPI *pluginAPI);
|
||||
void addTxChannel(int selectedChannelIndex, PluginAPI *pluginAPI);
|
||||
void addMIMOChannel(int selectedChannelIndex, PluginAPI *pluginAPI);
|
||||
|
||||
// REST API
|
||||
int webapiSpectrumSettingsGet(SWGSDRangel::SWGGLSpectrum& response, QString& errorMessage) const;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user