From 48ad79ee1ef9f850c99b4a3eebd85098ad054128 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 30 Mar 2023 13:27:34 +0200 Subject: [PATCH] Utils: Introduce UniqueObjectPtr We very often want to remove a Qobject in a scope but because it has a parent it can be deleted earlier. So using std::unique_ptr can lead to double deletion. UniqueObjectPtr can track if a pointer is already deleted. So no double deletion is possible but we still delete the object in that scope. UniqueObjectPtr is based on std::unique_ptr but uses a QPointer as internal pointer representation. Because QPointer is not convertable you cannot cast from one type to an other(QTBUG-112464). Because of that UniqueObjectInternalPointer derives from QPointer and adds a conversion constructor. Change-Id: I2c7707489f6db836cc5db2463efa8c33932b6455 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Thomas Hartmann --- src/libs/utils/CMakeLists.txt | 1 + src/libs/utils/uniqueobjectptr.h | 58 +++++++++++++++++++ src/libs/utils/utils.qbs | 1 + .../components/toolbar/toolbar.cpp | 12 ++-- .../qmldesigner/components/toolbar/toolbar.h | 6 +- src/plugins/qmldesigner/qmldesignerplugin.cpp | 6 +- 6 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 src/libs/utils/uniqueobjectptr.h diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt index 59728939cb7..8777a6a881a 100644 --- a/src/libs/utils/CMakeLists.txt +++ b/src/libs/utils/CMakeLists.txt @@ -186,6 +186,7 @@ add_qtc_library(Utils treemodel.cpp treemodel.h treeviewcombobox.cpp treeviewcombobox.h uncommentselection.cpp uncommentselection.h + uniqueobjectptr.h unixutils.cpp unixutils.h url.cpp url.h utils.qrc diff --git a/src/libs/utils/uniqueobjectptr.h b/src/libs/utils/uniqueobjectptr.h new file mode 100644 index 00000000000..e660e459564 --- /dev/null +++ b/src/libs/utils/uniqueobjectptr.h @@ -0,0 +1,58 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +#include +#include + +namespace Utils { + +namespace Internal { + +template +class UniqueObjectInternalPointer : public QPointer +{ +public: + using QPointer::QPointer; + + template + && !std::is_same_v, std::decay_t>>> + UniqueObjectInternalPointer(const UniqueObjectInternalPointer &p) noexcept + : QPointer{p.data()} + {} +}; + +template +struct UniqueObjectPtrDeleter +{ + using pointer = UniqueObjectInternalPointer; + + constexpr UniqueObjectPtrDeleter() noexcept = default; + template>> + constexpr UniqueObjectPtrDeleter(const UniqueObjectPtrDeleter &) noexcept + {} + + constexpr void operator()(pointer p) const + { + static_assert(!std::is_void_v, "can't delete pointer to incomplete type"); + static_assert(sizeof(Type) > 0, "can't delete pointer to incomplete type"); + + delete p.data(); + } +}; + +} // namespace Internal + +template +using UniqueObjectPtr = std::unique_ptr>; + +template +auto makeUniqueObjectPtr(Arguments &&...arguments) +{ + return UniqueObjectPtr{new Type(std::forward(arguments)...)}; +} +} // namespace Utils diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index 6fb84c69cc2..451a9f34943 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -329,6 +329,7 @@ Project { "headerviewstretcher.h", "uncommentselection.cpp", "uncommentselection.h", + "uniqueobjectptr.h" "unixutils.cpp", "unixutils.h", "url.cpp", diff --git a/src/plugins/qmldesigner/components/toolbar/toolbar.cpp b/src/plugins/qmldesigner/components/toolbar/toolbar.cpp index 436515caa47..c8e05999ed0 100644 --- a/src/plugins/qmldesigner/components/toolbar/toolbar.cpp +++ b/src/plugins/qmldesigner/components/toolbar/toolbar.cpp @@ -47,7 +47,7 @@ Utils::FilePath qmlSourcesPath() return Core::ICore::resourcePath("qmldesigner/toolbar"); } -std::unique_ptr ToolBar::create() +Utils::UniqueObjectPtr ToolBar::create() { if (!isVisible()) return nullptr; @@ -58,7 +58,7 @@ std::unique_ptr ToolBar::create() //Core::ICore::statusBar()->hide(); - auto toolBar = std::make_unique(); + auto toolBar = Utils::makeUniqueObjectPtr(); toolBar->setObjectName("QDS-TOOLBAR"); toolBar->setContextMenuPolicy(Qt::PreventContextMenu); @@ -66,7 +66,7 @@ std::unique_ptr ToolBar::create() toolBar->setFloatable(false); toolBar->setMovable(false); - auto quickWidget = new StudioQuickWidget; + auto quickWidget = std::make_unique(); quickWidget->setFixedHeight(48); quickWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); @@ -84,20 +84,20 @@ std::unique_ptr ToolBar::create() quickWidget->setSource(QUrl::fromLocalFile(qmlFilePath.toFSPathString())); - toolBar->addWidget(quickWidget); + toolBar->addWidget(quickWidget.release()); window->addToolBar(toolBar.get()); return toolBar; } -std::unique_ptr ToolBar::createStatusBar() +Utils::UniqueObjectPtr ToolBar::createStatusBar() { if (!isVisible()) return nullptr; ToolBarBackend::registerDeclarativeType(); - auto quickWidget = std::make_unique(); + auto quickWidget = Utils::makeUniqueObjectPtr(); quickWidget->setFixedHeight(Theme::toolbarSize()); quickWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); diff --git a/src/plugins/qmldesigner/components/toolbar/toolbar.h b/src/plugins/qmldesigner/components/toolbar/toolbar.h index 1cdb2121c65..d086fdf3ed2 100644 --- a/src/plugins/qmldesigner/components/toolbar/toolbar.h +++ b/src/plugins/qmldesigner/components/toolbar/toolbar.h @@ -5,7 +5,7 @@ #include -#include +#include namespace QmlDesigner { @@ -13,8 +13,8 @@ class ToolBar { public: - static std::unique_ptr create(); - static std::unique_ptr createStatusBar(); + static Utils::UniqueObjectPtr create(); + static Utils::UniqueObjectPtr createStatusBar(); static bool isVisible(); }; diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index c41e272ad26..47c20047aa6 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -31,7 +31,6 @@ #include #include #include - #include #include #include @@ -66,6 +65,7 @@ #include #include #include +#include #include #include @@ -144,8 +144,8 @@ public: DesignModeWidget mainWidget; QtQuickDesignerFactory m_qtQuickDesignerFactory; bool blockEditorChange = false; - std::unique_ptr toolBar; - std::unique_ptr statusBar; + Utils::UniqueObjectPtr toolBar; + Utils::UniqueObjectPtr statusBar; }; QmlDesignerPlugin *QmlDesignerPlugin::m_instance = nullptr;