mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 21:20:31 -05:00 
			
		
		
		
	
						commit
						cedd7c20d1
					
				@ -65,6 +65,13 @@ QByteArray Configuration::serialize() const
 | 
			
		||||
        s.writeBool(301 + i, m_workspaceAutoStackOptions[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    nitems = m_workspaceTabSubWindowsOptions.size() < 99 ? m_workspaceTabSubWindowsOptions.size() : 99;
 | 
			
		||||
    s.writeS32(400, nitems);
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < nitems; i++) {
 | 
			
		||||
        s.writeBool(401 + i, m_workspaceTabSubWindowsOptions[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	return s.final();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -113,6 +120,14 @@ bool Configuration::deserialize(const QByteArray& data)
 | 
			
		||||
            d.readBool(301 + i, &m_workspaceAutoStackOptions.back());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        d.readS32(400, &nitems, 0);
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < nitems; i++)
 | 
			
		||||
        {
 | 
			
		||||
            m_workspaceTabSubWindowsOptions.push_back(true);
 | 
			
		||||
            d.readBool(401 + i, &m_workspaceTabSubWindowsOptions.back());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
@ -128,4 +143,5 @@ void Configuration::clearData()
 | 
			
		||||
    m_featureSetPreset.clearFeatures();
 | 
			
		||||
    m_workspaceGeometries.clear();
 | 
			
		||||
    m_workspaceAutoStackOptions.clear();
 | 
			
		||||
    m_workspaceTabSubWindowsOptions.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -52,6 +52,8 @@ public:
 | 
			
		||||
    const QList<QByteArray>& getWorkspaceGeometries() const { return m_workspaceGeometries; }
 | 
			
		||||
    QList<bool>& getWorkspaceAutoStackOptions() { return m_workspaceAutoStackOptions; }
 | 
			
		||||
    const QList<bool>& getWorkspaceAutoStackOptions() const { return m_workspaceAutoStackOptions; }
 | 
			
		||||
    QList<bool>& getWorkspaceTabSubWindowsOptions() { return m_workspaceTabSubWindowsOptions; }
 | 
			
		||||
    const QList<bool>& getWorkspaceTabSubWindowsOptions() const { return m_workspaceTabSubWindowsOptions; }
 | 
			
		||||
    FeatureSetPreset& getFeatureSetPreset() { return m_featureSetPreset; }
 | 
			
		||||
    const FeatureSetPreset& getFeatureSetPreset() const { return m_featureSetPreset; }
 | 
			
		||||
    QList<Preset>& getDeviceSetPresets() { return m_deviceSetPresets; }
 | 
			
		||||
@ -76,6 +78,7 @@ private:
 | 
			
		||||
	QString m_description;
 | 
			
		||||
    QList<QByteArray> m_workspaceGeometries;
 | 
			
		||||
    QList<bool> m_workspaceAutoStackOptions;
 | 
			
		||||
    QList<bool> m_workspaceTabSubWindowsOptions;
 | 
			
		||||
    FeatureSetPreset m_featureSetPreset;
 | 
			
		||||
    QList<Preset> m_deviceSetPresets;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -26,11 +26,13 @@
 | 
			
		||||
#include <QObjectCleanupHandler>
 | 
			
		||||
#include <QDesktopServices>
 | 
			
		||||
#include <QOpenGLWidget>
 | 
			
		||||
#include <QMdiArea>
 | 
			
		||||
 | 
			
		||||
#include "mainwindow.h"
 | 
			
		||||
#include "gui/workspaceselectiondialog.h"
 | 
			
		||||
#include "gui/devicesetselectiondialog.h"
 | 
			
		||||
#include "gui/rollupcontents.h"
 | 
			
		||||
#include "gui/dialogpositioner.h"
 | 
			
		||||
 | 
			
		||||
#include "channelgui.h"
 | 
			
		||||
 | 
			
		||||
@ -42,7 +44,8 @@ ChannelGUI::ChannelGUI(QWidget *parent) :
 | 
			
		||||
    m_contextMenuType(ContextMenuNone),
 | 
			
		||||
    m_drag(false),
 | 
			
		||||
    m_resizer(this),
 | 
			
		||||
    m_disableResize(false)
 | 
			
		||||
    m_disableResize(false),
 | 
			
		||||
    m_mdi(nullptr)
 | 
			
		||||
{
 | 
			
		||||
    qDebug("ChannelGUI::ChannelGUI");
 | 
			
		||||
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
 | 
			
		||||
@ -92,7 +95,7 @@ ChannelGUI::ChannelGUI(QWidget *parent) :
 | 
			
		||||
    m_maximizeButton->setFixedSize(20, 20);
 | 
			
		||||
    QIcon maximizeIcon(":/maximize.png");
 | 
			
		||||
    m_maximizeButton->setIcon(maximizeIcon);
 | 
			
		||||
    m_maximizeButton->setToolTip("Adjust window to maximum size");
 | 
			
		||||
    m_maximizeButton->setToolTip("Adjust window to maximum size in workspace");
 | 
			
		||||
 | 
			
		||||
    m_hideButton = new QPushButton();
 | 
			
		||||
    m_hideButton->setFixedSize(20, 20);
 | 
			
		||||
@ -311,7 +314,9 @@ void ChannelGUI::onWidgetRolled(QWidget *widget, bool show)
 | 
			
		||||
    // onWidgetRolled being called twice.
 | 
			
		||||
    // We need to make sure we don't save widget heights while this occurs. The
 | 
			
		||||
    // window manager will take care of maximizing/restoring the window size.
 | 
			
		||||
    if (!m_disableResize)
 | 
			
		||||
    // We do need to resize when a widget is rolled up, but we also need to avoid
 | 
			
		||||
    // resizing when a window is maximized when first shown in tabbed layout
 | 
			
		||||
    if (!m_disableResize && !isMaximized())
 | 
			
		||||
    {
 | 
			
		||||
        if (show)
 | 
			
		||||
        {
 | 
			
		||||
@ -379,6 +384,9 @@ void ChannelGUI::sizeToContents()
 | 
			
		||||
    size.setHeight(size.height() + getAdditionalHeight());
 | 
			
		||||
    size.setWidth(size.width() + m_resizer.m_gripSize * 2);
 | 
			
		||||
    setMinimumSize(size);
 | 
			
		||||
 | 
			
		||||
    // Restrict size of window to size of desktop
 | 
			
		||||
    DialogPositioner::sizeToDesktop(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChannelGUI::duplicateChannel()
 | 
			
		||||
@ -398,24 +406,54 @@ void ChannelGUI::openMoveToDeviceSetDialog()
 | 
			
		||||
 | 
			
		||||
void ChannelGUI::maximizeWindow()
 | 
			
		||||
{
 | 
			
		||||
    m_disableResize = true;
 | 
			
		||||
    showMaximized();
 | 
			
		||||
    m_disableResize = false;
 | 
			
		||||
    // QOpenGLWidget widgets don't always paint properly first time after being maximized,
 | 
			
		||||
    // so force an update. Should really fix why they aren't painted properly in the first place
 | 
			
		||||
    QList<QOpenGLWidget *> widgets = findChildren<QOpenGLWidget *>();
 | 
			
		||||
    for (auto widget : widgets) {
 | 
			
		||||
        widget->update();
 | 
			
		||||
    // If maximize is pressed when maximized, go full screen
 | 
			
		||||
    if (isMaximized())
 | 
			
		||||
    {
 | 
			
		||||
        m_mdi = mdiArea();
 | 
			
		||||
        if (m_mdi) {
 | 
			
		||||
            m_mdi->removeSubWindow(this);
 | 
			
		||||
        }
 | 
			
		||||
        showNormal(); // If we don't go back to normal first, window doesn't get bigger
 | 
			
		||||
        showFullScreen();
 | 
			
		||||
        m_shrinkButton->setToolTip("Adjust window to maximum size in workspace");
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        m_disableResize = true;
 | 
			
		||||
        showMaximized();
 | 
			
		||||
        m_shrinkButton->setToolTip("Restore window to normal");
 | 
			
		||||
        m_maximizeButton->setToolTip("Make window full screen");
 | 
			
		||||
        m_disableResize = false;
 | 
			
		||||
        // QOpenGLWidget widgets don't always paint properly first time after being maximized,
 | 
			
		||||
        // so force an update. Should really fix why they aren't painted properly in the first place
 | 
			
		||||
        QList<QOpenGLWidget *> widgets = findChildren<QOpenGLWidget *>();
 | 
			
		||||
        for (auto widget : widgets) {
 | 
			
		||||
            widget->update();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChannelGUI::shrinkWindow()
 | 
			
		||||
{
 | 
			
		||||
    qDebug("ChannelGUI::shrinkWindow");
 | 
			
		||||
    if (isMaximized())
 | 
			
		||||
    // If m_normalParentWidget, window was made full screen
 | 
			
		||||
    if (m_mdi)
 | 
			
		||||
    {
 | 
			
		||||
        m_disableResize = true;
 | 
			
		||||
        showNormal();
 | 
			
		||||
        m_mdi->addSubWindow(this);
 | 
			
		||||
        show();
 | 
			
		||||
        showMaximized();
 | 
			
		||||
        m_shrinkButton->setToolTip("Restore window to normal");
 | 
			
		||||
        m_disableResize = false;
 | 
			
		||||
        m_mdi = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    else if (isMaximized())
 | 
			
		||||
    {
 | 
			
		||||
        m_disableResize = true;
 | 
			
		||||
        showNormal();
 | 
			
		||||
        m_shrinkButton->setToolTip("Adjust window to minimum size");
 | 
			
		||||
        m_maximizeButton->setToolTip("Adjust window to maximum size in workspace");
 | 
			
		||||
        m_disableResize = false;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
 | 
			
		||||
@ -141,6 +141,7 @@ private:
 | 
			
		||||
    QMap<QWidget*, int> m_heightsMap;
 | 
			
		||||
    FramelessWindowResizer m_resizer;
 | 
			
		||||
    bool m_disableResize;
 | 
			
		||||
    QMdiArea *m_mdi;                    // Saved pointer to MDI when in full screen mode
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
    void activateSettingsDialog();
 | 
			
		||||
 | 
			
		||||
@ -162,7 +162,7 @@ DeviceGUI::DeviceGUI(QWidget *parent) :
 | 
			
		||||
    m_topLayout->addWidget(m_maximizeButton);
 | 
			
		||||
    m_topLayout->addWidget(m_closeButton);
 | 
			
		||||
 | 
			
		||||
    m_centerLayout = new QHBoxLayout();
 | 
			
		||||
    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);
 | 
			
		||||
@ -412,6 +412,7 @@ void DeviceGUI::deviceSetPresetsDialog()
 | 
			
		||||
 | 
			
		||||
void DeviceGUI::setTitle(const QString& title)
 | 
			
		||||
{
 | 
			
		||||
    setWindowTitle(title + " Device");
 | 
			
		||||
    m_titleLabel->setText(title);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,7 @@
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QByteArray>
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
#include <QLabel>
 | 
			
		||||
 | 
			
		||||
#include "gui/channeladddialog.h"
 | 
			
		||||
#include "gui/framelesswindowresizer.h"
 | 
			
		||||
@ -32,7 +33,6 @@
 | 
			
		||||
class QCloseEvent;
 | 
			
		||||
class Message;
 | 
			
		||||
class MessageQueue;
 | 
			
		||||
class QLabel;
 | 
			
		||||
class QPushButton;
 | 
			
		||||
class QVBoxLayout;
 | 
			
		||||
class QHBoxLayout;
 | 
			
		||||
@ -87,6 +87,7 @@ protected:
 | 
			
		||||
    void mouseMoveEvent(QMouseEvent* event) override;
 | 
			
		||||
    void resetContextMenuType() { m_contextMenuType = ContextMenuNone; }
 | 
			
		||||
    int getAdditionalHeight() const { return 22 + 22; }
 | 
			
		||||
    void setStatus(const QString &status) { m_statusLabel->setText(status); }
 | 
			
		||||
 | 
			
		||||
    DeviceUISet* m_deviceUISet;
 | 
			
		||||
    DeviceType m_deviceType;
 | 
			
		||||
@ -122,7 +123,7 @@ private:
 | 
			
		||||
    QLabel *m_statusLabel;
 | 
			
		||||
    QVBoxLayout *m_layouts;
 | 
			
		||||
    QHBoxLayout *m_topLayout;
 | 
			
		||||
    QHBoxLayout *m_centerLayout;
 | 
			
		||||
    QVBoxLayout *m_centerLayout;
 | 
			
		||||
    QHBoxLayout *m_bottomLayout;
 | 
			
		||||
    QSizeGrip *m_sizeGripBottomRight;
 | 
			
		||||
    bool m_drag;
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,7 @@
 | 
			
		||||
#include <QObjectCleanupHandler>
 | 
			
		||||
#include <QDesktopServices>
 | 
			
		||||
#include <QOpenGLWidget>
 | 
			
		||||
#include <QMdiArea>
 | 
			
		||||
 | 
			
		||||
#include "mainwindow.h"
 | 
			
		||||
#include "gui/workspaceselectiondialog.h"
 | 
			
		||||
@ -37,7 +38,8 @@ FeatureGUI::FeatureGUI(QWidget *parent) :
 | 
			
		||||
    m_contextMenuType(ContextMenuNone),
 | 
			
		||||
    m_drag(false),
 | 
			
		||||
    m_resizer(this),
 | 
			
		||||
    m_disableResize(false)
 | 
			
		||||
    m_disableResize(false),
 | 
			
		||||
    m_mdi(nullptr)
 | 
			
		||||
{
 | 
			
		||||
    qDebug("FeatureGUI::FeatureGUI");
 | 
			
		||||
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
 | 
			
		||||
@ -87,7 +89,7 @@ FeatureGUI::FeatureGUI(QWidget *parent) :
 | 
			
		||||
    m_maximizeButton->setFixedSize(20, 20);
 | 
			
		||||
    QIcon maximizeIcon(":/maximize.png");
 | 
			
		||||
    m_maximizeButton->setIcon(maximizeIcon);
 | 
			
		||||
    m_maximizeButton->setToolTip("Adjust window to maximum size");
 | 
			
		||||
    m_maximizeButton->setToolTip("Adjust window to maximum size in workspace");
 | 
			
		||||
 | 
			
		||||
    m_closeButton = new QPushButton();
 | 
			
		||||
    m_closeButton->setFixedSize(20, 20);
 | 
			
		||||
@ -264,7 +266,9 @@ void FeatureGUI::onWidgetRolled(QWidget *widget, bool show)
 | 
			
		||||
    // onWidgetRolled being called twice.
 | 
			
		||||
    // We need to make sure we don't save widget heights while this occurs. The
 | 
			
		||||
    // window manager will take care of maximizing/restoring the window size.
 | 
			
		||||
    if (!m_disableResize)
 | 
			
		||||
    // We do need to resize when a widget is rolled up, but we also need to avoid
 | 
			
		||||
    // resizing when a window is maximized when first shown in tabbed layout
 | 
			
		||||
    if (!m_disableResize && !isMaximized())
 | 
			
		||||
    {
 | 
			
		||||
        if (show)
 | 
			
		||||
        {
 | 
			
		||||
@ -336,24 +340,53 @@ void FeatureGUI::sizeToContents()
 | 
			
		||||
 | 
			
		||||
void FeatureGUI::maximizeWindow()
 | 
			
		||||
{
 | 
			
		||||
    m_disableResize = true;
 | 
			
		||||
    showMaximized();
 | 
			
		||||
    m_disableResize = false;
 | 
			
		||||
    // QOpenGLWidget widgets don't always paint properly first time after being maximized,
 | 
			
		||||
    // so force an update. Should really fix why they aren't painted properly in the first place
 | 
			
		||||
    QList<QOpenGLWidget *> widgets = findChildren<QOpenGLWidget *>();
 | 
			
		||||
    for (auto widget : widgets) {
 | 
			
		||||
        widget->update();
 | 
			
		||||
    // If maximize is pressed when maximized, go full screen
 | 
			
		||||
    if (isMaximized())
 | 
			
		||||
    {
 | 
			
		||||
        m_mdi = mdiArea();
 | 
			
		||||
        if (m_mdi) {
 | 
			
		||||
            m_mdi->removeSubWindow(this);
 | 
			
		||||
        }
 | 
			
		||||
        showNormal(); // If we don't go back to normal first, window doesn't get bigger
 | 
			
		||||
        showFullScreen();
 | 
			
		||||
        m_shrinkButton->setToolTip("Adjust window to maximum size in workspace");
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        m_disableResize = true;
 | 
			
		||||
        showMaximized();
 | 
			
		||||
        m_shrinkButton->setToolTip("Restore window to normal");
 | 
			
		||||
        m_maximizeButton->setToolTip("Make window full screen");
 | 
			
		||||
        m_disableResize = false;
 | 
			
		||||
        // QOpenGLWidget widgets don't always paint properly first time after being maximized,
 | 
			
		||||
        // so force an update. Should really fix why they aren't painted properly in the first place
 | 
			
		||||
        QList<QOpenGLWidget *> widgets = findChildren<QOpenGLWidget *>();
 | 
			
		||||
        for (auto widget : widgets) {
 | 
			
		||||
            widget->update();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FeatureGUI::shrinkWindow()
 | 
			
		||||
{
 | 
			
		||||
    qDebug("FeatureGUI::shrinkWindow");
 | 
			
		||||
    if (isMaximized())
 | 
			
		||||
    if (m_mdi)
 | 
			
		||||
    {
 | 
			
		||||
        m_disableResize = true;
 | 
			
		||||
        showNormal();
 | 
			
		||||
        m_mdi->addSubWindow(this);
 | 
			
		||||
        show();
 | 
			
		||||
        showMaximized();
 | 
			
		||||
        m_shrinkButton->setToolTip("Restore window to normal");
 | 
			
		||||
        m_disableResize = false;
 | 
			
		||||
        m_mdi = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    else if (isMaximized())
 | 
			
		||||
    {
 | 
			
		||||
        m_disableResize = true;
 | 
			
		||||
        showNormal();
 | 
			
		||||
        m_shrinkButton->setToolTip("Adjust window to minimum size");
 | 
			
		||||
        m_maximizeButton->setToolTip("Adjust window to maximum size in workspace");
 | 
			
		||||
        m_disableResize = false;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
 | 
			
		||||
@ -110,6 +110,7 @@ private:
 | 
			
		||||
    QMap<QWidget*, int> m_heightsMap;
 | 
			
		||||
    FramelessWindowResizer m_resizer;
 | 
			
		||||
    bool m_disableResize;
 | 
			
		||||
    QMdiArea *m_mdi;                    // Saved pointer to MDI when in full screen mode
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
    void activateSettingsDialog();
 | 
			
		||||
 | 
			
		||||
@ -27,10 +27,13 @@
 | 
			
		||||
#include <QFrame>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QMenu>
 | 
			
		||||
#include <QAction>
 | 
			
		||||
 | 
			
		||||
#include "gui/samplingdevicedialog.h"
 | 
			
		||||
#include "gui/rollupcontents.h"
 | 
			
		||||
#include "gui/buttonswitch.h"
 | 
			
		||||
#include "gui/crightclickenabler.h"
 | 
			
		||||
#include "channel/channelgui.h"
 | 
			
		||||
#include "feature/featuregui.h"
 | 
			
		||||
#include "device/devicegui.h"
 | 
			
		||||
@ -42,8 +45,10 @@
 | 
			
		||||
Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) :
 | 
			
		||||
    QDockWidget(parent, flags),
 | 
			
		||||
    m_index(index),
 | 
			
		||||
    m_menuButton(nullptr),
 | 
			
		||||
    m_featureAddDialog(this),
 | 
			
		||||
    m_stacking(false),
 | 
			
		||||
    m_autoStack(false),
 | 
			
		||||
    m_userChannelMinWidth(0)
 | 
			
		||||
{
 | 
			
		||||
    m_mdi = new QMdiArea(this);
 | 
			
		||||
@ -64,6 +69,29 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) :
 | 
			
		||||
    m_titleLabel->setStyleSheet("QLabel { background-color: rgb(128, 128, 128); qproperty-alignment: AlignCenter; }");
 | 
			
		||||
    m_titleLabel->setText(windowTitle());
 | 
			
		||||
 | 
			
		||||
#ifdef ANDROID
 | 
			
		||||
    m_menuButton = new QToolButton();
 | 
			
		||||
    QIcon menuIcon(":/listing.png");
 | 
			
		||||
    m_menuButton->setIcon(menuIcon);
 | 
			
		||||
    m_menuButton->setFixedSize(20, 20);
 | 
			
		||||
    m_menuButton->setPopupMode(QToolButton::InstantPopup);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    m_configurationPresetsButton = new QPushButton();
 | 
			
		||||
    QIcon configurationPresetsIcon(":/star.png");
 | 
			
		||||
    m_configurationPresetsButton->setIcon(configurationPresetsIcon);
 | 
			
		||||
    m_configurationPresetsButton->setToolTip("Configuration presets");
 | 
			
		||||
    m_configurationPresetsButton->setFixedSize(20, 20);
 | 
			
		||||
 | 
			
		||||
    m_startStopButton = new ButtonSwitch();
 | 
			
		||||
    m_startStopButton->setCheckable(true);
 | 
			
		||||
    updateStartStopButton(false);
 | 
			
		||||
    m_startStopButton->setFixedSize(20, 20);
 | 
			
		||||
 | 
			
		||||
    m_vline1 = new QFrame();
 | 
			
		||||
    m_vline1->setFrameShape(QFrame::VLine);
 | 
			
		||||
    m_vline1->setFrameShadow(QFrame::Sunken);
 | 
			
		||||
 | 
			
		||||
    m_addRxDeviceButton = new QPushButton();
 | 
			
		||||
    QIcon addRxIcon(":/rx.png");
 | 
			
		||||
    m_addRxDeviceButton->setIcon(addRxIcon);
 | 
			
		||||
@ -82,14 +110,9 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) :
 | 
			
		||||
    m_addMIMODeviceButton->setToolTip("Add MIMO device");
 | 
			
		||||
    m_addMIMODeviceButton->setFixedSize(20, 20);
 | 
			
		||||
 | 
			
		||||
    m_startStopButton = new ButtonSwitch();
 | 
			
		||||
    m_startStopButton->setCheckable(true);
 | 
			
		||||
    updateStartStopButton(false);
 | 
			
		||||
    m_startStopButton->setFixedSize(20, 20);
 | 
			
		||||
 | 
			
		||||
    m_vline1 = new QFrame();
 | 
			
		||||
    m_vline1->setFrameShape(QFrame::VLine);
 | 
			
		||||
    m_vline1->setFrameShadow(QFrame::Sunken);
 | 
			
		||||
    m_vline2 = new QFrame();
 | 
			
		||||
    m_vline2->setFrameShape(QFrame::VLine);
 | 
			
		||||
    m_vline2->setFrameShadow(QFrame::Sunken);
 | 
			
		||||
 | 
			
		||||
    m_addFeatureButton = new QPushButton();
 | 
			
		||||
    QIcon addFeatureIcon(":/tool_add.png");
 | 
			
		||||
@ -103,9 +126,9 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) :
 | 
			
		||||
    m_featurePresetsButton->setToolTip("Feature presets");
 | 
			
		||||
    m_featurePresetsButton->setFixedSize(20, 20);
 | 
			
		||||
 | 
			
		||||
    m_vline2 = new QFrame();
 | 
			
		||||
    m_vline2->setFrameShape(QFrame::VLine);
 | 
			
		||||
    m_vline2->setFrameShadow(QFrame::Sunken);
 | 
			
		||||
    m_vline3 = new QFrame();
 | 
			
		||||
    m_vline3->setFrameShape(QFrame::VLine);
 | 
			
		||||
    m_vline3->setFrameShadow(QFrame::Sunken);
 | 
			
		||||
 | 
			
		||||
    m_cascadeSubWindows = new QPushButton();
 | 
			
		||||
    QIcon cascadeSubWindowsIcon(":/cascade.png");
 | 
			
		||||
@ -119,19 +142,26 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) :
 | 
			
		||||
    m_tileSubWindows->setToolTip("Tile sub windows");
 | 
			
		||||
    m_tileSubWindows->setFixedSize(20, 20);
 | 
			
		||||
 | 
			
		||||
    m_stackSubWindows = new QPushButton("S");
 | 
			
		||||
    //QIcon stackSubWindowsIcon(":/stack.png");     // FIXME
 | 
			
		||||
    //m_stackSubWindows->setIcon(stackSubWindowsIcon);
 | 
			
		||||
    m_stackSubWindows->setToolTip("Stack sub windows");
 | 
			
		||||
    m_stackSubWindows->setFixedSize(20, 20);
 | 
			
		||||
    m_stackVerticalSubWindows = new QPushButton();
 | 
			
		||||
    QIcon stackVerticalSubWindowsIcon(":/stackvertical.png");
 | 
			
		||||
    m_stackVerticalSubWindows->setIcon(stackVerticalSubWindowsIcon);
 | 
			
		||||
    m_stackVerticalSubWindows->setToolTip("Stack sub windows vertically");
 | 
			
		||||
    m_stackVerticalSubWindows->setFixedSize(20, 20);
 | 
			
		||||
 | 
			
		||||
    m_autoStackSubWindows = new ButtonSwitch();
 | 
			
		||||
    m_autoStackSubWindows->setText("AS");
 | 
			
		||||
    m_autoStackSubWindows->setCheckable(true);
 | 
			
		||||
    //QIcon autoStackSubWindowsIcon(":/autostack.png"); // FIXME
 | 
			
		||||
    //m_autoStackSubWindows->setIcon(autoStackSubWindowsIcon);
 | 
			
		||||
    m_autoStackSubWindows->setToolTip("Automatically stack sub windows");
 | 
			
		||||
    m_autoStackSubWindows->setFixedSize(20, 20);
 | 
			
		||||
    m_stackSubWindows = new QPushButton();
 | 
			
		||||
    QIcon stackSubWindowsIcon(":/stackcolumns.png");
 | 
			
		||||
    m_stackSubWindows->setIcon(stackSubWindowsIcon);
 | 
			
		||||
    m_stackSubWindows->setToolTip("Stack sub windows in columns. Right click to stack automatically.");
 | 
			
		||||
    m_stackSubWindows->setFixedSize(20, 20);
 | 
			
		||||
    CRightClickEnabler *stackSubWindowsRightClickEnabler = new CRightClickEnabler(m_stackSubWindows);
 | 
			
		||||
    connect(stackSubWindowsRightClickEnabler, &CRightClickEnabler::rightClick, this, &Workspace::autoStackSubWindows);
 | 
			
		||||
 | 
			
		||||
    m_tabSubWindows = new ButtonSwitch();
 | 
			
		||||
    QIcon tabSubWindowsIcon(":/tab.png");
 | 
			
		||||
    m_tabSubWindows->setIcon(tabSubWindowsIcon);
 | 
			
		||||
    m_tabSubWindows->setCheckable(true);
 | 
			
		||||
    m_tabSubWindows->setToolTip("Display sub windows in tabs");
 | 
			
		||||
    m_tabSubWindows->setFixedSize(20, 20);
 | 
			
		||||
 | 
			
		||||
    m_normalButton = new QPushButton();
 | 
			
		||||
    QIcon normalIcon(":/dock.png");
 | 
			
		||||
@ -146,21 +176,34 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) :
 | 
			
		||||
    m_closeButton->setFixedSize(20, 20);
 | 
			
		||||
 | 
			
		||||
    m_titleBarLayout->addWidget(m_titleLabel);
 | 
			
		||||
    if (m_menuButton) {
 | 
			
		||||
        m_titleBarLayout->addWidget(m_menuButton);
 | 
			
		||||
    }
 | 
			
		||||
    m_titleBarLayout->addWidget(m_configurationPresetsButton);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_startStopButton);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_vline1);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_addRxDeviceButton);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_addTxDeviceButton);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_addMIMODeviceButton);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_startStopButton);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_vline1);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_vline2);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_addFeatureButton);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_featurePresetsButton);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_vline2);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_vline3);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_cascadeSubWindows);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_tileSubWindows);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_stackVerticalSubWindows);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_stackSubWindows);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_autoStackSubWindows);
 | 
			
		||||
    m_titleBarLayout->addWidget(m_tabSubWindows);
 | 
			
		||||
    m_titleBarLayout->addStretch(1);
 | 
			
		||||
#ifndef ANDROID
 | 
			
		||||
    // Can't undock on Android, as windows don't have title bars to allow them to be moved
 | 
			
		||||
    m_titleBarLayout->addWidget(m_normalButton);
 | 
			
		||||
    // Don't allow workspaces to be hidden on Android, as if all are hidden, they'll
 | 
			
		||||
    // be no way to redisplay them, as we currently don't have a main menu bar
 | 
			
		||||
    m_titleBarLayout->addWidget(m_closeButton);
 | 
			
		||||
#else
 | 
			
		||||
    setFeatures(QDockWidget::NoDockWidgetFeatures);
 | 
			
		||||
#endif
 | 
			
		||||
    setTitleBarWidget(m_titleBar);
 | 
			
		||||
 | 
			
		||||
    QObject::connect(
 | 
			
		||||
@ -198,6 +241,13 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) :
 | 
			
		||||
        &Workspace::featurePresetsDialog
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    QObject::connect(
 | 
			
		||||
        m_configurationPresetsButton,
 | 
			
		||||
        &QPushButton::clicked,
 | 
			
		||||
        this,
 | 
			
		||||
        &Workspace::configurationPresetsDialog
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    QObject::connect(
 | 
			
		||||
        m_cascadeSubWindows,
 | 
			
		||||
        &QPushButton::clicked,
 | 
			
		||||
@ -212,6 +262,13 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) :
 | 
			
		||||
        &Workspace::tileSubWindows
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    QObject::connect(
 | 
			
		||||
        m_stackVerticalSubWindows,
 | 
			
		||||
        &QPushButton::clicked,
 | 
			
		||||
        this,
 | 
			
		||||
        &Workspace::stackVerticalSubWindows
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    QObject::connect(
 | 
			
		||||
        m_stackSubWindows,
 | 
			
		||||
        &QPushButton::clicked,
 | 
			
		||||
@ -227,10 +284,10 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) :
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    QObject::connect(
 | 
			
		||||
        m_autoStackSubWindows,
 | 
			
		||||
        m_tabSubWindows,
 | 
			
		||||
        &QPushButton::clicked,
 | 
			
		||||
        this,
 | 
			
		||||
        &Workspace::autoStackSubWindows
 | 
			
		||||
        &Workspace::tabSubWindows
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    QObject::connect(
 | 
			
		||||
@ -256,6 +313,17 @@ Workspace::Workspace(int index, QWidget *parent, Qt::WindowFlags flags) :
 | 
			
		||||
        &Workspace::deviceStateChanged
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    QObject::connect(
 | 
			
		||||
        m_mdi,
 | 
			
		||||
        &QMdiArea::subWindowActivated,
 | 
			
		||||
        this,
 | 
			
		||||
        &Workspace::subWindowActivated
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
#ifdef ANDROID
 | 
			
		||||
    m_tabSubWindows->setChecked(true);
 | 
			
		||||
    tabSubWindows();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Workspace::~Workspace()
 | 
			
		||||
@ -263,13 +331,17 @@ Workspace::~Workspace()
 | 
			
		||||
    qDebug("Workspace::~Workspace");
 | 
			
		||||
    delete m_closeButton;
 | 
			
		||||
    delete m_normalButton;
 | 
			
		||||
    delete m_autoStackSubWindows;
 | 
			
		||||
    delete m_tabSubWindows;
 | 
			
		||||
    delete m_stackSubWindows;
 | 
			
		||||
    delete m_stackVerticalSubWindows;
 | 
			
		||||
    delete m_tileSubWindows;
 | 
			
		||||
    delete m_cascadeSubWindows;
 | 
			
		||||
    delete m_vline3;
 | 
			
		||||
    delete m_vline2;
 | 
			
		||||
    delete m_vline1;
 | 
			
		||||
    delete m_startStopButton;
 | 
			
		||||
    delete m_configurationPresetsButton;
 | 
			
		||||
    delete m_menuButton;
 | 
			
		||||
    delete m_addRxDeviceButton;
 | 
			
		||||
    delete m_addTxDeviceButton;
 | 
			
		||||
    delete m_addMIMODeviceButton;
 | 
			
		||||
@ -346,18 +418,126 @@ void Workspace::featurePresetsDialog()
 | 
			
		||||
    emit featurePresetsDialogRequested(p, this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::configurationPresetsDialog()
 | 
			
		||||
{
 | 
			
		||||
    emit configurationPresetsDialogRequested();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::cascadeSubWindows()
 | 
			
		||||
{
 | 
			
		||||
    m_autoStackSubWindows->setChecked(false);
 | 
			
		||||
    setAutoStackOption(false);
 | 
			
		||||
    m_tabSubWindows->setChecked(false);
 | 
			
		||||
    m_mdi->setViewMode(QMdiArea::SubWindowView);
 | 
			
		||||
    m_mdi->cascadeSubWindows();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::tileSubWindows()
 | 
			
		||||
{
 | 
			
		||||
    m_autoStackSubWindows->setChecked(false);
 | 
			
		||||
    setAutoStackOption(false);
 | 
			
		||||
    m_tabSubWindows->setChecked(false);
 | 
			
		||||
    m_mdi->setViewMode(QMdiArea::SubWindowView);
 | 
			
		||||
    m_mdi->tileSubWindows();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::stackVerticalSubWindows()
 | 
			
		||||
{
 | 
			
		||||
    setAutoStackOption(false);
 | 
			
		||||
    unmaximizeSubWindows();
 | 
			
		||||
    m_mdi->setViewMode(QMdiArea::SubWindowView);
 | 
			
		||||
 | 
			
		||||
    // Spacing between windows
 | 
			
		||||
    const int spacing = 2;
 | 
			
		||||
 | 
			
		||||
    // Categorise windows according to type and calculate min size needed
 | 
			
		||||
    QList<QMdiSubWindow *> windows = m_mdi->subWindowList(QMdiArea::CreationOrder);
 | 
			
		||||
    QList<DeviceGUI *> devices;
 | 
			
		||||
    QList<MainSpectrumGUI *> spectrums;
 | 
			
		||||
    QList<ChannelGUI *> channels;
 | 
			
		||||
    QList<FeatureGUI *> features;
 | 
			
		||||
    int minHeight = 0;
 | 
			
		||||
    int minWidth = 0;
 | 
			
		||||
    int nonFixedWindows = 0;
 | 
			
		||||
 | 
			
		||||
    for (auto window : windows)
 | 
			
		||||
    {
 | 
			
		||||
        if (window->isVisible() && !window->isMaximized())
 | 
			
		||||
        {
 | 
			
		||||
            if (window->inherits("DeviceGUI")) {
 | 
			
		||||
                devices.append(qobject_cast<DeviceGUI *>(window));
 | 
			
		||||
            } else if (window->inherits("MainSpectrumGUI")) {
 | 
			
		||||
                spectrums.append(qobject_cast<MainSpectrumGUI *>(window));
 | 
			
		||||
            } else if (window->inherits("ChannelGUI")) {
 | 
			
		||||
                channels.append(qobject_cast<ChannelGUI *>(window));
 | 
			
		||||
            } else if (window->inherits("FeatureGUI")) {
 | 
			
		||||
                features.append(qobject_cast<FeatureGUI *>(window));
 | 
			
		||||
            }
 | 
			
		||||
            minHeight += window->minimumSizeHint().height() + spacing;
 | 
			
		||||
            minWidth = std::max(minWidth, window->minimumSizeHint().width());
 | 
			
		||||
            if (window->sizePolicy().verticalPolicy() != QSizePolicy::Fixed) {
 | 
			
		||||
                nonFixedWindows++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Order windows by device/feature/channel index
 | 
			
		||||
    orderByIndex(devices);
 | 
			
		||||
    orderByIndex(spectrums);
 | 
			
		||||
    orderByIndex(channels);
 | 
			
		||||
    orderByIndex(features);
 | 
			
		||||
 | 
			
		||||
    // Will we need scroll bars?
 | 
			
		||||
    QSize mdiSize = m_mdi->size();
 | 
			
		||||
    bool requiresHScrollBar = minWidth > mdiSize.width();
 | 
			
		||||
    bool requiresVScrollBar = minHeight > mdiSize.height();
 | 
			
		||||
 | 
			
		||||
    // Reduce available size if scroll bars needed
 | 
			
		||||
    int sbWidth = qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
 | 
			
		||||
    if (requiresVScrollBar) {
 | 
			
		||||
        mdiSize.setWidth(mdiSize.width() - sbWidth);
 | 
			
		||||
    }
 | 
			
		||||
    if (requiresHScrollBar) {
 | 
			
		||||
        mdiSize.setHeight(mdiSize.height() - sbWidth);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Calculate spare vertical space, to be shared between non-fixed windows
 | 
			
		||||
    int spareSpacePerWindow;
 | 
			
		||||
    if (requiresVScrollBar) {
 | 
			
		||||
        spareSpacePerWindow = 0;
 | 
			
		||||
    } else {
 | 
			
		||||
        spareSpacePerWindow = (mdiSize.height() - minHeight) / nonFixedWindows;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Now position the windows
 | 
			
		||||
    int x = 0;
 | 
			
		||||
    int y = 0;
 | 
			
		||||
 | 
			
		||||
    for (auto window : devices)
 | 
			
		||||
    {
 | 
			
		||||
        window->move(x, y);
 | 
			
		||||
        y += window->size().height() + spacing;
 | 
			
		||||
    }
 | 
			
		||||
    for (auto window : spectrums)
 | 
			
		||||
    {
 | 
			
		||||
        window->move(x, y);
 | 
			
		||||
        window->resize(mdiSize.width(), window->minimumSizeHint().height() + spareSpacePerWindow);
 | 
			
		||||
        y += window->size().height() + spacing;
 | 
			
		||||
    }
 | 
			
		||||
    for (auto window : channels)
 | 
			
		||||
    {
 | 
			
		||||
        window->move(x, y);
 | 
			
		||||
        int extra = (window->sizePolicy().verticalPolicy() == QSizePolicy::Fixed) ? 0 : spareSpacePerWindow;
 | 
			
		||||
        window->resize(mdiSize.width(), window->minimumSizeHint().height() + extra);
 | 
			
		||||
        y += window->size().height() + spacing;
 | 
			
		||||
    }
 | 
			
		||||
    for (auto window : features)
 | 
			
		||||
    {
 | 
			
		||||
        window->move(x, y);
 | 
			
		||||
        int extra = (window->sizePolicy().verticalPolicy() == QSizePolicy::Fixed) ? 0 : spareSpacePerWindow;
 | 
			
		||||
        window->resize(mdiSize.width(), window->minimumSizeHint().height() + extra);
 | 
			
		||||
        y += window->size().height() + spacing;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::orderByIndex(QList<ChannelGUI *> &list)
 | 
			
		||||
{
 | 
			
		||||
    std::sort(list.begin(), list.end(),
 | 
			
		||||
@ -398,16 +578,36 @@ void Workspace::orderByIndex(QList<MainSpectrumGUI *> &list)
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::unmaximizeSubWindows()
 | 
			
		||||
{
 | 
			
		||||
    if (m_tabSubWindows->isChecked())
 | 
			
		||||
    {
 | 
			
		||||
        m_tabSubWindows->setChecked(false);
 | 
			
		||||
        // Unmaximize any maximized windows
 | 
			
		||||
        QList<QMdiSubWindow *> windows = m_mdi->subWindowList(QMdiArea::CreationOrder);
 | 
			
		||||
        for (auto window : windows)
 | 
			
		||||
        {
 | 
			
		||||
            if (window->isMaximized()) {
 | 
			
		||||
                window->showNormal();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Try to arrange windows somewhat like in earlier versions of SDRangel
 | 
			
		||||
// Devices and fixed size features stacked on left
 | 
			
		||||
// Spectrum and expandable features stacked in centre
 | 
			
		||||
// Channels stacked on right
 | 
			
		||||
void Workspace::stackSubWindows()
 | 
			
		||||
{
 | 
			
		||||
    unmaximizeSubWindows();
 | 
			
		||||
 | 
			
		||||
    // Set a flag so event handler knows if it's this code or the user that
 | 
			
		||||
    // resizes a window
 | 
			
		||||
    m_stacking = true;
 | 
			
		||||
 | 
			
		||||
    m_mdi->setViewMode(QMdiArea::SubWindowView);
 | 
			
		||||
 | 
			
		||||
    // Categorise windows according to type
 | 
			
		||||
    QList<QMdiSubWindow *> windows = m_mdi->subWindowList(QMdiArea::CreationOrder);
 | 
			
		||||
    QList<DeviceGUI *> devices;
 | 
			
		||||
@ -653,7 +853,54 @@ void Workspace::stackSubWindows()
 | 
			
		||||
 | 
			
		||||
void Workspace::autoStackSubWindows()
 | 
			
		||||
{
 | 
			
		||||
    if (m_autoStackSubWindows->isChecked()) {
 | 
			
		||||
    setAutoStackOption(!m_autoStack);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::tabSubWindows()
 | 
			
		||||
{
 | 
			
		||||
    if (m_tabSubWindows->isChecked())
 | 
			
		||||
    {
 | 
			
		||||
        // Disable autostack
 | 
			
		||||
        setAutoStackOption(false);
 | 
			
		||||
 | 
			
		||||
        // Move sub windows out of view, so they can't be seen next to a non-expandible window
 | 
			
		||||
        // Perhaps there's a better way to do this - showMinimized didn't work
 | 
			
		||||
        QList<QMdiSubWindow *> windows = m_mdi->subWindowList(QMdiArea::CreationOrder);
 | 
			
		||||
        for (auto window : windows)
 | 
			
		||||
        {
 | 
			
		||||
            if ((window != m_mdi->activeSubWindow()) && ((window->x() != 5000) || (window->y() != 0))) {
 | 
			
		||||
                window->move(5000, 0);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_mdi->setViewMode(QMdiArea::TabbedView);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        m_mdi->setViewMode(QMdiArea::SubWindowView);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::subWindowActivated(QMdiSubWindow *activatedWindow)
 | 
			
		||||
{
 | 
			
		||||
    if (activatedWindow && m_tabSubWindows->isChecked())
 | 
			
		||||
    {
 | 
			
		||||
        // Move other windows out of the way
 | 
			
		||||
        QList<QMdiSubWindow *> windows = m_mdi->subWindowList(QMdiArea::CreationOrder);
 | 
			
		||||
        for (auto window : windows)
 | 
			
		||||
        {
 | 
			
		||||
            if ((window != activatedWindow) && ((window->x() != 5000) || (window->y() != 0))) {
 | 
			
		||||
                window->move(5000, 0);
 | 
			
		||||
            } else if ((window == activatedWindow) && ((window->x() != 0) || (window->y() != 0))) {
 | 
			
		||||
                window->move(0, 0);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::layoutSubWindows()
 | 
			
		||||
{
 | 
			
		||||
    if (m_autoStack) {
 | 
			
		||||
        stackSubWindows();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -716,7 +963,7 @@ void Workspace::deviceStateChanged(int index, DeviceAPI *deviceAPI)
 | 
			
		||||
void Workspace::resizeEvent(QResizeEvent *event)
 | 
			
		||||
{
 | 
			
		||||
    QDockWidget::resizeEvent(event);
 | 
			
		||||
    autoStackSubWindows();
 | 
			
		||||
    layoutSubWindows();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::addToMdiArea(QMdiSubWindow *sub)
 | 
			
		||||
@ -725,17 +972,20 @@ void Workspace::addToMdiArea(QMdiSubWindow *sub)
 | 
			
		||||
    sub->installEventFilter(this);
 | 
			
		||||
    // Can't use Close event, as it's before window is closed, so
 | 
			
		||||
    // catch sub-window destroyed signal instead
 | 
			
		||||
    connect(sub, &QObject::destroyed, this, &Workspace::autoStackSubWindows);
 | 
			
		||||
    connect(sub, &QObject::destroyed, this, &Workspace::layoutSubWindows);
 | 
			
		||||
    m_mdi->addSubWindow(sub);
 | 
			
		||||
    sub->show();
 | 
			
		||||
    // Auto-stack when sub-window's  widgets are rolled up
 | 
			
		||||
    // Auto-stack when sub-window's widgets are rolled up
 | 
			
		||||
    ChannelGUI *channel = qobject_cast<ChannelGUI *>(sub);
 | 
			
		||||
    if (channel) {
 | 
			
		||||
        connect(channel->getRollupContents(), &RollupContents::widgetRolled, this, &Workspace::autoStackSubWindows);
 | 
			
		||||
        connect(channel->getRollupContents(), &RollupContents::widgetRolled, this, &Workspace::layoutSubWindows);
 | 
			
		||||
    }
 | 
			
		||||
    FeatureGUI *feature = qobject_cast<FeatureGUI *>(sub);
 | 
			
		||||
    if (feature) {
 | 
			
		||||
        connect(feature->getRollupContents(), &RollupContents::widgetRolled, this, &Workspace::autoStackSubWindows);
 | 
			
		||||
        connect(feature->getRollupContents(), &RollupContents::widgetRolled, this, &Workspace::layoutSubWindows);
 | 
			
		||||
    }
 | 
			
		||||
    if (m_tabSubWindows->isChecked()) {
 | 
			
		||||
        sub->showMaximized();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -743,14 +993,14 @@ void Workspace::removeFromMdiArea(QMdiSubWindow *sub)
 | 
			
		||||
{
 | 
			
		||||
    m_mdi->removeSubWindow(sub);
 | 
			
		||||
    sub->removeEventFilter(this);
 | 
			
		||||
    disconnect(sub, &QObject::destroyed, this, &Workspace::autoStackSubWindows);
 | 
			
		||||
    disconnect(sub, &QObject::destroyed, this, &Workspace::layoutSubWindows);
 | 
			
		||||
    ChannelGUI *channel = qobject_cast<ChannelGUI *>(sub);
 | 
			
		||||
    if (channel) {
 | 
			
		||||
        disconnect(channel->getRollupContents(), &RollupContents::widgetRolled, this, &Workspace::autoStackSubWindows);
 | 
			
		||||
        disconnect(channel->getRollupContents(), &RollupContents::widgetRolled, this, &Workspace::layoutSubWindows);
 | 
			
		||||
    }
 | 
			
		||||
    FeatureGUI *feature = qobject_cast<FeatureGUI *>(sub);
 | 
			
		||||
    if (feature) {
 | 
			
		||||
        disconnect(feature->getRollupContents(), &RollupContents::widgetRolled, this, &Workspace::autoStackSubWindows);
 | 
			
		||||
        disconnect(feature->getRollupContents(), &RollupContents::widgetRolled, this, &Workspace::layoutSubWindows);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -760,19 +1010,19 @@ bool Workspace::eventFilter(QObject *obj, QEvent *event)
 | 
			
		||||
    {
 | 
			
		||||
        QWidget *widget = qobject_cast<QWidget *>(obj);
 | 
			
		||||
        if (!widget->isMaximized()) {
 | 
			
		||||
            autoStackSubWindows();
 | 
			
		||||
            layoutSubWindows();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if (event->type() == QEvent::Hide)
 | 
			
		||||
    {
 | 
			
		||||
        QWidget *widget = qobject_cast<QWidget *>(obj);
 | 
			
		||||
        if (!widget->isMaximized()) {
 | 
			
		||||
            autoStackSubWindows();
 | 
			
		||||
            layoutSubWindows();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if (event->type() == QEvent::Resize)
 | 
			
		||||
    {
 | 
			
		||||
        if (!m_stacking && m_autoStackSubWindows->isChecked())
 | 
			
		||||
        if (!m_stacking && m_autoStack)
 | 
			
		||||
        {
 | 
			
		||||
            QWidget *widget = qobject_cast<QWidget *>(obj);
 | 
			
		||||
            QResizeEvent *resizeEvent = static_cast<QResizeEvent *>(event);
 | 
			
		||||
@ -812,12 +1062,38 @@ void Workspace::restoreMdiGeometry(const QByteArray& blob)
 | 
			
		||||
 | 
			
		||||
bool Workspace::getAutoStackOption() const
 | 
			
		||||
{
 | 
			
		||||
    return m_autoStackSubWindows->isChecked();
 | 
			
		||||
    return m_autoStack;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::setAutoStackOption(bool autoStack)
 | 
			
		||||
{
 | 
			
		||||
    m_autoStackSubWindows->doToggle(autoStack);
 | 
			
		||||
    m_autoStack = autoStack;
 | 
			
		||||
    if (!m_autoStack)
 | 
			
		||||
    {
 | 
			
		||||
        m_stackSubWindows->setStyleSheet(QString("QPushButton{ background-color: %1; }")
 | 
			
		||||
            .arg(palette().button().color().name()));
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        m_stackSubWindows->setStyleSheet(QString("QPushButton{ background-color: %1;  }")
 | 
			
		||||
            .arg(palette().highlight().color().darker(150).name()));
 | 
			
		||||
        stackSubWindows();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Workspace::getTabSubWindowsOption() const
 | 
			
		||||
{
 | 
			
		||||
    return m_tabSubWindows->isChecked();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::setTabSubWindowsOption(bool tab)
 | 
			
		||||
{
 | 
			
		||||
    m_tabSubWindows->doToggle(tab);
 | 
			
		||||
    if (tab) {
 | 
			
		||||
        tabSubWindows();
 | 
			
		||||
    } else {
 | 
			
		||||
        m_mdi->setViewMode(QMdiArea::SubWindowView);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspace::adjustSubWindowsAfterRestore()
 | 
			
		||||
 | 
			
		||||
@ -28,6 +28,7 @@
 | 
			
		||||
 | 
			
		||||
class QHBoxLayout;
 | 
			
		||||
class QLabel;
 | 
			
		||||
class QToolButton;
 | 
			
		||||
class QPushButton;
 | 
			
		||||
class QMdiArea;
 | 
			
		||||
class QMdiSubWindow;
 | 
			
		||||
@ -37,7 +38,6 @@ class ChannelGUI;
 | 
			
		||||
class FeatureGUI;
 | 
			
		||||
class DeviceGUI;
 | 
			
		||||
class MainSpectrumGUI;
 | 
			
		||||
 | 
			
		||||
class SDRGUI_API Workspace : public QDockWidget
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
@ -56,6 +56,8 @@ public:
 | 
			
		||||
    void restoreMdiGeometry(const QByteArray& blob);
 | 
			
		||||
    bool getAutoStackOption() const;
 | 
			
		||||
    void setAutoStackOption(bool autoStack);
 | 
			
		||||
    bool getTabSubWindowsOption() const;
 | 
			
		||||
    void setTabSubWindowsOption(bool tab);
 | 
			
		||||
    QList<QMdiSubWindow *> getSubWindowList() const;
 | 
			
		||||
    void orderByIndex(QList<ChannelGUI *> &list);
 | 
			
		||||
    void orderByIndex(QList<FeatureGUI *> &list);
 | 
			
		||||
@ -63,21 +65,26 @@ public:
 | 
			
		||||
    void orderByIndex(QList<MainSpectrumGUI *> &list);
 | 
			
		||||
    void adjustSubWindowsAfterRestore();
 | 
			
		||||
    void updateStartStopButton(bool checked);
 | 
			
		||||
    QToolButton *getMenuButton() const { return m_menuButton; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    int m_index;
 | 
			
		||||
    QToolButton *m_menuButton;
 | 
			
		||||
    QPushButton *m_configurationPresetsButton;
 | 
			
		||||
    ButtonSwitch *m_startStopButton;
 | 
			
		||||
    QFrame *m_vline1;
 | 
			
		||||
    QPushButton *m_addRxDeviceButton;
 | 
			
		||||
    QPushButton *m_addTxDeviceButton;
 | 
			
		||||
    QPushButton *m_addMIMODeviceButton;
 | 
			
		||||
    ButtonSwitch *m_startStopButton;
 | 
			
		||||
    QFrame *m_vline1;
 | 
			
		||||
    QFrame *m_vline2;
 | 
			
		||||
    QPushButton *m_addFeatureButton;
 | 
			
		||||
    QPushButton *m_featurePresetsButton;
 | 
			
		||||
    QFrame *m_vline2;
 | 
			
		||||
    QFrame *m_vline3;
 | 
			
		||||
    QPushButton *m_cascadeSubWindows;
 | 
			
		||||
    QPushButton *m_tileSubWindows;
 | 
			
		||||
    QPushButton *m_stackVerticalSubWindows;
 | 
			
		||||
    QPushButton *m_stackSubWindows;
 | 
			
		||||
    ButtonSwitch *m_autoStackSubWindows;
 | 
			
		||||
    ButtonSwitch *m_tabSubWindows;
 | 
			
		||||
    QWidget *m_titleBar;
 | 
			
		||||
    QHBoxLayout *m_titleBarLayout;
 | 
			
		||||
    QLabel *m_titleLabel;
 | 
			
		||||
@ -86,8 +93,11 @@ private:
 | 
			
		||||
    FeatureAddDialog m_featureAddDialog;
 | 
			
		||||
    QMdiArea *m_mdi;
 | 
			
		||||
    bool m_stacking;                // Set when stackSubWindows() is running
 | 
			
		||||
    bool m_autoStack;               // Automatically stack
 | 
			
		||||
    int m_userChannelMinWidth;      // Minimum width of channels column for stackSubWindows(), set by user resizing a channel window
 | 
			
		||||
 | 
			
		||||
    void unmaximizeSubWindows();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void resizeEvent(QResizeEvent *event) override;
 | 
			
		||||
    bool eventFilter(QObject *obj, QEvent *event) override;
 | 
			
		||||
@ -98,14 +108,19 @@ private slots:
 | 
			
		||||
    void addMIMODeviceClicked();
 | 
			
		||||
    void addFeatureDialog();
 | 
			
		||||
    void featurePresetsDialog();
 | 
			
		||||
    void configurationPresetsDialog();
 | 
			
		||||
    void cascadeSubWindows();
 | 
			
		||||
    void tileSubWindows();
 | 
			
		||||
    void stackVerticalSubWindows();
 | 
			
		||||
    void stackSubWindows();
 | 
			
		||||
    void autoStackSubWindows();
 | 
			
		||||
    void tabSubWindows();
 | 
			
		||||
    void layoutSubWindows();
 | 
			
		||||
    void startStopClicked(bool checked = false);
 | 
			
		||||
    void addFeatureEmitted(int featureIndex);
 | 
			
		||||
    void toggleFloating();
 | 
			
		||||
    void deviceStateChanged(int index, DeviceAPI *deviceAPI);
 | 
			
		||||
    void subWindowActivated(QMdiSubWindow *window);
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
    void addRxDevice(Workspace *inWorkspace, int deviceIndex);
 | 
			
		||||
@ -113,6 +128,7 @@ signals:
 | 
			
		||||
    void addMIMODevice(Workspace *inWorkspace, int deviceIndex);
 | 
			
		||||
    void addFeature(Workspace*, int);
 | 
			
		||||
    void featurePresetsDialogRequested(QPoint, Workspace*);
 | 
			
		||||
    void configurationPresetsDialogRequested();
 | 
			
		||||
    void startAllDevices(Workspace *inWorkspace);
 | 
			
		||||
    void stopAllDevices(Workspace *inWorkspace);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -23,6 +23,7 @@
 | 
			
		||||
#include <QSizeGrip>
 | 
			
		||||
#include <QObjectCleanupHandler>
 | 
			
		||||
#include <QDesktopServices>
 | 
			
		||||
#include <QMdiArea>
 | 
			
		||||
 | 
			
		||||
#include "mainwindow.h"
 | 
			
		||||
#include "gui/glspectrum.h"
 | 
			
		||||
@ -38,7 +39,8 @@ MainSpectrumGUI::MainSpectrumGUI(GLSpectrum *spectrum, GLSpectrumGUI *spectrumGU
 | 
			
		||||
    m_deviceType(DeviceRx),
 | 
			
		||||
    m_deviceSetIndex(0),
 | 
			
		||||
    m_drag(false),
 | 
			
		||||
    m_resizer(this)
 | 
			
		||||
    m_resizer(this),
 | 
			
		||||
    m_mdi(nullptr)
 | 
			
		||||
{
 | 
			
		||||
    qDebug("MainSpectrumGUI::MainSpectrumGUI: %p", parent);
 | 
			
		||||
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
 | 
			
		||||
@ -88,7 +90,7 @@ MainSpectrumGUI::MainSpectrumGUI(GLSpectrum *spectrum, GLSpectrumGUI *spectrumGU
 | 
			
		||||
    m_maximizeButton->setFixedSize(20, 20);
 | 
			
		||||
    QIcon maximizeIcon(":/maximize.png");
 | 
			
		||||
    m_maximizeButton->setIcon(maximizeIcon);
 | 
			
		||||
    m_maximizeButton->setToolTip("Adjust window to maximum size");
 | 
			
		||||
    m_maximizeButton->setToolTip("Adjust window to maximum size in workspace");
 | 
			
		||||
 | 
			
		||||
    m_hideButton = new QPushButton();
 | 
			
		||||
    m_hideButton->setFixedSize(20, 20);
 | 
			
		||||
@ -260,15 +262,42 @@ void MainSpectrumGUI::openMoveToWorkspaceDialog()
 | 
			
		||||
 | 
			
		||||
void MainSpectrumGUI::maximizeWindow()
 | 
			
		||||
{
 | 
			
		||||
    showMaximized();
 | 
			
		||||
    // If maximize is pressed when maximized, go full screen
 | 
			
		||||
    if (isMaximized())
 | 
			
		||||
    {
 | 
			
		||||
        m_mdi = mdiArea();
 | 
			
		||||
        if (m_mdi) {
 | 
			
		||||
            m_mdi->removeSubWindow(this);
 | 
			
		||||
        }
 | 
			
		||||
        showNormal(); // If we don't go back to normal first, window doesn't get bigger
 | 
			
		||||
        showFullScreen();
 | 
			
		||||
        m_shrinkButton->setToolTip("Adjust window to maximum size in workspace");
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        showMaximized();
 | 
			
		||||
        m_shrinkButton->setToolTip("Restore window to normal");
 | 
			
		||||
        m_maximizeButton->setToolTip("Make window full screen");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainSpectrumGUI::shrinkWindow()
 | 
			
		||||
{
 | 
			
		||||
    qDebug("MainSpectrumGUI::shrinkWindow");
 | 
			
		||||
    if (isMaximized())
 | 
			
		||||
    if (m_mdi)
 | 
			
		||||
    {
 | 
			
		||||
        showNormal();
 | 
			
		||||
        m_mdi->addSubWindow(this);
 | 
			
		||||
        show();
 | 
			
		||||
        showMaximized();
 | 
			
		||||
        m_shrinkButton->setToolTip("Restore window to normal");
 | 
			
		||||
        m_mdi = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    else if (isMaximized())
 | 
			
		||||
    {
 | 
			
		||||
        showNormal();
 | 
			
		||||
        m_shrinkButton->setToolTip("Adjust window to minimum size");
 | 
			
		||||
        m_maximizeButton->setToolTip("Adjust window to maximum size in workspace");
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
@ -279,6 +308,7 @@ void MainSpectrumGUI::shrinkWindow()
 | 
			
		||||
 | 
			
		||||
void MainSpectrumGUI::setTitle(const QString& title)
 | 
			
		||||
{
 | 
			
		||||
    setWindowTitle(title + " Spectrum");
 | 
			
		||||
    m_titleLabel->setText(title);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -88,6 +88,7 @@ private:
 | 
			
		||||
    bool m_drag;
 | 
			
		||||
    QPoint m_DragPosition;
 | 
			
		||||
    FramelessWindowResizer m_resizer;
 | 
			
		||||
    QMdiArea *m_mdi;                    // Saved pointer to MDI when in full screen mode
 | 
			
		||||
    static const int m_MinimumWidth = 380;
 | 
			
		||||
    static const int m_MinimumHeight = 200 + 20 + 10 + 6*22 + 5;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user