aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp36
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonsummarypage.h2
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp16
-rw-r--r--src/plugins/projectexplorer/projectexplorerconstants.h2
-rw-r--r--src/plugins/projectexplorer/projectfilewizardextension.cpp33
-rw-r--r--src/plugins/projectexplorer/projectfilewizardextension.h3
-rw-r--r--src/plugins/projectexplorer/projecttree.cpp15
-rw-r--r--src/plugins/projectexplorer/projecttree.h5
8 files changed, 99 insertions, 13 deletions
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp
index 5f02bc7779..27b4b682ab 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp
@@ -31,6 +31,8 @@
#include "../projectnodes.h"
#include "../session.h"
+#include "../projecttree.h"
+
#include <coreplugin/coreconstants.h>
#include <coreplugin/iversioncontrol.h>
@@ -125,10 +127,19 @@ void JsonSummaryPage::initializePage()
});
}
- Node *contextNode = m_wizard->value(QLatin1String(Constants::PREFERRED_PROJECT_NODE))
- .value<Node *>();
- initializeProjectTree(contextNode, files, kind,
- isProject ? AddSubProject : AddNewFile);
+ // Use static cast from void * to avoid qobject_cast (which needs a valid object) in value()
+ // in the following code:
+ auto contextNode = findWizardContextNode(static_cast<Node *>(m_wizard->value(Constants::PREFERRED_PROJECT_NODE).value<void *>()));
+ const ProjectAction currentAction = isProject ? AddSubProject : AddNewFile;
+
+ initializeProjectTree(contextNode, files, kind, currentAction);
+
+ // Refresh combobox on project tree changes:
+ connect(ProjectTree::instance(), &ProjectTree::treeChanged,
+ this, [this, files, kind, currentAction]() {
+ initializeProjectTree(findWizardContextNode(currentNode()), files, kind, currentAction);
+ });
+
bool hideProjectUi = JsonWizard::boolFromVariant(m_hideProjectUiValue, m_wizard->expander());
setProjectUiVisible(!hideProjectUi);
@@ -207,6 +218,23 @@ void JsonSummaryPage::summarySettingsHaveChanged()
updateProjectData(currentNode());
}
+Node *JsonSummaryPage::findWizardContextNode(Node *contextNode) const
+{
+ if (contextNode && !ProjectTree::hasNode(contextNode)) {
+ contextNode = nullptr;
+
+ // Static cast from void * to avoid qobject_cast (which needs a valid object) in value().
+ auto project = static_cast<Project *>(m_wizard->value(Constants::PROJECT_POINTER).value<void *>());
+ if (SessionManager::projects().contains(project) && project->rootProjectNode()) {
+ const QString path = m_wizard->value(Constants::PREFERRED_PROJECT_NODE_PATH).toString();
+ contextNode = project->rootProjectNode()->findNode([path](const Node *n) {
+ return path == n->filePath().toString();
+ });
+ }
+ }
+ return contextNode;
+}
+
void JsonSummaryPage::updateFileList()
{
m_fileList = m_wizard->generateFileList();
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.h b/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.h
index 1e0bd1800f..2fa134a38f 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.h
+++ b/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.h
@@ -33,6 +33,7 @@
namespace ProjectExplorer {
class FolderNode;
+class Node;
// Documentation inside.
class JsonSummaryPage : public Internal::ProjectWizardPage
@@ -52,6 +53,7 @@ public:
void summarySettingsHaveChanged();
private:
+ Node *findWizardContextNode(Node *contextNode) const;
void updateFileList();
void updateProjectData(FolderNode *node);
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index f47f2e0510..acd546e09b 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -3046,13 +3046,18 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
void ProjectExplorerPluginPrivate::addNewFile()
{
QTC_ASSERT(ProjectTree::currentNode(), return);
- QString location = directoryFor(ProjectTree::currentNode());
+ Node *currentNode = ProjectTree::currentNode();
+ QString location = directoryFor(currentNode);
QVariantMap map;
- map.insert(QLatin1String(Constants::PREFERRED_PROJECT_NODE), QVariant::fromValue(ProjectTree::currentNode()));
- if (ProjectTree::currentProject()) {
- QList<Id> profileIds = Utils::transform(ProjectTree::currentProject()->targets(), &Target::id);
+ // store void pointer to avoid QVariant to use qobject_cast, which might core-dump when trying
+ // to access meta data on an object that get deleted in the meantime:
+ map.insert(QLatin1String(Constants::PREFERRED_PROJECT_NODE), QVariant::fromValue(static_cast<void *>(currentNode)));
+ map.insert(Constants::PREFERRED_PROJECT_NODE_PATH, currentNode->filePath().toString());
+ if (Project *p = ProjectTree::currentProject()) {
+ QList<Id> profileIds = Utils::transform(p->targets(), &Target::id);
map.insert(QLatin1String(Constants::PROJECT_KIT_IDS), QVariant::fromValue(profileIds));
+ map.insert(Constants::PROJECT_POINTER, QVariant::fromValue(static_cast<void *>(p)));
}
ICore::showNewItemDialog(tr("New File", "Title of dialog"),
Utils::filtered(IWizardFactory::allWizardFactories(),
@@ -3121,7 +3126,8 @@ void ProjectExplorerPluginPrivate::addExistingDirectory()
void ProjectExplorerPlugin::addExistingFiles(FolderNode *folderNode, const QStringList &filePaths)
{
- if (!folderNode) // can happen when project is not yet parsed
+ // can happen when project is not yet parsed or finished parsing while the dialog was open:
+ if (!folderNode || !ProjectTree::hasNode(folderNode))
return;
const QString dir = directoryFor(folderNode);
diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h
index 559b11fb6a..13dfe2431a 100644
--- a/src/plugins/projectexplorer/projectexplorerconstants.h
+++ b/src/plugins/projectexplorer/projectexplorerconstants.h
@@ -126,6 +126,8 @@ const char IMPORT_WIZARD_CATEGORY_DISPLAY[] = QT_TRANSLATE_NOOP("ProjectExplorer
// Wizard extra values
const char PREFERRED_PROJECT_NODE[] = "ProjectExplorer.PreferredProjectNode";
+const char PREFERRED_PROJECT_NODE_PATH[] = "ProjectExplorer.PreferredProjectPath";
+const char PROJECT_POINTER[] = "ProjectExplorer.Project";
const char PROJECT_KIT_IDS[] = "ProjectExplorer.Profile.Ids";
// Build step lists ids:
diff --git a/src/plugins/projectexplorer/projectfilewizardextension.cpp b/src/plugins/projectexplorer/projectfilewizardextension.cpp
index c7bf50e246..e6bf826e7b 100644
--- a/src/plugins/projectexplorer/projectfilewizardextension.cpp
+++ b/src/plugins/projectexplorer/projectfilewizardextension.cpp
@@ -41,6 +41,7 @@
#include <texteditor/tabsettings.h>
#include <texteditor/storagesettings.h>
#include <projectexplorer/project.h>
+#include <projectexplorer/projecttree.h>
#include <projectexplorer/editorconfiguration.h>
#include <utils/mimetypes/mimedatabase.h>
#
@@ -120,7 +121,8 @@ void ProjectFileWizardExtension::firstExtensionPageShown(
QStringList filePaths;
ProjectAction projectAction;
- if (m_context->wizard->kind()== IWizardFactory::ProjectWizard) {
+ const IWizardFactory::WizardKind kind = m_context->wizard->kind();
+ if (kind == IWizardFactory::ProjectWizard) {
projectAction = AddSubProject;
filePaths << generatedProjectFilePath(files);
} else {
@@ -128,13 +130,38 @@ void ProjectFileWizardExtension::firstExtensionPageShown(
filePaths = Utils::transform(files, &GeneratedFile::path);
}
- Node *contextNode = extraValues.value(QLatin1String(Constants::PREFERRED_PROJECT_NODE)).value<Node *>();
+ // Static cast from void * to avoid qobject_cast (which needs a valid object) in value().
+ auto contextNode = static_cast<Node *>(extraValues.value(QLatin1String(Constants::PREFERRED_PROJECT_NODE)).value<void *>());
+ auto project = static_cast<Project *>(extraValues.value(Constants::PROJECT_POINTER).value<void *>());
+ const QString path = extraValues.value(Constants::PREFERRED_PROJECT_NODE_PATH).toString();
- m_context->page->initializeProjectTree(contextNode, filePaths, m_context->wizard->kind(),
+ m_context->page->initializeProjectTree(findWizardContextNode(contextNode, project, path),
+ filePaths, m_context->wizard->kind(),
projectAction);
+ // Refresh combobox on project tree changes:
+ connect(ProjectTree::instance(), &ProjectTree::treeChanged,
+ m_context->page, [this, project, path, filePaths, kind, projectAction]() {
+ m_context->page->initializeProjectTree(
+ findWizardContextNode(m_context->page->currentNode(), project, path), filePaths,
+ kind, projectAction);
+ });
+
m_context->page->initializeVersionControls();
}
+Node *ProjectFileWizardExtension::findWizardContextNode(Node *contextNode, Project *project,
+ const QString &path)
+{
+ if (contextNode && !ProjectTree::hasNode(contextNode)) {
+ if (SessionManager::projects().contains(project) && project->rootProjectNode()) {
+ contextNode = project->rootProjectNode()->findNode([path](const Node *n) {
+ return path == n->filePath().toString();
+ });
+ }
+ }
+ return contextNode;
+}
+
QList<QWizardPage *> ProjectFileWizardExtension::extensionPages(const IWizardFactory *wizard)
{
if (!m_context)
diff --git a/src/plugins/projectexplorer/projectfilewizardextension.h b/src/plugins/projectexplorer/projectfilewizardextension.h
index fe9d3f8d92..df1c61a650 100644
--- a/src/plugins/projectexplorer/projectfilewizardextension.h
+++ b/src/plugins/projectexplorer/projectfilewizardextension.h
@@ -31,6 +31,8 @@
namespace ProjectExplorer {
class FolderNode;
+class Node;
+class Project;
namespace Internal {
@@ -52,6 +54,7 @@ public slots:
void firstExtensionPageShown(const QList<Core::GeneratedFile> &files, const QVariantMap &extraValues) override;
private:
+ Node *findWizardContextNode(Node *contextNode, Project *project, const QString &path);
bool processProject(const QList<Core::GeneratedFile> &files,
bool *removeOpenProjectAttribute, QString *errorMessage);
diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp
index 50b8b65256..fcaf5d8178 100644
--- a/src/plugins/projectexplorer/projecttree.cpp
+++ b/src/plugins/projectexplorer/projecttree.cpp
@@ -72,10 +72,15 @@ ProjectTree::ProjectTree(QObject *parent) : QObject(parent)
connect(SessionManager::instance(), &SessionManager::projectAdded,
this, &ProjectTree::sessionChanged);
+ connect(SessionManager::instance(), &SessionManager::projectAdded,
+ this, &ProjectTree::treeChanged);
connect(SessionManager::instance(), &SessionManager::projectRemoved,
this, &ProjectTree::sessionChanged);
+ connect(SessionManager::instance(), &SessionManager::projectRemoved,
+ this, &ProjectTree::treeChanged);
connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
this, &ProjectTree::sessionChanged);
+ connect(this, &ProjectTree::subtreeChanged, this, &ProjectTree::treeChanged);
}
ProjectTree::~ProjectTree()
@@ -261,7 +266,8 @@ void ProjectTree::updateContext()
void ProjectTree::emitSubtreeChanged(FolderNode *node)
{
- emit s_instance->subtreeChanged(node);
+ if (hasNode(node))
+ emit s_instance->subtreeChanged(node);
}
void ProjectTree::collapseAll()
@@ -377,6 +383,13 @@ void ProjectTree::applyTreeManager(FolderNode *folder)
f(folder);
}
+bool ProjectTree::hasNode(const Node *node)
+{
+ return Utils::contains(SessionManager::projects(), [node](const Project *p) {
+ return p && p->rootProjectNode() && p->rootProjectNode()->findNode([node](const Node *n) { return n == node; });
+ });
+}
+
void ProjectTree::hideContextMenu()
{
m_focusForContextMenu = nullptr;
diff --git a/src/plugins/projectexplorer/projecttree.h b/src/plugins/projectexplorer/projecttree.h
index eb84adf58b..7f61a2ee78 100644
--- a/src/plugins/projectexplorer/projecttree.h
+++ b/src/plugins/projectexplorer/projecttree.h
@@ -68,6 +68,8 @@ public:
static void registerTreeManager(const TreeManagerFunction &treeChange);
static void applyTreeManager(FolderNode *folder);
+ static bool hasNode(const Node *node);
+
void collapseAll();
// for nodes to emit signals, do not call unless you are a node
@@ -83,6 +85,9 @@ signals:
void aboutToShowContextMenu(ProjectExplorer::Project *project,
ProjectExplorer::Node *node);
+ // Emitted on any change to the tree
+ void treeChanged();
+
private:
void sessionChanged();
void focusChanged();