Utils: Add a way to (shutdown-)guard pre-created objects

Some classes use private c'tors and a friend function for creation.

Since friendship is not transitive this cannot (nicely) be extended
to the GuardedObject implementation.

In the quest to achieve a uniform 'void setupFoo()' signature to
the outside, keep the creation of the guarded object were it is,
but allow it to be taken over bey a GuardedObject.

This setup still requires the _d_'tor to be public, but less
"dangerous" then a public c'tor - assuming there is some danger
in having that at all.

Use it for the PythoSettings and LanguageClientManager setup.

Change-Id: Ica114a0bb901d33d79c847910a2383ac1bc9e49a
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
hjk
2025-01-13 15:31:04 +01:00
parent 927f919c0b
commit 3f55bbc18c
7 changed files with 22 additions and 17 deletions

View File

@@ -18,15 +18,18 @@ template <class T>
class GuardedObject class GuardedObject
{ {
public: public:
GuardedObject() GuardedObject(T *obj)
: m_object(new T) : m_object(obj)
{ {
QObject::connect(shutdownGuard(), &QObject::destroyed, shutdownGuard(), [this] { QObject::connect(shutdownGuard(), &QObject::destroyed, shutdownGuard(), [this] {
delete m_object; delete m_object;
m_object = nullptr; m_object = nullptr;
}); });
} }
~GuardedObject() = default;
GuardedObject()
: GuardedObject(new T)
{}
T *get() const { return m_object; } T *get() const { return m_object; }

View File

@@ -29,6 +29,7 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/theme/theme.h> #include <utils/theme/theme.h>
#include <utils/shutdownguard.h>
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <QTimer> #include <QTimer>
@@ -50,8 +51,7 @@ class LanguageClientManagerPrivate
LanguageFunctionsFilter m_functionFilter; LanguageFunctionsFilter m_functionFilter;
}; };
LanguageClientManager::LanguageClientManager(QObject *parent) LanguageClientManager::LanguageClientManager()
: QObject(parent)
{ {
setObjectName("LanguageClientManager"); setObjectName("LanguageClientManager");
@@ -742,9 +742,9 @@ bool LanguageClientManager::isShutdownFinished()
&& managerInstance->m_scheduledForDeletion.isEmpty(); && managerInstance->m_scheduledForDeletion.isEmpty();
} }
void setupLanguageClientManager(QObject *guard) void setupLanguageClientManager()
{ {
(void) new LanguageClientManager(guard); static Utils::GuardedObject theLanguageClientManager{new LanguageClientManager};
} }
} // namespace LanguageClient } // namespace LanguageClient

View File

@@ -33,6 +33,8 @@ class LANGUAGECLIENT_EXPORT LanguageClientManager : public QObject
Q_DISABLE_COPY_MOVE(LanguageClientManager) Q_DISABLE_COPY_MOVE(LanguageClientManager)
public: public:
~LanguageClientManager() override;
static void clientStarted(Client *client); static void clientStarted(Client *client);
static void clientFinished(Client *client); static void clientFinished(Client *client);
static Client *startClient(const BaseSettings *setting, ProjectExplorer::Project *project = nullptr); static Client *startClient(const BaseSettings *setting, ProjectExplorer::Project *project = nullptr);
@@ -98,10 +100,9 @@ signals:
void openCallHierarchy(); void openCallHierarchy();
private: private:
explicit LanguageClientManager(QObject *parent); LanguageClientManager();
~LanguageClientManager() override;
friend void setupLanguageClientManager(QObject *guard); friend void setupLanguageClientManager();
void updateProject(ProjectExplorer::Project *project); void updateProject(ProjectExplorer::Project *project);
void projectAdded(ProjectExplorer::Project *project); void projectAdded(ProjectExplorer::Project *project);
@@ -127,6 +128,6 @@ template<typename T> bool LanguageClientManager::hasClients()
}); });
} }
void setupLanguageClientManager(QObject *guard); void setupLanguageClientManager();
} // namespace LanguageClient } // namespace LanguageClient

View File

@@ -50,7 +50,7 @@ void LanguageClientPlugin::initialize()
setupCallHierarchyFactory(); setupCallHierarchyFactory();
setupTypeHierarchyFactory(); setupTypeHierarchyFactory();
setupLanguageClientProjectPanel(); setupLanguageClientProjectPanel();
setupLanguageClientManager(this); setupLanguageClientManager();
setupLanguageClientOutline(); setupLanguageClientOutline();
#ifdef WITH_TESTS #ifdef WITH_TESTS

View File

@@ -90,7 +90,7 @@ class PythonPlugin final : public ExtensionSystem::IPlugin
setupPythonDebugWorker(); setupPythonDebugWorker();
setupPythonOutputParser(); setupPythonOutputParser();
setupPythonSettings(this); setupPythonSettings();
setupPythonWizard(); setupPythonWizard();
setupPipSupport(this); setupPipSupport(this);

View File

@@ -36,6 +36,7 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/treemodel.h> #include <utils/treemodel.h>
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <utils/shutdownguard.h>
#include <QCheckBox> #include <QCheckBox>
#include <QComboBox> #include <QComboBox>
@@ -1169,10 +1170,9 @@ Interpreter PythonSettings::interpreter(const QString &interpreterId)
Utils::equal(&Interpreter::id, interpreterId)); Utils::equal(&Interpreter::id, interpreterId));
} }
void setupPythonSettings(QObject *guard) void setupPythonSettings()
{ {
new PythonSettings; // Initializes settingsInstance static GuardedObject thePythonSettings{new PythonSettings};
settingsInstance->setParent(guard);
} }
Utils::ListModel<ProjectExplorer::Interpreter> *createInterpreterModel(QObject *parent) Utils::ListModel<ProjectExplorer::Interpreter> *createInterpreterModel(QObject *parent)

View File

@@ -78,7 +78,8 @@ private:
static void saveSettings(); static void saveSettings();
}; };
void setupPythonSettings(QObject *guard); void setupPythonSettings();
Utils::ListModel<ProjectExplorer::Interpreter> *createInterpreterModel(QObject *parent); Utils::ListModel<ProjectExplorer::Interpreter> *createInterpreterModel(QObject *parent);
} // Python::Internal } // Python::Internal