forked from qt-creator/qt-creator
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 <qt_ci_bot@qt-project.org> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -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
|
||||
|
||||
58
src/libs/utils/uniqueobjectptr.h
Normal file
58
src/libs/utils/uniqueobjectptr.h
Normal file
@@ -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 <QPointer>
|
||||
|
||||
#include <memory.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Utils {
|
||||
|
||||
namespace Internal {
|
||||
|
||||
template<typename Type>
|
||||
class UniqueObjectInternalPointer : public QPointer<Type>
|
||||
{
|
||||
public:
|
||||
using QPointer<Type>::QPointer;
|
||||
|
||||
template<typename UpType,
|
||||
typename = std::enable_if_t<std::is_convertible_v<UpType *, Type *>
|
||||
&& !std::is_same_v<std::decay_t<UpType>, std::decay_t<Type>>>>
|
||||
UniqueObjectInternalPointer(const UniqueObjectInternalPointer<UpType> &p) noexcept
|
||||
: QPointer<Type>{p.data()}
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
struct UniqueObjectPtrDeleter
|
||||
{
|
||||
using pointer = UniqueObjectInternalPointer<Type>;
|
||||
|
||||
constexpr UniqueObjectPtrDeleter() noexcept = default;
|
||||
template<typename UpType, typename = std::enable_if_t<std::is_convertible_v<UpType *, Type *>>>
|
||||
constexpr UniqueObjectPtrDeleter(const UniqueObjectPtrDeleter<UpType> &) noexcept
|
||||
{}
|
||||
|
||||
constexpr void operator()(pointer p) const
|
||||
{
|
||||
static_assert(!std::is_void_v<Type>, "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<typename Type>
|
||||
using UniqueObjectPtr = std::unique_ptr<Type, Internal::UniqueObjectPtrDeleter<Type>>;
|
||||
|
||||
template<typename Type, typename... Arguments>
|
||||
auto makeUniqueObjectPtr(Arguments &&...arguments)
|
||||
{
|
||||
return UniqueObjectPtr<Type>{new Type(std::forward<Arguments>(arguments)...)};
|
||||
}
|
||||
} // namespace Utils
|
||||
@@ -329,6 +329,7 @@ Project {
|
||||
"headerviewstretcher.h",
|
||||
"uncommentselection.cpp",
|
||||
"uncommentselection.h",
|
||||
"uniqueobjectptr.h"
|
||||
"unixutils.cpp",
|
||||
"unixutils.h",
|
||||
"url.cpp",
|
||||
|
||||
@@ -47,7 +47,7 @@ Utils::FilePath qmlSourcesPath()
|
||||
return Core::ICore::resourcePath("qmldesigner/toolbar");
|
||||
}
|
||||
|
||||
std::unique_ptr<QToolBar> ToolBar::create()
|
||||
Utils::UniqueObjectPtr<QToolBar> ToolBar::create()
|
||||
{
|
||||
if (!isVisible())
|
||||
return nullptr;
|
||||
@@ -58,7 +58,7 @@ std::unique_ptr<QToolBar> ToolBar::create()
|
||||
|
||||
//Core::ICore::statusBar()->hide();
|
||||
|
||||
auto toolBar = std::make_unique<QToolBar>();
|
||||
auto toolBar = Utils::makeUniqueObjectPtr<QToolBar>();
|
||||
toolBar->setObjectName("QDS-TOOLBAR");
|
||||
|
||||
toolBar->setContextMenuPolicy(Qt::PreventContextMenu);
|
||||
@@ -66,7 +66,7 @@ std::unique_ptr<QToolBar> ToolBar::create()
|
||||
toolBar->setFloatable(false);
|
||||
toolBar->setMovable(false);
|
||||
|
||||
auto quickWidget = new StudioQuickWidget;
|
||||
auto quickWidget = std::make_unique<StudioQuickWidget>();
|
||||
|
||||
quickWidget->setFixedHeight(48);
|
||||
quickWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
@@ -84,20 +84,20 @@ std::unique_ptr<QToolBar> ToolBar::create()
|
||||
|
||||
quickWidget->setSource(QUrl::fromLocalFile(qmlFilePath.toFSPathString()));
|
||||
|
||||
toolBar->addWidget(quickWidget);
|
||||
toolBar->addWidget(quickWidget.release());
|
||||
window->addToolBar(toolBar.get());
|
||||
|
||||
return toolBar;
|
||||
}
|
||||
|
||||
std::unique_ptr<QWidget> ToolBar::createStatusBar()
|
||||
Utils::UniqueObjectPtr<QWidget> ToolBar::createStatusBar()
|
||||
{
|
||||
if (!isVisible())
|
||||
return nullptr;
|
||||
|
||||
ToolBarBackend::registerDeclarativeType();
|
||||
|
||||
auto quickWidget = std::make_unique<StudioQuickWidget>();
|
||||
auto quickWidget = Utils::makeUniqueObjectPtr<StudioQuickWidget>();
|
||||
|
||||
quickWidget->setFixedHeight(Theme::toolbarSize());
|
||||
quickWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <QToolBar>
|
||||
|
||||
#include <memory>
|
||||
#include <utils/uniqueobjectptr.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -13,8 +13,8 @@ class ToolBar
|
||||
{
|
||||
|
||||
public:
|
||||
static std::unique_ptr<QToolBar> create();
|
||||
static std::unique_ptr<QWidget> createStatusBar();
|
||||
static Utils::UniqueObjectPtr<QToolBar> create();
|
||||
static Utils::UniqueObjectPtr<QWidget> createStatusBar();
|
||||
static bool isVisible();
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <texttool/texttool.h>
|
||||
#include <timelineeditor/timelineview.h>
|
||||
#include <transitioneditor/transitioneditorview.h>
|
||||
|
||||
#include <qmljseditor/qmljseditor.h>
|
||||
#include <qmljseditor/qmljseditorconstants.h>
|
||||
#include <qmljseditor/qmljseditordocument.h>
|
||||
@@ -66,6 +65,7 @@
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/uniqueobjectptr.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
@@ -144,8 +144,8 @@ public:
|
||||
DesignModeWidget mainWidget;
|
||||
QtQuickDesignerFactory m_qtQuickDesignerFactory;
|
||||
bool blockEditorChange = false;
|
||||
std::unique_ptr<QToolBar> toolBar;
|
||||
std::unique_ptr<QWidget> statusBar;
|
||||
Utils::UniqueObjectPtr<QToolBar> toolBar;
|
||||
Utils::UniqueObjectPtr<QWidget> statusBar;
|
||||
};
|
||||
|
||||
QmlDesignerPlugin *QmlDesignerPlugin::m_instance = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user