Qbs: Fix crashes when switching QbsRunConfigurations

Do not use pointers to qbs::(Group|Product|Project)Data. Those are
implicitly shared classes, and now have a isValid method so that
default constructed instances can be spotted.

Change-Id: Icd49fa517f2e17bc60cc82d103f479d3a2e7097a
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
Tobias Hunger
2013-06-21 15:09:01 +02:00
parent 28be3fb83b
commit 161b818b23
7 changed files with 62 additions and 69 deletions

View File

@@ -134,10 +134,10 @@ QString QbsInstallStep::installRoot() const
QString QbsInstallStep::absoluteInstallRoot() const QString QbsInstallStep::absoluteInstallRoot() const
{ {
const qbs::ProjectData *data = static_cast<QbsProject *>(project())->qbsProjectData(); const qbs::ProjectData data = static_cast<QbsProject *>(project())->qbsProjectData();
QString path = installRoot(); QString path = installRoot();
if (data && !data->buildDirectory().isEmpty() && !path.isEmpty()) if (data.isValid() && !data.buildDirectory().isEmpty() && !path.isEmpty())
path = QDir(data->buildDirectory()).absoluteFilePath(path); path = QDir(data.buildDirectory()).absoluteFilePath(path);
return path; return path;
} }
@@ -306,9 +306,9 @@ void QbsInstallStepConfigWidget::updateState()
m_ui->keepGoingCheckBox->setChecked(m_step->keepGoing()); m_ui->keepGoingCheckBox->setChecked(m_step->keepGoing());
} }
const qbs::ProjectData *data = static_cast<QbsProject *>(m_step->project())->qbsProjectData(); const qbs::ProjectData data = static_cast<QbsProject *>(m_step->project())->qbsProjectData();
if (data) if (data.isValid())
m_ui->installRootChooser->setBaseDirectory(data->buildDirectory()); m_ui->installRootChooser->setBaseDirectory(data.buildDirectory());
QString command = QLatin1String("qbs install "); QString command = QLatin1String("qbs install ");
if (m_step->dryRun()) if (m_step->dryRun())

View File

@@ -466,15 +466,14 @@ void QbsGroupNode::setupFolder(ProjectExplorer::FolderNode *root,
// QbsProductNode: // QbsProductNode:
// -------------------------------------------------------------------- // --------------------------------------------------------------------
QbsProductNode::QbsProductNode(const qbs::ProductData *prd) : QbsProductNode::QbsProductNode(const qbs::ProductData &prd) :
QbsBaseProjectNode(prd->location().fileName()), QbsBaseProjectNode(prd.location().fileName())
m_qbsProductData(0)
{ {
setIcon(m_productIcon); setIcon(m_productIcon);
ProjectExplorer::FileNode *idx = new QbsFileNode(prd->location().fileName(), ProjectExplorer::FileNode *idx = new QbsFileNode(prd.location().fileName(),
ProjectExplorer::ProjectFileType, false, ProjectExplorer::ProjectFileType, false,
prd->location().line()); prd.location().line());
addFileNodes(QList<ProjectExplorer::FileNode *>() << idx, this); addFileNodes(QList<ProjectExplorer::FileNode *>() << idx, this);
setQbsProductData(prd); setQbsProductData(prd);
@@ -482,22 +481,21 @@ QbsProductNode::QbsProductNode(const qbs::ProductData *prd) :
bool QbsProductNode::isEnabled() const bool QbsProductNode::isEnabled() const
{ {
return m_qbsProductData ? m_qbsProductData->isEnabled() : false; return m_qbsProductData.isEnabled();
} }
void QbsProductNode::setQbsProductData(const qbs::ProductData *prd) void QbsProductNode::setQbsProductData(const qbs::ProductData prd)
{ {
Q_ASSERT(prd);
if (m_qbsProductData == prd) if (m_qbsProductData == prd)
return; return;
bool productWasEnabled = m_qbsProductData ? m_qbsProductData->isEnabled() : true; bool productWasEnabled = m_qbsProductData.isEnabled();
bool productIsEnabled = prd->isEnabled(); bool productIsEnabled = prd.isEnabled();
bool updateExisting = productWasEnabled != productIsEnabled; bool updateExisting = productWasEnabled != productIsEnabled;
setDisplayName(prd->name()); setDisplayName(prd.name());
setPath(prd->location().fileName()); setPath(prd.location().fileName());
const QString &productPath = QFileInfo(prd->location().fileName()).absolutePath(); const QString &productPath = QFileInfo(prd.location().fileName()).absolutePath();
// Find the QbsFileNode we added earlier: // Find the QbsFileNode we added earlier:
QbsFileNode *idx = 0; QbsFileNode *idx = 0;
@@ -506,14 +504,14 @@ void QbsProductNode::setQbsProductData(const qbs::ProductData *prd)
if (idx) if (idx)
break; break;
} }
if (idx->update(prd->location()) || updateExisting) if (idx->update(prd.location()) || updateExisting)
idx->emitNodeUpdated(); idx->emitNodeUpdated();
QList<ProjectExplorer::ProjectNode *> toAdd; QList<ProjectExplorer::ProjectNode *> toAdd;
QList<ProjectExplorer::ProjectNode *> toRemove = subProjectNodes(); QList<ProjectExplorer::ProjectNode *> toRemove = subProjectNodes();
foreach (const qbs::GroupData &grp, prd->groups()) { foreach (const qbs::GroupData &grp, prd.groups()) {
if (grp.name() == prd->name() && grp.location() == prd->location()) { if (grp.name() == prd.name() && grp.location() == prd.location()) {
// Set implicit product group right onto this node: // Set implicit product group right onto this node:
QbsGroupNode::setupFiles(this, grp.allFilePaths(), productPath, updateExisting); QbsGroupNode::setupFiles(this, grp.allFilePaths(), productPath, updateExisting);
continue; continue;
@@ -541,7 +539,7 @@ QList<ProjectExplorer::RunConfiguration *> QbsProductNode::runConfigurationsFor(
Q_UNUSED(node); Q_UNUSED(node);
QList<ProjectExplorer::RunConfiguration *> result; QList<ProjectExplorer::RunConfiguration *> result;
QbsProjectNode *pn = qobject_cast<QbsProjectNode *>(projectNode()); QbsProjectNode *pn = qobject_cast<QbsProjectNode *>(projectNode());
if (!isEnabled() || !pn || pn->qbsProject()->targetExecutable(*m_qbsProductData, if (!isEnabled() || !pn || pn->qbsProject()->targetExecutable(m_qbsProductData,
qbs::InstallOptions()).isEmpty()) { qbs::InstallOptions()).isEmpty()) {
return result; return result;
} }
@@ -550,7 +548,7 @@ QList<ProjectExplorer::RunConfiguration *> QbsProductNode::runConfigurationsFor(
QbsRunConfiguration *qbsRc = qobject_cast<QbsRunConfiguration *>(rc); QbsRunConfiguration *qbsRc = qobject_cast<QbsRunConfiguration *>(rc);
if (!qbsRc) if (!qbsRc)
continue; continue;
if (qbsRc->qbsProduct() == qbsProductData()->name()) if (qbsRc->qbsProduct() == qbsProductData().name())
result << qbsRc; result << qbsRc;
} }
@@ -573,14 +571,14 @@ QbsGroupNode *QbsProductNode::findGroupNode(const QString &name)
QbsProjectNode::QbsProjectNode(QbsProject *project) : QbsProjectNode::QbsProjectNode(QbsProject *project) :
QbsBaseProjectNode(project->document()->fileName()), QbsBaseProjectNode(project->document()->fileName()),
m_project(project), m_qbsProject(0), m_qbsProjectData(0) m_project(project), m_qbsProject(0)
{ {
ctor(); ctor();
} }
QbsProjectNode::QbsProjectNode(const QString &path) : QbsProjectNode::QbsProjectNode(const QString &path) :
QbsBaseProjectNode(path), QbsBaseProjectNode(path),
m_project(0), m_qbsProject(0), m_qbsProjectData(0) m_project(0), m_qbsProject(0)
{ {
ctor(); ctor();
} }
@@ -588,14 +586,12 @@ QbsProjectNode::QbsProjectNode(const QString &path) :
QbsProjectNode::~QbsProjectNode() QbsProjectNode::~QbsProjectNode()
{ {
// do not delete m_project // do not delete m_project
delete m_qbsProjectData;
delete m_qbsProject; delete m_qbsProject;
} }
void QbsProjectNode::update(const qbs::Project *prj) void QbsProjectNode::update(const qbs::Project *prj)
{ {
if (prj) update(prj ? prj->projectData() : qbs::ProjectData());
update(prj->projectData());
delete m_qbsProject; delete m_qbsProject;
m_qbsProject = prj; m_qbsProject = prj;
@@ -621,19 +617,19 @@ void QbsProjectNode::update(const qbs::ProjectData &prjData)
foreach (const qbs::ProductData &prd, prjData.products()) { foreach (const qbs::ProductData &prd, prjData.products()) {
QbsProductNode *qn = findProductNode(prd.name()); QbsProductNode *qn = findProductNode(prd.name());
if (!qn) { if (!qn) {
toAdd << new QbsProductNode(&prd); toAdd << new QbsProductNode(prd);
} else { } else {
qn->setQbsProductData(&prd); qn->setQbsProductData(prd);
toRemove.removeOne(qn); toRemove.removeOne(qn);
} }
} }
delete m_qbsProjectData;
m_qbsProjectData = new qbs::ProjectData(prjData);
setDisplayName(prjData.name()); setDisplayName(prjData.name());
removeProjectNodes(toRemove); removeProjectNodes(toRemove);
addProjectNodes(toAdd); addProjectNodes(toAdd);
m_qbsProjectData = prjData;
} }
QbsProject *QbsProjectNode::project() const QbsProject *QbsProjectNode::project() const
@@ -651,7 +647,7 @@ const qbs::Project *QbsProjectNode::qbsProject() const
return m_qbsProject; return m_qbsProject;
} }
const qbs::ProjectData *QbsProjectNode::qbsProjectData() const const qbs::ProjectData QbsProjectNode::qbsProjectData() const
{ {
return m_qbsProjectData; return m_qbsProjectData;
} }
@@ -667,7 +663,7 @@ QbsProductNode *QbsProjectNode::findProductNode(const QString &name)
{ {
foreach (ProjectExplorer::ProjectNode *n, subProjectNodes()) { foreach (ProjectExplorer::ProjectNode *n, subProjectNodes()) {
QbsProductNode *qn = qobject_cast<QbsProductNode *>(n); QbsProductNode *qn = qobject_cast<QbsProductNode *>(n);
if (qn && qn->qbsProductData()->name() == name) if (qn && qn->qbsProductData().name() == name)
return qn; return qn;
} }
return 0; return 0;
@@ -677,7 +673,7 @@ QbsProjectNode *QbsProjectNode::findProjectNode(const QString &name)
{ {
foreach (ProjectExplorer::ProjectNode *n, subProjectNodes()) { foreach (ProjectExplorer::ProjectNode *n, subProjectNodes()) {
QbsProjectNode *qn = qobject_cast<QbsProjectNode *>(n); QbsProjectNode *qn = qobject_cast<QbsProjectNode *>(n);
if (qn && qn->qbsProjectData()->name() == name) if (qn && qn->qbsProjectData().name() == name)
return qn; return qn;
} }
return 0; return 0;

View File

@@ -148,19 +148,19 @@ class QbsProductNode : public QbsBaseProjectNode
Q_OBJECT Q_OBJECT
public: public:
explicit QbsProductNode(const qbs::ProductData *prd); explicit QbsProductNode(const qbs::ProductData &prd);
bool isEnabled() const; bool isEnabled() const;
void setQbsProductData(const qbs::ProductData *prd); void setQbsProductData(const qbs::ProductData prd);
const qbs::ProductData *qbsProductData() const { return m_qbsProductData; } const qbs::ProductData qbsProductData() const { return m_qbsProductData; }
QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node); QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node);
private: private:
QbsGroupNode *findGroupNode(const QString &name); QbsGroupNode *findGroupNode(const QString &name);
const qbs::ProductData *m_qbsProductData; qbs::ProductData m_qbsProductData;
static QIcon m_productIcon; static QIcon m_productIcon;
}; };
@@ -182,7 +182,7 @@ public:
QbsProject *project() const; QbsProject *project() const;
const qbs::Project *qbsProject() const; const qbs::Project *qbsProject() const;
const qbs::ProjectData *qbsProjectData() const; const qbs::ProjectData qbsProjectData() const;
private: private:
void ctor(); void ctor();
@@ -193,7 +193,7 @@ private:
QbsProject *m_project; QbsProject *m_project;
const qbs::Project *m_qbsProject; const qbs::Project *m_qbsProject;
const qbs::ProjectData *m_qbsProjectData; qbs::ProjectData m_qbsProjectData;
static QIcon m_projectIcon; static QIcon m_projectIcon;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -162,8 +162,8 @@ QStringList QbsProject::files(ProjectExplorer::Project::FilesMode fileMode) cons
{ {
Q_UNUSED(fileMode); Q_UNUSED(fileMode);
QSet<QString> result; QSet<QString> result;
if (m_rootProjectNode && m_rootProjectNode->qbsProjectData()) { if (m_rootProjectNode && m_rootProjectNode->qbsProjectData().isValid()) {
foreach (const qbs::ProductData &prd, m_rootProjectNode->qbsProjectData()->allProducts()) { foreach (const qbs::ProductData &prd, m_rootProjectNode->qbsProjectData().allProducts()) {
foreach (const qbs::GroupData &grp, prd.groups()) { foreach (const qbs::GroupData &grp, prd.groups()) {
foreach (const QString &file, grp.allFilePaths()) foreach (const QString &file, grp.allFilePaths())
result.insert(file); result.insert(file);
@@ -171,7 +171,7 @@ QStringList QbsProject::files(ProjectExplorer::Project::FilesMode fileMode) cons
} }
result.insert(prd.location().fileName()); result.insert(prd.location().fileName());
} }
result.insert(m_rootProjectNode->qbsProjectData()->location().fileName()); result.insert(m_rootProjectNode->qbsProjectData().location().fileName());
} }
return result.toList(); return result.toList();
} }
@@ -191,7 +191,7 @@ qbs::BuildJob *QbsProject::build(const qbs::BuildOptions &opts, QStringList prod
QList<qbs::ProductData> products; QList<qbs::ProductData> products;
foreach (const QString &productName, productNames) { foreach (const QString &productName, productNames) {
bool found = false; bool found = false;
foreach (const qbs::ProductData &data, qbsProjectData()->allProducts()) { foreach (const qbs::ProductData &data, qbsProjectData().allProducts()) {
if (data.name() == productName) { if (data.name() == productName) {
found = true; found = true;
products.append(data); products.append(data);
@@ -249,10 +249,10 @@ const qbs::Project *QbsProject::qbsProject() const
return m_rootProjectNode->qbsProject(); return m_rootProjectNode->qbsProject();
} }
const qbs::ProjectData *QbsProject::qbsProjectData() const const qbs::ProjectData QbsProject::qbsProjectData() const
{ {
if (!m_rootProjectNode) if (!m_rootProjectNode)
return 0; return qbs::ProjectData();
return m_rootProjectNode->qbsProjectData(); return m_rootProjectNode->qbsProjectData();
} }
@@ -494,9 +494,9 @@ void QbsProject::updateDocuments(const QSet<QString> &files)
m_qbsDocuments.unite(toAdd); m_qbsDocuments.unite(toAdd);
} }
void QbsProject::updateCppCodeModel(const qbs::ProjectData *prj) void QbsProject::updateCppCodeModel(const qbs::ProjectData &prj)
{ {
if (!prj) if (!prj.isValid())
return; return;
ProjectExplorer::Kit *k = 0; ProjectExplorer::Kit *k = 0;
@@ -525,7 +525,7 @@ void QbsProject::updateCppCodeModel(const qbs::ProjectData *prj)
} }
QStringList allFiles; QStringList allFiles;
foreach (const qbs::ProductData &prd, prj->allProducts()) { foreach (const qbs::ProductData &prd, prj.allProducts()) {
foreach (const qbs::GroupData &grp, prd.groups()) { foreach (const qbs::GroupData &grp, prd.groups()) {
const qbs::PropertyMap &props = grp.properties(); const qbs::PropertyMap &props = grp.properties();
@@ -600,7 +600,7 @@ void QbsProject::updateCppCodeModel(const qbs::ProjectData *prj)
m_codeModelFuture = modelmanager->updateSourceFiles(allFiles); m_codeModelFuture = modelmanager->updateSourceFiles(allFiles);
} }
void QbsProject::updateQmlJsCodeModel(const qbs::ProjectData *prj) void QbsProject::updateQmlJsCodeModel(const qbs::ProjectData &prj)
{ {
Q_UNUSED(prj); Q_UNUSED(prj);
QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();

View File

@@ -92,7 +92,7 @@ public:
Utils::FileName defaultBuildDirectory() const; Utils::FileName defaultBuildDirectory() const;
const qbs::Project *qbsProject() const; const qbs::Project *qbsProject() const;
const qbs::ProjectData *qbsProjectData() const; const qbs::ProjectData qbsProjectData() const;
bool needsSpecialDeployment() const; bool needsSpecialDeployment() const;
@@ -123,8 +123,8 @@ private:
void generateErrors(const qbs::ErrorInfo &e); void generateErrors(const qbs::ErrorInfo &e);
void prepareForParsing(); void prepareForParsing();
void updateDocuments(const QSet<QString> &files); void updateDocuments(const QSet<QString> &files);
void updateCppCodeModel(const qbs::ProjectData *prj); void updateCppCodeModel(const qbs::ProjectData &prj);
void updateQmlJsCodeModel(const qbs::ProjectData *prj); void updateQmlJsCodeModel(const qbs::ProjectData &prj);
QString qbsBuildDir() const; QString qbsBuildDir() const;
QbsManager *const m_manager; QbsManager *const m_manager;

View File

@@ -71,16 +71,13 @@ QString productFromId(Core::Id id)
return id.suffixAfter(QBS_RC_PREFIX); return id.suffixAfter(QBS_RC_PREFIX);
} }
const qbs::ProductData *findProduct(const qbs::ProjectData *pro, const QString &name) const qbs::ProductData findProduct(const qbs::ProjectData &pro, const QString &name)
{ {
if (!pro) foreach (const qbs::ProductData &product, pro.allProducts()) {
return 0;
foreach (const qbs::ProductData &product, pro->allProducts()) {
if (product.name() == name) if (product.name() == name)
return &product; return product;
} }
return 0; return qbs::ProductData();
} }
} // namespace } // namespace
@@ -197,12 +194,12 @@ void QbsRunConfiguration::installStepChanged()
QString QbsRunConfiguration::executable() const QString QbsRunConfiguration::executable() const
{ {
QbsProject *pro = static_cast<QbsProject *>(target()->project()); QbsProject *pro = static_cast<QbsProject *>(target()->project());
const qbs::ProductData *product = findProduct(pro->qbsProjectData(), m_qbsProduct); const qbs::ProductData product = findProduct(pro->qbsProjectData(), m_qbsProduct);
if (!product || !pro->qbsProject()) if (product.isValid() || !pro->qbsProject())
return QString(); return QString();
return pro->qbsProject()->targetExecutable(*product, installOptions()); return pro->qbsProject()->targetExecutable(product, installOptions());
} }
ProjectExplorer::LocalApplicationRunConfiguration::RunMode QbsRunConfiguration::runMode() const ProjectExplorer::LocalApplicationRunConfiguration::RunMode QbsRunConfiguration::runMode() const
@@ -521,7 +518,7 @@ bool QbsRunConfigurationFactory::canCreate(ProjectExplorer::Target *parent, cons
return false; return false;
QbsProject *project = static_cast<QbsProject *>(parent->project()); QbsProject *project = static_cast<QbsProject *>(parent->project());
return findProduct(project->qbsProjectData(), productFromId(id)); return !findProduct(project->qbsProjectData(), productFromId(id)).isValid();
} }
ProjectExplorer::RunConfiguration *QbsRunConfigurationFactory::doCreate(ProjectExplorer::Target *parent, const Core::Id id) ProjectExplorer::RunConfiguration *QbsRunConfigurationFactory::doCreate(ProjectExplorer::Target *parent, const Core::Id id)
@@ -562,10 +559,10 @@ QList<Core::Id> QbsRunConfigurationFactory::availableCreationIds(ProjectExplorer
return result; return result;
QbsProject *project = static_cast<QbsProject *>(parent->project()); QbsProject *project = static_cast<QbsProject *>(parent->project());
if (!project || !project->qbsProjectData() || !project->qbsProject()) if (!project || !project->qbsProject())
return result; return result;
foreach (const qbs::ProductData &product, project->qbsProjectData()->allProducts()) { foreach (const qbs::ProductData &product, project->qbsProjectData().allProducts()) {
if (!project->qbsProject()->targetExecutable(product, qbs::InstallOptions()).isEmpty()) if (!project->qbsProject()->targetExecutable(product, qbs::InstallOptions()).isEmpty())
result << Core::Id::fromString(QString::fromLatin1(QBS_RC_PREFIX) + product.name()); result << Core::Id::fromString(QString::fromLatin1(QBS_RC_PREFIX) + product.name());
} }