forked from qt-creator/qt-creator
Fix various crashes
Task-Number: QTCREATORBUG-6365 Change-Id: I19a200e3c811eef83d591f6eacca3e48eb0fba8f Reviewed-by: Tobias Hunger <tobias.hunger@nokia.com>
This commit is contained in:
@@ -89,6 +89,8 @@ struct BuildManagerPrivate {
|
||||
QString m_currentConfiguration;
|
||||
// used to decide if we are building a project to decide when to emit buildStateChanged(Project *)
|
||||
QHash<Project *, int> m_activeBuildSteps;
|
||||
QHash<Target *, int> m_activeBuildStepsPerTarget;
|
||||
QHash<ProjectConfiguration *, int> m_activeBuildStepsPerProjectConfiguration;
|
||||
Project *m_previousBuildStepProject;
|
||||
// is set to true while canceling, so that nextBuildStep knows that the BuildStep finished because of canceling
|
||||
bool m_canceling;
|
||||
@@ -221,7 +223,7 @@ void BuildManager::cancel()
|
||||
QTimer::singleShot(0, this, SLOT(emitCancelMessage()));
|
||||
|
||||
disconnectOutput(d->m_currentBuildStep);
|
||||
decrementActiveBuildSteps(d->m_currentBuildStep->buildConfiguration()->target()->project());
|
||||
decrementActiveBuildSteps(d->m_currentBuildStep);
|
||||
|
||||
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100, tr("Build canceled")); //TODO NBS fix in qtconcurrent
|
||||
clearBuildQueue();
|
||||
@@ -256,7 +258,7 @@ void BuildManager::emitCancelMessage()
|
||||
void BuildManager::clearBuildQueue()
|
||||
{
|
||||
foreach (BuildStep *bs, d->m_buildQueue) {
|
||||
decrementActiveBuildSteps(bs->buildConfiguration()->target()->project());
|
||||
decrementActiveBuildSteps(bs);
|
||||
disconnectOutput(bs);
|
||||
}
|
||||
|
||||
@@ -382,7 +384,7 @@ void BuildManager::nextBuildQueue()
|
||||
disconnectOutput(d->m_currentBuildStep);
|
||||
++d->m_progress;
|
||||
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100, msgProgress(d->m_progress, d->m_maxProgress));
|
||||
decrementActiveBuildSteps(d->m_currentBuildStep->buildConfiguration()->target()->project());
|
||||
decrementActiveBuildSteps(d->m_currentBuildStep);
|
||||
|
||||
bool result = d->m_watcher.result();
|
||||
if (!result) {
|
||||
@@ -491,7 +493,7 @@ bool BuildManager::buildQueueAppend(QList<BuildStep *> steps)
|
||||
for (i = 0; i < count; ++i) {
|
||||
++d->m_maxProgress;
|
||||
d->m_buildQueue.append(steps.at(i));
|
||||
incrementActiveBuildSteps(steps.at(i)->buildConfiguration()->target()->project());
|
||||
incrementActiveBuildSteps(steps.at(i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -531,14 +533,29 @@ void BuildManager::appendStep(BuildStep *step)
|
||||
startBuildQueue();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int count(const QHash<T *, int> &hash, T *key)
|
||||
{
|
||||
typename QHash<T *, int>::const_iterator it = hash.find(key);
|
||||
typename QHash<T *, int>::const_iterator end = hash.end();
|
||||
if (it != end)
|
||||
return *it;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BuildManager::isBuilding(Project *pro)
|
||||
{
|
||||
QHash<Project *, int>::iterator it = d->m_activeBuildSteps.find(pro);
|
||||
QHash<Project *, int>::iterator end = d->m_activeBuildSteps.end();
|
||||
if (it == end || *it == 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
return count(d->m_activeBuildSteps, pro) > 0;
|
||||
}
|
||||
|
||||
bool BuildManager::isBuilding(Target *t)
|
||||
{
|
||||
return count(d->m_activeBuildStepsPerTarget, t) > 0;
|
||||
}
|
||||
|
||||
bool BuildManager::isBuilding(ProjectConfiguration *p)
|
||||
{
|
||||
return count(d->m_activeBuildStepsPerProjectConfiguration, p) > 0;
|
||||
}
|
||||
|
||||
bool BuildManager::isBuilding(BuildStep *step)
|
||||
@@ -546,33 +563,51 @@ bool BuildManager::isBuilding(BuildStep *step)
|
||||
return (d->m_currentBuildStep == step) || d->m_buildQueue.contains(step);
|
||||
}
|
||||
|
||||
void BuildManager::incrementActiveBuildSteps(Project *pro)
|
||||
template <class T> bool increment(QHash<T *, int> &hash, T *key)
|
||||
{
|
||||
QHash<Project *, int>::iterator it = d->m_activeBuildSteps.find(pro);
|
||||
QHash<Project *, int>::iterator end = d->m_activeBuildSteps.end();
|
||||
typename QHash<T *, int>::iterator it = hash.find(key);
|
||||
typename QHash<T *, int>::iterator end = hash.end();
|
||||
if (it == end) {
|
||||
d->m_activeBuildSteps.insert(pro, 1);
|
||||
emit buildStateChanged(pro);
|
||||
hash.insert(key, 1);
|
||||
return true;
|
||||
} else if (*it == 0) {
|
||||
++*it;
|
||||
emit buildStateChanged(pro);
|
||||
return true;
|
||||
} else {
|
||||
++*it;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BuildManager::decrementActiveBuildSteps(Project *pro)
|
||||
template <class T> bool decrement(QHash<T *, int> &hash, T *key)
|
||||
{
|
||||
QHash<Project *, int>::iterator it = d->m_activeBuildSteps.find(pro);
|
||||
QHash<Project *, int>::iterator end = d->m_activeBuildSteps.end();
|
||||
typename QHash<T *, int>::iterator it = hash.find(key);
|
||||
typename QHash<T *, int>::iterator end = hash.end();
|
||||
if (it == end) {
|
||||
Q_ASSERT(false && "BuildManager d->m_activeBuildSteps says project is not building, but apparently a build step was still in the queue.");
|
||||
// Can't happen
|
||||
} else if (*it == 1) {
|
||||
--*it;
|
||||
emit buildStateChanged(pro);
|
||||
return true;
|
||||
} else {
|
||||
--*it;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BuildManager::incrementActiveBuildSteps(BuildStep *bs)
|
||||
{
|
||||
increment<ProjectConfiguration>(d->m_activeBuildStepsPerProjectConfiguration, bs->projectConfiguration());
|
||||
increment<Target>(d->m_activeBuildStepsPerTarget, bs->target());
|
||||
if (increment<Project>(d->m_activeBuildSteps, bs->project()))
|
||||
emit buildStateChanged(bs->project());
|
||||
}
|
||||
|
||||
void BuildManager::decrementActiveBuildSteps(BuildStep *bs)
|
||||
{
|
||||
decrement<ProjectConfiguration>(d->m_activeBuildStepsPerProjectConfiguration, bs->projectConfiguration());
|
||||
decrement<Target>(d->m_activeBuildStepsPerTarget, bs->target());
|
||||
if (decrement<Project>(d->m_activeBuildSteps, bs->project()))
|
||||
emit buildStateChanged(bs->project());
|
||||
}
|
||||
|
||||
void BuildManager::disconnectOutput(BuildStep *bs)
|
||||
|
||||
@@ -63,6 +63,8 @@ public:
|
||||
bool buildLists(QList<BuildStepList *> bsls);
|
||||
bool buildList(BuildStepList *bsl);
|
||||
bool isBuilding(Project *p);
|
||||
bool isBuilding(Target *t);
|
||||
bool isBuilding(ProjectConfiguration *p);
|
||||
bool isBuilding(BuildStep *step);
|
||||
|
||||
// Append any build step to the list of build steps (currently only used to add the QMakeStep)
|
||||
@@ -102,8 +104,8 @@ private:
|
||||
void nextStep();
|
||||
void clearBuildQueue();
|
||||
bool buildQueueAppend(QList<BuildStep *> steps);
|
||||
void incrementActiveBuildSteps(Project *pro);
|
||||
void decrementActiveBuildSteps(Project *pro);
|
||||
void incrementActiveBuildSteps(BuildStep *bs);
|
||||
void decrementActiveBuildSteps(BuildStep *bs);
|
||||
void disconnectOutput(BuildStep *bs);
|
||||
|
||||
BuildManagerPrivate *d;
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/buildmanager.h>
|
||||
|
||||
#include <QtCore/QMargins>
|
||||
#include <QtCore/QTimer>
|
||||
@@ -370,6 +372,29 @@ void BuildSettingsWidget::deleteConfiguration(BuildConfiguration *deleteConfigur
|
||||
m_target->buildConfigurations().size() <= 1)
|
||||
return;
|
||||
|
||||
ProjectExplorer::BuildManager *bm = ProjectExplorerPlugin::instance()->buildManager();
|
||||
if (bm->isBuilding(deleteConfiguration)) {
|
||||
QMessageBox box;
|
||||
QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Remove Build Configuration"), QMessageBox::AcceptRole);
|
||||
QPushButton *cancelClose = box.addButton(tr("Do Not Remove"), QMessageBox::RejectRole);
|
||||
box.setDefaultButton(cancelClose);
|
||||
box.setWindowTitle(tr("Remove Build Configuration %1?").arg(deleteConfiguration->displayName()));
|
||||
box.setText(tr("The build configuration <b>%1</b> is currently being built.").arg(deleteConfiguration->displayName()));
|
||||
box.setInformativeText(tr("Do you want to cancel the build process and remove the Build Configuration anyway?"));
|
||||
box.exec();
|
||||
if (box.clickedButton() != closeAnyway)
|
||||
return;
|
||||
bm->cancel();
|
||||
} else {
|
||||
QMessageBox msgBox(QMessageBox::Question, tr("Remove Build Configuration?"),
|
||||
tr("Do you really want to delete build configuration <b>%1</b>?").arg(deleteConfiguration->displayName()),
|
||||
QMessageBox::Yes|QMessageBox::No, this);
|
||||
msgBox.setDefaultButton(QMessageBox::No);
|
||||
msgBox.setEscapeButton(QMessageBox::No);
|
||||
if (msgBox.exec() == QMessageBox::No)
|
||||
return;
|
||||
}
|
||||
|
||||
m_target->removeBuildConfiguration(deleteConfiguration);
|
||||
|
||||
updateBuildSettings();
|
||||
|
||||
@@ -156,11 +156,21 @@ DeployConfiguration *BuildStep::deployConfiguration() const
|
||||
return dc;
|
||||
}
|
||||
|
||||
ProjectConfiguration *BuildStep::projectConfiguration() const
|
||||
{
|
||||
return static_cast<ProjectConfiguration *>(parent()->parent());
|
||||
}
|
||||
|
||||
Target *BuildStep::target() const
|
||||
{
|
||||
return qobject_cast<Target *>(parent()->parent()->parent());
|
||||
}
|
||||
|
||||
Project *BuildStep::project() const
|
||||
{
|
||||
return target()->project();
|
||||
}
|
||||
|
||||
bool BuildStep::immutable() const
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -72,7 +72,9 @@ public:
|
||||
|
||||
BuildConfiguration *buildConfiguration() const;
|
||||
DeployConfiguration *deployConfiguration() const;
|
||||
ProjectConfiguration *projectConfiguration() const;
|
||||
Target *target() const;
|
||||
Project *project() const;
|
||||
|
||||
enum OutputFormat { NormalOutput, ErrorOutput, MessageOutput, ErrorMessageOutput };
|
||||
enum OutputNewlineSetting { DoAppendNewline, DontAppendNewline };
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <coreplugin/ifile.h>
|
||||
#include <coreplugin/icontext.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <projectexplorer/buildmanager.h>
|
||||
#include <limits>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
@@ -166,9 +167,15 @@ void Project::addTarget(Target *t)
|
||||
setActiveTarget(t);
|
||||
}
|
||||
|
||||
void Project::removeTarget(Target *target)
|
||||
bool Project::removeTarget(Target *target)
|
||||
{
|
||||
QTC_ASSERT(target && d->m_targets.contains(target), return);
|
||||
if (!target || !d->m_targets.contains(target))
|
||||
return false;
|
||||
|
||||
ProjectExplorer::BuildManager *bm =
|
||||
ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager();
|
||||
if (bm->isBuilding(target))
|
||||
return false;
|
||||
|
||||
emit aboutToRemoveTarget(target);
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
|
||||
// Target:
|
||||
void addTarget(Target *target);
|
||||
void removeTarget(Target *target);
|
||||
bool removeTarget(Target *target);
|
||||
|
||||
QList<Target *> targets() const;
|
||||
// Note: activeTarget can be 0 (if no targets are defined).
|
||||
|
||||
@@ -1031,6 +1031,20 @@ void ProjectExplorerPlugin::unloadProject()
|
||||
if (debug)
|
||||
qDebug() << "ProjectExplorerPlugin::unloadProject";
|
||||
|
||||
if (buildManager()->isBuilding(d->m_currentProject)) {
|
||||
QMessageBox box;
|
||||
QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Unload"), QMessageBox::AcceptRole);
|
||||
QPushButton *cancelClose = box.addButton(tr("Do Not Unload"), QMessageBox::RejectRole);
|
||||
box.setDefaultButton(cancelClose);
|
||||
box.setWindowTitle(tr("Unload Project %1?").arg(d->m_currentProject->displayName()));
|
||||
box.setText(tr("The project %1 is currently being built.").arg(d->m_currentProject->displayName()));
|
||||
box.setInformativeText(tr("Do you want to cancel the build process and unload the project anyway?"));
|
||||
box.exec();
|
||||
if (box.clickedButton() != closeAnyway)
|
||||
return;
|
||||
buildManager()->cancel();
|
||||
}
|
||||
|
||||
Core::IFile *fi = d->m_currentProject->file();
|
||||
|
||||
if (!fi || fi->fileName().isEmpty()) //nothing to save?
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/buildmanager.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QPair>
|
||||
@@ -389,6 +391,20 @@ void RunSettingsWidget::addDeployConfiguration()
|
||||
void RunSettingsWidget::removeDeployConfiguration()
|
||||
{
|
||||
DeployConfiguration *dc = m_target->activeDeployConfiguration();
|
||||
ProjectExplorer::BuildManager *bm = ProjectExplorerPlugin::instance()->buildManager();
|
||||
if (bm->isBuilding(dc)) {
|
||||
QMessageBox box;
|
||||
QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Remove Deploy Configuration"), QMessageBox::AcceptRole);
|
||||
QPushButton *cancelClose = box.addButton(tr("Do Not Remove"), QMessageBox::RejectRole);
|
||||
box.setDefaultButton(cancelClose);
|
||||
box.setWindowTitle(tr("Remove Deploy Configuration %1?").arg(dc->displayName()));
|
||||
box.setText(tr("The deploy configuration <b>%1</b> is currently being built.").arg(dc->displayName()));
|
||||
box.setInformativeText(tr("Do you want to cancel the build process and remove the Deploy Configuration anyway?"));
|
||||
box.exec();
|
||||
if (box.clickedButton() != closeAnyway)
|
||||
return;
|
||||
bm->cancel();
|
||||
} else {
|
||||
QMessageBox msgBox(QMessageBox::Question, tr("Remove Deploy Configuration?"),
|
||||
tr("Do you really want to delete deploy configuration <b>%1</b>?").arg(dc->displayName()),
|
||||
QMessageBox::Yes|QMessageBox::No, this);
|
||||
@@ -396,8 +412,10 @@ void RunSettingsWidget::removeDeployConfiguration()
|
||||
msgBox.setEscapeButton(QMessageBox::No);
|
||||
if (msgBox.exec() == QMessageBox::No)
|
||||
return;
|
||||
}
|
||||
|
||||
m_target->removeDeployConfiguration(dc);
|
||||
|
||||
m_removeDeployToolButton->setEnabled(m_target->deployConfigurations().size() > 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
|
||||
#include <limits>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <projectexplorer/buildmanager.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtGui/QIcon>
|
||||
@@ -174,11 +176,16 @@ void Target::addBuildConfiguration(BuildConfiguration *configuration)
|
||||
setActiveBuildConfiguration(configuration);
|
||||
}
|
||||
|
||||
void Target::removeBuildConfiguration(BuildConfiguration *configuration)
|
||||
bool Target::removeBuildConfiguration(BuildConfiguration *configuration)
|
||||
{
|
||||
//todo: this might be error prone
|
||||
if (!d->m_buildConfigurations.contains(configuration))
|
||||
return;
|
||||
return false;
|
||||
|
||||
ProjectExplorer::BuildManager *bm =
|
||||
ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager();
|
||||
if (bm->isBuilding(configuration))
|
||||
return false;
|
||||
|
||||
d->m_buildConfigurations.removeOne(configuration);
|
||||
|
||||
@@ -192,6 +199,7 @@ void Target::removeBuildConfiguration(BuildConfiguration *configuration)
|
||||
}
|
||||
|
||||
delete configuration;
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<BuildConfiguration *> Target::buildConfigurations() const
|
||||
@@ -242,11 +250,16 @@ void Target::addDeployConfiguration(DeployConfiguration *dc)
|
||||
Q_ASSERT(activeDeployConfiguration());
|
||||
}
|
||||
|
||||
void Target::removeDeployConfiguration(DeployConfiguration *dc)
|
||||
bool Target::removeDeployConfiguration(DeployConfiguration *dc)
|
||||
{
|
||||
//todo: this might be error prone
|
||||
if (!d->m_deployConfigurations.contains(dc))
|
||||
return;
|
||||
return false;
|
||||
|
||||
ProjectExplorer::BuildManager *bm =
|
||||
ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager();
|
||||
if (bm->isBuilding(dc))
|
||||
return false;
|
||||
|
||||
d->m_deployConfigurations.removeOne(dc);
|
||||
|
||||
@@ -260,6 +273,7 @@ void Target::removeDeployConfiguration(DeployConfiguration *dc)
|
||||
}
|
||||
|
||||
delete dc;
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<DeployConfiguration *> Target::deployConfigurations() const
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
|
||||
// Build configuration
|
||||
void addBuildConfiguration(BuildConfiguration *configuration);
|
||||
void removeBuildConfiguration(BuildConfiguration *configuration);
|
||||
bool removeBuildConfiguration(BuildConfiguration *configuration);
|
||||
|
||||
QList<BuildConfiguration *> buildConfigurations() const;
|
||||
virtual BuildConfiguration *activeBuildConfiguration() const;
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
|
||||
// DeployConfiguration
|
||||
void addDeployConfiguration(DeployConfiguration *dc);
|
||||
void removeDeployConfiguration(DeployConfiguration *dc);
|
||||
bool removeDeployConfiguration(DeployConfiguration *dc);
|
||||
|
||||
QList<DeployConfiguration *> deployConfigurations() const;
|
||||
virtual DeployConfiguration *activeDeployConfiguration() const;
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#include "targetsettingswidget.h"
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/buildmanager.h>
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtGui/QLabel>
|
||||
@@ -47,6 +49,7 @@
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QStackedWidget>
|
||||
#include <QtGui/QPushButton>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace ProjectExplorer::Internal;
|
||||
@@ -230,13 +233,33 @@ void TargetSettingsPanelWidget::removeTarget()
|
||||
{
|
||||
int index = m_selector->currentIndex();
|
||||
Target *t = m_targets.at(index);
|
||||
|
||||
ProjectExplorer::BuildManager *bm = ProjectExplorerPlugin::instance()->buildManager();
|
||||
if (bm->isBuilding(t)) {
|
||||
QMessageBox box;
|
||||
QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Remove Target"), QMessageBox::AcceptRole);
|
||||
QPushButton *cancelClose = box.addButton(tr("Do Not Remove"), QMessageBox::RejectRole);
|
||||
box.setDefaultButton(cancelClose);
|
||||
box.setWindowTitle(tr("Remove Target %1?").arg(t->displayName()));
|
||||
box.setText(tr("The target <b>%1</b> is currently being built.").arg(t->displayName()));
|
||||
box.setInformativeText(tr("Do you want to cancel the build process and remove the Target anyway?"));
|
||||
box.exec();
|
||||
if (box.clickedButton() != closeAnyway)
|
||||
return;
|
||||
bm->cancel();
|
||||
} else {
|
||||
// We don't show the generic message box on removing the target, if we showed the still building one
|
||||
int ret = QMessageBox::warning(this, tr("Qt Creator"),
|
||||
tr("Do you really want to remove the\n"
|
||||
"\"%1\" target?").arg(t->displayName()),
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::No);
|
||||
if (ret == QMessageBox::Yes)
|
||||
if (ret != QMessageBox::Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
m_project->removeTarget(t);
|
||||
|
||||
}
|
||||
|
||||
void TargetSettingsPanelWidget::targetAdded(ProjectExplorer::Target *target)
|
||||
|
||||
Reference in New Issue
Block a user