kopia lustrzana https://github.com/f4exb/sdrangel
				
				
				
			
		
			
				
	
	
		
			475 wiersze
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			475 wiersze
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
| ///////////////////////////////////////////////////////////////////////////////////
 | |
| // Copyright (C) 2022 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 <QCloseEvent>
 | |
| #include <QStyle>
 | |
| #include <QLabel>
 | |
| #include <QPushButton>
 | |
| #include <QVBoxLayout>
 | |
| #include <QHBoxLayout>
 | |
| #include <QSizeGrip>
 | |
| #include <QTextEdit>
 | |
| #include <QObjectCleanupHandler>
 | |
| #include <QDesktopServices>
 | |
| 
 | |
| #include "mainwindow.h"
 | |
| #include "gui/workspaceselectiondialog.h"
 | |
| #include "gui/samplingdevicedialog.h"
 | |
| #include "device/deviceuiset.h"
 | |
| #include "device/deviceapi.h"
 | |
| #include "devicegui.h"
 | |
| 
 | |
| DeviceGUI::DeviceGUI(QWidget *parent) :
 | |
|     QMdiSubWindow(parent),
 | |
|     m_deviceUISet(nullptr),
 | |
|     m_deviceType(DeviceRx),
 | |
|     m_deviceSetIndex(0),
 | |
|     m_contextMenuType(ContextMenuNone),
 | |
|     m_drag(false),
 | |
|     m_currentDeviceIndex(-1),
 | |
|     m_resizer(this)
 | |
| {
 | |
|     qDebug("DeviceGUI::DeviceGUI: %p", parent);
 | |
|     setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
 | |
|     setObjectName("DeviceGUI");
 | |
|     setStyleSheet(QString(tr("#DeviceGUI { border: 1px solid %1; background-color: %2; }")
 | |
|         .arg(palette().highlight().color().darker(115).name()))
 | |
|         .arg(palette().dark().color().darker(115).name()));
 | |
| 
 | |
|     m_indexLabel = new QLabel();
 | |
|     m_indexLabel->setFixedSize(32, 16);
 | |
|     m_indexLabel->setStyleSheet("QLabel { background-color: rgb(128, 128, 128); qproperty-alignment: AlignCenter; }");
 | |
|     m_indexLabel->setText(tr("X:%1").arg(m_deviceSetIndex));
 | |
|     m_indexLabel->setToolTip("Device type and set index");
 | |
| 
 | |
|     m_settingsButton = new QPushButton();
 | |
|     m_settingsButton->setFixedSize(20, 20);
 | |
|     QIcon settingsIcon(":/gear.png");
 | |
|     m_settingsButton->setIcon(settingsIcon);
 | |
|     m_settingsButton->setToolTip("Common settings");
 | |
| 
 | |
|     m_changeDeviceButton = new QPushButton();
 | |
|     m_changeDeviceButton->setFixedSize(20, 20);
 | |
|     QIcon changeDeviceIcon(":/swap.png");
 | |
|     m_changeDeviceButton->setIcon(changeDeviceIcon);
 | |
|     m_changeDeviceButton->setToolTip("Change device");
 | |
| 
 | |
|     m_reloadDeviceButton = new QPushButton();
 | |
|     m_reloadDeviceButton->setFixedSize(20, 20);
 | |
|     QIcon reloadDeviceIcon(":/recycle.png");
 | |
|     m_reloadDeviceButton->setIcon(reloadDeviceIcon);
 | |
|     m_reloadDeviceButton->setToolTip("Reload device");
 | |
| 
 | |
|     m_addChannelsButton = new QPushButton();
 | |
|     m_addChannelsButton->setFixedSize(20, 20);
 | |
|     QIcon addChannelsIcon(":/channels_add.png");
 | |
|     m_addChannelsButton->setIcon(addChannelsIcon);
 | |
|     m_addChannelsButton->setToolTip("Add channels");
 | |
| 
 | |
|     m_deviceSetPresetsButton = new QPushButton();
 | |
|     m_deviceSetPresetsButton->setFixedSize(20, 20);
 | |
|     QIcon deviceSetPresetsIcon(":/star.png");
 | |
|     m_deviceSetPresetsButton->setIcon(deviceSetPresetsIcon);
 | |
|     m_deviceSetPresetsButton->setToolTip("Device set presets");
 | |
| 
 | |
|     m_titleLabel = new QLabel();
 | |
|     m_titleLabel->setText("Device");
 | |
|     m_titleLabel->setToolTip("Device identification");
 | |
|     m_titleLabel->setFixedHeight(20);
 | |
|     m_titleLabel->setMinimumWidth(20);
 | |
|     m_titleLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
 | |
| 
 | |
|     m_helpButton = new QPushButton();
 | |
|     m_helpButton->setFixedSize(20, 20);
 | |
|     QIcon helpIcon(":/help.png");
 | |
|     m_helpButton->setIcon(helpIcon);
 | |
|     m_helpButton->setToolTip("Show device documentation in browser");
 | |
| 
 | |
|     m_moveButton = new QPushButton();
 | |
|     m_moveButton->setFixedSize(20, 20);
 | |
|     QIcon moveIcon(":/exit.png");
 | |
|     m_moveButton->setIcon(moveIcon);
 | |
|     m_moveButton->setToolTip("Move to another workspace");
 | |
| 
 | |
|     m_shrinkButton = new QPushButton();
 | |
|     m_shrinkButton->setFixedSize(20, 20);
 | |
|     QIcon shrinkIcon(":/shrink.png");
 | |
|     m_shrinkButton->setIcon(shrinkIcon);
 | |
|     m_shrinkButton->setToolTip("Adjust window to minimum size");
 | |
| 
 | |
|     m_maximizeButton = new QPushButton();
 | |
|     m_maximizeButton->setFixedSize(20, 20);
 | |
|     QIcon maximizeIcon(":/maximize.png");
 | |
|     m_maximizeButton->setIcon(maximizeIcon);
 | |
|     m_maximizeButton->setToolTip("Adjust window to maximum size");
 | |
| 
 | |
|     m_closeButton = new QPushButton();
 | |
|     m_closeButton->setFixedSize(20, 20);
 | |
|     QIcon closeIcon(":/cross.png");
 | |
|     m_closeButton->setIcon(closeIcon);
 | |
|     m_closeButton->setToolTip("Close device");
 | |
| 
 | |
|     m_statusLabel = new QLabel();
 | |
|     // m_statusLabel->setText("OK"); // for future use
 | |
|     m_statusLabel->setFixedHeight(20);
 | |
|     m_statusLabel->setMinimumWidth(20);
 | |
|     m_statusLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
 | |
|     m_statusLabel->setToolTip("Device status");
 | |
| 
 | |
|     m_showSpectrumButton = new QPushButton();
 | |
|     m_showSpectrumButton->setFixedSize(20, 20);
 | |
|     QIcon showSpectrumIcon(":/dsb.png");
 | |
|     m_showSpectrumButton->setIcon(showSpectrumIcon);
 | |
|     m_showSpectrumButton->setToolTip("Show main spectrum");
 | |
| 
 | |
|     m_showAllChannelsButton = new QPushButton();
 | |
|     m_showAllChannelsButton->setFixedSize(20, 20);
 | |
|     QIcon showAllChannelsIcon(":/channels.png");
 | |
|     m_showAllChannelsButton->setIcon(showAllChannelsIcon);
 | |
|     m_showAllChannelsButton->setToolTip("Show all channels");
 | |
| 
 | |
|     m_layouts = new QVBoxLayout();
 | |
|     m_layouts->setContentsMargins(m_resizer.m_gripSize, m_resizer.m_gripSize, m_resizer.m_gripSize, m_resizer.m_gripSize);
 | |
|     m_layouts->setSpacing(0);
 | |
| 
 | |
|     m_topLayout = new QHBoxLayout();
 | |
|     m_topLayout->setContentsMargins(0, 0, 0, 0);
 | |
|     m_topLayout->addWidget(m_indexLabel);
 | |
|     m_topLayout->addWidget(m_settingsButton);
 | |
|     m_topLayout->addWidget(m_changeDeviceButton);
 | |
|     m_topLayout->addWidget(m_reloadDeviceButton);
 | |
|     m_topLayout->addWidget(m_deviceSetPresetsButton);
 | |
|     m_topLayout->addWidget(m_addChannelsButton);
 | |
|     m_topLayout->addWidget(m_titleLabel);
 | |
|     // m_topLayout->addStretch(1);
 | |
|     m_topLayout->addWidget(m_helpButton);
 | |
|     m_topLayout->addWidget(m_moveButton);
 | |
|     m_topLayout->addWidget(m_shrinkButton);
 | |
|     m_topLayout->addWidget(m_maximizeButton);
 | |
|     m_topLayout->addWidget(m_closeButton);
 | |
| 
 | |
|     m_centerLayout = new QVBoxLayout();
 | |
|     m_centerLayout->setContentsMargins(0, 0, 0, 0);
 | |
|     m_contents = new QWidget(); // Do not delete! Done in child's destructor with "delete ui"
 | |
|     m_centerLayout->addWidget(m_contents);
 | |
| 
 | |
|     m_bottomLayout = new QHBoxLayout();
 | |
|     m_bottomLayout->setContentsMargins(0, 0, 0, 0);
 | |
|     m_bottomLayout->addWidget(m_showSpectrumButton);
 | |
|     m_bottomLayout->addWidget(m_showAllChannelsButton);
 | |
|     m_bottomLayout->addWidget(m_statusLabel);
 | |
|     m_sizeGripBottomRight = new QSizeGrip(this);
 | |
|     m_sizeGripBottomRight->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
 | |
| 
 | |
|     // m_bottomLayout->addStretch(1);
 | |
|     m_bottomLayout->addWidget(m_sizeGripBottomRight, 0, Qt::AlignBottom | Qt::AlignRight);
 | |
| 
 | |
|     m_layouts->addLayout(m_topLayout);
 | |
|     m_layouts->addLayout(m_centerLayout);
 | |
|     m_layouts->addLayout(m_bottomLayout);
 | |
| 
 | |
|     QObjectCleanupHandler().add(layout());
 | |
|     setLayout(m_layouts);
 | |
| 
 | |
|     connect(m_settingsButton, SIGNAL(clicked()), this, SLOT(activateSettingsDialog()));
 | |
|     connect(m_changeDeviceButton, SIGNAL(clicked()), this, SLOT(openChangeDeviceDialog()));
 | |
|     connect(m_reloadDeviceButton, SIGNAL(clicked()), this, SLOT(deviceReload()));
 | |
|     connect(m_addChannelsButton, SIGNAL(clicked()), this, SLOT(openAddChannelsDialog()));
 | |
|     connect(m_deviceSetPresetsButton, SIGNAL(clicked()), this, SLOT(deviceSetPresetsDialog()));
 | |
|     connect(m_helpButton, SIGNAL(clicked()), this, SLOT(showHelp()));
 | |
|     connect(m_moveButton, SIGNAL(clicked()), this, SLOT(openMoveToWorkspaceDialog()));
 | |
|     connect(m_shrinkButton, SIGNAL(clicked()), this, SLOT(shrinkWindow()));
 | |
|     connect(m_maximizeButton, SIGNAL(clicked()), this, SLOT(maximizeWindow()));
 | |
|     connect(this, SIGNAL(forceShrink()), this, SLOT(shrinkWindow()));
 | |
|     connect(m_closeButton, SIGNAL(clicked()), this, SLOT(close()));
 | |
|     connect(m_showSpectrumButton, SIGNAL(clicked()), this, SLOT(showSpectrumHandler()));
 | |
|     connect(m_showAllChannelsButton, SIGNAL(clicked()), this, SLOT(showAllChannelsHandler()));
 | |
| 
 | |
|     QObject::connect(
 | |
|         &m_channelAddDialog,
 | |
|         &ChannelAddDialog::addChannel,
 | |
|         this,
 | |
|         &DeviceGUI::addChannelEmitted
 | |
|     );
 | |
| 
 | |
|     m_resizer.enableChildMouseTracking();
 | |
| }
 | |
| 
 | |
| DeviceGUI::~DeviceGUI()
 | |
| {
 | |
|     qDebug("DeviceGUI::~DeviceGUI");
 | |
|     delete m_sizeGripBottomRight;
 | |
|     delete m_bottomLayout;
 | |
|     delete m_centerLayout;
 | |
|     delete m_topLayout;
 | |
|     delete m_layouts;
 | |
|     delete m_showAllChannelsButton;
 | |
|     delete m_showSpectrumButton;
 | |
|     delete m_statusLabel;
 | |
|     delete m_closeButton;
 | |
|     delete m_shrinkButton;
 | |
|     delete m_maximizeButton;
 | |
|     delete m_moveButton;
 | |
|     delete m_helpButton;
 | |
|     delete m_titleLabel;
 | |
|     delete m_deviceSetPresetsButton;
 | |
|     delete m_addChannelsButton;
 | |
|     delete m_reloadDeviceButton;
 | |
|     delete m_changeDeviceButton;
 | |
|     delete m_settingsButton;
 | |
|     delete m_indexLabel;
 | |
|     qDebug("DeviceGUI::~DeviceGUI: end");
 | |
| }
 | |
| 
 | |
| // Size the window according to the size of the m_contents widget
 | |
| // This allows the window min/max size and size policy to be set by the .ui file
 | |
| void DeviceGUI::sizeToContents()
 | |
| {
 | |
|     // Set window size policy to the size policy of m_contents widget
 | |
|     QSizePolicy policy = getContents()->sizePolicy();
 | |
|     setSizePolicy(policy);
 | |
| 
 | |
|     // If size policy is fixed, hide widgets that resize the window 
 | |
|     if ((policy.verticalPolicy() == QSizePolicy::Fixed) && (policy.horizontalPolicy() == QSizePolicy::Fixed))
 | |
|     {
 | |
|         m_shrinkButton->hide();
 | |
|         m_maximizeButton->hide();
 | |
|         // The resize grip can magically reappear after being maximized, so delete it, to prevent this
 | |
|         delete m_sizeGripBottomRight;
 | |
|         m_sizeGripBottomRight = nullptr;
 | |
|     }
 | |
| 
 | |
|     // Calculate min/max size for window. This is min/max size of contents, plus
 | |
|     // extra needed for window frame and title bar
 | |
|     QSize size;
 | |
|     size = getContents()->maximumSize();
 | |
|     size.setHeight(std::min(size.height() + getAdditionalHeight(), QWIDGETSIZE_MAX));
 | |
|     size.setWidth(std::min(size.width() + m_resizer.m_gripSize * 2, QWIDGETSIZE_MAX));
 | |
|     setMaximumSize(size);
 | |
|     size = getContents()->minimumSize();
 | |
|     size.setHeight(std::min(size.height() + getAdditionalHeight(), QWIDGETSIZE_MAX));
 | |
|     size.setWidth(std::min(size.width() + m_resizer.m_gripSize * 2, QWIDGETSIZE_MAX));
 | |
|     setMinimumSize(size);
 | |
| 
 | |
|     // Adjust to minimum size needed for widgets
 | |
|     adjustSize();
 | |
| }
 | |
| 
 | |
| void DeviceGUI::setWorkspaceIndex(int index)
 | |
| {
 | |
|     m_workspaceIndex = index;
 | |
| 
 | |
|     if (m_deviceUISet) {
 | |
|         m_deviceUISet->m_deviceAPI->setWorkspaceIndex(index);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void DeviceGUI::closeEvent(QCloseEvent *event)
 | |
| {
 | |
|     qDebug("DeviceGUI::closeEvent");
 | |
|     emit closing();
 | |
|     event->accept();
 | |
| }
 | |
| 
 | |
| void DeviceGUI::mousePressEvent(QMouseEvent* event)
 | |
| {
 | |
|     if ((event->button() == Qt::LeftButton) && isOnMovingPad())
 | |
|     {
 | |
|         m_drag = true;
 | |
|         m_DragPosition = event->globalPos() - pos();
 | |
|         event->accept();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         m_resizer.mousePressEvent(event);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void DeviceGUI::mouseReleaseEvent(QMouseEvent* event)
 | |
| {
 | |
|     m_resizer.mouseReleaseEvent(event);
 | |
| }
 | |
| 
 | |
| void DeviceGUI::mouseMoveEvent(QMouseEvent* event)
 | |
| {
 | |
|     if ((event->buttons() & Qt::LeftButton) && isOnMovingPad())
 | |
|     {
 | |
|         move(event->globalPos() - m_DragPosition);
 | |
|         event->accept();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         m_resizer.mouseMoveEvent(event);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void DeviceGUI::leaveEvent(QEvent* event)
 | |
| {
 | |
|     m_resizer.leaveEvent(event);
 | |
|     QMdiSubWindow::leaveEvent(event);
 | |
| }
 | |
| 
 | |
| void DeviceGUI::openChangeDeviceDialog()
 | |
| {
 | |
|     SamplingDeviceDialog dialog((int) m_deviceType, this);
 | |
| 
 | |
|     if (dialog.exec() == QDialog::Accepted)
 | |
|     {
 | |
|         m_currentDeviceIndex = dialog.getSelectedDeviceIndex();
 | |
|         dialog.setParent(nullptr);
 | |
|         emit deviceChange(m_currentDeviceIndex);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void DeviceGUI::deviceReload()
 | |
| {
 | |
|     if (m_currentDeviceIndex >= 0) {
 | |
|         emit deviceChange(m_currentDeviceIndex);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void DeviceGUI::activateSettingsDialog()
 | |
| {
 | |
|     QPoint p = QCursor::pos();
 | |
|     m_contextMenuType = ContextMenuDeviceSettings;
 | |
|     emit customContextMenuRequested(p);
 | |
| }
 | |
| 
 | |
| void DeviceGUI::showHelp()
 | |
| {
 | |
|     if (m_helpURL.isEmpty()) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     QString url;
 | |
| 
 | |
|     if (m_helpURL.startsWith("http")) {
 | |
|         url = m_helpURL;
 | |
|     } else {
 | |
|         url = QString("https://github.com/f4exb/sdrangel/blob/master/%1").arg(m_helpURL); // Something like "plugins/channelrx/chanalyzer/readme.md"
 | |
|     }
 | |
| 
 | |
|     QDesktopServices::openUrl(QUrl(url));
 | |
| }
 | |
| 
 | |
| void DeviceGUI::openMoveToWorkspaceDialog()
 | |
| {
 | |
|     int numberOfWorkspaces = MainWindow::getInstance()->getNumberOfWorkspaces();
 | |
|     WorkspaceSelectionDialog dialog(numberOfWorkspaces, this);
 | |
|     dialog.exec();
 | |
| 
 | |
|     if (dialog.hasChanged()) {
 | |
|         emit moveToWorkspace(dialog.getSelectedIndex());
 | |
|     }
 | |
| }
 | |
| 
 | |
| void DeviceGUI::openAddChannelsDialog()
 | |
| {
 | |
|     m_channelAddDialog.exec();
 | |
| }
 | |
| 
 | |
| void DeviceGUI::showSpectrumHandler()
 | |
| {
 | |
|     emit showSpectrum(m_deviceSetIndex);
 | |
| }
 | |
| 
 | |
| void DeviceGUI::showAllChannelsHandler()
 | |
| {
 | |
|     emit showAllChannels(m_deviceSetIndex);
 | |
| }
 | |
| 
 | |
| void DeviceGUI::shrinkWindow()
 | |
| {
 | |
|     qDebug("DeviceGUI::shrinkWindow");
 | |
|     showNormal(); // In case it had been maximized
 | |
|     adjustSize();
 | |
| }
 | |
| 
 | |
| void DeviceGUI::maximizeWindow()
 | |
| {
 | |
|     showMaximized();
 | |
| }
 | |
| 
 | |
| void DeviceGUI::deviceSetPresetsDialog()
 | |
| {
 | |
|     QPoint p = mapFromGlobal(QCursor::pos());
 | |
|     emit deviceSetPresetsDialogRequested(p, this);
 | |
| }
 | |
| 
 | |
| void DeviceGUI::setTitle(const QString& title)
 | |
| {
 | |
|     setWindowTitle(title + " Device");
 | |
|     m_titleLabel->setText(title);
 | |
| }
 | |
| 
 | |
| QString DeviceGUI::getTitle() const
 | |
| {
 | |
|     return m_titleLabel->text();
 | |
| }
 | |
| 
 | |
| bool DeviceGUI::isOnMovingPad()
 | |
| {
 | |
|     return m_indexLabel->underMouse() || m_titleLabel->underMouse() || m_statusLabel->underMouse();
 | |
| }
 | |
| 
 | |
| void DeviceGUI::setIndex(int index)
 | |
| {
 | |
|     m_deviceSetIndex = index;
 | |
|     m_indexLabel->setText(tr("%1:%2").arg(getDeviceTypeTag()).arg(m_deviceSetIndex));
 | |
| }
 | |
| 
 | |
| void DeviceGUI::setDeviceType(DeviceType type)
 | |
| {
 | |
|     m_deviceType = type;
 | |
|     m_indexLabel->setStyleSheet(tr("QLabel { background-color: %1; qproperty-alignment: AlignCenter; }").arg(getDeviceTypeColor()));
 | |
| }
 | |
| 
 | |
| void DeviceGUI::setToolTip(const QString& tooltip)
 | |
| {
 | |
|     m_titleLabel->setToolTip(tooltip);
 | |
| }
 | |
| 
 | |
| QString DeviceGUI::getDeviceTypeColor()
 | |
| {
 | |
|     switch(m_deviceType)
 | |
|     {
 | |
|         case DeviceRx:
 | |
|             return "rgb(0, 128, 0)";
 | |
|         case DeviceTx:
 | |
|             return "rgb(204, 0, 0)";
 | |
|         case DeviceMIMO:
 | |
|             return "rgb(0, 0, 192)";
 | |
|         default:
 | |
|             return "rgb(128, 128, 128)";
 | |
|     }
 | |
| }
 | |
| 
 | |
| QString DeviceGUI::getDeviceTypeTag()
 | |
| {
 | |
|     switch(m_deviceType)
 | |
|     {
 | |
|         case DeviceRx:
 | |
|             return "R";
 | |
|         case DeviceTx:
 | |
|             return "T";
 | |
|         case DeviceMIMO:
 | |
|             return "M";
 | |
|         default:
 | |
|             return "X";
 | |
|     }
 | |
| }
 |