Fix UI glitches in external window with HiDPI screens

This commit is contained in:
Alex Spataru 2021-10-01 04:12:04 -05:00
parent 5144695aaf
commit 92b0a0193e
7 changed files with 99 additions and 225 deletions

View File

@ -174,7 +174,6 @@ HEADERS += \
src/Widgets/Common/AnalogGauge.h \
src/Widgets/Common/AttitudeIndicator.h \
src/Widgets/Common/BaseWidget.h \
src/Widgets/Common/ExternalWindow.h \
src/Widgets/Compass.h \
src/Widgets/DataGroup.h \
src/Widgets/Gauge.h \
@ -213,7 +212,6 @@ SOURCES += \
src/Widgets/Common/AnalogGauge.cpp \
src/Widgets/Common/AttitudeIndicator.cpp \
src/Widgets/Common/BaseWidget.cpp \
src/Widgets/Common/ExternalWindow.cpp \
src/Widgets/Compass.cpp \
src/Widgets/DataGroup.cpp \
src/Widgets/Gauge.cpp \

View File

@ -21,6 +21,7 @@
*/
import QtQuick
import QtQuick.Window
import QtQuick.Layouts
import QtQuick.Controls
@ -37,7 +38,7 @@ Item {
anchors.fill: parent
title: loader.widgetTitle
icon.source: loader.widgetIcon
onHeaderDoubleClicked: loader.displayWindow()
onHeaderDoubleClicked: externalWindow.visible = true
borderColor: Cpp_ThemeManager.datasetWindowBorder
WidgetLoader {
@ -56,4 +57,22 @@ Item {
source: window
anchors.fill: window
}
Window {
id: externalWindow
minimumWidth: 640
minimumHeight: 480
title: externalLoader.widgetTitle
palette.base: Cpp_ThemeManager.datasetWindowBackground
palette.window: Cpp_ThemeManager.datasetWindowBackground
flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
WidgetLoader {
id: externalLoader
widgetIndex: index
anchors.fill: parent
isExternalWindow: true
widgetVisible: externalWindow.visible
}
}
}

View File

@ -1,61 +0,0 @@
/*
* Copyright (c) 2020-2021 Alex Spataru <https://github.com/alex-spataru>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "ExternalWindow.h"
#include <QShowEvent>
#include <QHideEvent>
using namespace Widgets;
ExternalWindow::ExternalWindow()
: m_widget(nullptr)
{
setLayout(&m_layout);
}
QWidget *ExternalWindow::widget()
{
return m_widget;
}
void ExternalWindow::setWidget(QWidget *widget)
{
Q_ASSERT(widget);
if (m_widget)
m_layout.removeWidget(m_widget);
m_layout.addWidget(widget);
}
void ExternalWindow::showEvent(QShowEvent *event)
{
event->accept();
emit visibleChanged();
}
void ExternalWindow::hideEvent(QHideEvent *event)
{
event->accept();
emit visibleChanged();
}

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2020-2021 Alex Spataru <https://github.com/alex-spataru>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef WIDGETS_COMMON_EXTERNAL_WINDOW_H
#define WIDGETS_COMMON_EXTERNAL_WINDOW_H
#include <QDialog>
#include <QHBoxLayout>
namespace Widgets
{
class ExternalWindow : public QDialog
{
Q_OBJECT
signals:
void visibleChanged();
public:
ExternalWindow();
QWidget *widget();
void setWidget(QWidget *widget);
protected:
void showEvent(QShowEvent *event);
void hideEvent(QHideEvent *event);
private:
QWidget *m_widget;
QHBoxLayout m_layout;
};
}
#endif

View File

@ -46,6 +46,7 @@ WidgetLoader::WidgetLoader(QQuickItem *parent)
, m_index(-1)
, m_widget(nullptr)
, m_widgetVisible(false)
, m_isExternalWindow(false)
{
// Set item flags
setFlag(ItemHasContents, true);
@ -53,17 +54,6 @@ WidgetLoader::WidgetLoader(QQuickItem *parent)
setFlag(ItemAcceptsInputMethod, true);
setAcceptedMouseButtons(Qt::AllButtons);
// Configure main window
m_window.setMinimumWidth(640);
m_window.setMinimumHeight(480);
// Set window palette
QPalette palette;
auto theme = Misc::ThemeManager::getInstance();
palette.setColor(QPalette::Base, theme->datasetWindowBackground());
palette.setColor(QPalette::Window, theme->datasetWindowBackground());
m_window.setPalette(palette);
// Resize widget to fit QML item size
connect(this, &QQuickPaintedItem::widthChanged, this,
&WidgetLoader::updateWidgetSize);
@ -73,9 +63,6 @@ WidgetLoader::WidgetLoader(QQuickItem *parent)
// Automatically update the widget's visibility
connect(UI::Dashboard::getInstance(), &UI::Dashboard::widgetVisibilityChanged, this,
&WidgetLoader::updateWidgetVisible);
// Enable/disable the window widget automatically
connect(&m_window, SIGNAL(visibleChanged()), this, SLOT(updateWidgetWindow()));
}
/**
@ -198,6 +185,11 @@ QString WidgetLoader::widgetTitle() const
return tr("Invalid");
}
bool WidgetLoader::isExternalWindow() const
{
return m_isExternalWindow;
}
/**
* Returns the type of the current widget (e.g. group, plot, bar, gauge, etc...)
*/
@ -206,12 +198,10 @@ UI::Dashboard::WidgetType WidgetLoader::widgetType() const
return UI::Dashboard::getInstance()->widgetType(widgetIndex());
}
/**
* Shows a window with the current widget
*/
void WidgetLoader::displayWindow()
void WidgetLoader::setVisible(const bool visible)
{
m_window.showNormal();
if (m_widget)
m_widget->setEnabled(visible);
}
/**
@ -231,20 +221,11 @@ void WidgetLoader::setWidgetIndex(const int index)
m_widget = nullptr;
}
// Delete central widget of window
if (m_window.widget())
delete m_window.widget();
// Hide widget window
if (m_window.isVisible())
m_window.hide();
// Construct new widget
switch (widgetType())
{
case UI::Dashboard::WidgetType::Group:
m_widget = new DataGroup(relativeIndex());
m_window.setWidget(new DataGroup(relativeIndex()));
break;
case UI::Dashboard::WidgetType::MultiPlot:
m_widget = new QPushButton("Multi-Plot");
@ -254,26 +235,21 @@ void WidgetLoader::setWidgetIndex(const int index)
break;
case UI::Dashboard::WidgetType::Bar:
m_widget = new Bar(relativeIndex());
m_window.setWidget(new Bar(relativeIndex()));
break;
case UI::Dashboard::WidgetType::Gauge:
m_widget = new Gauge(relativeIndex());
m_window.setWidget(new Gauge(relativeIndex()));
break;
case UI::Dashboard::WidgetType::Thermometer:
m_widget = new QPushButton("Thermometer");
break;
case UI::Dashboard::WidgetType::Compass:
m_widget = new Compass(relativeIndex());
m_window.setWidget(new Compass(relativeIndex()));
break;
case UI::Dashboard::WidgetType::Gyroscope:
m_widget = new Gyroscope(relativeIndex());
m_window.setWidget(new Gyroscope(relativeIndex()));
break;
case UI::Dashboard::WidgetType::Accelerometer:
m_widget = new Accelerometer(relativeIndex());
m_window.setWidget(new Accelerometer(relativeIndex()));
break;
case UI::Dashboard::WidgetType::Map:
m_widget = new QPushButton("Map");
@ -282,11 +258,6 @@ void WidgetLoader::setWidgetIndex(const int index)
break;
}
// Update window title
m_window.setWindowTitle(widgetTitle());
if (m_window.widget())
m_window.widget()->setEnabled(false);
// Allow widget to receive events from the QML interface
if (m_widget)
{
@ -298,6 +269,12 @@ void WidgetLoader::setWidgetIndex(const int index)
}
}
void WidgetLoader::setIsExternalWindow(const bool isWindow)
{
m_isExternalWindow = isWindow;
emit isExternalWindowChanged();
}
/**
* Resizes the widget to fit inside the QML item.
*/
@ -310,16 +287,6 @@ void WidgetLoader::updateWidgetSize()
}
}
/**
* Enables/disables the widget updates of the external window when the window
* is shown or hidden.
*/
void WidgetLoader::updateWidgetWindow()
{
if (m_window.widget())
m_window.widget()->setEnabled(m_window.isVisible());
}
/**
* Updates the visibility status of the current widget (this function is called
* automatically by the UI::Dashboard class via signals/slots).
@ -328,16 +295,13 @@ void WidgetLoader::updateWidgetVisible()
{
bool visible = UI::Dashboard::getInstance()->widgetVisible(widgetIndex());
if (widgetVisible() != visible)
if (widgetVisible() != visible && !isExternalWindow())
{
m_widgetVisible = visible;
if (m_widget)
m_widget->setEnabled(visible);
if (m_window.widget())
m_window.widget()->setEnabled(visible);
emit widgetVisibleChanged();
}
}

View File

@ -30,8 +30,6 @@
#include <UI/Dashboard.h>
#include "Common/ExternalWindow.h"
namespace Widgets
{
class WidgetLoader : public QQuickPaintedItem
@ -55,11 +53,20 @@ class WidgetLoader : public QQuickPaintedItem
Q_PROPERTY(bool widgetVisible
READ widgetVisible
NOTIFY widgetVisibleChanged)
Q_PROPERTY(bool isExternalWindow
READ isExternalWindow
WRITE setIsExternalWindow
NOTIFY isExternalWindowChanged)
Q_PROPERTY(bool widgetVisible
READ widgetVisible
WRITE setVisible
NOTIFY widgetVisibleChanged)
// clang-format on
signals:
void widgetIndexChanged();
void widgetVisibleChanged();
void isExternalWindowChanged();
public:
WidgetLoader(QQuickItem *parent = 0);
@ -74,15 +81,16 @@ public:
bool widgetVisible() const;
QString widgetIcon() const;
QString widgetTitle() const;
bool isExternalWindow() const;
UI::Dashboard::WidgetType widgetType() const;
public slots:
void displayWindow();
void setVisible(const bool visible);
void setWidgetIndex(const int index);
void setIsExternalWindow(const bool isWindow);
private slots:
void updateWidgetSize();
void updateWidgetWindow();
void updateWidgetVisible();
protected:
@ -92,8 +100,8 @@ protected:
private:
int m_index;
QWidget *m_widget;
ExternalWindow m_window;
bool m_widgetVisible;
bool m_isExternalWindow;
};
}