Skip to content
Snippets Groups Projects
qt4project.cpp 41.2 KiB
Newer Older
dt's avatar
dt committed
void Qt4Project::createApplicationProjects()
con's avatar
con committed
{
dt's avatar
dt committed
    foreach (Target *target, targets()) {
        if (target->runConfigurations().count()) {
            // Remove all run configurations which the new project wizard created
            QList<RunConfiguration*> toRemove;
            foreach (RunConfiguration * rc, target->runConfigurations()) {
                CustomExecutableRunConfiguration *cerc = qobject_cast<CustomExecutableRunConfiguration *>(rc);
                if (cerc && !cerc->isConfigured())
                    toRemove.append(rc);
dt's avatar
dt committed
            foreach (RunConfiguration *rc, toRemove)
                target->removeRunConfiguration(rc);
con's avatar
con committed
        }

        // We use the list twice
        QList<Qt4ProFileNode *> profiles = applicationProFiles();
        QStringList paths;
        foreach (Qt4ProFileNode *pro, profiles)
            paths << pro->path();

        foreach (RunConfiguration *rc, target->runConfigurations()) {
            if (Qt4RunConfiguration *qt4rc = qobject_cast<Qt4RunConfiguration *>(rc)) {
                if (!paths.contains(qt4rc->proFilePath())) {
                    // A deleted .pro file? or a change template
                    // We do remove those though
                    target->removeRunConfiguration(rc);
                }
            }
        }

dt's avatar
dt committed
        // Only add new runconfigurations if there are none.
        if (target->runConfigurations().isEmpty()) {
            Qt4Target *qt4Target = static_cast<Qt4Target *>(target);
            foreach (Qt4ProFileNode *qt4proFile, profiles) {
dt's avatar
dt committed
                qt4Target->addRunConfigurationForPath(qt4proFile->path());
con's avatar
con committed
            }
        }
dt's avatar
dt committed
        // Oh still none? Add a custom executable runconfiguration
Tobias Hunger's avatar
Tobias Hunger committed
        if (target->runConfigurations().isEmpty()) {
            target->addRunConfiguration(new ProjectExplorer::CustomExecutableRunConfiguration(target));
        }
con's avatar
con committed
    }
}

QList<Qt4ProFileNode *> Qt4Project::leafProFiles() const
{
    QList<Qt4ProFileNode *> list;
    if (!rootProjectNode())
        return list;
    collectLeafProFiles(list, rootProjectNode());
    return list;
}

con's avatar
con committed
QList<Qt4ProFileNode *> Qt4Project::applicationProFiles() const
{
    QList<Qt4ProFileNode *> list;
Tobias Hunger's avatar
Tobias Hunger committed
    if (!rootProjectNode())
        return list;
con's avatar
con committed
    collectApplicationProFiles(list, rootProjectNode());
    return list;
}

bool Qt4Project::hasApplicationProFile(const QString &path) const
{
    if (path.isEmpty())
        return false;

    QList<Qt4ProFileNode *> list = applicationProFiles();
    foreach (Qt4ProFileNode * node, list)
        if (node->path() == path)
            return true;
    return false;
}

QStringList Qt4Project::applicationProFilePathes(const QString &prepend) const
{
    QStringList proFiles;
    foreach (Qt4ProFileNode *node, applicationProFiles())
        proFiles.append(prepend + node->path());
    return proFiles;
}

Tobias Hunger's avatar
Tobias Hunger committed
void Qt4Project::activeTargetWasChanged()
{
    if (!activeTarget())
        return;

    scheduleAsyncUpdate();
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) {
            ProFileCacheManager::instance()->discardFile(name);
            node->update();
CentralizedFolderWatcher *Qt4Project::centralizedFolderWatcher()
{
    return &m_centralizedFolderWatcher;
}

/////////////
/// Centralized Folder Watcher
////////////

// All the folder have a trailing slash!

namespace {
   bool debugCFW = false;
}

CentralizedFolderWatcher::CentralizedFolderWatcher()
{
    connect (&m_watcher, SIGNAL(directoryChanged(QString)),
             this, SLOT(folderChanged(QString)));
}

CentralizedFolderWatcher::~CentralizedFolderWatcher()
{

}

QSet<QString> CentralizedFolderWatcher::recursiveDirs(const QString &folder)
{
    QSet<QString> result;
    QDir dir(folder);
    QStringList list = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
    foreach (const QString &f, list) {
        result.insert(folder + f + "/");
        result += recursiveDirs(folder + f + "/");
    }
    return result;
}

void CentralizedFolderWatcher::watchFolders(const QList<QString> &folders, Qt4PriFileNode *node)
{
    if (debugCFW)
        qDebug()<<"CFW::watchFolders()"<<folders<<"for node"<<node->path();
    m_watcher.addPaths(folders);

    foreach (const QString &f, folders) {
        QString folder = f;
        if (!folder.endsWith('/'))
            folder.append('/');
        m_map.insert(folder, node);

        // Support for recursive watching
        // we add the recursive directories we find
        QSet<QString> tmp = recursiveDirs(folder);
        if (!tmp.isEmpty())
            m_watcher.addPaths(tmp.toList());
        m_recursiveWatchedFolders += tmp;

        if (debugCFW)
            qDebug()<<"adding recursive dirs for"<< folder<<":"<<tmp;
    }
}

void CentralizedFolderWatcher::unwatchFolders(const QList<QString> &folders, Qt4PriFileNode *node)
{
    if (debugCFW)
        qDebug()<<"CFW::unwatchFolders()"<<folders<<"for node"<<node->path();
    foreach (const QString &f, folders) {
        QString folder = f;
        if (!folder.endsWith('/'))
            folder.append('/');
        m_map.remove(folder, node);
        if (!m_map.contains(folder)) {
            m_watcher.removePath(folder);
        }

        // Figure out which recursive directories we can remove
        // TODO this might not scale. I'm pretty sure it doesn't
        // A scaling implementation would need to save more information
        // where a given directory watcher actual comes from...

        QStringList toRemove;
        foreach (const QString &rwf, m_recursiveWatchedFolders) {
            if (rwf.startsWith(folder)) {
                // So the rwf is a subdirectory of a folder we aren't watching
                // but maybe someone else wants us to watch
                bool needToWatch = false;
                QMultiMap<QString, Qt4PriFileNode *>::const_iterator it, end;
                end = m_map.constEnd();
                for (it = m_map.constEnd(); it != end; ++it) {
                    if (rwf.startsWith(it.key())) {
                        needToWatch = true;
                        break;
                    }
                }
                if (!needToWatch) {
                    m_watcher.removePath(rwf);
                    toRemove << rwf;
                }
            }
        }

        if (debugCFW)
            qDebug()<<"removing recursive dirs for"<<folder<<":"<<toRemove;

        foreach (const QString &tr, toRemove) {
            m_recursiveWatchedFolders.remove(tr);
        }
    }
}


void CentralizedFolderWatcher::folderChanged(const QString &folder)
{
    if (debugCFW)
        qDebug()<<"CFW::folderChanged"<<folder;
    // Figure out whom to inform

    while (true) {
        if (!dir.endsWith('/'))
            dir.append('/');
        QList<Qt4PriFileNode *> nodes = m_map.values(dir);
        foreach (Qt4PriFileNode *node, nodes) {
            node->folderChanged(folder);
        }

        // Chop off last part, and break if there's nothing to chop off
        //
        if (dir.length() < 2)

        // We start before the last slash
        int index = dir.lastIndexOf('/', dir.length() - 2);
        if (index == -1)
            break;
        dir = dir.left(index + 1);
    QString folderWithSlash = folder;
    if (!folder.endsWith('/'))
        folderWithSlash.append('/');


    // If a subdirectory was added, watch it too
    QSet<QString> tmp = recursiveDirs(folderWithSlash);
    if (!tmp.isEmpty()) {
        if (debugCFW)
            qDebug()<<"found new recursive dirs"<<tmp;
        m_watcher.addPaths(tmp.toList());
        m_recursiveWatchedFolders += tmp;
    }
}

/*!
  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 = project()->projectDirectory();
//        buildDir.replace(qtSourceDir, currentQtDir);
//        project()->setValue(buildConfiguration, "buildDirectory", buildDir);
//        project()->setValue(buildConfiguration, "autoShadowBuild", true);
//    }
//}