Skip to content
Snippets Groups Projects
qt4project.cpp 45.3 KiB
Newer Older
    emit runConfigurationsEnabledStateChanged();
    emit targetInformationChanged();
ProjectExplorer::ToolChain::ToolChainType Qt4Project::toolChainType(BuildConfiguration *configuration) const
    const ProjectExplorer::ToolChain::ToolChainType originalType =
        (ProjectExplorer::ToolChain::ToolChainType)configuration->value("ToolChain").toInt();
    ProjectExplorer::ToolChain::ToolChainType type = originalType;
    const QtVersion *version = qtVersion(configuration);
    if (!version->possibleToolChainTypes().contains(type)) // use default tool chain
        type = version->defaultToolchainType();
    if (type != originalType)
        const_cast<Qt4Project *>(this)->setToolChainType(configuration, type);
dt's avatar
dt committed
BuildConfigWidget *Qt4Project::createConfigWidget()
con's avatar
con committed
{
    return new Qt4ProjectConfigWidget(this);
con's avatar
con committed
}

dt's avatar
dt committed
QList<BuildConfigWidget*> Qt4Project::subConfigWidgets()
con's avatar
con committed
{
dt's avatar
dt committed
    QList<BuildConfigWidget*> subWidgets;
con's avatar
con committed
    subWidgets << new Qt4BuildEnvironmentWidget(this);
    return subWidgets;
}

void Qt4Project::collectApplicationProFiles(QList<Qt4ProFileNode *> &list, Qt4ProFileNode *node)
{
    if (node->projectType() == Internal::ApplicationTemplate
        || node->projectType() == Internal::ScriptTemplate) {
        list.append(node);
    }
    foreach (ProjectNode *n, node->subProjectNodes()) {
        Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(n);
        if (qt4ProFileNode)
            collectApplicationProFiles(list, qt4ProFileNode);
    }
}

void Qt4Project::foldersAboutToBeAdded(FolderNode *, const QList<FolderNode*> &nodes)
{
    QList<Qt4ProFileNode *> list;
    foreach (FolderNode *node, nodes) {
        Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(node);
        if (qt4ProFileNode)
            collectApplicationProFiles(list, qt4ProFileNode);
    }
    m_applicationProFileChange = list;
}

void Qt4Project::checkForNewApplicationProjects()
{
    // Check all new project nodes
    // against all runConfigurations

    foreach (Qt4ProFileNode *qt4proFile, m_applicationProFileChange) {
        bool found = false;
        foreach (QSharedPointer<RunConfiguration> rc, runConfigurations()) {
dt's avatar
dt committed
            QSharedPointer<Qt4RunConfiguration> qtrc = rc.objectCast<Qt4RunConfiguration>();
con's avatar
con committed
            if (qtrc && qtrc->proFilePath() == qt4proFile->path()) {
                found = true;
                break;
            }
        }
        if (!found) {
            QSharedPointer<Qt4RunConfiguration> newRc(new Qt4RunConfiguration(this, qt4proFile->path()));
            addRunConfiguration(newRc);
            m_isApplication = true;
        }
    }
}

void Qt4Project::checkForDeletedApplicationProjects()
{
    QStringList paths;
    foreach (Qt4ProFileNode * node, applicationProFiles())
        paths.append(node->path());

//    qDebug()<<"Still existing paths :"<<paths;
con's avatar
con committed

    QList<QSharedPointer<Qt4RunConfiguration> > removeList;
    foreach (QSharedPointer<RunConfiguration> rc, runConfigurations()) {
dt's avatar
dt committed
        if (QSharedPointer<Qt4RunConfiguration> qt4rc = rc.objectCast<Qt4RunConfiguration>()) {
con's avatar
con committed
            if (!paths.contains(qt4rc->proFilePath())) {
                removeList.append(qt4rc);
//                qDebug()<<"Removing runConfiguration for "<<qt4rc->proFilePath();
con's avatar
con committed
            }
        }
    }

    bool resetActiveRunConfiguration = false;
    QSharedPointer<RunConfiguration> rc(new ProjectExplorer::CustomExecutableRunConfiguration(this));
hjk's avatar
hjk committed
    foreach (QSharedPointer<Qt4RunConfiguration> qt4rc, removeList) {
con's avatar
con committed
        removeRunConfiguration(qt4rc);
        if (activeRunConfiguration() == qt4rc)
            resetActiveRunConfiguration = true;
    }

    if (runConfigurations().isEmpty()) {
        QSharedPointer<RunConfiguration> rc(new ProjectExplorer::CustomExecutableRunConfiguration(this));
        addRunConfiguration(rc);
        setActiveRunConfiguration(rc);
        m_isApplication = false;
    } else if (resetActiveRunConfiguration) {
        setActiveRunConfiguration(runConfigurations().first());
    }
}

QList<Qt4ProFileNode *> Qt4Project::applicationProFiles() const
{
    QList<Qt4ProFileNode *> list;
    collectApplicationProFiles(list, rootProjectNode());
    return list;
}

void Qt4Project::projectTypeChanged(Qt4ProFileNode *node, const Qt4ProjectType oldType, const Qt4ProjectType newType)
{
    if (oldType == Internal::ApplicationTemplate
        || oldType == Internal::ScriptTemplate) {
        // check wheter we need to delete a Run Configuration
        checkForDeletedApplicationProjects();
    }

    if (newType == Internal::ApplicationTemplate
        || newType == Internal::ScriptTemplate) {
        // add a new Run Configuration
        m_applicationProFileChange.clear();
        m_applicationProFileChange.append(node);
        checkForNewApplicationProjects();
    }
}

void Qt4Project::proFileUpdated(Qt4ProjectManager::Internal::Qt4ProFileNode *node)
{
    foreach (QSharedPointer<RunConfiguration> rc, runConfigurations()) {
dt's avatar
dt committed
        if (QSharedPointer<Qt4RunConfiguration> qt4rc = rc.objectCast<Qt4RunConfiguration>()) {
con's avatar
con committed
            if (qt4rc->proFilePath() == node->path()) {
                qt4rc->invalidateCachedTargetInformation();
QMakeStep *Qt4Project::qmakeStep() const
{
    QMakeStep *qs = 0;
    foreach(BuildStep *bs, buildSteps())
        if ((qs = qobject_cast<QMakeStep *>(bs)) != 0)
            return qs;
    return 0;
}

con's avatar
con committed
MakeStep *Qt4Project::makeStep() const
{
    MakeStep *qs = 0;
    foreach(BuildStep *bs, buildSteps())
        if ((qs = qobject_cast<MakeStep *>(bs)) != 0)
            return qs;
    return 0;
}
bool Qt4Project::hasSubNode(Qt4PriFileNode *root, const QString &path)
    if (root->path() == path)
        return true;
    foreach (FolderNode *fn, root->subFolderNodes()) {
        if (qobject_cast<Qt4ProFileNode *>(fn)) {
            // we aren't interested in pro file nodes
hjk's avatar
hjk committed
        } else if (Qt4PriFileNode *qt4prifilenode = qobject_cast<Qt4PriFileNode *>(fn)) {
            if (hasSubNode(qt4prifilenode, path))
                return true;
        }
    }
    return false;
}

void Qt4Project::findProFile(const QString& fileName, Qt4ProFileNode *root, QList<Qt4ProFileNode *> &list)
{
    if (hasSubNode(root, fileName))
        list.append(root);

    foreach (FolderNode *fn, root->subFolderNodes())
        if (Qt4ProFileNode *qt4proFileNode =  qobject_cast<Qt4ProFileNode *>(fn))
            findProFile(fileName, qt4proFileNode, list);
}

void Qt4Project::notifyChanged(const QString &name)
{
    if (files(Qt4Project::ExcludeGeneratedFiles).contains(name)) {
        QList<Qt4ProFileNode *> list;
        findProFile(name, rootProjectNode(), list);
        foreach(Qt4ProFileNode *node, list)
            node->update();
    }

void Qt4Project::invalidateCachedTargetInformation()
{
    emit targetInformationChanged();
void Qt4Project::emitBuildDirectoryChanged()
{
    emit buildDirectoryChanged();
}

// We match -spec and -platfrom separetly
// We ignore -cache, because qmake contained a bug that it didn't
// mention the -cache in the Makefile
// That means changing the -cache option in the additional arguments
// does not automatically rerun qmake. Alas, we could try more
// intelligent matching for -cache, but i guess people rarely
// do use that.

dt's avatar
dt committed
QStringList Qt4Project::removeSpecFromArgumentList(const QStringList &old)
{
    if (!old.contains("-spec") && !old.contains("-platform") && !old.contains("-cache"))
        return old;
    QStringList newList;
    bool ignoreNext = false;
    foreach(const QString &item, old) {
        if (ignoreNext) {
            ignoreNext = false;
        } else if (item == "-spec" || item == "-platform" || item == "-cache") {
            ignoreNext = true;
        } else {
            newList << item;
        }
    }
    return newList;
}

dt's avatar
dt committed
QString Qt4Project::extractSpecFromArgumentList(const QStringList &list)
{
    int index = list.indexOf("-spec");
    if (index == -1)
        index = list.indexOf("-platform");
    if (index == -1)
        return QString();
    if (index + 1 < list.length())
        return list.at(index +1);
    else
        return QString();
}

// returns true if both are equal
bool Qt4Project::compareBuildConfigurationToImportFrom(BuildConfiguration *configuration, const QString &workingDirectory)
    QMakeStep *qs = qmakeStep();
    if (QDir(workingDirectory).exists(QLatin1String("Makefile")) && qs) {
        QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(workingDirectory);
        QtVersion *version = qtVersion(configuration);
        if (version->qmakeCommand() == qmakePath) {
            // same qtversion
            QPair<QtVersion::QmakeBuildConfig, QStringList> result =
                    QtVersionManager::scanMakeFile(workingDirectory, version->defaultBuildConfig());
            if (QtVersion::QmakeBuildConfig(configuration->value("buildConfiguration").toInt()) == result.first) {
                // The QMake Build Configuration are the same,
                // now compare arguments lists
                // we have to compare without the spec/platform cmd argument
                // and compare that on its own
                QString actualSpec = extractSpecFromArgumentList(qs->value(configuration->name(), "qmakeArgs").toStringList());
                if (actualSpec.isEmpty())
dt's avatar
dt committed
                    actualSpec = version->mkspec();

                // Now to convert the actualSpec to a absolute path, we go through a few hops
                if (QFileInfo(actualSpec).isRelative()) {
                    QString path = version->sourcePath() + "/mkspecs/" + actualSpec;
                    if (QFileInfo(path).exists()) {
                        actualSpec = QDir::cleanPath(path);
                    } else {
                        path = version->versionInfo().value("QMAKE_MKSPECS") + "/" + actualSpec;
                        if (QFileInfo(path).exists()) {
                            actualSpec = QDir::cleanPath(path);
                        } else {
                            path = workingDirectory + "/" + actualSpec;
                            if (QFileInfo(path).exists())
                                actualSpec = QDir::cleanPath(path);
                        }
                    }
                }


                QString parsedSpec = extractSpecFromArgumentList(result.second);
                // if the MakeFile did not contain a mkspec, then it is the default for that qmake
                if (parsedSpec.isEmpty())
                    parsedSpec = version->sourcePath() + "/mkspecs/" + version->mkspec();
                if (QFileInfo(parsedSpec).isRelative())
                    parsedSpec = QDir::cleanPath(workingDirectory + "/" + parsedSpec);

                QStringList actualArgs = removeSpecFromArgumentList(qs->value(configuration->name(), "qmakeArgs").toStringList());
                QStringList parsedArgs = removeSpecFromArgumentList(result.second);

#ifdef Q_OS_WIN
                actualSpec = actualSpec.toLower();
                parsedSpec = parsedSpec.toLower();
#endif

                if (debug) {
                    qDebug()<<"Actual args:"<<actualArgs;
                    qDebug()<<"Parsed args:"<<parsedArgs;
                    qDebug()<<"Actual spec:"<<actualSpec;
                    qDebug()<<"Parsed spec:"<<parsedSpec;
                }

                if (actualArgs == parsedArgs && actualSpec == parsedSpec)

/*!
  Handle special case were a subproject of the qt directory is opened, and
  qt was configured to be built as a shadow build -> also build in the sub-
  project in the correct shadow build directory.
  */

// TODO this function should be called on project first load
// and it should check against all configured qt versions ?
//void Qt4Project::detectQtShadowBuild(const QString &buildConfiguration) const
//{
//    if (project()->activeBuildConfiguration() == buildConfiguration)
//        return;
//
//    const QString currentQtDir = static_cast<Qt4Project *>(project())->qtDir(buildConfiguration);
//    const QString qtSourceDir = static_cast<Qt4Project *>(project())->qtVersion(buildConfiguration)->sourcePath();
//
//    // if the project is a sub-project of Qt and Qt was shadow-built then automatically
//    // adjust the build directory of the sub-project.
//    if (project()->file()->fileName().startsWith(qtSourceDir) && qtSourceDir != currentQtDir) {
//        project()->setValue(buildConfiguration, "useShadowBuild", true);
//        QString buildDir = QFileInfo(project()->file()->fileName()).absolutePath();
//        buildDir.replace(qtSourceDir, currentQtDir);
//        project()->setValue(buildConfiguration, "buildDirectory", buildDir);
//        project()->setValue(buildConfiguration, "autoShadowBuild", true);
//    }
//}