mirror of
https://github.com/Serial-Studio/Serial-Studio.git
synced 2025-01-31 17:42:55 +08:00
Revert to QWidget-based external window
This commit is contained in:
parent
f2515dd1c0
commit
1cdf5e5a59
@ -69,6 +69,7 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050F00
|
||||
QMAKE_CXXFLAGS *= -MP
|
||||
}
|
||||
|
||||
CONFIG += ltcg
|
||||
CONFIG += c++11
|
||||
CONFIG += silent
|
||||
|
||||
|
@ -21,105 +21,47 @@
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import SerialStudio 1.0
|
||||
|
||||
import "../Widgets" as Widgets
|
||||
import "../FramelessWindow" as FramelessWindow
|
||||
|
||||
Item {
|
||||
id: root
|
||||
visible: false
|
||||
|
||||
property int widgetIndex: -1
|
||||
property FramelessWindow.CustomWindow externalWindow: null
|
||||
|
||||
Widgets.Window {
|
||||
id: window
|
||||
anchors.fill: parent
|
||||
title: loader.widgetTitle
|
||||
icon.source: loader.widgetIcon
|
||||
headerDoubleClickEnabled: true
|
||||
borderColor: Cpp_ThemeManager.widgetWindowBorder
|
||||
onHeaderDoubleClicked: {
|
||||
if (root.externalWindow !== null)
|
||||
root.externalWindow.showNormal()
|
||||
else
|
||||
externalWindowLoader.active = true
|
||||
}
|
||||
Connections {
|
||||
target: Cpp_UI_Dashboard
|
||||
|
||||
WidgetLoader {
|
||||
id: loader
|
||||
widgetIndex: root.widgetIndex
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: window.borderWidth
|
||||
rightMargin: window.borderWidth
|
||||
bottomMargin: window.borderWidth
|
||||
}
|
||||
function onWidgetVisibilityChanged() {
|
||||
if (loader.status == Loader.Ready)
|
||||
root.visible = Cpp_UI_Dashboard.widgetVisible(root.widgetIndex)
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: externalWindowLoader
|
||||
id: loader
|
||||
anchors.fill: parent
|
||||
onLoaded: root.visible = Cpp_UI_Dashboard.widgetVisible(root.widgetIndex)
|
||||
|
||||
active: false
|
||||
asynchronous: true
|
||||
sourceComponent: Widgets.Window {
|
||||
id: window
|
||||
title: widget.widgetTitle
|
||||
icon.source: widget.widgetIcon
|
||||
headerDoubleClickEnabled: true
|
||||
borderColor: Cpp_ThemeManager.widgetWindowBorder
|
||||
onHeaderDoubleClicked: widget.showExternalWindow()
|
||||
|
||||
sourceComponent: FramelessWindow.CustomWindow {
|
||||
id: _window
|
||||
minimumWidth: 640 + shadowMargin
|
||||
minimumHeight: 480 + shadowMargin
|
||||
title: externalLoader.widgetTitle
|
||||
extraFlags: Qt.WindowStaysOnTopHint
|
||||
titlebarText: Cpp_ThemeManager.text
|
||||
titlebarColor: Cpp_ThemeManager.widgetWindowBackground
|
||||
backgroundColor: Cpp_ThemeManager.widgetWindowBackground
|
||||
borderColor: isMaximized ? backgroundColor : Cpp_ThemeManager.highlight
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 200
|
||||
onTriggered: _window.showNormal()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.externalWindow = this
|
||||
timer.start()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
clip: true
|
||||
anchors.fill: parent
|
||||
radius: _window.radius
|
||||
anchors.margins: _window.shadowMargin
|
||||
color: Cpp_ThemeManager.widgetWindowBackground
|
||||
anchors.topMargin: _window.titlebar.height + _window.shadowMargin
|
||||
|
||||
Rectangle {
|
||||
height: _window.radius
|
||||
color: Cpp_ThemeManager.widgetWindowBackground
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
WidgetLoader {
|
||||
id: widget
|
||||
widgetIndex: root.widgetIndex
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: window.borderWidth
|
||||
rightMargin: window.borderWidth
|
||||
bottomMargin: window.borderWidth
|
||||
}
|
||||
|
||||
WidgetLoader {
|
||||
id: externalLoader
|
||||
anchors.fill: parent
|
||||
isExternalWindow: true
|
||||
widgetIndex: root.widgetIndex
|
||||
widgetVisible: _window.visible
|
||||
anchors.margins: _window.radius
|
||||
}
|
||||
}
|
||||
|
||||
FramelessWindow.ResizeHandles {
|
||||
window: _window
|
||||
anchors.fill: parent
|
||||
handleSize: _window.handleSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,23 +29,9 @@ Repeater {
|
||||
property real cellWidth: 0
|
||||
property real cellHeight: 0
|
||||
|
||||
delegate: Loader {
|
||||
id: loader
|
||||
asynchronous: true
|
||||
delegate: WidgetDelegate {
|
||||
widgetIndex: index
|
||||
width: root.cellWidth
|
||||
height: root.cellHeight
|
||||
|
||||
sourceComponent: WidgetDelegate {
|
||||
widgetIndex: index
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Cpp_UI_Dashboard
|
||||
|
||||
function onWidgetVisibilityChanged() {
|
||||
loader.visible = Cpp_UI_Dashboard.widgetVisible(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ MenuBar {
|
||||
title: qsTr("Help")
|
||||
|
||||
DecentMenuItem {
|
||||
onTriggered: app.about.show()
|
||||
onTriggered: app.aboutDialog.show()
|
||||
text: qsTr("About %1").arg(Cpp_AppName)
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,7 @@ MenuBar {
|
||||
title: qsTr("Help")
|
||||
|
||||
MenuItem {
|
||||
onTriggered: app.about.show()
|
||||
onTriggered: app.aboutDialog.show()
|
||||
text: qsTr("About %1").arg(Cpp_AppName)
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ FramelessWindow.CustomWindow {
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Make a donation")
|
||||
onClicked: app.donations.show()
|
||||
onClicked: app.donateDialog.show()
|
||||
}
|
||||
|
||||
Button {
|
||||
@ -191,7 +191,7 @@ FramelessWindow.CustomWindow {
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Acknowledgements")
|
||||
onClicked: acknowledgements.show()
|
||||
onClicked: acknowledgementsDialog.show()
|
||||
}
|
||||
|
||||
Item {
|
||||
|
@ -122,8 +122,8 @@ FramelessWindow.CustomWindow {
|
||||
root.requestUpdate()
|
||||
|
||||
// Show donations dialog every 15 launches
|
||||
if (root.appLaunchCount % 15 == 0 && !app.donations.doNotShowAgain)
|
||||
app.donations.showAutomatically()
|
||||
if (root.appLaunchCount % 15 == 0 && !app.donateDialog.doNotShowAgain)
|
||||
app.donateDialog.showAutomatically()
|
||||
|
||||
// Ask user if he/she wants to enable automatic updates
|
||||
if (root.appLaunchCount == 2 && Cpp_UpdaterEnabled) {
|
||||
@ -269,7 +269,7 @@ FramelessWindow.CustomWindow {
|
||||
setupChecked: root.setupVisible
|
||||
consoleChecked: root.consoleVisible
|
||||
dashboardChecked: root.dashboardVisible
|
||||
onJsonEditorClicked: app.jsonEditor.show()
|
||||
onJsonEditorClicked: app.jsonEditorWindow.show()
|
||||
onSetupClicked: setup.visible ? setup.hide() : setup.show()
|
||||
|
||||
onDashboardClicked: {
|
||||
|
@ -38,12 +38,12 @@ Item {
|
||||
//
|
||||
// Access to dialogs & windows
|
||||
//
|
||||
property Windows.About about: null
|
||||
property Windows.Donate donations: null
|
||||
property Windows.CsvPlayer csvPlayer: null
|
||||
property Windows.About aboutDialog: null
|
||||
property Windows.Donate donateDialog: null
|
||||
property Windows.MainWindow mainWindow: null
|
||||
property Windows.JsonEditor jsonEditor: null
|
||||
property Windows.Acknowledgements acknowledgements: null
|
||||
property Windows.CsvPlayer csvPlayerDialog: null
|
||||
property Windows.JsonEditor jsonEditorWindow: null
|
||||
property Windows.Acknowledgements acknowledgementsDialog: null
|
||||
|
||||
//
|
||||
// Check for updates (non-silent mode)
|
||||
@ -73,7 +73,7 @@ Item {
|
||||
Loader {
|
||||
asynchronous: true
|
||||
sourceComponent: Windows.About {
|
||||
Component.onCompleted: app.about = this
|
||||
Component.onCompleted: app.aboutDialog = this
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ Item {
|
||||
Loader {
|
||||
asynchronous: true
|
||||
sourceComponent: Windows.CsvPlayer {
|
||||
Component.onCompleted: app.csvPlayer = this
|
||||
Component.onCompleted: app.csvPlayerDialog = this
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ Item {
|
||||
Loader {
|
||||
asynchronous: true
|
||||
sourceComponent: Windows.JsonEditor {
|
||||
Component.onCompleted: app.jsonEditor = this
|
||||
Component.onCompleted: app.jsonEditorWindow = this
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ Item {
|
||||
Loader {
|
||||
asynchronous: false
|
||||
sourceComponent: Windows.Donate {
|
||||
Component.onCompleted: app.donations = this
|
||||
Component.onCompleted: app.donateDialog = this
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ Item {
|
||||
Loader {
|
||||
asynchronous: true
|
||||
sourceComponent: Windows.Acknowledgements {
|
||||
Component.onCompleted: app.acknowledgements = this
|
||||
Component.onCompleted: app.acknowledgementsDialog = this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ WidgetLoader::WidgetLoader(QQuickItem *parent)
|
||||
, m_index(-1)
|
||||
, m_widget(nullptr)
|
||||
, m_widgetVisible(false)
|
||||
, m_isExternalWindow(false)
|
||||
{
|
||||
// Set item flags
|
||||
setFlag(ItemHasContents, true);
|
||||
@ -63,6 +62,20 @@ WidgetLoader::WidgetLoader(QQuickItem *parent)
|
||||
connect(this, &QQuickPaintedItem::heightChanged, this,
|
||||
&WidgetLoader::updateWidgetSize);
|
||||
|
||||
// Configure external window
|
||||
m_window.setMinimumWidth(640);
|
||||
m_window.setMinimumHeight(480);
|
||||
|
||||
// Set window palette
|
||||
QPalette palette;
|
||||
auto theme = Misc::ThemeManager::getInstance();
|
||||
palette.setColor(QPalette::Base, theme->widgetWindowBackground());
|
||||
palette.setColor(QPalette::Window, theme->widgetWindowBackground());
|
||||
m_window.setPalette(palette);
|
||||
|
||||
// Enable/disable the external window widget automatically
|
||||
connect(&m_window, SIGNAL(visibleChanged()), this, SLOT(updateExternalWindow()));
|
||||
|
||||
// Automatically update the widget's visibility
|
||||
connect(Dashboard::getInstance(), &Dashboard::widgetVisibilityChanged, this,
|
||||
&WidgetLoader::updateWidgetVisible);
|
||||
@ -75,6 +88,9 @@ WidgetLoader::~WidgetLoader()
|
||||
{
|
||||
if (m_widget)
|
||||
delete m_widget;
|
||||
|
||||
if (m_window.centralWidget())
|
||||
delete m_window.centralWidget();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,18 +216,6 @@ QString WidgetLoader::widgetTitle() const
|
||||
return tr("Invalid");
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to @c true, then the widget visibility shall be controlled
|
||||
* directly by the QML interface.
|
||||
*
|
||||
* If set to @c false, then the widget visbility shall be controlled
|
||||
* by the UI::Dashboard class via the SIGNAL/SLOT system.
|
||||
*/
|
||||
bool WidgetLoader::isExternalWindow() const
|
||||
{
|
||||
return m_isExternalWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the current widget (e.g. group, plot, bar, gauge, etc...)
|
||||
*/
|
||||
@ -220,6 +224,15 @@ UI::Dashboard::WidgetType WidgetLoader::widgetType() const
|
||||
return UI::Dashboard::getInstance()->widgetType(widgetIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the external window
|
||||
*/
|
||||
void WidgetLoader::showExternalWindow()
|
||||
{
|
||||
if (m_window.centralWidget())
|
||||
m_window.showNormal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the visibility & enabled status of the widget
|
||||
*/
|
||||
@ -251,87 +264,69 @@ void WidgetLoader::setWidgetIndex(const int index)
|
||||
{
|
||||
case UI::Dashboard::WidgetType::Group:
|
||||
m_widget = new Widgets::DataGroup(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::DataGroup(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::MultiPlot:
|
||||
m_widget = new Widgets::MultiPlot(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::MultiPlot(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::FFT:
|
||||
m_widget = new Widgets::FFTPlot(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::FFTPlot(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::Plot:
|
||||
m_widget = new Widgets::Plot(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::Plot(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::Bar:
|
||||
m_widget = new Widgets::Bar(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::Bar(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::Gauge:
|
||||
m_widget = new Widgets::Gauge(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::Gauge(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::Compass:
|
||||
m_widget = new Widgets::Compass(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::Compass(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::Gyroscope:
|
||||
m_widget = new Widgets::Gyroscope(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::Gyroscope(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::Accelerometer:
|
||||
m_widget = new Widgets::Accelerometer(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::Accelerometer(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::GPS:
|
||||
m_widget = new Widgets::GPS(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::GPS(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::LED:
|
||||
m_widget = new Widgets::LEDPanel(relativeIndex());
|
||||
m_window.setCentralWidget(new Widgets::LEDPanel(relativeIndex()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Configure external window
|
||||
if (m_window.centralWidget())
|
||||
{
|
||||
m_window.setWindowTitle(widgetTitle());
|
||||
m_window.centralWidget()->setEnabled(false);
|
||||
}
|
||||
|
||||
// Allow widget to receive events from the QML interface
|
||||
if (m_widget)
|
||||
{
|
||||
m_widget->setEnabled(true);
|
||||
m_widget->installEventFilter(this);
|
||||
QTimer::singleShot(100, this, SLOT(updateWidgetVisible()));
|
||||
emit widgetIndexChanged();
|
||||
updateWidgetVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the widget visibility controller source.
|
||||
*
|
||||
* If set to @c true, then the widget visibility shall be controlled
|
||||
* directly by the QML interface.
|
||||
*
|
||||
* If set to @c false, then the widget visbility shall be controlled
|
||||
* by the UI::Dashboard class via the SIGNAL/SLOT system.
|
||||
*/
|
||||
void WidgetLoader::setIsExternalWindow(const bool isWindow)
|
||||
{
|
||||
m_isExternalWindow = isWindow;
|
||||
emit isExternalWindowChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function must be called directly by a QML MouseArea item.
|
||||
* Unfortunatelly, enter/leave events cannot be processed
|
||||
* directly by the @c WidgetLoader::event(QEvent *event) function.
|
||||
*/
|
||||
void WidgetLoader::processMouseHover(const bool containsMouse)
|
||||
{
|
||||
if (containsMouse)
|
||||
{
|
||||
QEnterEvent event(QPoint(0, 0), QPoint(0, 0), QPoint(0, 0));
|
||||
processEnterEvent(&event);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
QEvent event(QEvent::Leave);
|
||||
processLeaveEvent(&event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the widget to fit inside the QML item.
|
||||
*/
|
||||
@ -352,7 +347,7 @@ void WidgetLoader::updateWidgetVisible()
|
||||
{
|
||||
bool visible = UI::Dashboard::getInstance()->widgetVisible(widgetIndex());
|
||||
|
||||
if (widgetVisible() != visible && !isExternalWindow())
|
||||
if (widgetVisible() != visible)
|
||||
{
|
||||
m_widgetVisible = visible;
|
||||
|
||||
@ -363,6 +358,16 @@ void WidgetLoader::updateWidgetVisible()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/disables the widget updates of the external window when the window
|
||||
* is shown or hidden.
|
||||
*/
|
||||
void WidgetLoader::updateExternalWindow()
|
||||
{
|
||||
if (m_window.centralWidget())
|
||||
m_window.centralWidget()->setEnabled(m_window.isVisible());
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets the widget handle the mouse leave events
|
||||
*/
|
||||
|
@ -25,12 +25,34 @@
|
||||
#include <QWidget>
|
||||
#include <QObject>
|
||||
#include <QPainter>
|
||||
#include <QMainWindow>
|
||||
#include <QQuickPaintedItem>
|
||||
|
||||
#include <UI/Dashboard.h>
|
||||
|
||||
namespace UI
|
||||
{
|
||||
class WidgetWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void visibleChanged();
|
||||
|
||||
private:
|
||||
void showEvent(QShowEvent *event)
|
||||
{
|
||||
event->accept();
|
||||
emit visibleChanged();
|
||||
}
|
||||
|
||||
void hideEvent(QHideEvent *event)
|
||||
{
|
||||
event->accept();
|
||||
emit visibleChanged();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The WidgetLoader class
|
||||
*
|
||||
@ -76,10 +98,6 @@ class WidgetLoader : public QQuickPaintedItem
|
||||
Q_PROPERTY(QString widgetTitle
|
||||
READ widgetTitle
|
||||
NOTIFY widgetIndexChanged)
|
||||
Q_PROPERTY(bool isExternalWindow
|
||||
READ isExternalWindow
|
||||
WRITE setIsExternalWindow
|
||||
NOTIFY isExternalWindowChanged)
|
||||
Q_PROPERTY(bool widgetVisible
|
||||
READ widgetVisible
|
||||
WRITE setVisible
|
||||
@ -89,7 +107,6 @@ class WidgetLoader : public QQuickPaintedItem
|
||||
signals:
|
||||
void widgetIndexChanged();
|
||||
void widgetVisibleChanged();
|
||||
void isExternalWindowChanged();
|
||||
|
||||
public:
|
||||
WidgetLoader(QQuickItem *parent = 0);
|
||||
@ -104,18 +121,17 @@ public:
|
||||
bool widgetVisible() const;
|
||||
QString widgetIcon() const;
|
||||
QString widgetTitle() const;
|
||||
bool isExternalWindow() const;
|
||||
UI::Dashboard::WidgetType widgetType() const;
|
||||
|
||||
public slots:
|
||||
void showExternalWindow();
|
||||
void setVisible(const bool visible);
|
||||
void setWidgetIndex(const int index);
|
||||
void setIsExternalWindow(const bool isWindow);
|
||||
void processMouseHover(const bool containsMouse);
|
||||
|
||||
private slots:
|
||||
void updateWidgetSize();
|
||||
void updateWidgetVisible();
|
||||
void updateExternalWindow();
|
||||
|
||||
protected:
|
||||
void processLeaveEvent(QEvent *event);
|
||||
@ -127,6 +143,6 @@ private:
|
||||
int m_index;
|
||||
QWidget *m_widget;
|
||||
bool m_widgetVisible;
|
||||
bool m_isExternalWindow;
|
||||
WidgetWindow m_window;
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user