routine code quality improvement

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-09-15 18:24:34 +08:00
parent 31eed109a0
commit 91bb8273b8
13 changed files with 133 additions and 55 deletions

View File

@ -9,6 +9,7 @@
#include <QtWidgets/qpushbutton.h>
#include <QtWidgets/qboxlayout.h>
#include <QtWidgets/qfileiconprovider.h>
#include <QtWidgets/qmessagebox.h>
#include <StandardTitleBar>
#include <FramelessWidgetsHelper>
#include <StandardSystemButton>
@ -44,6 +45,14 @@ void Dialog::setupUi()
findButton = new QPushButton(tr("&Find"));
findButton->setDefault(true);
connect(findButton, &QPushButton::clicked, this, [this](){
const QString text = lineEdit->text();
if (text.isEmpty()) {
QMessageBox::warning(this, tr("Warning"), tr("You didn't enter anything in the search box."));
} else {
QMessageBox::information(this, tr("Result"), tr("You wanted to find: \"%1\".").arg(text));
}
});
moreButton = new QPushButton(tr("&More"));
moreButton->setCheckable(true);

View File

@ -113,7 +113,7 @@ Q_SIGNALS:
private:
void initialize();
void updateAll();
void mouseEventHandler(const QMouseEvent *event);
Q_NODISCARD bool mouseEventHandler(QMouseEvent *event);
Q_NODISCARD QRect windowIconRect() const;
Q_NODISCARD bool isInTitleBarIconArea(const QPoint &pos) const;
Q_NODISCARD bool windowIconVisible_real() const;

View File

@ -77,7 +77,7 @@ public:
Q_NODISCARD QFont titleFont() const;
void setTitleFont(const QFont &value);
void mouseEventHandler(const QMouseEvent *event);
Q_NODISCARD bool mouseEventHandler(QMouseEvent *event);
Q_NODISCARD QRect windowIconRect() const;
Q_NODISCARD bool windowIconVisible_real() const;

View File

@ -38,35 +38,39 @@ function(setup_compile_params arg_target)
QT_DISABLE_DEPRECATED_BEFORE=0x070000
QT_DISABLE_DEPRECATED_UP_TO=0x070000 # Since 6.5
)
if(MSVC)
if(WIN32) # Needed by both MSVC and MinGW
set(_WIN32_WINNT_WIN10 0x0A00)
set(NTDDI_WIN10_CO 0x0A00000B)
target_compile_definitions(${arg_target} PRIVATE
WINVER=${_WIN32_WINNT_WIN10} _WIN32_WINNT=${_WIN32_WINNT_WIN10}
_WIN32_IE=${_WIN32_WINNT_WIN10} NTDDI_VERSION=${NTDDI_WIN10_CO}
)
endif()
if(MSVC)
target_compile_definitions(${arg_target} PRIVATE
_CRT_NON_CONFORMING_SWPRINTFS _CRT_SECURE_NO_WARNINGS
_CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_WARNINGS
_CRT_NONSTDC_NO_DEPRECATE _ENABLE_EXTENDED_ALIGNED_STORAGE
NOMINMAX UNICODE _UNICODE WIN32_LEAN_AND_MEAN WINRT_LEAN_AND_MEAN
WINVER=${_WIN32_WINNT_WIN10} _WIN32_WINNT=${_WIN32_WINNT_WIN10}
_WIN32_IE=${_WIN32_WINNT_WIN10} NTDDI_VERSION=${NTDDI_WIN10_CO}
)
target_compile_options(${arg_target} PRIVATE
/utf-8 /W3 /WX # Cannot use /W4 here, Qt's own headers are not warning-clean.
/utf-8 /W3 /WX # Can't use /W4 here, Qt's own headers are not warning-clean, especially QtQuick headers.
$<$<CONFIG:Debug>:/JMC>
$<$<NOT:$<CONFIG:Debug>>:/guard:cf /Gw /Gy /QIntel-jcc-erratum /Zc:inline> # /guard:ehcont ? /Qspectre-load ?
$<$<NOT:$<CONFIG:Debug>>:/guard:cf /Gw /Gy /QIntel-jcc-erratum /Zc:inline> # /guard:ehcont? /Qspectre-load?
)
target_link_options(${arg_target} PRIVATE
/WX # Make sure we don't use wrong parameters.
$<$<NOT:$<CONFIG:Debug>>:/CETCOMPAT /GUARD:CF /OPT:REF /OPT:ICF> # /GUARD:EHCONT ?
$<$<NOT:$<CONFIG:Debug>>:/CETCOMPAT /GUARD:CF /OPT:REF /OPT:ICF> # /GUARD:EHCONT?
)
else()
target_compile_options(${arg_target} PRIVATE
-Wall -Wextra -Werror
#$<$<NOT:$<CONFIG:Debug>>:-ffunction-sections -fdata-sections -fcf-protection=full -Wa,-mno-branches-within-32B-boundaries>
$<$<NOT:$<CONFIG:Debug>>:-ffunction-sections -fdata-sections -fcf-protection=full> # -Wa,-mno-branches-within-32B-boundaries?
)
#[[target_link_options(${arg_target} PRIVATE
target_link_options(${arg_target} PRIVATE
$<$<NOT:$<CONFIG:Debug>>:-Wl,--gc-sections>
)
if(CLANG)
#[[if(CLANG)
target_compile_options(${arg_target} PRIVATE
$<$<NOT:$<CONFIG:Debug>>:-Xclang -cfguard -mretpoline>
)

View File

@ -122,24 +122,24 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
managerPriv->notifySystemThemeHasChangedOrNot();
}
}
return false;
return QObject::eventFilter(object, event);
}
// We are only interested in events that are dispatched to top level windows.
if (!object->isWindowType()) {
return false;
return QObject::eventFilter(object, event);
}
const QEvent::Type type = event->type();
// We are only interested in some specific mouse events.
if ((type != QEvent::MouseButtonPress) && (type != QEvent::MouseButtonRelease)
&& (type != QEvent::MouseButtonDblClick) && (type != QEvent::MouseMove)) {
return false;
return QObject::eventFilter(object, event);
}
const auto window = qobject_cast<QWindow *>(object);
const WId windowId = window->winId();
g_qtHelper()->mutex.lock();
if (!g_qtHelper()->data.contains(windowId)) {
g_qtHelper()->mutex.unlock();
return false;
return QObject::eventFilter(object, event);
}
const QtHelperData data = g_qtHelper()->data.value(windowId);
g_qtHelper()->mutex.unlock();
@ -166,6 +166,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
const Qt::Edges edges = Utils::calculateWindowEdges(window, scenePos);
if (edges != Qt::Edges{}) {
Utils::startSystemResize(window, edges, globalPos);
event->accept();
return true;
}
}
@ -179,6 +180,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
if (button == Qt::RightButton) {
if (!ignoreThisEvent && insideTitleBar) {
data.params.showSystemMenu(scenePos);
event->accept();
return true;
}
}
@ -190,6 +192,8 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
newWindowState = Qt::WindowMaximized;
}
data.params.setWindowState(newWindowState);
event->accept();
return true;
}
} break;
case QEvent::MouseMove: {
@ -210,6 +214,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
if (data.leftButtonPressed) {
if (!ignoreThisEvent && insideTitleBar) {
Utils::startSystemMove(window, globalPos);
event->accept();
return true;
}
}
@ -217,7 +222,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
default:
break;
}
return false;
return QObject::eventFilter(object, event);
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -764,6 +764,11 @@ void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const bool sel
// Popup the system menu at the required position.
const int result = TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft()
? TPM_RIGHTALIGN : TPM_LEFTALIGN)), pos.x(), pos.y(), 0, hWnd, nullptr);
// Unhighlight the first menu item after the popup menu is closed, otherwise it will keep
// highlighting until we unhighlight it manually.
HiliteMenuItem(hWnd, hMenu, SC_RESTORE, (MF_BYCOMMAND | MFS_UNHILITE));
if (result == 0) {
// The user canceled the menu, no need to continue.
return;

View File

@ -801,19 +801,35 @@ FramelessQuickHelper *FramelessQuickHelper::get(QObject *object)
if (!object) {
return nullptr;
}
FramelessQuickHelper *instance = nullptr;
QObject *parent = nullptr;
if (const auto item = qobject_cast<QQuickItem *>(object)) {
parent = ((item->window() && item->window()->contentItem()) ? item->window()->contentItem() : item);
QQuickItem *parentItem = nullptr;
if (const auto window = qobject_cast<QQuickWindow *>(object)) {
if (QQuickItem * const item = window->contentItem()) {
parent = item;
parentItem = item;
} else {
parent = window;
}
} else if (const auto item = qobject_cast<QQuickItem *>(object)) {
if (QQuickWindow * const window = item->window()) {
if (QQuickItem * const contentItem = window->contentItem()) {
parent = contentItem;
parentItem = contentItem;
} else {
parent = window;
parentItem = item;
}
} else {
parent = item;
parentItem = item;
}
} else {
parent = object;
}
instance = parent->findChild<FramelessQuickHelper *>();
FramelessQuickHelper *instance = parent->findChild<FramelessQuickHelper *>();
if (!instance) {
instance = new FramelessQuickHelper;
if (const auto item = qobject_cast<QQuickItem *>(parent)) {
instance->setParentItem(item);
}
instance->setParentItem(parentItem);
instance->setParent(parent);
// No need to do this here, we'll do it once the item has been assigned to a specific window.
//instance->d_func()->attachToWindow();
@ -943,14 +959,19 @@ void FramelessQuickHelper::itemChange(const ItemChange change, const ItemChangeD
{
QQuickItem::itemChange(change, value);
if ((change == ItemSceneChange) && value.window) {
const QObject * const p = parent();
const QQuickItem * const pItem = parentItem();
QQuickItem * const rootItem = value.window->contentItem();
if (rootItem) {
if ((parentItem() != rootItem) || (parent() != rootItem)) {
if ((pItem != rootItem) || (p != rootItem)) {
setParentItem(rootItem);
setParent(rootItem);
}
} else {
if (parent() != value.window) {
if (pItem != nullptr) {
setParentItem(nullptr);
}
if (p != value.window) {
setParent(value.window);
}
}

View File

@ -357,11 +357,11 @@ void QuickStandardTitleBar::updateWindowIcon()
m_windowIcon->setSource(icon);
}
void QuickStandardTitleBar::mouseEventHandler(const QMouseEvent *event)
bool QuickStandardTitleBar::mouseEventHandler(QMouseEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
return false;
}
const Qt::MouseButton button = event->button();
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
@ -402,6 +402,7 @@ void QuickStandardTitleBar::mouseEventHandler(const QMouseEvent *event)
return scenePos;
}());
});
// Don't eat this event, we have not handled it yet.
}
break;
case QEvent::MouseButtonDblClick:
@ -409,12 +410,16 @@ void QuickStandardTitleBar::mouseEventHandler(const QMouseEvent *event)
if ((button == Qt::LeftButton) && interestArea) {
m_closeTriggered = true;
w->close();
// Eat this event, we have handled it here.
event->accept();
return true;
}
}
break;
default:
break;
}
return false;
}
QRect QuickStandardTitleBar::windowIconRect() const
@ -521,6 +526,8 @@ void QuickStandardTitleBar::itemChange(const ItemChange change, const ItemChange
m_windowTitleChangeConnection = connect(value.window, &QQuickWindow::windowTitleChanged, this, &QuickStandardTitleBar::updateTitleLabelText);
updateAll();
value.window->installEventFilter(this);
// The window has changed, we need to re-add or re-remove the window icon rect to
// the hit test visible whitelist. This is different with Qt Widgets.
FramelessQuickHelper::get(this)->setHitTestVisible(windowIconRect(), windowIconVisible_real());
}
}
@ -542,9 +549,14 @@ bool QuickStandardTitleBar::eventFilter(QObject *object, QEvent *event)
const QEvent::Type type = event->type();
if (type == QEvent::LanguageChange) {
retranslateUi();
// Don't eat the event here, we need it to keep dispatching to other
// objects that may be interested in this event.
} else if ((type >= QEvent::MouseButtonPress) && (type <= QEvent::MouseMove)) {
const auto mouseEvent = static_cast<QMouseEvent *>(event);
mouseEventHandler(mouseEvent);
if (mouseEventHandler(mouseEvent)) {
// We have handled the event already, stop dispatching.
return true;
}
}
return QQuickRectangle::eventFilter(object, event);
}

View File

@ -28,12 +28,14 @@
#include "framelesswidgetshelper.h"
#include "framelesswidget.h"
#include "framelessmainwindow.h"
#include "framelessdialog.h"
#include "widgetssharedhelper_p.h"
#include "standardtitlebar_p.h"
#include "standardsystembutton_p.h"
#include "framelesswidgetshelper_p.h"
#include "framelesswidget_p.h"
#include "framelessmainwindow_p.h"
#include "framelessdialog_p.h"
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -62,12 +64,14 @@ void initialize()
qRegisterMetaType<FramelessWidgetsHelper>();
qRegisterMetaType<FramelessWidget>();
qRegisterMetaType<FramelessMainWindow>();
qRegisterMetaType<FramelessDialog>();
qRegisterMetaType<WidgetsSharedHelper>();
qRegisterMetaType<StandardTitleBarPrivate>();
qRegisterMetaType<StandardSystemButtonPrivate>();
qRegisterMetaType<FramelessWidgetsHelperPrivate>();
qRegisterMetaType<FramelessWidgetPrivate>();
qRegisterMetaType<FramelessMainWindowPrivate>();
qRegisterMetaType<FramelessDialogPrivate>();
#endif
}

View File

@ -421,15 +421,10 @@ void FramelessWidgetsHelperPrivate::attachToWindow()
QWidget *FramelessWidgetsHelperPrivate::getWindow() const
{
Q_Q(const FramelessWidgetsHelper);
const auto parentWidget = qobject_cast<QWidget *>(q->parent());
if (!parentWidget) {
return nullptr;
if (const auto parentWidget = qobject_cast<QWidget *>(q->parent())) {
return (parentWidget->nativeParentWidget() ? parentWidget->nativeParentWidget() : parentWidget->window());
}
QWidget * const nativeParentWidget = parentWidget->nativeParentWidget();
if (nativeParentWidget) {
return nativeParentWidget;
}
return parentWidget->window();
return nullptr;
}
WidgetsHelperData FramelessWidgetsHelperPrivate::getWindowData() const
@ -782,15 +777,13 @@ FramelessWidgetsHelper *FramelessWidgetsHelper::get(QObject *object)
if (!object) {
return nullptr;
}
FramelessWidgetsHelper *instance = nullptr;
QObject *parent = nullptr;
if (object->isWidgetType()) {
const auto widget = qobject_cast<QWidget *>(object);
if (const auto widget = qobject_cast<QWidget *>(object)) {
parent = (widget->nativeParentWidget() ? widget->nativeParentWidget() : widget->window());
} else {
parent = object;
}
instance = parent->findChild<FramelessWidgetsHelper *>();
FramelessWidgetsHelper *instance = parent->findChild<FramelessWidgetsHelper *>();
if (!instance) {
instance = new FramelessWidgetsHelper(parent);
instance->d_func()->attachToWindow();

View File

@ -25,6 +25,7 @@
#include "standardsystembutton.h"
#include "standardsystembutton_p.h"
#include <QtGui/qpainter.h>
#include <QtGui/qevent.h>
#include <QtWidgets/qtooltip.h>
#include <framelessmanager_p.h>
#include <utils.h>
@ -314,6 +315,7 @@ void StandardSystemButtonPrivate::enterEventHandler(QT_ENTER_EVENT_TYPE *event)
return;
}
setHovered(true);
event->accept();
}
void StandardSystemButtonPrivate::leaveEventHandler(QEvent *event)
@ -323,6 +325,7 @@ void StandardSystemButtonPrivate::leaveEventHandler(QEvent *event)
return;
}
setHovered(false);
event->accept();
}
void StandardSystemButtonPrivate::paintEventHandler(QPaintEvent *event)
@ -373,6 +376,7 @@ void StandardSystemButtonPrivate::paintEventHandler(QPaintEvent *event)
painter.drawText(buttonRect, Qt::AlignCenter, m_code);
}
painter.restore();
event->accept();
}
void StandardSystemButtonPrivate::initialize()

View File

@ -126,7 +126,10 @@ ChromePalette *StandardTitleBarPrivate::chromePalette() const
void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event)
{
Q_UNUSED(event);
Q_ASSERT(event);
if (!event) {
return;
}
Q_Q(StandardTitleBar);
if (!m_window || m_chromePalette.isNull()) {
return;
@ -181,6 +184,7 @@ void StandardTitleBarPrivate::paintTitleBar(QPaintEvent *event)
}
}
painter.restore();
event->accept();
}
bool StandardTitleBarPrivate::titleLabelVisible() const
@ -230,6 +234,13 @@ void StandardTitleBarPrivate::setWindowIconVisible(const bool value)
return;
}
m_windowIconVisible = value;
// Ideally we should use FramelessWidgetsHelper::get(this) everywhere, but sadly when
// we call it here, it may be too early that FramelessWidgetsHelper has not attached
// to the top level widget yet, and thus it will trigger an assert error (the assert
// should not be suppressed, because it usually indicates there's something really
// wrong). So here we have to use the top level widget directly, as a special case.
// NOTE: In your own code, you should always use FramelessWidgetsHelper::get(this)
// if possible.
FramelessWidgetsHelper::get(m_window)->setHitTestVisible(windowIconRect(), windowIconVisible_real());
Q_Q(StandardTitleBar);
q->update();
@ -252,14 +263,11 @@ void StandardTitleBarPrivate::setTitleFont(const QFont &value)
Q_EMIT q->titleFontChanged();
}
void StandardTitleBarPrivate::mouseEventHandler(const QMouseEvent *event)
bool StandardTitleBarPrivate::mouseEventHandler(QMouseEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
if (!m_window) {
return;
return false;
}
Q_Q(const StandardTitleBar);
const Qt::MouseButton button = event->button();
@ -271,7 +279,8 @@ void StandardTitleBarPrivate::mouseEventHandler(const QMouseEvent *event)
const bool interestArea = isInTitleBarIconArea(scenePos);
switch (event->type()) {
case QEvent::MouseButtonRelease:
if (interestArea) {
// We need a valid top level widget here.
if (m_window && interestArea) {
// Sadly the mouse release events are always triggered before the
// mouse double click events, and if we intercept the mouse release
// events here, we'll never get the double click events afterwards,
@ -294,6 +303,7 @@ void StandardTitleBarPrivate::mouseEventHandler(const QMouseEvent *event)
if (m_closeTriggered) {
return;
}
// Please refer to the comments in StandardTitleBarPrivate::setWindowIconVisible().
FramelessWidgetsHelper::get(m_window)->showSystemMenu([button, q, &scenePos]() -> QPoint {
if (button == Qt::LeftButton) {
return {0, q->height()};
@ -301,17 +311,23 @@ void StandardTitleBarPrivate::mouseEventHandler(const QMouseEvent *event)
return scenePos;
}());
});
// Don't eat this event, we have not handled it yet.
}
break;
case QEvent::MouseButtonDblClick:
if ((button == Qt::LeftButton) && interestArea) {
// We need a valid top level widget here.
if (m_window && (button == Qt::LeftButton) && interestArea) {
m_closeTriggered = true;
m_window->close();
// Eat this event, we have handled it here.
event->accept();
return true;
}
break;
default:
break;
}
return false;
}
QRect StandardTitleBarPrivate::windowIconRect() const
@ -604,14 +620,14 @@ void StandardTitleBar::mouseReleaseEvent(QMouseEvent *event)
{
QWidget::mouseReleaseEvent(event);
Q_D(StandardTitleBar);
d->mouseEventHandler(event);
Q_UNUSED(d->mouseEventHandler(event));
}
void StandardTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
QWidget::mouseDoubleClickEvent(event);
Q_D(StandardTitleBar);
d->mouseEventHandler(event);
Q_UNUSED(d->mouseEventHandler(event));
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -121,15 +121,15 @@ bool WidgetsSharedHelper::eventFilter(QObject *object, QEvent *event)
const auto paintEvent = static_cast<QPaintEvent *>(event);
paintEventHandler(paintEvent);
} break;
case QEvent::WindowStateChange: {
case QEvent::WindowStateChange:
changeEventHandler(event);
} break;
break;
case QEvent::Move:
case QEvent::Resize: {
case QEvent::Resize:
if (m_micaEnabled) {
m_targetWidget->update();
}
} break;
break;
default:
break;
}
@ -179,7 +179,10 @@ void WidgetsSharedHelper::changeEventHandler(QEvent *event)
void WidgetsSharedHelper::paintEventHandler(QPaintEvent *event)
{
Q_UNUSED(event);
Q_ASSERT(event);
if (!event) {
return;
}
if (m_micaEnabled && m_micaMaterial) {
QPainter painter(m_targetWidget);
m_micaMaterial->paint(&painter, m_targetWidget->size(),
@ -205,6 +208,8 @@ void WidgetsSharedHelper::paintEventHandler(QPaintEvent *event)
painter.restore();
}
#endif
// Don't eat this event here, we need Qt to keep dispatching this paint event
// otherwise the widget won't paint anything else from the user side.
}
bool WidgetsSharedHelper::shouldDrawFrameBorder() const